diff --git a/80-kvm.rules b/80-kvm.rules deleted file mode 100644 index c2f7317aacca3ee63cfaa322f87472d62193ffa7..0000000000000000000000000000000000000000 --- a/80-kvm.rules +++ /dev/null @@ -1 +0,0 @@ -KERNEL=="kvm", GROUP="kvm", MODE="0660" diff --git a/99-qemu-guest-agent.rules b/99-qemu-guest-agent.rules deleted file mode 100644 index 8a290abbd3e372c417b7cc3ccef37afb31b8935a..0000000000000000000000000000000000000000 --- a/99-qemu-guest-agent.rules +++ /dev/null @@ -1,2 +0,0 @@ -SUBSYSTEM=="virtio-ports", ATTR{name}=="org.qemu.guest_agent.0", \ - TAG+="systemd" ENV{SYSTEMD_WANTS}="qemu-guest-agent.service" diff --git a/9p-Lock-directory-streams-with-a-CoMutex.patch b/9p-Lock-directory-streams-with-a-CoMutex.patch new file mode 100644 index 0000000000000000000000000000000000000000..ff656575e8b47d4c0c6c78a51d6dfa5e822cfb7f --- /dev/null +++ b/9p-Lock-directory-streams-with-a-CoMutex.patch @@ -0,0 +1,67 @@ +From ed463454efd0ac3042ff772bfe1b1d846dc281a5 Mon Sep 17 00:00:00 2001 +From: Greg Kurz +Date: Mon, 25 May 2020 10:38:03 +0200 +Subject: [PATCH 641/709] 9p: Lock directory streams with a CoMutex + +Locking was introduced in QEMU 2.7 to address the deprecation of +readdir_r(3) in glibc 2.24. It turns out that the frontend code is +the worst place to handle a critical section with a pthread mutex: +the code runs in a coroutine on behalf of the QEMU mainloop and then +yields control, waiting for the fsdev backend to process the request +in a worker thread. If the client resends another readdir request for +the same fid before the previous one finally unlocked the mutex, we're +deadlocked. + +This never bit us because the linux client serializes readdir requests +for the same fid, but it is quite easy to demonstrate with a custom +client. + +A good solution could be to narrow the critical section in the worker +thread code and to return a copy of the dirent to the frontend, but +this causes quite some changes in both 9p.c and codir.c. So, instead +of that, in order for people to easily backport the fix to older QEMU +versions, let's simply use a CoMutex since all the users for this +sit in coroutines. + +Fixes: 7cde47d4a89d ("9p: add locking to V9fsDir") +Reviewed-by: Christian Schoenebeck +Message-Id: <158981894794.109297.3530035833368944254.stgit@bahia.lan> +Signed-off-by: Greg Kurz +--- + hw/9pfs/9p.h | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/hw/9pfs/9p.h b/hw/9pfs/9p.h +index dd1c6cb8d2..3ab580764c 100644 +--- a/hw/9pfs/9p.h ++++ b/hw/9pfs/9p.h +@@ -197,22 +197,22 @@ typedef struct V9fsXattr + + typedef struct V9fsDir { + DIR *stream; +- QemuMutex readdir_mutex; ++ CoMutex readdir_mutex; + } V9fsDir; + + static inline void v9fs_readdir_lock(V9fsDir *dir) + { +- qemu_mutex_lock(&dir->readdir_mutex); ++ qemu_co_mutex_lock(&dir->readdir_mutex); + } + + static inline void v9fs_readdir_unlock(V9fsDir *dir) + { +- qemu_mutex_unlock(&dir->readdir_mutex); ++ qemu_co_mutex_unlock(&dir->readdir_mutex); + } + + static inline void v9fs_readdir_init(V9fsDir *dir) + { +- qemu_mutex_init(&dir->readdir_mutex); ++ qemu_co_mutex_init(&dir->readdir_mutex); + } + + /* +-- +2.23.0 + diff --git a/9pfs-include-linux-limits.h-for-XATTR_SIZE_MAX.patch b/9pfs-include-linux-limits.h-for-XATTR_SIZE_MAX.patch new file mode 100644 index 0000000000000000000000000000000000000000..18eee5ec3b891fd96f4e6fe16e62ea6dc2468d53 --- /dev/null +++ b/9pfs-include-linux-limits.h-for-XATTR_SIZE_MAX.patch @@ -0,0 +1,36 @@ +From 03556ea920b23c466ce7c1283199033de33ee671 Mon Sep 17 00:00:00 2001 +From: Dan Robertson +Date: Mon, 25 May 2020 10:38:03 +0200 +Subject: [PATCH 640/709] 9pfs: include linux/limits.h for XATTR_SIZE_MAX +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +linux/limits.h should be included for the XATTR_SIZE_MAX definition used +by v9fs_xattrcreate. + +Fixes: 3b79ef2cf488 ("9pfs: limit xattr size in xattrcreate") +Signed-off-by: Dan Robertson +Reviewed-by: Philippe Mathieu-Daudé +Reviewed-by: Christian Schoenebeck +Message-Id: <20200515203015.7090-2-dan@dlrobertson.com> +Signed-off-by: Greg Kurz +--- + hw/9pfs/9p.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/hw/9pfs/9p.c b/hw/9pfs/9p.c +index a2a14b5979..68c2df7333 100644 +--- a/hw/9pfs/9p.c ++++ b/hw/9pfs/9p.c +@@ -28,6 +28,7 @@ + #include "sysemu/qtest.h" + #include "qemu/xxhash.h" + #include ++#include + + int open_fd_hw; + int total_open_fd; +-- +2.23.0 + diff --git a/9pfs-local-Fix-possible-memory-leak-in-local_link.patch b/9pfs-local-Fix-possible-memory-leak-in-local_link.patch deleted file mode 100644 index f9491f18950937af2708fdd47553a152c400eed0..0000000000000000000000000000000000000000 --- a/9pfs-local-Fix-possible-memory-leak-in-local_link.patch +++ /dev/null @@ -1,21 +0,0 @@ -There is a possible memory leak while local_link return -1 without free -odirpath and oname. - -Reported-by: Euler Robot -Reviewed-by: Christian Schoenebeck -Signed-off-by: Jaijun Chen -Signed-off-by: Xiang Zheng - -diff --git a/hw/9pfs/9p-local.c b/hw/9pfs/9p-local.c -index 4708c0bd89..491b08aee8 100644 ---- a/hw/9pfs/9p-local.c -+++ b/hw/9pfs/9p-local.c -@@ -947,7 +947,7 @@ static int local_link(FsContext *ctx, V9fsPath *oldpath, - if (ctx->export_flags & V9FS_SM_MAPPED_FILE && - local_is_mapped_file_metadata(ctx, name)) { - errno = EINVAL; -- return -1; -+ goto out; - } - - odirfd = local_opendir_nofollow(ctx, odirpath); diff --git a/9pfs-local-ignore-O_NOATIME-if-we-don-t-have-permiss.patch b/9pfs-local-ignore-O_NOATIME-if-we-don-t-have-permiss.patch new file mode 100644 index 0000000000000000000000000000000000000000..f17fba2d16e88c98c21a3bb4cb17b354a9f12f9d --- /dev/null +++ b/9pfs-local-ignore-O_NOATIME-if-we-don-t-have-permiss.patch @@ -0,0 +1,61 @@ +From a5804fcf7b22fc7d1f9ec794dd284c7d504bd16b Mon Sep 17 00:00:00 2001 +From: Omar Sandoval +Date: Thu, 14 May 2020 08:06:43 +0200 +Subject: [PATCH 400/709] 9pfs: local: ignore O_NOATIME if we don't have + permissions + +QEMU's local 9pfs server passes through O_NOATIME from the client. If +the QEMU process doesn't have permissions to use O_NOATIME (namely, it +does not own the file nor have the CAP_FOWNER capability), the open will +fail. This causes issues when from the client's point of view, it +believes it has permissions to use O_NOATIME (e.g., a process running as +root in the virtual machine). Additionally, overlayfs on Linux opens +files on the lower layer using O_NOATIME, so in this case a 9pfs mount +can't be used as a lower layer for overlayfs (cf. +https://github.com/osandov/drgn/blob/dabfe1971951701da13863dbe6d8a1d172ad9650/vmtest/onoatimehack.c +and https://github.com/NixOS/nixpkgs/issues/54509). + +Luckily, O_NOATIME is effectively a hint, and is often ignored by, e.g., +network filesystems. open(2) notes that O_NOATIME "may not be effective +on all filesystems. One example is NFS, where the server maintains the +access time." This means that we can honor it when possible but fall +back to ignoring it. + +Acked-by: Christian Schoenebeck +Signed-off-by: Omar Sandoval +Message-Id: +Signed-off-by: Greg Kurz +--- + hw/9pfs/9p-util.h | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +diff --git a/hw/9pfs/9p-util.h b/hw/9pfs/9p-util.h +index 79ed6b233e..546f46dc7d 100644 +--- a/hw/9pfs/9p-util.h ++++ b/hw/9pfs/9p-util.h +@@ -37,9 +37,22 @@ static inline int openat_file(int dirfd, const char *name, int flags, + { + int fd, serrno, ret; + ++again: + fd = openat(dirfd, name, flags | O_NOFOLLOW | O_NOCTTY | O_NONBLOCK, + mode); + if (fd == -1) { ++ if (errno == EPERM && (flags & O_NOATIME)) { ++ /* ++ * The client passed O_NOATIME but we lack permissions to honor it. ++ * Rather than failing the open, fall back without O_NOATIME. This ++ * doesn't break the semantics on the client side, as the Linux ++ * open(2) man page notes that O_NOATIME "may not be effective on ++ * all filesystems". In particular, NFS and other network ++ * filesystems ignore it entirely. ++ */ ++ flags &= ~O_NOATIME; ++ goto again; ++ } + return -1; + } + +-- +2.23.0 + diff --git a/ACPI-Build-Hardware-Error-Source-Table.patch b/ACPI-Build-Hardware-Error-Source-Table.patch new file mode 100644 index 0000000000000000000000000000000000000000..625934b6e6dac21384a418dd133fdbcfd203e3a5 --- /dev/null +++ b/ACPI-Build-Hardware-Error-Source-Table.patch @@ -0,0 +1,245 @@ +From 205cc75deec196bb3266a0dac407a195a646b5fc Mon Sep 17 00:00:00 2001 +From: Dongjiu Geng +Date: Tue, 12 May 2020 11:06:04 +0800 +Subject: [PATCH 440/709] ACPI: Build Hardware Error Source Table + +This patch builds Hardware Error Source Table(HEST) via fw_cfg blobs. +Now it only supports ARMv8 SEA, a type of Generic Hardware Error +Source version 2(GHESv2) error source. Afterwards, we can extend +the supported types if needed. For the CPER section, currently it +is memory section because kernel mainly wants userspace to handle +the memory errors. + +This patch follows the spec ACPI 6.2 to build the Hardware Error +Source table. For more detailed information, please refer to +document: docs/specs/acpi_hest_ghes.rst + +build_ghes_hw_error_notification() helper will help to add Hardware +Error Notification to ACPI tables without using packed C structures +and avoid endianness issues as API doesn't need explicit conversion. + +Signed-off-by: Xiang Zheng +Signed-off-by: Dongjiu Geng +Reviewed-by: Igor Mammedov +Reviewed-by: Michael S. Tsirkin +Message-id: 20200512030609.19593-6-gengdongjiu@huawei.com +Signed-off-by: Peter Maydell +--- + hw/acpi/ghes.c | 126 +++++++++++++++++++++++++++++++++++++++ + hw/arm/virt-acpi-build.c | 2 + + include/hw/acpi/ghes.h | 39 ++++++++++++ + 3 files changed, 167 insertions(+) + +diff --git a/hw/acpi/ghes.c b/hw/acpi/ghes.c +index e1b3f8fcaa..091fd87094 100644 +--- a/hw/acpi/ghes.c ++++ b/hw/acpi/ghes.c +@@ -23,6 +23,7 @@ + #include "qemu/units.h" + #include "hw/acpi/ghes.h" + #include "hw/acpi/aml-build.h" ++#include "qemu/error-report.h" + + #define ACPI_GHES_ERRORS_FW_CFG_FILE "etc/hardware_errors" + #define ACPI_GHES_DATA_ADDR_FW_CFG_FILE "etc/hardware_errors_addr" +@@ -33,6 +34,42 @@ + /* Now only support ARMv8 SEA notification type error source */ + #define ACPI_GHES_ERROR_SOURCE_COUNT 1 + ++/* Generic Hardware Error Source version 2 */ ++#define ACPI_GHES_SOURCE_GENERIC_ERROR_V2 10 ++ ++/* Address offset in Generic Address Structure(GAS) */ ++#define GAS_ADDR_OFFSET 4 ++ ++/* ++ * Hardware Error Notification ++ * ACPI 4.0: 17.3.2.7 Hardware Error Notification ++ * Composes dummy Hardware Error Notification descriptor of specified type ++ */ ++static void build_ghes_hw_error_notification(GArray *table, const uint8_t type) ++{ ++ /* Type */ ++ build_append_int_noprefix(table, type, 1); ++ /* ++ * Length: ++ * Total length of the structure in bytes ++ */ ++ build_append_int_noprefix(table, 28, 1); ++ /* Configuration Write Enable */ ++ build_append_int_noprefix(table, 0, 2); ++ /* Poll Interval */ ++ build_append_int_noprefix(table, 0, 4); ++ /* Vector */ ++ build_append_int_noprefix(table, 0, 4); ++ /* Switch To Polling Threshold Value */ ++ build_append_int_noprefix(table, 0, 4); ++ /* Switch To Polling Threshold Window */ ++ build_append_int_noprefix(table, 0, 4); ++ /* Error Threshold Value */ ++ build_append_int_noprefix(table, 0, 4); ++ /* Error Threshold Window */ ++ build_append_int_noprefix(table, 0, 4); ++} ++ + /* + * Build table for the hardware error fw_cfg blob. + * Initialize "etc/hardware_errors" and "etc/hardware_errors_addr" fw_cfg blobs. +@@ -87,3 +124,92 @@ void build_ghes_error_table(GArray *hardware_errors, BIOSLinker *linker) + bios_linker_loader_write_pointer(linker, ACPI_GHES_DATA_ADDR_FW_CFG_FILE, + 0, sizeof(uint64_t), ACPI_GHES_ERRORS_FW_CFG_FILE, 0); + } ++ ++/* Build Generic Hardware Error Source version 2 (GHESv2) */ ++static void build_ghes_v2(GArray *table_data, int source_id, BIOSLinker *linker) ++{ ++ uint64_t address_offset; ++ /* ++ * Type: ++ * Generic Hardware Error Source version 2(GHESv2 - Type 10) ++ */ ++ build_append_int_noprefix(table_data, ACPI_GHES_SOURCE_GENERIC_ERROR_V2, 2); ++ /* Source Id */ ++ build_append_int_noprefix(table_data, source_id, 2); ++ /* Related Source Id */ ++ build_append_int_noprefix(table_data, 0xffff, 2); ++ /* Flags */ ++ build_append_int_noprefix(table_data, 0, 1); ++ /* Enabled */ ++ build_append_int_noprefix(table_data, 1, 1); ++ ++ /* Number of Records To Pre-allocate */ ++ build_append_int_noprefix(table_data, 1, 4); ++ /* Max Sections Per Record */ ++ build_append_int_noprefix(table_data, 1, 4); ++ /* Max Raw Data Length */ ++ build_append_int_noprefix(table_data, ACPI_GHES_MAX_RAW_DATA_LENGTH, 4); ++ ++ address_offset = table_data->len; ++ /* Error Status Address */ ++ build_append_gas(table_data, AML_AS_SYSTEM_MEMORY, 0x40, 0, ++ 4 /* QWord access */, 0); ++ bios_linker_loader_add_pointer(linker, ACPI_BUILD_TABLE_FILE, ++ address_offset + GAS_ADDR_OFFSET, sizeof(uint64_t), ++ ACPI_GHES_ERRORS_FW_CFG_FILE, source_id * sizeof(uint64_t)); ++ ++ switch (source_id) { ++ case ACPI_HEST_SRC_ID_SEA: ++ /* ++ * Notification Structure ++ * Now only enable ARMv8 SEA notification type ++ */ ++ build_ghes_hw_error_notification(table_data, ACPI_GHES_NOTIFY_SEA); ++ break; ++ default: ++ error_report("Not support this error source"); ++ abort(); ++ } ++ ++ /* Error Status Block Length */ ++ build_append_int_noprefix(table_data, ACPI_GHES_MAX_RAW_DATA_LENGTH, 4); ++ ++ /* ++ * Read Ack Register ++ * ACPI 6.1: 18.3.2.8 Generic Hardware Error Source ++ * version 2 (GHESv2 - Type 10) ++ */ ++ address_offset = table_data->len; ++ build_append_gas(table_data, AML_AS_SYSTEM_MEMORY, 0x40, 0, ++ 4 /* QWord access */, 0); ++ bios_linker_loader_add_pointer(linker, ACPI_BUILD_TABLE_FILE, ++ address_offset + GAS_ADDR_OFFSET, ++ sizeof(uint64_t), ACPI_GHES_ERRORS_FW_CFG_FILE, ++ (ACPI_GHES_ERROR_SOURCE_COUNT + source_id) * sizeof(uint64_t)); ++ ++ /* ++ * Read Ack Preserve field ++ * We only provide the first bit in Read Ack Register to OSPM to write ++ * while the other bits are preserved. ++ */ ++ build_append_int_noprefix(table_data, ~0x1ULL, 8); ++ /* Read Ack Write */ ++ build_append_int_noprefix(table_data, 0x1, 8); ++} ++ ++/* Build Hardware Error Source Table */ ++void acpi_build_hest(GArray *table_data, BIOSLinker *linker) ++{ ++ uint64_t hest_start = table_data->len; ++ ++ /* Hardware Error Source Table header*/ ++ acpi_data_push(table_data, sizeof(AcpiTableHeader)); ++ ++ /* Error Source Count */ ++ build_append_int_noprefix(table_data, ACPI_GHES_ERROR_SOURCE_COUNT, 4); ++ ++ build_ghes_v2(table_data, ACPI_HEST_SRC_ID_SEA, linker); ++ ++ build_header(linker, table_data, (void *)(table_data->data + hest_start), ++ "HEST", table_data->len - hest_start, 1, NULL, NULL); ++} +diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c +index 8397bda424..ef94e034f6 100644 +--- a/hw/arm/virt-acpi-build.c ++++ b/hw/arm/virt-acpi-build.c +@@ -821,6 +821,8 @@ void virt_acpi_build(VirtMachineState *vms, AcpiBuildTables *tables) + + if (vms->ras) { + build_ghes_error_table(tables->hardware_errors, tables->linker); ++ acpi_add_table(table_offsets, tables_blob); ++ acpi_build_hest(tables_blob, tables->linker); + } + + if (ms->numa_state->num_nodes > 0) { +diff --git a/include/hw/acpi/ghes.h b/include/hw/acpi/ghes.h +index 50379b0d0a..18debd8cf7 100644 +--- a/include/hw/acpi/ghes.h ++++ b/include/hw/acpi/ghes.h +@@ -24,5 +24,44 @@ + + #include "hw/acpi/bios-linker-loader.h" + ++/* ++ * Values for Hardware Error Notification Type field ++ */ ++enum AcpiGhesNotifyType { ++ /* Polled */ ++ ACPI_GHES_NOTIFY_POLLED = 0, ++ /* External Interrupt */ ++ ACPI_GHES_NOTIFY_EXTERNAL = 1, ++ /* Local Interrupt */ ++ ACPI_GHES_NOTIFY_LOCAL = 2, ++ /* SCI */ ++ ACPI_GHES_NOTIFY_SCI = 3, ++ /* NMI */ ++ ACPI_GHES_NOTIFY_NMI = 4, ++ /* CMCI, ACPI 5.0: 18.3.2.7, Table 18-290 */ ++ ACPI_GHES_NOTIFY_CMCI = 5, ++ /* MCE, ACPI 5.0: 18.3.2.7, Table 18-290 */ ++ ACPI_GHES_NOTIFY_MCE = 6, ++ /* GPIO-Signal, ACPI 6.0: 18.3.2.7, Table 18-332 */ ++ ACPI_GHES_NOTIFY_GPIO = 7, ++ /* ARMv8 SEA, ACPI 6.1: 18.3.2.9, Table 18-345 */ ++ ACPI_GHES_NOTIFY_SEA = 8, ++ /* ARMv8 SEI, ACPI 6.1: 18.3.2.9, Table 18-345 */ ++ ACPI_GHES_NOTIFY_SEI = 9, ++ /* External Interrupt - GSIV, ACPI 6.1: 18.3.2.9, Table 18-345 */ ++ ACPI_GHES_NOTIFY_GSIV = 10, ++ /* Software Delegated Exception, ACPI 6.2: 18.3.2.9, Table 18-383 */ ++ ACPI_GHES_NOTIFY_SDEI = 11, ++ /* 12 and greater are reserved */ ++ ACPI_GHES_NOTIFY_RESERVED = 12 ++}; ++ ++enum { ++ ACPI_HEST_SRC_ID_SEA = 0, ++ /* future ids go here */ ++ ACPI_HEST_SRC_ID_RESERVED, ++}; ++ + void build_ghes_error_table(GArray *hardware_errors, BIOSLinker *linker); ++void acpi_build_hest(GArray *table_data, BIOSLinker *linker); + #endif +-- +2.23.0 + diff --git a/ACPI-Build-related-register-address-fields-via-hardw.patch b/ACPI-Build-related-register-address-fields-via-hardw.patch new file mode 100644 index 0000000000000000000000000000000000000000..05c490d48013ada3997456f6458c647d25e0fad0 --- /dev/null +++ b/ACPI-Build-related-register-address-fields-via-hardw.patch @@ -0,0 +1,259 @@ +From aa16508f1d1bce2411fdbe82aa20e559bbd90e48 Mon Sep 17 00:00:00 2001 +From: Dongjiu Geng +Date: Tue, 12 May 2020 11:06:03 +0800 +Subject: [PATCH 439/709] ACPI: Build related register address fields via + hardware error fw_cfg blob + +This patch builds error_block_address and read_ack_register fields +in hardware errors table , the error_block_address points to Generic +Error Status Block(GESB) via bios_linker. The max size for one GESB +is 1kb, For more detailed information, please refer to +document: docs/specs/acpi_hest_ghes.rst + +Now we only support one Error source, if necessary, we can extend to +support more. + +Suggested-by: Laszlo Ersek +Signed-off-by: Xiang Zheng +Reviewed-by: Jonathan Cameron +Reviewed-by: Igor Mammedov +Signed-off-by: Dongjiu Geng +Reviewed-by: Michael S. Tsirkin +Message-id: 20200512030609.19593-5-gengdongjiu@huawei.com +Signed-off-by: Peter Maydell +--- + default-configs/arm-softmmu.mak | 1 + + hw/acpi/Kconfig | 4 ++ + hw/acpi/Makefile.objs | 1 + + hw/acpi/aml-build.c | 2 + + hw/acpi/ghes.c | 89 +++++++++++++++++++++++++++++++++ + hw/arm/virt-acpi-build.c | 5 ++ + include/hw/acpi/aml-build.h | 1 + + include/hw/acpi/ghes.h | 28 +++++++++++ + 8 files changed, 131 insertions(+) + create mode 100644 hw/acpi/ghes.c + create mode 100644 include/hw/acpi/ghes.h + +diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak +index 36a0e89daa..8fc09a4a51 100644 +--- a/default-configs/arm-softmmu.mak ++++ b/default-configs/arm-softmmu.mak +@@ -42,3 +42,4 @@ CONFIG_FSL_IMX7=y + CONFIG_FSL_IMX6UL=y + CONFIG_SEMIHOSTING=y + CONFIG_ALLWINNER_H3=y ++CONFIG_ACPI_APEI=y +diff --git a/hw/acpi/Kconfig b/hw/acpi/Kconfig +index 54209c6f2f..1932f66af8 100644 +--- a/hw/acpi/Kconfig ++++ b/hw/acpi/Kconfig +@@ -28,6 +28,10 @@ config ACPI_HMAT + bool + depends on ACPI + ++config ACPI_APEI ++ bool ++ depends on ACPI ++ + config ACPI_PCI + bool + depends on ACPI && PCI +diff --git a/hw/acpi/Makefile.objs b/hw/acpi/Makefile.objs +index cab9bcd457..72886c7965 100644 +--- a/hw/acpi/Makefile.objs ++++ b/hw/acpi/Makefile.objs +@@ -8,6 +8,7 @@ common-obj-$(CONFIG_ACPI_NVDIMM) += nvdimm.o + common-obj-$(CONFIG_ACPI_VMGENID) += vmgenid.o + common-obj-$(CONFIG_ACPI_HW_REDUCED) += generic_event_device.o + common-obj-$(CONFIG_ACPI_HMAT) += hmat.o ++common-obj-$(CONFIG_ACPI_APEI) += ghes.o + common-obj-$(call lnot,$(CONFIG_ACPI_X86)) += acpi-stub.o + common-obj-$(call lnot,$(CONFIG_PC)) += acpi-x86-stub.o + +diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c +index 2c3702b882..3681ec6e3d 100644 +--- a/hw/acpi/aml-build.c ++++ b/hw/acpi/aml-build.c +@@ -1578,6 +1578,7 @@ void acpi_build_tables_init(AcpiBuildTables *tables) + tables->table_data = g_array_new(false, true /* clear */, 1); + tables->tcpalog = g_array_new(false, true /* clear */, 1); + tables->vmgenid = g_array_new(false, true /* clear */, 1); ++ tables->hardware_errors = g_array_new(false, true /* clear */, 1); + tables->linker = bios_linker_loader_init(); + } + +@@ -1588,6 +1589,7 @@ void acpi_build_tables_cleanup(AcpiBuildTables *tables, bool mfre) + g_array_free(tables->table_data, true); + g_array_free(tables->tcpalog, mfre); + g_array_free(tables->vmgenid, mfre); ++ g_array_free(tables->hardware_errors, mfre); + } + + /* +diff --git a/hw/acpi/ghes.c b/hw/acpi/ghes.c +new file mode 100644 +index 0000000000..e1b3f8fcaa +--- /dev/null ++++ b/hw/acpi/ghes.c +@@ -0,0 +1,89 @@ ++/* ++ * Support for generating APEI tables and recording CPER for Guests ++ * ++ * Copyright (c) 2020 HUAWEI TECHNOLOGIES CO., LTD. ++ * ++ * Author: Dongjiu Geng ++ * ++ * 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 . ++ */ ++ ++#include "qemu/osdep.h" ++#include "qemu/units.h" ++#include "hw/acpi/ghes.h" ++#include "hw/acpi/aml-build.h" ++ ++#define ACPI_GHES_ERRORS_FW_CFG_FILE "etc/hardware_errors" ++#define ACPI_GHES_DATA_ADDR_FW_CFG_FILE "etc/hardware_errors_addr" ++ ++/* The max size in bytes for one error block */ ++#define ACPI_GHES_MAX_RAW_DATA_LENGTH (1 * KiB) ++ ++/* Now only support ARMv8 SEA notification type error source */ ++#define ACPI_GHES_ERROR_SOURCE_COUNT 1 ++ ++/* ++ * Build table for the hardware error fw_cfg blob. ++ * Initialize "etc/hardware_errors" and "etc/hardware_errors_addr" fw_cfg blobs. ++ * See docs/specs/acpi_hest_ghes.rst for blobs format. ++ */ ++void build_ghes_error_table(GArray *hardware_errors, BIOSLinker *linker) ++{ ++ int i, error_status_block_offset; ++ ++ /* Build error_block_address */ ++ for (i = 0; i < ACPI_GHES_ERROR_SOURCE_COUNT; i++) { ++ build_append_int_noprefix(hardware_errors, 0, sizeof(uint64_t)); ++ } ++ ++ /* Build read_ack_register */ ++ for (i = 0; i < ACPI_GHES_ERROR_SOURCE_COUNT; i++) { ++ /* ++ * Initialize the value of read_ack_register to 1, so GHES can be ++ * writeable after (re)boot. ++ * ACPI 6.2: 18.3.2.8 Generic Hardware Error Source version 2 ++ * (GHESv2 - Type 10) ++ */ ++ build_append_int_noprefix(hardware_errors, 1, sizeof(uint64_t)); ++ } ++ ++ /* Generic Error Status Block offset in the hardware error fw_cfg blob */ ++ error_status_block_offset = hardware_errors->len; ++ ++ /* Reserve space for Error Status Data Block */ ++ acpi_data_push(hardware_errors, ++ ACPI_GHES_MAX_RAW_DATA_LENGTH * ACPI_GHES_ERROR_SOURCE_COUNT); ++ ++ /* Tell guest firmware to place hardware_errors blob into RAM */ ++ bios_linker_loader_alloc(linker, ACPI_GHES_ERRORS_FW_CFG_FILE, ++ hardware_errors, sizeof(uint64_t), false); ++ ++ for (i = 0; i < ACPI_GHES_ERROR_SOURCE_COUNT; i++) { ++ /* ++ * Tell firmware to patch error_block_address entries to point to ++ * corresponding "Generic Error Status Block" ++ */ ++ bios_linker_loader_add_pointer(linker, ++ ACPI_GHES_ERRORS_FW_CFG_FILE, sizeof(uint64_t) * i, ++ sizeof(uint64_t), ACPI_GHES_ERRORS_FW_CFG_FILE, ++ error_status_block_offset + i * ACPI_GHES_MAX_RAW_DATA_LENGTH); ++ } ++ ++ /* ++ * tell firmware to write hardware_errors GPA into ++ * hardware_errors_addr fw_cfg, once the former has been initialized. ++ */ ++ bios_linker_loader_write_pointer(linker, ACPI_GHES_DATA_ADDR_FW_CFG_FILE, ++ 0, sizeof(uint64_t), ACPI_GHES_ERRORS_FW_CFG_FILE, 0); ++} +diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c +index f22b1e6097..8397bda424 100644 +--- a/hw/arm/virt-acpi-build.c ++++ b/hw/arm/virt-acpi-build.c +@@ -49,6 +49,7 @@ + #include "sysemu/reset.h" + #include "kvm_arm.h" + #include "migration/vmstate.h" ++#include "hw/acpi/ghes.h" + + #define ARM_SPI_BASE 32 + +@@ -818,6 +819,10 @@ void virt_acpi_build(VirtMachineState *vms, AcpiBuildTables *tables) + acpi_add_table(table_offsets, tables_blob); + build_spcr(tables_blob, tables->linker, vms); + ++ if (vms->ras) { ++ build_ghes_error_table(tables->hardware_errors, tables->linker); ++ } ++ + if (ms->numa_state->num_nodes > 0) { + acpi_add_table(table_offsets, tables_blob); + build_srat(tables_blob, tables->linker, vms); +diff --git a/include/hw/acpi/aml-build.h b/include/hw/acpi/aml-build.h +index 1539fe0667..ed7c89309e 100644 +--- a/include/hw/acpi/aml-build.h ++++ b/include/hw/acpi/aml-build.h +@@ -220,6 +220,7 @@ struct AcpiBuildTables { + GArray *rsdp; + GArray *tcpalog; + GArray *vmgenid; ++ GArray *hardware_errors; + BIOSLinker *linker; + } AcpiBuildTables; + +diff --git a/include/hw/acpi/ghes.h b/include/hw/acpi/ghes.h +new file mode 100644 +index 0000000000..50379b0d0a +--- /dev/null ++++ b/include/hw/acpi/ghes.h +@@ -0,0 +1,28 @@ ++/* ++ * Support for generating APEI tables and recording CPER for Guests ++ * ++ * Copyright (c) 2020 HUAWEI TECHNOLOGIES CO., LTD. ++ * ++ * Author: Dongjiu Geng ++ * ++ * 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 . ++ */ ++ ++#ifndef ACPI_GHES_H ++#define ACPI_GHES_H ++ ++#include "hw/acpi/bios-linker-loader.h" ++ ++void build_ghes_error_table(GArray *hardware_errors, BIOSLinker *linker); ++#endif +-- +2.23.0 + diff --git a/ACPI-Record-Generic-Error-Status-Block-GESB-table.patch b/ACPI-Record-Generic-Error-Status-Block-GESB-table.patch new file mode 100644 index 0000000000000000000000000000000000000000..a21c596ab7386789ac70b66559dad27d2eb27bfe --- /dev/null +++ b/ACPI-Record-Generic-Error-Status-Block-GESB-table.patch @@ -0,0 +1,289 @@ +From 558b9d86407d56e13d8a2cd61cdecf0359e7804a Mon Sep 17 00:00:00 2001 +From: Dongjiu Geng +Date: Tue, 12 May 2020 11:06:07 +0800 +Subject: [PATCH 443/709] ACPI: Record Generic Error Status Block(GESB) table + +kvm_arch_on_sigbus_vcpu() error injection uses source_id as +index in etc/hardware_errors to find out Error Status Data +Block entry corresponding to error source. So supported source_id +values should be assigned here and not be changed afterwards to +make sure that guest will write error into expected Error Status +Data Block. + +Before QEMU writes a new error to ACPI table, it will check whether +previous error has been acknowledged. If not acknowledged, the new +errors will be ignored and not be recorded. For the errors section +type, QEMU simulate it to memory section error. + +Signed-off-by: Dongjiu Geng +Signed-off-by: Xiang Zheng +Reviewed-by: Igor Mammedov +Reviewed-by: Michael S. Tsirkin +Message-id: 20200512030609.19593-9-gengdongjiu@huawei.com +Signed-off-by: Peter Maydell +--- + hw/acpi/ghes.c | 219 +++++++++++++++++++++++++++++++++++++++++ + include/hw/acpi/ghes.h | 1 + + 2 files changed, 220 insertions(+) + +diff --git a/hw/acpi/ghes.c b/hw/acpi/ghes.c +index e74af23c36..b363bc331d 100644 +--- a/hw/acpi/ghes.c ++++ b/hw/acpi/ghes.c +@@ -26,6 +26,7 @@ + #include "qemu/error-report.h" + #include "hw/acpi/generic_event_device.h" + #include "hw/nvram/fw_cfg.h" ++#include "qemu/uuid.h" + + #define ACPI_GHES_ERRORS_FW_CFG_FILE "etc/hardware_errors" + #define ACPI_GHES_DATA_ADDR_FW_CFG_FILE "etc/hardware_errors_addr" +@@ -42,6 +43,36 @@ + /* Address offset in Generic Address Structure(GAS) */ + #define GAS_ADDR_OFFSET 4 + ++/* ++ * The total size of Generic Error Data Entry ++ * ACPI 6.1/6.2: 18.3.2.7.1 Generic Error Data, ++ * Table 18-343 Generic Error Data Entry ++ */ ++#define ACPI_GHES_DATA_LENGTH 72 ++ ++/* The memory section CPER size, UEFI 2.6: N.2.5 Memory Error Section */ ++#define ACPI_GHES_MEM_CPER_LENGTH 80 ++ ++/* Masks for block_status flags */ ++#define ACPI_GEBS_UNCORRECTABLE 1 ++ ++/* ++ * Total size for Generic Error Status Block except Generic Error Data Entries ++ * ACPI 6.2: 18.3.2.7.1 Generic Error Data, ++ * Table 18-380 Generic Error Status Block ++ */ ++#define ACPI_GHES_GESB_SIZE 20 ++ ++/* ++ * Values for error_severity field ++ */ ++enum AcpiGenericErrorSeverity { ++ ACPI_CPER_SEV_RECOVERABLE = 0, ++ ACPI_CPER_SEV_FATAL = 1, ++ ACPI_CPER_SEV_CORRECTED = 2, ++ ACPI_CPER_SEV_NONE = 3, ++}; ++ + /* + * Hardware Error Notification + * ACPI 4.0: 17.3.2.7 Hardware Error Notification +@@ -72,6 +103,138 @@ static void build_ghes_hw_error_notification(GArray *table, const uint8_t type) + build_append_int_noprefix(table, 0, 4); + } + ++/* ++ * Generic Error Data Entry ++ * ACPI 6.1: 18.3.2.7.1 Generic Error Data ++ */ ++static void acpi_ghes_generic_error_data(GArray *table, ++ const uint8_t *section_type, uint32_t error_severity, ++ uint8_t validation_bits, uint8_t flags, ++ uint32_t error_data_length, QemuUUID fru_id, ++ uint64_t time_stamp) ++{ ++ const uint8_t fru_text[20] = {0}; ++ ++ /* Section Type */ ++ g_array_append_vals(table, section_type, 16); ++ ++ /* Error Severity */ ++ build_append_int_noprefix(table, error_severity, 4); ++ /* Revision */ ++ build_append_int_noprefix(table, 0x300, 2); ++ /* Validation Bits */ ++ build_append_int_noprefix(table, validation_bits, 1); ++ /* Flags */ ++ build_append_int_noprefix(table, flags, 1); ++ /* Error Data Length */ ++ build_append_int_noprefix(table, error_data_length, 4); ++ ++ /* FRU Id */ ++ g_array_append_vals(table, fru_id.data, ARRAY_SIZE(fru_id.data)); ++ ++ /* FRU Text */ ++ g_array_append_vals(table, fru_text, sizeof(fru_text)); ++ ++ /* Timestamp */ ++ build_append_int_noprefix(table, time_stamp, 8); ++} ++ ++/* ++ * Generic Error Status Block ++ * ACPI 6.1: 18.3.2.7.1 Generic Error Data ++ */ ++static void acpi_ghes_generic_error_status(GArray *table, uint32_t block_status, ++ uint32_t raw_data_offset, uint32_t raw_data_length, ++ uint32_t data_length, uint32_t error_severity) ++{ ++ /* Block Status */ ++ build_append_int_noprefix(table, block_status, 4); ++ /* Raw Data Offset */ ++ build_append_int_noprefix(table, raw_data_offset, 4); ++ /* Raw Data Length */ ++ build_append_int_noprefix(table, raw_data_length, 4); ++ /* Data Length */ ++ build_append_int_noprefix(table, data_length, 4); ++ /* Error Severity */ ++ build_append_int_noprefix(table, error_severity, 4); ++} ++ ++/* UEFI 2.6: N.2.5 Memory Error Section */ ++static void acpi_ghes_build_append_mem_cper(GArray *table, ++ uint64_t error_physical_addr) ++{ ++ /* ++ * Memory Error Record ++ */ ++ ++ /* Validation Bits */ ++ build_append_int_noprefix(table, ++ (1ULL << 14) | /* Type Valid */ ++ (1ULL << 1) /* Physical Address Valid */, ++ 8); ++ /* Error Status */ ++ build_append_int_noprefix(table, 0, 8); ++ /* Physical Address */ ++ build_append_int_noprefix(table, error_physical_addr, 8); ++ /* Skip all the detailed information normally found in such a record */ ++ build_append_int_noprefix(table, 0, 48); ++ /* Memory Error Type */ ++ build_append_int_noprefix(table, 0 /* Unknown error */, 1); ++ /* Skip all the detailed information normally found in such a record */ ++ build_append_int_noprefix(table, 0, 7); ++} ++ ++static int acpi_ghes_record_mem_error(uint64_t error_block_address, ++ uint64_t error_physical_addr) ++{ ++ GArray *block; ++ ++ /* Memory Error Section Type */ ++ const uint8_t uefi_cper_mem_sec[] = ++ UUID_LE(0xA5BC1114, 0x6F64, 0x4EDE, 0xB8, 0x63, 0x3E, 0x83, \ ++ 0xED, 0x7C, 0x83, 0xB1); ++ ++ /* invalid fru id: ACPI 4.0: 17.3.2.6.1 Generic Error Data, ++ * Table 17-13 Generic Error Data Entry ++ */ ++ QemuUUID fru_id = {}; ++ uint32_t data_length; ++ ++ block = g_array_new(false, true /* clear */, 1); ++ ++ /* This is the length if adding a new generic error data entry*/ ++ data_length = ACPI_GHES_DATA_LENGTH + ACPI_GHES_MEM_CPER_LENGTH; ++ ++ /* ++ * Check whether it will run out of the preallocated memory if adding a new ++ * generic error data entry ++ */ ++ if ((data_length + ACPI_GHES_GESB_SIZE) > ACPI_GHES_MAX_RAW_DATA_LENGTH) { ++ error_report("Not enough memory to record new CPER!!!"); ++ g_array_free(block, true); ++ return -1; ++ } ++ ++ /* Build the new generic error status block header */ ++ acpi_ghes_generic_error_status(block, ACPI_GEBS_UNCORRECTABLE, ++ 0, 0, data_length, ACPI_CPER_SEV_RECOVERABLE); ++ ++ /* Build this new generic error data entry header */ ++ acpi_ghes_generic_error_data(block, uefi_cper_mem_sec, ++ ACPI_CPER_SEV_RECOVERABLE, 0, 0, ++ ACPI_GHES_MEM_CPER_LENGTH, fru_id, 0); ++ ++ /* Build the memory section CPER for above new generic error data entry */ ++ acpi_ghes_build_append_mem_cper(block, error_physical_addr); ++ ++ /* Write the generic error data entry into guest memory */ ++ cpu_physical_memory_write(error_block_address, block->data, block->len); ++ ++ g_array_free(block, true); ++ ++ return 0; ++} ++ + /* + * Build table for the hardware error fw_cfg blob. + * Initialize "etc/hardware_errors" and "etc/hardware_errors_addr" fw_cfg blobs. +@@ -227,3 +390,59 @@ void acpi_ghes_add_fw_cfg(AcpiGhesState *ags, FWCfgState *s, + fw_cfg_add_file_callback(s, ACPI_GHES_DATA_ADDR_FW_CFG_FILE, NULL, NULL, + NULL, &(ags->ghes_addr_le), sizeof(ags->ghes_addr_le), false); + } ++ ++int acpi_ghes_record_errors(uint8_t source_id, uint64_t physical_address) ++{ ++ uint64_t error_block_addr, read_ack_register_addr, read_ack_register = 0; ++ uint64_t start_addr; ++ bool ret = -1; ++ AcpiGedState *acpi_ged_state; ++ AcpiGhesState *ags; ++ ++ assert(source_id < ACPI_HEST_SRC_ID_RESERVED); ++ ++ acpi_ged_state = ACPI_GED(object_resolve_path_type("", TYPE_ACPI_GED, ++ NULL)); ++ g_assert(acpi_ged_state); ++ ags = &acpi_ged_state->ghes_state; ++ ++ start_addr = le64_to_cpu(ags->ghes_addr_le); ++ ++ if (physical_address) { ++ ++ if (source_id < ACPI_HEST_SRC_ID_RESERVED) { ++ start_addr += source_id * sizeof(uint64_t); ++ } ++ ++ cpu_physical_memory_read(start_addr, &error_block_addr, ++ sizeof(error_block_addr)); ++ ++ error_block_addr = le64_to_cpu(error_block_addr); ++ ++ read_ack_register_addr = start_addr + ++ ACPI_GHES_ERROR_SOURCE_COUNT * sizeof(uint64_t); ++ ++ cpu_physical_memory_read(read_ack_register_addr, ++ &read_ack_register, sizeof(read_ack_register)); ++ ++ /* zero means OSPM does not acknowledge the error */ ++ if (!read_ack_register) { ++ error_report("OSPM does not acknowledge previous error," ++ " so can not record CPER for current error anymore"); ++ } else if (error_block_addr) { ++ read_ack_register = cpu_to_le64(0); ++ /* ++ * Clear the Read Ack Register, OSPM will write it to 1 when ++ * it acknowledges this error. ++ */ ++ cpu_physical_memory_write(read_ack_register_addr, ++ &read_ack_register, sizeof(uint64_t)); ++ ++ ret = acpi_ghes_record_mem_error(error_block_addr, ++ physical_address); ++ } else ++ error_report("can not find Generic Error Status Block"); ++ } ++ ++ return ret; ++} +diff --git a/include/hw/acpi/ghes.h b/include/hw/acpi/ghes.h +index a3420fc9be..4ad025e09a 100644 +--- a/include/hw/acpi/ghes.h ++++ b/include/hw/acpi/ghes.h +@@ -70,4 +70,5 @@ void build_ghes_error_table(GArray *hardware_errors, BIOSLinker *linker); + void acpi_build_hest(GArray *table_data, BIOSLinker *linker); + void acpi_ghes_add_fw_cfg(AcpiGhesState *vms, FWCfgState *s, + GArray *hardware_errors); ++int acpi_ghes_record_errors(uint8_t notify, uint64_t error_physical_addr); + #endif +-- +2.23.0 + diff --git a/ACPI-Record-the-Generic-Error-Status-Block-address.patch b/ACPI-Record-the-Generic-Error-Status-Block-address.patch new file mode 100644 index 0000000000000000000000000000000000000000..83c27504853b0cc9c4793d6c12a9861b12167405 --- /dev/null +++ b/ACPI-Record-the-Generic-Error-Status-Block-address.patch @@ -0,0 +1,160 @@ +From a08a64627b6b5874f3dbf202fb08563e7a74b1ea Mon Sep 17 00:00:00 2001 +From: Dongjiu Geng +Date: Tue, 12 May 2020 11:06:05 +0800 +Subject: [PATCH 441/709] ACPI: Record the Generic Error Status Block address + +Record the GHEB address via fw_cfg file, when recording +a error to CPER, it will use this address to find out +Generic Error Data Entries and write the error. + +In order to avoid migration failure, make hardware +error table address to a part of GED device instead +of global variable, then this address will be migrated +to target QEMU. + +Acked-by: Xiang Zheng +Signed-off-by: Dongjiu Geng +Reviewed-by: Igor Mammedov +Reviewed-by: Michael S. Tsirkin +Message-id: 20200512030609.19593-7-gengdongjiu@huawei.com +Signed-off-by: Peter Maydell +--- + hw/acpi/generic_event_device.c | 19 +++++++++++++++++++ + hw/acpi/ghes.c | 14 ++++++++++++++ + hw/arm/virt-acpi-build.c | 8 ++++++++ + include/hw/acpi/generic_event_device.h | 2 ++ + include/hw/acpi/ghes.h | 6 ++++++ + 5 files changed, 49 insertions(+) + +diff --git a/hw/acpi/generic_event_device.c b/hw/acpi/generic_event_device.c +index 5d17f78a1e..b1cbdd86b6 100644 +--- a/hw/acpi/generic_event_device.c ++++ b/hw/acpi/generic_event_device.c +@@ -247,6 +247,24 @@ static const VMStateDescription vmstate_ged_state = { + } + }; + ++static bool ghes_needed(void *opaque) ++{ ++ AcpiGedState *s = opaque; ++ return s->ghes_state.ghes_addr_le; ++} ++ ++static const VMStateDescription vmstate_ghes_state = { ++ .name = "acpi-ged/ghes", ++ .version_id = 1, ++ .minimum_version_id = 1, ++ .needed = ghes_needed, ++ .fields = (VMStateField[]) { ++ VMSTATE_STRUCT(ghes_state, AcpiGedState, 1, ++ vmstate_ghes_state, AcpiGhesState), ++ VMSTATE_END_OF_LIST() ++ } ++}; ++ + static const VMStateDescription vmstate_acpi_ged = { + .name = "acpi-ged", + .version_id = 1, +@@ -257,6 +275,7 @@ static const VMStateDescription vmstate_acpi_ged = { + }, + .subsections = (const VMStateDescription * []) { + &vmstate_memhp_state, ++ &vmstate_ghes_state, + NULL + } + }; +diff --git a/hw/acpi/ghes.c b/hw/acpi/ghes.c +index 091fd87094..e74af23c36 100644 +--- a/hw/acpi/ghes.c ++++ b/hw/acpi/ghes.c +@@ -24,6 +24,8 @@ + #include "hw/acpi/ghes.h" + #include "hw/acpi/aml-build.h" + #include "qemu/error-report.h" ++#include "hw/acpi/generic_event_device.h" ++#include "hw/nvram/fw_cfg.h" + + #define ACPI_GHES_ERRORS_FW_CFG_FILE "etc/hardware_errors" + #define ACPI_GHES_DATA_ADDR_FW_CFG_FILE "etc/hardware_errors_addr" +@@ -213,3 +215,15 @@ void acpi_build_hest(GArray *table_data, BIOSLinker *linker) + build_header(linker, table_data, (void *)(table_data->data + hest_start), + "HEST", table_data->len - hest_start, 1, NULL, NULL); + } ++ ++void acpi_ghes_add_fw_cfg(AcpiGhesState *ags, FWCfgState *s, ++ GArray *hardware_error) ++{ ++ /* Create a read-only fw_cfg file for GHES */ ++ fw_cfg_add_file(s, ACPI_GHES_ERRORS_FW_CFG_FILE, hardware_error->data, ++ hardware_error->len); ++ ++ /* Create a read-write fw_cfg file for Address */ ++ fw_cfg_add_file_callback(s, ACPI_GHES_DATA_ADDR_FW_CFG_FILE, NULL, NULL, ++ NULL, &(ags->ghes_addr_le), sizeof(ags->ghes_addr_le), false); ++} +diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c +index ef94e034f6..1b0a584c7b 100644 +--- a/hw/arm/virt-acpi-build.c ++++ b/hw/arm/virt-acpi-build.c +@@ -917,6 +917,7 @@ void virt_acpi_setup(VirtMachineState *vms) + { + AcpiBuildTables tables; + AcpiBuildState *build_state; ++ AcpiGedState *acpi_ged_state; + + if (!vms->fw_cfg) { + trace_virt_acpi_setup(); +@@ -947,6 +948,13 @@ void virt_acpi_setup(VirtMachineState *vms) + fw_cfg_add_file(vms->fw_cfg, ACPI_BUILD_TPMLOG_FILE, tables.tcpalog->data, + acpi_data_len(tables.tcpalog)); + ++ if (vms->ras) { ++ assert(vms->acpi_dev); ++ acpi_ged_state = ACPI_GED(vms->acpi_dev); ++ acpi_ghes_add_fw_cfg(&acpi_ged_state->ghes_state, ++ vms->fw_cfg, tables.hardware_errors); ++ } ++ + build_state->rsdp_mr = acpi_add_rom_blob(virt_acpi_build_update, + build_state, tables.rsdp, + ACPI_BUILD_RSDP_FILE, 0); +diff --git a/include/hw/acpi/generic_event_device.h b/include/hw/acpi/generic_event_device.h +index 9eb86ca4fd..83917de024 100644 +--- a/include/hw/acpi/generic_event_device.h ++++ b/include/hw/acpi/generic_event_device.h +@@ -61,6 +61,7 @@ + + #include "hw/sysbus.h" + #include "hw/acpi/memory_hotplug.h" ++#include "hw/acpi/ghes.h" + + #define ACPI_POWER_BUTTON_DEVICE "PWRB" + +@@ -96,6 +97,7 @@ typedef struct AcpiGedState { + GEDState ged_state; + uint32_t ged_event_bitmap; + qemu_irq irq; ++ AcpiGhesState ghes_state; + } AcpiGedState; + + void build_ged_aml(Aml *table, const char* name, HotplugHandler *hotplug_dev, +diff --git a/include/hw/acpi/ghes.h b/include/hw/acpi/ghes.h +index 18debd8cf7..a3420fc9be 100644 +--- a/include/hw/acpi/ghes.h ++++ b/include/hw/acpi/ghes.h +@@ -62,6 +62,12 @@ enum { + ACPI_HEST_SRC_ID_RESERVED, + }; + ++typedef struct AcpiGhesState { ++ uint64_t ghes_addr_le; ++} AcpiGhesState; ++ + void build_ghes_error_table(GArray *hardware_errors, BIOSLinker *linker); + void acpi_build_hest(GArray *table_data, BIOSLinker *linker); ++void acpi_ghes_add_fw_cfg(AcpiGhesState *vms, FWCfgState *s, ++ GArray *hardware_errors); + #endif +-- +2.23.0 + diff --git a/ARM-KVM-Check-KVM_CAP_ARM_IRQ_LINE_LAYOUT_2-for-smp_.patch b/ARM-KVM-Check-KVM_CAP_ARM_IRQ_LINE_LAYOUT_2-for-smp_.patch deleted file mode 100644 index 5727a1d482a732c900701024507156a0f999bf40..0000000000000000000000000000000000000000 --- a/ARM-KVM-Check-KVM_CAP_ARM_IRQ_LINE_LAYOUT_2-for-smp_.patch +++ /dev/null @@ -1,61 +0,0 @@ -From f3c1fc4dce1582ccc1754899d5149d233e8629ff Mon Sep 17 00:00:00 2001 -From: Eric Auger -Date: Thu, 3 Oct 2019 17:46:40 +0200 -Subject: [PATCH 3/3] ARM: KVM: Check KVM_CAP_ARM_IRQ_LINE_LAYOUT_2 for - smp_cpus > 256 - -Host kernel within [4.18, 5.3] report an erroneous KVM_MAX_VCPUS=512 -for ARM. The actual capability to instantiate more than 256 vcpus -was fixed in 5.4 with the upgrade of the KVM_IRQ_LINE ABI to support -vcpu id encoded on 12 bits instead of 8 and a redistributor consuming -a single KVM IO device instead of 2. - -So let's check this capability when attempting to use more than 256 -vcpus within any ARM kvm accelerated machine. - -Signed-off-by: Eric Auger -Reviewed-by: Richard Henderson -Reviewed-by: Andrew Jones -Acked-by: Marc Zyngier -Message-id: 20191003154640.22451-4-eric.auger@redhat.com -Signed-off-by: Peter Maydell -(cherry-picked from commit fff9f5558d0e0813d4f80bfe1602acf225eca4fd) -[yu: Use the legacy smp_cpus instead of ms->smp.cpus, as we don't have - struct CpuTopology in MachineState at that time. See commit - edeeec911702 for details.] -Signed-off-by: Zenghui Yu ---- - target/arm/kvm.c | 10 +++++++++- - 1 file changed, 9 insertions(+), 1 deletion(-) - -diff --git a/target/arm/kvm.c b/target/arm/kvm.c -index f60185ad..383423c4 100644 ---- a/target/arm/kvm.c -+++ b/target/arm/kvm.c -@@ -174,6 +174,7 @@ int kvm_arm_get_max_vm_ipa_size(MachineState *ms) - - int kvm_arch_init(MachineState *ms, KVMState *s) - { -+ int ret = 0; - /* For ARM interrupt delivery is always asynchronous, - * whether we are using an in-kernel VGIC or not. - */ -@@ -187,7 +188,14 @@ int kvm_arch_init(MachineState *ms, KVMState *s) - - cap_has_mp_state = kvm_check_extension(s, KVM_CAP_MP_STATE); - -- return 0; -+ if (smp_cpus > 256 && -+ !kvm_check_extension(s, KVM_CAP_ARM_IRQ_LINE_LAYOUT_2)) { -+ error_report("Using more than 256 vcpus requires a host kernel " -+ "with KVM_CAP_ARM_IRQ_LINE_LAYOUT_2"); -+ ret = -EINVAL; -+ } -+ -+ return ret; - } - - unsigned long kvm_arch_vcpu_id(CPUState *cpu) --- -2.19.1 - diff --git a/ARM-PL061-Introduce-N_GPIOS.patch b/ARM-PL061-Introduce-N_GPIOS.patch new file mode 100644 index 0000000000000000000000000000000000000000..f3b57786da478d540f53e66f5e9426c2e9673e9b --- /dev/null +++ b/ARM-PL061-Introduce-N_GPIOS.patch @@ -0,0 +1,74 @@ +From faf58e53695be8eedc47b6232d581d37461d0f6e Mon Sep 17 00:00:00 2001 +From: Geert Uytterhoeven +Date: Tue, 19 May 2020 10:51:43 +0200 +Subject: [PATCH 630/709] ARM: PL061: Introduce N_GPIOS +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Add a definition for the number of GPIO lines controlled by a PL061 +instance, and use it instead of the hardcoded magic value 8. + +Suggested-by: Philippe Mathieu-Daudé +Signed-off-by: Geert Uytterhoeven +Reviewed-by: Philippe Mathieu-Daudé +Message-id: 20200519085143.1376-1-geert+renesas@glider.be +Signed-off-by: Peter Maydell +--- + hw/gpio/pl061.c | 12 +++++++----- + 1 file changed, 7 insertions(+), 5 deletions(-) + +diff --git a/hw/gpio/pl061.c b/hw/gpio/pl061.c +index 2a828260bd..6d3c36bc16 100644 +--- a/hw/gpio/pl061.c ++++ b/hw/gpio/pl061.c +@@ -36,6 +36,8 @@ static const uint8_t pl061_id_luminary[12] = + #define TYPE_PL061 "pl061" + #define PL061(obj) OBJECT_CHECK(PL061State, (obj), TYPE_PL061) + ++#define N_GPIOS 8 ++ + typedef struct PL061State { + SysBusDevice parent_obj; + +@@ -62,7 +64,7 @@ typedef struct PL061State { + uint32_t cr; + uint32_t amsel; + qemu_irq irq; +- qemu_irq out[8]; ++ qemu_irq out[N_GPIOS]; + const unsigned char *id; + uint32_t rsvd_start; /* reserved area: [rsvd_start, 0xfcc] */ + } PL061State; +@@ -112,7 +114,7 @@ static void pl061_update(PL061State *s) + changed = s->old_out_data ^ out; + if (changed) { + s->old_out_data = out; +- for (i = 0; i < 8; i++) { ++ for (i = 0; i < N_GPIOS; i++) { + mask = 1 << i; + if (changed & mask) { + DPRINTF("Set output %d = %d\n", i, (out & mask) != 0); +@@ -125,7 +127,7 @@ static void pl061_update(PL061State *s) + changed = (s->old_in_data ^ s->data) & ~s->dir; + if (changed) { + s->old_in_data = s->data; +- for (i = 0; i < 8; i++) { ++ for (i = 0; i < N_GPIOS; i++) { + mask = 1 << i; + if (changed & mask) { + DPRINTF("Changed input %d = %d\n", i, (s->data & mask) != 0); +@@ -364,8 +366,8 @@ static void pl061_init(Object *obj) + memory_region_init_io(&s->iomem, obj, &pl061_ops, s, "pl061", 0x1000); + sysbus_init_mmio(sbd, &s->iomem); + sysbus_init_irq(sbd, &s->irq); +- qdev_init_gpio_in(dev, pl061_set_irq, 8); +- qdev_init_gpio_out(dev, s->out, 8); ++ qdev_init_gpio_in(dev, pl061_set_irq, N_GPIOS); ++ qdev_init_gpio_out(dev, s->out, N_GPIOS); + } + + static void pl061_class_init(ObjectClass *klass, void *data) +-- +2.23.0 + diff --git a/ARM64-record-vtimer-tick-when-cpu-is-stopped.patch b/ARM64-record-vtimer-tick-when-cpu-is-stopped.patch deleted file mode 100644 index b2ad176f8d56fdc71b6663f36bad7cc93ed4429a..0000000000000000000000000000000000000000 --- a/ARM64-record-vtimer-tick-when-cpu-is-stopped.patch +++ /dev/null @@ -1,134 +0,0 @@ -From d2fd6d1a5200b9a58863839d21d291cd4f76ac31 Mon Sep 17 00:00:00 2001 -From: Ying Fang -Date: Mon, 29 Jul 2019 15:47:27 +0800 -Subject: [PATCH] ARM64: record vtimer tick when cpu is stopped - -The vtimer kick still increases even if the vcpu is stopped when VM has -save/restore or suspend/resume operation. This will cause guest watchdog -soft-lockup if the VM has lots of memory in use. - -Signed-off-by: Hao Hong -Signed-off-by: Haibin Wang -Signed-off-by: Ying Fang ---- - cpus.c | 58 ++++++++++++++++++++++++++++++++++++++++++++ - target/arm/cpu.h | 2 ++ - target/arm/machine.c | 1 + - 3 files changed, 61 insertions(+) - -diff --git a/cpus.c b/cpus.c -index e83f72b4..f6ec48a2 100644 ---- a/cpus.c -+++ b/cpus.c -@@ -1063,6 +1063,28 @@ void cpu_synchronize_all_pre_loadvm(void) - } - } - -+#ifdef __aarch64__ -+static void get_vcpu_timer_tick(CPUState *cs) -+{ -+ CPUARMState *env = &ARM_CPU(cs)->env; -+ int err; -+ struct kvm_one_reg reg; -+ uint64_t timer_tick; -+ -+ reg.id = KVM_REG_ARM_TIMER_CNT; -+ reg.addr = (uintptr_t) &timer_tick; -+ -+ err = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, ®); -+ if (err < 0) { -+ error_report("get vcpu tick failed, ret = %d", err); -+ env->vtimer = 0; -+ return; -+ } -+ env->vtimer = timer_tick; -+ return; -+} -+#endif -+ - static int do_vm_stop(RunState state, bool send_stop) - { - int ret = 0; -@@ -1070,6 +1092,11 @@ static int do_vm_stop(RunState state, bool send_stop) - if (runstate_is_running()) { - cpu_disable_ticks(); - pause_all_vcpus(); -+#ifdef __aarch64__ -+ if (first_cpu) { -+ get_vcpu_timer_tick(first_cpu); -+ } -+#endif - runstate_set(state); - vm_state_notify(0, state); - if (send_stop) { -@@ -1909,11 +1936,42 @@ void cpu_resume(CPUState *cpu) - qemu_cpu_kick(cpu); - } - -+#ifdef __aarch64__ -+static void set_vcpu_timer_tick(CPUState *cs) -+{ -+ CPUARMState *env = &ARM_CPU(cs)->env; -+ -+ if (env->vtimer == 0) { -+ return; -+ } -+ -+ int err; -+ struct kvm_one_reg reg; -+ uint64_t timer_tick = env->vtimer; -+ env->vtimer = 0; -+ -+ reg.id = KVM_REG_ARM_TIMER_CNT; -+ reg.addr = (uintptr_t) &timer_tick; -+ -+ err = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®); -+ if (err < 0) { -+ error_report("Set vcpu tick failed, ret = %d", err); -+ return; -+ } -+ return; -+} -+#endif -+ - void resume_all_vcpus(void) - { - CPUState *cpu; - - qemu_clock_enable(QEMU_CLOCK_VIRTUAL, true); -+#ifdef __aarch64__ -+ if (first_cpu) { -+ set_vcpu_timer_tick(first_cpu); -+ } -+#endif - CPU_FOREACH(cpu) { - cpu_resume(cpu); - } -diff --git a/target/arm/cpu.h b/target/arm/cpu.h -index d4d28369..e107e395 100644 ---- a/target/arm/cpu.h -+++ b/target/arm/cpu.h -@@ -270,6 +270,8 @@ typedef struct CPUARMState { - uint64_t elr_el[4]; /* AArch64 exception link regs */ - uint64_t sp_el[4]; /* AArch64 banked stack pointers */ - -+ uint64_t vtimer; /* Timer tick when vcpu stop */ -+ - /* System control coprocessor (cp15) */ - struct { - uint32_t c0_cpuid; -diff --git a/target/arm/machine.c b/target/arm/machine.c -index b2925496..d64a0057 100644 ---- a/target/arm/machine.c -+++ b/target/arm/machine.c -@@ -792,6 +792,7 @@ const VMStateDescription vmstate_arm_cpu = { - VMSTATE_UINT32(env.exception.syndrome, ARMCPU), - VMSTATE_UINT32(env.exception.fsr, ARMCPU), - VMSTATE_UINT64(env.exception.vaddress, ARMCPU), -+ VMSTATE_UINT64(env.vtimer, ARMCPU), - VMSTATE_TIMER_PTR(gt_timer[GTIMER_PHYS], ARMCPU), - VMSTATE_TIMER_PTR(gt_timer[GTIMER_VIRT], ARMCPU), - { --- -2.23.0 - diff --git a/COVER-RISC-V-Remove-deprecated-ISA-CPUs-and-machines.patch b/COVER-RISC-V-Remove-deprecated-ISA-CPUs-and-machines.patch new file mode 100644 index 0000000000000000000000000000000000000000..4dba9c2f67a8323b1c00808707515afe721cded0 --- /dev/null +++ b/COVER-RISC-V-Remove-deprecated-ISA-CPUs-and-machines.patch @@ -0,0 +1,29 @@ +From e0c4f85ea494f419166eb0991528769f8abe8126 Mon Sep 17 00:00:00 2001 +From: Alistair Francis +Date: Tue, 5 May 2020 18:09:57 -0700 +Subject: [PATCH 670/709] COVER: RISC-V: Remove deprecated ISA, CPUs and + machines + +---CHANGELOG--- +PUBLIC + +v4: + - Remove all of the < PRIV_VERSION_1_10_0 checks +v3: + - Don't use SiFive CPUs for Spike machine +v2: + - Remove the CPUs and ISA seperatley +---END--- + +Signed-off-by: Alistair Francis +--- + COVER | 0 + 1 file changed, 0 insertions(+), 0 deletions(-) + create mode 100644 COVER + +diff --git a/COVER b/COVER +new file mode 100644 +index 0000000000..e69de29bb2 +-- +2.23.0 + diff --git a/COVER-RISC-V-Update-the-Hypervisor-spec-to-v0.6.1.patch b/COVER-RISC-V-Update-the-Hypervisor-spec-to-v0.6.1.patch new file mode 100644 index 0000000000000000000000000000000000000000..4af4c4fe57d139e85578678201053c5232146a92 --- /dev/null +++ b/COVER-RISC-V-Update-the-Hypervisor-spec-to-v0.6.1.patch @@ -0,0 +1,33 @@ +From c3df759ed4fc5357ba21de2b65feb36973600d38 Mon Sep 17 00:00:00 2001 +From: Alistair Francis +Date: Sun, 26 Apr 2020 09:10:10 -0700 +Subject: [PATCH 688/709] COVER: RISC-V: Update the Hypervisor spec to v0.6.1 + +---CHANGELOG--- +PUBLIC +This series updates the experimental QEMU RISC-V Hypervisor spec to the +v0.6.1 draft implementation. + +THis includes support for the new 2-stage lookup instructions and the new +CSRs. + +It also includes the new 0.6.1 support for the virtual instruction +fault. + +This was tested by running 32-bit and 64-bit Xvisor on QEMU and starting +Linux guests. + +---END--- + +Signed-off-by: Alistair Francis +--- + build/__COVER__ | 0 + 1 file changed, 0 insertions(+), 0 deletions(-) + create mode 100644 build/__COVER__ + +diff --git a/build/__COVER__ b/build/__COVER__ +new file mode 100644 +index 0000000000..e69de29bb2 +-- +2.23.0 + diff --git a/Cadence-gem-fix-wraparound-in-64bit-descriptors.patch b/Cadence-gem-fix-wraparound-in-64bit-descriptors.patch new file mode 100644 index 0000000000000000000000000000000000000000..b14d558a30abd6dfc685f0e90f0b1a29318fec66 --- /dev/null +++ b/Cadence-gem-fix-wraparound-in-64bit-descriptors.patch @@ -0,0 +1,40 @@ +From f1e7cb1388e46eac8285854af2abdfde41ffa226 Mon Sep 17 00:00:00 2001 +From: Ramon Fried +Date: Fri, 17 Apr 2020 20:17:36 +0300 +Subject: [PATCH 112/709] Cadence: gem: fix wraparound in 64bit descriptors + +Wraparound of TX descriptor cyclic buffer only updated +the low 32 bits of the descriptor. +Fix that by checking if we're working with 64bit descriptors. + +Signed-off-by: Ramon Fried +Reviewed-by: Edgar E. Iglesias +Message-id: 20200417171736.441607-1-rfried.dev@gmail.com +Signed-off-by: Peter Maydell +--- + hw/net/cadence_gem.c | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +diff --git a/hw/net/cadence_gem.c b/hw/net/cadence_gem.c +index 51ec5a072d..b7b7985bf2 100644 +--- a/hw/net/cadence_gem.c ++++ b/hw/net/cadence_gem.c +@@ -1238,7 +1238,14 @@ static void gem_transmit(CadenceGEMState *s) + /* read next descriptor */ + if (tx_desc_get_wrap(desc)) { + tx_desc_set_last(desc); +- packet_desc_addr = s->regs[GEM_TXQBASE]; ++ ++ if (s->regs[GEM_DMACFG] & GEM_DMACFG_ADDR_64B) { ++ packet_desc_addr = s->regs[GEM_TBQPH]; ++ packet_desc_addr <<= 32; ++ } else { ++ packet_desc_addr = 0; ++ } ++ packet_desc_addr |= s->regs[GEM_TXQBASE]; + } else { + packet_desc_addr += 4 * gem_get_desc_len(s, false); + } +-- +2.23.0 + diff --git a/Compress-lines-for-immediate-return.patch b/Compress-lines-for-immediate-return.patch new file mode 100644 index 0000000000000000000000000000000000000000..a919dc932de87f36eee0d8b350fd44f1d1e723cd --- /dev/null +++ b/Compress-lines-for-immediate-return.patch @@ -0,0 +1,225 @@ +From b3ac2b94cdc939a90d5a22338ae507689e2cfab0 Mon Sep 17 00:00:00 2001 +From: Simran Singhal +Date: Wed, 1 Apr 2020 22:23:14 +0530 +Subject: [PATCH 194/709] Compress lines for immediate return + +Compress two lines into a single line if immediate return statement is found. + +It also remove variables progress, val, data, ret and sock +as they are no longer needed. + +Remove space between function "mixer_load" and '(' to fix the +checkpatch.pl error:- +ERROR: space prohibited between function name and open parenthesis '(' + +Done using following coccinelle script: +@@ +local idexpression ret; +expression e; +@@ + +-ret = ++return + e; +-return ret; + +Signed-off-by: Simran Singhal +Reviewed-by: Stefan Hajnoczi +Message-Id: <20200401165314.GA3213@simran-Inspiron-5558> +[lv: in handle_aiocb_write_zeroes_unmap() move "int ret" inside the #ifdef] +Signed-off-by: Laurent Vivier +--- + block/file-posix.c | 8 +++----- + block/nfs.c | 3 +-- + block/nvme.c | 4 +--- + block/vhdx.c | 3 +-- + hw/audio/ac97.c | 4 +--- + hw/audio/adlib.c | 5 +---- + hw/display/cirrus_vga.c | 4 +--- + migration/ram.c | 4 +--- + ui/gtk.c | 3 +-- + util/qemu-sockets.c | 5 +---- + 10 files changed, 12 insertions(+), 31 deletions(-) + +diff --git a/block/file-posix.c b/block/file-posix.c +index bf09ad8bc0..05e094be29 100644 +--- a/block/file-posix.c ++++ b/block/file-posix.c +@@ -1617,13 +1617,12 @@ static int handle_aiocb_write_zeroes_unmap(void *opaque) + { + RawPosixAIOData *aiocb = opaque; + BDRVRawState *s G_GNUC_UNUSED = aiocb->bs->opaque; +- int ret; + + /* First try to write zeros and unmap at the same time */ + + #ifdef CONFIG_FALLOCATE_PUNCH_HOLE +- ret = do_fallocate(s->fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE, +- aiocb->aio_offset, aiocb->aio_nbytes); ++ int ret = do_fallocate(s->fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE, ++ aiocb->aio_offset, aiocb->aio_nbytes); + if (ret != -ENOTSUP) { + return ret; + } +@@ -1631,8 +1630,7 @@ static int handle_aiocb_write_zeroes_unmap(void *opaque) + + /* If we couldn't manage to unmap while guaranteed that the area reads as + * all-zero afterwards, just write zeroes without unmapping */ +- ret = handle_aiocb_write_zeroes(aiocb); +- return ret; ++ return handle_aiocb_write_zeroes(aiocb); + } + + #ifndef HAVE_COPY_FILE_RANGE +diff --git a/block/nfs.c b/block/nfs.c +index 2393fbfe6b..18c0a73694 100644 +--- a/block/nfs.c ++++ b/block/nfs.c +@@ -623,8 +623,7 @@ static int nfs_file_open(BlockDriverState *bs, QDict *options, int flags, + } + + bs->total_sectors = ret; +- ret = 0; +- return ret; ++ return 0; + } + + static QemuOptsList nfs_create_opts = { +diff --git a/block/nvme.c b/block/nvme.c +index 7b7c0cc5d6..eb2f54dd9d 100644 +--- a/block/nvme.c ++++ b/block/nvme.c +@@ -575,11 +575,9 @@ static bool nvme_poll_cb(void *opaque) + { + EventNotifier *e = opaque; + BDRVNVMeState *s = container_of(e, BDRVNVMeState, irq_notifier); +- bool progress = false; + + trace_nvme_poll_cb(s); +- progress = nvme_poll_queues(s); +- return progress; ++ return nvme_poll_queues(s); + } + + static int nvme_init(BlockDriverState *bs, const char *device, int namespace, +diff --git a/block/vhdx.c b/block/vhdx.c +index 45be0a4321..aedd782604 100644 +--- a/block/vhdx.c ++++ b/block/vhdx.c +@@ -411,8 +411,7 @@ int vhdx_update_headers(BlockDriverState *bs, BDRVVHDXState *s, + if (ret < 0) { + return ret; + } +- ret = vhdx_update_header(bs, s, generate_data_write_guid, log_guid); +- return ret; ++ return vhdx_update_header(bs, s, generate_data_write_guid, log_guid); + } + + /* opens the specified header block from the VHDX file header section */ +diff --git a/hw/audio/ac97.c b/hw/audio/ac97.c +index 1ec87feec0..8a9b9924c4 100644 +--- a/hw/audio/ac97.c ++++ b/hw/audio/ac97.c +@@ -573,11 +573,9 @@ static uint32_t nam_readb (void *opaque, uint32_t addr) + static uint32_t nam_readw (void *opaque, uint32_t addr) + { + AC97LinkState *s = opaque; +- uint32_t val = ~0U; + uint32_t index = addr; + s->cas = 0; +- val = mixer_load (s, index); +- return val; ++ return mixer_load(s, index); + } + + static uint32_t nam_readl (void *opaque, uint32_t addr) +diff --git a/hw/audio/adlib.c b/hw/audio/adlib.c +index d6c1fb0586..7c3b67dcfb 100644 +--- a/hw/audio/adlib.c ++++ b/hw/audio/adlib.c +@@ -120,13 +120,10 @@ static void adlib_write(void *opaque, uint32_t nport, uint32_t val) + static uint32_t adlib_read(void *opaque, uint32_t nport) + { + AdlibState *s = opaque; +- uint8_t data; + int a = nport & 3; + + adlib_kill_timers (s); +- data = OPLRead (s->opl, a); +- +- return data; ++ return OPLRead (s->opl, a); + } + + static void timer_handler (void *opaque, int c, double interval_Sec) +diff --git a/hw/display/cirrus_vga.c b/hw/display/cirrus_vga.c +index 0d391e1300..1f29731ffe 100644 +--- a/hw/display/cirrus_vga.c ++++ b/hw/display/cirrus_vga.c +@@ -2411,12 +2411,10 @@ static uint64_t cirrus_linear_bitblt_read(void *opaque, + unsigned size) + { + CirrusVGAState *s = opaque; +- uint32_t ret; + + /* XXX handle bitblt */ + (void)s; +- ret = 0xff; +- return ret; ++ return 0xff; + } + + static void cirrus_linear_bitblt_write(void *opaque, +diff --git a/migration/ram.c b/migration/ram.c +index 04f13feb2e..06cba88632 100644 +--- a/migration/ram.c ++++ b/migration/ram.c +@@ -2135,9 +2135,7 @@ int ram_postcopy_send_discard_bitmap(MigrationState *ms) + } + trace_ram_postcopy_send_discard_bitmap(); + +- ret = postcopy_each_ram_send_discard(ms); +- +- return ret; ++ return postcopy_each_ram_send_discard(ms); + } + + /** +diff --git a/ui/gtk.c b/ui/gtk.c +index 030b251c61..83f2f5d49b 100644 +--- a/ui/gtk.c ++++ b/ui/gtk.c +@@ -1650,8 +1650,7 @@ static GSList *gd_vc_menu_init(GtkDisplayState *s, VirtualConsole *vc, + G_CALLBACK(gd_menu_switch_vc), s); + gtk_menu_shell_append(GTK_MENU_SHELL(view_menu), vc->menu_item); + +- group = gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(vc->menu_item)); +- return group; ++ return gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(vc->menu_item)); + } + + #if defined(CONFIG_VTE) +diff --git a/util/qemu-sockets.c b/util/qemu-sockets.c +index bcc06d0e01..86c48b9fa5 100644 +--- a/util/qemu-sockets.c ++++ b/util/qemu-sockets.c +@@ -765,15 +765,12 @@ static int vsock_connect_addr(const struct sockaddr_vm *svm, Error **errp) + static int vsock_connect_saddr(VsockSocketAddress *vaddr, Error **errp) + { + struct sockaddr_vm svm; +- int sock = -1; + + if (!vsock_parse_vaddr_to_sockaddr(vaddr, &svm, errp)) { + return -1; + } + +- sock = vsock_connect_addr(&svm, errp); +- +- return sock; ++ return vsock_connect_addr(&svm, errp); + } + + static int vsock_listen_saddr(VsockSocketAddress *vaddr, +-- +2.23.0 + diff --git a/Drop-more-errp-parameters-after-previous-commit.patch b/Drop-more-errp-parameters-after-previous-commit.patch new file mode 100644 index 0000000000000000000000000000000000000000..543ac0dd20cdae10c18d12b7cf9a27f2837a4db9 --- /dev/null +++ b/Drop-more-errp-parameters-after-previous-commit.patch @@ -0,0 +1,582 @@ +From 40c2281cc3342573bd72895997b5cfaddee36ef2 Mon Sep 17 00:00:00 2001 +From: Markus Armbruster +Date: Tue, 5 May 2020 17:29:23 +0200 +Subject: [PATCH 477/709] Drop more @errp parameters after previous commit + +Several functions can't fail anymore: ich9_pm_add_properties(), +device_add_bootindex_property(), ppc_compat_add_property(), +spapr_caps_add_properties(), PropertyInfo.create(). Drop their @errp +parameter. + +Signed-off-by: Markus Armbruster +Reviewed-by: Eric Blake +Reviewed-by: Paolo Bonzini +Message-Id: <20200505152926.18877-16-armbru@redhat.com> +--- + bootdevice.c | 2 +- + hw/acpi/ich9.c | 2 +- + hw/block/fdc.c | 4 ++-- + hw/block/nvme.c | 2 +- + hw/block/vhost-user-blk.c | 2 +- + hw/block/virtio-blk.c | 2 +- + hw/core/qdev-properties.c | 2 +- + hw/core/qdev.c | 2 +- + hw/isa/lpc_ich9.c | 2 +- + hw/net/e1000.c | 2 +- + hw/net/e1000e.c | 2 +- + hw/net/eepro100.c | 2 +- + hw/net/lance.c | 2 +- + hw/net/lasi_i82596.c | 2 +- + hw/net/ne2000-pci.c | 2 +- + hw/net/pcnet-pci.c | 2 +- + hw/net/rtl8139.c | 2 +- + hw/net/spapr_llan.c | 2 +- + hw/net/sungem.c | 2 +- + hw/net/sunhme.c | 2 +- + hw/net/tulip.c | 2 +- + hw/net/virtio-net.c | 2 +- + hw/net/vmxnet3.c | 2 +- + hw/ppc/spapr.c | 5 ++--- + hw/ppc/spapr_caps.c | 2 +- + hw/s390x/s390-ccw.c | 2 +- + hw/scsi/scsi-bus.c | 2 +- + hw/scsi/vhost-scsi.c | 2 +- + hw/scsi/vhost-user-scsi.c | 2 +- + hw/usb/dev-network.c | 2 +- + hw/usb/host-libusb.c | 2 +- + hw/usb/redirect.c | 2 +- + hw/vfio/pci.c | 2 +- + include/hw/acpi/ich9.h | 2 +- + include/hw/ppc/spapr.h | 2 +- + include/hw/qdev-core.h | 2 +- + include/sysemu/sysemu.h | 2 +- + target/ppc/compat.c | 3 +-- + target/ppc/cpu.h | 3 +-- + 39 files changed, 41 insertions(+), 44 deletions(-) + +diff --git a/bootdevice.c b/bootdevice.c +index d11576d575..0ff55e2b79 100644 +--- a/bootdevice.c ++++ b/bootdevice.c +@@ -327,7 +327,7 @@ static void property_release_bootindex(Object *obj, const char *name, + + void device_add_bootindex_property(Object *obj, int32_t *bootindex, + const char *name, const char *suffix, +- DeviceState *dev, Error **errp) ++ DeviceState *dev) + { + BootIndexProperty *prop = g_malloc0(sizeof(*prop)); + +diff --git a/hw/acpi/ich9.c b/hw/acpi/ich9.c +index 9e4c03bef8..2d204babc6 100644 +--- a/hw/acpi/ich9.c ++++ b/hw/acpi/ich9.c +@@ -369,7 +369,7 @@ static void ich9_pm_set_enable_tco(Object *obj, bool value, Error **errp) + s->pm.enable_tco = value; + } + +-void ich9_pm_add_properties(Object *obj, ICH9LPCPMRegs *pm, Error **errp) ++void ich9_pm_add_properties(Object *obj, ICH9LPCPMRegs *pm) + { + static const uint32_t gpe0_len = ICH9_PMIO_GPE0_LEN; + pm->acpi_memory_hotplug.is_enabled = true; +diff --git a/hw/block/fdc.c b/hw/block/fdc.c +index 9628cc171e..c5fb9d6ece 100644 +--- a/hw/block/fdc.c ++++ b/hw/block/fdc.c +@@ -2813,10 +2813,10 @@ static void isabus_fdc_instance_init(Object *obj) + + device_add_bootindex_property(obj, &isa->bootindexA, + "bootindexA", "/floppy@0", +- DEVICE(obj), NULL); ++ DEVICE(obj)); + device_add_bootindex_property(obj, &isa->bootindexB, + "bootindexB", "/floppy@1", +- DEVICE(obj), NULL); ++ DEVICE(obj)); + } + + static const TypeInfo isa_fdc_info = { +diff --git a/hw/block/nvme.c b/hw/block/nvme.c +index 9b453423cf..2f3100e56c 100644 +--- a/hw/block/nvme.c ++++ b/hw/block/nvme.c +@@ -1594,7 +1594,7 @@ static void nvme_instance_init(Object *obj) + + device_add_bootindex_property(obj, &s->conf.bootindex, + "bootindex", "/namespace@1,0", +- DEVICE(obj), &error_abort); ++ DEVICE(obj)); + } + + static const TypeInfo nvme_info = { +diff --git a/hw/block/vhost-user-blk.c b/hw/block/vhost-user-blk.c +index 6c485d1c9e..5263e0c9ad 100644 +--- a/hw/block/vhost-user-blk.c ++++ b/hw/block/vhost-user-blk.c +@@ -481,7 +481,7 @@ static void vhost_user_blk_instance_init(Object *obj) + VHostUserBlk *s = VHOST_USER_BLK(obj); + + device_add_bootindex_property(obj, &s->bootindex, "bootindex", +- "/disk@0,0", DEVICE(obj), NULL); ++ "/disk@0,0", DEVICE(obj)); + } + + static const VMStateDescription vmstate_vhost_user_blk = { +diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c +index 97ba8a2187..fb32717a12 100644 +--- a/hw/block/virtio-blk.c ++++ b/hw/block/virtio-blk.c +@@ -1248,7 +1248,7 @@ static void virtio_blk_instance_init(Object *obj) + + device_add_bootindex_property(obj, &s->conf.conf.bootindex, + "bootindex", "/disk@0,0", +- DEVICE(obj), NULL); ++ DEVICE(obj)); + } + + static const VMStateDescription vmstate_virtio_blk = { +diff --git a/hw/core/qdev-properties.c b/hw/core/qdev-properties.c +index 2f294ec4a4..cc924815da 100644 +--- a/hw/core/qdev-properties.c ++++ b/hw/core/qdev-properties.c +@@ -1250,7 +1250,7 @@ const PropertyInfo qdev_prop_size = { + + /* --- object link property --- */ + +-static void create_link_property(ObjectClass *oc, Property *prop, Error **errp) ++static void create_link_property(ObjectClass *oc, Property *prop) + { + object_class_property_add_link(oc, prop->name, prop->link_type, + prop->offset, +diff --git a/hw/core/qdev.c b/hw/core/qdev.c +index 3f91bff712..2afa2562b8 100644 +--- a/hw/core/qdev.c ++++ b/hw/core/qdev.c +@@ -782,7 +782,7 @@ static void qdev_class_add_property(DeviceClass *klass, Property *prop) + ObjectClass *oc = OBJECT_CLASS(klass); + + if (prop->info->create) { +- prop->info->create(oc, prop, &error_abort); ++ prop->info->create(oc, prop); + } else { + ObjectProperty *op; + +diff --git a/hw/isa/lpc_ich9.c b/hw/isa/lpc_ich9.c +index c975d46675..cd6e169d47 100644 +--- a/hw/isa/lpc_ich9.c ++++ b/hw/isa/lpc_ich9.c +@@ -639,7 +639,7 @@ static void ich9_lpc_initfn(Object *obj) + object_property_add_uint8_ptr(OBJECT(lpc), ACPI_PM_PROP_ACPI_DISABLE_CMD, + &acpi_disable_cmd, OBJ_PROP_FLAG_READ); + +- ich9_pm_add_properties(obj, &lpc->pm, NULL); ++ ich9_pm_add_properties(obj, &lpc->pm); + } + + static void ich9_lpc_realize(PCIDevice *d, Error **errp) +diff --git a/hw/net/e1000.c b/hw/net/e1000.c +index 0d2c2759e3..a18f80e369 100644 +--- a/hw/net/e1000.c ++++ b/hw/net/e1000.c +@@ -1774,7 +1774,7 @@ static void e1000_instance_init(Object *obj) + E1000State *n = E1000(obj); + device_add_bootindex_property(obj, &n->conf.bootindex, + "bootindex", "/ethernet-phy@0", +- DEVICE(n), NULL); ++ DEVICE(n)); + } + + static const TypeInfo e1000_base_info = { +diff --git a/hw/net/e1000e.c b/hw/net/e1000e.c +index 79ba158d41..fda34518c9 100644 +--- a/hw/net/e1000e.c ++++ b/hw/net/e1000e.c +@@ -705,7 +705,7 @@ static void e1000e_instance_init(Object *obj) + E1000EState *s = E1000E(obj); + device_add_bootindex_property(obj, &s->conf.bootindex, + "bootindex", "/ethernet-phy@0", +- DEVICE(obj), NULL); ++ DEVICE(obj)); + } + + static const TypeInfo e1000e_info = { +diff --git a/hw/net/eepro100.c b/hw/net/eepro100.c +index f6474f0e68..16e95ef9cc 100644 +--- a/hw/net/eepro100.c ++++ b/hw/net/eepro100.c +@@ -1883,7 +1883,7 @@ static void eepro100_instance_init(Object *obj) + EEPRO100State *s = DO_UPCAST(EEPRO100State, dev, PCI_DEVICE(obj)); + device_add_bootindex_property(obj, &s->conf.bootindex, + "bootindex", "/ethernet-phy@0", +- DEVICE(s), NULL); ++ DEVICE(s)); + } + + static E100PCIDeviceInfo e100_devices[] = { +diff --git a/hw/net/lance.c b/hw/net/lance.c +index 688724db0b..4c5f01baad 100644 +--- a/hw/net/lance.c ++++ b/hw/net/lance.c +@@ -134,7 +134,7 @@ static void lance_instance_init(Object *obj) + + device_add_bootindex_property(obj, &s->conf.bootindex, + "bootindex", "/ethernet-phy@0", +- DEVICE(obj), NULL); ++ DEVICE(obj)); + } + + static Property lance_properties[] = { +diff --git a/hw/net/lasi_i82596.c b/hw/net/lasi_i82596.c +index 52637a562d..5e0fd69763 100644 +--- a/hw/net/lasi_i82596.c ++++ b/hw/net/lasi_i82596.c +@@ -152,7 +152,7 @@ static void lasi_82596_instance_init(Object *obj) + + device_add_bootindex_property(obj, &s->conf.bootindex, + "bootindex", "/ethernet-phy@0", +- DEVICE(obj), NULL); ++ DEVICE(obj)); + } + + static Property lasi_82596_properties[] = { +diff --git a/hw/net/ne2000-pci.c b/hw/net/ne2000-pci.c +index e11d67bf75..9e5d10859a 100644 +--- a/hw/net/ne2000-pci.c ++++ b/hw/net/ne2000-pci.c +@@ -92,7 +92,7 @@ static void ne2000_instance_init(Object *obj) + + device_add_bootindex_property(obj, &s->c.bootindex, + "bootindex", "/ethernet-phy@0", +- &pci_dev->qdev, NULL); ++ &pci_dev->qdev); + } + + static Property ne2000_properties[] = { +diff --git a/hw/net/pcnet-pci.c b/hw/net/pcnet-pci.c +index d1f31e0272..49d3e42e83 100644 +--- a/hw/net/pcnet-pci.c ++++ b/hw/net/pcnet-pci.c +@@ -250,7 +250,7 @@ static void pcnet_instance_init(Object *obj) + + device_add_bootindex_property(obj, &s->conf.bootindex, + "bootindex", "/ethernet-phy@0", +- DEVICE(obj), NULL); ++ DEVICE(obj)); + } + + static Property pcnet_properties[] = { +diff --git a/hw/net/rtl8139.c b/hw/net/rtl8139.c +index 70aca7ec26..ab93d78ab3 100644 +--- a/hw/net/rtl8139.c ++++ b/hw/net/rtl8139.c +@@ -3415,7 +3415,7 @@ static void rtl8139_instance_init(Object *obj) + + device_add_bootindex_property(obj, &s->conf.bootindex, + "bootindex", "/ethernet-phy@0", +- DEVICE(obj), NULL); ++ DEVICE(obj)); + } + + static Property rtl8139_properties[] = { +diff --git a/hw/net/spapr_llan.c b/hw/net/spapr_llan.c +index a2377025a7..968a1ce78e 100644 +--- a/hw/net/spapr_llan.c ++++ b/hw/net/spapr_llan.c +@@ -340,7 +340,7 @@ static void spapr_vlan_instance_init(Object *obj) + + device_add_bootindex_property(obj, &dev->nicconf.bootindex, + "bootindex", "", +- DEVICE(dev), NULL); ++ DEVICE(dev)); + + if (dev->compat_flags & SPAPRVLAN_FLAG_RX_BUF_POOLS) { + for (i = 0; i < RX_MAX_POOLS; i++) { +diff --git a/hw/net/sungem.c b/hw/net/sungem.c +index b01197d952..e4b7b57704 100644 +--- a/hw/net/sungem.c ++++ b/hw/net/sungem.c +@@ -1378,7 +1378,7 @@ static void sungem_instance_init(Object *obj) + + device_add_bootindex_property(obj, &s->conf.bootindex, + "bootindex", "/ethernet-phy@0", +- DEVICE(obj), NULL); ++ DEVICE(obj)); + } + + static Property sungem_properties[] = { +diff --git a/hw/net/sunhme.c b/hw/net/sunhme.c +index 9c38583180..bc48d46b9f 100644 +--- a/hw/net/sunhme.c ++++ b/hw/net/sunhme.c +@@ -901,7 +901,7 @@ static void sunhme_instance_init(Object *obj) + + device_add_bootindex_property(obj, &s->conf.bootindex, + "bootindex", "/ethernet-phy@0", +- DEVICE(obj), NULL); ++ DEVICE(obj)); + } + + static void sunhme_reset(DeviceState *ds) +diff --git a/hw/net/tulip.c b/hw/net/tulip.c +index 1295f51d07..6cefc0add2 100644 +--- a/hw/net/tulip.c ++++ b/hw/net/tulip.c +@@ -1001,7 +1001,7 @@ static void tulip_instance_init(Object *obj) + + device_add_bootindex_property(obj, &d->c.bootindex, + "bootindex", "/ethernet-phy@0", +- &pci_dev->qdev, NULL); ++ &pci_dev->qdev); + } + + static Property tulip_properties[] = { +diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c +index e51231e795..b43fd7d608 100644 +--- a/hw/net/virtio-net.c ++++ b/hw/net/virtio-net.c +@@ -3125,7 +3125,7 @@ static void virtio_net_instance_init(Object *obj) + n->config_size = sizeof(struct virtio_net_config); + device_add_bootindex_property(obj, &n->nic_conf.bootindex, + "bootindex", "/ethernet-phy@0", +- DEVICE(n), NULL); ++ DEVICE(n)); + } + + static int virtio_net_pre_save(void *opaque) +diff --git a/hw/net/vmxnet3.c b/hw/net/vmxnet3.c +index 6d91cd8309..7a6ca4ec35 100644 +--- a/hw/net/vmxnet3.c ++++ b/hw/net/vmxnet3.c +@@ -2237,7 +2237,7 @@ static void vmxnet3_instance_init(Object *obj) + VMXNET3State *s = VMXNET3(obj); + device_add_bootindex_property(obj, &s->conf.bootindex, + "bootindex", "/ethernet-phy@0", +- DEVICE(obj), NULL); ++ DEVICE(obj)); + } + + static void vmxnet3_pci_uninit(PCIDevice *pci_dev) +diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c +index 976d40f60f..b73f4d94d3 100644 +--- a/hw/ppc/spapr.c ++++ b/hw/ppc/spapr.c +@@ -3316,8 +3316,7 @@ static void spapr_instance_init(Object *obj) + " place of standard EPOW events when possible" + " (required for memory hot-unplug support)"); + ppc_compat_add_property(obj, "max-cpu-compat", &spapr->max_compat_pvr, +- "Maximum permitted CPU compatibility mode", +- &error_fatal); ++ "Maximum permitted CPU compatibility mode"); + + object_property_add_str(obj, "resize-hpt", + spapr_get_resize_hpt, spapr_set_resize_hpt); +@@ -4525,7 +4524,7 @@ static void spapr_machine_class_init(ObjectClass *oc, void *data) + smc->default_caps.caps[SPAPR_CAP_LARGE_DECREMENTER] = SPAPR_CAP_ON; + smc->default_caps.caps[SPAPR_CAP_CCF_ASSIST] = SPAPR_CAP_ON; + smc->default_caps.caps[SPAPR_CAP_FWNMI] = SPAPR_CAP_ON; +- spapr_caps_add_properties(smc, &error_abort); ++ spapr_caps_add_properties(smc); + smc->irq = &spapr_irq_dual; + smc->dr_phb_enabled = true; + smc->linux_pci_probe = true; +diff --git a/hw/ppc/spapr_caps.c b/hw/ppc/spapr_caps.c +index 184563e608..efdc0dbbcf 100644 +--- a/hw/ppc/spapr_caps.c ++++ b/hw/ppc/spapr_caps.c +@@ -824,7 +824,7 @@ void spapr_caps_cpu_apply(SpaprMachineState *spapr, PowerPCCPU *cpu) + } + } + +-void spapr_caps_add_properties(SpaprMachineClass *smc, Error **errp) ++void spapr_caps_add_properties(SpaprMachineClass *smc) + { + ObjectClass *klass = OBJECT_CLASS(smc); + int i; +diff --git a/hw/s390x/s390-ccw.c b/hw/s390x/s390-ccw.c +index 0c5a5b60bd..569020dae4 100644 +--- a/hw/s390x/s390-ccw.c ++++ b/hw/s390x/s390-ccw.c +@@ -151,7 +151,7 @@ static void s390_ccw_instance_init(Object *obj) + S390CCWDevice *dev = S390_CCW_DEVICE(obj); + + device_add_bootindex_property(obj, &dev->bootindex, "bootindex", +- "/disk@0,0", DEVICE(obj), NULL); ++ "/disk@0,0", DEVICE(obj)); + } + + static void s390_ccw_class_init(ObjectClass *klass, void *data) +diff --git a/hw/scsi/scsi-bus.c b/hw/scsi/scsi-bus.c +index ab5459a589..1733307407 100644 +--- a/hw/scsi/scsi-bus.c ++++ b/hw/scsi/scsi-bus.c +@@ -1738,7 +1738,7 @@ static void scsi_dev_instance_init(Object *obj) + + device_add_bootindex_property(obj, &s->conf.bootindex, + "bootindex", NULL, +- &s->qdev, NULL); ++ &s->qdev); + } + + static const TypeInfo scsi_device_type_info = { +diff --git a/hw/scsi/vhost-scsi.c b/hw/scsi/vhost-scsi.c +index f052377b7e..ffa667171d 100644 +--- a/hw/scsi/vhost-scsi.c ++++ b/hw/scsi/vhost-scsi.c +@@ -311,7 +311,7 @@ static void vhost_scsi_instance_init(Object *obj) + vsc->feature_bits = kernel_feature_bits; + + device_add_bootindex_property(obj, &vsc->bootindex, "bootindex", NULL, +- DEVICE(vsc), NULL); ++ DEVICE(vsc)); + } + + static const TypeInfo vhost_scsi_info = { +diff --git a/hw/scsi/vhost-user-scsi.c b/hw/scsi/vhost-user-scsi.c +index a01bf63a08..ae380b63b4 100644 +--- a/hw/scsi/vhost-user-scsi.c ++++ b/hw/scsi/vhost-user-scsi.c +@@ -217,7 +217,7 @@ static void vhost_user_scsi_instance_init(Object *obj) + + /* Add the bootindex property for this object */ + device_add_bootindex_property(obj, &vsc->bootindex, "bootindex", NULL, +- DEVICE(vsc), NULL); ++ DEVICE(vsc)); + } + + static const TypeInfo vhost_user_scsi_info = { +diff --git a/hw/usb/dev-network.c b/hw/usb/dev-network.c +index 6210427544..720744488b 100644 +--- a/hw/usb/dev-network.c ++++ b/hw/usb/dev-network.c +@@ -1381,7 +1381,7 @@ static void usb_net_instance_init(Object *obj) + + device_add_bootindex_property(obj, &s->conf.bootindex, + "bootindex", "/ethernet-phy@0", +- &dev->qdev, NULL); ++ &dev->qdev); + } + + static const VMStateDescription vmstate_usb_net = { +diff --git a/hw/usb/host-libusb.c b/hw/usb/host-libusb.c +index 2ac7a936fb..78a5c2ba55 100644 +--- a/hw/usb/host-libusb.c ++++ b/hw/usb/host-libusb.c +@@ -1101,7 +1101,7 @@ static void usb_host_instance_init(Object *obj) + + device_add_bootindex_property(obj, &s->bootindex, + "bootindex", NULL, +- &udev->qdev, NULL); ++ &udev->qdev); + } + + static void usb_host_unrealize(USBDevice *udev, Error **errp) +diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c +index 45d8b76218..e9a97feaed 100644 +--- a/hw/usb/redirect.c ++++ b/hw/usb/redirect.c +@@ -2595,7 +2595,7 @@ static void usbredir_instance_init(Object *obj) + + device_add_bootindex_property(obj, &dev->bootindex, + "bootindex", NULL, +- &udev->qdev, NULL); ++ &udev->qdev); + } + + static const TypeInfo usbredir_dev_info = { +diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c +index 5e75a95129..342dd6b912 100644 +--- a/hw/vfio/pci.c ++++ b/hw/vfio/pci.c +@@ -3133,7 +3133,7 @@ static void vfio_instance_init(Object *obj) + + device_add_bootindex_property(obj, &vdev->bootindex, + "bootindex", NULL, +- &pci_dev->qdev, NULL); ++ &pci_dev->qdev); + vdev->host.domain = ~0U; + vdev->host.bus = ~0U; + vdev->host.slot = ~0U; +diff --git a/include/hw/acpi/ich9.h b/include/hw/acpi/ich9.h +index 41568d1837..28a53181cb 100644 +--- a/include/hw/acpi/ich9.h ++++ b/include/hw/acpi/ich9.h +@@ -72,7 +72,7 @@ void ich9_pm_init(PCIDevice *lpc_pci, ICH9LPCPMRegs *pm, + void ich9_pm_iospace_update(ICH9LPCPMRegs *pm, uint32_t pm_io_base); + extern const VMStateDescription vmstate_ich9_pm; + +-void ich9_pm_add_properties(Object *obj, ICH9LPCPMRegs *pm, Error **errp); ++void ich9_pm_add_properties(Object *obj, ICH9LPCPMRegs *pm); + + void ich9_pm_device_pre_plug_cb(HotplugHandler *hotplug_dev, DeviceState *dev, + Error **errp); +diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h +index e579eaf28c..d2533e7264 100644 +--- a/include/hw/ppc/spapr.h ++++ b/include/hw/ppc/spapr.h +@@ -921,7 +921,7 @@ static inline uint8_t spapr_get_cap(SpaprMachineState *spapr, int cap) + void spapr_caps_init(SpaprMachineState *spapr); + void spapr_caps_apply(SpaprMachineState *spapr); + void spapr_caps_cpu_apply(SpaprMachineState *spapr, PowerPCCPU *cpu); +-void spapr_caps_add_properties(SpaprMachineClass *smc, Error **errp); ++void spapr_caps_add_properties(SpaprMachineClass *smc); + int spapr_caps_post_migration(SpaprMachineState *spapr); + + void spapr_check_pagesize(SpaprMachineState *spapr, hwaddr pagesize, +diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h +index d87d989e72..6f537f687f 100644 +--- a/include/hw/qdev-core.h ++++ b/include/hw/qdev-core.h +@@ -286,7 +286,7 @@ struct PropertyInfo { + const QEnumLookup *enum_table; + int (*print)(DeviceState *dev, Property *prop, char *dest, size_t len); + void (*set_default_value)(ObjectProperty *op, const Property *prop); +- void (*create)(ObjectClass *oc, Property *prop, Error **errp); ++ void (*create)(ObjectClass *oc, Property *prop); + ObjectPropertyAccessor *get; + ObjectPropertyAccessor *set; + ObjectPropertyRelease *release; +diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h +index ef81302e1a..26c0c802d1 100644 +--- a/include/sysemu/sysemu.h ++++ b/include/sysemu/sysemu.h +@@ -92,7 +92,7 @@ void check_boot_index(int32_t bootindex, Error **errp); + void del_boot_device_path(DeviceState *dev, const char *suffix); + void device_add_bootindex_property(Object *obj, int32_t *bootindex, + const char *name, const char *suffix, +- DeviceState *dev, Error **errp); ++ DeviceState *dev); + void restore_boot_order(void *opaque); + void validate_bootdevices(const char *devices, Error **errp); + void add_boot_device_lchs(DeviceState *dev, const char *suffix, +diff --git a/target/ppc/compat.c b/target/ppc/compat.c +index 7f144392f8..fda0dfe8f8 100644 +--- a/target/ppc/compat.c ++++ b/target/ppc/compat.c +@@ -298,8 +298,7 @@ out: + } + + void ppc_compat_add_property(Object *obj, const char *name, +- uint32_t *compat_pvr, const char *basedesc, +- Error **errp) ++ uint32_t *compat_pvr, const char *basedesc) + { + gchar *namesv[ARRAY_SIZE(compat_table) + 1]; + gchar *names, *desc; +diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h +index 6b6dd7e483..7db7882f52 100644 +--- a/target/ppc/cpu.h ++++ b/target/ppc/cpu.h +@@ -1338,8 +1338,7 @@ void ppc_set_compat_all(uint32_t compat_pvr, Error **errp); + #endif + int ppc_compat_max_vthreads(PowerPCCPU *cpu); + void ppc_compat_add_property(Object *obj, const char *name, +- uint32_t *compat_pvr, const char *basedesc, +- Error **errp); ++ uint32_t *compat_pvr, const char *basedesc); + #endif /* defined(TARGET_PPC64) */ + + typedef CPUPPCState CPUArchState; +-- +2.23.0 + diff --git a/Fix-iotest-153.patch b/Fix-iotest-153.patch new file mode 100644 index 0000000000000000000000000000000000000000..9d52ab2c2fd6be38e4c2671017b55ce9f7e9a045 --- /dev/null +++ b/Fix-iotest-153.patch @@ -0,0 +1,93 @@ +From 44e808c13045b1032143ab8e144b4d48264ad609 Mon Sep 17 00:00:00 2001 +From: Maxim Levitsky +Date: Mon, 4 May 2020 16:19:59 +0300 +Subject: [PATCH 259/709] Fix iotest 153 + +Commit f62514b3def5fb2acbef64d0e053c0c31fa45aff made qemu-img reject -o "" but this test uses it. +Since this test only tries to do a dry-run run of qemu-img amend, +replace the -o "" with dummy -o "size=$size". + +Fixes: f62514b3def5fb2acbef64d0e053c0c31fa45aff + +Signed-off-by: Maxim Levitsky +Message-Id: <20200504131959.9533-1-mlevitsk@redhat.com> +Signed-off-by: Max Reitz +--- + tests/qemu-iotests/153 | 2 +- + tests/qemu-iotests/153.out | 12 ++++++------ + 2 files changed, 7 insertions(+), 7 deletions(-) + +diff --git a/tests/qemu-iotests/153 b/tests/qemu-iotests/153 +index 2b13111768..cf961d3609 100755 +--- a/tests/qemu-iotests/153 ++++ b/tests/qemu-iotests/153 +@@ -122,7 +122,7 @@ for opts1 in "" "read-only=on" "read-only=on,force-share=on"; do + _run_cmd $QEMU_IMG check $L "${TEST_IMG}" + _run_cmd $QEMU_IMG compare $L "${TEST_IMG}" "${TEST_IMG}" + _run_cmd $QEMU_IMG map $L "${TEST_IMG}" +- _run_cmd $QEMU_IMG amend -o "" $L "${TEST_IMG}" ++ _run_cmd $QEMU_IMG amend -o "size=$size" $L "${TEST_IMG}" + _run_cmd $QEMU_IMG commit $L "${TEST_IMG}" + _run_cmd $QEMU_IMG resize $L "${TEST_IMG}" $size + _run_cmd $QEMU_IMG rebase $L "${TEST_IMG}" -b "${TEST_IMG}.base" +diff --git a/tests/qemu-iotests/153.out b/tests/qemu-iotests/153.out +index f7464dd8d3..b2a90caa6b 100644 +--- a/tests/qemu-iotests/153.out ++++ b/tests/qemu-iotests/153.out +@@ -56,7 +56,7 @@ _qemu_img_wrapper map TEST_DIR/t.qcow2 + qemu-img: Could not open 'TEST_DIR/t.qcow2': Failed to get shared "write" lock + Is another process using the image [TEST_DIR/t.qcow2]? + +-_qemu_img_wrapper amend -o TEST_DIR/t.qcow2 ++_qemu_img_wrapper amend -o size=32M TEST_DIR/t.qcow2 + qemu-img: Could not open 'TEST_DIR/t.qcow2': Failed to get "write" lock + Is another process using the image [TEST_DIR/t.qcow2]? + +@@ -118,7 +118,7 @@ _qemu_img_wrapper compare -U TEST_DIR/t.qcow2 TEST_DIR/t.qcow2 + + _qemu_img_wrapper map -U TEST_DIR/t.qcow2 + +-_qemu_img_wrapper amend -o -U TEST_DIR/t.qcow2 ++_qemu_img_wrapper amend -o size=32M -U TEST_DIR/t.qcow2 + qemu-img: unrecognized option '-U' + Try 'qemu-img --help' for more information + +@@ -187,7 +187,7 @@ _qemu_img_wrapper compare TEST_DIR/t.qcow2 TEST_DIR/t.qcow2 + + _qemu_img_wrapper map TEST_DIR/t.qcow2 + +-_qemu_img_wrapper amend -o TEST_DIR/t.qcow2 ++_qemu_img_wrapper amend -o size=32M TEST_DIR/t.qcow2 + qemu-img: Could not open 'TEST_DIR/t.qcow2': Failed to get "write" lock + Is another process using the image [TEST_DIR/t.qcow2]? + +@@ -241,7 +241,7 @@ _qemu_img_wrapper compare -U TEST_DIR/t.qcow2 TEST_DIR/t.qcow2 + + _qemu_img_wrapper map -U TEST_DIR/t.qcow2 + +-_qemu_img_wrapper amend -o -U TEST_DIR/t.qcow2 ++_qemu_img_wrapper amend -o size=32M -U TEST_DIR/t.qcow2 + qemu-img: unrecognized option '-U' + Try 'qemu-img --help' for more information + +@@ -303,7 +303,7 @@ _qemu_img_wrapper compare TEST_DIR/t.qcow2 TEST_DIR/t.qcow2 + + _qemu_img_wrapper map TEST_DIR/t.qcow2 + +-_qemu_img_wrapper amend -o TEST_DIR/t.qcow2 ++_qemu_img_wrapper amend -o size=32M TEST_DIR/t.qcow2 + + _qemu_img_wrapper commit TEST_DIR/t.qcow2 + +@@ -345,7 +345,7 @@ _qemu_img_wrapper compare -U TEST_DIR/t.qcow2 TEST_DIR/t.qcow2 + + _qemu_img_wrapper map -U TEST_DIR/t.qcow2 + +-_qemu_img_wrapper amend -o -U TEST_DIR/t.qcow2 ++_qemu_img_wrapper amend -o size=32M -U TEST_DIR/t.qcow2 + qemu-img: unrecognized option '-U' + Try 'qemu-img --help' for more information + +-- +2.23.0 + diff --git a/KVM-Move-hwpoison-page-related-functions-into-kvm-al.patch b/KVM-Move-hwpoison-page-related-functions-into-kvm-al.patch new file mode 100644 index 0000000000000000000000000000000000000000..eec4731d4f61715f64128b078dc10c3279452ff4 --- /dev/null +++ b/KVM-Move-hwpoison-page-related-functions-into-kvm-al.patch @@ -0,0 +1,172 @@ +From 6b552b9bc8421c48e91c9a40ce5dccf78020c339 Mon Sep 17 00:00:00 2001 +From: Dongjiu Geng +Date: Tue, 12 May 2020 11:06:06 +0800 +Subject: [PATCH 442/709] KVM: Move hwpoison page related functions into + kvm-all.c + +kvm_hwpoison_page_add() and kvm_unpoison_all() will both +be used by X86 and ARM platforms, so moving them into +"accel/kvm/kvm-all.c" to avoid duplicate code. + +For architectures that don't use the poison-list functionality +the reset handler will harmlessly do nothing, so let's register +the kvm_unpoison_all() function in the generic kvm_init() function. + +Reviewed-by: Peter Maydell +Signed-off-by: Dongjiu Geng +Signed-off-by: Xiang Zheng +Acked-by: Xiang Zheng +Message-id: 20200512030609.19593-8-gengdongjiu@huawei.com +Signed-off-by: Peter Maydell +--- + accel/kvm/kvm-all.c | 36 ++++++++++++++++++++++++++++++++++++ + include/sysemu/kvm_int.h | 12 ++++++++++++ + target/i386/kvm.c | 36 ------------------------------------ + 3 files changed, 48 insertions(+), 36 deletions(-) + +diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c +index 439a4efe52..36be11795d 100644 +--- a/accel/kvm/kvm-all.c ++++ b/accel/kvm/kvm-all.c +@@ -44,6 +44,7 @@ + #include "qapi/visitor.h" + #include "qapi/qapi-types-common.h" + #include "qapi/qapi-visit-common.h" ++#include "sysemu/reset.h" + + #include "hw/boards.h" + +@@ -883,6 +884,39 @@ int kvm_vm_check_extension(KVMState *s, unsigned int extension) + return ret; + } + ++typedef struct HWPoisonPage { ++ ram_addr_t ram_addr; ++ QLIST_ENTRY(HWPoisonPage) list; ++} HWPoisonPage; ++ ++static QLIST_HEAD(, HWPoisonPage) hwpoison_page_list = ++ QLIST_HEAD_INITIALIZER(hwpoison_page_list); ++ ++static void kvm_unpoison_all(void *param) ++{ ++ HWPoisonPage *page, *next_page; ++ ++ QLIST_FOREACH_SAFE(page, &hwpoison_page_list, list, next_page) { ++ QLIST_REMOVE(page, list); ++ qemu_ram_remap(page->ram_addr, TARGET_PAGE_SIZE); ++ g_free(page); ++ } ++} ++ ++void kvm_hwpoison_page_add(ram_addr_t ram_addr) ++{ ++ HWPoisonPage *page; ++ ++ QLIST_FOREACH(page, &hwpoison_page_list, list) { ++ if (page->ram_addr == ram_addr) { ++ return; ++ } ++ } ++ page = g_new(HWPoisonPage, 1); ++ page->ram_addr = ram_addr; ++ QLIST_INSERT_HEAD(&hwpoison_page_list, page, list); ++} ++ + static uint32_t adjust_ioeventfd_endianness(uint32_t val, uint32_t size) + { + #if defined(HOST_WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN) +@@ -2085,6 +2119,8 @@ static int kvm_init(MachineState *ms) + s->kernel_irqchip_split = mc->default_kernel_irqchip_split ? ON_OFF_AUTO_ON : ON_OFF_AUTO_OFF; + } + ++ qemu_register_reset(kvm_unpoison_all, NULL); ++ + if (s->kernel_irqchip_allowed) { + kvm_irqchip_create(s); + } +diff --git a/include/sysemu/kvm_int.h b/include/sysemu/kvm_int.h +index ac2d1f8b56..c660a70c51 100644 +--- a/include/sysemu/kvm_int.h ++++ b/include/sysemu/kvm_int.h +@@ -42,4 +42,16 @@ void kvm_memory_listener_register(KVMState *s, KVMMemoryListener *kml, + AddressSpace *as, int as_id); + + void kvm_set_max_memslot_size(hwaddr max_slot_size); ++ ++/** ++ * kvm_hwpoison_page_add: ++ * ++ * Parameters: ++ * @ram_addr: the address in the RAM for the poisoned page ++ * ++ * Add a poisoned page to the list ++ * ++ * Return: None. ++ */ ++void kvm_hwpoison_page_add(ram_addr_t ram_addr); + #endif +diff --git a/target/i386/kvm.c b/target/i386/kvm.c +index 4901c6dd74..34f838728d 100644 +--- a/target/i386/kvm.c ++++ b/target/i386/kvm.c +@@ -24,7 +24,6 @@ + #include "sysemu/sysemu.h" + #include "sysemu/hw_accel.h" + #include "sysemu/kvm_int.h" +-#include "sysemu/reset.h" + #include "sysemu/runstate.h" + #include "kvm_i386.h" + #include "hyperv.h" +@@ -533,40 +532,6 @@ uint64_t kvm_arch_get_supported_msr_feature(KVMState *s, uint32_t index) + } + } + +- +-typedef struct HWPoisonPage { +- ram_addr_t ram_addr; +- QLIST_ENTRY(HWPoisonPage) list; +-} HWPoisonPage; +- +-static QLIST_HEAD(, HWPoisonPage) hwpoison_page_list = +- QLIST_HEAD_INITIALIZER(hwpoison_page_list); +- +-static void kvm_unpoison_all(void *param) +-{ +- HWPoisonPage *page, *next_page; +- +- QLIST_FOREACH_SAFE(page, &hwpoison_page_list, list, next_page) { +- QLIST_REMOVE(page, list); +- qemu_ram_remap(page->ram_addr, TARGET_PAGE_SIZE); +- g_free(page); +- } +-} +- +-static void kvm_hwpoison_page_add(ram_addr_t ram_addr) +-{ +- HWPoisonPage *page; +- +- QLIST_FOREACH(page, &hwpoison_page_list, list) { +- if (page->ram_addr == ram_addr) { +- return; +- } +- } +- page = g_new(HWPoisonPage, 1); +- page->ram_addr = ram_addr; +- QLIST_INSERT_HEAD(&hwpoison_page_list, page, list); +-} +- + static int kvm_get_mce_cap_supported(KVMState *s, uint64_t *mce_cap, + int *max_banks) + { +@@ -2180,7 +2145,6 @@ int kvm_arch_init(MachineState *ms, KVMState *s) + fprintf(stderr, "e820_add_entry() table is full\n"); + return ret; + } +- qemu_register_reset(kvm_unpoison_all, NULL); + + shadow_mem = object_property_get_int(OBJECT(s), "kvm-shadow-mem", &error_abort); + if (shadow_mem != -1) { +-- +2.23.0 + diff --git a/MAINTAINERS-Add-ACPI-HEST-GHES-entries.patch b/MAINTAINERS-Add-ACPI-HEST-GHES-entries.patch new file mode 100644 index 0000000000000000000000000000000000000000..b446f866eb6d922355b9402f58369739af993a2b --- /dev/null +++ b/MAINTAINERS-Add-ACPI-HEST-GHES-entries.patch @@ -0,0 +1,44 @@ +From f7e462f82b06d39acefff7b8f153bf5e6b3d28e5 Mon Sep 17 00:00:00 2001 +From: Dongjiu Geng +Date: Tue, 12 May 2020 11:06:09 +0800 +Subject: [PATCH 445/709] MAINTAINERS: Add ACPI/HEST/GHES entries +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +I and Xiang are willing to review the APEI-related patches and +volunteer as the reviewers for the HEST/GHES part. + +Signed-off-by: Dongjiu Geng +Signed-off-by: Xiang Zheng +Reviewed-by: Philippe Mathieu-Daudé +Acked-by: Michael S. Tsirkin +Message-id: 20200512030609.19593-11-gengdongjiu@huawei.com +Signed-off-by: Peter Maydell +--- + MAINTAINERS | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/MAINTAINERS b/MAINTAINERS +index 005ee98a59..f972e12bfd 100644 +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -1516,6 +1516,15 @@ F: tests/qtest/bios-tables-test.c + F: tests/qtest/acpi-utils.[hc] + F: tests/data/acpi/ + ++ACPI/HEST/GHES ++R: Dongjiu Geng ++R: Xiang Zheng ++L: qemu-arm@nongnu.org ++S: Maintained ++F: hw/acpi/ghes.c ++F: include/hw/acpi/ghes.h ++F: docs/specs/acpi_hest_ghes.rst ++ + ppc4xx + M: David Gibson + L: qemu-ppc@nongnu.org +-- +2.23.0 + diff --git a/MAINTAINERS-Add-Huacai-Chen-as-fuloong2e-co-maintain.patch b/MAINTAINERS-Add-Huacai-Chen-as-fuloong2e-co-maintain.patch new file mode 100644 index 0000000000000000000000000000000000000000..18d7bc09e74f23e141a9fa10403e4d99b73293a2 --- /dev/null +++ b/MAINTAINERS-Add-Huacai-Chen-as-fuloong2e-co-maintain.patch @@ -0,0 +1,47 @@ +From 97eeef8aeeac1c5fb64f6785bbcef2e57f7c62ce Mon Sep 17 00:00:00 2001 +From: Huacai Chen +Date: Wed, 8 Apr 2020 17:16:20 +0800 +Subject: [PATCH 653/709] MAINTAINERS: Add Huacai Chen as fuloong2e + co-maintainer +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +I submitted the MIPS/fuloong2e support about ten years ago, and +after that I became a MIPS kernel developer. Last year, Philippe +Mathieu- Daudé asked me that whether I can be a reviewer of +MIPS/fuloong2e, and I promised that I will do some QEMU work in +the next year (i.e., 2020 and later). I think now (and also in +future) I can have some spare time, so I can finally do some real +work on QEMU/MIPS. And if possible, I hope I can be a co-maintainer +of MIPS/fuloong2e. + +Cc: Jiaxun Yang +Signed-off-by: Huacai Chen +Message-Id: <1586337380-25217-3-git-send-email-chenhc@lemote.com> +[PMD: Added Jiaxun Yang as reviewer] +Signed-off-by: Philippe Mathieu-Daudé +Reviewed-by: Aleksandar Markovic +Message-Id: <20200510210128.18343-2-f4bug@amsat.org> +--- + MAINTAINERS | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/MAINTAINERS b/MAINTAINERS +index 3690f313c3..8f597aae12 100644 +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -1082,8 +1082,10 @@ S: Obsolete + F: hw/mips/mips_r4k.c + + Fulong 2E ++M: Huacai Chen + M: Philippe Mathieu-Daudé + M: Aleksandar Markovic ++R: Jiaxun Yang + S: Odd Fixes + F: hw/mips/mips_fulong2e.c + F: hw/isa/vt82c686.c +-- +2.23.0 + diff --git a/MAINTAINERS-Add-myself-as-streams-maintainer.patch b/MAINTAINERS-Add-myself-as-streams-maintainer.patch new file mode 100644 index 0000000000000000000000000000000000000000..8ff71dd7ad7e274bd2d43ee0bdf248f0502c7c3d --- /dev/null +++ b/MAINTAINERS-Add-myself-as-streams-maintainer.patch @@ -0,0 +1,38 @@ +From 6d0af39f81cd22c7d26fd00e262d722e0003014f Mon Sep 17 00:00:00 2001 +From: "Edgar E. Iglesias" +Date: Wed, 6 May 2020 10:25:13 +0200 +Subject: [PATCH 410/709] MAINTAINERS: Add myself as streams maintainer +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Since we're missing a maintainer, add myself. + +Reviewed-by: Alistair Francis +Signed-off-by: Edgar E. Iglesias +Reviewed-by: Philippe Mathieu-Daudé +Message-Id: <20200506082513.18751-10-edgar.iglesias@gmail.com> +--- + MAINTAINERS | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/MAINTAINERS b/MAINTAINERS +index 005ee98a59..d11f3cb976 100644 +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -2315,6 +2315,12 @@ F: net/slirp.c + F: include/net/slirp.h + T: git https://people.debian.org/~sthibault/qemu.git slirp + ++Streams ++M: Edgar E. Iglesias ++S: Maintained ++F: hw/core/stream.c ++F: include/hw/stream.h ++ + Stubs + M: Paolo Bonzini + S: Maintained +-- +2.23.0 + diff --git a/MAINTAINERS-Change-Aleksandar-Rikalo-s-email-address.patch b/MAINTAINERS-Change-Aleksandar-Rikalo-s-email-address.patch new file mode 100644 index 0000000000000000000000000000000000000000..ec5894bb636e9f2f62b81708e4aab21521dc7e81 --- /dev/null +++ b/MAINTAINERS-Change-Aleksandar-Rikalo-s-email-address.patch @@ -0,0 +1,97 @@ +From 97d8974620053db5754af808583de70380f73a10 Mon Sep 17 00:00:00 2001 +From: Aleksandar Markovic +Date: Mon, 18 May 2020 22:09:16 +0200 +Subject: [PATCH 666/709] MAINTAINERS: Change Aleksandar Rikalo's email address +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Aleksandar Rikalo wants to use a different email address from +now on. + +Reviewed-by: Aleksandar Rikalo +Reviewed-by: Philippe Mathieu-Daudé +Tested-by: Philippe Mathieu-Daudé +Signed-off-by: Aleksandar Markovic +Message-id: <20200518200920.17344-18-aleksandar.qemu.devel@gmail.com> +Signed-off-by: Philippe Mathieu-Daudé +--- + .mailmap | 3 ++- + MAINTAINERS | 12 ++++++------ + 2 files changed, 8 insertions(+), 7 deletions(-) + +diff --git a/.mailmap b/.mailmap +index 6412067bde..e3628c7a66 100644 +--- a/.mailmap ++++ b/.mailmap +@@ -42,7 +42,8 @@ Justin Terry (VM) Justin Terry (VM) via Qemu-devel + Aleksandar Markovic + Aleksandar Markovic +-Aleksandar Rikalo ++Aleksandar Rikalo ++Aleksandar Rikalo + Anthony Liguori Anthony Liguori + James Hogan + Leif Lindholm +diff --git a/MAINTAINERS b/MAINTAINERS +index f46ab150dc..a209b5d8ce 100644 +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -213,7 +213,7 @@ F: disas/microblaze.c + MIPS TCG CPUs + M: Aleksandar Markovic + R: Aurelien Jarno +-R: Aleksandar Rikalo ++R: Aleksandar Rikalo + S: Maintained + F: target/mips/ + F: default-configs/*mips* +@@ -1048,7 +1048,7 @@ MIPS Machines + ------------- + Jazz + M: Hervé Poussineau +-R: Aleksandar Rikalo ++R: Aleksandar Rikalo + S: Maintained + F: hw/mips/jazz.c + F: hw/display/jazz_led.c +@@ -1069,7 +1069,7 @@ F: tests/acceptance/machine_mips_malta.py + + Mipssim + M: Aleksandar Markovic +-R: Aleksandar Rikalo ++R: Aleksandar Rikalo + S: Odd Fixes + F: hw/mips/mipssim.c + F: hw/net/mipsnet.c +@@ -1077,7 +1077,7 @@ F: hw/net/mipsnet.c + R4000 + M: Aleksandar Markovic + R: Aurelien Jarno +-R: Aleksandar Rikalo ++R: Aleksandar Rikalo + S: Obsolete + F: hw/mips/r4k.c + +@@ -1094,7 +1094,7 @@ F: include/hw/isa/vt82c686.h + + Boston + M: Paul Burton +-R: Aleksandar Rikalo ++R: Aleksandar Rikalo + S: Maintained + F: hw/core/loader-fit.c + F: hw/mips/boston.c +@@ -2608,7 +2608,7 @@ F: disas/i386.c + MIPS TCG target + M: Aleksandar Markovic + R: Aurelien Jarno +-R: Aleksandar Rikalo ++R: Aleksandar Rikalo + S: Maintained + F: tcg/mips/ + +-- +2.23.0 + diff --git a/MAINTAINERS-Mark-the-LatticeMico32-target-as-orphan.patch b/MAINTAINERS-Mark-the-LatticeMico32-target-as-orphan.patch new file mode 100644 index 0000000000000000000000000000000000000000..04a09ad95cb20dc958040fa5ce0dab6ea6840259 --- /dev/null +++ b/MAINTAINERS-Mark-the-LatticeMico32-target-as-orphan.patch @@ -0,0 +1,74 @@ +From 4b4d96c776f552e4a7ffe2b686ef1dfc9ad3f98f Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Mon, 16 Mar 2020 15:28:27 +0100 +Subject: [PATCH 188/709] MAINTAINERS: Mark the LatticeMico32 target as orphan +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Michael Walle expressed his desire to orphan the lm32 target [*]: + + I guess it is time to pull the plug. Mainly, because I have + no time for this anymore. I've always worked on this on my + spare time and life changed. And secondly, I guess RISC-V is + taking over ;) It has a far better ecosystem. Also, to my + knowledge the only (public) user of LM32 is milkymist and this + project is dead for years now.. + + So time to say goodbye. It was fun and I've learned a lot - + technically and also how a huge open source project works. + Thank you everyone for that :) + + Basically everything still works and there are even TCG test + cases which covers all instructions the processor has. + +Many thanks to Michael for his substantial contributions to QEMU, +and for maintaining the LM32 target for various years! + +[*] https://www.mail-archive.com/qemu-devel@nongnu.org/msg605024.html + +Acked-by: Michael Walle +Signed-off-by: Philippe Mathieu-Daudé +Reviewed-by: Richard Henderson +Message-Id: <20200316142827.20867-1-philmd@redhat.com> +Signed-off-by: Laurent Vivier +--- + MAINTAINERS | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +diff --git a/MAINTAINERS b/MAINTAINERS +index 8aa8efaf1d..d6886be131 100644 +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -184,8 +184,8 @@ F: hw/net/*i82596* + F: include/hw/net/lasi_82596.h + + LM32 TCG CPUs +-M: Michael Walle +-S: Maintained ++R: Michael Walle ++S: Orphan + F: target/lm32/ + F: disas/lm32.c + F: hw/lm32/ +@@ -977,13 +977,13 @@ F: pc-bios/hppa-firmware.img + LM32 Machines + ------------- + EVR32 and uclinux BSP +-M: Michael Walle +-S: Maintained ++R: Michael Walle ++S: Orphan + F: hw/lm32/lm32_boards.c + + milkymist +-M: Michael Walle +-S: Maintained ++R: Michael Walle ++S: Orphan + F: hw/lm32/milkymist.c + + M68K Machines +-- +2.23.0 + diff --git a/MAINTAINERS-Update-Keith-Busch-s-email-address.patch b/MAINTAINERS-Update-Keith-Busch-s-email-address.patch new file mode 100644 index 0000000000000000000000000000000000000000..a8e4ede76497a83c638abc89354378500bf84c07 --- /dev/null +++ b/MAINTAINERS-Update-Keith-Busch-s-email-address.patch @@ -0,0 +1,35 @@ +From 8261cc171f98e89714a0578412e7880396a4f4a6 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Tue, 21 Apr 2020 14:22:36 +0200 +Subject: [PATCH 192/709] MAINTAINERS: Update Keith Busch's email address +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +keith.busch@intel.com address is being rejected. +Replace by the email address Keith is actively using. + +Signed-off-by: Philippe Mathieu-Daudé +Acked-by: Keith Busch +Message-Id: <20200421122236.24867-1-f4bug@amsat.org> +Signed-off-by: Laurent Vivier +--- + MAINTAINERS | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/MAINTAINERS b/MAINTAINERS +index d6886be131..1f84e3ae2c 100644 +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -1735,7 +1735,7 @@ F: hw/virtio/virtio-crypto-pci.c + F: include/hw/virtio/virtio-crypto.h + + nvme +-M: Keith Busch ++M: Keith Busch + L: qemu-block@nongnu.org + S: Supported + F: hw/block/nvme* +-- +2.23.0 + diff --git a/MAINTAINERS-Upgrade-myself-as-9pfs-co-maintainer.patch b/MAINTAINERS-Upgrade-myself-as-9pfs-co-maintainer.patch new file mode 100644 index 0000000000000000000000000000000000000000..35b787b97c8125a7efb6ccc0e71b47a59c0a77ea --- /dev/null +++ b/MAINTAINERS-Upgrade-myself-as-9pfs-co-maintainer.patch @@ -0,0 +1,34 @@ +From 233982af53915bd9fbfa604e3b566b50af6fe5a7 Mon Sep 17 00:00:00 2001 +From: Christian Schoenebeck +Date: Thu, 14 May 2020 08:06:43 +0200 +Subject: [PATCH 398/709] MAINTAINERS: Upgrade myself as 9pfs co-maintainer +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +As suggested by Greg, let's upgrade myself as co-maintainer of 9pfs. + +Signed-off-by: Christian Schoenebeck +Reviewed-by: Philippe Mathieu-Daudé +Message-Id: +Signed-off-by: Greg Kurz +--- + MAINTAINERS | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/MAINTAINERS b/MAINTAINERS +index 1f84e3ae2c..005ee98a59 100644 +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -1657,7 +1657,7 @@ F: include/sysemu/balloon.h + + virtio-9p + M: Greg Kurz +-R: Christian Schoenebeck ++M: Christian Schoenebeck + S: Odd Fixes + F: hw/9pfs/ + X: hw/9pfs/xen-9p* +-- +2.23.0 + diff --git a/MAINTAINERS-update-the-orphaned-cpus-common.c-file.patch b/MAINTAINERS-update-the-orphaned-cpus-common.c-file.patch new file mode 100644 index 0000000000000000000000000000000000000000..c3b10f9093f0141d2d1ba19313d3bd732dbe6865 --- /dev/null +++ b/MAINTAINERS-update-the-orphaned-cpus-common.c-file.patch @@ -0,0 +1,33 @@ +From adf1cfbdc29e6e3342ca07701be4d2cbfd7d3907 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Alex=20Benn=C3=A9e?= +Date: Wed, 13 May 2020 18:31:56 +0100 +Subject: [PATCH 502/709] MAINTAINERS: update the orphaned cpus-common.c file +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +We forgot to update MAINTAINERS when this code was re-factored. + +Fixes: 267f685b8b +Signed-off-by: Alex Bennée +Reviewed-by: Philippe Mathieu-Daudé +Message-Id: <20200513173200.11830-5-alex.bennee@linaro.org> +--- + MAINTAINERS | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/MAINTAINERS b/MAINTAINERS +index f02e290702..47ef3139e6 100644 +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -115,6 +115,7 @@ M: Richard Henderson + R: Paolo Bonzini + S: Maintained + F: cpus.c ++F: cpus-common.c + F: exec.c + F: accel/tcg/ + F: accel/stubs/tcg-stub.c +-- +2.23.0 + diff --git a/Makefile-Drop-unused-broken-target-recurse-fuzz.patch b/Makefile-Drop-unused-broken-target-recurse-fuzz.patch new file mode 100644 index 0000000000000000000000000000000000000000..4331d3d2c7a0262fe42cc56017bfdde6016c5ac6 --- /dev/null +++ b/Makefile-Drop-unused-broken-target-recurse-fuzz.patch @@ -0,0 +1,31 @@ +From 14b6ce68cc8658be107247544e9a287ed17aaf76 Mon Sep 17 00:00:00 2001 +From: Markus Armbruster +Date: Fri, 24 Apr 2020 09:11:40 +0200 +Subject: [PATCH 032/709] Makefile: Drop unused, broken target recurse-fuzz + +Target recurse-fuzz depends on pc-bios/optionrom/fuzz, which can't be +made. It's not used anywhere. Added in commit c621dc3e01c, looks +like cargo cult. Delete. + +Signed-off-by: Markus Armbruster +Message-Id: <20200424071142.3525-2-armbru@redhat.com> +Reviewed-by: Alexander Bulekov +--- + Makefile | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/Makefile b/Makefile +index 8a9113e666..34275f57c9 100644 +--- a/Makefile ++++ b/Makefile +@@ -582,7 +582,6 @@ $(ROM_DIRS_RULES): + + .PHONY: recurse-all recurse-clean recurse-install + recurse-all: $(addsuffix /all, $(TARGET_DIRS) $(ROM_DIRS)) +-recurse-fuzz: $(addsuffix /fuzz, $(TARGET_DIRS) $(ROM_DIRS)) + recurse-clean: $(addsuffix /clean, $(TARGET_DIRS) $(ROM_DIRS)) + recurse-install: $(addsuffix /install, $(TARGET_DIRS)) + $(addsuffix /install, $(TARGET_DIRS)): all +-- +2.23.0 + diff --git a/Makefile-List-fuzz-targets-in-make-help.patch b/Makefile-List-fuzz-targets-in-make-help.patch new file mode 100644 index 0000000000000000000000000000000000000000..59941bf8fa5e69fb1f7aa171b149564cee183885 --- /dev/null +++ b/Makefile-List-fuzz-targets-in-make-help.patch @@ -0,0 +1,48 @@ +From 763815a83744fe7b9c5d88bd54370f25742fd10c Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Thu, 14 May 2020 16:34:29 +0200 +Subject: [PATCH 485/709] Makefile: List fuzz targets in 'make help' +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +List softmmu fuzz targets in 'make help' output: + + $ make help + ... + Architecture specific targets: + aarch64-softmmu/all - Build for aarch64-softmmu + aarch64-softmmu/fuzz - Build fuzzer for aarch64-softmmu + alpha-softmmu/all - Build for alpha-softmmu + alpha-softmmu/fuzz - Build fuzzer for alpha-softmmu + arm-softmmu/all - Build for arm-softmmu + arm-softmmu/fuzz - Build fuzzer for arm-softmmu + ... + +Signed-off-by: Philippe Mathieu-Daudé +Message-id: 20200514143433.18569-3-philmd@redhat.com +Signed-off-by: Stefan Hajnoczi +--- + Makefile | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/Makefile b/Makefile +index 34275f57c9..40e4f7677b 100644 +--- a/Makefile ++++ b/Makefile +@@ -1252,7 +1252,11 @@ endif + @$(if $(TARGET_DIRS), \ + echo 'Architecture specific targets:'; \ + $(foreach t, $(TARGET_DIRS), \ +- $(call print-help-run,$(t)/all,Build for $(t));) \ ++ $(call print-help-run,$(t)/all,Build for $(t)); \ ++ $(if $(CONFIG_FUZZ), \ ++ $(if $(findstring softmmu,$(t)), \ ++ $(call print-help-run,$(t)/fuzz,Build fuzzer for $(t)); \ ++ ))) \ + echo '') + @$(if $(TOOLS), \ + echo 'Tools targets:'; \ +-- +2.23.0 + diff --git a/Open-5.1-development-tree.patch b/Open-5.1-development-tree.patch new file mode 100644 index 0000000000000000000000000000000000000000..4b72a9c4825b3389797a477f50407a9b91152617 --- /dev/null +++ b/Open-5.1-development-tree.patch @@ -0,0 +1,20 @@ +From a7922a3c81f34f45b1ebc9670a7769edc4c42a43 Mon Sep 17 00:00:00 2001 +From: Peter Maydell +Date: Wed, 29 Apr 2020 15:07:10 +0100 +Subject: [PATCH 053/709] Open 5.1 development tree + +Signed-off-by: Peter Maydell +--- + VERSION | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/VERSION b/VERSION +index 0062ac9718..a480698ce5 100644 +--- a/VERSION ++++ b/VERSION +@@ -1 +1 @@ +-5.0.0 ++5.0.50 +-- +2.23.0 + diff --git a/Refactor-vhost_user_set_mem_table-functions.patch b/Refactor-vhost_user_set_mem_table-functions.patch new file mode 100644 index 0000000000000000000000000000000000000000..5a74d8a972778ca86e266c3cce4ea2fe7c23f947 --- /dev/null +++ b/Refactor-vhost_user_set_mem_table-functions.patch @@ -0,0 +1,229 @@ +From 2d9da9dff35765fc3c0f5a67da04a38066897650 Mon Sep 17 00:00:00 2001 +From: Raphael Norwitz +Date: Wed, 25 Mar 2020 06:35:06 -0400 +Subject: [PATCH 225/709] Refactor vhost_user_set_mem_table functions +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +vhost_user_set_mem_table() and vhost_user_set_mem_table_postcopy() have +gotten convoluted, and have some identical code. + +This change moves the logic populating the VhostUserMemory struct and +fds array from vhost_user_set_mem_table() and +vhost_user_set_mem_table_postcopy() to a new function, +vhost_user_fill_set_mem_table_msg(). + +No functionality is impacted. + +Signed-off-by: Raphael Norwitz +Signed-off-by: Peter Turschmid +Message-Id: <1585132506-13316-1-git-send-email-raphael.norwitz@nutanix.com> +Reviewed-by: Marc-André Lureau +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +--- + hw/virtio/vhost-user.c | 143 +++++++++++++++++++---------------------- + 1 file changed, 67 insertions(+), 76 deletions(-) + +diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c +index 08e7e63790..ec21e8fbe8 100644 +--- a/hw/virtio/vhost-user.c ++++ b/hw/virtio/vhost-user.c +@@ -407,18 +407,79 @@ static int vhost_user_set_log_base(struct vhost_dev *dev, uint64_t base, + return 0; + } + ++static int vhost_user_fill_set_mem_table_msg(struct vhost_user *u, ++ struct vhost_dev *dev, ++ VhostUserMsg *msg, ++ int *fds, size_t *fd_num, ++ bool track_ramblocks) ++{ ++ int i, fd; ++ ram_addr_t offset; ++ MemoryRegion *mr; ++ struct vhost_memory_region *reg; ++ ++ msg->hdr.request = VHOST_USER_SET_MEM_TABLE; ++ ++ for (i = 0; i < dev->mem->nregions; ++i) { ++ reg = dev->mem->regions + i; ++ ++ assert((uintptr_t)reg->userspace_addr == reg->userspace_addr); ++ mr = memory_region_from_host((void *)(uintptr_t)reg->userspace_addr, ++ &offset); ++ fd = memory_region_get_fd(mr); ++ if (fd > 0) { ++ if (track_ramblocks) { ++ assert(*fd_num < VHOST_MEMORY_MAX_NREGIONS); ++ trace_vhost_user_set_mem_table_withfd(*fd_num, mr->name, ++ reg->memory_size, ++ reg->guest_phys_addr, ++ reg->userspace_addr, ++ offset); ++ u->region_rb_offset[i] = offset; ++ u->region_rb[i] = mr->ram_block; ++ } else if (*fd_num == VHOST_MEMORY_MAX_NREGIONS) { ++ error_report("Failed preparing vhost-user memory table msg"); ++ return -1; ++ } ++ msg->payload.memory.regions[*fd_num].userspace_addr = ++ reg->userspace_addr; ++ msg->payload.memory.regions[*fd_num].memory_size = ++ reg->memory_size; ++ msg->payload.memory.regions[*fd_num].guest_phys_addr = ++ reg->guest_phys_addr; ++ msg->payload.memory.regions[*fd_num].mmap_offset = offset; ++ fds[(*fd_num)++] = fd; ++ } else if (track_ramblocks) { ++ u->region_rb_offset[i] = 0; ++ u->region_rb[i] = NULL; ++ } ++ } ++ ++ msg->payload.memory.nregions = *fd_num; ++ ++ if (!*fd_num) { ++ error_report("Failed initializing vhost-user memory map, " ++ "consider using -object memory-backend-file share=on"); ++ return -1; ++ } ++ ++ msg->hdr.size = sizeof(msg->payload.memory.nregions); ++ msg->hdr.size += sizeof(msg->payload.memory.padding); ++ msg->hdr.size += *fd_num * sizeof(VhostUserMemoryRegion); ++ ++ return 1; ++} ++ + static int vhost_user_set_mem_table_postcopy(struct vhost_dev *dev, + struct vhost_memory *mem) + { + struct vhost_user *u = dev->opaque; + int fds[VHOST_MEMORY_MAX_NREGIONS]; +- int i, fd; + size_t fd_num = 0; + VhostUserMsg msg_reply; + int region_i, msg_i; + + VhostUserMsg msg = { +- .hdr.request = VHOST_USER_SET_MEM_TABLE, + .hdr.flags = VHOST_USER_VERSION, + }; + +@@ -433,48 +494,11 @@ static int vhost_user_set_mem_table_postcopy(struct vhost_dev *dev, + u->region_rb_len = dev->mem->nregions; + } + +- for (i = 0; i < dev->mem->nregions; ++i) { +- struct vhost_memory_region *reg = dev->mem->regions + i; +- ram_addr_t offset; +- MemoryRegion *mr; +- +- assert((uintptr_t)reg->userspace_addr == reg->userspace_addr); +- mr = memory_region_from_host((void *)(uintptr_t)reg->userspace_addr, +- &offset); +- fd = memory_region_get_fd(mr); +- if (fd > 0) { +- assert(fd_num < VHOST_MEMORY_MAX_NREGIONS); +- trace_vhost_user_set_mem_table_withfd(fd_num, mr->name, +- reg->memory_size, +- reg->guest_phys_addr, +- reg->userspace_addr, offset); +- u->region_rb_offset[i] = offset; +- u->region_rb[i] = mr->ram_block; +- msg.payload.memory.regions[fd_num].userspace_addr = +- reg->userspace_addr; +- msg.payload.memory.regions[fd_num].memory_size = reg->memory_size; +- msg.payload.memory.regions[fd_num].guest_phys_addr = +- reg->guest_phys_addr; +- msg.payload.memory.regions[fd_num].mmap_offset = offset; +- fds[fd_num++] = fd; +- } else { +- u->region_rb_offset[i] = 0; +- u->region_rb[i] = NULL; +- } +- } +- +- msg.payload.memory.nregions = fd_num; +- +- if (!fd_num) { +- error_report("Failed initializing vhost-user memory map, " +- "consider using -object memory-backend-file share=on"); ++ if (vhost_user_fill_set_mem_table_msg(u, dev, &msg, fds, &fd_num, ++ true) < 0) { + return -1; + } + +- msg.hdr.size = sizeof(msg.payload.memory.nregions); +- msg.hdr.size += sizeof(msg.payload.memory.padding); +- msg.hdr.size += fd_num * sizeof(VhostUserMemoryRegion); +- + if (vhost_user_write(dev, &msg, fds, fd_num) < 0) { + return -1; + } +@@ -545,7 +569,6 @@ static int vhost_user_set_mem_table(struct vhost_dev *dev, + { + struct vhost_user *u = dev->opaque; + int fds[VHOST_MEMORY_MAX_NREGIONS]; +- int i, fd; + size_t fd_num = 0; + bool do_postcopy = u->postcopy_listen && u->postcopy_fd.handler; + bool reply_supported = virtio_has_feature(dev->protocol_features, +@@ -559,7 +582,6 @@ static int vhost_user_set_mem_table(struct vhost_dev *dev, + } + + VhostUserMsg msg = { +- .hdr.request = VHOST_USER_SET_MEM_TABLE, + .hdr.flags = VHOST_USER_VERSION, + }; + +@@ -567,42 +589,11 @@ static int vhost_user_set_mem_table(struct vhost_dev *dev, + msg.hdr.flags |= VHOST_USER_NEED_REPLY_MASK; + } + +- for (i = 0; i < dev->mem->nregions; ++i) { +- struct vhost_memory_region *reg = dev->mem->regions + i; +- ram_addr_t offset; +- MemoryRegion *mr; +- +- assert((uintptr_t)reg->userspace_addr == reg->userspace_addr); +- mr = memory_region_from_host((void *)(uintptr_t)reg->userspace_addr, +- &offset); +- fd = memory_region_get_fd(mr); +- if (fd > 0) { +- if (fd_num == VHOST_MEMORY_MAX_NREGIONS) { +- error_report("Failed preparing vhost-user memory table msg"); +- return -1; +- } +- msg.payload.memory.regions[fd_num].userspace_addr = +- reg->userspace_addr; +- msg.payload.memory.regions[fd_num].memory_size = reg->memory_size; +- msg.payload.memory.regions[fd_num].guest_phys_addr = +- reg->guest_phys_addr; +- msg.payload.memory.regions[fd_num].mmap_offset = offset; +- fds[fd_num++] = fd; +- } +- } +- +- msg.payload.memory.nregions = fd_num; +- +- if (!fd_num) { +- error_report("Failed initializing vhost-user memory map, " +- "consider using -object memory-backend-file share=on"); ++ if (vhost_user_fill_set_mem_table_msg(u, dev, &msg, fds, &fd_num, ++ false) < 0) { + return -1; + } + +- msg.hdr.size = sizeof(msg.payload.memory.nregions); +- msg.hdr.size += sizeof(msg.payload.memory.padding); +- msg.hdr.size += fd_num * sizeof(VhostUserMemoryRegion); +- + if (vhost_user_write(dev, &msg, fds, fd_num) < 0) { + return -1; + } +-- +2.23.0 + diff --git a/Revert-9p-init_in_iov_from_pdu-can-truncate-the-size.patch b/Revert-9p-init_in_iov_from_pdu-can-truncate-the-size.patch new file mode 100644 index 0000000000000000000000000000000000000000..fe9fce18451bb0f6a6696ce4a2d005baf1aee023 --- /dev/null +++ b/Revert-9p-init_in_iov_from_pdu-can-truncate-the-size.patch @@ -0,0 +1,203 @@ +From cf45183b718f02b1369e18c795dc51bc1821245d Mon Sep 17 00:00:00 2001 +From: Stefano Stabellini +Date: Thu, 21 May 2020 12:26:25 -0700 +Subject: [PATCH 645/709] Revert "9p: init_in_iov_from_pdu can truncate the + size" + +This reverts commit 16724a173049ac29c7b5ade741da93a0f46edff7. +It causes https://bugs.launchpad.net/bugs/1877688. + +Signed-off-by: Stefano Stabellini +Reviewed-by: Christian Schoenebeck +Message-Id: <20200521192627.15259-1-sstabellini@kernel.org> +Signed-off-by: Greg Kurz +--- + hw/9pfs/9p.c | 33 +++++++++++---------------------- + hw/9pfs/9p.h | 2 +- + hw/9pfs/virtio-9p-device.c | 11 ++++------- + hw/9pfs/xen-9p-backend.c | 15 ++++++--------- + 4 files changed, 22 insertions(+), 39 deletions(-) + +diff --git a/hw/9pfs/9p.c b/hw/9pfs/9p.c +index 68c2df7333..45a788f6e6 100644 +--- a/hw/9pfs/9p.c ++++ b/hw/9pfs/9p.c +@@ -2103,29 +2103,22 @@ out_nofid: + * with qemu_iovec_destroy(). + */ + static void v9fs_init_qiov_from_pdu(QEMUIOVector *qiov, V9fsPDU *pdu, +- size_t skip, size_t *size, ++ size_t skip, size_t size, + bool is_write) + { + QEMUIOVector elem; + struct iovec *iov; + unsigned int niov; +- size_t alloc_size = *size + skip; + + if (is_write) { +- pdu->s->transport->init_out_iov_from_pdu(pdu, &iov, &niov, alloc_size); ++ pdu->s->transport->init_out_iov_from_pdu(pdu, &iov, &niov, size + skip); + } else { +- pdu->s->transport->init_in_iov_from_pdu(pdu, &iov, &niov, &alloc_size); +- } +- +- if (alloc_size < skip) { +- *size = 0; +- } else { +- *size = alloc_size - skip; ++ pdu->s->transport->init_in_iov_from_pdu(pdu, &iov, &niov, size + skip); + } + + qemu_iovec_init_external(&elem, iov, niov); + qemu_iovec_init(qiov, niov); +- qemu_iovec_concat(qiov, &elem, skip, *size); ++ qemu_iovec_concat(qiov, &elem, skip, size); + } + + static int v9fs_xattr_read(V9fsState *s, V9fsPDU *pdu, V9fsFidState *fidp, +@@ -2133,14 +2126,15 @@ static int v9fs_xattr_read(V9fsState *s, V9fsPDU *pdu, V9fsFidState *fidp, + { + ssize_t err; + size_t offset = 7; +- size_t read_count; ++ uint64_t read_count; + QEMUIOVector qiov_full; + + if (fidp->fs.xattr.len < off) { + read_count = 0; +- } else if (fidp->fs.xattr.len - off < max_count) { +- read_count = fidp->fs.xattr.len - off; + } else { ++ read_count = fidp->fs.xattr.len - off; ++ } ++ if (read_count > max_count) { + read_count = max_count; + } + err = pdu_marshal(pdu, offset, "d", read_count); +@@ -2149,7 +2143,7 @@ static int v9fs_xattr_read(V9fsState *s, V9fsPDU *pdu, V9fsFidState *fidp, + } + offset += err; + +- v9fs_init_qiov_from_pdu(&qiov_full, pdu, offset, &read_count, false); ++ v9fs_init_qiov_from_pdu(&qiov_full, pdu, offset, read_count, false); + err = v9fs_pack(qiov_full.iov, qiov_full.niov, 0, + ((char *)fidp->fs.xattr.value) + off, + read_count); +@@ -2278,11 +2272,9 @@ static void coroutine_fn v9fs_read(void *opaque) + QEMUIOVector qiov_full; + QEMUIOVector qiov; + int32_t len; +- size_t size = max_count; + +- v9fs_init_qiov_from_pdu(&qiov_full, pdu, offset + 4, &size, false); ++ v9fs_init_qiov_from_pdu(&qiov_full, pdu, offset + 4, max_count, false); + qemu_iovec_init(&qiov, qiov_full.niov); +- max_count = size; + do { + qemu_iovec_reset(&qiov); + qemu_iovec_concat(&qiov, &qiov_full, count, qiov_full.size - count); +@@ -2533,7 +2525,6 @@ static void coroutine_fn v9fs_write(void *opaque) + int32_t len = 0; + int32_t total = 0; + size_t offset = 7; +- size_t size; + V9fsFidState *fidp; + V9fsPDU *pdu = opaque; + V9fsState *s = pdu->s; +@@ -2546,9 +2537,7 @@ static void coroutine_fn v9fs_write(void *opaque) + return; + } + offset += err; +- size = count; +- v9fs_init_qiov_from_pdu(&qiov_full, pdu, offset, &size, true); +- count = size; ++ v9fs_init_qiov_from_pdu(&qiov_full, pdu, offset, count, true); + trace_v9fs_write(pdu->tag, pdu->id, fid, off, count, qiov_full.niov); + + fidp = get_fid(pdu, fid); +diff --git a/hw/9pfs/9p.h b/hw/9pfs/9p.h +index 3ab580764c..ee2271663c 100644 +--- a/hw/9pfs/9p.h ++++ b/hw/9pfs/9p.h +@@ -436,7 +436,7 @@ struct V9fsTransport { + ssize_t (*pdu_vunmarshal)(V9fsPDU *pdu, size_t offset, const char *fmt, + va_list ap); + void (*init_in_iov_from_pdu)(V9fsPDU *pdu, struct iovec **piov, +- unsigned int *pniov, size_t *size); ++ unsigned int *pniov, size_t size); + void (*init_out_iov_from_pdu)(V9fsPDU *pdu, struct iovec **piov, + unsigned int *pniov, size_t size); + void (*push_and_notify)(V9fsPDU *pdu); +diff --git a/hw/9pfs/virtio-9p-device.c b/hw/9pfs/virtio-9p-device.c +index e5b44977c7..36f3aa9352 100644 +--- a/hw/9pfs/virtio-9p-device.c ++++ b/hw/9pfs/virtio-9p-device.c +@@ -147,22 +147,19 @@ static ssize_t virtio_pdu_vunmarshal(V9fsPDU *pdu, size_t offset, + } + + static void virtio_init_in_iov_from_pdu(V9fsPDU *pdu, struct iovec **piov, +- unsigned int *pniov, size_t *size) ++ unsigned int *pniov, size_t size) + { + V9fsState *s = pdu->s; + V9fsVirtioState *v = container_of(s, V9fsVirtioState, state); + VirtQueueElement *elem = v->elems[pdu->idx]; + size_t buf_size = iov_size(elem->in_sg, elem->in_num); + +- if (buf_size < P9_IOHDRSZ) { ++ if (buf_size < size) { + VirtIODevice *vdev = VIRTIO_DEVICE(v); + + virtio_error(vdev, +- "VirtFS reply type %d needs %zu bytes, buffer has %zu, less than minimum", +- pdu->id + 1, *size, buf_size); +- } +- if (buf_size < *size) { +- *size = buf_size; ++ "VirtFS reply type %d needs %zu bytes, buffer has %zu", ++ pdu->id + 1, size, buf_size); + } + + *piov = elem->in_sg; +diff --git a/hw/9pfs/xen-9p-backend.c b/hw/9pfs/xen-9p-backend.c +index f04caabfe5..fc197f6c8a 100644 +--- a/hw/9pfs/xen-9p-backend.c ++++ b/hw/9pfs/xen-9p-backend.c +@@ -188,7 +188,7 @@ static void xen_9pfs_init_out_iov_from_pdu(V9fsPDU *pdu, + static void xen_9pfs_init_in_iov_from_pdu(V9fsPDU *pdu, + struct iovec **piov, + unsigned int *pniov, +- size_t *size) ++ size_t size) + { + Xen9pfsDev *xen_9pfs = container_of(pdu->s, Xen9pfsDev, state); + Xen9pfsRing *ring = &xen_9pfs->rings[pdu->tag % xen_9pfs->num_rings]; +@@ -198,19 +198,16 @@ static void xen_9pfs_init_in_iov_from_pdu(V9fsPDU *pdu, + g_free(ring->sg); + + ring->sg = g_new0(struct iovec, 2); +- xen_9pfs_in_sg(ring, ring->sg, &num, pdu->idx, *size); ++ xen_9pfs_in_sg(ring, ring->sg, &num, pdu->idx, size); + + buf_size = iov_size(ring->sg, num); +- if (buf_size < P9_IOHDRSZ) { +- xen_pv_printf(&xen_9pfs->xendev, 0, "Xen 9pfs reply type %d needs " +- "%zu bytes, buffer has %zu, less than minimum\n", +- pdu->id + 1, *size, buf_size); ++ if (buf_size < size) { ++ xen_pv_printf(&xen_9pfs->xendev, 0, "Xen 9pfs request type %d" ++ "needs %zu bytes, buffer has %zu\n", pdu->id, size, ++ buf_size); + xen_be_set_state(&xen_9pfs->xendev, XenbusStateClosing); + xen_9pfs_disconnect(&xen_9pfs->xendev); + } +- if (buf_size < *size) { +- *size = buf_size; +- } + + *piov = ring->sg; + *pniov = num; +-- +2.23.0 + diff --git a/Revert-Enable-build-and-install-of-our-rST-docs.patch b/Revert-Enable-build-and-install-of-our-rST-docs.patch deleted file mode 100644 index e357273e1015d55a8849a53abec1c520c14e6b51..0000000000000000000000000000000000000000 --- a/Revert-Enable-build-and-install-of-our-rST-docs.patch +++ /dev/null @@ -1,1306 +0,0 @@ -From 4ed2ab47ab39de39f9753074b79303638dac020d Mon Sep 17 00:00:00 2001 -From: zhanghailiang -Date: Wed, 17 Jul 2019 09:51:03 +0800 -Subject: [PATCH] Revert "Enable build and install of our rST docs" - ---- - .gitignore | 1 - - MAINTAINERS | 6 - - Makefile | 88 +++--------- - configure | 15 +- - docs/conf.py | 216 ----------------------------- - docs/cpu-hotplug.rst | 2 +- - docs/devel/conf.py | 15 -- - docs/devel/index.rst | 22 --- - docs/devel/memory.rst | 363 ------------------------------------------------- - docs/devel/memory.txt | 351 +++++++++++++++++++++++++++++++++++++++++++++++ - docs/index.rst | 15 -- - docs/interop/conf.py | 15 -- - docs/interop/index.rst | 18 --- - 13 files changed, 374 insertions(+), 753 deletions(-) - delete mode 100644 docs/conf.py - delete mode 100644 docs/devel/conf.py - delete mode 100644 docs/devel/index.rst - delete mode 100644 docs/devel/memory.rst - create mode 100644 docs/devel/memory.txt - delete mode 100644 docs/index.rst - delete mode 100644 docs/interop/conf.py - delete mode 100644 docs/interop/index.rst - -diff --git a/.gitignore b/.gitignore -index 8f78221..7385d5c 100644 ---- a/.gitignore -+++ b/.gitignore -@@ -1,4 +1,3 @@ --/.doctrees - /config-devices.* - /config-all-devices.* - /config-all-disas.* -diff --git a/MAINTAINERS b/MAINTAINERS -index 56139ac..a162586 100644 ---- a/MAINTAINERS -+++ b/MAINTAINERS -@@ -2586,9 +2586,3 @@ GIT submodules - M: Daniel P. Berrange - S: Odd Fixes - F: scripts/git-submodule.sh -- --Sphinx documentation configuration and build machinery --M: Peter Maydell --S: Maintained --F: docs/conf.py --F: docs/*/conf.py -diff --git a/Makefile b/Makefile -index 04a0d45..d1e465f 100644 ---- a/Makefile -+++ b/Makefile -@@ -87,20 +87,6 @@ endif - - include $(SRC_PATH)/rules.mak - --# Create QEMU_PKGVERSION and FULL_VERSION strings --# If PKGVERSION is set, use that; otherwise get version and -dirty status from git --QEMU_PKGVERSION := $(if $(PKGVERSION),$(PKGVERSION),$(shell \ -- cd $(SRC_PATH); \ -- if test -e .git; then \ -- git describe --match 'v*' 2>/dev/null | tr -d '\n'; \ -- if ! git diff-index --quiet HEAD &>/dev/null; then \ -- echo "-dirty"; \ -- fi; \ -- fi)) -- --# Either "version (pkgversion)", or just "version" if pkgversion not set --FULL_VERSION := $(if $(QEMU_PKGVERSION),$(VERSION) ($(QEMU_PKGVERSION)),$(VERSION)) -- - GENERATED_FILES = qemu-version.h config-host.h qemu-options.def - - GENERATED_QAPI_FILES = qapi/qapi-builtin-types.h qapi/qapi-builtin-types.c -@@ -419,12 +405,27 @@ dummy := $(call unnest-vars,, \ - - include $(SRC_PATH)/tests/Makefile.include - --all: $(DOCS) $(if $(BUILD_DOCS),sphinxdocs) $(TOOLS) $(HELPERS-y) recurse-all modules -+all: $(DOCS) $(TOOLS) $(HELPERS-y) recurse-all modules - - qemu-version.h: FORCE - $(call quiet-command, \ -- (printf '#define QEMU_PKGVERSION "$(QEMU_PKGVERSION)"\n'; \ -- printf '#define QEMU_FULL_VERSION "$(FULL_VERSION)"\n'; \ -+ (cd $(SRC_PATH); \ -+ if test -n "$(PKGVERSION)"; then \ -+ pkgvers="$(PKGVERSION)"; \ -+ else \ -+ if test -d .git; then \ -+ pkgvers=$$(git describe --match 'v*' 2>/dev/null | tr -d '\n');\ -+ if ! git diff-index --quiet HEAD &>/dev/null; then \ -+ pkgvers="$${pkgvers}-dirty"; \ -+ fi; \ -+ fi; \ -+ fi; \ -+ printf "#define QEMU_PKGVERSION \"$${pkgvers}\"\n"; \ -+ if test -n "$${pkgvers}"; then \ -+ printf '#define QEMU_FULL_VERSION QEMU_VERSION " (" QEMU_PKGVERSION ")"\n'; \ -+ else \ -+ printf '#define QEMU_FULL_VERSION QEMU_VERSION\n'; \ -+ fi; \ - ) > $@.tmp) - $(call quiet-command, if ! cmp -s $@ $@.tmp; then \ - mv $@.tmp $@; \ -@@ -656,22 +657,6 @@ dist: qemu-$(VERSION).tar.bz2 - qemu-%.tar.bz2: - $(SRC_PATH)/scripts/make-release "$(SRC_PATH)" "$(patsubst qemu-%.tar.bz2,%,$@)" - --# Sphinx does not allow building manuals into the same directory as --# the source files, so if we're doing an in-tree QEMU build we must --# build the manuals into a subdirectory (and then install them from --# there for 'make install'). For an out-of-tree build we can just --# use the docs/ subdirectory in the build tree as normal. --ifeq ($(realpath $(SRC_PATH)),$(realpath .)) --MANUAL_BUILDDIR := docs/built --else --MANUAL_BUILDDIR := docs --endif -- --define clean-manual = --rm -rf $(MANUAL_BUILDDIR)/$1/_static --rm -f $(MANUAL_BUILDDIR)/$1/objects.inv $(MANUAL_BUILDDIR)/$1/searchindex.js $(MANUAL_BUILDDIR)/$1/*.html --endef -- - distclean: clean - rm -f config-host.mak config-host.h* config-host.ld $(DOCS) qemu-options.texi qemu-img-cmds.texi qemu-monitor.texi qemu-monitor-info.texi - rm -f config-all-devices.mak config-all-disas.mak config.status -@@ -692,9 +677,6 @@ distclean: clean - rm -f docs/interop/qemu-qmp-ref.html docs/interop/qemu-ga-ref.html - rm -f docs/qemu-block-drivers.7 - rm -f docs/qemu-cpu-models.7 -- rm -rf .doctrees -- $(call clean-manual,devel) -- $(call clean-manual,interop) - for d in $(TARGET_DIRS); do \ - rm -rf $$d || exit 1 ; \ - done -@@ -728,20 +710,7 @@ else - BLOBS= - endif - --# Note that we manually filter-out the non-Sphinx documentation which --# is currently built into the docs/interop directory in the build tree. --define install-manual = --for d in $$(cd $(MANUAL_BUILDDIR) && find $1 -type d); do $(INSTALL_DIR) "$(DESTDIR)$(qemu_docdir)/$$d"; done --for f in $$(cd $(MANUAL_BUILDDIR) && find $1 -type f -a '!' '(' -name 'qemu-*-qapi.*' -o -name 'qemu-*-ref.*' ')' ); do $(INSTALL_DATA) "$(MANUAL_BUILDDIR)/$$f" "$(DESTDIR)$(qemu_docdir)/$$f"; done --endef -- --# Note that we deliberately do not install the "devel" manual: it is --# for QEMU developers, and not interesting to our users. --.PHONY: install-sphinxdocs --install-sphinxdocs: sphinxdocs -- $(call install-manual,interop) -- --install-doc: $(DOCS) install-sphinxdocs -+install-doc: $(DOCS) - $(INSTALL_DIR) "$(DESTDIR)$(qemu_docdir)" - $(INSTALL_DATA) qemu-doc.html "$(DESTDIR)$(qemu_docdir)" - $(INSTALL_DATA) qemu-doc.txt "$(DESTDIR)$(qemu_docdir)" -@@ -892,23 +861,6 @@ docs/version.texi: $(SRC_PATH)/VERSION - %.pdf: %.texi docs/version.texi - $(call quiet-command,texi2pdf $(TEXI2PDFFLAGS) $< -o $@,"GEN","$@") - --# Sphinx builds all its documentation at once in one invocation --# and handles "don't rebuild things unless necessary" itself. --# The '.doctrees' files are cached information to speed this up. --.PHONY: sphinxdocs --sphinxdocs: $(MANUAL_BUILDDIR)/devel/index.html $(MANUAL_BUILDDIR)/interop/index.html -- --# Canned command to build a single manual --build-manual = $(call quiet-command,sphinx-build $(if $(V),,-q) -b html -D version=$(VERSION) -D release="$(FULL_VERSION)" -d .doctrees/$1 $(SRC_PATH)/docs/$1 $(MANUAL_BUILDDIR)/$1 ,"SPHINX","$(MANUAL_BUILDDIR)/$1") --# We assume all RST files in the manual's directory are used in it --manual-deps = $(wildcard $(SRC_PATH)/docs/$1/*.rst) $(SRC_PATH)/docs/$1/conf.py $(SRC_PATH)/docs/conf.py -- --$(MANUAL_BUILDDIR)/devel/index.html: $(call manual-deps,devel) -- $(call build-manual,devel) -- --$(MANUAL_BUILDDIR)/interop/index.html: $(call manual-deps,interop) -- $(call build-manual,interop) -- - qemu-options.texi: $(SRC_PATH)/qemu-options.hx $(SRC_PATH)/scripts/hxtool - $(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -t < $< > $@,"GEN","$@") - -@@ -937,7 +889,7 @@ docs/qemu-block-drivers.7: docs/qemu-block-drivers.texi - docs/qemu-cpu-models.7: docs/qemu-cpu-models.texi - scripts/qemu-trace-stap.1: scripts/qemu-trace-stap.texi - --html: qemu-doc.html docs/interop/qemu-qmp-ref.html docs/interop/qemu-ga-ref.html sphinxdocs -+html: qemu-doc.html docs/interop/qemu-qmp-ref.html docs/interop/qemu-ga-ref.html - info: qemu-doc.info docs/interop/qemu-qmp-ref.info docs/interop/qemu-ga-ref.info - pdf: qemu-doc.pdf docs/interop/qemu-qmp-ref.pdf docs/interop/qemu-ga-ref.pdf - txt: qemu-doc.txt docs/interop/qemu-qmp-ref.txt docs/interop/qemu-ga-ref.txt -diff --git a/configure b/configure -index 1c563a7..384a241 100755 ---- a/configure -+++ b/configure -@@ -4708,24 +4708,13 @@ if compile_prog "" "" ; then - syncfs=yes - fi - --# Check we have a new enough version of sphinx-build --has_sphinx_build() { -- # This is a bit awkward but works: create a trivial document and -- # try to run it with our configuration file (which enforces a -- # version requirement). This will fail if either -- # sphinx-build doesn't exist at all or if it is too old. -- mkdir -p "$TMPDIR1/sphinx" -- touch "$TMPDIR1/sphinx/index.rst" -- sphinx-build -c "$source_path/docs" -b html "$TMPDIR1/sphinx" "$TMPDIR1/sphinx/out" >/dev/null 2>&1 --} -- - # Check if tools are available to build documentation. - if test "$docs" != "no" ; then -- if has makeinfo && has pod2man && has_sphinx_build; then -+ if has makeinfo && has pod2man; then - docs=yes - else - if test "$docs" = "yes" ; then -- feature_not_found "docs" "Install texinfo, Perl/perl-podlators and python-sphinx" -+ feature_not_found "docs" "Install texinfo and Perl/perl-podlators" - fi - docs=no - fi -diff --git a/docs/conf.py b/docs/conf.py -deleted file mode 100644 -index befbcc6..0000000 ---- a/docs/conf.py -+++ /dev/null -@@ -1,216 +0,0 @@ --# -*- coding: utf-8 -*- --# --# QEMU documentation build configuration file, created by --# sphinx-quickstart on Thu Jan 31 16:40:14 2019. --# --# This config file can be used in one of two ways: --# (1) as a common config file which is included by the conf.py --# for each of QEMU's manuals: in this case sphinx-build is run multiple --# times, once per subdirectory. --# (2) as a top level conf file which will result in building all --# the manuals into a single document: in this case sphinx-build is --# run once, on the top-level docs directory. --# --# QEMU's makefiles take option (1), which allows us to install --# only the ones the user cares about (in particular we don't want --# to ship the 'devel' manual to end-users). --# Third-party sites such as readthedocs.org will take option (2). --# --# --# This file is execfile()d with the current directory set to its --# containing dir. --# --# Note that not all possible configuration values are present in this --# autogenerated file. --# --# All configuration values have a default; values that are commented out --# serve to show the default. -- --import os --import sys -- --# The per-manual conf.py will set qemu_docdir for a single-manual build; --# otherwise set it here if this is an entire-manual-set build. --# This is always the absolute path of the docs/ directory in the source tree. --try: -- qemu_docdir --except NameError: -- qemu_docdir = os.path.abspath(".") -- --# If extensions (or modules to document with autodoc) are in another directory, --# add these directories to sys.path here. If the directory is relative to the --# documentation root, use an absolute path starting from qemu_docdir. --# --# sys.path.insert(0, os.path.join(qemu_docdir, "my_subdir")) -- -- --# -- General configuration ------------------------------------------------ -- --# If your documentation needs a minimal Sphinx version, state it here. --# --# 1.3 is where the 'alabaster' theme was shipped with Sphinx. --needs_sphinx = '1.3' -- --# Add any Sphinx extension module names here, as strings. They can be --# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom --# ones. --extensions = [] -- --# Add any paths that contain templates here, relative to this directory. --templates_path = ['_templates'] -- --# The suffix(es) of source filenames. --# You can specify multiple suffix as a list of string: --# --# source_suffix = ['.rst', '.md'] --source_suffix = '.rst' -- --# The master toctree document. --master_doc = 'index' -- --# General information about the project. --project = u'QEMU' --copyright = u'2019, The QEMU Project Developers' --author = u'The QEMU Project Developers' -- --# The version info for the project you're documenting, acts as replacement for --# |version| and |release|, also used in various other places throughout the --# built documents. -- --# Extract this information from the VERSION file, for the benefit of --# standalone Sphinx runs as used by readthedocs.org. Builds run from --# the Makefile will pass version and release on the sphinx-build --# command line, which override this. --try: -- extracted_version = None -- with open(os.path.join(qemu_docdir, '../VERSION')) as f: -- extracted_version = f.readline().strip() --except: -- pass --finally: -- if extracted_version: -- version = release = extracted_version -- else: -- version = release = "unknown version" -- --# The language for content autogenerated by Sphinx. Refer to documentation --# for a list of supported languages. --# --# This is also used if you do content translation via gettext catalogs. --# Usually you set "language" from the command line for these cases. --language = None -- --# List of patterns, relative to source directory, that match files and --# directories to ignore when looking for source files. --# This patterns also effect to html_static_path and html_extra_path --exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] -- --# The name of the Pygments (syntax highlighting) style to use. --pygments_style = 'sphinx' -- --# If true, `todo` and `todoList` produce output, else they produce nothing. --todo_include_todos = False -- --# Sphinx defaults to warning about use of :option: for options not defined --# with "option::" in the document being processed. Turn that off. --suppress_warnings = ["ref.option"] -- --# -- Options for HTML output ---------------------------------------------- -- --# The theme to use for HTML and HTML Help pages. See the documentation for --# a list of builtin themes. --# --html_theme = 'alabaster' -- --# Theme options are theme-specific and customize the look and feel of a theme --# further. For a list of options available for each theme, see the --# documentation. --# We initialize this to empty here, so the per-manual conf.py can just --# add individual key/value entries. --html_theme_options = { --} -- --# Add any paths that contain custom static files (such as style sheets) here, --# relative to this directory. They are copied after the builtin static files, --# so a file named "default.css" will overwrite the builtin "default.css". --# QEMU doesn't yet have any static files, so comment this out so we don't --# get a warning about a missing directory. --# If we do ever add this then it would probably be better to call the --# subdirectory sphinx_static, as the Linux kernel does. --# html_static_path = ['_static'] -- --# Custom sidebar templates, must be a dictionary that maps document names --# to template names. --# --# This is required for the alabaster theme --# refs: http://alabaster.readthedocs.io/en/latest/installation.html#sidebars --html_sidebars = { -- '**': [ -- 'about.html', -- 'navigation.html', -- 'searchbox.html', -- ] --} -- --# Don't copy the rST source files to the HTML output directory, --# and don't put links to the sources into the output HTML. --html_copy_source = False -- --# -- Options for HTMLHelp output ------------------------------------------ -- --# Output file base name for HTML help builder. --htmlhelp_basename = 'QEMUdoc' -- -- --# -- Options for LaTeX output --------------------------------------------- -- --latex_elements = { -- # The paper size ('letterpaper' or 'a4paper'). -- # -- # 'papersize': 'letterpaper', -- -- # The font size ('10pt', '11pt' or '12pt'). -- # -- # 'pointsize': '10pt', -- -- # Additional stuff for the LaTeX preamble. -- # -- # 'preamble': '', -- -- # Latex figure (float) alignment -- # -- # 'figure_align': 'htbp', --} -- --# Grouping the document tree into LaTeX files. List of tuples --# (source start file, target name, title, --# author, documentclass [howto, manual, or own class]). --latex_documents = [ -- (master_doc, 'QEMU.tex', u'QEMU Documentation', -- u'The QEMU Project Developers', 'manual'), --] -- -- --# -- Options for manual page output --------------------------------------- -- --# One entry per manual page. List of tuples --# (source start file, name, description, authors, manual section). --man_pages = [ -- (master_doc, 'qemu', u'QEMU Documentation', -- [author], 1) --] -- -- --# -- Options for Texinfo output ------------------------------------------- -- --# Grouping the document tree into Texinfo files. List of tuples --# (source start file, target name, title, author, --# dir menu entry, description, category) --texinfo_documents = [ -- (master_doc, 'QEMU', u'QEMU Documentation', -- author, 'QEMU', 'One line description of project.', -- 'Miscellaneous'), --] -- -- -- -diff --git a/docs/cpu-hotplug.rst b/docs/cpu-hotplug.rst -index d0b0640..cfeb79f 100644 ---- a/docs/cpu-hotplug.rst -+++ b/docs/cpu-hotplug.rst -@@ -60,7 +60,7 @@ vCPU hotplug - hot-plugged (no "qom-path" member). From its output in step (3), we - can see that ``IvyBridge-IBRS-x86_64-cpu`` is present in socket 0, - while hot-plugging a CPU into socket 1 requires passing the listed -- properties to QMP ``device_add``:: -+ properties to QMP ``device_add``: - - (QEMU) device_add id=cpu-2 driver=IvyBridge-IBRS-x86_64-cpu socket-id=1 core-id=0 thread-id=0 - { -diff --git a/docs/devel/conf.py b/docs/devel/conf.py -deleted file mode 100644 -index 7441f87..0000000 ---- a/docs/devel/conf.py -+++ /dev/null -@@ -1,15 +0,0 @@ --# -*- coding: utf-8 -*- --# --# QEMU documentation build configuration file for the 'devel' manual. --# --# This includes the top level conf file and then makes any necessary tweaks. --import sys --import os -- --qemu_docdir = os.path.abspath("..") --parent_config = os.path.join(qemu_docdir, "conf.py") --exec(compile(open(parent_config, "rb").read(), parent_config, 'exec')) -- --# This slightly misuses the 'description', but is the best way to get --# the manual title to appear in the sidebar. --html_theme_options['description'] = u'Developer''s Guide' -diff --git a/docs/devel/index.rst b/docs/devel/index.rst -deleted file mode 100644 -index ebbab63..0000000 ---- a/docs/devel/index.rst -+++ /dev/null -@@ -1,22 +0,0 @@ --.. This is the top level page for the 'devel' manual. -- -- --QEMU Developer's Guide --====================== -- --This manual documents various parts of the internals of QEMU. --You only need to read it if you are interested in reading or --modifying QEMU's source code. -- --Contents: -- --.. toctree:: -- :maxdepth: 2 -- -- kconfig -- loads-stores -- memory -- migration -- stable-process -- testing -- decodetree -diff --git a/docs/devel/memory.rst b/docs/devel/memory.rst -deleted file mode 100644 -index b6a4c37..0000000 ---- a/docs/devel/memory.rst -+++ /dev/null -@@ -1,363 +0,0 @@ --============== --The memory API --============== -- --The memory API models the memory and I/O buses and controllers of a QEMU --machine. It attempts to allow modelling of: -- --- ordinary RAM --- memory-mapped I/O (MMIO) --- memory controllers that can dynamically reroute physical memory regions -- to different destinations -- --The memory model provides support for -- --- tracking RAM changes by the guest --- setting up coalesced memory for kvm --- setting up ioeventfd regions for kvm -- --Memory is modelled as an acyclic graph of MemoryRegion objects. Sinks --(leaves) are RAM and MMIO regions, while other nodes represent --buses, memory controllers, and memory regions that have been rerouted. -- --In addition to MemoryRegion objects, the memory API provides AddressSpace --objects for every root and possibly for intermediate MemoryRegions too. --These represent memory as seen from the CPU or a device's viewpoint. -- --Types of regions ------------------ -- --There are multiple types of memory regions (all represented by a single C type --MemoryRegion): -- --- RAM: a RAM region is simply a range of host memory that can be made available -- to the guest. -- You typically initialize these with memory_region_init_ram(). Some special -- purposes require the variants memory_region_init_resizeable_ram(), -- memory_region_init_ram_from_file(), or memory_region_init_ram_ptr(). -- --- MMIO: a range of guest memory that is implemented by host callbacks; -- each read or write causes a callback to be called on the host. -- You initialize these with memory_region_init_io(), passing it a -- MemoryRegionOps structure describing the callbacks. -- --- ROM: a ROM memory region works like RAM for reads (directly accessing -- a region of host memory), and forbids writes. You initialize these with -- memory_region_init_rom(). -- --- ROM device: a ROM device memory region works like RAM for reads -- (directly accessing a region of host memory), but like MMIO for -- writes (invoking a callback). You initialize these with -- memory_region_init_rom_device(). -- --- IOMMU region: an IOMMU region translates addresses of accesses made to it -- and forwards them to some other target memory region. As the name suggests, -- these are only needed for modelling an IOMMU, not for simple devices. -- You initialize these with memory_region_init_iommu(). -- --- container: a container simply includes other memory regions, each at -- a different offset. Containers are useful for grouping several regions -- into one unit. For example, a PCI BAR may be composed of a RAM region -- and an MMIO region. -- -- A container's subregions are usually non-overlapping. In some cases it is -- useful to have overlapping regions; for example a memory controller that -- can overlay a subregion of RAM with MMIO or ROM, or a PCI controller -- that does not prevent card from claiming overlapping BARs. -- -- You initialize a pure container with memory_region_init(). -- --- alias: a subsection of another region. Aliases allow a region to be -- split apart into discontiguous regions. Examples of uses are memory banks -- used when the guest address space is smaller than the amount of RAM -- addressed, or a memory controller that splits main memory to expose a "PCI -- hole". Aliases may point to any type of region, including other aliases, -- but an alias may not point back to itself, directly or indirectly. -- You initialize these with memory_region_init_alias(). -- --- reservation region: a reservation region is primarily for debugging. -- It claims I/O space that is not supposed to be handled by QEMU itself. -- The typical use is to track parts of the address space which will be -- handled by the host kernel when KVM is enabled. You initialize these -- by passing a NULL callback parameter to memory_region_init_io(). -- --It is valid to add subregions to a region which is not a pure container --(that is, to an MMIO, RAM or ROM region). This means that the region --will act like a container, except that any addresses within the container's --region which are not claimed by any subregion are handled by the --container itself (ie by its MMIO callbacks or RAM backing). However --it is generally possible to achieve the same effect with a pure container --one of whose subregions is a low priority "background" region covering --the whole address range; this is often clearer and is preferred. --Subregions cannot be added to an alias region. -- --Migration ----------- -- --Where the memory region is backed by host memory (RAM, ROM and --ROM device memory region types), this host memory needs to be --copied to the destination on migration. These APIs which allocate --the host memory for you will also register the memory so it is --migrated: -- --- memory_region_init_ram() --- memory_region_init_rom() --- memory_region_init_rom_device() -- --For most devices and boards this is the correct thing. If you --have a special case where you need to manage the migration of --the backing memory yourself, you can call the functions: -- --- memory_region_init_ram_nomigrate() --- memory_region_init_rom_nomigrate() --- memory_region_init_rom_device_nomigrate() -- --which only initialize the MemoryRegion and leave handling --migration to the caller. -- --The functions: -- --- memory_region_init_resizeable_ram() --- memory_region_init_ram_from_file() --- memory_region_init_ram_from_fd() --- memory_region_init_ram_ptr() --- memory_region_init_ram_device_ptr() -- --are for special cases only, and so they do not automatically --register the backing memory for migration; the caller must --manage migration if necessary. -- --Region names -------------- -- --Regions are assigned names by the constructor. For most regions these are --only used for debugging purposes, but RAM regions also use the name to identify --live migration sections. This means that RAM region names need to have ABI --stability. -- --Region lifecycle ------------------ -- --A region is created by one of the memory_region_init*() functions and --attached to an object, which acts as its owner or parent. QEMU ensures --that the owner object remains alive as long as the region is visible to --the guest, or as long as the region is in use by a virtual CPU or another --device. For example, the owner object will not die between an --address_space_map operation and the corresponding address_space_unmap. -- --After creation, a region can be added to an address space or a --container with memory_region_add_subregion(), and removed using --memory_region_del_subregion(). -- --Various region attributes (read-only, dirty logging, coalesced mmio, --ioeventfd) can be changed during the region lifecycle. They take effect --as soon as the region is made visible. This can be immediately, later, --or never. -- --Destruction of a memory region happens automatically when the owner --object dies. -- --If however the memory region is part of a dynamically allocated data --structure, you should call object_unparent() to destroy the memory region --before the data structure is freed. For an example see VFIOMSIXInfo --and VFIOQuirk in hw/vfio/pci.c. -- --You must not destroy a memory region as long as it may be in use by a --device or CPU. In order to do this, as a general rule do not create or --destroy memory regions dynamically during a device's lifetime, and only --call object_unparent() in the memory region owner's instance_finalize --callback. The dynamically allocated data structure that contains the --memory region then should obviously be freed in the instance_finalize --callback as well. -- --If you break this rule, the following situation can happen: -- --- the memory region's owner had a reference taken via memory_region_ref -- (for example by address_space_map) -- --- the region is unparented, and has no owner anymore -- --- when address_space_unmap is called, the reference to the memory region's -- owner is leaked. -- -- --There is an exception to the above rule: it is okay to call --object_unparent at any time for an alias or a container region. It is --therefore also okay to create or destroy alias and container regions --dynamically during a device's lifetime. -- --This exceptional usage is valid because aliases and containers only help --QEMU building the guest's memory map; they are never accessed directly. --memory_region_ref and memory_region_unref are never called on aliases --or containers, and the above situation then cannot happen. Exploiting --this exception is rarely necessary, and therefore it is discouraged, --but nevertheless it is used in a few places. -- --For regions that "have no owner" (NULL is passed at creation time), the --machine object is actually used as the owner. Since instance_finalize is --never called for the machine object, you must never call object_unparent --on regions that have no owner, unless they are aliases or containers. -- -- --Overlapping regions and priority ---------------------------------- --Usually, regions may not overlap each other; a memory address decodes into --exactly one target. In some cases it is useful to allow regions to overlap, --and sometimes to control which of an overlapping regions is visible to the --guest. This is done with memory_region_add_subregion_overlap(), which --allows the region to overlap any other region in the same container, and --specifies a priority that allows the core to decide which of two regions at --the same address are visible (highest wins). --Priority values are signed, and the default value is zero. This means that --you can use memory_region_add_subregion_overlap() both to specify a region --that must sit 'above' any others (with a positive priority) and also a --background region that sits 'below' others (with a negative priority). -- --If the higher priority region in an overlap is a container or alias, then --the lower priority region will appear in any "holes" that the higher priority --region has left by not mapping subregions to that area of its address range. --(This applies recursively -- if the subregions are themselves containers or --aliases that leave holes then the lower priority region will appear in these --holes too.) -- --For example, suppose we have a container A of size 0x8000 with two subregions --B and C. B is a container mapped at 0x2000, size 0x4000, priority 2; C is --an MMIO region mapped at 0x0, size 0x6000, priority 1. B currently has two --of its own subregions: D of size 0x1000 at offset 0 and E of size 0x1000 at --offset 0x2000. As a diagram:: -- -- 0 1000 2000 3000 4000 5000 6000 7000 8000 -- |------|------|------|------|------|------|------|------| -- A: [ ] -- C: [CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC] -- B: [ ] -- D: [DDDDD] -- E: [EEEEE] -- --The regions that will be seen within this address range then are:: -- -- [CCCCCCCCCCCC][DDDDD][CCCCC][EEEEE][CCCCC] -- --Since B has higher priority than C, its subregions appear in the flat map --even where they overlap with C. In ranges where B has not mapped anything --C's region appears. -- --If B had provided its own MMIO operations (ie it was not a pure container) --then these would be used for any addresses in its range not handled by --D or E, and the result would be:: -- -- [CCCCCCCCCCCC][DDDDD][BBBBB][EEEEE][BBBBB] -- --Priority values are local to a container, because the priorities of two --regions are only compared when they are both children of the same container. --This means that the device in charge of the container (typically modelling --a bus or a memory controller) can use them to manage the interaction of --its child regions without any side effects on other parts of the system. --In the example above, the priorities of D and E are unimportant because --they do not overlap each other. It is the relative priority of B and C --that causes D and E to appear on top of C: D and E's priorities are never --compared against the priority of C. -- --Visibility ------------ --The memory core uses the following rules to select a memory region when the --guest accesses an address: -- --- all direct subregions of the root region are matched against the address, in -- descending priority order -- -- - if the address lies outside the region offset/size, the subregion is -- discarded -- - if the subregion is a leaf (RAM or MMIO), the search terminates, returning -- this leaf region -- - if the subregion is a container, the same algorithm is used within the -- subregion (after the address is adjusted by the subregion offset) -- - if the subregion is an alias, the search is continued at the alias target -- (after the address is adjusted by the subregion offset and alias offset) -- - if a recursive search within a container or alias subregion does not -- find a match (because of a "hole" in the container's coverage of its -- address range), then if this is a container with its own MMIO or RAM -- backing the search terminates, returning the container itself. Otherwise -- we continue with the next subregion in priority order -- --- if none of the subregions match the address then the search terminates -- with no match found -- --Example memory map -------------------- -- --:: -- -- system_memory: container@0-2^48-1 -- | -- +---- lomem: alias@0-0xdfffffff ---> #ram (0-0xdfffffff) -- | -- +---- himem: alias@0x100000000-0x11fffffff ---> #ram (0xe0000000-0xffffffff) -- | -- +---- vga-window: alias@0xa0000-0xbffff ---> #pci (0xa0000-0xbffff) -- | (prio 1) -- | -- +---- pci-hole: alias@0xe0000000-0xffffffff ---> #pci (0xe0000000-0xffffffff) -- -- pci (0-2^32-1) -- | -- +--- vga-area: container@0xa0000-0xbffff -- | | -- | +--- alias@0x00000-0x7fff ---> #vram (0x010000-0x017fff) -- | | -- | +--- alias@0x08000-0xffff ---> #vram (0x020000-0x027fff) -- | -- +---- vram: ram@0xe1000000-0xe1ffffff -- | -- +---- vga-mmio: mmio@0xe2000000-0xe200ffff -- -- ram: ram@0x00000000-0xffffffff -- --This is a (simplified) PC memory map. The 4GB RAM block is mapped into the --system address space via two aliases: "lomem" is a 1:1 mapping of the first --3.5GB; "himem" maps the last 0.5GB at address 4GB. This leaves 0.5GB for the --so-called PCI hole, that allows a 32-bit PCI bus to exist in a system with --4GB of memory. -- --The memory controller diverts addresses in the range 640K-768K to the PCI --address space. This is modelled using the "vga-window" alias, mapped at a --higher priority so it obscures the RAM at the same addresses. The vga window --can be removed by programming the memory controller; this is modelled by --removing the alias and exposing the RAM underneath. -- --The pci address space is not a direct child of the system address space, since --we only want parts of it to be visible (we accomplish this using aliases). --It has two subregions: vga-area models the legacy vga window and is occupied --by two 32K memory banks pointing at two sections of the framebuffer. --In addition the vram is mapped as a BAR at address e1000000, and an additional --BAR containing MMIO registers is mapped after it. -- --Note that if the guest maps a BAR outside the PCI hole, it would not be --visible as the pci-hole alias clips it to a 0.5GB range. -- --MMIO Operations ----------------- -- --MMIO regions are provided with ->read() and ->write() callbacks, --which are sufficient for most devices. Some devices change behaviour --based on the attributes used for the memory transaction, or need --to be able to respond that the access should provoke a bus error --rather than completing successfully; those devices can use the --->read_with_attrs() and ->write_with_attrs() callbacks instead. -- --In addition various constraints can be supplied to control how these --callbacks are called: -- --- .valid.min_access_size, .valid.max_access_size define the access sizes -- (in bytes) which the device accepts; accesses outside this range will -- have device and bus specific behaviour (ignored, or machine check) --- .valid.unaligned specifies that the *device being modelled* supports -- unaligned accesses; if false, unaligned accesses will invoke the -- appropriate bus or CPU specific behaviour. --- .impl.min_access_size, .impl.max_access_size define the access sizes -- (in bytes) supported by the *implementation*; other access sizes will be -- emulated using the ones available. For example a 4-byte write will be -- emulated using four 1-byte writes, if .impl.max_access_size = 1. --- .impl.unaligned specifies that the *implementation* supports unaligned -- accesses; if false, unaligned accesses will be emulated by two aligned -- accesses. -diff --git a/docs/devel/memory.txt b/docs/devel/memory.txt -new file mode 100644 -index 0000000..42577e1 ---- /dev/null -+++ b/docs/devel/memory.txt -@@ -0,0 +1,351 @@ -+The memory API -+============== -+ -+The memory API models the memory and I/O buses and controllers of a QEMU -+machine. It attempts to allow modelling of: -+ -+ - ordinary RAM -+ - memory-mapped I/O (MMIO) -+ - memory controllers that can dynamically reroute physical memory regions -+ to different destinations -+ -+The memory model provides support for -+ -+ - tracking RAM changes by the guest -+ - setting up coalesced memory for kvm -+ - setting up ioeventfd regions for kvm -+ -+Memory is modelled as an acyclic graph of MemoryRegion objects. Sinks -+(leaves) are RAM and MMIO regions, while other nodes represent -+buses, memory controllers, and memory regions that have been rerouted. -+ -+In addition to MemoryRegion objects, the memory API provides AddressSpace -+objects for every root and possibly for intermediate MemoryRegions too. -+These represent memory as seen from the CPU or a device's viewpoint. -+ -+Types of regions -+---------------- -+ -+There are multiple types of memory regions (all represented by a single C type -+MemoryRegion): -+ -+- RAM: a RAM region is simply a range of host memory that can be made available -+ to the guest. -+ You typically initialize these with memory_region_init_ram(). Some special -+ purposes require the variants memory_region_init_resizeable_ram(), -+ memory_region_init_ram_from_file(), or memory_region_init_ram_ptr(). -+ -+- MMIO: a range of guest memory that is implemented by host callbacks; -+ each read or write causes a callback to be called on the host. -+ You initialize these with memory_region_init_io(), passing it a -+ MemoryRegionOps structure describing the callbacks. -+ -+- ROM: a ROM memory region works like RAM for reads (directly accessing -+ a region of host memory), and forbids writes. You initialize these with -+ memory_region_init_rom(). -+ -+- ROM device: a ROM device memory region works like RAM for reads -+ (directly accessing a region of host memory), but like MMIO for -+ writes (invoking a callback). You initialize these with -+ memory_region_init_rom_device(). -+ -+- IOMMU region: an IOMMU region translates addresses of accesses made to it -+ and forwards them to some other target memory region. As the name suggests, -+ these are only needed for modelling an IOMMU, not for simple devices. -+ You initialize these with memory_region_init_iommu(). -+ -+- container: a container simply includes other memory regions, each at -+ a different offset. Containers are useful for grouping several regions -+ into one unit. For example, a PCI BAR may be composed of a RAM region -+ and an MMIO region. -+ -+ A container's subregions are usually non-overlapping. In some cases it is -+ useful to have overlapping regions; for example a memory controller that -+ can overlay a subregion of RAM with MMIO or ROM, or a PCI controller -+ that does not prevent card from claiming overlapping BARs. -+ -+ You initialize a pure container with memory_region_init(). -+ -+- alias: a subsection of another region. Aliases allow a region to be -+ split apart into discontiguous regions. Examples of uses are memory banks -+ used when the guest address space is smaller than the amount of RAM -+ addressed, or a memory controller that splits main memory to expose a "PCI -+ hole". Aliases may point to any type of region, including other aliases, -+ but an alias may not point back to itself, directly or indirectly. -+ You initialize these with memory_region_init_alias(). -+ -+- reservation region: a reservation region is primarily for debugging. -+ It claims I/O space that is not supposed to be handled by QEMU itself. -+ The typical use is to track parts of the address space which will be -+ handled by the host kernel when KVM is enabled. You initialize these -+ by passing a NULL callback parameter to memory_region_init_io(). -+ -+It is valid to add subregions to a region which is not a pure container -+(that is, to an MMIO, RAM or ROM region). This means that the region -+will act like a container, except that any addresses within the container's -+region which are not claimed by any subregion are handled by the -+container itself (ie by its MMIO callbacks or RAM backing). However -+it is generally possible to achieve the same effect with a pure container -+one of whose subregions is a low priority "background" region covering -+the whole address range; this is often clearer and is preferred. -+Subregions cannot be added to an alias region. -+ -+Migration -+--------- -+ -+Where the memory region is backed by host memory (RAM, ROM and -+ROM device memory region types), this host memory needs to be -+copied to the destination on migration. These APIs which allocate -+the host memory for you will also register the memory so it is -+migrated: -+ - memory_region_init_ram() -+ - memory_region_init_rom() -+ - memory_region_init_rom_device() -+ -+For most devices and boards this is the correct thing. If you -+have a special case where you need to manage the migration of -+the backing memory yourself, you can call the functions: -+ - memory_region_init_ram_nomigrate() -+ - memory_region_init_rom_nomigrate() -+ - memory_region_init_rom_device_nomigrate() -+which only initialize the MemoryRegion and leave handling -+migration to the caller. -+ -+The functions: -+ - memory_region_init_resizeable_ram() -+ - memory_region_init_ram_from_file() -+ - memory_region_init_ram_from_fd() -+ - memory_region_init_ram_ptr() -+ - memory_region_init_ram_device_ptr() -+are for special cases only, and so they do not automatically -+register the backing memory for migration; the caller must -+manage migration if necessary. -+ -+Region names -+------------ -+ -+Regions are assigned names by the constructor. For most regions these are -+only used for debugging purposes, but RAM regions also use the name to identify -+live migration sections. This means that RAM region names need to have ABI -+stability. -+ -+Region lifecycle -+---------------- -+ -+A region is created by one of the memory_region_init*() functions and -+attached to an object, which acts as its owner or parent. QEMU ensures -+that the owner object remains alive as long as the region is visible to -+the guest, or as long as the region is in use by a virtual CPU or another -+device. For example, the owner object will not die between an -+address_space_map operation and the corresponding address_space_unmap. -+ -+After creation, a region can be added to an address space or a -+container with memory_region_add_subregion(), and removed using -+memory_region_del_subregion(). -+ -+Various region attributes (read-only, dirty logging, coalesced mmio, -+ioeventfd) can be changed during the region lifecycle. They take effect -+as soon as the region is made visible. This can be immediately, later, -+or never. -+ -+Destruction of a memory region happens automatically when the owner -+object dies. -+ -+If however the memory region is part of a dynamically allocated data -+structure, you should call object_unparent() to destroy the memory region -+before the data structure is freed. For an example see VFIOMSIXInfo -+and VFIOQuirk in hw/vfio/pci.c. -+ -+You must not destroy a memory region as long as it may be in use by a -+device or CPU. In order to do this, as a general rule do not create or -+destroy memory regions dynamically during a device's lifetime, and only -+call object_unparent() in the memory region owner's instance_finalize -+callback. The dynamically allocated data structure that contains the -+memory region then should obviously be freed in the instance_finalize -+callback as well. -+ -+If you break this rule, the following situation can happen: -+ -+- the memory region's owner had a reference taken via memory_region_ref -+ (for example by address_space_map) -+ -+- the region is unparented, and has no owner anymore -+ -+- when address_space_unmap is called, the reference to the memory region's -+ owner is leaked. -+ -+ -+There is an exception to the above rule: it is okay to call -+object_unparent at any time for an alias or a container region. It is -+therefore also okay to create or destroy alias and container regions -+dynamically during a device's lifetime. -+ -+This exceptional usage is valid because aliases and containers only help -+QEMU building the guest's memory map; they are never accessed directly. -+memory_region_ref and memory_region_unref are never called on aliases -+or containers, and the above situation then cannot happen. Exploiting -+this exception is rarely necessary, and therefore it is discouraged, -+but nevertheless it is used in a few places. -+ -+For regions that "have no owner" (NULL is passed at creation time), the -+machine object is actually used as the owner. Since instance_finalize is -+never called for the machine object, you must never call object_unparent -+on regions that have no owner, unless they are aliases or containers. -+ -+ -+Overlapping regions and priority -+-------------------------------- -+Usually, regions may not overlap each other; a memory address decodes into -+exactly one target. In some cases it is useful to allow regions to overlap, -+and sometimes to control which of an overlapping regions is visible to the -+guest. This is done with memory_region_add_subregion_overlap(), which -+allows the region to overlap any other region in the same container, and -+specifies a priority that allows the core to decide which of two regions at -+the same address are visible (highest wins). -+Priority values are signed, and the default value is zero. This means that -+you can use memory_region_add_subregion_overlap() both to specify a region -+that must sit 'above' any others (with a positive priority) and also a -+background region that sits 'below' others (with a negative priority). -+ -+If the higher priority region in an overlap is a container or alias, then -+the lower priority region will appear in any "holes" that the higher priority -+region has left by not mapping subregions to that area of its address range. -+(This applies recursively -- if the subregions are themselves containers or -+aliases that leave holes then the lower priority region will appear in these -+holes too.) -+ -+For example, suppose we have a container A of size 0x8000 with two subregions -+B and C. B is a container mapped at 0x2000, size 0x4000, priority 2; C is -+an MMIO region mapped at 0x0, size 0x6000, priority 1. B currently has two -+of its own subregions: D of size 0x1000 at offset 0 and E of size 0x1000 at -+offset 0x2000. As a diagram: -+ -+ 0 1000 2000 3000 4000 5000 6000 7000 8000 -+ |------|------|------|------|------|------|------|------| -+ A: [ ] -+ C: [CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC] -+ B: [ ] -+ D: [DDDDD] -+ E: [EEEEE] -+ -+The regions that will be seen within this address range then are: -+ [CCCCCCCCCCCC][DDDDD][CCCCC][EEEEE][CCCCC] -+ -+Since B has higher priority than C, its subregions appear in the flat map -+even where they overlap with C. In ranges where B has not mapped anything -+C's region appears. -+ -+If B had provided its own MMIO operations (ie it was not a pure container) -+then these would be used for any addresses in its range not handled by -+D or E, and the result would be: -+ [CCCCCCCCCCCC][DDDDD][BBBBB][EEEEE][BBBBB] -+ -+Priority values are local to a container, because the priorities of two -+regions are only compared when they are both children of the same container. -+This means that the device in charge of the container (typically modelling -+a bus or a memory controller) can use them to manage the interaction of -+its child regions without any side effects on other parts of the system. -+In the example above, the priorities of D and E are unimportant because -+they do not overlap each other. It is the relative priority of B and C -+that causes D and E to appear on top of C: D and E's priorities are never -+compared against the priority of C. -+ -+Visibility -+---------- -+The memory core uses the following rules to select a memory region when the -+guest accesses an address: -+ -+- all direct subregions of the root region are matched against the address, in -+ descending priority order -+ - if the address lies outside the region offset/size, the subregion is -+ discarded -+ - if the subregion is a leaf (RAM or MMIO), the search terminates, returning -+ this leaf region -+ - if the subregion is a container, the same algorithm is used within the -+ subregion (after the address is adjusted by the subregion offset) -+ - if the subregion is an alias, the search is continued at the alias target -+ (after the address is adjusted by the subregion offset and alias offset) -+ - if a recursive search within a container or alias subregion does not -+ find a match (because of a "hole" in the container's coverage of its -+ address range), then if this is a container with its own MMIO or RAM -+ backing the search terminates, returning the container itself. Otherwise -+ we continue with the next subregion in priority order -+- if none of the subregions match the address then the search terminates -+ with no match found -+ -+Example memory map -+------------------ -+ -+system_memory: container@0-2^48-1 -+ | -+ +---- lomem: alias@0-0xdfffffff ---> #ram (0-0xdfffffff) -+ | -+ +---- himem: alias@0x100000000-0x11fffffff ---> #ram (0xe0000000-0xffffffff) -+ | -+ +---- vga-window: alias@0xa0000-0xbffff ---> #pci (0xa0000-0xbffff) -+ | (prio 1) -+ | -+ +---- pci-hole: alias@0xe0000000-0xffffffff ---> #pci (0xe0000000-0xffffffff) -+ -+pci (0-2^32-1) -+ | -+ +--- vga-area: container@0xa0000-0xbffff -+ | | -+ | +--- alias@0x00000-0x7fff ---> #vram (0x010000-0x017fff) -+ | | -+ | +--- alias@0x08000-0xffff ---> #vram (0x020000-0x027fff) -+ | -+ +---- vram: ram@0xe1000000-0xe1ffffff -+ | -+ +---- vga-mmio: mmio@0xe2000000-0xe200ffff -+ -+ram: ram@0x00000000-0xffffffff -+ -+This is a (simplified) PC memory map. The 4GB RAM block is mapped into the -+system address space via two aliases: "lomem" is a 1:1 mapping of the first -+3.5GB; "himem" maps the last 0.5GB at address 4GB. This leaves 0.5GB for the -+so-called PCI hole, that allows a 32-bit PCI bus to exist in a system with -+4GB of memory. -+ -+The memory controller diverts addresses in the range 640K-768K to the PCI -+address space. This is modelled using the "vga-window" alias, mapped at a -+higher priority so it obscures the RAM at the same addresses. The vga window -+can be removed by programming the memory controller; this is modelled by -+removing the alias and exposing the RAM underneath. -+ -+The pci address space is not a direct child of the system address space, since -+we only want parts of it to be visible (we accomplish this using aliases). -+It has two subregions: vga-area models the legacy vga window and is occupied -+by two 32K memory banks pointing at two sections of the framebuffer. -+In addition the vram is mapped as a BAR at address e1000000, and an additional -+BAR containing MMIO registers is mapped after it. -+ -+Note that if the guest maps a BAR outside the PCI hole, it would not be -+visible as the pci-hole alias clips it to a 0.5GB range. -+ -+MMIO Operations -+--------------- -+ -+MMIO regions are provided with ->read() and ->write() callbacks, -+which are sufficient for most devices. Some devices change behaviour -+based on the attributes used for the memory transaction, or need -+to be able to respond that the access should provoke a bus error -+rather than completing successfully; those devices can use the -+->read_with_attrs() and ->write_with_attrs() callbacks instead. -+ -+In addition various constraints can be supplied to control how these -+callbacks are called: -+ -+ - .valid.min_access_size, .valid.max_access_size define the access sizes -+ (in bytes) which the device accepts; accesses outside this range will -+ have device and bus specific behaviour (ignored, or machine check) -+ - .valid.unaligned specifies that the *device being modelled* supports -+ unaligned accesses; if false, unaligned accesses will invoke the -+ appropriate bus or CPU specific behaviour. -+ - .impl.min_access_size, .impl.max_access_size define the access sizes -+ (in bytes) supported by the *implementation*; other access sizes will be -+ emulated using the ones available. For example a 4-byte write will be -+ emulated using four 1-byte writes, if .impl.max_access_size = 1. -+ - .impl.unaligned specifies that the *implementation* supports unaligned -+ accesses; if false, unaligned accesses will be emulated by two aligned -+ accesses. -diff --git a/docs/index.rst b/docs/index.rst -deleted file mode 100644 -index 3690955..0000000 ---- a/docs/index.rst -+++ /dev/null -@@ -1,15 +0,0 @@ --.. QEMU documentation master file, created by -- sphinx-quickstart on Thu Jan 31 16:40:14 2019. -- You can adapt this file completely to your liking, but it should at least -- contain the root `toctree` directive. -- --Welcome to QEMU's documentation! --================================ -- --.. toctree:: -- :maxdepth: 2 -- :caption: Contents: -- -- interop/index -- devel/index -- -diff --git a/docs/interop/conf.py b/docs/interop/conf.py -deleted file mode 100644 -index cf3c69d..0000000 ---- a/docs/interop/conf.py -+++ /dev/null -@@ -1,15 +0,0 @@ --# -*- coding: utf-8 -*- --# --# QEMU documentation build configuration file for the 'interop' manual. --# --# This includes the top level conf file and then makes any necessary tweaks. --import sys --import os -- --qemu_docdir = os.path.abspath("..") --parent_config = os.path.join(qemu_docdir, "conf.py") --exec(compile(open(parent_config, "rb").read(), parent_config, 'exec')) -- --# This slightly misuses the 'description', but is the best way to get --# the manual title to appear in the sidebar. --html_theme_options['description'] = u'System Emulation Management and Interoperability Guide' -diff --git a/docs/interop/index.rst b/docs/interop/index.rst -deleted file mode 100644 -index 2df977d..0000000 ---- a/docs/interop/index.rst -+++ /dev/null -@@ -1,18 +0,0 @@ --.. This is the top level page for the 'interop' manual. -- -- --QEMU System Emulation Management and Interoperability Guide --=========================================================== -- --This manual contains documents and specifications that are useful --for making QEMU interoperate with other software. -- --Contents: -- --.. toctree:: -- :maxdepth: 2 -- -- bitmaps -- live-block-operations -- pr-helper -- --- -1.8.3.1 - diff --git a/Revert-hw-display-ramfb-initialize-fw-config-space-w.patch b/Revert-hw-display-ramfb-initialize-fw-config-space-w.patch new file mode 100644 index 0000000000000000000000000000000000000000..ae80c71857121e3cedf70d14eb8127e64bb4a09f --- /dev/null +++ b/Revert-hw-display-ramfb-initialize-fw-config-space-w.patch @@ -0,0 +1,171 @@ +From 2fc979cb9d717161c1dfde69fa5fe495c1ab03e9 Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann +Date: Wed, 29 Apr 2020 13:52:31 +0200 +Subject: [PATCH 509/709] Revert "hw/display/ramfb: initialize fw-config space + with xres/ yres" + +This reverts commit f79081b4b71b72640bedd40a7cd76f864c8287f1. + +Patch has broken byteorder handling: RAMFBCfg fields are in bigendian +byteorder, the reset function doesn't care so native byteorder is used +instead. Given this went unnoticed so far the feature is obviously +unused, so just revert the patch. + +Cc: Hou Qiming +Signed-off-by: Gerd Hoffmann +Acked-by: Laszlo Ersek +Message-id: 20200429115236.28709-2-kraxel@redhat.com +--- + hw/display/ramfb-standalone.c | 12 +----------- + hw/display/ramfb.c | 16 +--------------- + hw/vfio/display.c | 4 ++-- + include/hw/display/ramfb.h | 2 +- + stubs/ramfb.c | 2 +- + 5 files changed, 6 insertions(+), 30 deletions(-) + +diff --git a/hw/display/ramfb-standalone.c b/hw/display/ramfb-standalone.c +index d76a9d0fe2..b18db97eeb 100644 +--- a/hw/display/ramfb-standalone.c ++++ b/hw/display/ramfb-standalone.c +@@ -3,7 +3,6 @@ + #include "qemu/module.h" + #include "hw/loader.h" + #include "hw/qdev-properties.h" +-#include "hw/isa/isa.h" + #include "hw/display/ramfb.h" + #include "ui/console.h" + +@@ -13,8 +12,6 @@ typedef struct RAMFBStandaloneState { + SysBusDevice parent_obj; + QemuConsole *con; + RAMFBState *state; +- uint32_t xres; +- uint32_t yres; + } RAMFBStandaloneState; + + static void display_update_wrapper(void *dev) +@@ -37,22 +34,15 @@ static void ramfb_realizefn(DeviceState *dev, Error **errp) + RAMFBStandaloneState *ramfb = RAMFB(dev); + + ramfb->con = graphic_console_init(dev, 0, &wrapper_ops, dev); +- ramfb->state = ramfb_setup(dev, errp); ++ ramfb->state = ramfb_setup(errp); + } + +-static Property ramfb_properties[] = { +- DEFINE_PROP_UINT32("xres", RAMFBStandaloneState, xres, 0), +- DEFINE_PROP_UINT32("yres", RAMFBStandaloneState, yres, 0), +- DEFINE_PROP_END_OF_LIST(), +-}; +- + static void ramfb_class_initfn(ObjectClass *klass, void *data) + { + DeviceClass *dc = DEVICE_CLASS(klass); + + set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories); + dc->realize = ramfb_realizefn; +- device_class_set_props(dc, ramfb_properties); + dc->desc = "ram framebuffer standalone device"; + dc->user_creatable = true; + } +diff --git a/hw/display/ramfb.c b/hw/display/ramfb.c +index 7ba07c80f6..bd4746dc17 100644 +--- a/hw/display/ramfb.c ++++ b/hw/display/ramfb.c +@@ -13,7 +13,6 @@ + + #include "qemu/osdep.h" + #include "qapi/error.h" +-#include "qemu/option.h" + #include "hw/loader.h" + #include "hw/display/ramfb.h" + #include "ui/console.h" +@@ -31,7 +30,6 @@ struct QEMU_PACKED RAMFBCfg { + struct RAMFBState { + DisplaySurface *ds; + uint32_t width, height; +- uint32_t starting_width, starting_height; + struct RAMFBCfg cfg; + bool locked; + }; +@@ -117,11 +115,9 @@ static void ramfb_reset(void *opaque) + RAMFBState *s = (RAMFBState *)opaque; + s->locked = false; + memset(&s->cfg, 0, sizeof(s->cfg)); +- s->cfg.width = s->starting_width; +- s->cfg.height = s->starting_height; + } + +-RAMFBState *ramfb_setup(DeviceState* dev, Error **errp) ++RAMFBState *ramfb_setup(Error **errp) + { + FWCfgState *fw_cfg = fw_cfg_find(); + RAMFBState *s; +@@ -133,16 +129,6 @@ RAMFBState *ramfb_setup(DeviceState* dev, Error **errp) + + s = g_new0(RAMFBState, 1); + +- const char *s_fb_width = qemu_opt_get(dev->opts, "xres"); +- const char *s_fb_height = qemu_opt_get(dev->opts, "yres"); +- if (s_fb_width) { +- s->cfg.width = atoi(s_fb_width); +- s->starting_width = s->cfg.width; +- } +- if (s_fb_height) { +- s->cfg.height = atoi(s_fb_height); +- s->starting_height = s->cfg.height; +- } + s->locked = false; + + rom_add_vga("vgabios-ramfb.bin"); +diff --git a/hw/vfio/display.c b/hw/vfio/display.c +index f4977c66e1..a57a22674d 100644 +--- a/hw/vfio/display.c ++++ b/hw/vfio/display.c +@@ -353,7 +353,7 @@ static int vfio_display_dmabuf_init(VFIOPCIDevice *vdev, Error **errp) + &vfio_display_dmabuf_ops, + vdev); + if (vdev->enable_ramfb) { +- vdev->dpy->ramfb = ramfb_setup(DEVICE(vdev), errp); ++ vdev->dpy->ramfb = ramfb_setup(errp); + } + vfio_display_edid_init(vdev); + return 0; +@@ -479,7 +479,7 @@ static int vfio_display_region_init(VFIOPCIDevice *vdev, Error **errp) + &vfio_display_region_ops, + vdev); + if (vdev->enable_ramfb) { +- vdev->dpy->ramfb = ramfb_setup(DEVICE(vdev), errp); ++ vdev->dpy->ramfb = ramfb_setup(errp); + } + return 0; + } +diff --git a/include/hw/display/ramfb.h b/include/hw/display/ramfb.h +index f6c2de93b2..b33a2c467b 100644 +--- a/include/hw/display/ramfb.h ++++ b/include/hw/display/ramfb.h +@@ -4,7 +4,7 @@ + /* ramfb.c */ + typedef struct RAMFBState RAMFBState; + void ramfb_display_update(QemuConsole *con, RAMFBState *s); +-RAMFBState *ramfb_setup(DeviceState *dev, Error **errp); ++RAMFBState *ramfb_setup(Error **errp); + + /* ramfb-standalone.c */ + #define TYPE_RAMFB_DEVICE "ramfb" +diff --git a/stubs/ramfb.c b/stubs/ramfb.c +index 0799093a5d..48143f3354 100644 +--- a/stubs/ramfb.c ++++ b/stubs/ramfb.c +@@ -6,7 +6,7 @@ void ramfb_display_update(QemuConsole *con, RAMFBState *s) + { + } + +-RAMFBState *ramfb_setup(DeviceState* dev, Error **errp) ++RAMFBState *ramfb_setup(Error **errp) + { + error_setg(errp, "ramfb support not available"); + return NULL; +-- +2.23.0 + diff --git a/Revert-hw-display-ramfb-lock-guest-resolution-after-.patch b/Revert-hw-display-ramfb-lock-guest-resolution-after-.patch new file mode 100644 index 0000000000000000000000000000000000000000..63facb58ab846f3b4396b6a8952d4d1a207f0cf4 --- /dev/null +++ b/Revert-hw-display-ramfb-lock-guest-resolution-after-.patch @@ -0,0 +1,92 @@ +From c326eedc7584b94f6f9f3b8ba61a6e9ff04ad681 Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann +Date: Wed, 29 Apr 2020 13:52:32 +0200 +Subject: [PATCH 510/709] Revert "hw/display/ramfb: lock guest resolution after + it's set" + +This reverts commit a9e0cb67b7f4c485755659f9b764c38b5f970de4. + +This breaks OVMF. Reproducer: Just hit 'ESC' at early boot to enter +firmware setup. OVMF wants switch from (default) 800x600 to 640x480 for +that, and this patch blocks it. + +Cc: Hou Qiming +Signed-off-by: Gerd Hoffmann +Reviewed-by: Laszlo Ersek +Message-id: 20200429115236.28709-3-kraxel@redhat.com +--- + hw/display/ramfb.c | 26 ++++---------------------- + 1 file changed, 4 insertions(+), 22 deletions(-) + +diff --git a/hw/display/ramfb.c b/hw/display/ramfb.c +index bd4746dc17..9d41c2ad28 100644 +--- a/hw/display/ramfb.c ++++ b/hw/display/ramfb.c +@@ -31,7 +31,6 @@ struct RAMFBState { + DisplaySurface *ds; + uint32_t width, height; + struct RAMFBCfg cfg; +- bool locked; + }; + + static void ramfb_unmap_display_surface(pixman_image_t *image, void *unused) +@@ -72,25 +71,18 @@ static DisplaySurface *ramfb_create_display_surface(int width, int height, + static void ramfb_fw_cfg_write(void *dev, off_t offset, size_t len) + { + RAMFBState *s = dev; +- uint32_t fourcc, format, width, height; ++ uint32_t fourcc, format; + hwaddr stride, addr; + +- width = be32_to_cpu(s->cfg.width); +- height = be32_to_cpu(s->cfg.height); ++ s->width = be32_to_cpu(s->cfg.width); ++ s->height = be32_to_cpu(s->cfg.height); + stride = be32_to_cpu(s->cfg.stride); + fourcc = be32_to_cpu(s->cfg.fourcc); + addr = be64_to_cpu(s->cfg.addr); + format = qemu_drm_format_to_pixman(fourcc); + + fprintf(stderr, "%s: %dx%d @ 0x%" PRIx64 "\n", __func__, +- width, height, addr); +- if (s->locked) { +- fprintf(stderr, "%s: resolution locked, change rejected\n", __func__); +- return; +- } +- s->locked = true; +- s->width = width; +- s->height = height; ++ s->width, s->height, addr); + s->ds = ramfb_create_display_surface(s->width, s->height, + format, stride, addr); + } +@@ -110,13 +102,6 @@ void ramfb_display_update(QemuConsole *con, RAMFBState *s) + dpy_gfx_update_full(con); + } + +-static void ramfb_reset(void *opaque) +-{ +- RAMFBState *s = (RAMFBState *)opaque; +- s->locked = false; +- memset(&s->cfg, 0, sizeof(s->cfg)); +-} +- + RAMFBState *ramfb_setup(Error **errp) + { + FWCfgState *fw_cfg = fw_cfg_find(); +@@ -129,12 +114,9 @@ RAMFBState *ramfb_setup(Error **errp) + + s = g_new0(RAMFBState, 1); + +- s->locked = false; +- + rom_add_vga("vgabios-ramfb.bin"); + fw_cfg_add_file_callback(fw_cfg, "etc/ramfb", + NULL, ramfb_fw_cfg_write, s, + &s->cfg, sizeof(s->cfg), false); +- qemu_register_reset(ramfb_reset, s); + return s; + } +-- +2.23.0 + diff --git a/Typo-Correct-the-name-of-CPU-hotplug-memory-region.patch b/Typo-Correct-the-name-of-CPU-hotplug-memory-region.patch new file mode 100644 index 0000000000000000000000000000000000000000..5b8d9af9c57adfa011a25bb7a2771ba31d99ae48 --- /dev/null +++ b/Typo-Correct-the-name-of-CPU-hotplug-memory-region.patch @@ -0,0 +1,31 @@ +From 119a2ef1dce90ffa2b86a43fb190027fcc5cdb9a Mon Sep 17 00:00:00 2001 +From: Keqian Zhu +Date: Mon, 13 Apr 2020 17:15:52 +0800 +Subject: [PATCH 098/709] Typo: Correct the name of CPU hotplug memory region + +Replace "acpi-mem-hotplug" with "acpi-cpu-hotplug" + +Signed-off-by: Keqian Zhu +Message-id: 20200413091552.62748-4-zhukeqian1@huawei.com +Reviewed-by: Peter Maydell +Signed-off-by: Peter Maydell +--- + hw/acpi/cpu.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/hw/acpi/cpu.c b/hw/acpi/cpu.c +index e2c957ce00..3d6a500fb7 100644 +--- a/hw/acpi/cpu.c ++++ b/hw/acpi/cpu.c +@@ -222,7 +222,7 @@ void cpu_hotplug_hw_init(MemoryRegion *as, Object *owner, + state->devs[i].arch_id = id_list->cpus[i].arch_id; + } + memory_region_init_io(&state->ctrl_reg, owner, &cpu_hotplug_ops, state, +- "acpi-mem-hotplug", ACPI_CPU_HOTPLUG_REG_LEN); ++ "acpi-cpu-hotplug", ACPI_CPU_HOTPLUG_REG_LEN); + memory_region_add_subregion(as, base_addr, &state->ctrl_reg); + } + +-- +2.23.0 + diff --git a/accel-tcg-Add-block-comment-for-probe_access.patch b/accel-tcg-Add-block-comment-for-probe_access.patch new file mode 100644 index 0000000000000000000000000000000000000000..31031328a56698ad9c63f663fc147f7de7dd05ff --- /dev/null +++ b/accel-tcg-Add-block-comment-for-probe_access.patch @@ -0,0 +1,44 @@ +From 857129b34190a4c2e782006dc255352a6cd3934b Mon Sep 17 00:00:00 2001 +From: Richard Henderson +Date: Fri, 8 May 2020 08:43:43 -0700 +Subject: [PATCH 367/709] accel/tcg: Add block comment for probe_access + +Reviewed-by: Peter Maydell +Signed-off-by: Richard Henderson +Message-id: 20200508154359.7494-4-richard.henderson@linaro.org +Signed-off-by: Peter Maydell +--- + include/exec/exec-all.h | 17 +++++++++++++++++ + 1 file changed, 17 insertions(+) + +diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h +index 350c4b451b..d656a1f05c 100644 +--- a/include/exec/exec-all.h ++++ b/include/exec/exec-all.h +@@ -330,6 +330,23 @@ static inline void tlb_flush_by_mmuidx_all_cpus_synced(CPUState *cpu, + { + } + #endif ++/** ++ * probe_access: ++ * @env: CPUArchState ++ * @addr: guest virtual address to look up ++ * @size: size of the access ++ * @access_type: read, write or execute permission ++ * @mmu_idx: MMU index to use for lookup ++ * @retaddr: return address for unwinding ++ * ++ * Look up the guest virtual address @addr. Raise an exception if the ++ * page does not satisfy @access_type. Raise an exception if the ++ * access (@addr, @size) hits a watchpoint. For writes, mark a clean ++ * page as dirty. ++ * ++ * Finally, return the host address for a page that is backed by RAM, ++ * or NULL if the page requires I/O. ++ */ + void *probe_access(CPUArchState *env, target_ulong addr, int size, + MMUAccessType access_type, int mmu_idx, uintptr_t retaddr); + +-- +2.23.0 + diff --git a/accel-tcg-Add-endian-specific-cpu_-ld-st-operations.patch b/accel-tcg-Add-endian-specific-cpu_-ld-st-operations.patch new file mode 100644 index 0000000000000000000000000000000000000000..ee50708033f848031f457d522315d40a4add5940 --- /dev/null +++ b/accel-tcg-Add-endian-specific-cpu_-ld-st-operations.patch @@ -0,0 +1,1127 @@ +From b9e60257c10a0116318dc4e23148f7e4d85811a8 Mon Sep 17 00:00:00 2001 +From: Richard Henderson +Date: Fri, 8 May 2020 08:43:46 -0700 +Subject: [PATCH 370/709] accel/tcg: Add endian-specific cpu_{ld, st}* + operations + +We currently have target-endian versions of these operations, +but no easy way to force a specific endianness. This can be +helpful if the target has endian-specific operations, or a mode +that swaps endianness. + +Reviewed-by: Peter Maydell +Signed-off-by: Richard Henderson +Message-id: 20200508154359.7494-7-richard.henderson@linaro.org +Signed-off-by: Peter Maydell +--- + accel/tcg/cputlb.c | 236 +++++++++++++++++++++++-------- + accel/tcg/user-exec.c | 211 +++++++++++++++++++++++----- + docs/devel/loads-stores.rst | 39 ++++-- + include/exec/cpu_ldst.h | 271 +++++++++++++++++++++++++++--------- + 4 files changed, 581 insertions(+), 176 deletions(-) + +diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c +index c708e9785f..eb2cf9de5e 100644 +--- a/accel/tcg/cputlb.c ++++ b/accel/tcg/cputlb.c +@@ -1772,36 +1772,54 @@ int cpu_ldsb_mmuidx_ra(CPUArchState *env, abi_ptr addr, + full_ldub_mmu); + } + +-uint32_t cpu_lduw_mmuidx_ra(CPUArchState *env, abi_ptr addr, +- int mmu_idx, uintptr_t ra) ++uint32_t cpu_lduw_be_mmuidx_ra(CPUArchState *env, abi_ptr addr, ++ int mmu_idx, uintptr_t ra) + { +- return cpu_load_helper(env, addr, mmu_idx, ra, MO_TEUW, +- MO_TE == MO_LE +- ? full_le_lduw_mmu : full_be_lduw_mmu); ++ return cpu_load_helper(env, addr, mmu_idx, ra, MO_BEUW, full_be_lduw_mmu); + } + +-int cpu_ldsw_mmuidx_ra(CPUArchState *env, abi_ptr addr, +- int mmu_idx, uintptr_t ra) ++int cpu_ldsw_be_mmuidx_ra(CPUArchState *env, abi_ptr addr, ++ int mmu_idx, uintptr_t ra) ++{ ++ return (int16_t)cpu_load_helper(env, addr, mmu_idx, ra, MO_BESW, ++ full_be_lduw_mmu); ++} ++ ++uint32_t cpu_ldl_be_mmuidx_ra(CPUArchState *env, abi_ptr addr, ++ int mmu_idx, uintptr_t ra) ++{ ++ return cpu_load_helper(env, addr, mmu_idx, ra, MO_BEUL, full_be_ldul_mmu); ++} ++ ++uint64_t cpu_ldq_be_mmuidx_ra(CPUArchState *env, abi_ptr addr, ++ int mmu_idx, uintptr_t ra) ++{ ++ return cpu_load_helper(env, addr, mmu_idx, ra, MO_BEQ, helper_be_ldq_mmu); ++} ++ ++uint32_t cpu_lduw_le_mmuidx_ra(CPUArchState *env, abi_ptr addr, ++ int mmu_idx, uintptr_t ra) ++{ ++ return cpu_load_helper(env, addr, mmu_idx, ra, MO_LEUW, full_le_lduw_mmu); ++} ++ ++int cpu_ldsw_le_mmuidx_ra(CPUArchState *env, abi_ptr addr, ++ int mmu_idx, uintptr_t ra) + { +- return (int16_t)cpu_load_helper(env, addr, mmu_idx, ra, MO_TESW, +- MO_TE == MO_LE +- ? full_le_lduw_mmu : full_be_lduw_mmu); ++ return (int16_t)cpu_load_helper(env, addr, mmu_idx, ra, MO_LESW, ++ full_le_lduw_mmu); + } + +-uint32_t cpu_ldl_mmuidx_ra(CPUArchState *env, abi_ptr addr, +- int mmu_idx, uintptr_t ra) ++uint32_t cpu_ldl_le_mmuidx_ra(CPUArchState *env, abi_ptr addr, ++ int mmu_idx, uintptr_t ra) + { +- return cpu_load_helper(env, addr, mmu_idx, ra, MO_TEUL, +- MO_TE == MO_LE +- ? full_le_ldul_mmu : full_be_ldul_mmu); ++ return cpu_load_helper(env, addr, mmu_idx, ra, MO_LEUL, full_le_ldul_mmu); + } + +-uint64_t cpu_ldq_mmuidx_ra(CPUArchState *env, abi_ptr addr, +- int mmu_idx, uintptr_t ra) ++uint64_t cpu_ldq_le_mmuidx_ra(CPUArchState *env, abi_ptr addr, ++ int mmu_idx, uintptr_t ra) + { +- return cpu_load_helper(env, addr, mmu_idx, ra, MO_TEQ, +- MO_TE == MO_LE +- ? helper_le_ldq_mmu : helper_be_ldq_mmu); ++ return cpu_load_helper(env, addr, mmu_idx, ra, MO_LEQ, helper_le_ldq_mmu); + } + + uint32_t cpu_ldub_data_ra(CPUArchState *env, target_ulong ptr, +@@ -1815,25 +1833,50 @@ int cpu_ldsb_data_ra(CPUArchState *env, target_ulong ptr, uintptr_t retaddr) + return cpu_ldsb_mmuidx_ra(env, ptr, cpu_mmu_index(env, false), retaddr); + } + +-uint32_t cpu_lduw_data_ra(CPUArchState *env, target_ulong ptr, +- uintptr_t retaddr) ++uint32_t cpu_lduw_be_data_ra(CPUArchState *env, target_ulong ptr, ++ uintptr_t retaddr) ++{ ++ return cpu_lduw_be_mmuidx_ra(env, ptr, cpu_mmu_index(env, false), retaddr); ++} ++ ++int cpu_ldsw_be_data_ra(CPUArchState *env, target_ulong ptr, uintptr_t retaddr) + { +- return cpu_lduw_mmuidx_ra(env, ptr, cpu_mmu_index(env, false), retaddr); ++ return cpu_ldsw_be_mmuidx_ra(env, ptr, cpu_mmu_index(env, false), retaddr); + } + +-int cpu_ldsw_data_ra(CPUArchState *env, target_ulong ptr, uintptr_t retaddr) ++uint32_t cpu_ldl_be_data_ra(CPUArchState *env, target_ulong ptr, ++ uintptr_t retaddr) + { +- return cpu_ldsw_mmuidx_ra(env, ptr, cpu_mmu_index(env, false), retaddr); ++ return cpu_ldl_be_mmuidx_ra(env, ptr, cpu_mmu_index(env, false), retaddr); + } + +-uint32_t cpu_ldl_data_ra(CPUArchState *env, target_ulong ptr, uintptr_t retaddr) ++uint64_t cpu_ldq_be_data_ra(CPUArchState *env, target_ulong ptr, ++ uintptr_t retaddr) + { +- return cpu_ldl_mmuidx_ra(env, ptr, cpu_mmu_index(env, false), retaddr); ++ return cpu_ldq_be_mmuidx_ra(env, ptr, cpu_mmu_index(env, false), retaddr); + } + +-uint64_t cpu_ldq_data_ra(CPUArchState *env, target_ulong ptr, uintptr_t retaddr) ++uint32_t cpu_lduw_le_data_ra(CPUArchState *env, target_ulong ptr, ++ uintptr_t retaddr) + { +- return cpu_ldq_mmuidx_ra(env, ptr, cpu_mmu_index(env, false), retaddr); ++ return cpu_lduw_le_mmuidx_ra(env, ptr, cpu_mmu_index(env, false), retaddr); ++} ++ ++int cpu_ldsw_le_data_ra(CPUArchState *env, target_ulong ptr, uintptr_t retaddr) ++{ ++ return cpu_ldsw_le_mmuidx_ra(env, ptr, cpu_mmu_index(env, false), retaddr); ++} ++ ++uint32_t cpu_ldl_le_data_ra(CPUArchState *env, target_ulong ptr, ++ uintptr_t retaddr) ++{ ++ return cpu_ldl_le_mmuidx_ra(env, ptr, cpu_mmu_index(env, false), retaddr); ++} ++ ++uint64_t cpu_ldq_le_data_ra(CPUArchState *env, target_ulong ptr, ++ uintptr_t retaddr) ++{ ++ return cpu_ldq_le_mmuidx_ra(env, ptr, cpu_mmu_index(env, false), retaddr); + } + + uint32_t cpu_ldub_data(CPUArchState *env, target_ulong ptr) +@@ -1846,24 +1889,44 @@ int cpu_ldsb_data(CPUArchState *env, target_ulong ptr) + return cpu_ldsb_data_ra(env, ptr, 0); + } + +-uint32_t cpu_lduw_data(CPUArchState *env, target_ulong ptr) ++uint32_t cpu_lduw_be_data(CPUArchState *env, target_ulong ptr) ++{ ++ return cpu_lduw_be_data_ra(env, ptr, 0); ++} ++ ++int cpu_ldsw_be_data(CPUArchState *env, target_ulong ptr) ++{ ++ return cpu_ldsw_be_data_ra(env, ptr, 0); ++} ++ ++uint32_t cpu_ldl_be_data(CPUArchState *env, target_ulong ptr) ++{ ++ return cpu_ldl_be_data_ra(env, ptr, 0); ++} ++ ++uint64_t cpu_ldq_be_data(CPUArchState *env, target_ulong ptr) + { +- return cpu_lduw_data_ra(env, ptr, 0); ++ return cpu_ldq_be_data_ra(env, ptr, 0); + } + +-int cpu_ldsw_data(CPUArchState *env, target_ulong ptr) ++uint32_t cpu_lduw_le_data(CPUArchState *env, target_ulong ptr) + { +- return cpu_ldsw_data_ra(env, ptr, 0); ++ return cpu_lduw_le_data_ra(env, ptr, 0); + } + +-uint32_t cpu_ldl_data(CPUArchState *env, target_ulong ptr) ++int cpu_ldsw_le_data(CPUArchState *env, target_ulong ptr) + { +- return cpu_ldl_data_ra(env, ptr, 0); ++ return cpu_ldsw_le_data_ra(env, ptr, 0); + } + +-uint64_t cpu_ldq_data(CPUArchState *env, target_ulong ptr) ++uint32_t cpu_ldl_le_data(CPUArchState *env, target_ulong ptr) + { +- return cpu_ldq_data_ra(env, ptr, 0); ++ return cpu_ldl_le_data_ra(env, ptr, 0); ++} ++ ++uint64_t cpu_ldq_le_data(CPUArchState *env, target_ulong ptr) ++{ ++ return cpu_ldq_le_data_ra(env, ptr, 0); + } + + /* +@@ -2121,22 +2184,40 @@ void cpu_stb_mmuidx_ra(CPUArchState *env, target_ulong addr, uint32_t val, + cpu_store_helper(env, addr, val, mmu_idx, retaddr, MO_UB); + } + +-void cpu_stw_mmuidx_ra(CPUArchState *env, target_ulong addr, uint32_t val, +- int mmu_idx, uintptr_t retaddr) ++void cpu_stw_be_mmuidx_ra(CPUArchState *env, target_ulong addr, uint32_t val, ++ int mmu_idx, uintptr_t retaddr) + { +- cpu_store_helper(env, addr, val, mmu_idx, retaddr, MO_TEUW); ++ cpu_store_helper(env, addr, val, mmu_idx, retaddr, MO_BEUW); + } + +-void cpu_stl_mmuidx_ra(CPUArchState *env, target_ulong addr, uint32_t val, +- int mmu_idx, uintptr_t retaddr) ++void cpu_stl_be_mmuidx_ra(CPUArchState *env, target_ulong addr, uint32_t val, ++ int mmu_idx, uintptr_t retaddr) + { +- cpu_store_helper(env, addr, val, mmu_idx, retaddr, MO_TEUL); ++ cpu_store_helper(env, addr, val, mmu_idx, retaddr, MO_BEUL); + } + +-void cpu_stq_mmuidx_ra(CPUArchState *env, target_ulong addr, uint64_t val, +- int mmu_idx, uintptr_t retaddr) ++void cpu_stq_be_mmuidx_ra(CPUArchState *env, target_ulong addr, uint64_t val, ++ int mmu_idx, uintptr_t retaddr) ++{ ++ cpu_store_helper(env, addr, val, mmu_idx, retaddr, MO_BEQ); ++} ++ ++void cpu_stw_le_mmuidx_ra(CPUArchState *env, target_ulong addr, uint32_t val, ++ int mmu_idx, uintptr_t retaddr) + { +- cpu_store_helper(env, addr, val, mmu_idx, retaddr, MO_TEQ); ++ cpu_store_helper(env, addr, val, mmu_idx, retaddr, MO_LEUW); ++} ++ ++void cpu_stl_le_mmuidx_ra(CPUArchState *env, target_ulong addr, uint32_t val, ++ int mmu_idx, uintptr_t retaddr) ++{ ++ cpu_store_helper(env, addr, val, mmu_idx, retaddr, MO_LEUL); ++} ++ ++void cpu_stq_le_mmuidx_ra(CPUArchState *env, target_ulong addr, uint64_t val, ++ int mmu_idx, uintptr_t retaddr) ++{ ++ cpu_store_helper(env, addr, val, mmu_idx, retaddr, MO_LEQ); + } + + void cpu_stb_data_ra(CPUArchState *env, target_ulong ptr, +@@ -2145,22 +2226,40 @@ void cpu_stb_data_ra(CPUArchState *env, target_ulong ptr, + cpu_stb_mmuidx_ra(env, ptr, val, cpu_mmu_index(env, false), retaddr); + } + +-void cpu_stw_data_ra(CPUArchState *env, target_ulong ptr, +- uint32_t val, uintptr_t retaddr) ++void cpu_stw_be_data_ra(CPUArchState *env, target_ulong ptr, ++ uint32_t val, uintptr_t retaddr) + { +- cpu_stw_mmuidx_ra(env, ptr, val, cpu_mmu_index(env, false), retaddr); ++ cpu_stw_be_mmuidx_ra(env, ptr, val, cpu_mmu_index(env, false), retaddr); + } + +-void cpu_stl_data_ra(CPUArchState *env, target_ulong ptr, +- uint32_t val, uintptr_t retaddr) ++void cpu_stl_be_data_ra(CPUArchState *env, target_ulong ptr, ++ uint32_t val, uintptr_t retaddr) + { +- cpu_stl_mmuidx_ra(env, ptr, val, cpu_mmu_index(env, false), retaddr); ++ cpu_stl_be_mmuidx_ra(env, ptr, val, cpu_mmu_index(env, false), retaddr); + } + +-void cpu_stq_data_ra(CPUArchState *env, target_ulong ptr, +- uint64_t val, uintptr_t retaddr) ++void cpu_stq_be_data_ra(CPUArchState *env, target_ulong ptr, ++ uint64_t val, uintptr_t retaddr) + { +- cpu_stq_mmuidx_ra(env, ptr, val, cpu_mmu_index(env, false), retaddr); ++ cpu_stq_be_mmuidx_ra(env, ptr, val, cpu_mmu_index(env, false), retaddr); ++} ++ ++void cpu_stw_le_data_ra(CPUArchState *env, target_ulong ptr, ++ uint32_t val, uintptr_t retaddr) ++{ ++ cpu_stw_le_mmuidx_ra(env, ptr, val, cpu_mmu_index(env, false), retaddr); ++} ++ ++void cpu_stl_le_data_ra(CPUArchState *env, target_ulong ptr, ++ uint32_t val, uintptr_t retaddr) ++{ ++ cpu_stl_le_mmuidx_ra(env, ptr, val, cpu_mmu_index(env, false), retaddr); ++} ++ ++void cpu_stq_le_data_ra(CPUArchState *env, target_ulong ptr, ++ uint64_t val, uintptr_t retaddr) ++{ ++ cpu_stq_le_mmuidx_ra(env, ptr, val, cpu_mmu_index(env, false), retaddr); + } + + void cpu_stb_data(CPUArchState *env, target_ulong ptr, uint32_t val) +@@ -2168,19 +2267,34 @@ void cpu_stb_data(CPUArchState *env, target_ulong ptr, uint32_t val) + cpu_stb_data_ra(env, ptr, val, 0); + } + +-void cpu_stw_data(CPUArchState *env, target_ulong ptr, uint32_t val) ++void cpu_stw_be_data(CPUArchState *env, target_ulong ptr, uint32_t val) ++{ ++ cpu_stw_be_data_ra(env, ptr, val, 0); ++} ++ ++void cpu_stl_be_data(CPUArchState *env, target_ulong ptr, uint32_t val) ++{ ++ cpu_stl_be_data_ra(env, ptr, val, 0); ++} ++ ++void cpu_stq_be_data(CPUArchState *env, target_ulong ptr, uint64_t val) ++{ ++ cpu_stq_be_data_ra(env, ptr, val, 0); ++} ++ ++void cpu_stw_le_data(CPUArchState *env, target_ulong ptr, uint32_t val) + { +- cpu_stw_data_ra(env, ptr, val, 0); ++ cpu_stw_le_data_ra(env, ptr, val, 0); + } + +-void cpu_stl_data(CPUArchState *env, target_ulong ptr, uint32_t val) ++void cpu_stl_le_data(CPUArchState *env, target_ulong ptr, uint32_t val) + { +- cpu_stl_data_ra(env, ptr, val, 0); ++ cpu_stl_le_data_ra(env, ptr, val, 0); + } + +-void cpu_stq_data(CPUArchState *env, target_ulong ptr, uint64_t val) ++void cpu_stq_le_data(CPUArchState *env, target_ulong ptr, uint64_t val) + { +- cpu_stq_data_ra(env, ptr, val, 0); ++ cpu_stq_le_data_ra(env, ptr, val, 0); + } + + /* First set of helpers allows passing in of OI and RETADDR. This makes +diff --git a/accel/tcg/user-exec.c b/accel/tcg/user-exec.c +index 987342c50c..52359949df 100644 +--- a/accel/tcg/user-exec.c ++++ b/accel/tcg/user-exec.c +@@ -783,46 +783,90 @@ int cpu_ldsb_data(CPUArchState *env, abi_ptr ptr) + return ret; + } + +-uint32_t cpu_lduw_data(CPUArchState *env, abi_ptr ptr) ++uint32_t cpu_lduw_be_data(CPUArchState *env, abi_ptr ptr) + { + uint32_t ret; +- uint16_t meminfo = trace_mem_get_info(MO_TEUW, MMU_USER_IDX, false); ++ uint16_t meminfo = trace_mem_get_info(MO_BEUW, MMU_USER_IDX, false); + + trace_guest_mem_before_exec(env_cpu(env), ptr, meminfo); +- ret = lduw_p(g2h(ptr)); ++ ret = lduw_be_p(g2h(ptr)); + qemu_plugin_vcpu_mem_cb(env_cpu(env), ptr, meminfo); + return ret; + } + +-int cpu_ldsw_data(CPUArchState *env, abi_ptr ptr) ++int cpu_ldsw_be_data(CPUArchState *env, abi_ptr ptr) + { + int ret; +- uint16_t meminfo = trace_mem_get_info(MO_TESW, MMU_USER_IDX, false); ++ uint16_t meminfo = trace_mem_get_info(MO_BESW, MMU_USER_IDX, false); + + trace_guest_mem_before_exec(env_cpu(env), ptr, meminfo); +- ret = ldsw_p(g2h(ptr)); ++ ret = ldsw_be_p(g2h(ptr)); + qemu_plugin_vcpu_mem_cb(env_cpu(env), ptr, meminfo); + return ret; + } + +-uint32_t cpu_ldl_data(CPUArchState *env, abi_ptr ptr) ++uint32_t cpu_ldl_be_data(CPUArchState *env, abi_ptr ptr) + { + uint32_t ret; +- uint16_t meminfo = trace_mem_get_info(MO_TEUL, MMU_USER_IDX, false); ++ uint16_t meminfo = trace_mem_get_info(MO_BEUL, MMU_USER_IDX, false); + + trace_guest_mem_before_exec(env_cpu(env), ptr, meminfo); +- ret = ldl_p(g2h(ptr)); ++ ret = ldl_be_p(g2h(ptr)); + qemu_plugin_vcpu_mem_cb(env_cpu(env), ptr, meminfo); + return ret; + } + +-uint64_t cpu_ldq_data(CPUArchState *env, abi_ptr ptr) ++uint64_t cpu_ldq_be_data(CPUArchState *env, abi_ptr ptr) + { + uint64_t ret; +- uint16_t meminfo = trace_mem_get_info(MO_TEQ, MMU_USER_IDX, false); ++ uint16_t meminfo = trace_mem_get_info(MO_BEQ, MMU_USER_IDX, false); + + trace_guest_mem_before_exec(env_cpu(env), ptr, meminfo); +- ret = ldq_p(g2h(ptr)); ++ ret = ldq_be_p(g2h(ptr)); ++ qemu_plugin_vcpu_mem_cb(env_cpu(env), ptr, meminfo); ++ return ret; ++} ++ ++uint32_t cpu_lduw_le_data(CPUArchState *env, abi_ptr ptr) ++{ ++ uint32_t ret; ++ uint16_t meminfo = trace_mem_get_info(MO_LEUW, MMU_USER_IDX, false); ++ ++ trace_guest_mem_before_exec(env_cpu(env), ptr, meminfo); ++ ret = lduw_le_p(g2h(ptr)); ++ qemu_plugin_vcpu_mem_cb(env_cpu(env), ptr, meminfo); ++ return ret; ++} ++ ++int cpu_ldsw_le_data(CPUArchState *env, abi_ptr ptr) ++{ ++ int ret; ++ uint16_t meminfo = trace_mem_get_info(MO_LESW, MMU_USER_IDX, false); ++ ++ trace_guest_mem_before_exec(env_cpu(env), ptr, meminfo); ++ ret = ldsw_le_p(g2h(ptr)); ++ qemu_plugin_vcpu_mem_cb(env_cpu(env), ptr, meminfo); ++ return ret; ++} ++ ++uint32_t cpu_ldl_le_data(CPUArchState *env, abi_ptr ptr) ++{ ++ uint32_t ret; ++ uint16_t meminfo = trace_mem_get_info(MO_LEUL, MMU_USER_IDX, false); ++ ++ trace_guest_mem_before_exec(env_cpu(env), ptr, meminfo); ++ ret = ldl_le_p(g2h(ptr)); ++ qemu_plugin_vcpu_mem_cb(env_cpu(env), ptr, meminfo); ++ return ret; ++} ++ ++uint64_t cpu_ldq_le_data(CPUArchState *env, abi_ptr ptr) ++{ ++ uint64_t ret; ++ uint16_t meminfo = trace_mem_get_info(MO_LEQ, MMU_USER_IDX, false); ++ ++ trace_guest_mem_before_exec(env_cpu(env), ptr, meminfo); ++ ret = ldq_le_p(g2h(ptr)); + qemu_plugin_vcpu_mem_cb(env_cpu(env), ptr, meminfo); + return ret; + } +@@ -847,42 +891,82 @@ int cpu_ldsb_data_ra(CPUArchState *env, abi_ptr ptr, uintptr_t retaddr) + return ret; + } + +-uint32_t cpu_lduw_data_ra(CPUArchState *env, abi_ptr ptr, uintptr_t retaddr) ++uint32_t cpu_lduw_be_data_ra(CPUArchState *env, abi_ptr ptr, uintptr_t retaddr) ++{ ++ uint32_t ret; ++ ++ set_helper_retaddr(retaddr); ++ ret = cpu_lduw_be_data(env, ptr); ++ clear_helper_retaddr(); ++ return ret; ++} ++ ++int cpu_ldsw_be_data_ra(CPUArchState *env, abi_ptr ptr, uintptr_t retaddr) ++{ ++ int ret; ++ ++ set_helper_retaddr(retaddr); ++ ret = cpu_ldsw_be_data(env, ptr); ++ clear_helper_retaddr(); ++ return ret; ++} ++ ++uint32_t cpu_ldl_be_data_ra(CPUArchState *env, abi_ptr ptr, uintptr_t retaddr) + { + uint32_t ret; + + set_helper_retaddr(retaddr); +- ret = cpu_lduw_data(env, ptr); ++ ret = cpu_ldl_be_data(env, ptr); + clear_helper_retaddr(); + return ret; + } + +-int cpu_ldsw_data_ra(CPUArchState *env, abi_ptr ptr, uintptr_t retaddr) ++uint64_t cpu_ldq_be_data_ra(CPUArchState *env, abi_ptr ptr, uintptr_t retaddr) ++{ ++ uint64_t ret; ++ ++ set_helper_retaddr(retaddr); ++ ret = cpu_ldq_be_data(env, ptr); ++ clear_helper_retaddr(); ++ return ret; ++} ++ ++uint32_t cpu_lduw_le_data_ra(CPUArchState *env, abi_ptr ptr, uintptr_t retaddr) ++{ ++ uint32_t ret; ++ ++ set_helper_retaddr(retaddr); ++ ret = cpu_lduw_le_data(env, ptr); ++ clear_helper_retaddr(); ++ return ret; ++} ++ ++int cpu_ldsw_le_data_ra(CPUArchState *env, abi_ptr ptr, uintptr_t retaddr) + { + int ret; + + set_helper_retaddr(retaddr); +- ret = cpu_ldsw_data(env, ptr); ++ ret = cpu_ldsw_le_data(env, ptr); + clear_helper_retaddr(); + return ret; + } + +-uint32_t cpu_ldl_data_ra(CPUArchState *env, abi_ptr ptr, uintptr_t retaddr) ++uint32_t cpu_ldl_le_data_ra(CPUArchState *env, abi_ptr ptr, uintptr_t retaddr) + { + uint32_t ret; + + set_helper_retaddr(retaddr); +- ret = cpu_ldl_data(env, ptr); ++ ret = cpu_ldl_le_data(env, ptr); + clear_helper_retaddr(); + return ret; + } + +-uint64_t cpu_ldq_data_ra(CPUArchState *env, abi_ptr ptr, uintptr_t retaddr) ++uint64_t cpu_ldq_le_data_ra(CPUArchState *env, abi_ptr ptr, uintptr_t retaddr) + { + uint64_t ret; + + set_helper_retaddr(retaddr); +- ret = cpu_ldq_data(env, ptr); ++ ret = cpu_ldq_le_data(env, ptr); + clear_helper_retaddr(); + return ret; + } +@@ -896,30 +980,57 @@ void cpu_stb_data(CPUArchState *env, abi_ptr ptr, uint32_t val) + qemu_plugin_vcpu_mem_cb(env_cpu(env), ptr, meminfo); + } + +-void cpu_stw_data(CPUArchState *env, abi_ptr ptr, uint32_t val) ++void cpu_stw_be_data(CPUArchState *env, abi_ptr ptr, uint32_t val) + { +- uint16_t meminfo = trace_mem_get_info(MO_TEUW, MMU_USER_IDX, true); ++ uint16_t meminfo = trace_mem_get_info(MO_BEUW, MMU_USER_IDX, true); + + trace_guest_mem_before_exec(env_cpu(env), ptr, meminfo); +- stw_p(g2h(ptr), val); ++ stw_be_p(g2h(ptr), val); + qemu_plugin_vcpu_mem_cb(env_cpu(env), ptr, meminfo); + } + +-void cpu_stl_data(CPUArchState *env, abi_ptr ptr, uint32_t val) ++void cpu_stl_be_data(CPUArchState *env, abi_ptr ptr, uint32_t val) + { +- uint16_t meminfo = trace_mem_get_info(MO_TEUL, MMU_USER_IDX, true); ++ uint16_t meminfo = trace_mem_get_info(MO_BEUL, MMU_USER_IDX, true); + + trace_guest_mem_before_exec(env_cpu(env), ptr, meminfo); +- stl_p(g2h(ptr), val); ++ stl_be_p(g2h(ptr), val); + qemu_plugin_vcpu_mem_cb(env_cpu(env), ptr, meminfo); + } + +-void cpu_stq_data(CPUArchState *env, abi_ptr ptr, uint64_t val) ++void cpu_stq_be_data(CPUArchState *env, abi_ptr ptr, uint64_t val) + { +- uint16_t meminfo = trace_mem_get_info(MO_TEQ, MMU_USER_IDX, true); ++ uint16_t meminfo = trace_mem_get_info(MO_BEQ, MMU_USER_IDX, true); + + trace_guest_mem_before_exec(env_cpu(env), ptr, meminfo); +- stq_p(g2h(ptr), val); ++ stq_be_p(g2h(ptr), val); ++ qemu_plugin_vcpu_mem_cb(env_cpu(env), ptr, meminfo); ++} ++ ++void cpu_stw_le_data(CPUArchState *env, abi_ptr ptr, uint32_t val) ++{ ++ uint16_t meminfo = trace_mem_get_info(MO_LEUW, MMU_USER_IDX, true); ++ ++ trace_guest_mem_before_exec(env_cpu(env), ptr, meminfo); ++ stw_le_p(g2h(ptr), val); ++ qemu_plugin_vcpu_mem_cb(env_cpu(env), ptr, meminfo); ++} ++ ++void cpu_stl_le_data(CPUArchState *env, abi_ptr ptr, uint32_t val) ++{ ++ uint16_t meminfo = trace_mem_get_info(MO_LEUL, MMU_USER_IDX, true); ++ ++ trace_guest_mem_before_exec(env_cpu(env), ptr, meminfo); ++ stl_le_p(g2h(ptr), val); ++ qemu_plugin_vcpu_mem_cb(env_cpu(env), ptr, meminfo); ++} ++ ++void cpu_stq_le_data(CPUArchState *env, abi_ptr ptr, uint64_t val) ++{ ++ uint16_t meminfo = trace_mem_get_info(MO_LEQ, MMU_USER_IDX, true); ++ ++ trace_guest_mem_before_exec(env_cpu(env), ptr, meminfo); ++ stq_le_p(g2h(ptr), val); + qemu_plugin_vcpu_mem_cb(env_cpu(env), ptr, meminfo); + } + +@@ -931,27 +1042,51 @@ void cpu_stb_data_ra(CPUArchState *env, abi_ptr ptr, + clear_helper_retaddr(); + } + +-void cpu_stw_data_ra(CPUArchState *env, abi_ptr ptr, +- uint32_t val, uintptr_t retaddr) ++void cpu_stw_be_data_ra(CPUArchState *env, abi_ptr ptr, ++ uint32_t val, uintptr_t retaddr) + { + set_helper_retaddr(retaddr); +- cpu_stw_data(env, ptr, val); ++ cpu_stw_be_data(env, ptr, val); + clear_helper_retaddr(); + } + +-void cpu_stl_data_ra(CPUArchState *env, abi_ptr ptr, +- uint32_t val, uintptr_t retaddr) ++void cpu_stl_be_data_ra(CPUArchState *env, abi_ptr ptr, ++ uint32_t val, uintptr_t retaddr) ++{ ++ set_helper_retaddr(retaddr); ++ cpu_stl_be_data(env, ptr, val); ++ clear_helper_retaddr(); ++} ++ ++void cpu_stq_be_data_ra(CPUArchState *env, abi_ptr ptr, ++ uint64_t val, uintptr_t retaddr) ++{ ++ set_helper_retaddr(retaddr); ++ cpu_stq_be_data(env, ptr, val); ++ clear_helper_retaddr(); ++} ++ ++void cpu_stw_le_data_ra(CPUArchState *env, abi_ptr ptr, ++ uint32_t val, uintptr_t retaddr) ++{ ++ set_helper_retaddr(retaddr); ++ cpu_stw_le_data(env, ptr, val); ++ clear_helper_retaddr(); ++} ++ ++void cpu_stl_le_data_ra(CPUArchState *env, abi_ptr ptr, ++ uint32_t val, uintptr_t retaddr) + { + set_helper_retaddr(retaddr); +- cpu_stl_data(env, ptr, val); ++ cpu_stl_le_data(env, ptr, val); + clear_helper_retaddr(); + } + +-void cpu_stq_data_ra(CPUArchState *env, abi_ptr ptr, +- uint64_t val, uintptr_t retaddr) ++void cpu_stq_le_data_ra(CPUArchState *env, abi_ptr ptr, ++ uint64_t val, uintptr_t retaddr) + { + set_helper_retaddr(retaddr); +- cpu_stq_data(env, ptr, val); ++ cpu_stq_le_data(env, ptr, val); + clear_helper_retaddr(); + } + +diff --git a/docs/devel/loads-stores.rst b/docs/devel/loads-stores.rst +index 0d99eb24c1..9a944ef1af 100644 +--- a/docs/devel/loads-stores.rst ++++ b/docs/devel/loads-stores.rst +@@ -97,9 +97,9 @@ function, which is a return address into the generated code. + + Function names follow the pattern: + +-load: ``cpu_ld{sign}{size}_mmuidx_ra(env, ptr, mmuidx, retaddr)`` ++load: ``cpu_ld{sign}{size}{end}_mmuidx_ra(env, ptr, mmuidx, retaddr)`` + +-store: ``cpu_st{size}_mmuidx_ra(env, ptr, val, mmuidx, retaddr)`` ++store: ``cpu_st{size}{end}_mmuidx_ra(env, ptr, val, mmuidx, retaddr)`` + + ``sign`` + - (empty) : for 32 or 64 bit sizes +@@ -112,9 +112,14 @@ store: ``cpu_st{size}_mmuidx_ra(env, ptr, val, mmuidx, retaddr)`` + - ``l`` : 32 bits + - ``q`` : 64 bits + ++``end`` ++ - (empty) : for target endian, or 8 bit sizes ++ - ``_be`` : big endian ++ - ``_le`` : little endian ++ + Regexes for git grep: +- - ``\`` +- - ``\`` ++ - ``\`` ++ - ``\`` + + ``cpu_{ld,st}*_data_ra`` + ~~~~~~~~~~~~~~~~~~~~~~~~ +@@ -129,9 +134,9 @@ be performed with a context other than the default. + + Function names follow the pattern: + +-load: ``cpu_ld{sign}{size}_data_ra(env, ptr, ra)`` ++load: ``cpu_ld{sign}{size}{end}_data_ra(env, ptr, ra)`` + +-store: ``cpu_st{size}_data_ra(env, ptr, val, ra)`` ++store: ``cpu_st{size}{end}_data_ra(env, ptr, val, ra)`` + + ``sign`` + - (empty) : for 32 or 64 bit sizes +@@ -144,9 +149,14 @@ store: ``cpu_st{size}_data_ra(env, ptr, val, ra)`` + - ``l`` : 32 bits + - ``q`` : 64 bits + ++``end`` ++ - (empty) : for target endian, or 8 bit sizes ++ - ``_be`` : big endian ++ - ``_le`` : little endian ++ + Regexes for git grep: +- - ``\`` +- - ``\`` ++ - ``\`` ++ - ``\`` + + ``cpu_{ld,st}*_data`` + ~~~~~~~~~~~~~~~~~~~~~ +@@ -163,9 +173,9 @@ the CPU state anyway. + + Function names follow the pattern: + +-load: ``cpu_ld{sign}{size}_data(env, ptr)`` ++load: ``cpu_ld{sign}{size}{end}_data(env, ptr)`` + +-store: ``cpu_st{size}_data(env, ptr, val)`` ++store: ``cpu_st{size}{end}_data(env, ptr, val)`` + + ``sign`` + - (empty) : for 32 or 64 bit sizes +@@ -178,9 +188,14 @@ store: ``cpu_st{size}_data(env, ptr, val)`` + - ``l`` : 32 bits + - ``q`` : 64 bits + ++``end`` ++ - (empty) : for target endian, or 8 bit sizes ++ - ``_be`` : big endian ++ - ``_le`` : little endian ++ + Regexes for git grep +- - ``\`` +- - ``\`` ++ - ``\`` ++ - ``\`` + + ``cpu_ld*_code`` + ~~~~~~~~~~~~~~~~ +diff --git a/include/exec/cpu_ldst.h b/include/exec/cpu_ldst.h +index 53de19753a..c14a48f65e 100644 +--- a/include/exec/cpu_ldst.h ++++ b/include/exec/cpu_ldst.h +@@ -25,13 +25,13 @@ + * + * The syntax for the accessors is: + * +- * load: cpu_ld{sign}{size}_{mmusuffix}(env, ptr) +- * cpu_ld{sign}{size}_{mmusuffix}_ra(env, ptr, retaddr) +- * cpu_ld{sign}{size}_mmuidx_ra(env, ptr, mmu_idx, retaddr) ++ * load: cpu_ld{sign}{size}{end}_{mmusuffix}(env, ptr) ++ * cpu_ld{sign}{size}{end}_{mmusuffix}_ra(env, ptr, retaddr) ++ * cpu_ld{sign}{size}{end}_mmuidx_ra(env, ptr, mmu_idx, retaddr) + * +- * store: cpu_st{size}_{mmusuffix}(env, ptr, val) +- * cpu_st{size}_{mmusuffix}_ra(env, ptr, val, retaddr) +- * cpu_st{size}_mmuidx_ra(env, ptr, val, mmu_idx, retaddr) ++ * store: cpu_st{size}{end}_{mmusuffix}(env, ptr, val) ++ * cpu_st{size}{end}_{mmusuffix}_ra(env, ptr, val, retaddr) ++ * cpu_st{size}{end}_mmuidx_ra(env, ptr, val, mmu_idx, retaddr) + * + * sign is: + * (empty): for 32 and 64 bit sizes +@@ -44,6 +44,11 @@ + * l: 32 bits + * q: 64 bits + * ++ * end is: ++ * (empty): for target native endian, or for 8 bit access ++ * _be: for forced big endian ++ * _le: for forced little endian ++ * + * mmusuffix is one of the generic suffixes "data" or "code", or "mmuidx". + * The "mmuidx" suffix carries an extra mmu_idx argument that specifies + * the index to use; the "data" and "code" suffixes take the index from +@@ -95,32 +100,57 @@ typedef target_ulong abi_ptr; + #endif + + uint32_t cpu_ldub_data(CPUArchState *env, abi_ptr ptr); +-uint32_t cpu_lduw_data(CPUArchState *env, abi_ptr ptr); +-uint32_t cpu_ldl_data(CPUArchState *env, abi_ptr ptr); +-uint64_t cpu_ldq_data(CPUArchState *env, abi_ptr ptr); + int cpu_ldsb_data(CPUArchState *env, abi_ptr ptr); +-int cpu_ldsw_data(CPUArchState *env, abi_ptr ptr); + +-uint32_t cpu_ldub_data_ra(CPUArchState *env, abi_ptr ptr, uintptr_t retaddr); +-uint32_t cpu_lduw_data_ra(CPUArchState *env, abi_ptr ptr, uintptr_t retaddr); +-uint32_t cpu_ldl_data_ra(CPUArchState *env, abi_ptr ptr, uintptr_t retaddr); +-uint64_t cpu_ldq_data_ra(CPUArchState *env, abi_ptr ptr, uintptr_t retaddr); +-int cpu_ldsb_data_ra(CPUArchState *env, abi_ptr ptr, uintptr_t retaddr); +-int cpu_ldsw_data_ra(CPUArchState *env, abi_ptr ptr, uintptr_t retaddr); ++uint32_t cpu_lduw_be_data(CPUArchState *env, abi_ptr ptr); ++int cpu_ldsw_be_data(CPUArchState *env, abi_ptr ptr); ++uint32_t cpu_ldl_be_data(CPUArchState *env, abi_ptr ptr); ++uint64_t cpu_ldq_be_data(CPUArchState *env, abi_ptr ptr); ++ ++uint32_t cpu_lduw_le_data(CPUArchState *env, abi_ptr ptr); ++int cpu_ldsw_le_data(CPUArchState *env, abi_ptr ptr); ++uint32_t cpu_ldl_le_data(CPUArchState *env, abi_ptr ptr); ++uint64_t cpu_ldq_le_data(CPUArchState *env, abi_ptr ptr); ++ ++uint32_t cpu_ldub_data_ra(CPUArchState *env, abi_ptr ptr, uintptr_t ra); ++int cpu_ldsb_data_ra(CPUArchState *env, abi_ptr ptr, uintptr_t ra); ++ ++uint32_t cpu_lduw_be_data_ra(CPUArchState *env, abi_ptr ptr, uintptr_t ra); ++int cpu_ldsw_be_data_ra(CPUArchState *env, abi_ptr ptr, uintptr_t ra); ++uint32_t cpu_ldl_be_data_ra(CPUArchState *env, abi_ptr ptr, uintptr_t ra); ++uint64_t cpu_ldq_be_data_ra(CPUArchState *env, abi_ptr ptr, uintptr_t ra); ++ ++uint32_t cpu_lduw_le_data_ra(CPUArchState *env, abi_ptr ptr, uintptr_t ra); ++int cpu_ldsw_le_data_ra(CPUArchState *env, abi_ptr ptr, uintptr_t ra); ++uint32_t cpu_ldl_le_data_ra(CPUArchState *env, abi_ptr ptr, uintptr_t ra); ++uint64_t cpu_ldq_le_data_ra(CPUArchState *env, abi_ptr ptr, uintptr_t ra); + + void cpu_stb_data(CPUArchState *env, abi_ptr ptr, uint32_t val); +-void cpu_stw_data(CPUArchState *env, abi_ptr ptr, uint32_t val); +-void cpu_stl_data(CPUArchState *env, abi_ptr ptr, uint32_t val); +-void cpu_stq_data(CPUArchState *env, abi_ptr ptr, uint64_t val); ++ ++void cpu_stw_be_data(CPUArchState *env, abi_ptr ptr, uint32_t val); ++void cpu_stl_be_data(CPUArchState *env, abi_ptr ptr, uint32_t val); ++void cpu_stq_be_data(CPUArchState *env, abi_ptr ptr, uint64_t val); ++ ++void cpu_stw_le_data(CPUArchState *env, abi_ptr ptr, uint32_t val); ++void cpu_stl_le_data(CPUArchState *env, abi_ptr ptr, uint32_t val); ++void cpu_stq_le_data(CPUArchState *env, abi_ptr ptr, uint64_t val); + + void cpu_stb_data_ra(CPUArchState *env, abi_ptr ptr, +- uint32_t val, uintptr_t retaddr); +-void cpu_stw_data_ra(CPUArchState *env, abi_ptr ptr, +- uint32_t val, uintptr_t retaddr); +-void cpu_stl_data_ra(CPUArchState *env, abi_ptr ptr, +- uint32_t val, uintptr_t retaddr); +-void cpu_stq_data_ra(CPUArchState *env, abi_ptr ptr, +- uint64_t val, uintptr_t retaddr); ++ uint32_t val, uintptr_t ra); ++ ++void cpu_stw_be_data_ra(CPUArchState *env, abi_ptr ptr, ++ uint32_t val, uintptr_t ra); ++void cpu_stl_be_data_ra(CPUArchState *env, abi_ptr ptr, ++ uint32_t val, uintptr_t ra); ++void cpu_stq_be_data_ra(CPUArchState *env, abi_ptr ptr, ++ uint64_t val, uintptr_t ra); ++ ++void cpu_stw_le_data_ra(CPUArchState *env, abi_ptr ptr, ++ uint32_t val, uintptr_t ra); ++void cpu_stl_le_data_ra(CPUArchState *env, abi_ptr ptr, ++ uint32_t val, uintptr_t ra); ++void cpu_stq_le_data_ra(CPUArchState *env, abi_ptr ptr, ++ uint64_t val, uintptr_t ra); + + #if defined(CONFIG_USER_ONLY) + +@@ -157,34 +187,58 @@ static inline uint32_t cpu_ldub_mmuidx_ra(CPUArchState *env, abi_ptr addr, + return cpu_ldub_data_ra(env, addr, ra); + } + +-static inline uint32_t cpu_lduw_mmuidx_ra(CPUArchState *env, abi_ptr addr, +- int mmu_idx, uintptr_t ra) ++static inline int cpu_ldsb_mmuidx_ra(CPUArchState *env, abi_ptr addr, ++ int mmu_idx, uintptr_t ra) + { +- return cpu_lduw_data_ra(env, addr, ra); ++ return cpu_ldsb_data_ra(env, addr, ra); + } + +-static inline uint32_t cpu_ldl_mmuidx_ra(CPUArchState *env, abi_ptr addr, +- int mmu_idx, uintptr_t ra) ++static inline uint32_t cpu_lduw_be_mmuidx_ra(CPUArchState *env, abi_ptr addr, ++ int mmu_idx, uintptr_t ra) + { +- return cpu_ldl_data_ra(env, addr, ra); ++ return cpu_lduw_be_data_ra(env, addr, ra); + } + +-static inline uint64_t cpu_ldq_mmuidx_ra(CPUArchState *env, abi_ptr addr, +- int mmu_idx, uintptr_t ra) ++static inline int cpu_ldsw_be_mmuidx_ra(CPUArchState *env, abi_ptr addr, ++ int mmu_idx, uintptr_t ra) + { +- return cpu_ldq_data_ra(env, addr, ra); ++ return cpu_ldsw_be_data_ra(env, addr, ra); + } + +-static inline int cpu_ldsb_mmuidx_ra(CPUArchState *env, abi_ptr addr, +- int mmu_idx, uintptr_t ra) ++static inline uint32_t cpu_ldl_be_mmuidx_ra(CPUArchState *env, abi_ptr addr, ++ int mmu_idx, uintptr_t ra) + { +- return cpu_ldsb_data_ra(env, addr, ra); ++ return cpu_ldl_be_data_ra(env, addr, ra); + } + +-static inline int cpu_ldsw_mmuidx_ra(CPUArchState *env, abi_ptr addr, +- int mmu_idx, uintptr_t ra) ++static inline uint64_t cpu_ldq_be_mmuidx_ra(CPUArchState *env, abi_ptr addr, ++ int mmu_idx, uintptr_t ra) ++{ ++ return cpu_ldq_be_data_ra(env, addr, ra); ++} ++ ++static inline uint32_t cpu_lduw_le_mmuidx_ra(CPUArchState *env, abi_ptr addr, ++ int mmu_idx, uintptr_t ra) ++{ ++ return cpu_lduw_le_data_ra(env, addr, ra); ++} ++ ++static inline int cpu_ldsw_le_mmuidx_ra(CPUArchState *env, abi_ptr addr, ++ int mmu_idx, uintptr_t ra) ++{ ++ return cpu_ldsw_le_data_ra(env, addr, ra); ++} ++ ++static inline uint32_t cpu_ldl_le_mmuidx_ra(CPUArchState *env, abi_ptr addr, ++ int mmu_idx, uintptr_t ra) ++{ ++ return cpu_ldl_le_data_ra(env, addr, ra); ++} ++ ++static inline uint64_t cpu_ldq_le_mmuidx_ra(CPUArchState *env, abi_ptr addr, ++ int mmu_idx, uintptr_t ra) + { +- return cpu_ldsw_data_ra(env, addr, ra); ++ return cpu_ldq_le_data_ra(env, addr, ra); + } + + static inline void cpu_stb_mmuidx_ra(CPUArchState *env, abi_ptr addr, +@@ -193,22 +247,46 @@ static inline void cpu_stb_mmuidx_ra(CPUArchState *env, abi_ptr addr, + cpu_stb_data_ra(env, addr, val, ra); + } + +-static inline void cpu_stw_mmuidx_ra(CPUArchState *env, abi_ptr addr, +- uint32_t val, int mmu_idx, uintptr_t ra) ++static inline void cpu_stw_be_mmuidx_ra(CPUArchState *env, abi_ptr addr, ++ uint32_t val, int mmu_idx, ++ uintptr_t ra) + { +- cpu_stw_data_ra(env, addr, val, ra); ++ cpu_stw_be_data_ra(env, addr, val, ra); + } + +-static inline void cpu_stl_mmuidx_ra(CPUArchState *env, abi_ptr addr, +- uint32_t val, int mmu_idx, uintptr_t ra) ++static inline void cpu_stl_be_mmuidx_ra(CPUArchState *env, abi_ptr addr, ++ uint32_t val, int mmu_idx, ++ uintptr_t ra) ++{ ++ cpu_stl_be_data_ra(env, addr, val, ra); ++} ++ ++static inline void cpu_stq_be_mmuidx_ra(CPUArchState *env, abi_ptr addr, ++ uint64_t val, int mmu_idx, ++ uintptr_t ra) ++{ ++ cpu_stq_be_data_ra(env, addr, val, ra); ++} ++ ++static inline void cpu_stw_le_mmuidx_ra(CPUArchState *env, abi_ptr addr, ++ uint32_t val, int mmu_idx, ++ uintptr_t ra) ++{ ++ cpu_stw_le_data_ra(env, addr, val, ra); ++} ++ ++static inline void cpu_stl_le_mmuidx_ra(CPUArchState *env, abi_ptr addr, ++ uint32_t val, int mmu_idx, ++ uintptr_t ra) + { +- cpu_stl_data_ra(env, addr, val, ra); ++ cpu_stl_le_data_ra(env, addr, val, ra); + } + +-static inline void cpu_stq_mmuidx_ra(CPUArchState *env, abi_ptr addr, +- uint64_t val, int mmu_idx, uintptr_t ra) ++static inline void cpu_stq_le_mmuidx_ra(CPUArchState *env, abi_ptr addr, ++ uint64_t val, int mmu_idx, ++ uintptr_t ra) + { +- cpu_stq_data_ra(env, addr, val, ra); ++ cpu_stq_le_data_ra(env, addr, val, ra); + } + + #else +@@ -243,29 +321,92 @@ static inline CPUTLBEntry *tlb_entry(CPUArchState *env, uintptr_t mmu_idx, + + uint32_t cpu_ldub_mmuidx_ra(CPUArchState *env, abi_ptr addr, + int mmu_idx, uintptr_t ra); +-uint32_t cpu_lduw_mmuidx_ra(CPUArchState *env, abi_ptr addr, +- int mmu_idx, uintptr_t ra); +-uint32_t cpu_ldl_mmuidx_ra(CPUArchState *env, abi_ptr addr, +- int mmu_idx, uintptr_t ra); +-uint64_t cpu_ldq_mmuidx_ra(CPUArchState *env, abi_ptr addr, +- int mmu_idx, uintptr_t ra); +- + int cpu_ldsb_mmuidx_ra(CPUArchState *env, abi_ptr addr, + int mmu_idx, uintptr_t ra); +-int cpu_ldsw_mmuidx_ra(CPUArchState *env, abi_ptr addr, +- int mmu_idx, uintptr_t ra); ++ ++uint32_t cpu_lduw_be_mmuidx_ra(CPUArchState *env, abi_ptr addr, ++ int mmu_idx, uintptr_t ra); ++int cpu_ldsw_be_mmuidx_ra(CPUArchState *env, abi_ptr addr, ++ int mmu_idx, uintptr_t ra); ++uint32_t cpu_ldl_be_mmuidx_ra(CPUArchState *env, abi_ptr addr, ++ int mmu_idx, uintptr_t ra); ++uint64_t cpu_ldq_be_mmuidx_ra(CPUArchState *env, abi_ptr addr, ++ int mmu_idx, uintptr_t ra); ++ ++uint32_t cpu_lduw_le_mmuidx_ra(CPUArchState *env, abi_ptr addr, ++ int mmu_idx, uintptr_t ra); ++int cpu_ldsw_le_mmuidx_ra(CPUArchState *env, abi_ptr addr, ++ int mmu_idx, uintptr_t ra); ++uint32_t cpu_ldl_le_mmuidx_ra(CPUArchState *env, abi_ptr addr, ++ int mmu_idx, uintptr_t ra); ++uint64_t cpu_ldq_le_mmuidx_ra(CPUArchState *env, abi_ptr addr, ++ int mmu_idx, uintptr_t ra); + + void cpu_stb_mmuidx_ra(CPUArchState *env, abi_ptr addr, uint32_t val, + int mmu_idx, uintptr_t retaddr); +-void cpu_stw_mmuidx_ra(CPUArchState *env, abi_ptr addr, uint32_t val, +- int mmu_idx, uintptr_t retaddr); +-void cpu_stl_mmuidx_ra(CPUArchState *env, abi_ptr addr, uint32_t val, +- int mmu_idx, uintptr_t retaddr); +-void cpu_stq_mmuidx_ra(CPUArchState *env, abi_ptr addr, uint64_t val, +- int mmu_idx, uintptr_t retaddr); ++ ++void cpu_stw_be_mmuidx_ra(CPUArchState *env, abi_ptr addr, uint32_t val, ++ int mmu_idx, uintptr_t retaddr); ++void cpu_stl_be_mmuidx_ra(CPUArchState *env, abi_ptr addr, uint32_t val, ++ int mmu_idx, uintptr_t retaddr); ++void cpu_stq_be_mmuidx_ra(CPUArchState *env, abi_ptr addr, uint64_t val, ++ int mmu_idx, uintptr_t retaddr); ++ ++void cpu_stw_le_mmuidx_ra(CPUArchState *env, abi_ptr addr, uint32_t val, ++ int mmu_idx, uintptr_t retaddr); ++void cpu_stl_le_mmuidx_ra(CPUArchState *env, abi_ptr addr, uint32_t val, ++ int mmu_idx, uintptr_t retaddr); ++void cpu_stq_le_mmuidx_ra(CPUArchState *env, abi_ptr addr, uint64_t val, ++ int mmu_idx, uintptr_t retaddr); + + #endif /* defined(CONFIG_USER_ONLY) */ + ++#ifdef TARGET_WORDS_BIGENDIAN ++# define cpu_lduw_data cpu_lduw_be_data ++# define cpu_ldsw_data cpu_ldsw_be_data ++# define cpu_ldl_data cpu_ldl_be_data ++# define cpu_ldq_data cpu_ldq_be_data ++# define cpu_lduw_data_ra cpu_lduw_be_data_ra ++# define cpu_ldsw_data_ra cpu_ldsw_be_data_ra ++# define cpu_ldl_data_ra cpu_ldl_be_data_ra ++# define cpu_ldq_data_ra cpu_ldq_be_data_ra ++# define cpu_lduw_mmuidx_ra cpu_lduw_be_mmuidx_ra ++# define cpu_ldsw_mmuidx_ra cpu_ldsw_be_mmuidx_ra ++# define cpu_ldl_mmuidx_ra cpu_ldl_be_mmuidx_ra ++# define cpu_ldq_mmuidx_ra cpu_ldq_be_mmuidx_ra ++# define cpu_stw_data cpu_stw_be_data ++# define cpu_stl_data cpu_stl_be_data ++# define cpu_stq_data cpu_stq_be_data ++# define cpu_stw_data_ra cpu_stw_be_data_ra ++# define cpu_stl_data_ra cpu_stl_be_data_ra ++# define cpu_stq_data_ra cpu_stq_be_data_ra ++# define cpu_stw_mmuidx_ra cpu_stw_be_mmuidx_ra ++# define cpu_stl_mmuidx_ra cpu_stl_be_mmuidx_ra ++# define cpu_stq_mmuidx_ra cpu_stq_be_mmuidx_ra ++#else ++# define cpu_lduw_data cpu_lduw_le_data ++# define cpu_ldsw_data cpu_ldsw_le_data ++# define cpu_ldl_data cpu_ldl_le_data ++# define cpu_ldq_data cpu_ldq_le_data ++# define cpu_lduw_data_ra cpu_lduw_le_data_ra ++# define cpu_ldsw_data_ra cpu_ldsw_le_data_ra ++# define cpu_ldl_data_ra cpu_ldl_le_data_ra ++# define cpu_ldq_data_ra cpu_ldq_le_data_ra ++# define cpu_lduw_mmuidx_ra cpu_lduw_le_mmuidx_ra ++# define cpu_ldsw_mmuidx_ra cpu_ldsw_le_mmuidx_ra ++# define cpu_ldl_mmuidx_ra cpu_ldl_le_mmuidx_ra ++# define cpu_ldq_mmuidx_ra cpu_ldq_le_mmuidx_ra ++# define cpu_stw_data cpu_stw_le_data ++# define cpu_stl_data cpu_stl_le_data ++# define cpu_stq_data cpu_stq_le_data ++# define cpu_stw_data_ra cpu_stw_le_data_ra ++# define cpu_stl_data_ra cpu_stl_le_data_ra ++# define cpu_stq_data_ra cpu_stq_le_data_ra ++# define cpu_stw_mmuidx_ra cpu_stw_le_mmuidx_ra ++# define cpu_stl_mmuidx_ra cpu_stl_le_mmuidx_ra ++# define cpu_stq_mmuidx_ra cpu_stq_le_mmuidx_ra ++#endif ++ + uint32_t cpu_ldub_code(CPUArchState *env, abi_ptr addr); + uint32_t cpu_lduw_code(CPUArchState *env, abi_ptr addr); + uint32_t cpu_ldl_code(CPUArchState *env, abi_ptr addr); +-- +2.23.0 + diff --git a/accel-tcg-Add-probe_access_flags.patch b/accel-tcg-Add-probe_access_flags.patch new file mode 100644 index 0000000000000000000000000000000000000000..234df53935cf56e7020fe0465ebc33e1b817dd5c --- /dev/null +++ b/accel-tcg-Add-probe_access_flags.patch @@ -0,0 +1,363 @@ +From 069cfe77d63e06e2b25912aea9fea6ea14bb246a Mon Sep 17 00:00:00 2001 +From: Richard Henderson +Date: Fri, 8 May 2020 08:43:45 -0700 +Subject: [PATCH 369/709] accel/tcg: Add probe_access_flags + +This new interface will allow targets to probe for a page +and then handle watchpoints themselves. This will be most +useful for vector predicated memory operations, where one +page lookup can be used for many operations, and one test +can avoid many watchpoint checks. + +Signed-off-by: Richard Henderson +Message-id: 20200508154359.7494-6-richard.henderson@linaro.org +Reviewed-by: Peter Maydell +Signed-off-by: Peter Maydell +--- + accel/tcg/cputlb.c | 157 ++++++++++++++++++++-------------------- + accel/tcg/user-exec.c | 43 ++++++++--- + include/exec/cpu-all.h | 13 +++- + include/exec/exec-all.h | 22 ++++++ + 4 files changed, 148 insertions(+), 87 deletions(-) + +diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c +index e3b5750c3b..c708e9785f 100644 +--- a/accel/tcg/cputlb.c ++++ b/accel/tcg/cputlb.c +@@ -1231,131 +1231,134 @@ static void notdirty_write(CPUState *cpu, vaddr mem_vaddr, unsigned size, + } + } + +-/* +- * Probe for whether the specified guest access is permitted. If it is not +- * permitted then an exception will be taken in the same way as if this +- * were a real access (and we will not return). +- * If the size is 0 or the page requires I/O access, returns NULL; otherwise, +- * returns the address of the host page similar to tlb_vaddr_to_host(). +- */ +-void *probe_access(CPUArchState *env, target_ulong addr, int size, +- MMUAccessType access_type, int mmu_idx, uintptr_t retaddr) ++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) + { + uintptr_t index = tlb_index(env, mmu_idx, addr); + CPUTLBEntry *entry = tlb_entry(env, mmu_idx, addr); +- target_ulong tlb_addr; ++ target_ulong tlb_addr, page_addr; + size_t elt_ofs; +- int wp_access; +- +- g_assert(-(addr | TARGET_PAGE_MASK) >= size); ++ int flags; + + switch (access_type) { + case MMU_DATA_LOAD: + elt_ofs = offsetof(CPUTLBEntry, addr_read); +- wp_access = BP_MEM_READ; + break; + case MMU_DATA_STORE: + elt_ofs = offsetof(CPUTLBEntry, addr_write); +- wp_access = BP_MEM_WRITE; + break; + case MMU_INST_FETCH: + elt_ofs = offsetof(CPUTLBEntry, addr_code); +- wp_access = BP_MEM_READ; + break; + default: + g_assert_not_reached(); + } + tlb_addr = tlb_read_ofs(entry, elt_ofs); + +- if (unlikely(!tlb_hit(tlb_addr, addr))) { +- if (!victim_tlb_hit(env, mmu_idx, index, elt_ofs, +- addr & TARGET_PAGE_MASK)) { +- tlb_fill(env_cpu(env), addr, size, access_type, mmu_idx, retaddr); +- /* TLB resize via tlb_fill may have moved the entry. */ +- index = tlb_index(env, mmu_idx, addr); ++ 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)) { ++ CPUState *cs = env_cpu(env); ++ CPUClass *cc = CPU_GET_CLASS(cs); ++ ++ if (!cc->tlb_fill(cs, addr, fault_size, access_type, ++ mmu_idx, nonfault, retaddr)) { ++ /* Non-faulting page table read failed. */ ++ *phost = NULL; ++ return TLB_INVALID_MASK; ++ } ++ ++ /* TLB resize via tlb_fill may have moved the entry. */ + entry = tlb_entry(env, mmu_idx, addr); + } + tlb_addr = tlb_read_ofs(entry, elt_ofs); + } ++ flags = tlb_addr & TLB_FLAGS_MASK; + +- if (!size) { +- return NULL; ++ /* Fold all "mmio-like" bits into TLB_MMIO. This is not RAM. */ ++ if (unlikely(flags & ~(TLB_WATCHPOINT | TLB_NOTDIRTY))) { ++ *phost = NULL; ++ return TLB_MMIO; + } + +- if (unlikely(tlb_addr & TLB_FLAGS_MASK)) { ++ /* Everything else is RAM. */ ++ *phost = (void *)((uintptr_t)addr + entry->addend); ++ 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 flags; ++ ++ flags = probe_access_internal(env, addr, 0, access_type, mmu_idx, ++ nonfault, phost, retaddr); ++ ++ /* 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]; + +- /* Reject I/O access, or other required slow-path. */ +- if (tlb_addr & (TLB_MMIO | TLB_BSWAP | TLB_DISCARD_WRITE)) { +- return NULL; +- } ++ notdirty_write(env_cpu(env), addr, 1, iotlbentry, retaddr); ++ flags &= ~TLB_NOTDIRTY; ++ } ++ ++ return flags; ++} ++ ++void *probe_access(CPUArchState *env, target_ulong addr, int size, ++ MMUAccessType access_type, int mmu_idx, uintptr_t retaddr) ++{ ++ 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); ++ ++ /* Per the interface, size == 0 merely faults the access. */ ++ if (size == 0) { ++ return NULL; ++ } ++ ++ 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]; + + /* Handle watchpoints. */ +- if (tlb_addr & TLB_WATCHPOINT) { ++ 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); + } + + /* Handle clean RAM pages. */ +- if (tlb_addr & TLB_NOTDIRTY) { +- notdirty_write(env_cpu(env), addr, size, iotlbentry, retaddr); ++ if (flags & TLB_NOTDIRTY) { ++ notdirty_write(env_cpu(env), addr, 1, iotlbentry, retaddr); + } + } + +- return (void *)((uintptr_t)addr + entry->addend); ++ return host; + } + + void *tlb_vaddr_to_host(CPUArchState *env, abi_ptr addr, + MMUAccessType access_type, int mmu_idx) + { +- CPUTLBEntry *entry = tlb_entry(env, mmu_idx, addr); +- target_ulong tlb_addr, page; +- size_t elt_ofs; +- +- switch (access_type) { +- case MMU_DATA_LOAD: +- elt_ofs = offsetof(CPUTLBEntry, addr_read); +- break; +- case MMU_DATA_STORE: +- elt_ofs = offsetof(CPUTLBEntry, addr_write); +- break; +- case MMU_INST_FETCH: +- elt_ofs = offsetof(CPUTLBEntry, addr_code); +- break; +- default: +- g_assert_not_reached(); +- } ++ void *host; ++ int flags; + +- page = addr & TARGET_PAGE_MASK; +- tlb_addr = tlb_read_ofs(entry, elt_ofs); +- +- if (!tlb_hit_page(tlb_addr, page)) { +- uintptr_t index = tlb_index(env, mmu_idx, addr); +- +- if (!victim_tlb_hit(env, mmu_idx, index, elt_ofs, page)) { +- CPUState *cs = env_cpu(env); +- CPUClass *cc = CPU_GET_CLASS(cs); ++ flags = probe_access_internal(env, addr, 0, access_type, ++ mmu_idx, true, &host, 0); + +- if (!cc->tlb_fill(cs, addr, 0, access_type, mmu_idx, true, 0)) { +- /* Non-faulting page table read failed. */ +- return NULL; +- } +- +- /* TLB resize via tlb_fill may have moved the entry. */ +- entry = tlb_entry(env, mmu_idx, addr); +- } +- tlb_addr = tlb_read_ofs(entry, elt_ofs); +- } +- +- if (tlb_addr & ~TARGET_PAGE_MASK) { +- /* IO access */ +- return NULL; +- } +- +- return (void *)((uintptr_t)addr + entry->addend); ++ /* No combination of flags are expected by the caller. */ ++ return flags ? NULL : host; + } + +- + #ifdef CONFIG_PLUGIN + /* + * Perform a TLB lookup and populate the qemu_plugin_hwaddr structure. +diff --git a/accel/tcg/user-exec.c b/accel/tcg/user-exec.c +index 03538e2a38..987342c50c 100644 +--- a/accel/tcg/user-exec.c ++++ b/accel/tcg/user-exec.c +@@ -190,13 +190,12 @@ static inline int handle_cpu_signal(uintptr_t pc, siginfo_t *info, + g_assert_not_reached(); + } + +-void *probe_access(CPUArchState *env, target_ulong addr, int size, +- MMUAccessType access_type, int mmu_idx, uintptr_t retaddr) ++static int probe_access_internal(CPUArchState *env, target_ulong addr, ++ int fault_size, MMUAccessType access_type, ++ bool nonfault, uintptr_t ra) + { + int flags; + +- g_assert(-(addr | TARGET_PAGE_MASK) >= size); +- + switch (access_type) { + case MMU_DATA_STORE: + flags = PAGE_WRITE; +@@ -212,12 +211,38 @@ void *probe_access(CPUArchState *env, target_ulong addr, int size, + } + + if (!guest_addr_valid(addr) || page_check_range(addr, 1, flags) < 0) { +- CPUState *cpu = env_cpu(env); +- CPUClass *cc = CPU_GET_CLASS(cpu); +- cc->tlb_fill(cpu, addr, size, access_type, MMU_USER_IDX, false, +- retaddr); +- g_assert_not_reached(); ++ if (nonfault) { ++ return TLB_INVALID_MASK; ++ } else { ++ CPUState *cpu = env_cpu(env); ++ CPUClass *cc = CPU_GET_CLASS(cpu); ++ cc->tlb_fill(cpu, addr, fault_size, access_type, ++ MMU_USER_IDX, false, ra); ++ g_assert_not_reached(); ++ } + } ++ return 0; ++} ++ ++int probe_access_flags(CPUArchState *env, target_ulong addr, ++ MMUAccessType access_type, int mmu_idx, ++ bool nonfault, void **phost, uintptr_t ra) ++{ ++ int flags; ++ ++ flags = probe_access_internal(env, addr, 0, access_type, nonfault, ra); ++ *phost = flags ? NULL : g2h(addr); ++ return flags; ++} ++ ++void *probe_access(CPUArchState *env, target_ulong addr, int size, ++ MMUAccessType access_type, int mmu_idx, uintptr_t ra) ++{ ++ int flags; ++ ++ g_assert(-(addr | TARGET_PAGE_MASK) >= size); ++ flags = probe_access_internal(env, addr, size, access_type, false, ra); ++ g_assert(flags == 0); + + return size ? g2h(addr) : NULL; + } +diff --git a/include/exec/cpu-all.h b/include/exec/cpu-all.h +index 49384bb66a..43ddcf024c 100644 +--- a/include/exec/cpu-all.h ++++ b/include/exec/cpu-all.h +@@ -328,7 +328,18 @@ CPUArchState *cpu_copy(CPUArchState *env); + | CPU_INTERRUPT_TGT_EXT_3 \ + | CPU_INTERRUPT_TGT_EXT_4) + +-#if !defined(CONFIG_USER_ONLY) ++#ifdef CONFIG_USER_ONLY ++ ++/* ++ * Allow some level of source compatibility with softmmu. We do not ++ * support any of the more exotic features, so only invalid pages may ++ * be signaled by probe_access_flags(). ++ */ ++#define TLB_INVALID_MASK (1 << (TARGET_PAGE_BITS_MIN - 1)) ++#define TLB_MMIO 0 ++#define TLB_WATCHPOINT 0 ++ ++#else + + /* + * Flags stored in the low bits of the TLB virtual address. +diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h +index d656a1f05c..8792bea07a 100644 +--- a/include/exec/exec-all.h ++++ b/include/exec/exec-all.h +@@ -362,6 +362,28 @@ static inline void *probe_read(CPUArchState *env, target_ulong addr, int size, + return probe_access(env, addr, size, MMU_DATA_LOAD, mmu_idx, retaddr); + } + ++/** ++ * probe_access_flags: ++ * @env: CPUArchState ++ * @addr: guest virtual address to look up ++ * @access_type: read, write or execute permission ++ * @mmu_idx: MMU index to use for lookup ++ * @nonfault: suppress the fault ++ * @phost: return value for host address ++ * @retaddr: return address for unwinding ++ * ++ * Similar to probe_access, loosely returning the TLB_FLAGS_MASK for ++ * the page, and storing the host address for RAM in @phost. ++ * ++ * If @nonfault is set, do not raise an exception but return TLB_INVALID_MASK. ++ * Do not handle watchpoints, but include TLB_WATCHPOINT in the returned flags. ++ * Do handle clean pages, so exclude TLB_NOTDIRY from the returned flags. ++ * For simplicity, all "mmio-like" flags are folded to TLB_MMIO. ++ */ ++int probe_access_flags(CPUArchState *env, target_ulong addr, ++ MMUAccessType access_type, int mmu_idx, ++ bool nonfault, void **phost, uintptr_t retaddr); ++ + #define CODE_GEN_ALIGN 16 /* must be >= of the size of a icache line */ + + /* Estimated block size for TB allocation. */ +-- +2.23.0 + diff --git a/accel-tcg-Adjust-probe_access-call-to-page_check_ran.patch b/accel-tcg-Adjust-probe_access-call-to-page_check_ran.patch new file mode 100644 index 0000000000000000000000000000000000000000..80062e1509e75192017c551a59b21d75c41d1254 --- /dev/null +++ b/accel-tcg-Adjust-probe_access-call-to-page_check_ran.patch @@ -0,0 +1,36 @@ +From 7a1bfee682d8474340ec0fced19b9f0faef9f568 Mon Sep 17 00:00:00 2001 +From: Richard Henderson +Date: Fri, 8 May 2020 08:43:44 -0700 +Subject: [PATCH 368/709] accel/tcg: Adjust probe_access call to + page_check_range + +We have validated that addr+size does not cross a page boundary. +Therefore we need to validate exactly one page. We can achieve +that passing any value 1 <= x <= size to page_check_range. + +Passing 1 will simplify the next patch. + +Signed-off-by: Richard Henderson +Message-id: 20200508154359.7494-5-richard.henderson@linaro.org +Reviewed-by: Peter Maydell +Signed-off-by: Peter Maydell +--- + accel/tcg/user-exec.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/accel/tcg/user-exec.c b/accel/tcg/user-exec.c +index 4be78eb9b3..03538e2a38 100644 +--- a/accel/tcg/user-exec.c ++++ b/accel/tcg/user-exec.c +@@ -211,7 +211,7 @@ void *probe_access(CPUArchState *env, target_ulong addr, int size, + g_assert_not_reached(); + } + +- if (!guest_addr_valid(addr) || page_check_range(addr, size, flags) < 0) { ++ if (!guest_addr_valid(addr) || page_check_range(addr, 1, flags) < 0) { + CPUState *cpu = env_cpu(env); + CPUClass *cc = CPU_GET_CLASS(cpu); + cc->tlb_fill(cpu, addr, size, access_type, MMU_USER_IDX, false, +-- +2.23.0 + diff --git a/accel-tcg-Relax-va-restrictions-on-64-bit-guests.patch b/accel-tcg-Relax-va-restrictions-on-64-bit-guests.patch new file mode 100644 index 0000000000000000000000000000000000000000..59624d339112249cc6f5bb549e30abbb9c0f2526 --- /dev/null +++ b/accel-tcg-Relax-va-restrictions-on-64-bit-guests.patch @@ -0,0 +1,137 @@ +From 7d8cbbabcb1234ffba9a946083073a5e01cdc020 Mon Sep 17 00:00:00 2001 +From: Richard Henderson +Date: Wed, 13 May 2020 18:51:30 +0100 +Subject: [PATCH 494/709] accel/tcg: Relax va restrictions on 64-bit guests +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +We cannot at present limit a 64-bit guest to a virtual address +space smaller than the host. It will mostly work to ignore this +limitation, except if the guest uses high bits of the address +space for tags. But it will certainly work better, as presently +we can wind up failing to allocate the guest stack. + +Widen our user-only page tree to the host or abi pointer width. +Remove the workaround for this problem from target/alpha. +Always validate guest addresses vs reserved_va, as there we +control allocation ourselves. + +Signed-off-by: Richard Henderson +Signed-off-by: Alex Bennée + +Message-Id: <20200513175134.19619-7-alex.bennee@linaro.org> +--- + accel/tcg/translate-all.c | 15 +++++++++------ + include/exec/cpu-all.h | 23 +++++++++++++++++++---- + target/alpha/cpu-param.h | 15 ++------------- + 3 files changed, 30 insertions(+), 23 deletions(-) + +diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c +index 9924e66d1f..e4f703a7e6 100644 +--- a/accel/tcg/translate-all.c ++++ b/accel/tcg/translate-all.c +@@ -173,8 +173,13 @@ struct page_collection { + #define TB_FOR_EACH_JMP(head_tb, tb, n) \ + TB_FOR_EACH_TAGGED((head_tb)->jmp_list_head, tb, n, jmp_list_next) + +-/* In system mode we want L1_MAP to be based on ram offsets, +- while in user mode we want it to be based on virtual addresses. */ ++/* ++ * In system mode we want L1_MAP to be based on ram offsets, ++ * while in user mode we want it to be based on virtual addresses. ++ * ++ * TODO: For user mode, see the caveat re host vs guest virtual ++ * address spaces near GUEST_ADDR_MAX. ++ */ + #if !defined(CONFIG_USER_ONLY) + #if HOST_LONG_BITS < TARGET_PHYS_ADDR_SPACE_BITS + # define L1_MAP_ADDR_SPACE_BITS HOST_LONG_BITS +@@ -182,7 +187,7 @@ struct page_collection { + # define L1_MAP_ADDR_SPACE_BITS TARGET_PHYS_ADDR_SPACE_BITS + #endif + #else +-# define L1_MAP_ADDR_SPACE_BITS TARGET_VIRT_ADDR_SPACE_BITS ++# define L1_MAP_ADDR_SPACE_BITS MIN(HOST_LONG_BITS, TARGET_ABI_BITS) + #endif + + /* Size of the L2 (and L3, etc) page tables. */ +@@ -2497,9 +2502,7 @@ void page_set_flags(target_ulong start, target_ulong end, int flags) + /* 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. */ +-#if TARGET_ABI_BITS > L1_MAP_ADDR_SPACE_BITS +- assert(end <= ((target_ulong)1 << L1_MAP_ADDR_SPACE_BITS)); +-#endif ++ assert(end - 1 <= GUEST_ADDR_MAX); + assert(start < end); + assert_memory_lock(); + +diff --git a/include/exec/cpu-all.h b/include/exec/cpu-all.h +index 0895a57881..d14374bdd4 100644 +--- a/include/exec/cpu-all.h ++++ b/include/exec/cpu-all.h +@@ -162,12 +162,27 @@ extern unsigned long guest_base; + extern bool have_guest_base; + extern unsigned long reserved_va; + +-#if HOST_LONG_BITS <= TARGET_VIRT_ADDR_SPACE_BITS +-#define GUEST_ADDR_MAX (~0ul) ++/* ++ * Limit the guest addresses as best we can. ++ * ++ * When not using -R reserved_va, we cannot really limit the guest ++ * to less address space than the host. For 32-bit guests, this ++ * acts as a sanity check that we're not giving the guest an address ++ * that it cannot even represent. For 64-bit guests... the address ++ * might not be what the real kernel would give, but it is at least ++ * representable in the guest. ++ * ++ * TODO: Improve address allocation to avoid this problem, and to ++ * avoid setting bits at the top of guest addresses that might need ++ * to be used for tags. ++ */ ++#if MIN(TARGET_VIRT_ADDR_SPACE_BITS, TARGET_ABI_BITS) <= 32 ++# define GUEST_ADDR_MAX_ UINT32_MAX + #else +-#define GUEST_ADDR_MAX (reserved_va ? reserved_va - 1 : \ +- (1ul << TARGET_VIRT_ADDR_SPACE_BITS) - 1) ++# define GUEST_ADDR_MAX_ (~0ul) + #endif ++#define GUEST_ADDR_MAX (reserved_va ? reserved_va - 1 : GUEST_ADDR_MAX_) ++ + #else + + #include "exec/hwaddr.h" +diff --git a/target/alpha/cpu-param.h b/target/alpha/cpu-param.h +index 692aee27ca..1153992e42 100644 +--- a/target/alpha/cpu-param.h ++++ b/target/alpha/cpu-param.h +@@ -10,22 +10,11 @@ + + #define TARGET_LONG_BITS 64 + #define TARGET_PAGE_BITS 13 +-#ifdef CONFIG_USER_ONLY +-/* +- * ??? The kernel likes to give addresses in high memory. If the host has +- * more virtual address space than the guest, this can lead to impossible +- * allocations. Honor the long-standing assumption that only kernel addrs +- * are negative, but otherwise allow allocations anywhere. This could lead +- * to tricky emulation problems for programs doing tagged addressing, but +- * that's far fewer than encounter the impossible allocation problem. +- */ +-#define TARGET_PHYS_ADDR_SPACE_BITS 63 +-#define TARGET_VIRT_ADDR_SPACE_BITS 63 +-#else ++ + /* ??? EV4 has 34 phys addr bits, EV5 has 40, EV6 has 44. */ + #define TARGET_PHYS_ADDR_SPACE_BITS 44 + #define TARGET_VIRT_ADDR_SPACE_BITS (30 + TARGET_PAGE_BITS) +-#endif ++ + #define NB_MMU_MODES 3 + + #endif +-- +2.23.0 + diff --git a/accel-tcg-don-t-disable-exec_tb-trace-events.patch b/accel-tcg-don-t-disable-exec_tb-trace-events.patch new file mode 100644 index 0000000000000000000000000000000000000000..be711d6223c318bc4f8727284b660e1b3999dfd7 --- /dev/null +++ b/accel-tcg-don-t-disable-exec_tb-trace-events.patch @@ -0,0 +1,40 @@ +From 6a7aa856c59fba11c119fd2f62a2dbd03f8ca08f Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Alex=20Benn=C3=A9e?= +Date: Wed, 13 May 2020 18:51:31 +0100 +Subject: [PATCH 495/709] accel/tcg: don't disable exec_tb trace events +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +I doubt the well predicted trace event check is particularly special in +the grand context of TCG code execution. + +Signed-off-by: Alex Bennée +Reviewed-by: Philippe Mathieu-Daudé +Message-Id: <20200513175134.19619-8-alex.bennee@linaro.org> +--- + accel/tcg/trace-events | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/accel/tcg/trace-events b/accel/tcg/trace-events +index 01852217a6..385b9f749b 100644 +--- a/accel/tcg/trace-events ++++ b/accel/tcg/trace-events +@@ -1,10 +1,10 @@ + # See docs/devel/tracing.txt for syntax documentation. + +-# TCG related tracing (mostly disabled by default) ++# TCG related tracing + # cpu-exec.c +-disable exec_tb(void *tb, uintptr_t pc) "tb:%p pc=0x%"PRIxPTR +-disable exec_tb_nocache(void *tb, uintptr_t pc) "tb:%p pc=0x%"PRIxPTR +-disable exec_tb_exit(void *last_tb, unsigned int flags) "tb:%p flags=0x%x" ++exec_tb(void *tb, uintptr_t pc) "tb:%p pc=0x%"PRIxPTR ++exec_tb_nocache(void *tb, uintptr_t pc) "tb:%p pc=0x%"PRIxPTR ++exec_tb_exit(void *last_tb, unsigned int flags) "tb:%p flags=0x%x" + + # translate-all.c + translate_block(void *tb, uintptr_t pc, uint8_t *tb_code) "tb:%p, pc:0x%"PRIxPTR", tb_code:%p" +-- +2.23.0 + diff --git a/acpi-Add-Windows-ACPI-Emulated-Device-Table-WAET.patch b/acpi-Add-Windows-ACPI-Emulated-Device-Table-WAET.patch new file mode 100644 index 0000000000000000000000000000000000000000..27c11444bb3f7200d60ad5bdbcabe1c5350e2d68 --- /dev/null +++ b/acpi-Add-Windows-ACPI-Emulated-Device-Table-WAET.patch @@ -0,0 +1,87 @@ +From 14cda3503dc00754bab9ce6c688ea21f791c4a33 Mon Sep 17 00:00:00 2001 +From: Liran Alon +Date: Fri, 13 Mar 2020 16:50:08 +0200 +Subject: [PATCH 227/709] acpi: Add Windows ACPI Emulated Device Table (WAET) + +Microsoft introduced this ACPI table to avoid Windows guests performing +various workarounds for device erratas. As the virtual device emulated +by VMM may not have the errata. + +Currently, WAET allows hypervisor to inform guest about two +specific behaviors: One for RTC and the other for ACPI PM timer. + +Support for WAET have been introduced since Windows Vista. This ACPI +table is also exposed by other common hypervisors by default, including: +VMware, GCP and AWS. + +This patch adds WAET ACPI Table to QEMU. + +We set "ACPI PM timer good" bit in "Emualted Device Flags" field to +indicate that the ACPI PM timer has been enhanced to not require +multiple reads to obtain a reliable value. +This results in improving the performance of Windows guests that use +ACPI PM timer by avoiding unnecessary VMExits caused by these multiple +reads. + +Co-developed-by: Elad Gabay +Signed-off-by: Liran Alon +Message-Id: <20200313145009.144820-3-liran.alon@oracle.com> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +Reviewed-by: Igor Mammedov +--- + hw/i386/acpi-build.c | 31 +++++++++++++++++++++++++++++++ + 1 file changed, 31 insertions(+) + +diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c +index 7d880bec4a..2e15f6848e 100644 +--- a/hw/i386/acpi-build.c ++++ b/hw/i386/acpi-build.c +@@ -2512,6 +2512,34 @@ build_dmar_q35(GArray *table_data, BIOSLinker *linker) + build_header(linker, table_data, (void *)(table_data->data + dmar_start), + "DMAR", table_data->len - dmar_start, 1, NULL, NULL); + } ++ ++/* ++ * Windows ACPI Emulated Devices Table ++ * (Version 1.0 - April 6, 2009) ++ * Spec: http://download.microsoft.com/download/7/E/7/7E7662CF-CBEA-470B-A97E-CE7CE0D98DC2/WAET.docx ++ * ++ * Helpful to speedup Windows guests and ignored by others. ++ */ ++static void ++build_waet(GArray *table_data, BIOSLinker *linker) ++{ ++ int waet_start = table_data->len; ++ ++ /* WAET header */ ++ acpi_data_push(table_data, sizeof(AcpiTableHeader)); ++ /* ++ * Set "ACPI PM timer good" flag. ++ * ++ * Tells Windows guests that our ACPI PM timer is reliable in the ++ * sense that guest can read it only once to obtain a reliable value. ++ * Which avoids costly VMExits caused by guest re-reading it unnecessarily. ++ */ ++ build_append_int_noprefix(table_data, 1 << 1 /* ACPI PM timer good */, 4); ++ ++ build_header(linker, table_data, (void *)(table_data->data + waet_start), ++ "WAET", table_data->len - waet_start, 1, NULL, NULL); ++} ++ + /* + * IVRS table as specified in AMD IOMMU Specification v2.62, Section 5.2 + * accessible here http://support.amd.com/TechDocs/48882_IOMMU.pdf +@@ -2859,6 +2887,9 @@ void acpi_build(AcpiBuildTables *tables, MachineState *machine) + machine->nvdimms_state, machine->ram_slots); + } + ++ acpi_add_table(table_offsets, tables_blob); ++ build_waet(tables_blob, tables->linker); ++ + /* Add tables supplied by user (if any) */ + for (u = acpi_table_first(); u; u = acpi_table_next(u)) { + unsigned len = acpi_table_len(u); +-- +2.23.0 + diff --git a/acpi-DSDT-without-_STA.patch b/acpi-DSDT-without-_STA.patch new file mode 100644 index 0000000000000000000000000000000000000000..81bb389c67418004f9c7f6cd0456172688597622 --- /dev/null +++ b/acpi-DSDT-without-_STA.patch @@ -0,0 +1,39 @@ +From e3a99063af7bc78e51c19cb007acb646d381a9c7 Mon Sep 17 00:00:00 2001 +From: "Michael S. Tsirkin" +Date: Mon, 4 May 2020 08:47:02 -0400 +Subject: [PATCH 217/709] acpi: DSDT without _STA + +commit f6595976e699 ("acpi: drop pointless _STA method") replaced +_STA method with simple name object. Update DSDT accordingly. + +Signed-off-by: Michael S. Tsirkin +--- + tests/qtest/bios-tables-test-allowed-diff.h | 17 ----------------- + 1 files changed, 17 deletions(-) + +diff --git a/tests/qtest/bios-tables-test-allowed-diff.h b/tests/qtest/bios-tables-test-allowed-diff.h +index 6a052c5044..dfb8523c8b 100644 +--- a/tests/qtest/bios-tables-test-allowed-diff.h ++++ b/tests/qtest/bios-tables-test-allowed-diff.h +@@ -1,18 +1 @@ + /* List of comma-separated changed AML files to ignore */ +-"tests/data/acpi/pc/DSDT", +-"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.ipmikcs", +-"tests/data/acpi/pc/DSDT.memhp", +-"tests/data/acpi/pc/DSDT.numamem", +-"tests/data/acpi/q35/DSDT", +-"tests/data/acpi/q35/DSDT.acpihmat", +-"tests/data/acpi/q35/DSDT.bridge", +-"tests/data/acpi/q35/DSDT.cphp", +-"tests/data/acpi/q35/DSDT.dimmpxm", +-"tests/data/acpi/q35/DSDT.ipmibt", +-"tests/data/acpi/q35/DSDT.memhp", +-"tests/data/acpi/q35/DSDT.mmio64", +-"tests/data/acpi/q35/DSDT.numamem", +-- +2.23.0 + diff --git a/acpi-add-ISADeviceClass-build_aml.patch b/acpi-add-ISADeviceClass-build_aml.patch new file mode 100644 index 0000000000000000000000000000000000000000..a833d91c3ec326028a24593f98abefc16c97a0c0 --- /dev/null +++ b/acpi-add-ISADeviceClass-build_aml.patch @@ -0,0 +1,80 @@ +From a53e581ee818d44bea9dcd2c543c2d08a5934fae Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann +Date: Wed, 29 Apr 2020 15:59:53 +0200 +Subject: [PATCH 210/709] acpi: add ISADeviceClass->build_aml() + +Also add isa_aml_build() function which walks all isa devices. +This allows to move aml builder code to isa devices. + +Signed-off-by: Gerd Hoffmann +Reviewed-by: Igor Mammedov +Message-Id: <20200429140003.7336-6-kraxel@redhat.com> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +--- + hw/i386/acpi-build.c | 1 + + hw/isa/isa-bus.c | 15 +++++++++++++++ + include/hw/isa/isa.h | 2 ++ + 3 files changed, 18 insertions(+) + +diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c +index 3a046b03e4..97f3c75cd9 100644 +--- a/hw/i386/acpi-build.c ++++ b/hw/i386/acpi-build.c +@@ -1288,6 +1288,7 @@ static void build_isa_devices_aml(Aml *table) + error_report("No ISA bus, unable to define IPMI ACPI data"); + } else { + build_acpi_ipmi_devices(scope, BUS(obj), "\\_SB.PCI0.ISA"); ++ isa_build_aml(ISA_BUS(obj), scope); + } + + aml_append(table, scope); +diff --git a/hw/isa/isa-bus.c b/hw/isa/isa-bus.c +index 798dd9194e..1f2189f4d5 100644 +--- a/hw/isa/isa-bus.c ++++ b/hw/isa/isa-bus.c +@@ -207,6 +207,21 @@ ISADevice *isa_vga_init(ISABus *bus) + } + } + ++void isa_build_aml(ISABus *bus, Aml *scope) ++{ ++ BusChild *kid; ++ ISADevice *dev; ++ ISADeviceClass *dc; ++ ++ QTAILQ_FOREACH(kid, &bus->parent_obj.children, sibling) { ++ dev = ISA_DEVICE(kid->child); ++ dc = ISA_DEVICE_GET_CLASS(dev); ++ if (dc->build_aml) { ++ dc->build_aml(dev, scope); ++ } ++ } ++} ++ + static void isabus_dev_print(Monitor *mon, DeviceState *dev, int indent) + { + ISADevice *d = ISA_DEVICE(dev); +diff --git a/include/hw/isa/isa.h b/include/hw/isa/isa.h +index 59a4d4b50a..02c2350274 100644 +--- a/include/hw/isa/isa.h ++++ b/include/hw/isa/isa.h +@@ -69,6 +69,7 @@ typedef struct IsaDmaClass { + + typedef struct ISADeviceClass { + DeviceClass parent_class; ++ void (*build_aml)(ISADevice *dev, Aml *scope); + } ISADeviceClass; + + struct ISABus { +@@ -107,6 +108,7 @@ ISADevice *isa_try_create(ISABus *bus, const char *name); + ISADevice *isa_create_simple(ISABus *bus, const char *name); + + ISADevice *isa_vga_init(ISABus *bus); ++void isa_build_aml(ISABus *bus, Aml *scope); + + /** + * isa_register_ioport: Install an I/O port region on the ISA bus. +-- +2.23.0 + diff --git a/acpi-add-aml-builder-stubs.patch b/acpi-add-aml-builder-stubs.patch new file mode 100644 index 0000000000000000000000000000000000000000..3e382753091e4ca981b9c451956757f81f6635cd --- /dev/null +++ b/acpi-add-aml-builder-stubs.patch @@ -0,0 +1,119 @@ +From 17d08ba4659dc66a51a7eab83aeafcc9765d0a87 Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann +Date: Wed, 29 Apr 2020 15:59:50 +0200 +Subject: [PATCH 207/709] acpi: add aml builder stubs + +Needed when moving aml builder code to devices. + +Signed-off-by: Gerd Hoffmann +Reviewed-by: Igor Mammedov +Message-Id: <20200429140003.7336-3-kraxel@redhat.com> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +--- + hw/acpi/Makefile.objs | 4 +- + hw/acpi/aml-build-stub.c | 79 ++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 81 insertions(+), 2 deletions(-) + create mode 100644 hw/acpi/aml-build-stub.c + +diff --git a/hw/acpi/Makefile.objs b/hw/acpi/Makefile.objs +index 777da07f4d..cab9bcd457 100644 +--- a/hw/acpi/Makefile.objs ++++ b/hw/acpi/Makefile.objs +@@ -20,6 +20,6 @@ common-obj-$(CONFIG_TPM) += tpm.o + common-obj-$(CONFIG_IPMI) += ipmi.o + common-obj-$(call lnot,$(CONFIG_IPMI)) += ipmi-stub.o + else +-common-obj-y += acpi-stub.o ++common-obj-y += acpi-stub.o aml-build-stub.o + endif +-common-obj-$(CONFIG_ALL) += acpi-stub.o acpi-x86-stub.o ipmi-stub.o ++common-obj-$(CONFIG_ALL) += acpi-stub.o aml-build-stub.o acpi-x86-stub.o ipmi-stub.o +diff --git a/hw/acpi/aml-build-stub.c b/hw/acpi/aml-build-stub.c +new file mode 100644 +index 0000000000..58b2e16227 +--- /dev/null ++++ b/hw/acpi/aml-build-stub.c +@@ -0,0 +1,79 @@ ++/* ++ * ACPI aml builder stubs for platforms that don't support ACPI. ++ * ++ * Copyright (c) 2006 Fabrice Bellard ++ * Copyright (c) 2016 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 . ++ */ ++ ++#include "qemu/osdep.h" ++#include "hw/acpi/acpi.h" ++#include "hw/acpi/aml-build.h" ++ ++void aml_append(Aml *parent_ctx, Aml *child) ++{ ++} ++ ++Aml *aml_resource_template(void) ++{ ++ return NULL; ++} ++ ++Aml *aml_device(const char *name_format, ...) ++{ ++ return NULL; ++} ++ ++Aml *aml_eisaid(const char *str) ++{ ++ return NULL; ++} ++ ++Aml *aml_name_decl(const char *name, Aml *val) ++{ ++ return NULL; ++} ++ ++Aml *aml_io(AmlIODecode dec, uint16_t min_base, uint16_t max_base, ++ uint8_t aln, uint8_t len) ++{ ++ return NULL; ++} ++ ++Aml *aml_irq_no_flags(uint8_t irq) ++{ ++ return NULL; ++} ++ ++Aml *aml_int(const uint64_t val) ++{ ++ return NULL; ++} ++ ++Aml *aml_package(uint8_t num_elements) ++{ ++ return NULL; ++} ++ ++Aml *aml_dma(AmlDmaType typ, AmlDmaBusMaster bm, AmlTransferSize sz, ++ uint8_t channel) ++{ ++ return NULL; ++} ++ ++Aml *aml_buffer(int buffer_size, uint8_t *byte_list) ++{ ++ return NULL; ++} +-- +2.23.0 + diff --git a/acpi-drop-pointless-_STA-method.patch b/acpi-drop-pointless-_STA-method.patch new file mode 100644 index 0000000000000000000000000000000000000000..dc2f473b4ba9fa5ccba1dc544b423308a1ee9e3e --- /dev/null +++ b/acpi-drop-pointless-_STA-method.patch @@ -0,0 +1,71 @@ +From 88b3648f557855f7da85b5d32f1a08c5a66c2a01 Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann +Date: Wed, 29 Apr 2020 15:59:52 +0200 +Subject: [PATCH 209/709] acpi: drop pointless _STA method +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +When returning a constant there is no point in having a method +in the first place, _STA can be a simple integer instead. + +Signed-off-by: Gerd Hoffmann +Reviewed-by: Igor Mammedov +Message-Id: <20200429140003.7336-5-kraxel@redhat.com> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +Reviewed-by: Philippe Mathieu-Daudé +--- + hw/i386/acpi-build.c | 14 +++----------- + 1 file changed, 3 insertions(+), 11 deletions(-) + +diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c +index 23c77eeb95..3a046b03e4 100644 +--- a/hw/i386/acpi-build.c ++++ b/hw/i386/acpi-build.c +@@ -1151,14 +1151,11 @@ static Aml *build_kbd_device_aml(void) + { + Aml *dev; + Aml *crs; +- Aml *method; + + dev = aml_device("KBD"); + aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0303"))); + +- method = aml_method("_STA", 0, AML_NOTSERIALIZED); +- aml_append(method, aml_return(aml_int(0x0f))); +- aml_append(dev, method); ++ aml_append(dev, aml_name_decl("_STA", aml_int(0xf))); + + crs = aml_resource_template(); + aml_append(crs, aml_io(AML_DECODE16, 0x0060, 0x0060, 0x01, 0x01)); +@@ -1173,14 +1170,11 @@ static Aml *build_mouse_device_aml(void) + { + Aml *dev; + Aml *crs; +- Aml *method; + + dev = aml_device("MOU"); + aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0F13"))); + +- method = aml_method("_STA", 0, AML_NOTSERIALIZED); +- aml_append(method, aml_return(aml_int(0x0f))); +- aml_append(dev, method); ++ aml_append(dev, aml_name_decl("_STA", aml_int(0xf))); + + crs = aml_resource_template(); + aml_append(crs, aml_irq_no_flags(12)); +@@ -2238,9 +2232,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, + TPM_CRB_ADDR_SIZE, AML_READ_WRITE)); + aml_append(dev, aml_name_decl("_CRS", crs)); + +- method = aml_method("_STA", 0, AML_NOTSERIALIZED); +- aml_append(method, aml_return(aml_int(0x0f))); +- aml_append(dev, method); ++ aml_append(dev, aml_name_decl("_STA", aml_int(0xf))); + + tpm_build_ppi_acpi(tpm, dev); + +-- +2.23.0 + diff --git a/acpi-nvdimm-change-NVDIMM_UUID_LE-to-a-common-macro.patch b/acpi-nvdimm-change-NVDIMM_UUID_LE-to-a-common-macro.patch new file mode 100644 index 0000000000000000000000000000000000000000..c9fcf18db533ad3fd0724cf8da2834fd1f67ecd0 --- /dev/null +++ b/acpi-nvdimm-change-NVDIMM_UUID_LE-to-a-common-macro.patch @@ -0,0 +1,93 @@ +From 1439f213074a8ebc30e6713ce1bf766407ddce46 Mon Sep 17 00:00:00 2001 +From: Dongjiu Geng +Date: Tue, 12 May 2020 11:06:00 +0800 +Subject: [PATCH 436/709] acpi: nvdimm: change NVDIMM_UUID_LE to a common macro + +The little end UUID is used in many places, so make +NVDIMM_UUID_LE to a common macro to convert the UUID +to a little end array. + +Reviewed-by: Xiang Zheng +Signed-off-by: Dongjiu Geng +Message-id: 20200512030609.19593-2-gengdongjiu@huawei.com +Reviewed-by: Peter Maydell +Signed-off-by: Peter Maydell +--- + hw/acpi/nvdimm.c | 10 +++------- + include/qemu/uuid.h | 27 +++++++++++++++++++++++++++ + 2 files changed, 30 insertions(+), 7 deletions(-) + +diff --git a/hw/acpi/nvdimm.c b/hw/acpi/nvdimm.c +index fa7bf8b507..9316d12b70 100644 +--- a/hw/acpi/nvdimm.c ++++ b/hw/acpi/nvdimm.c +@@ -27,6 +27,7 @@ + */ + + #include "qemu/osdep.h" ++#include "qemu/uuid.h" + #include "hw/acpi/acpi.h" + #include "hw/acpi/aml-build.h" + #include "hw/acpi/bios-linker-loader.h" +@@ -34,18 +35,13 @@ + #include "hw/mem/nvdimm.h" + #include "qemu/nvdimm-utils.h" + +-#define NVDIMM_UUID_LE(a, b, c, d0, d1, d2, d3, d4, d5, d6, d7) \ +- { (a) & 0xff, ((a) >> 8) & 0xff, ((a) >> 16) & 0xff, ((a) >> 24) & 0xff, \ +- (b) & 0xff, ((b) >> 8) & 0xff, (c) & 0xff, ((c) >> 8) & 0xff, \ +- (d0), (d1), (d2), (d3), (d4), (d5), (d6), (d7) } +- + /* + * define Byte Addressable Persistent Memory (PM) Region according to + * ACPI 6.0: 5.2.25.1 System Physical Address Range Structure. + */ + static const uint8_t nvdimm_nfit_spa_uuid[] = +- NVDIMM_UUID_LE(0x66f0d379, 0xb4f3, 0x4074, 0xac, 0x43, 0x0d, 0x33, +- 0x18, 0xb7, 0x8c, 0xdb); ++ UUID_LE(0x66f0d379, 0xb4f3, 0x4074, 0xac, 0x43, 0x0d, 0x33, ++ 0x18, 0xb7, 0x8c, 0xdb); + + /* + * NVDIMM Firmware Interface Table +diff --git a/include/qemu/uuid.h b/include/qemu/uuid.h +index 129c45f2c5..9925febfa5 100644 +--- a/include/qemu/uuid.h ++++ b/include/qemu/uuid.h +@@ -34,6 +34,33 @@ typedef struct { + }; + } QemuUUID; + ++/** ++ * UUID_LE - converts the fields of UUID to little-endian array, ++ * each of parameters is the filed of UUID. ++ * ++ * @time_low: The low field of the timestamp ++ * @time_mid: The middle field of the timestamp ++ * @time_hi_and_version: The high field of the timestamp ++ * multiplexed with the version number ++ * @clock_seq_hi_and_reserved: The high field of the clock ++ * sequence multiplexed with the variant ++ * @clock_seq_low: The low field of the clock sequence ++ * @node0: The spatially unique node0 identifier ++ * @node1: The spatially unique node1 identifier ++ * @node2: The spatially unique node2 identifier ++ * @node3: The spatially unique node3 identifier ++ * @node4: The spatially unique node4 identifier ++ * @node5: The spatially unique node5 identifier ++ */ ++#define UUID_LE(time_low, time_mid, time_hi_and_version, \ ++ clock_seq_hi_and_reserved, clock_seq_low, node0, node1, node2, \ ++ node3, node4, node5) \ ++ { (time_low) & 0xff, ((time_low) >> 8) & 0xff, ((time_low) >> 16) & 0xff, \ ++ ((time_low) >> 24) & 0xff, (time_mid) & 0xff, ((time_mid) >> 8) & 0xff, \ ++ (time_hi_and_version) & 0xff, ((time_hi_and_version) >> 8) & 0xff, \ ++ (clock_seq_hi_and_reserved), (clock_seq_low), (node0), (node1), (node2),\ ++ (node3), (node4), (node5) } ++ + #define UUID_FMT "%02hhx%02hhx%02hhx%02hhx-" \ + "%02hhx%02hhx-%02hhx%02hhx-" \ + "%02hhx%02hhx-" \ +-- +2.23.0 + diff --git a/acpi-unit-test-Ignore-diff-in-WAET-ACPI-table.patch b/acpi-unit-test-Ignore-diff-in-WAET-ACPI-table.patch new file mode 100644 index 0000000000000000000000000000000000000000..45345fa451ee01f4e0917738b08ad08fcceed32f --- /dev/null +++ b/acpi-unit-test-Ignore-diff-in-WAET-ACPI-table.patch @@ -0,0 +1,40 @@ +From 4b773fc2f7e56cddc9c192e0c95b3097dbbcf1e9 Mon Sep 17 00:00:00 2001 +From: Liran Alon +Date: Fri, 13 Mar 2020 16:50:07 +0200 +Subject: [PATCH 226/709] acpi: unit-test: Ignore diff in WAET ACPI table + +This is done as a preparation for the following patch to expose WAET +ACPI table to guest. + +This patch performs steps 1-3 as describes in +tests/qtest/bios-tables-test.c. + +Signed-off-by: Liran Alon +Message-Id: <20200313145009.144820-2-liran.alon@oracle.com> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +--- + tests/data/acpi/pc/WAET | 0 + tests/data/acpi/q35/WAET | 0 + tests/qtest/bios-tables-test-allowed-diff.h | 2 ++ + 3 files changed, 2 insertions(+) + create mode 100644 tests/data/acpi/pc/WAET + create mode 100644 tests/data/acpi/q35/WAET + +diff --git a/tests/data/acpi/pc/WAET b/tests/data/acpi/pc/WAET +new file mode 100644 +index 0000000000..e69de29bb2 +diff --git a/tests/data/acpi/q35/WAET b/tests/data/acpi/q35/WAET +new file mode 100644 +index 0000000000..e69de29bb2 +diff --git a/tests/qtest/bios-tables-test-allowed-diff.h b/tests/qtest/bios-tables-test-allowed-diff.h +index dfb8523c8b..b269a1e3e5 100644 +--- a/tests/qtest/bios-tables-test-allowed-diff.h ++++ b/tests/qtest/bios-tables-test-allowed-diff.h +@@ -1 +1,3 @@ + /* List of comma-separated changed AML files to ignore */ ++"tests/data/acpi/pc/WAET", ++"tests/data/acpi/q35/WAET", +-- +2.23.0 + diff --git a/acpi-unit-test-Update-WAET-ACPI-Table-expected-binar.patch b/acpi-unit-test-Update-WAET-ACPI-Table-expected-binar.patch new file mode 100644 index 0000000000000000000000000000000000000000..b001ea8220643c230312d9c9c8aa8268b9fa1f8f --- /dev/null +++ b/acpi-unit-test-Update-WAET-ACPI-Table-expected-binar.patch @@ -0,0 +1,50 @@ +From 1aaef7d809280388e4e0b73cd21f5aa0a6443b75 Mon Sep 17 00:00:00 2001 +From: Liran Alon +Date: Fri, 13 Mar 2020 16:50:09 +0200 +Subject: [PATCH 228/709] acpi: unit-test: Update WAET ACPI Table expected + binaries + +This is done according to step (6) in the process described at +tests/qtest/bios-tables-test.c. + +Expected WAET.dsl: + +[000h 0000 4] Signature : "WAET" [Windows ACPI Emulated Devices Table] +[004h 0004 4] Table Length : 00000028 +[008h 0008 1] Revision : 01 +[009h 0009 1] Checksum : 88 +[00Ah 0010 6] Oem ID : "BOCHS " +[010h 0016 8] Oem Table ID : "BXPCWAET" +[018h 0024 4] Oem Revision : 00000001 +[01Ch 0028 4] Asl Compiler ID : "BXPC" +[020h 0032 4] Asl Compiler Revision : 00000001 + +[024h 0036 4] Flags (decoded below) : 00000002 + RTC needs no INT ack : 0 + PM timer, one read only : 1 + +Raw Table Data: Length 40 (0x28) + + 0000: 57 41 45 54 28 00 00 00 01 88 42 4F 43 48 53 20 // WAET(.....BOCHS + 0010: 42 58 50 43 57 41 45 54 01 00 00 00 42 58 50 43 // BXPCWAET....BXPC + 0020: 01 00 00 00 02 00 00 00 // ........ + +Signed-off-by: Liran Alon +Message-Id: <20200313145009.144820-4-liran.alon@oracle.com> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +--- + tests/qtest/bios-tables-test-allowed-diff.h | 2 -- + 1 files changed, 2 deletions(-) + +diff --git a/tests/qtest/bios-tables-test-allowed-diff.h b/tests/qtest/bios-tables-test-allowed-diff.h +index b269a1e3e5..dfb8523c8b 100644 +--- a/tests/qtest/bios-tables-test-allowed-diff.h ++++ b/tests/qtest/bios-tables-test-allowed-diff.h +@@ -1,3 +1 @@ + /* List of comma-separated changed AML files to ignore */ +-"tests/data/acpi/pc/WAET", +-"tests/data/acpi/q35/WAET", +-- +2.23.0 + diff --git a/aio-posix-disable-fdmon-io_uring-when-GSource-is-use.patch b/aio-posix-disable-fdmon-io_uring-when-GSource-is-use.patch new file mode 100644 index 0000000000000000000000000000000000000000..ec9596853cf1420226b4292ac9ebd8b26568b7b7 --- /dev/null +++ b/aio-posix-disable-fdmon-io_uring-when-GSource-is-use.patch @@ -0,0 +1,96 @@ +From ba607ca8bff4d2c2062902f8355657c865ac7c29 Mon Sep 17 00:00:00 2001 +From: Stefan Hajnoczi +Date: Mon, 11 May 2020 19:36:30 +0100 +Subject: [PATCH 574/709] aio-posix: disable fdmon-io_uring when GSource is + used + +The glib event loop does not call fdmon_io_uring_wait() so fd handlers +waiting to be submitted build up in the list. There is no benefit is +using io_uring when the glib GSource is being used, so disable it +instead of implementing a more complex fix. + +This fixes a memory leak where AioHandlers would build up and increasing +amounts of CPU time were spent iterating them in aio_pending(). The +symptom is that guests become slow when QEMU is built with io_uring +support. + +Buglink: https://bugs.launchpad.net/qemu/+bug/1877716 +Fixes: 73fd282e7b6dd4e4ea1c3bbb3d302c8db51e4ccf ("aio-posix: add io_uring fd monitoring implementation") +Signed-off-by: Stefan Hajnoczi +Tested-by: Oleksandr Natalenko +Message-id: 20200511183630.279750-3-stefanha@redhat.com +Signed-off-by: Stefan Hajnoczi +--- + include/block/aio.h | 3 +++ + util/aio-posix.c | 12 ++++++++++++ + util/aio-win32.c | 4 ++++ + util/async.c | 1 + + 4 files changed, 20 insertions(+) + +diff --git a/include/block/aio.h b/include/block/aio.h +index 62ed954344..b2f703fa3f 100644 +--- a/include/block/aio.h ++++ b/include/block/aio.h +@@ -701,6 +701,9 @@ void aio_context_setup(AioContext *ctx); + */ + void aio_context_destroy(AioContext *ctx); + ++/* Used internally, do not call outside AioContext code */ ++void aio_context_use_g_source(AioContext *ctx); ++ + /** + * aio_context_set_poll_params: + * @ctx: the aio context +diff --git a/util/aio-posix.c b/util/aio-posix.c +index 8af334ab19..1b2a3af65b 100644 +--- a/util/aio-posix.c ++++ b/util/aio-posix.c +@@ -682,6 +682,18 @@ void aio_context_destroy(AioContext *ctx) + aio_free_deleted_handlers(ctx); + } + ++void aio_context_use_g_source(AioContext *ctx) ++{ ++ /* ++ * Disable io_uring when the glib main loop is used because it doesn't ++ * support mixed glib/aio_poll() usage. It relies on aio_poll() being ++ * called regularly so that changes to the monitored file descriptors are ++ * submitted, otherwise a list of pending fd handlers builds up. ++ */ ++ fdmon_io_uring_destroy(ctx); ++ aio_free_deleted_handlers(ctx); ++} ++ + void aio_context_set_poll_params(AioContext *ctx, int64_t max_ns, + int64_t grow, int64_t shrink, Error **errp) + { +diff --git a/util/aio-win32.c b/util/aio-win32.c +index 729d533faf..953c56ab48 100644 +--- a/util/aio-win32.c ++++ b/util/aio-win32.c +@@ -414,6 +414,10 @@ void aio_context_destroy(AioContext *ctx) + { + } + ++void aio_context_use_g_source(AioContext *ctx) ++{ ++} ++ + void aio_context_set_poll_params(AioContext *ctx, int64_t max_ns, + int64_t grow, int64_t shrink, Error **errp) + { +diff --git a/util/async.c b/util/async.c +index 3165a28f2f..1319eee3bc 100644 +--- a/util/async.c ++++ b/util/async.c +@@ -362,6 +362,7 @@ static GSourceFuncs aio_source_funcs = { + + GSource *aio_get_g_source(AioContext *ctx) + { ++ aio_context_use_g_source(ctx); + g_source_ref(&ctx->source); + return &ctx->source; + } +-- +2.23.0 + diff --git a/aio-posix-don-t-duplicate-fd-handler-deletion-in-fdm.patch b/aio-posix-don-t-duplicate-fd-handler-deletion-in-fdm.patch new file mode 100644 index 0000000000000000000000000000000000000000..86e83cea56b7cf36f6bbab3626b33ebe31fd5354 --- /dev/null +++ b/aio-posix-don-t-duplicate-fd-handler-deletion-in-fdm.patch @@ -0,0 +1,71 @@ +From de137e44f75d9868f5b548638081850f6ac771f2 Mon Sep 17 00:00:00 2001 +From: Stefan Hajnoczi +Date: Mon, 11 May 2020 19:36:29 +0100 +Subject: [PATCH 573/709] aio-posix: don't duplicate fd handler deletion in + fdmon_io_uring_destroy() + +The io_uring file descriptor monitoring implementation has an internal +list of fd handlers that are pending submission to io_uring. +fdmon_io_uring_destroy() deletes all fd handlers on the list. + +Don't delete fd handlers directly in fdmon_io_uring_destroy() for two +reasons: +1. This duplicates the aio-posix.c AioHandler deletion code and could + become outdated if the struct changes. +2. Only handlers with the FDMON_IO_URING_REMOVE flag set are safe to + remove. If the flag is not set then something still has a pointer to + the fd handler. Let aio-posix.c and its user worry about that. In + practice this isn't an issue because fdmon_io_uring_destroy() is only + called when shutting down so all users have removed their fd + handlers, but the next patch will need this! + +Signed-off-by: Stefan Hajnoczi +Tested-by: Oleksandr Natalenko +Message-id: 20200511183630.279750-2-stefanha@redhat.com +Signed-off-by: Stefan Hajnoczi +--- + util/aio-posix.c | 1 + + util/fdmon-io_uring.c | 13 ++++++++++--- + 2 files changed, 11 insertions(+), 3 deletions(-) + +diff --git a/util/aio-posix.c b/util/aio-posix.c +index c3613d299e..8af334ab19 100644 +--- a/util/aio-posix.c ++++ b/util/aio-posix.c +@@ -679,6 +679,7 @@ void aio_context_destroy(AioContext *ctx) + { + fdmon_io_uring_destroy(ctx); + fdmon_epoll_disable(ctx); ++ aio_free_deleted_handlers(ctx); + } + + void aio_context_set_poll_params(AioContext *ctx, int64_t max_ns, +diff --git a/util/fdmon-io_uring.c b/util/fdmon-io_uring.c +index d5a80ed6fb..1d14177df0 100644 +--- a/util/fdmon-io_uring.c ++++ b/util/fdmon-io_uring.c +@@ -342,11 +342,18 @@ void fdmon_io_uring_destroy(AioContext *ctx) + + io_uring_queue_exit(&ctx->fdmon_io_uring); + +- /* No need to submit these anymore, just free them. */ ++ /* Move handlers due to be removed onto the deleted list */ + while ((node = QSLIST_FIRST_RCU(&ctx->submit_list))) { ++ unsigned flags = atomic_fetch_and(&node->flags, ++ ~(FDMON_IO_URING_PENDING | ++ FDMON_IO_URING_ADD | ++ FDMON_IO_URING_REMOVE)); ++ ++ if (flags & FDMON_IO_URING_REMOVE) { ++ QLIST_INSERT_HEAD_RCU(&ctx->deleted_aio_handlers, node, node_deleted); ++ } ++ + QSLIST_REMOVE_HEAD_RCU(&ctx->submit_list, node_submitted); +- QLIST_REMOVE(node, node); +- g_free(node); + } + + ctx->fdmon_ops = &fdmon_poll_ops; +-- +2.23.0 + diff --git a/arm-translate-a64-fix-uninitialized-variable-warning.patch b/arm-translate-a64-fix-uninitialized-variable-warning.patch deleted file mode 100644 index 8e31bbf51e12d63818e74aca17f94020301c7855..0000000000000000000000000000000000000000 --- a/arm-translate-a64-fix-uninitialized-variable-warning.patch +++ /dev/null @@ -1,36 +0,0 @@ -From b4bab3bf6a75d97d2f1098c4dc52d35ced003c70 Mon Sep 17 00:00:00 2001 -From: Pan Nengyuan -Date: Mon, 13 Jan 2020 17:01:11 +0800 -Subject: [PATCH] arm/translate-a64: fix uninitialized variable warning - -Fixes: -target/arm/translate-a64.c: In function 'disas_crypto_three_reg_sha512': -target/arm/translate-a64.c:13625:9: error: 'genfn' may be used uninitialized in this function [-Werror=maybe-uninitialized] - genfn(tcg_rd_ptr, tcg_rn_ptr, tcg_rm_ptr); - ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -qemu/target/arm/translate-a64.c:13609:8: error: 'feature' may be used uninitialized in this function [-Werror=maybe-uninitialized] - if (!feature) { - -Reported-by: Euler Robot -Signed-off-by: Pan Nengyuan ---- - target/arm/translate-a64.c | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c -index dcdeb801..5f423d5d 100644 ---- a/target/arm/translate-a64.c -+++ b/target/arm/translate-a64.c -@@ -13767,6 +13767,8 @@ static void disas_crypto_three_reg_sha512(DisasContext *s, uint32_t insn) - feature = dc_isar_feature(aa64_sha3, s); - genfn = NULL; - break; -+ default: -+ g_assert_not_reached(); - } - } else { - switch (opcode) { --- -2.18.1 - - diff --git a/arm-virt-Fix-virt_machine_device_plug_cb-error-API-v.patch b/arm-virt-Fix-virt_machine_device_plug_cb-error-API-v.patch new file mode 100644 index 0000000000000000000000000000000000000000..7afb22631b97011da82e6111e557d0779dea2e54 --- /dev/null +++ b/arm-virt-Fix-virt_machine_device_plug_cb-error-API-v.patch @@ -0,0 +1,54 @@ +From 0fbddcecf23dcc311b42d9faf87dc2656dadd62a Mon Sep 17 00:00:00 2001 +From: Markus Armbruster +Date: Wed, 22 Apr 2020 15:07:10 +0200 +Subject: [PATCH 018/709] arm/virt: Fix virt_machine_device_plug_cb() error API + violation +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The Error ** argument must be NULL, &error_abort, &error_fatal, or a +pointer to a variable containing NULL. Passing an argument of the +latter kind twice without clearing it in between is wrong: if the +first call sets an error, it no longer points to NULL for the second +call. + +virt_machine_device_plug_cb() passes @errp to +cryptodev_builtin_sym_close_session() in a loop. Harmless, because +cryptodev_builtin_sym_close_session() can't actually fail. Fix by +dropping its Error ** parameter. + +Cc: Peter Maydell +Cc: qemu-arm@nongnu.org +Signed-off-by: Markus Armbruster +Reviewed-by: Philippe Mathieu-Daudé +Message-Id: <20200422130719.28225-6-armbru@redhat.com> +--- + 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 7dc96abf72..cca5316256 100644 +--- a/hw/arm/virt.c ++++ b/hw/arm/virt.c +@@ -1186,7 +1186,7 @@ static void create_smmu(const VirtMachineState *vms, + g_free(node); + } + +-static void create_virtio_iommu_dt_bindings(VirtMachineState *vms, Error **errp) ++static void create_virtio_iommu_dt_bindings(VirtMachineState *vms) + { + const char compat[] = "virtio,pci-iommu"; + uint16_t bdf = vms->virtio_iommu_bdf; +@@ -2118,7 +2118,7 @@ static void virt_machine_device_plug_cb(HotplugHandler *hotplug_dev, + + vms->iommu = VIRT_IOMMU_VIRTIO; + vms->virtio_iommu_bdf = pci_get_bdf(pdev); +- create_virtio_iommu_dt_bindings(vms, errp); ++ create_virtio_iommu_dt_bindings(vms); + } + } + +-- +2.23.0 + diff --git a/aspeed-Add-boot-stub-for-smp-booting.patch b/aspeed-Add-boot-stub-for-smp-booting.patch new file mode 100644 index 0000000000000000000000000000000000000000..1b31451527ce93a8662f0556cae7c29eeb41d1f9 --- /dev/null +++ b/aspeed-Add-boot-stub-for-smp-booting.patch @@ -0,0 +1,137 @@ +From 9bb6d14081ce0859480168b1c322b6a88706161e Mon Sep 17 00:00:00 2001 +From: Joel Stanley +Date: Thu, 9 Apr 2020 16:01:37 +0930 +Subject: [PATCH 358/709] aspeed: Add boot stub for smp booting +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This is a boot stub that is similar to the code u-boot runs, allowing +the kernel to boot the secondary CPU. + +u-boot works as follows: + + 1. Initialises the SMP mailbox area in the SCU at 0x1e6e2180 with default values + + 2. Copies a stub named 'mailbox_insn' from flash to the SCU, just above the + mailbox area + + 3. Sets AST_SMP_MBOX_FIELD_READY to a magic value to indicate the + secondary can begin execution from the stub + + 4. The stub waits until the AST_SMP_MBOX_FIELD_GOSIGN register is set to + a magic value + + 5. Jumps to the address in AST_SMP_MBOX_FIELD_ENTRY, starting Linux + +Linux indicates it is ready by writing the address of its entrypoint +function to AST_SMP_MBOX_FIELD_ENTRY and the 'go' magic number to +AST_SMP_MBOX_FIELD_GOSIGN. The secondary CPU sees this at step 4 and +breaks out of it's loop. + +To be compatible, a fixed qemu stub is loaded into the mailbox area. As +qemu can ensure the stub is loaded before execution starts, we do not +need to emulate the AST_SMP_MBOX_FIELD_READY behaviour of u-boot. The +secondary CPU's program counter points to the beginning of the stub, +allowing qemu to start secondaries at step four. + +Reboot behaviour is preserved by resetting AST_SMP_MBOX_FIELD_GOSIGN +when the secondaries are reset. + +This is only configured when the system is booted with -kernel and qemu +does not execute u-boot first. + +Reviewed-by: Cédric Le Goater +Tested-by: Cédric Le Goater +Signed-off-by: Joel Stanley +Signed-off-by: Peter Maydell +--- + hw/arm/aspeed.c | 65 +++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 65 insertions(+) + +diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c +index a6a2102a93..a3a8cd0a58 100644 +--- a/hw/arm/aspeed.c ++++ b/hw/arm/aspeed.c +@@ -116,6 +116,58 @@ static const MemoryRegionOps max_ram_ops = { + .endianness = DEVICE_NATIVE_ENDIAN, + }; + ++#define AST_SMP_MAILBOX_BASE 0x1e6e2180 ++#define AST_SMP_MBOX_FIELD_ENTRY (AST_SMP_MAILBOX_BASE + 0x0) ++#define AST_SMP_MBOX_FIELD_GOSIGN (AST_SMP_MAILBOX_BASE + 0x4) ++#define AST_SMP_MBOX_FIELD_READY (AST_SMP_MAILBOX_BASE + 0x8) ++#define AST_SMP_MBOX_FIELD_POLLINSN (AST_SMP_MAILBOX_BASE + 0xc) ++#define AST_SMP_MBOX_CODE (AST_SMP_MAILBOX_BASE + 0x10) ++#define AST_SMP_MBOX_GOSIGN 0xabbaab00 ++ ++static void aspeed_write_smpboot(ARMCPU *cpu, ++ const struct arm_boot_info *info) ++{ ++ static const uint32_t poll_mailbox_ready[] = { ++ /* ++ * r2 = per-cpu go sign value ++ * r1 = AST_SMP_MBOX_FIELD_ENTRY ++ * r0 = AST_SMP_MBOX_FIELD_GOSIGN ++ */ ++ 0xee100fb0, /* mrc p15, 0, r0, c0, c0, 5 */ ++ 0xe21000ff, /* ands r0, r0, #255 */ ++ 0xe59f201c, /* ldr r2, [pc, #28] */ ++ 0xe1822000, /* orr r2, r2, r0 */ ++ ++ 0xe59f1018, /* ldr r1, [pc, #24] */ ++ 0xe59f0018, /* ldr r0, [pc, #24] */ ++ ++ 0xe320f002, /* wfe */ ++ 0xe5904000, /* ldr r4, [r0] */ ++ 0xe1520004, /* cmp r2, r4 */ ++ 0x1afffffb, /* bne */ ++ 0xe591f000, /* ldr pc, [r1] */ ++ AST_SMP_MBOX_GOSIGN, ++ AST_SMP_MBOX_FIELD_ENTRY, ++ AST_SMP_MBOX_FIELD_GOSIGN, ++ }; ++ ++ rom_add_blob_fixed("aspeed.smpboot", poll_mailbox_ready, ++ sizeof(poll_mailbox_ready), ++ info->smp_loader_start); ++} ++ ++static void aspeed_reset_secondary(ARMCPU *cpu, ++ const struct arm_boot_info *info) ++{ ++ AddressSpace *as = arm_boot_address_space(cpu, info); ++ CPUState *cs = CPU(cpu); ++ ++ /* info->smp_bootreg_addr */ ++ address_space_stl_notdirty(as, AST_SMP_MBOX_FIELD_GOSIGN, 0, ++ MEMTXATTRS_UNSPECIFIED, NULL); ++ cpu_set_pc(cs, info->smp_loader_start); ++} ++ + #define FIRMWARE_ADDR 0x0 + + static void write_boot_rom(DriveInfo *dinfo, hwaddr addr, size_t rom_size, +@@ -270,6 +322,19 @@ static void aspeed_machine_init(MachineState *machine) + } + } + ++ if (machine->kernel_filename && bmc->soc.num_cpus > 1) { ++ /* With no u-boot we must set up a boot stub for the secondary CPU */ ++ MemoryRegion *smpboot = g_new(MemoryRegion, 1); ++ memory_region_init_ram(smpboot, OBJECT(bmc), "aspeed.smpboot", ++ 0x80, &error_abort); ++ memory_region_add_subregion(get_system_memory(), ++ AST_SMP_MAILBOX_BASE, smpboot); ++ ++ aspeed_board_binfo.write_secondary_boot = aspeed_write_smpboot; ++ aspeed_board_binfo.secondary_cpu_reset_hook = aspeed_reset_secondary; ++ aspeed_board_binfo.smp_loader_start = AST_SMP_MBOX_CODE; ++ } ++ + aspeed_board_binfo.ram_size = ram_size; + aspeed_board_binfo.loader_start = sc->memmap[ASPEED_SDRAM]; + aspeed_board_binfo.nb_cpus = bmc->soc.num_cpus; +-- +2.23.0 + diff --git a/aspeed-Add-support-for-the-sonorapass-bmc-board.patch b/aspeed-Add-support-for-the-sonorapass-bmc-board.patch new file mode 100644 index 0000000000000000000000000000000000000000..ea1392e32d60fef85d19c285528c6dc20fae3e01 --- /dev/null +++ b/aspeed-Add-support-for-the-sonorapass-bmc-board.patch @@ -0,0 +1,139 @@ +From 143b040f4abfafcbb562252df9fb350192ae6160 Mon Sep 17 00:00:00 2001 +From: Patrick Williams +Date: Wed, 6 May 2020 13:32:19 -0500 +Subject: [PATCH 435/709] aspeed: Add support for the sonorapass-bmc board +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Sonora Pass is a 2 socket x86 motherboard designed by Facebook +and supported by OpenBMC. Strapping configuration was obtained +from hardware and i2c configuration is based on dts found at: + +https://github.com/facebook/openbmc-linux/blob/1633c87b8ba7c162095787c988979b748ba65dc8/arch/arm/boot/dts/aspeed-bmc-facebook-sonorapass.dts + +Booted a test image of http://github.com/facebook/openbmc to login +prompt. + +Signed-off-by: Patrick Williams +Reviewed-by: Amithash Prasad +Reviewed-by: Cédric Le Goater +[PMM: fixed block comment style nit] +Signed-off-by: Peter Maydell +--- + hw/arm/aspeed.c | 78 +++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 78 insertions(+) + +diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c +index 1eacb2fc17..4d57d1e436 100644 +--- a/hw/arm/aspeed.c ++++ b/hw/arm/aspeed.c +@@ -73,6 +73,21 @@ struct AspeedBoardState { + SCU_AST2500_HW_STRAP_ACPI_ENABLE | \ + SCU_HW_STRAP_SPI_MODE(SCU_HW_STRAP_SPI_MASTER)) + ++/* Sonorapass hardware value: 0xF100D216 */ ++#define SONORAPASS_BMC_HW_STRAP1 ( \ ++ SCU_AST2500_HW_STRAP_SPI_AUTOFETCH_ENABLE | \ ++ SCU_AST2500_HW_STRAP_GPIO_STRAP_ENABLE | \ ++ SCU_AST2500_HW_STRAP_UART_DEBUG | \ ++ SCU_AST2500_HW_STRAP_RESERVED28 | \ ++ SCU_AST2500_HW_STRAP_DDR4_ENABLE | \ ++ SCU_HW_STRAP_VGA_CLASS_CODE | \ ++ SCU_HW_STRAP_LPC_RESET_PIN | \ ++ SCU_HW_STRAP_SPI_MODE(SCU_HW_STRAP_SPI_MASTER) | \ ++ SCU_AST2500_HW_STRAP_SET_AXI_AHB_RATIO(AXI_AHB_RATIO_2_1) | \ ++ SCU_HW_STRAP_VGA_BIOS_ROM | \ ++ SCU_HW_STRAP_VGA_SIZE_SET(VGA_16M_DRAM) | \ ++ SCU_AST2500_HW_STRAP_RESERVED1) ++ + /* Swift hardware value: 0xF11AD206 */ + #define SWIFT_BMC_HW_STRAP1 ( \ + AST2500_HW_STRAP1_DEFAULTS | \ +@@ -437,6 +452,50 @@ static void swift_bmc_i2c_init(AspeedBoardState *bmc) + i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 12), "tmp105", 0x4a); + } + ++static void sonorapass_bmc_i2c_init(AspeedBoardState *bmc) ++{ ++ AspeedSoCState *soc = &bmc->soc; ++ ++ /* bus 2 : */ ++ i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 2), "tmp105", 0x48); ++ i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 2), "tmp105", 0x49); ++ /* bus 2 : pca9546 @ 0x73 */ ++ ++ /* bus 3 : pca9548 @ 0x70 */ ++ ++ /* bus 4 : */ ++ uint8_t *eeprom4_54 = g_malloc0(8 * 1024); ++ smbus_eeprom_init_one(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 4), 0x54, ++ eeprom4_54); ++ /* PCA9539 @ 0x76, but PCA9552 is compatible */ ++ i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 4), "pca9552", 0x76); ++ /* PCA9539 @ 0x77, but PCA9552 is compatible */ ++ i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 4), "pca9552", 0x77); ++ ++ /* bus 6 : */ ++ i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 6), "tmp105", 0x48); ++ i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 6), "tmp105", 0x49); ++ /* bus 6 : pca9546 @ 0x73 */ ++ ++ /* bus 8 : */ ++ uint8_t *eeprom8_56 = g_malloc0(8 * 1024); ++ smbus_eeprom_init_one(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 8), 0x56, ++ eeprom8_56); ++ i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 8), "pca9552", 0x60); ++ i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 8), "pca9552", 0x61); ++ /* bus 8 : adc128d818 @ 0x1d */ ++ /* bus 8 : adc128d818 @ 0x1f */ ++ ++ /* ++ * bus 13 : pca9548 @ 0x71 ++ * - channel 3: ++ * - tmm421 @ 0x4c ++ * - tmp421 @ 0x4e ++ * - tmp421 @ 0x4f ++ */ ++ ++} ++ + static void witherspoon_bmc_i2c_init(AspeedBoardState *bmc) + { + AspeedSoCState *soc = &bmc->soc; +@@ -549,6 +608,21 @@ static void aspeed_machine_romulus_class_init(ObjectClass *oc, void *data) + mc->default_ram_size = 512 * MiB; + }; + ++static void aspeed_machine_sonorapass_class_init(ObjectClass *oc, void *data) ++{ ++ MachineClass *mc = MACHINE_CLASS(oc); ++ AspeedMachineClass *amc = ASPEED_MACHINE_CLASS(oc); ++ ++ mc->desc = "OCP SonoraPass BMC (ARM1176)"; ++ amc->soc_name = "ast2500-a1"; ++ amc->hw_strap1 = SONORAPASS_BMC_HW_STRAP1; ++ amc->fmc_model = "mx66l1g45g"; ++ amc->spi_model = "mx66l1g45g"; ++ amc->num_cs = 2; ++ amc->i2c_init = sonorapass_bmc_i2c_init; ++ mc->default_ram_size = 512 * MiB; ++}; ++ + static void aspeed_machine_swift_class_init(ObjectClass *oc, void *data) + { + MachineClass *mc = MACHINE_CLASS(oc); +@@ -628,6 +702,10 @@ static const TypeInfo aspeed_machine_types[] = { + .name = MACHINE_TYPE_NAME("swift-bmc"), + .parent = TYPE_ASPEED_MACHINE, + .class_init = aspeed_machine_swift_class_init, ++ }, { ++ .name = MACHINE_TYPE_NAME("sonorapass-bmc"), ++ .parent = TYPE_ASPEED_MACHINE, ++ .class_init = aspeed_machine_sonorapass_class_init, + }, { + .name = MACHINE_TYPE_NAME("witherspoon-bmc"), + .parent = TYPE_ASPEED_MACHINE, +-- +2.23.0 + diff --git a/aspeed-Support-AST2600A1-silicon-revision.patch b/aspeed-Support-AST2600A1-silicon-revision.patch new file mode 100644 index 0000000000000000000000000000000000000000..617715127f1843c84ece475457f2e8a420c1c6d6 --- /dev/null +++ b/aspeed-Support-AST2600A1-silicon-revision.patch @@ -0,0 +1,136 @@ +From 7582591ae745f224a58fd9a36e3b9230fb03bfc2 Mon Sep 17 00:00:00 2001 +From: Joel Stanley +Date: Mon, 4 May 2020 19:07:03 +0930 +Subject: [PATCH 360/709] aspeed: Support AST2600A1 silicon revision +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +There are minimal differences from Qemu's point of view between the A0 +and A1 silicon revisions. + +As the A1 exercises different code paths in u-boot it is desirable to +emulate that instead. + +Signed-off-by: Joel Stanley +Reviewed-by: Andrew Jeffery +Reviewed-by: Cédric Le Goater +Message-id: 20200504093703.261135-1-joel@jms.id.au +Signed-off-by: Peter Maydell +--- + hw/arm/aspeed.c | 8 ++++---- + hw/arm/aspeed_ast2600.c | 6 +++--- + hw/misc/aspeed_scu.c | 11 +++++------ + include/hw/misc/aspeed_scu.h | 1 + + 4 files changed, 13 insertions(+), 13 deletions(-) + +diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c +index a3a8cd0a58..1eacb2fc17 100644 +--- a/hw/arm/aspeed.c ++++ b/hw/arm/aspeed.c +@@ -93,7 +93,7 @@ struct AspeedBoardState { + + /* Tacoma hardware value */ + #define TACOMA_BMC_HW_STRAP1 0x00000000 +-#define TACOMA_BMC_HW_STRAP2 0x00000000 ++#define TACOMA_BMC_HW_STRAP2 0x00000040 + + /* + * The max ram region is for firmwares that scan the address space +@@ -585,7 +585,7 @@ static void aspeed_machine_ast2600_evb_class_init(ObjectClass *oc, void *data) + AspeedMachineClass *amc = ASPEED_MACHINE_CLASS(oc); + + mc->desc = "Aspeed AST2600 EVB (Cortex A7)"; +- amc->soc_name = "ast2600-a0"; ++ amc->soc_name = "ast2600-a1"; + amc->hw_strap1 = AST2600_EVB_HW_STRAP1; + amc->hw_strap2 = AST2600_EVB_HW_STRAP2; + amc->fmc_model = "w25q512jv"; +@@ -600,8 +600,8 @@ static void aspeed_machine_tacoma_class_init(ObjectClass *oc, void *data) + MachineClass *mc = MACHINE_CLASS(oc); + AspeedMachineClass *amc = ASPEED_MACHINE_CLASS(oc); + +- mc->desc = "Aspeed AST2600 EVB (Cortex A7)"; +- amc->soc_name = "ast2600-a0"; ++ mc->desc = "OpenPOWER Tacoma BMC (Cortex A7)"; ++ amc->soc_name = "ast2600-a1"; + amc->hw_strap1 = TACOMA_BMC_HW_STRAP1; + amc->hw_strap2 = TACOMA_BMC_HW_STRAP2; + amc->fmc_model = "mx66l1g45g"; +diff --git a/hw/arm/aspeed_ast2600.c b/hw/arm/aspeed_ast2600.c +index 1a869e09b9..c6e0ab84ac 100644 +--- a/hw/arm/aspeed_ast2600.c ++++ b/hw/arm/aspeed_ast2600.c +@@ -557,9 +557,9 @@ static void aspeed_soc_ast2600_class_init(ObjectClass *oc, void *data) + + dc->realize = aspeed_soc_ast2600_realize; + +- sc->name = "ast2600-a0"; ++ sc->name = "ast2600-a1"; + sc->cpu_type = ARM_CPU_TYPE_NAME("cortex-a7"); +- sc->silicon_rev = AST2600_A0_SILICON_REV; ++ sc->silicon_rev = AST2600_A1_SILICON_REV; + sc->sram_size = 0x10000; + sc->spis_num = 2; + sc->ehcis_num = 2; +@@ -571,7 +571,7 @@ static void aspeed_soc_ast2600_class_init(ObjectClass *oc, void *data) + } + + static const TypeInfo aspeed_soc_ast2600_type_info = { +- .name = "ast2600-a0", ++ .name = "ast2600-a1", + .parent = TYPE_ASPEED_SOC, + .instance_size = sizeof(AspeedSoCState), + .instance_init = aspeed_soc_ast2600_init, +diff --git a/hw/misc/aspeed_scu.c b/hw/misc/aspeed_scu.c +index 9d7482a9df..ec4fef900e 100644 +--- a/hw/misc/aspeed_scu.c ++++ b/hw/misc/aspeed_scu.c +@@ -431,6 +431,7 @@ static uint32_t aspeed_silicon_revs[] = { + AST2500_A0_SILICON_REV, + AST2500_A1_SILICON_REV, + AST2600_A0_SILICON_REV, ++ AST2600_A1_SILICON_REV, + }; + + bool is_supported_silicon_rev(uint32_t silicon_rev) +@@ -649,12 +650,10 @@ static const MemoryRegionOps aspeed_ast2600_scu_ops = { + .valid.unaligned = false, + }; + +-static const uint32_t ast2600_a0_resets[ASPEED_AST2600_SCU_NR_REGS] = { +- [AST2600_SILICON_REV] = AST2600_SILICON_REV, +- [AST2600_SILICON_REV2] = AST2600_SILICON_REV, +- [AST2600_SYS_RST_CTRL] = 0xF7CFFEDC | 0x100, ++static const uint32_t ast2600_a1_resets[ASPEED_AST2600_SCU_NR_REGS] = { ++ [AST2600_SYS_RST_CTRL] = 0xF7C3FED8, + [AST2600_SYS_RST_CTRL2] = 0xFFFFFFFC, +- [AST2600_CLK_STOP_CTRL] = 0xEFF43E8B, ++ [AST2600_CLK_STOP_CTRL] = 0xFFFF7F8A, + [AST2600_CLK_STOP_CTRL2] = 0xFFF0FFF0, + [AST2600_SDRAM_HANDSHAKE] = 0x00000040, /* SoC completed DRAM init */ + [AST2600_HPLL_PARAM] = 0x1000405F, +@@ -684,7 +683,7 @@ static void aspeed_2600_scu_class_init(ObjectClass *klass, void *data) + + dc->desc = "ASPEED 2600 System Control Unit"; + dc->reset = aspeed_ast2600_scu_reset; +- asc->resets = ast2600_a0_resets; ++ asc->resets = ast2600_a1_resets; + asc->calc_hpll = aspeed_2500_scu_calc_hpll; /* No change since AST2500 */ + asc->apb_divider = 4; + asc->nr_regs = ASPEED_AST2600_SCU_NR_REGS; +diff --git a/include/hw/misc/aspeed_scu.h b/include/hw/misc/aspeed_scu.h +index 1d7f7ffc15..a6739bb846 100644 +--- a/include/hw/misc/aspeed_scu.h ++++ b/include/hw/misc/aspeed_scu.h +@@ -41,6 +41,7 @@ typedef struct AspeedSCUState { + #define AST2500_A0_SILICON_REV 0x04000303U + #define AST2500_A1_SILICON_REV 0x04010303U + #define AST2600_A0_SILICON_REV 0x05000303U ++#define AST2600_A1_SILICON_REV 0x05010303U + + #define ASPEED_IS_AST2500(si_rev) ((((si_rev) >> 24) & 0xff) == 0x04) + +-- +2.23.0 + diff --git a/aspeed-sdmc-Implement-AST2600-locking-behaviour.patch b/aspeed-sdmc-Implement-AST2600-locking-behaviour.patch new file mode 100644 index 0000000000000000000000000000000000000000..06a837d805b24b5bb5ff490356eb27b53f87b0fc --- /dev/null +++ b/aspeed-sdmc-Implement-AST2600-locking-behaviour.patch @@ -0,0 +1,118 @@ +From f4ab4f8e772700dcef1c99b75b0704bd5ca96b6a Mon Sep 17 00:00:00 2001 +From: Joel Stanley +Date: Tue, 5 May 2020 18:31:36 +0930 +Subject: [PATCH 361/709] aspeed: sdmc: Implement AST2600 locking behaviour +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The AST2600 handles this differently with the extra 'hardlock' state, so +move the testing to the soc specific class' write callback. + +Signed-off-by: Joel Stanley +Reviewed-by: Cédric Le Goater +Message-id: 20200505090136.341426-1-joel@jms.id.au +Signed-off-by: Peter Maydell +--- + hw/misc/aspeed_sdmc.c | 55 +++++++++++++++++++++++++++++++++++-------- + 1 file changed, 45 insertions(+), 10 deletions(-) + +diff --git a/hw/misc/aspeed_sdmc.c b/hw/misc/aspeed_sdmc.c +index 7b466bf19a..14db9cfc1f 100644 +--- a/hw/misc/aspeed_sdmc.c ++++ b/hw/misc/aspeed_sdmc.c +@@ -23,7 +23,12 @@ + + /* Protection Key Register */ + #define R_PROT (0x00 / 4) ++#define PROT_UNLOCKED 0x01 ++#define PROT_HARDLOCKED 0x10 /* AST2600 */ ++#define PROT_SOFTLOCKED 0x00 ++ + #define PROT_KEY_UNLOCK 0xFC600309 ++#define PROT_KEY_HARDLOCK 0xDEADDEAD /* AST2600 */ + + /* Configuration Register */ + #define R_CONF (0x04 / 4) +@@ -130,16 +135,6 @@ static void aspeed_sdmc_write(void *opaque, hwaddr addr, uint64_t data, + return; + } + +- if (addr == R_PROT) { +- s->regs[addr] = (data == PROT_KEY_UNLOCK) ? 1 : 0; +- return; +- } +- +- if (!s->regs[R_PROT]) { +- qemu_log_mask(LOG_GUEST_ERROR, "%s: SDMC is locked!\n", __func__); +- return; +- } +- + asc->write(s, addr, data); + } + +@@ -320,6 +315,16 @@ static uint32_t aspeed_2400_sdmc_compute_conf(AspeedSDMCState *s, uint32_t data) + static void aspeed_2400_sdmc_write(AspeedSDMCState *s, uint32_t reg, + uint32_t data) + { ++ if (reg == R_PROT) { ++ s->regs[reg] = (data == PROT_KEY_UNLOCK) ? PROT_UNLOCKED : PROT_SOFTLOCKED; ++ return; ++ } ++ ++ if (!s->regs[R_PROT]) { ++ qemu_log_mask(LOG_GUEST_ERROR, "%s: SDMC is locked!\n", __func__); ++ return; ++ } ++ + switch (reg) { + case R_CONF: + data = aspeed_2400_sdmc_compute_conf(s, data); +@@ -368,6 +373,16 @@ static uint32_t aspeed_2500_sdmc_compute_conf(AspeedSDMCState *s, uint32_t data) + static void aspeed_2500_sdmc_write(AspeedSDMCState *s, uint32_t reg, + uint32_t data) + { ++ if (reg == R_PROT) { ++ s->regs[reg] = (data == PROT_KEY_UNLOCK) ? PROT_UNLOCKED : PROT_SOFTLOCKED; ++ return; ++ } ++ ++ if (!s->regs[R_PROT]) { ++ qemu_log_mask(LOG_GUEST_ERROR, "%s: SDMC is locked!\n", __func__); ++ return; ++ } ++ + switch (reg) { + case R_CONF: + data = aspeed_2500_sdmc_compute_conf(s, data); +@@ -424,7 +439,27 @@ static uint32_t aspeed_2600_sdmc_compute_conf(AspeedSDMCState *s, uint32_t data) + static void aspeed_2600_sdmc_write(AspeedSDMCState *s, uint32_t reg, + uint32_t data) + { ++ if (s->regs[R_PROT] == PROT_HARDLOCKED) { ++ qemu_log_mask(LOG_GUEST_ERROR, "%s: SDMC is locked until system reset!\n", ++ __func__); ++ return; ++ } ++ ++ if (reg != R_PROT && s->regs[R_PROT] == PROT_SOFTLOCKED) { ++ qemu_log_mask(LOG_GUEST_ERROR, "%s: SDMC is locked!\n", __func__); ++ return; ++ } ++ + switch (reg) { ++ case R_PROT: ++ if (data == PROT_KEY_UNLOCK) { ++ data = PROT_UNLOCKED; ++ } else if (data == PROT_KEY_HARDLOCK) { ++ data = PROT_HARDLOCKED; ++ } else { ++ data = PROT_SOFTLOCKED; ++ } ++ break; + case R_CONF: + data = aspeed_2600_sdmc_compute_conf(s, data); + break; +-- +2.23.0 + diff --git a/ati-vga-Do-not-allow-unaligned-access-via-index-regi.patch b/ati-vga-Do-not-allow-unaligned-access-via-index-regi.patch new file mode 100644 index 0000000000000000000000000000000000000000..d5eed64af671c4c475dece826c4a37c00f5749ae --- /dev/null +++ b/ati-vga-Do-not-allow-unaligned-access-via-index-regi.patch @@ -0,0 +1,36 @@ +From b0588cb51da6986715294bfec4b52f55612a666e Mon Sep 17 00:00:00 2001 +From: BALATON Zoltan +Date: Sat, 16 May 2020 15:13:03 +0200 +Subject: [PATCH 507/709] ati-vga: Do not allow unaligned access via index + register + +According to docs bits 1 and 0 of MM_INDEX are hard coded to 0 so +unaligned access via this register should not be possible. +This also fixes problems reported in bug #1878134. + +Buglink: https://bugs.launchpad.net/qemu/+bug/1878134 +Signed-off-by: BALATON Zoltan +Tested-by: Alexander Bulekov +Acked-by: Alexander Bulekov +Message-id: 20200516132352.39E9374594E@zero.eik.bme.hu +Signed-off-by: Gerd Hoffmann +--- + hw/display/ati.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/hw/display/ati.c b/hw/display/ati.c +index 58ec8291d4..065f197678 100644 +--- a/hw/display/ati.c ++++ b/hw/display/ati.c +@@ -511,7 +511,7 @@ static void ati_mm_write(void *opaque, hwaddr addr, + } + switch (addr) { + case MM_INDEX: +- s->regs.mm_index = data; ++ s->regs.mm_index = data & ~3; + break; + case MM_DATA ... MM_DATA + 3: + /* indexed access to regs or memory */ +-- +2.23.0 + diff --git a/audio-Let-audio_sample_to_uint64-use-const-samples-a.patch b/audio-Let-audio_sample_to_uint64-use-const-samples-a.patch new file mode 100644 index 0000000000000000000000000000000000000000..c57f2cddde522f8123e5e641dcc153bfb27093b5 --- /dev/null +++ b/audio-Let-audio_sample_to_uint64-use-const-samples-a.patch @@ -0,0 +1,53 @@ +From e709d2ac47e71a879294f20e3fb994b7aea55226 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Tue, 5 May 2020 15:25:57 +0200 +Subject: [PATCH 650/709] audio: Let audio_sample_to_uint64() use const samples + argument +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The samples are the input to convert to u64. As we should +not modify them, mark the argument const. + +Signed-off-by: Philippe Mathieu-Daudé +Message-Id: <20200505132603.8575-2-f4bug@amsat.org> +Signed-off-by: Gerd Hoffmann +--- + audio/audio.h | 2 +- + audio/mixeng.c | 4 ++-- + 2 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/audio/audio.h b/audio/audio.h +index 0db3c7dd5e..f27a12298f 100644 +--- a/audio/audio.h ++++ b/audio/audio.h +@@ -163,7 +163,7 @@ int wav_start_capture(AudioState *state, CaptureState *s, const char *path, + bool audio_is_cleaning_up(void); + void audio_cleanup(void); + +-void audio_sample_to_uint64(void *samples, int pos, ++void audio_sample_to_uint64(const void *samples, int pos, + uint64_t *left, uint64_t *right); + void audio_sample_from_uint64(void *samples, int pos, + uint64_t left, uint64_t right); +diff --git a/audio/mixeng.c b/audio/mixeng.c +index 924dcb858a..f27deb165b 100644 +--- a/audio/mixeng.c ++++ b/audio/mixeng.c +@@ -339,10 +339,10 @@ f_sample *mixeng_clip_float[2] = { + clip_natural_float_from_stereo, + }; + +-void audio_sample_to_uint64(void *samples, int pos, ++void audio_sample_to_uint64(const void *samples, int pos, + uint64_t *left, uint64_t *right) + { +- struct st_sample *sample = samples; ++ const struct st_sample *sample = samples; + sample += pos; + #ifdef FLOAT_MIXENG + error_report( +-- +2.23.0 + diff --git a/audio-Let-capture_callback-handler-use-const-buffer-.patch b/audio-Let-capture_callback-handler-use-const-buffer-.patch new file mode 100644 index 0000000000000000000000000000000000000000..3ea17c36c0a7e17719fd71827f153e5bd4056e7d --- /dev/null +++ b/audio-Let-capture_callback-handler-use-const-buffer-.patch @@ -0,0 +1,63 @@ +From 57a878ed4f76a3a6b06dd8fa7df846adad6633ac Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Tue, 5 May 2020 15:25:58 +0200 +Subject: [PATCH 651/709] audio: Let capture_callback handler use const buffer + argument +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The buffer is the captured input to pass to backends. +As we should not modify it, mark the argument const. + +Signed-off-by: Philippe Mathieu-Daudé +Message-Id: <20200505132603.8575-3-f4bug@amsat.org> +Signed-off-by: Gerd Hoffmann +--- + audio/audio.h | 2 +- + audio/wavcapture.c | 2 +- + ui/vnc.c | 2 +- + 3 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/audio/audio.h b/audio/audio.h +index f27a12298f..b883ebfb1f 100644 +--- a/audio/audio.h ++++ b/audio/audio.h +@@ -60,7 +60,7 @@ typedef enum { + + struct audio_capture_ops { + void (*notify) (void *opaque, audcnotification_e cmd); +- void (*capture) (void *opaque, void *buf, int size); ++ void (*capture) (void *opaque, const void *buf, int size); + void (*destroy) (void *opaque); + }; + +diff --git a/audio/wavcapture.c b/audio/wavcapture.c +index 8d7ce2eda1..17e87ed6f4 100644 +--- a/audio/wavcapture.c ++++ b/audio/wavcapture.c +@@ -71,7 +71,7 @@ static void wav_destroy (void *opaque) + g_free (wav->path); + } + +-static void wav_capture (void *opaque, void *buf, int size) ++static void wav_capture(void *opaque, const void *buf, int size) + { + WAVState *wav = opaque; + +diff --git a/ui/vnc.c b/ui/vnc.c +index 1d7138a3a0..12a12714e1 100644 +--- a/ui/vnc.c ++++ b/ui/vnc.c +@@ -1177,7 +1177,7 @@ static void audio_capture_destroy(void *opaque) + { + } + +-static void audio_capture(void *opaque, void *buf, int size) ++static void audio_capture(void *opaque, const void *buf, int size) + { + VncState *vs = opaque; + +-- +2.23.0 + diff --git a/audio-fix-wavcapture-segfault.patch b/audio-fix-wavcapture-segfault.patch new file mode 100644 index 0000000000000000000000000000000000000000..c71ac13f39bf1dd8777414c6b9d953f8df5ab949 --- /dev/null +++ b/audio-fix-wavcapture-segfault.patch @@ -0,0 +1,49 @@ +From cbaf25d1f59ee13fc7542a06ea70784f2e000c04 Mon Sep 17 00:00:00 2001 +From: Bruce Rogers +Date: Thu, 21 May 2020 11:29:31 -0600 +Subject: [PATCH 649/709] audio: fix wavcapture segfault +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Commit 571a8c522e caused the HMP wavcapture command to segfault when +processing audio data in audio_pcm_sw_write(), where a NULL +sw->hw->pcm_ops is dereferenced. This fix checks that the pointer is +valid before dereferincing it. A similar fix is also made in the +parallel function audio_pcm_sw_read(). + +Fixes: 571a8c522e (audio: split ctl_* functions into enable_* and +volume_*) +Signed-off-by: Bruce Rogers +Reviewed-by: Philippe Mathieu-Daudé +Message-id: 20200521172931.121903-1-brogers@suse.com +Signed-off-by: Gerd Hoffmann +--- + audio/audio.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/audio/audio.c b/audio/audio.c +index 95d9fb16ca..ce8c6dec5f 100644 +--- a/audio/audio.c ++++ b/audio/audio.c +@@ -649,7 +649,7 @@ static size_t audio_pcm_sw_read(SWVoiceIn *sw, void *buf, size_t size) + total += isamp; + } + +- if (!hw->pcm_ops->volume_in) { ++ if (hw->pcm_ops && !hw->pcm_ops->volume_in) { + mixeng_volume (sw->buf, ret, &sw->vol); + } + +@@ -736,7 +736,7 @@ static size_t audio_pcm_sw_write(SWVoiceOut *sw, void *buf, size_t size) + if (swlim) { + sw->conv (sw->buf, buf, swlim); + +- if (!sw->hw->pcm_ops->volume_out) { ++ if (sw->hw->pcm_ops && !sw->hw->pcm_ops->volume_out) { + mixeng_volume (sw->buf, swlim, &sw->vol); + } + } +-- +2.23.0 + diff --git a/audio-jack-add-JACK-client-audiodev.patch b/audio-jack-add-JACK-client-audiodev.patch new file mode 100644 index 0000000000000000000000000000000000000000..790b0c6c0617a60f77bc9373b105d4eecb11f43c --- /dev/null +++ b/audio-jack-add-JACK-client-audiodev.patch @@ -0,0 +1,854 @@ +From 2e44570321056feaa045a51d5e3e8585cea627d0 Mon Sep 17 00:00:00 2001 +From: Geoffrey McRae +Date: Wed, 29 Apr 2020 15:53:58 +1000 +Subject: [PATCH 644/709] audio/jack: add JACK client audiodev + +This commit adds a new audiodev backend to allow QEMU to use JACK as +both an audio sink and source. + +Signed-off-by: Geoffrey McRae +Message-Id: <20200512101603.E3DB73A038E@moya.office.hostfission.com> +Signed-off-by: Gerd Hoffmann +--- + audio/Makefile.objs | 5 + + audio/audio.c | 1 + + audio/audio_template.h | 2 + + audio/jackaudio.c | 667 +++++++++++++++++++++++++++++++++++++++++ + configure | 17 ++ + qapi/audio.json | 56 +++- + 6 files changed, 746 insertions(+), 2 deletions(-) + create mode 100644 audio/jackaudio.c + +diff --git a/audio/Makefile.objs b/audio/Makefile.objs +index d7490a379f..b4a4c11f31 100644 +--- a/audio/Makefile.objs ++++ b/audio/Makefile.objs +@@ -28,3 +28,8 @@ common-obj-$(CONFIG_AUDIO_SDL) += sdl.mo + sdl.mo-objs = sdlaudio.o + sdl.mo-cflags := $(SDL_CFLAGS) + sdl.mo-libs := $(SDL_LIBS) ++ ++# jack module ++common-obj-$(CONFIG_AUDIO_JACK) += jack.mo ++jack.mo-objs = jackaudio.o ++jack.mo-libs := $(JACK_LIBS) +diff --git a/audio/audio.c b/audio/audio.c +index 7a9e680355..95d9fb16ca 100644 +--- a/audio/audio.c ++++ b/audio/audio.c +@@ -1969,6 +1969,7 @@ void audio_create_pdos(Audiodev *dev) + CASE(ALSA, alsa, Alsa); + CASE(COREAUDIO, coreaudio, Coreaudio); + CASE(DSOUND, dsound, ); ++ CASE(JACK, jack, Jack); + CASE(OSS, oss, Oss); + CASE(PA, pa, Pa); + CASE(SDL, sdl, ); +diff --git a/audio/audio_template.h b/audio/audio_template.h +index 7013d3041f..8dd48ce14e 100644 +--- a/audio/audio_template.h ++++ b/audio/audio_template.h +@@ -330,6 +330,8 @@ AudiodevPerDirectionOptions *glue(audio_get_pdo_, TYPE)(Audiodev *dev) + dev->u.coreaudio.TYPE); + case AUDIODEV_DRIVER_DSOUND: + return dev->u.dsound.TYPE; ++ case AUDIODEV_DRIVER_JACK: ++ return qapi_AudiodevJackPerDirectionOptions_base(dev->u.jack.TYPE); + case AUDIODEV_DRIVER_OSS: + return qapi_AudiodevOssPerDirectionOptions_base(dev->u.oss.TYPE); + case AUDIODEV_DRIVER_PA: +diff --git a/audio/jackaudio.c b/audio/jackaudio.c +new file mode 100644 +index 0000000000..722ddb1dfe +--- /dev/null ++++ b/audio/jackaudio.c +@@ -0,0 +1,667 @@ ++/* ++ * QEMU JACK Audio Connection Kit Client ++ * ++ * Copyright (c) 2020 Geoffrey McRae (gnif) ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a copy ++ * of this software and associated documentation files (the "Software"), to deal ++ * in the Software without restriction, including without limitation the rights ++ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ++ * copies of the Software, and to permit persons to whom the Software is ++ * furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ++ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ * 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. ++ */ ++ ++#include "qemu/osdep.h" ++#include "qemu/module.h" ++#include "qemu/atomic.h" ++#include "qemu-common.h" ++#include "audio.h" ++ ++#define AUDIO_CAP "jack" ++#include "audio_int.h" ++ ++#include ++#include ++ ++struct QJack; ++ ++typedef enum QJackState { ++ QJACK_STATE_DISCONNECTED, ++ QJACK_STATE_STOPPED, ++ QJACK_STATE_RUNNING, ++ QJACK_STATE_SHUTDOWN ++} ++QJackState; ++ ++typedef struct QJackBuffer { ++ int channels; ++ int frames; ++ uint32_t used; ++ int rptr, wptr; ++ float **data; ++} ++QJackBuffer; ++ ++typedef struct QJackClient { ++ AudiodevJackPerDirectionOptions *opt; ++ ++ bool out; ++ bool finished; ++ bool connect_ports; ++ int packets; ++ ++ QJackState state; ++ jack_client_t *client; ++ jack_nframes_t freq; ++ ++ struct QJack *j; ++ int nchannels; ++ int buffersize; ++ jack_port_t **port; ++ QJackBuffer fifo; ++} ++QJackClient; ++ ++typedef struct QJackOut { ++ HWVoiceOut hw; ++ QJackClient c; ++} ++QJackOut; ++ ++typedef struct QJackIn { ++ HWVoiceIn hw; ++ QJackClient c; ++} ++QJackIn; ++ ++static int qjack_client_init(QJackClient *c); ++static void qjack_client_connect_ports(QJackClient *c); ++static void qjack_client_fini(QJackClient *c); ++ ++static void qjack_buffer_create(QJackBuffer *buffer, int channels, int frames) ++{ ++ buffer->channels = channels; ++ buffer->frames = frames; ++ buffer->used = 0; ++ buffer->rptr = 0; ++ buffer->wptr = 0; ++ buffer->data = g_malloc(channels * sizeof(float *)); ++ for (int i = 0; i < channels; ++i) { ++ buffer->data[i] = g_malloc(frames * sizeof(float)); ++ } ++} ++ ++static void qjack_buffer_clear(QJackBuffer *buffer) ++{ ++ assert(buffer->data); ++ atomic_store_release(&buffer->used, 0); ++ buffer->rptr = 0; ++ buffer->wptr = 0; ++} ++ ++static void qjack_buffer_free(QJackBuffer *buffer) ++{ ++ if (!buffer->data) { ++ return; ++ } ++ ++ for (int i = 0; i < buffer->channels; ++i) { ++ g_free(buffer->data[i]); ++ } ++ ++ g_free(buffer->data); ++ buffer->data = NULL; ++} ++ ++/* write PCM interleaved */ ++static int qjack_buffer_write(QJackBuffer *buffer, float *data, int size) ++{ ++ assert(buffer->data); ++ const int samples = size / sizeof(float); ++ int frames = samples / buffer->channels; ++ const int avail = buffer->frames - atomic_load_acquire(&buffer->used); ++ ++ if (frames > avail) { ++ frames = avail; ++ } ++ ++ int copy = frames; ++ int wptr = buffer->wptr; ++ ++ while (copy) { ++ ++ for (int c = 0; c < buffer->channels; ++c) { ++ buffer->data[c][wptr] = *data++; ++ } ++ ++ if (++wptr == buffer->frames) { ++ wptr = 0; ++ } ++ ++ --copy; ++ } ++ ++ buffer->wptr = wptr; ++ ++ atomic_add(&buffer->used, frames); ++ return frames * buffer->channels * sizeof(float); ++}; ++ ++/* write PCM linear */ ++static int qjack_buffer_write_l(QJackBuffer *buffer, float **dest, int frames) ++{ ++ assert(buffer->data); ++ const int avail = buffer->frames - atomic_load_acquire(&buffer->used); ++ int wptr = buffer->wptr; ++ ++ if (frames > avail) { ++ frames = avail; ++ } ++ ++ int right = buffer->frames - wptr; ++ if (right > frames) { ++ right = frames; ++ } ++ ++ const int left = frames - right; ++ for (int c = 0; c < buffer->channels; ++c) { ++ memcpy(buffer->data[c] + wptr, dest[c] , right * sizeof(float)); ++ memcpy(buffer->data[c] , dest[c] + right, left * sizeof(float)); ++ } ++ ++ wptr += frames; ++ if (wptr >= buffer->frames) { ++ wptr -= buffer->frames; ++ } ++ buffer->wptr = wptr; ++ ++ atomic_add(&buffer->used, frames); ++ return frames; ++} ++ ++/* read PCM interleaved */ ++static int qjack_buffer_read(QJackBuffer *buffer, float *dest, int size) ++{ ++ assert(buffer->data); ++ const int samples = size / sizeof(float); ++ int frames = samples / buffer->channels; ++ const int avail = atomic_load_acquire(&buffer->used); ++ ++ if (frames > avail) { ++ frames = avail; ++ } ++ ++ int copy = frames; ++ int rptr = buffer->rptr; ++ ++ while (copy) { ++ ++ for (int c = 0; c < buffer->channels; ++c) { ++ *dest++ = buffer->data[c][rptr]; ++ } ++ ++ if (++rptr == buffer->frames) { ++ rptr = 0; ++ } ++ ++ --copy; ++ } ++ ++ buffer->rptr = rptr; ++ ++ atomic_sub(&buffer->used, frames); ++ return frames * buffer->channels * sizeof(float); ++} ++ ++/* read PCM linear */ ++static int qjack_buffer_read_l(QJackBuffer *buffer, float **dest, int frames) ++{ ++ assert(buffer->data); ++ int copy = frames; ++ const int used = atomic_load_acquire(&buffer->used); ++ int rptr = buffer->rptr; ++ ++ if (copy > used) { ++ copy = used; ++ } ++ ++ int right = buffer->frames - rptr; ++ if (right > copy) { ++ right = copy; ++ } ++ ++ const int left = copy - right; ++ for (int c = 0; c < buffer->channels; ++c) { ++ memcpy(dest[c] , buffer->data[c] + rptr, right * sizeof(float)); ++ memcpy(dest[c] + right, buffer->data[c] , left * sizeof(float)); ++ } ++ ++ rptr += copy; ++ if (rptr >= buffer->frames) { ++ rptr -= buffer->frames; ++ } ++ buffer->rptr = rptr; ++ ++ atomic_sub(&buffer->used, copy); ++ return copy; ++} ++ ++static int qjack_process(jack_nframes_t nframes, void *arg) ++{ ++ QJackClient *c = (QJackClient *)arg; ++ ++ if (c->state != QJACK_STATE_RUNNING) { ++ return 0; ++ } ++ ++ /* get the buffers for the ports */ ++ float *buffers[c->nchannels]; ++ for (int i = 0; i < c->nchannels; ++i) { ++ buffers[i] = jack_port_get_buffer(c->port[i], nframes); ++ } ++ ++ if (c->out) { ++ qjack_buffer_read_l(&c->fifo, buffers, nframes); ++ } else { ++ qjack_buffer_write_l(&c->fifo, buffers, nframes); ++ } ++ ++ return 0; ++} ++ ++static void qjack_port_registration(jack_port_id_t port, int reg, void *arg) ++{ ++ if (reg) { ++ QJackClient *c = (QJackClient *)arg; ++ c->connect_ports = true; ++ } ++} ++ ++static int qjack_xrun(void *arg) ++{ ++ QJackClient *c = (QJackClient *)arg; ++ if (c->state != QJACK_STATE_RUNNING) { ++ return 0; ++ } ++ ++ qjack_buffer_clear(&c->fifo); ++ return 0; ++} ++ ++static void qjack_shutdown(void *arg) ++{ ++ QJackClient *c = (QJackClient *)arg; ++ c->state = QJACK_STATE_SHUTDOWN; ++} ++ ++static void qjack_client_recover(QJackClient *c) ++{ ++ if (c->state == QJACK_STATE_SHUTDOWN) { ++ qjack_client_fini(c); ++ } ++ ++ /* packets is used simply to throttle this */ ++ if (c->state == QJACK_STATE_DISCONNECTED && ++ c->packets % 100 == 0) { ++ ++ /* if not finished then attempt to recover */ ++ if (!c->finished) { ++ dolog("attempting to reconnect to server\n"); ++ qjack_client_init(c); ++ } ++ } ++} ++ ++static size_t qjack_write(HWVoiceOut *hw, void *buf, size_t len) ++{ ++ QJackOut *jo = (QJackOut *)hw; ++ ++jo->c.packets; ++ ++ if (jo->c.state != QJACK_STATE_RUNNING) { ++ qjack_client_recover(&jo->c); ++ return len; ++ } ++ ++ qjack_client_connect_ports(&jo->c); ++ return qjack_buffer_write(&jo->c.fifo, buf, len); ++} ++ ++static size_t qjack_read(HWVoiceIn *hw, void *buf, size_t len) ++{ ++ QJackIn *ji = (QJackIn *)hw; ++ ++ji->c.packets; ++ ++ if (ji->c.state != QJACK_STATE_RUNNING) { ++ qjack_client_recover(&ji->c); ++ return len; ++ } ++ ++ qjack_client_connect_ports(&ji->c); ++ return qjack_buffer_read(&ji->c.fifo, buf, len); ++} ++ ++static void qjack_client_connect_ports(QJackClient *c) ++{ ++ if (!c->connect_ports || !c->opt->connect_ports) { ++ return; ++ } ++ ++ c->connect_ports = false; ++ const char **ports; ++ ports = jack_get_ports(c->client, c->opt->connect_ports, NULL, ++ c->out ? JackPortIsInput : JackPortIsOutput); ++ ++ if (!ports) { ++ return; ++ } ++ ++ for (int i = 0; i < c->nchannels && ports[i]; ++i) { ++ const char *p = jack_port_name(c->port[i]); ++ if (jack_port_connected_to(c->port[i], ports[i])) { ++ continue; ++ } ++ ++ if (c->out) { ++ dolog("connect %s -> %s\n", p, ports[i]); ++ jack_connect(c->client, p, ports[i]); ++ } else { ++ dolog("connect %s -> %s\n", ports[i], p); ++ jack_connect(c->client, ports[i], p); ++ } ++ } ++} ++ ++static int qjack_client_init(QJackClient *c) ++{ ++ jack_status_t status; ++ char client_name[jack_client_name_size()]; ++ jack_options_t options = JackNullOption; ++ ++ c->finished = false; ++ c->connect_ports = true; ++ ++ snprintf(client_name, sizeof(client_name), "%s-%s", ++ c->out ? "out" : "in", ++ c->opt->client_name ? c->opt->client_name : qemu_get_vm_name()); ++ ++ if (c->opt->exact_name) { ++ options |= JackUseExactName; ++ } ++ ++ if (!c->opt->start_server) { ++ options |= JackNoStartServer; ++ } ++ ++ if (c->opt->server_name) { ++ options |= JackServerName; ++ } ++ ++ c->client = jack_client_open(client_name, options, &status, ++ c->opt->server_name); ++ ++ if (c->client == NULL) { ++ dolog("jack_client_open failed: status = 0x%2.0x\n", status); ++ if (status & JackServerFailed) { ++ dolog("unable to connect to JACK server\n"); ++ } ++ return -1; ++ } ++ ++ c->freq = jack_get_sample_rate(c->client); ++ ++ if (status & JackServerStarted) { ++ dolog("JACK server started\n"); ++ } ++ ++ if (status & JackNameNotUnique) { ++ dolog("JACK unique name assigned %s\n", ++ jack_get_client_name(c->client)); ++ } ++ ++ jack_set_process_callback(c->client, qjack_process , c); ++ jack_set_port_registration_callback(c->client, qjack_port_registration, c); ++ jack_set_xrun_callback(c->client, qjack_xrun, c); ++ jack_on_shutdown(c->client, qjack_shutdown, c); ++ ++ /* ++ * ensure the buffersize is no smaller then 512 samples, some (all?) qemu ++ * virtual devices do not work correctly otherwise ++ */ ++ if (c->buffersize < 512) { ++ c->buffersize = 512; ++ } ++ ++ /* create a 2 period buffer */ ++ qjack_buffer_create(&c->fifo, c->nchannels, c->buffersize * 2); ++ ++ /* allocate and register the ports */ ++ c->port = g_malloc(sizeof(jack_port_t *) * c->nchannels); ++ for (int i = 0; i < c->nchannels; ++i) { ++ ++ char port_name[16]; ++ snprintf( ++ port_name, ++ sizeof(port_name), ++ c->out ? "output %d" : "input %d", ++ i); ++ ++ c->port[i] = jack_port_register( ++ c->client, ++ port_name, ++ JACK_DEFAULT_AUDIO_TYPE, ++ c->out ? JackPortIsOutput : JackPortIsInput, ++ 0); ++ } ++ ++ /* activate the session */ ++ jack_activate(c->client); ++ c->buffersize = jack_get_buffer_size(c->client); ++ ++ qjack_client_connect_ports(c); ++ c->state = QJACK_STATE_RUNNING; ++ return 0; ++} ++ ++static int qjack_init_out(HWVoiceOut *hw, struct audsettings *as, ++ void *drv_opaque) ++{ ++ QJackOut *jo = (QJackOut *)hw; ++ Audiodev *dev = (Audiodev *)drv_opaque; ++ ++ if (jo->c.state != QJACK_STATE_DISCONNECTED) { ++ return 0; ++ } ++ ++ jo->c.out = true; ++ jo->c.nchannels = as->nchannels; ++ jo->c.opt = dev->u.jack.out; ++ int ret = qjack_client_init(&jo->c); ++ if (ret != 0) { ++ return ret; ++ } ++ ++ /* report the buffer size to qemu */ ++ hw->samples = jo->c.buffersize; ++ ++ /* report the audio format we support */ ++ struct audsettings os = { ++ .freq = jo->c.freq, ++ .nchannels = jo->c.nchannels, ++ .fmt = AUDIO_FORMAT_F32, ++ .endianness = 0 ++ }; ++ audio_pcm_init_info(&hw->info, &os); ++ ++ dolog("JACK output configured for %dHz (%d samples)\n", ++ jo->c.freq, jo->c.buffersize); ++ ++ return 0; ++} ++ ++static int qjack_init_in(HWVoiceIn *hw, struct audsettings *as, ++ void *drv_opaque) ++{ ++ QJackIn *ji = (QJackIn *)hw; ++ Audiodev *dev = (Audiodev *)drv_opaque; ++ ++ if (ji->c.state != QJACK_STATE_DISCONNECTED) { ++ return 0; ++ } ++ ++ ji->c.out = false; ++ ji->c.nchannels = as->nchannels; ++ ji->c.opt = dev->u.jack.in; ++ int ret = qjack_client_init(&ji->c); ++ if (ret != 0) { ++ return ret; ++ } ++ ++ /* report the buffer size to qemu */ ++ hw->samples = ji->c.buffersize; ++ ++ /* report the audio format we support */ ++ struct audsettings is = { ++ .freq = ji->c.freq, ++ .nchannels = ji->c.nchannels, ++ .fmt = AUDIO_FORMAT_F32, ++ .endianness = 0 ++ }; ++ audio_pcm_init_info(&hw->info, &is); ++ ++ dolog("JACK input configured for %dHz (%d samples)\n", ++ ji->c.freq, ji->c.buffersize); ++ ++ return 0; ++} ++ ++static void qjack_client_fini(QJackClient *c) ++{ ++ switch (c->state) { ++ case QJACK_STATE_RUNNING: ++ /* fallthrough */ ++ ++ case QJACK_STATE_STOPPED: ++ for (int i = 0; i < c->nchannels; ++i) { ++ jack_port_unregister(c->client, c->port[i]); ++ } ++ jack_deactivate(c->client); ++ /* fallthrough */ ++ ++ case QJACK_STATE_SHUTDOWN: ++ jack_client_close(c->client); ++ /* fallthrough */ ++ ++ case QJACK_STATE_DISCONNECTED: ++ break; ++ } ++ ++ qjack_buffer_free(&c->fifo); ++ g_free(c->port); ++ ++ c->state = QJACK_STATE_DISCONNECTED; ++} ++ ++static void qjack_fini_out(HWVoiceOut *hw) ++{ ++ QJackOut *jo = (QJackOut *)hw; ++ jo->c.finished = true; ++ qjack_client_fini(&jo->c); ++} ++ ++static void qjack_fini_in(HWVoiceIn *hw) ++{ ++ QJackIn *ji = (QJackIn *)hw; ++ ji->c.finished = true; ++ qjack_client_fini(&ji->c); ++} ++ ++static void qjack_enable_out(HWVoiceOut *hw, bool enable) ++{ ++} ++ ++static void qjack_enable_in(HWVoiceIn *hw, bool enable) ++{ ++} ++ ++static int qjack_thread_creator(jack_native_thread_t *thread, ++ const pthread_attr_t *attr, void *(*function)(void *), void *arg) ++{ ++ int ret = pthread_create(thread, attr, function, arg); ++ if (ret != 0) { ++ return ret; ++ } ++ ++ /* set the name of the thread */ ++ pthread_setname_np(*thread, "jack-client"); ++ ++ return ret; ++} ++ ++static void *qjack_init(Audiodev *dev) ++{ ++ assert(dev->driver == AUDIODEV_DRIVER_JACK); ++ ++ dev->u.jack.has_in = false; ++ ++ return dev; ++} ++ ++static void qjack_fini(void *opaque) ++{ ++} ++ ++static struct audio_pcm_ops jack_pcm_ops = { ++ .init_out = qjack_init_out, ++ .fini_out = qjack_fini_out, ++ .write = qjack_write, ++ .run_buffer_out = audio_generic_run_buffer_out, ++ .enable_out = qjack_enable_out, ++ ++ .init_in = qjack_init_in, ++ .fini_in = qjack_fini_in, ++ .read = qjack_read, ++ .enable_in = qjack_enable_in ++}; ++ ++static struct audio_driver jack_driver = { ++ .name = "jack", ++ .descr = "JACK Audio Connection Kit Client", ++ .init = qjack_init, ++ .fini = qjack_fini, ++ .pcm_ops = &jack_pcm_ops, ++ .can_be_default = 1, ++ .max_voices_out = INT_MAX, ++ .max_voices_in = INT_MAX, ++ .voice_size_out = sizeof(QJackOut), ++ .voice_size_in = sizeof(QJackIn) ++}; ++ ++static void qjack_error(const char *msg) ++{ ++ dolog("E: %s\n", msg); ++} ++ ++static void qjack_info(const char *msg) ++{ ++ dolog("I: %s\n", msg); ++} ++ ++static void register_audio_jack(void) ++{ ++ audio_driver_register(&jack_driver); ++ jack_set_thread_creator(qjack_thread_creator); ++ jack_set_error_function(qjack_error); ++ jack_set_info_function(qjack_info); ++} ++type_init(register_audio_jack); +diff --git a/configure b/configure +index 2fc05c4465..b969dee675 100755 +--- a/configure ++++ b/configure +@@ -3629,6 +3629,22 @@ for drv in $audio_drv_list; do + oss_libs="$oss_lib" + ;; + ++ jack | try-jack) ++ if $pkg_config jack --exists; then ++ jack_libs=$($pkg_config jack --libs) ++ if test "$drv" = "try-jack"; then ++ audio_drv_list=$(echo "$audio_drv_list" | sed -e 's/try-jack/jack/') ++ fi ++ else ++ if test "$drv" = "try-jack"; then ++ audio_drv_list=$(echo "$audio_drv_list" | sed -e 's/try-jack//') ++ else ++ error_exit "$drv check failed" \ ++ "Make sure to have the $drv libs and headers installed." ++ fi ++ fi ++ ;; ++ + *) + echo "$audio_possible_drivers" | grep -q "\<$drv\>" || { + error_exit "Unknown driver '$drv' selected" \ +@@ -6904,6 +6920,7 @@ echo "PULSE_LIBS=$pulse_libs" >> $config_host_mak + echo "COREAUDIO_LIBS=$coreaudio_libs" >> $config_host_mak + echo "DSOUND_LIBS=$dsound_libs" >> $config_host_mak + echo "OSS_LIBS=$oss_libs" >> $config_host_mak ++echo "JACK_LIBS=$jack_libs" >> $config_host_mak + if test "$audio_win_int" = "yes" ; then + echo "CONFIG_AUDIO_WIN_INT=y" >> $config_host_mak + fi +diff --git a/qapi/audio.json b/qapi/audio.json +index c31251f45b..f62bd0d7f6 100644 +--- a/qapi/audio.json ++++ b/qapi/audio.json +@@ -152,6 +152,55 @@ + '*out': 'AudiodevPerDirectionOptions', + '*latency': 'uint32' } } + ++## ++# @AudiodevJackPerDirectionOptions: ++# ++# Options of the JACK backend that are used for both playback and ++# recording. ++# ++# @server-name: select from among several possible concurrent server instances ++# (default: environment variable $JACK_DEFAULT_SERVER if set, else "default") ++# ++# @client-name: the client name to use. The server will modify this name to ++# create a unique variant, if needed unless @exact-name is true (default: the ++# guest's name) ++# ++# @connect-ports: if set, a regular expression of JACK client port name(s) to ++# monitor for and automatically connect to ++# ++# @start-server: start a jack server process if one is not already present ++# (default: false) ++# ++# @exact-name: use the exact name requested otherwise JACK automatically ++# generates a unique one, if needed (default: false) ++# ++# Since: 5.1 ++## ++{ 'struct': 'AudiodevJackPerDirectionOptions', ++ 'base': 'AudiodevPerDirectionOptions', ++ 'data': { ++ '*server-name': 'str', ++ '*client-name': 'str', ++ '*connect-ports': 'str', ++ '*start-server': 'bool', ++ '*exact-name': 'bool' } } ++ ++## ++# @AudiodevJackOptions: ++# ++# Options of the JACK audio backend. ++# ++# @in: options of the capture stream ++# ++# @out: options of the playback stream ++# ++# Since: 5.1 ++## ++{ 'struct': 'AudiodevJackOptions', ++ 'data': { ++ '*in': 'AudiodevJackPerDirectionOptions', ++ '*out': 'AudiodevJackPerDirectionOptions' } } ++ + ## + # @AudiodevOssPerDirectionOptions: + # +@@ -297,11 +346,13 @@ + # + # An enumeration of possible audio backend drivers. + # ++# @jack: JACK audio backend (since 5.1) ++# + # Since: 4.0 + ## + { 'enum': 'AudiodevDriver', +- 'data': [ 'none', 'alsa', 'coreaudio', 'dsound', 'oss', 'pa', 'sdl', +- 'spice', 'wav' ] } ++ 'data': [ 'none', 'alsa', 'coreaudio', 'dsound', 'jack', 'oss', 'pa', ++ 'sdl', 'spice', 'wav' ] } + + ## + # @Audiodev: +@@ -327,6 +378,7 @@ + 'alsa': 'AudiodevAlsaOptions', + 'coreaudio': 'AudiodevCoreaudioOptions', + 'dsound': 'AudiodevDsoundOptions', ++ 'jack': 'AudiodevJackOptions', + 'oss': 'AudiodevOssOptions', + 'pa': 'AudiodevPaOptions', + 'sdl': 'AudiodevGenericOptions', +-- +2.23.0 + diff --git a/audio-mixeng-fix-clang-10-warning.patch b/audio-mixeng-fix-clang-10-warning.patch new file mode 100644 index 0000000000000000000000000000000000000000..d8933cc082d162ba178f5cc6aec4e05654df2fd5 --- /dev/null +++ b/audio-mixeng-fix-clang-10-warning.patch @@ -0,0 +1,60 @@ +From 9c61fcc89a70256c19047d251aa44f666f06089c Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Volker=20R=C3=BCmelin?= +Date: Sat, 23 May 2020 22:17:12 +0200 +Subject: [PATCH 648/709] audio/mixeng: fix clang 10+ warning +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The code in CONV_NATURAL_FLOAT() and CLIP_NATURAL_FLOAT() +seems to use the constant 2^31-0.5 to convert float to integer +and back. But the float type lacks the required precision and +the constant used for the conversion is 2^31. This is equiva- +lent to a [-1.f, 1.f] <-> [INT32_MIN, INT32_MAX + 1] mapping. + +This patch explicitly writes down the used constant. The +compiler generated code doesn't change. + +The constant 2^31 has an exact float representation and the +clang 10 compiler stops complaining about an implicit int to +float conversion with a changed value. + +A few notes: +- The conversion of 1.f to INT32_MAX + 1 doesn't overflow. The + type of the destination variable is int64_t. +- At a later stage one of the clip_* functions in + audio/mixeng_template.h limits INT32_MAX + 1 to the integer + range. +- The clip_natural_float_* functions in audio/mixeng.c convert + INT32_MAX and INT32_MAX + 1 to 1.f. + +Buglink: https://bugs.launchpad.net/bugs/1878627 +Signed-off-by: Volker Rümelin +Message-id: 20200523201712.23908-1-vr_qemu@t-online.de +Signed-off-by: Gerd Hoffmann +--- + audio/mixeng.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/audio/mixeng.c b/audio/mixeng.c +index 739a500449..924dcb858a 100644 +--- a/audio/mixeng.c ++++ b/audio/mixeng.c +@@ -271,11 +271,12 @@ f_sample *mixeng_clip[2][2][2][3] = { + #define CONV_NATURAL_FLOAT(x) (x) + #define CLIP_NATURAL_FLOAT(x) (x) + #else +-static const float float_scale = UINT_MAX / 2.f; ++/* macros to map [-1.f, 1.f] <-> [INT32_MIN, INT32_MAX + 1] */ ++static const float float_scale = (int64_t)INT32_MAX + 1; + #define CONV_NATURAL_FLOAT(x) ((x) * float_scale) + + #ifdef RECIPROCAL +-static const float float_scale_reciprocal = 2.f / UINT_MAX; ++static const float float_scale_reciprocal = 1.f / ((int64_t)INT32_MAX + 1); + #define CLIP_NATURAL_FLOAT(x) ((x) * float_scale_reciprocal) + #else + #define CLIP_NATURAL_FLOAT(x) ((x) / float_scale) +-- +2.23.0 + diff --git a/backup-Improve-error-for-bdrv_getlength-failure.patch b/backup-Improve-error-for-bdrv_getlength-failure.patch new file mode 100644 index 0000000000000000000000000000000000000000..633a96d736d476165b054e5c48a826360319da27 --- /dev/null +++ b/backup-Improve-error-for-bdrv_getlength-failure.patch @@ -0,0 +1,39 @@ +From 58226634c4b02af7b10862f7fbd3610a344bfb7f Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Thu, 30 Apr 2020 16:27:53 +0200 +Subject: [PATCH 344/709] backup: Improve error for bdrv_getlength() failure + +bdrv_get_device_name() will be an empty string with modern management +tools that don't use -drive. Use bdrv_get_device_or_node_name() instead +so that the node name is used if the BlockBackend is anonymous. + +While at it, start with upper case to make the message consistent with +the rest of the function. + +Signed-off-by: Kevin Wolf +Reviewed-by: Vladimir Sementsov-Ogievskiy +Reviewed-by: Alberto Garcia +Message-Id: <20200430142755.315494-3-kwolf@redhat.com> +Signed-off-by: Kevin Wolf +--- + block/backup.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/block/backup.c b/block/backup.c +index a7a7dcaf4c..c4c3b8cd46 100644 +--- a/block/backup.c ++++ b/block/backup.c +@@ -400,8 +400,8 @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs, + + len = bdrv_getlength(bs); + if (len < 0) { +- error_setg_errno(errp, -len, "unable to get length for '%s'", +- bdrv_get_device_name(bs)); ++ error_setg_errno(errp, -len, "Unable to get length for '%s'", ++ bdrv_get_device_or_node_name(bs)); + goto error; + } + +-- +2.23.0 + diff --git a/backup-Make-sure-that-source-and-target-size-match.patch b/backup-Make-sure-that-source-and-target-size-match.patch new file mode 100644 index 0000000000000000000000000000000000000000..55536c2639c7e2f8b2bd1848b322b250cb8d343a --- /dev/null +++ b/backup-Make-sure-that-source-and-target-size-match.patch @@ -0,0 +1,113 @@ +From 958a04bd32af18d9a207bcc78046e56a202aebc2 Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Thu, 30 Apr 2020 16:27:54 +0200 +Subject: [PATCH 345/709] backup: Make sure that source and target size match + +Since the introduction of a backup filter node in commit 00e30f05d, the +backup block job crashes when the target image is smaller than the +source image because it will try to write after the end of the target +node without having BLK_PERM_RESIZE. (Previously, the BlockBackend layer +would have caught this and errored out gracefully.) + +We can fix this and even do better than the old behaviour: Check that +source and target have the same image size at the start of the block job +and unshare BLK_PERM_RESIZE. (This permission was already unshared +before the same commit 00e30f05d, but the BlockBackend that was used to +make the restriction was removed without a replacement.) This will +immediately error out when starting the job instead of only when writing +to a block that doesn't exist in the target. + +Longer target than source would technically work because we would never +write to blocks that don't exist, but semantically these are invalid, +too, because a backup is supposed to create a copy, not just an image +that starts with a copy. + +Fixes: 00e30f05de1d19586345ec373970ef4c192c6270 +Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1778593 +Cc: qemu-stable@nongnu.org +Signed-off-by: Kevin Wolf +Message-Id: <20200430142755.315494-4-kwolf@redhat.com> +Reviewed-by: Vladimir Sementsov-Ogievskiy +Signed-off-by: Kevin Wolf +--- + block/backup-top.c | 14 +++++++++----- + block/backup.c | 14 +++++++++++++- + 2 files changed, 22 insertions(+), 6 deletions(-) + +diff --git a/block/backup-top.c b/block/backup-top.c +index 3b50c06e2c..79b268e6dc 100644 +--- a/block/backup-top.c ++++ b/block/backup-top.c +@@ -148,8 +148,10 @@ static void backup_top_child_perm(BlockDriverState *bs, BdrvChild *c, + * + * Share write to target (child_file), to not interfere + * with guest writes to its disk which may be in target backing chain. ++ * Can't resize during a backup block job because we check the size ++ * only upfront. + */ +- *nshared = BLK_PERM_ALL; ++ *nshared = BLK_PERM_ALL & ~BLK_PERM_RESIZE; + *nperm = BLK_PERM_WRITE; + } else { + /* Source child */ +@@ -159,7 +161,7 @@ static void backup_top_child_perm(BlockDriverState *bs, BdrvChild *c, + if (perm & BLK_PERM_WRITE) { + *nperm = *nperm | BLK_PERM_CONSISTENT_READ; + } +- *nshared &= ~BLK_PERM_WRITE; ++ *nshared &= ~(BLK_PERM_WRITE | BLK_PERM_RESIZE); + } + } + +@@ -192,11 +194,13 @@ BlockDriverState *bdrv_backup_top_append(BlockDriverState *source, + { + Error *local_err = NULL; + BDRVBackupTopState *state; +- BlockDriverState *top = bdrv_new_open_driver(&bdrv_backup_top_filter, +- filter_node_name, +- BDRV_O_RDWR, errp); ++ BlockDriverState *top; + bool appended = false; + ++ assert(source->total_sectors == target->total_sectors); ++ ++ top = bdrv_new_open_driver(&bdrv_backup_top_filter, filter_node_name, ++ BDRV_O_RDWR, errp); + if (!top) { + return NULL; + } +diff --git a/block/backup.c b/block/backup.c +index c4c3b8cd46..4f13bb20a5 100644 +--- a/block/backup.c ++++ b/block/backup.c +@@ -340,7 +340,7 @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs, + BlockCompletionFunc *cb, void *opaque, + JobTxn *txn, Error **errp) + { +- int64_t len; ++ int64_t len, target_len; + BackupBlockJob *job = NULL; + int64_t cluster_size; + BdrvRequestFlags write_flags; +@@ -405,6 +405,18 @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs, + goto error; + } + ++ target_len = bdrv_getlength(target); ++ if (target_len < 0) { ++ error_setg_errno(errp, -target_len, "Unable to get length for '%s'", ++ bdrv_get_device_or_node_name(bs)); ++ goto error; ++ } ++ ++ if (target_len != len) { ++ error_setg(errp, "Source and target image have different sizes"); ++ goto error; ++ } ++ + cluster_size = backup_calculate_cluster_size(target, errp); + if (cluster_size < 0) { + goto error; +-- +2.23.0 + diff --git a/bamboo-sam460ex-Tidy-up-error-message-for-unsupporte.patch b/bamboo-sam460ex-Tidy-up-error-message-for-unsupporte.patch new file mode 100644 index 0000000000000000000000000000000000000000..d0a1d81ae790321b71f95144fd724c81eada0bbc --- /dev/null +++ b/bamboo-sam460ex-Tidy-up-error-message-for-unsupporte.patch @@ -0,0 +1,51 @@ +From 0f1eddf5ed7e35d8d16dfa042ced1107c762cec4 Mon Sep 17 00:00:00 2001 +From: Markus Armbruster +Date: Wed, 22 Apr 2020 15:48:14 +0200 +Subject: [PATCH 030/709] bamboo, sam460ex: Tidy up error message for + unsupported RAM size +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Improve + + $ ppc-softmmu/qemu-system-ppc -M sam460ex -m 4096 + qemu-system-ppc: Max 1 banks of 2048 ,1024 ,512 ,256 ,128 ,64 ,32 MB DIMM/bank supported + qemu-system-ppc: Possible valid RAM size: 2048 + +to + + qemu-system-ppc: at most 1 bank of 2048, 1024, 512, 256, 128, 64, 32 MiB each supported + Possible valid RAM size: 1024 MiB + +Signed-off-by: Markus Armbruster +Message-Id: <20200422134815.1584-4-armbru@redhat.com> +Reviewed-by: BALATON Zoltan +Reviewed-by: Philippe Mathieu-Daudé +--- + hw/ppc/ppc4xx_devs.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/hw/ppc/ppc4xx_devs.c b/hw/ppc/ppc4xx_devs.c +index 3376c43ff5..f1651e04d9 100644 +--- a/hw/ppc/ppc4xx_devs.c ++++ b/hw/ppc/ppc4xx_devs.c +@@ -716,11 +716,11 @@ void ppc4xx_sdram_banks(MemoryRegion *ram, int nr_banks, + for (i = 0; sdram_bank_sizes[i]; i++) { + g_string_append_printf(s, "%" PRIi64 "%s", + sdram_bank_sizes[i] / MiB, +- sdram_bank_sizes[i + 1] ? " ," : ""); ++ sdram_bank_sizes[i + 1] ? ", " : ""); + } +- error_report("Max %d banks of %s MB DIMM/bank supported", +- nr_banks, s->str); +- error_report("Possible valid RAM size: %" PRIi64, ++ 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", + used_size ? used_size / MiB : sdram_bank_sizes[i - 1] / MiB); + + g_string_free(s, true); +-- +2.23.0 + diff --git a/bios-tables-test-test-pc-dimm-and-nvdimm-coldplug-fo.patch b/bios-tables-test-test-pc-dimm-and-nvdimm-coldplug-fo.patch new file mode 100644 index 0000000000000000000000000000000000000000..0055b44c7876dae399f7c6bc4d1fb907df0ce92a --- /dev/null +++ b/bios-tables-test-test-pc-dimm-and-nvdimm-coldplug-fo.patch @@ -0,0 +1,46 @@ +From 62293b4f58276d9f0a25ec35f4bc2e97540ba98f Mon Sep 17 00:00:00 2001 +From: Shameer Kolothum +Date: Tue, 21 Apr 2020 13:59:33 +0100 +Subject: [PATCH 223/709] bios-tables-test: test pc-dimm and nvdimm coldplug + for arm/virt + +Since we now have both pc-dimm and nvdimm support, update +test_acpi_virt_tcg_memhp() to include those. + +Signed-off-by: Shameer Kolothum +Message-Id: <20200421125934.14952-7-shameerali.kolothum.thodi@huawei.com> +Acked-by: Peter Maydell +Tested-by: Eric Auger +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +--- + tests/qtest/bios-tables-test.c | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +diff --git a/tests/qtest/bios-tables-test.c b/tests/qtest/bios-tables-test.c +index 0a597bbacf..c9843829b3 100644 +--- a/tests/qtest/bios-tables-test.c ++++ b/tests/qtest/bios-tables-test.c +@@ -927,12 +927,17 @@ static void test_acpi_virt_tcg_memhp(void) + }; + + data.variant = ".memhp"; +- test_acpi_one(" -cpu cortex-a57" ++ test_acpi_one(" -machine nvdimm=on" ++ " -cpu cortex-a57" + " -m 256M,slots=3,maxmem=1G" + " -object memory-backend-ram,id=ram0,size=128M" + " -object memory-backend-ram,id=ram1,size=128M" + " -numa node,memdev=ram0 -numa node,memdev=ram1" +- " -numa dist,src=0,dst=1,val=21", ++ " -numa dist,src=0,dst=1,val=21" ++ " -object memory-backend-ram,id=ram2,size=128M" ++ " -object memory-backend-ram,id=nvm0,size=128M" ++ " -device pc-dimm,id=dimm0,memdev=ram2,node=0" ++ " -device nvdimm,id=dimm1,memdev=nvm0,node=1", + &data); + + free_test_data(&data); +-- +2.23.0 + diff --git a/bitmaps-Update-maintainer.patch b/bitmaps-Update-maintainer.patch new file mode 100644 index 0000000000000000000000000000000000000000..a8ea3a185bb54fcefb8358548885c1c98f41647a --- /dev/null +++ b/bitmaps-Update-maintainer.patch @@ -0,0 +1,50 @@ +From edb059040371784d12c05c0f3a19a9ddcd3a868d Mon Sep 17 00:00:00 2001 +From: Eric Blake +Date: Thu, 14 May 2020 13:00:03 -0500 +Subject: [PATCH 586/709] bitmaps: Update maintainer + +Dirty bitmaps are important to incremental backups, including exposure +over NBD where I'm already maintainer. Also, I'm aware that lately I +have been doing as much code/review on bitmaps as John Snow who is +trying to scale back in order to focus elsewhere; and many of the +recent patches have come from Vladimir, who is also interested in +taking on maintainer duties, but would like to start with +co-maintainership. Therefore, it's time to revamp the ownership of +this category, as agreed between the three of us. + +Signed-off-by: Eric Blake +Message-Id: <20200514180003.325406-1-eblake@redhat.com> +Acked-by: John Snow +Reviewed-by: John Snow +--- + MAINTAINERS | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/MAINTAINERS b/MAINTAINERS +index 47ef3139e6..4e99bb05da 100644 +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -2011,8 +2011,9 @@ F: qapi/transaction.json + T: git https://repo.or.cz/qemu/armbru.git block-next + + Dirty Bitmaps +-M: John Snow +-R: Vladimir Sementsov-Ogievskiy ++M: Eric Blake ++M: Vladimir Sementsov-Ogievskiy ++R: John Snow + L: qemu-block@nongnu.org + S: Supported + F: include/qemu/hbitmap.h +@@ -2023,7 +2024,7 @@ F: migration/block-dirty-bitmap.c + F: util/hbitmap.c + F: tests/test-hbitmap.c + F: docs/interop/bitmaps.rst +-T: git https://github.com/jnsnow/qemu.git bitmaps ++T: git https://repo.or.cz/qemu/ericb.git bitmaps + + Character device backends + M: Marc-André Lureau +-- +2.23.0 + diff --git a/block-Add-BdrvChildRole-and-BdrvChildRoleBits.patch b/block-Add-BdrvChildRole-and-BdrvChildRoleBits.patch new file mode 100644 index 0000000000000000000000000000000000000000..ea48fb23afb1aece9b8866dcc96f2e4433c3c585 --- /dev/null +++ b/block-Add-BdrvChildRole-and-BdrvChildRoleBits.patch @@ -0,0 +1,89 @@ +From 3284bcf430a1d42885c184de73df52fcfd86d589 Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Wed, 13 May 2020 13:05:14 +0200 +Subject: [PATCH 536/709] block: Add BdrvChildRole and BdrvChildRoleBits + +This mask will supplement BdrvChildClass when it comes to what role (or +combination of roles) a child takes for its parent. It consists of +BdrvChildRoleBits values (which is an enum). + +Because empty enums are not allowed, let us just start with it filled. + +Signed-off-by: Max Reitz +Message-Id: <20200513110544.176672-5-mreitz@redhat.com> +Reviewed-by: Eric Blake +Signed-off-by: Kevin Wolf +--- + include/block/block.h | 56 +++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 56 insertions(+) + +diff --git a/include/block/block.h b/include/block/block.h +index bc42e507bb..35f1a1cecf 100644 +--- a/include/block/block.h ++++ b/include/block/block.h +@@ -268,6 +268,62 @@ enum { + DEFAULT_PERM_UNCHANGED = BLK_PERM_ALL & ~DEFAULT_PERM_PASSTHROUGH, + }; + ++/* ++ * Flags that parent nodes assign to child nodes to specify what kind of ++ * role(s) they take. ++ * ++ * At least one of DATA, METADATA, FILTERED, or COW must be set for ++ * every child. ++ */ ++enum BdrvChildRoleBits { ++ /* ++ * This child stores data. ++ * Any node may have an arbitrary number of such children. ++ */ ++ BDRV_CHILD_DATA = (1 << 0), ++ ++ /* ++ * This child stores metadata. ++ * Any node may have an arbitrary number of metadata-storing ++ * children. ++ */ ++ BDRV_CHILD_METADATA = (1 << 1), ++ ++ /* ++ * A child that always presents exactly the same visible data as ++ * the parent, e.g. by virtue of the parent forwarding all reads ++ * and writes. ++ * This flag is mutually exclusive with DATA, METADATA, and COW. ++ * Any node may have at most one filtered child at a time. ++ */ ++ BDRV_CHILD_FILTERED = (1 << 2), ++ ++ /* ++ * Child from which to read all data that isn’t allocated in the ++ * parent (i.e., the backing child); such data is copied to the ++ * parent through COW (and optionally COR). ++ * This field is mutually exclusive with DATA, METADATA, and ++ * FILTERED. ++ * Any node may have at most one such backing child at a time. ++ */ ++ BDRV_CHILD_COW = (1 << 3), ++ ++ /* ++ * The primary child. For most drivers, this is the child whose ++ * filename applies best to the parent node. ++ * Any node may have at most one primary child at a time. ++ */ ++ BDRV_CHILD_PRIMARY = (1 << 4), ++ ++ /* Useful combination of flags */ ++ BDRV_CHILD_IMAGE = BDRV_CHILD_DATA ++ | BDRV_CHILD_METADATA ++ | BDRV_CHILD_PRIMARY, ++}; ++ ++/* Mask of BdrvChildRoleBits values */ ++typedef unsigned int BdrvChildRole; ++ + char *bdrv_perm_names(uint64_t perm); + uint64_t bdrv_qapi_perm_to_blk_perm(BlockPermission qapi_perm); + +-- +2.23.0 + diff --git a/block-Add-BdrvChildRole-to-BdrvChild.patch b/block-Add-BdrvChildRole-to-BdrvChild.patch new file mode 100644 index 0000000000000000000000000000000000000000..053ce3120a2a266635915b36747d997e2e2d4bf7 --- /dev/null +++ b/block-Add-BdrvChildRole-to-BdrvChild.patch @@ -0,0 +1,657 @@ +From 258b776515cc812a26783ffab98b31aa8eb008d4 Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Wed, 13 May 2020 13:05:15 +0200 +Subject: [PATCH 537/709] block: Add BdrvChildRole to BdrvChild + +For now, it is always set to 0. Later patches in this series will +ensure that all callers pass an appropriate combination of flags. + +Signed-off-by: Max Reitz +Reviewed-by: Eric Blake +Message-Id: <20200513110544.176672-6-mreitz@redhat.com> +Signed-off-by: Kevin Wolf +--- + block.c | 11 ++++++++--- + block/backup-top.c | 3 ++- + block/blkdebug.c | 2 +- + block/blklogwrites.c | 6 +++--- + block/blkreplay.c | 2 +- + block/blkverify.c | 4 ++-- + block/block-backend.c | 4 ++-- + block/bochs.c | 2 +- + block/cloop.c | 2 +- + block/copy-on-read.c | 2 +- + block/crypto.c | 2 +- + block/dmg.c | 2 +- + block/filter-compress.c | 2 +- + block/parallels.c | 2 +- + block/qcow.c | 2 +- + block/qcow2.c | 6 +++--- + block/qed.c | 2 +- + block/quorum.c | 4 ++-- + block/raw-format.c | 2 +- + block/replication.c | 2 +- + block/throttle.c | 2 +- + block/vdi.c | 2 +- + block/vhdx.c | 2 +- + block/vmdk.c | 4 ++-- + block/vpc.c | 2 +- + block/vvfat.c | 2 +- + blockjob.c | 5 +++-- + include/block/block.h | 2 ++ + include/block/block_int.h | 2 ++ + tests/test-bdrv-drain.c | 20 +++++++++++--------- + tests/test-bdrv-graph-mod.c | 4 ++-- + 31 files changed, 62 insertions(+), 49 deletions(-) + +diff --git a/block.c b/block.c +index 0ce9b61c97..14810e0426 100644 +--- a/block.c ++++ b/block.c +@@ -2571,6 +2571,7 @@ static void bdrv_replace_child(BdrvChild *child, BlockDriverState *new_bs) + BdrvChild *bdrv_root_attach_child(BlockDriverState *child_bs, + const char *child_name, + const BdrvChildClass *child_class, ++ BdrvChildRole child_role, + AioContext *ctx, + uint64_t perm, uint64_t shared_perm, + void *opaque, Error **errp) +@@ -2592,6 +2593,7 @@ BdrvChild *bdrv_root_attach_child(BlockDriverState *child_bs, + .bs = NULL, + .name = g_strdup(child_name), + .klass = child_class, ++ .role = child_role, + .perm = perm, + .shared_perm = shared_perm, + .opaque = opaque, +@@ -2644,6 +2646,7 @@ BdrvChild *bdrv_attach_child(BlockDriverState *parent_bs, + BlockDriverState *child_bs, + const char *child_name, + const BdrvChildClass *child_class, ++ BdrvChildRole child_role, + Error **errp) + { + BdrvChild *child; +@@ -2656,7 +2659,7 @@ BdrvChild *bdrv_attach_child(BlockDriverState *parent_bs, + perm, shared_perm, &perm, &shared_perm); + + child = bdrv_root_attach_child(child_bs, child_name, child_class, +- bdrv_get_aio_context(parent_bs), ++ child_role, bdrv_get_aio_context(parent_bs), + perm, shared_perm, parent_bs, errp); + if (child == NULL) { + return NULL; +@@ -2774,7 +2777,7 @@ void bdrv_set_backing_hd(BlockDriverState *bs, BlockDriverState *backing_hd, + } + + bs->backing = bdrv_attach_child(bs, backing_hd, "backing", &child_backing, +- errp); ++ 0, errp); + /* If backing_hd was already part of bs's backing chain, and + * inherits_from pointed recursively to bs then let's update it to + * point directly to bs (else it will become NULL). */ +@@ -2965,6 +2968,7 @@ BdrvChild *bdrv_open_child(const char *filename, + QDict *options, const char *bdref_key, + BlockDriverState *parent, + const BdrvChildClass *child_class, ++ BdrvChildRole child_role, + bool allow_none, Error **errp) + { + BlockDriverState *bs; +@@ -2975,7 +2979,8 @@ BdrvChild *bdrv_open_child(const char *filename, + return NULL; + } + +- return bdrv_attach_child(parent, bs, bdref_key, child_class, errp); ++ return bdrv_attach_child(parent, bs, bdref_key, child_class, child_role, ++ errp); + } + + /* +diff --git a/block/backup-top.c b/block/backup-top.c +index 282845a410..f891dd7838 100644 +--- a/block/backup-top.c ++++ b/block/backup-top.c +@@ -214,7 +214,8 @@ BlockDriverState *bdrv_backup_top_append(BlockDriverState *source, + source->supported_zero_flags); + + bdrv_ref(target); +- state->target = bdrv_attach_child(top, target, "target", &child_file, errp); ++ state->target = bdrv_attach_child(top, target, "target", &child_file, 0, ++ errp); + if (!state->target) { + bdrv_unref(target); + bdrv_unref(top); +diff --git a/block/blkdebug.c b/block/blkdebug.c +index f369d54ee4..c91e78d5c8 100644 +--- a/block/blkdebug.c ++++ b/block/blkdebug.c +@@ -497,7 +497,7 @@ static int blkdebug_open(BlockDriverState *bs, QDict *options, int flags, + + /* Open the image file */ + bs->file = bdrv_open_child(qemu_opt_get(opts, "x-image"), options, "image", +- bs, &child_file, false, &local_err); ++ bs, &child_file, 0, false, &local_err); + if (local_err) { + ret = -EINVAL; + error_propagate(errp, local_err); +diff --git a/block/blklogwrites.c b/block/blklogwrites.c +index f3b3259d8d..739db6dcf6 100644 +--- a/block/blklogwrites.c ++++ b/block/blklogwrites.c +@@ -157,7 +157,7 @@ static int blk_log_writes_open(BlockDriverState *bs, QDict *options, int flags, + } + + /* Open the file */ +- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, false, ++ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, 0, false, + &local_err); + if (local_err) { + ret = -EINVAL; +@@ -166,8 +166,8 @@ static int blk_log_writes_open(BlockDriverState *bs, QDict *options, int flags, + } + + /* Open the log file */ +- s->log_file = bdrv_open_child(NULL, options, "log", bs, &child_file, false, +- &local_err); ++ s->log_file = bdrv_open_child(NULL, options, "log", bs, &child_file, 0, ++ false, &local_err); + if (local_err) { + ret = -EINVAL; + error_propagate(errp, local_err); +diff --git a/block/blkreplay.c b/block/blkreplay.c +index 131c9e8477..9b2814fc58 100644 +--- a/block/blkreplay.c ++++ b/block/blkreplay.c +@@ -28,7 +28,7 @@ static int blkreplay_open(BlockDriverState *bs, QDict *options, int flags, + + /* Open the image file */ + bs->file = bdrv_open_child(NULL, options, "image", +- bs, &child_file, false, &local_err); ++ bs, &child_file, 0, false, &local_err); + if (local_err) { + ret = -EINVAL; + error_propagate(errp, local_err); +diff --git a/block/blkverify.c b/block/blkverify.c +index ba6b1853ae..ba4f6d7b7c 100644 +--- a/block/blkverify.c ++++ b/block/blkverify.c +@@ -125,7 +125,7 @@ static int blkverify_open(BlockDriverState *bs, QDict *options, int flags, + + /* Open the raw file */ + bs->file = bdrv_open_child(qemu_opt_get(opts, "x-raw"), options, "raw", +- bs, &child_file, false, &local_err); ++ bs, &child_file, 0, false, &local_err); + if (local_err) { + ret = -EINVAL; + error_propagate(errp, local_err); +@@ -134,7 +134,7 @@ static int blkverify_open(BlockDriverState *bs, QDict *options, int flags, + + /* Open the test file */ + s->test_file = bdrv_open_child(qemu_opt_get(opts, "x-image"), options, +- "test", bs, &child_format, false, ++ "test", bs, &child_format, 0, false, + &local_err); + if (local_err) { + ret = -EINVAL; +diff --git a/block/block-backend.c b/block/block-backend.c +index c0af79147a..efc7acb3d8 100644 +--- a/block/block-backend.c ++++ b/block/block-backend.c +@@ -423,7 +423,7 @@ BlockBackend *blk_new_open(const char *filename, const char *reference, + return NULL; + } + +- blk->root = bdrv_root_attach_child(bs, "root", &child_root, blk->ctx, ++ blk->root = bdrv_root_attach_child(bs, "root", &child_root, 0, blk->ctx, + perm, BLK_PERM_ALL, blk, errp); + if (!blk->root) { + blk_unref(blk); +@@ -834,7 +834,7 @@ int blk_insert_bs(BlockBackend *blk, BlockDriverState *bs, Error **errp) + { + ThrottleGroupMember *tgm = &blk->public.throttle_group_member; + bdrv_ref(bs); +- blk->root = bdrv_root_attach_child(bs, "root", &child_root, blk->ctx, ++ blk->root = bdrv_root_attach_child(bs, "root", &child_root, 0, blk->ctx, + blk->perm, blk->shared_perm, blk, errp); + if (blk->root == NULL) { + return -EPERM; +diff --git a/block/bochs.c b/block/bochs.c +index e7bbeaa1c4..b013e73063 100644 +--- a/block/bochs.c ++++ b/block/bochs.c +@@ -110,7 +110,7 @@ static int bochs_open(BlockDriverState *bs, QDict *options, int flags, + return ret; + } + +- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, ++ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, 0, + false, errp); + if (!bs->file) { + return -EINVAL; +diff --git a/block/cloop.c b/block/cloop.c +index f90f1a4b4c..3ed9fa63cc 100644 +--- a/block/cloop.c ++++ b/block/cloop.c +@@ -71,7 +71,7 @@ static int cloop_open(BlockDriverState *bs, QDict *options, int flags, + return ret; + } + +- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, ++ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, 0, + false, errp); + if (!bs->file) { + return -EINVAL; +diff --git a/block/copy-on-read.c b/block/copy-on-read.c +index 7504ca6ffc..a2c4e6dc58 100644 +--- a/block/copy-on-read.c ++++ b/block/copy-on-read.c +@@ -28,7 +28,7 @@ + static int cor_open(BlockDriverState *bs, QDict *options, int flags, + Error **errp) + { +- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, false, ++ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, 0, false, + errp); + if (!bs->file) { + return -EINVAL; +diff --git a/block/crypto.c b/block/crypto.c +index bdb2b27475..8b516bfee2 100644 +--- a/block/crypto.c ++++ b/block/crypto.c +@@ -218,7 +218,7 @@ static int block_crypto_open_generic(QCryptoBlockFormat format, + unsigned int cflags = 0; + QDict *cryptoopts = NULL; + +- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, ++ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, 0, + false, errp); + if (!bs->file) { + return -EINVAL; +diff --git a/block/dmg.c b/block/dmg.c +index ef3c6e771d..af8188638c 100644 +--- a/block/dmg.c ++++ b/block/dmg.c +@@ -439,7 +439,7 @@ static int dmg_open(BlockDriverState *bs, QDict *options, int flags, + return ret; + } + +- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, ++ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, 0, + false, errp); + if (!bs->file) { + return -EINVAL; +diff --git a/block/filter-compress.c b/block/filter-compress.c +index 82c315b298..4dc5f9fb8c 100644 +--- a/block/filter-compress.c ++++ b/block/filter-compress.c +@@ -30,7 +30,7 @@ + static int compress_open(BlockDriverState *bs, QDict *options, int flags, + Error **errp) + { +- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, false, ++ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, 0, false, + errp); + if (!bs->file) { + return -EINVAL; +diff --git a/block/parallels.c b/block/parallels.c +index bd5f6ffa09..9855ac1162 100644 +--- a/block/parallels.c ++++ b/block/parallels.c +@@ -739,7 +739,7 @@ static int parallels_open(BlockDriverState *bs, QDict *options, int flags, + Error *local_err = NULL; + char *buf; + +- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, ++ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, 0, + false, errp); + if (!bs->file) { + return -EINVAL; +diff --git a/block/qcow.c b/block/qcow.c +index 6a72dea049..13583f0339 100644 +--- a/block/qcow.c ++++ b/block/qcow.c +@@ -130,7 +130,7 @@ static int qcow_open(BlockDriverState *bs, QDict *options, int flags, + qdict_extract_subqdict(options, &encryptopts, "encrypt."); + encryptfmt = qdict_get_try_str(encryptopts, "format"); + +- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, ++ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, 0, + false, errp); + if (!bs->file) { + ret = -EINVAL; +diff --git a/block/qcow2.c b/block/qcow2.c +index 76bec61ee9..86335d9403 100644 +--- a/block/qcow2.c ++++ b/block/qcow2.c +@@ -1591,7 +1591,7 @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options, + + /* Open external data file */ + s->data_file = bdrv_open_child(NULL, options, "data-file", bs, &child_file, +- true, &local_err); ++ 0, true, &local_err); + if (local_err) { + error_propagate(errp, local_err); + ret = -EINVAL; +@@ -1601,7 +1601,7 @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options, + if (s->incompatible_features & QCOW2_INCOMPAT_DATA_FILE) { + if (!s->data_file && s->image_data_file) { + s->data_file = bdrv_open_child(s->image_data_file, options, +- "data-file", bs, &child_file, ++ "data-file", bs, &child_file, 0, + false, errp); + if (!s->data_file) { + ret = -EINVAL; +@@ -1863,7 +1863,7 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags, + .ret = -EINPROGRESS + }; + +- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, ++ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, 0, + false, errp); + if (!bs->file) { + return -EINVAL; +diff --git a/block/qed.c b/block/qed.c +index 337eb6dbb6..1ad2aba810 100644 +--- a/block/qed.c ++++ b/block/qed.c +@@ -547,7 +547,7 @@ static int bdrv_qed_open(BlockDriverState *bs, QDict *options, int flags, + .ret = -EINPROGRESS + }; + +- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, ++ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, 0, + false, errp); + if (!bs->file) { + return -EINVAL; +diff --git a/block/quorum.c b/block/quorum.c +index a0824c300d..024de76e6f 100644 +--- a/block/quorum.c ++++ b/block/quorum.c +@@ -977,7 +977,7 @@ static int quorum_open(BlockDriverState *bs, QDict *options, int flags, + assert(ret < 32); + + s->children[i] = bdrv_open_child(NULL, options, indexstr, bs, +- &child_format, false, &local_err); ++ &child_format, 0, false, &local_err); + if (local_err) { + ret = -EINVAL; + goto close_exit; +@@ -1053,7 +1053,7 @@ static void quorum_add_child(BlockDriverState *bs, BlockDriverState *child_bs, + /* We can safely add the child now */ + bdrv_ref(child_bs); + +- child = bdrv_attach_child(bs, child_bs, indexstr, &child_format, errp); ++ child = bdrv_attach_child(bs, child_bs, indexstr, &child_format, 0, errp); + if (child == NULL) { + s->next_child_index--; + goto out; +diff --git a/block/raw-format.c b/block/raw-format.c +index 00e13bb41e..4b8d4ce8be 100644 +--- a/block/raw-format.c ++++ b/block/raw-format.c +@@ -428,7 +428,7 @@ static int raw_open(BlockDriverState *bs, QDict *options, int flags, + BDRVRawState *s = bs->opaque; + int ret; + +- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, ++ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, 0, + false, errp); + if (!bs->file) { + return -EINVAL; +diff --git a/block/replication.c b/block/replication.c +index af428c5b66..052c7ef601 100644 +--- a/block/replication.c ++++ b/block/replication.c +@@ -90,7 +90,7 @@ static int replication_open(BlockDriverState *bs, QDict *options, + const char *mode; + const char *top_id; + +- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, ++ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, 0, + false, errp); + if (!bs->file) { + return -EINVAL; +diff --git a/block/throttle.c b/block/throttle.c +index 71f4bb0ad1..2dea913be7 100644 +--- a/block/throttle.c ++++ b/block/throttle.c +@@ -82,7 +82,7 @@ static int throttle_open(BlockDriverState *bs, QDict *options, + int ret; + + bs->file = bdrv_open_child(NULL, options, "file", bs, +- &child_file, false, errp); ++ &child_file, 0, false, errp); + if (!bs->file) { + return -EINVAL; + } +diff --git a/block/vdi.c b/block/vdi.c +index 0ef733ae19..653acb5fc1 100644 +--- a/block/vdi.c ++++ b/block/vdi.c +@@ -378,7 +378,7 @@ static int vdi_open(BlockDriverState *bs, QDict *options, int flags, + Error *local_err = NULL; + QemuUUID uuid_link, uuid_parent; + +- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, ++ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, 0, + false, errp); + if (!bs->file) { + return -EINVAL; +diff --git a/block/vhdx.c b/block/vhdx.c +index e692cf80cc..dde156c97b 100644 +--- a/block/vhdx.c ++++ b/block/vhdx.c +@@ -996,7 +996,7 @@ static int vhdx_open(BlockDriverState *bs, QDict *options, int flags, + uint64_t signature; + Error *local_err = NULL; + +- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, ++ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, 0, + false, errp); + if (!bs->file) { + return -EINVAL; +diff --git a/block/vmdk.c b/block/vmdk.c +index 56e85689f3..c2cb741e2d 100644 +--- a/block/vmdk.c ++++ b/block/vmdk.c +@@ -1152,7 +1152,7 @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs, + assert(ret < 32); + + extent_file = bdrv_open_child(extent_path, options, extent_opt_prefix, +- bs, &child_file, false, &local_err); ++ bs, &child_file, 0, false, &local_err); + g_free(extent_path); + if (local_err) { + error_propagate(errp, local_err); +@@ -1257,7 +1257,7 @@ static int vmdk_open(BlockDriverState *bs, QDict *options, int flags, + uint32_t magic; + Error *local_err = NULL; + +- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, ++ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, 0, + false, errp); + if (!bs->file) { + return -EINVAL; +diff --git a/block/vpc.c b/block/vpc.c +index 46a2d48659..b2a86074a5 100644 +--- a/block/vpc.c ++++ b/block/vpc.c +@@ -228,7 +228,7 @@ static int vpc_open(BlockDriverState *bs, QDict *options, int flags, + int ret; + int64_t bs_size; + +- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, ++ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, 0, + false, errp); + if (!bs->file) { + return -EINVAL; +diff --git a/block/vvfat.c b/block/vvfat.c +index f845d9b485..cd8ae50a2c 100644 +--- a/block/vvfat.c ++++ b/block/vvfat.c +@@ -3183,7 +3183,7 @@ static int enable_write_target(BlockDriverState *bs, Error **errp) + options = qdict_new(); + qdict_put_str(options, "write-target.driver", "qcow"); + s->qcow = bdrv_open_child(s->qcow_filename, options, "write-target", bs, +- &child_vvfat_qcow, false, errp); ++ &child_vvfat_qcow, 0, false, errp); + qobject_unref(options); + if (!s->qcow) { + ret = -EINVAL; +diff --git a/blockjob.c b/blockjob.c +index be38c8c550..470facfd47 100644 +--- a/blockjob.c ++++ b/blockjob.c +@@ -217,8 +217,9 @@ int block_job_add_bdrv(BlockJob *job, const char *name, BlockDriverState *bs, + if (job->job.aio_context != qemu_get_aio_context()) { + aio_context_release(job->job.aio_context); + } +- c = bdrv_root_attach_child(bs, name, &child_job, job->job.aio_context, +- perm, shared_perm, job, errp); ++ c = bdrv_root_attach_child(bs, name, &child_job, 0, ++ job->job.aio_context, perm, shared_perm, job, ++ errp); + if (job->job.aio_context != qemu_get_aio_context()) { + aio_context_acquire(job->job.aio_context); + } +diff --git a/include/block/block.h b/include/block/block.h +index 35f1a1cecf..25e299605e 100644 +--- a/include/block/block.h ++++ b/include/block/block.h +@@ -353,6 +353,7 @@ BdrvChild *bdrv_open_child(const char *filename, + QDict *options, const char *bdref_key, + BlockDriverState* parent, + const BdrvChildClass *child_class, ++ BdrvChildRole child_role, + bool allow_none, Error **errp); + BlockDriverState *bdrv_open_blockdev_ref(BlockdevRef *ref, Error **errp); + void bdrv_set_backing_hd(BlockDriverState *bs, BlockDriverState *backing_hd, +@@ -598,6 +599,7 @@ BdrvChild *bdrv_attach_child(BlockDriverState *parent_bs, + BlockDriverState *child_bs, + const char *child_name, + const BdrvChildClass *child_class, ++ BdrvChildRole child_role, + Error **errp); + + bool bdrv_op_is_blocked(BlockDriverState *bs, BlockOpType op, Error **errp); +diff --git a/include/block/block_int.h b/include/block/block_int.h +index 9a78b981e4..1c6641c17a 100644 +--- a/include/block/block_int.h ++++ b/include/block/block_int.h +@@ -746,6 +746,7 @@ struct BdrvChild { + BlockDriverState *bs; + char *name; + const BdrvChildClass *klass; ++ BdrvChildRole role; + void *opaque; + + /** +@@ -1233,6 +1234,7 @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs, + BdrvChild *bdrv_root_attach_child(BlockDriverState *child_bs, + const char *child_name, + const BdrvChildClass *child_class, ++ BdrvChildRole child_role, + AioContext *ctx, + uint64_t perm, uint64_t shared_perm, + void *opaque, Error **errp); +diff --git a/tests/test-bdrv-drain.c b/tests/test-bdrv-drain.c +index 9d683a6c11..c03705ea37 100644 +--- a/tests/test-bdrv-drain.c ++++ b/tests/test-bdrv-drain.c +@@ -1202,7 +1202,7 @@ static void do_test_delete_by_drain(bool detach_instead_of_delete, + + null_bs = bdrv_open("null-co://", NULL, NULL, BDRV_O_RDWR | BDRV_O_PROTOCOL, + &error_abort); +- bdrv_attach_child(bs, null_bs, "null-child", &child_file, &error_abort); ++ bdrv_attach_child(bs, null_bs, "null-child", &child_file, 0, &error_abort); + + /* This child will be the one to pass to requests through to, and + * it will stall until a drain occurs */ +@@ -1211,13 +1211,13 @@ static void do_test_delete_by_drain(bool detach_instead_of_delete, + child_bs->total_sectors = 65536 >> BDRV_SECTOR_BITS; + /* Takes our reference to child_bs */ + tts->wait_child = bdrv_attach_child(bs, child_bs, "wait-child", &child_file, +- &error_abort); ++ 0, &error_abort); + + /* This child is just there to be deleted + * (for detach_instead_of_delete == true) */ + null_bs = bdrv_open("null-co://", NULL, NULL, BDRV_O_RDWR | BDRV_O_PROTOCOL, + &error_abort); +- bdrv_attach_child(bs, null_bs, "null-child", &child_file, &error_abort); ++ bdrv_attach_child(bs, null_bs, "null-child", &child_file, 0, &error_abort); + + blk = blk_new(qemu_get_aio_context(), BLK_PERM_ALL, BLK_PERM_ALL); + blk_insert_bs(blk, bs, &error_abort); +@@ -1314,7 +1314,7 @@ static void detach_indirect_bh(void *opaque) + + bdrv_ref(data->c); + data->child_c = bdrv_attach_child(data->parent_b, data->c, "PB-C", +- &child_file, &error_abort); ++ &child_file, 0, &error_abort); + } + + static void detach_by_parent_aio_cb(void *opaque, int ret) +@@ -1396,13 +1396,15 @@ static void test_detach_indirect(bool by_parent_cb) + /* Set child relationships */ + bdrv_ref(b); + bdrv_ref(a); +- child_b = bdrv_attach_child(parent_b, b, "PB-B", &child_file, &error_abort); +- child_a = bdrv_attach_child(parent_b, a, "PB-A", &child_backing, &error_abort); ++ child_b = bdrv_attach_child(parent_b, b, "PB-B", &child_file, 0, ++ &error_abort); ++ child_a = bdrv_attach_child(parent_b, a, "PB-A", &child_backing, 0, ++ &error_abort); + + bdrv_ref(a); + bdrv_attach_child(parent_a, a, "PA-A", + by_parent_cb ? &child_file : &detach_by_driver_cb_class, +- &error_abort); ++ 0, &error_abort); + + g_assert_cmpint(parent_a->refcnt, ==, 1); + g_assert_cmpint(parent_b->refcnt, ==, 1); +@@ -1813,7 +1815,7 @@ static void test_drop_intermediate_poll(void) + /* Takes the reference to chain[i - 1] */ + chain[i]->backing = bdrv_attach_child(chain[i], chain[i - 1], + "chain", &chain_child_class, +- &error_abort); ++ 0, &error_abort); + } + } + +@@ -2031,7 +2033,7 @@ static void do_test_replace_child_mid_drain(int old_drain_count, + + bdrv_ref(old_child_bs); + parent_bs->backing = bdrv_attach_child(parent_bs, old_child_bs, "child", +- &child_backing, &error_abort); ++ &child_backing, 0, &error_abort); + + for (i = 0; i < old_drain_count; i++) { + bdrv_drained_begin(old_child_bs); +diff --git a/tests/test-bdrv-graph-mod.c b/tests/test-bdrv-graph-mod.c +index fef42cb294..8b8c186c9f 100644 +--- a/tests/test-bdrv-graph-mod.c ++++ b/tests/test-bdrv-graph-mod.c +@@ -111,7 +111,7 @@ static void test_update_perm_tree(void) + + blk_insert_bs(root, bs, &error_abort); + +- bdrv_attach_child(filter, bs, "child", &child_file, &error_abort); ++ bdrv_attach_child(filter, bs, "child", &child_file, 0, &error_abort); + + bdrv_append(filter, bs, &local_err); + +@@ -177,7 +177,7 @@ static void test_should_update_child(void) + bdrv_set_backing_hd(target, bs, &error_abort); + + g_assert(target->backing->bs == bs); +- bdrv_attach_child(filter, target, "target", &child_file, &error_abort); ++ bdrv_attach_child(filter, target, "target", &child_file, 0, &error_abort); + bdrv_append(filter, bs, &error_abort); + g_assert(target->backing->bs == bs); + +-- +2.23.0 + diff --git a/block-Add-BlockDriver.is_format.patch b/block-Add-BlockDriver.is_format.patch new file mode 100644 index 0000000000000000000000000000000000000000..79592b3a40435ebb1b5d16e85f1cf876816a3d69 --- /dev/null +++ b/block-Add-BlockDriver.is_format.patch @@ -0,0 +1,212 @@ +From d67066d8bc01a14f7c9d9b9aeeffb30a10f0e900 Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Wed, 13 May 2020 13:05:12 +0200 +Subject: [PATCH 534/709] block: Add BlockDriver.is_format + +We want to unify child_format and child_file at some point. One of the +important things that set format drivers apart from other drivers is +that they do not expect other format nodes under them (except in the +backing chain), i.e. we must not probe formats inside of formats. That +means we need something on which to distinguish format drivers from +others, and hence this flag. + +Signed-off-by: Max Reitz +Reviewed-by: Eric Blake +Reviewed-by: Alberto Garcia +Message-Id: <20200513110544.176672-3-mreitz@redhat.com> +Signed-off-by: Kevin Wolf +--- + block/bochs.c | 1 + + block/cloop.c | 1 + + block/crypto.c | 2 ++ + block/dmg.c | 1 + + block/parallels.c | 1 + + block/qcow.c | 1 + + block/qcow2.c | 1 + + block/qed.c | 1 + + block/raw-format.c | 1 + + block/vdi.c | 1 + + block/vhdx.c | 1 + + block/vmdk.c | 1 + + block/vpc.c | 1 + + include/block/block_int.h | 7 +++++++ + 14 files changed, 21 insertions(+) + +diff --git a/block/bochs.c b/block/bochs.c +index 32bb83b268..e7bbeaa1c4 100644 +--- a/block/bochs.c ++++ b/block/bochs.c +@@ -301,6 +301,7 @@ static BlockDriver bdrv_bochs = { + .bdrv_refresh_limits = bochs_refresh_limits, + .bdrv_co_preadv = bochs_co_preadv, + .bdrv_close = bochs_close, ++ .is_format = true, + }; + + static void bdrv_bochs_init(void) +diff --git a/block/cloop.c b/block/cloop.c +index 4de94876d4..f90f1a4b4c 100644 +--- a/block/cloop.c ++++ b/block/cloop.c +@@ -297,6 +297,7 @@ static BlockDriver bdrv_cloop = { + .bdrv_refresh_limits = cloop_refresh_limits, + .bdrv_co_preadv = cloop_co_preadv, + .bdrv_close = cloop_close, ++ .is_format = true, + }; + + static void bdrv_cloop_init(void) +diff --git a/block/crypto.c b/block/crypto.c +index 6b21d6bf6c..bdb2b27475 100644 +--- a/block/crypto.c ++++ b/block/crypto.c +@@ -771,6 +771,8 @@ static BlockDriver bdrv_crypto_luks = { + .bdrv_get_info = block_crypto_get_info_luks, + .bdrv_get_specific_info = block_crypto_get_specific_info_luks, + ++ .is_format = true, ++ + .strong_runtime_opts = block_crypto_strong_runtime_opts, + }; + +diff --git a/block/dmg.c b/block/dmg.c +index 4a045f2b3e..ef3c6e771d 100644 +--- a/block/dmg.c ++++ b/block/dmg.c +@@ -753,6 +753,7 @@ static BlockDriver bdrv_dmg = { + .bdrv_child_perm = bdrv_format_default_perms, + .bdrv_co_preadv = dmg_co_preadv, + .bdrv_close = dmg_close, ++ .is_format = true, + }; + + static void bdrv_dmg_init(void) +diff --git a/block/parallels.c b/block/parallels.c +index e7717c508e..bd5f6ffa09 100644 +--- a/block/parallels.c ++++ b/block/parallels.c +@@ -918,6 +918,7 @@ static BlockDriver bdrv_parallels = { + .bdrv_co_flush_to_os = parallels_co_flush_to_os, + .bdrv_co_readv = parallels_co_readv, + .bdrv_co_writev = parallels_co_writev, ++ .is_format = true, + .supports_backing = true, + .bdrv_co_create = parallels_co_create, + .bdrv_co_create_opts = parallels_co_create_opts, +diff --git a/block/qcow.c b/block/qcow.c +index b0475b73a5..6a72dea049 100644 +--- a/block/qcow.c ++++ b/block/qcow.c +@@ -1185,6 +1185,7 @@ static BlockDriver bdrv_qcow = { + .bdrv_co_create = qcow_co_create, + .bdrv_co_create_opts = qcow_co_create_opts, + .bdrv_has_zero_init = bdrv_has_zero_init_1, ++ .is_format = true, + .supports_backing = true, + .bdrv_refresh_limits = qcow_refresh_limits, + +diff --git a/block/qcow2.c b/block/qcow2.c +index ad9ab4fafa..76bec61ee9 100644 +--- a/block/qcow2.c ++++ b/block/qcow2.c +@@ -5767,6 +5767,7 @@ BlockDriver bdrv_qcow2 = { + .bdrv_save_vmstate = qcow2_save_vmstate, + .bdrv_load_vmstate = qcow2_load_vmstate, + ++ .is_format = true, + .supports_backing = true, + .bdrv_change_backing_file = qcow2_change_backing_file, + +diff --git a/block/qed.c b/block/qed.c +index 5da9726518..337eb6dbb6 100644 +--- a/block/qed.c ++++ b/block/qed.c +@@ -1665,6 +1665,7 @@ static BlockDriver bdrv_qed = { + .format_name = "qed", + .instance_size = sizeof(BDRVQEDState), + .create_opts = &qed_create_opts, ++ .is_format = true, + .supports_backing = true, + + .bdrv_probe = bdrv_qed_probe, +diff --git a/block/raw-format.c b/block/raw-format.c +index 9108e43696..00e13bb41e 100644 +--- a/block/raw-format.c ++++ b/block/raw-format.c +@@ -566,6 +566,7 @@ BlockDriver bdrv_raw = { + .bdrv_co_copy_range_to = &raw_co_copy_range_to, + .bdrv_co_truncate = &raw_co_truncate, + .bdrv_getlength = &raw_getlength, ++ .is_format = true, + .has_variable_length = true, + .bdrv_measure = &raw_measure, + .bdrv_get_info = &raw_get_info, +diff --git a/block/vdi.c b/block/vdi.c +index 2d28046615..0ef733ae19 100644 +--- a/block/vdi.c ++++ b/block/vdi.c +@@ -1053,6 +1053,7 @@ static BlockDriver bdrv_vdi = { + + .bdrv_get_info = vdi_get_info, + ++ .is_format = true, + .create_opts = &vdi_create_opts, + .bdrv_co_check = vdi_co_check, + }; +diff --git a/block/vhdx.c b/block/vhdx.c +index 53e756438a..e692cf80cc 100644 +--- a/block/vhdx.c ++++ b/block/vhdx.c +@@ -2254,6 +2254,7 @@ static BlockDriver bdrv_vhdx = { + .bdrv_co_check = vhdx_co_check, + .bdrv_has_zero_init = vhdx_has_zero_init, + ++ .is_format = true, + .create_opts = &vhdx_create_opts, + }; + +diff --git a/block/vmdk.c b/block/vmdk.c +index b18f128816..56e85689f3 100644 +--- a/block/vmdk.c ++++ b/block/vmdk.c +@@ -3070,6 +3070,7 @@ static BlockDriver bdrv_vmdk = { + .bdrv_get_info = vmdk_get_info, + .bdrv_gather_child_options = vmdk_gather_child_options, + ++ .is_format = true, + .supports_backing = true, + .create_opts = &vmdk_create_opts, + }; +diff --git a/block/vpc.c b/block/vpc.c +index 5e31dd1e47..46a2d48659 100644 +--- a/block/vpc.c ++++ b/block/vpc.c +@@ -1250,6 +1250,7 @@ static BlockDriver bdrv_vpc = { + + .bdrv_get_info = vpc_get_info, + ++ .is_format = true, + .create_opts = &vpc_create_opts, + .bdrv_has_zero_init = vpc_has_zero_init, + .strong_runtime_opts = vpc_strong_runtime_opts, +diff --git a/include/block/block_int.h b/include/block/block_int.h +index 7ba8c89036..1c24df53fd 100644 +--- a/include/block/block_int.h ++++ b/include/block/block_int.h +@@ -95,6 +95,13 @@ struct BlockDriver { + * must implement them and return -ENOTSUP. + */ + bool is_filter; ++ /* ++ * Set to true if the BlockDriver is a format driver. Format nodes ++ * generally do not expect their children to be other format nodes ++ * (except for backing files), and so format probing is disabled ++ * on those children. ++ */ ++ bool is_format; + /* + * Return true if @to_replace can be replaced by a BDS with the + * same data as @bs without it affecting @bs's behavior (that is, +-- +2.23.0 + diff --git a/block-Add-bdrv_default_perms.patch b/block-Add-bdrv_default_perms.patch new file mode 100644 index 0000000000000000000000000000000000000000..c95c3251271393f90676229d3c9b22e5435df901 --- /dev/null +++ b/block-Add-bdrv_default_perms.patch @@ -0,0 +1,96 @@ +From 2519f54919a9c3e0696e2fac7d564e15722618c4 Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Wed, 13 May 2020 13:05:29 +0200 +Subject: [PATCH 551/709] block: Add bdrv_default_perms() + +This callback can be used by BDSs that use child_of_bds with the +appropriate BdrvChildRole for their children. + +Also, make bdrv_format_default_perms() use it for child_of_bds children +(just a temporary solution until we can drop bdrv_format_default_perms() +altogether). + +Signed-off-by: Max Reitz +Message-Id: <20200513110544.176672-20-mreitz@redhat.com> +Reviewed-by: Eric Blake +Signed-off-by: Kevin Wolf +--- + block.c | 32 ++++++++++++++++++++++++++++++++ + include/block/block_int.h | 11 +++++++++++ + 2 files changed, 43 insertions(+) + +diff --git a/block.c b/block.c +index 5ff6cbd796..088727fdbe 100644 +--- a/block.c ++++ b/block.c +@@ -2596,6 +2596,13 @@ void bdrv_format_default_perms(BlockDriverState *bs, BdrvChild *c, + uint64_t *nperm, uint64_t *nshared) + { + bool backing = (child_class == &child_backing); ++ ++ if (child_class == &child_of_bds) { ++ bdrv_default_perms(bs, c, child_class, role, reopen_queue, ++ perm, shared, nperm, nshared); ++ return; ++ } ++ + assert(child_class == &child_backing || child_class == &child_file); + + if (!backing) { +@@ -2607,6 +2614,31 @@ void bdrv_format_default_perms(BlockDriverState *bs, BdrvChild *c, + } + } + ++void bdrv_default_perms(BlockDriverState *bs, BdrvChild *c, ++ const BdrvChildClass *child_class, BdrvChildRole role, ++ BlockReopenQueue *reopen_queue, ++ uint64_t perm, uint64_t shared, ++ uint64_t *nperm, uint64_t *nshared) ++{ ++ assert(child_class == &child_of_bds); ++ ++ if (role & BDRV_CHILD_FILTERED) { ++ assert(!(role & (BDRV_CHILD_DATA | BDRV_CHILD_METADATA | ++ BDRV_CHILD_COW))); ++ bdrv_filter_default_perms(bs, c, child_class, role, reopen_queue, ++ perm, shared, nperm, nshared); ++ } else if (role & BDRV_CHILD_COW) { ++ assert(!(role & (BDRV_CHILD_DATA | BDRV_CHILD_METADATA))); ++ bdrv_default_perms_for_cow(bs, c, child_class, role, reopen_queue, ++ perm, shared, nperm, nshared); ++ } else if (role & (BDRV_CHILD_METADATA | BDRV_CHILD_DATA)) { ++ bdrv_default_perms_for_storage(bs, c, child_class, role, reopen_queue, ++ perm, shared, nperm, nshared); ++ } else { ++ g_assert_not_reached(); ++ } ++} ++ + uint64_t bdrv_qapi_perm_to_blk_perm(BlockPermission qapi_perm) + { + static const uint64_t permissions[] = { +diff --git a/include/block/block_int.h b/include/block/block_int.h +index 54df821d61..3a9dda9be7 100644 +--- a/include/block/block_int.h ++++ b/include/block/block_int.h +@@ -1288,6 +1288,17 @@ void bdrv_format_default_perms(BlockDriverState *bs, BdrvChild *c, + bool bdrv_recurse_can_replace(BlockDriverState *bs, + BlockDriverState *to_replace); + ++/* ++ * Default implementation for BlockDriver.bdrv_child_perm() that can ++ * be used by block filters and image formats, as long as they use the ++ * child_of_bds child class and set an appropriate BdrvChildRole. ++ */ ++void bdrv_default_perms(BlockDriverState *bs, BdrvChild *c, ++ const BdrvChildClass *child_class, BdrvChildRole role, ++ BlockReopenQueue *reopen_queue, ++ uint64_t perm, uint64_t shared, ++ uint64_t *nperm, uint64_t *nshared); ++ + /* + * Default implementation for drivers to pass bdrv_co_block_status() to + * their file. +-- +2.23.0 + diff --git a/block-Add-bdrv_make_empty.patch b/block-Add-bdrv_make_empty.patch new file mode 100644 index 0000000000000000000000000000000000000000..92e311906167226db48ebfd1583f06c05c84e3b4 --- /dev/null +++ b/block-Add-bdrv_make_empty.patch @@ -0,0 +1,68 @@ +From 6f7a3b535f0d48d138e43cadf13323f083bfb547 Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Wed, 29 Apr 2020 16:11:23 +0200 +Subject: [PATCH 528/709] block: Add bdrv_make_empty() + +Right now, all users of bdrv_make_empty() call the BlockDriver method +directly. That is not only bad style, it is also wrong, unless the +caller has a BdrvChild with a WRITE or WRITE_UNCHANGED permission. +(WRITE_UNCHANGED suffices, because callers generally use this function +to clear a node with a backing file after a commit operation.) + +Introduce bdrv_make_empty() that verifies that it does. + +Signed-off-by: Max Reitz +Message-Id: <20200429141126.85159-2-mreitz@redhat.com> +Reviewed-by: Eric Blake +Signed-off-by: Kevin Wolf +--- + block.c | 23 +++++++++++++++++++++++ + include/block/block.h | 1 + + 2 files changed, 24 insertions(+) + +diff --git a/block.c b/block.c +index 0653ccb913..c6a5c144b7 100644 +--- a/block.c ++++ b/block.c +@@ -6764,3 +6764,26 @@ void bdrv_del_child(BlockDriverState *parent_bs, BdrvChild *child, Error **errp) + + parent_bs->drv->bdrv_del_child(parent_bs, child, errp); + } ++ ++int bdrv_make_empty(BdrvChild *c, Error **errp) ++{ ++ BlockDriver *drv = c->bs->drv; ++ int ret; ++ ++ assert(c->perm & (BLK_PERM_WRITE | BLK_PERM_WRITE_UNCHANGED)); ++ ++ if (!drv->bdrv_make_empty) { ++ error_setg(errp, "%s does not support emptying nodes", ++ drv->format_name); ++ return -ENOTSUP; ++ } ++ ++ ret = drv->bdrv_make_empty(c->bs); ++ if (ret < 0) { ++ error_setg_errno(errp, -ret, "Failed to empty %s", ++ c->bs->filename); ++ return ret; ++ } ++ ++ return 0; ++} +diff --git a/include/block/block.h b/include/block/block.h +index 4de8d8f8a6..8f3eb70df4 100644 +--- a/include/block/block.h ++++ b/include/block/block.h +@@ -352,6 +352,7 @@ BlockMeasureInfo *bdrv_measure(BlockDriver *drv, QemuOpts *opts, + void bdrv_get_geometry(BlockDriverState *bs, uint64_t *nb_sectors_ptr); + void bdrv_refresh_limits(BlockDriverState *bs, Error **errp); + int bdrv_commit(BlockDriverState *bs); ++int bdrv_make_empty(BdrvChild *c, Error **errp); + int bdrv_change_backing_file(BlockDriverState *bs, + const char *backing_file, const char *backing_fmt); + void bdrv_register(BlockDriver *bdrv); +-- +2.23.0 + diff --git a/block-Add-blk_make_empty.patch b/block-Add-blk_make_empty.patch new file mode 100644 index 0000000000000000000000000000000000000000..18b493fab50368151b34bf52ddcb46a11f62047c --- /dev/null +++ b/block-Add-blk_make_empty.patch @@ -0,0 +1,50 @@ +From 2b7bbdbdefe203cf8468c61b4217e578981d6fce Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Wed, 29 Apr 2020 16:11:25 +0200 +Subject: [PATCH 529/709] block: Add blk_make_empty() + +Two callers of BlockDriver.bdrv_make_empty() remain that should not call +this method directly. Both do not have access to a BdrvChild, but they +can use a BlockBackend, so we add this function that lets them use it. + +Signed-off-by: Max Reitz +Message-Id: <20200429141126.85159-4-mreitz@redhat.com> +Reviewed-by: Eric Blake +Signed-off-by: Kevin Wolf +--- + block/block-backend.c | 10 ++++++++++ + include/sysemu/block-backend.h | 2 ++ + 2 files changed, 12 insertions(+) + +diff --git a/block/block-backend.c b/block/block-backend.c +index f4944861fa..47bd56244d 100644 +--- a/block/block-backend.c ++++ b/block/block-backend.c +@@ -2402,3 +2402,13 @@ const BdrvChild *blk_root(BlockBackend *blk) + { + return blk->root; + } ++ ++int blk_make_empty(BlockBackend *blk, Error **errp) ++{ ++ if (!blk_is_available(blk)) { ++ error_setg(errp, "No medium inserted"); ++ return -ENOMEDIUM; ++ } ++ ++ return bdrv_make_empty(blk->root, errp); ++} +diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h +index 0917663d89..8203d7f6f9 100644 +--- a/include/sysemu/block-backend.h ++++ b/include/sysemu/block-backend.h +@@ -266,4 +266,6 @@ int coroutine_fn blk_co_copy_range(BlockBackend *blk_in, int64_t off_in, + + const BdrvChild *blk_root(BlockBackend *blk); + ++int blk_make_empty(BlockBackend *blk, Error **errp); ++ + #endif +-- +2.23.0 + diff --git a/block-Add-blk_new_with_bs-helper.patch b/block-Add-blk_new_with_bs-helper.patch new file mode 100644 index 0000000000000000000000000000000000000000..f918647a58aa3485bdf478d7eeae3f48ae6589f9 --- /dev/null +++ b/block-Add-blk_new_with_bs-helper.patch @@ -0,0 +1,343 @@ +From a3aeeab557f08285c4fcf537fca575b069eb67ef Mon Sep 17 00:00:00 2001 +From: Eric Blake +Date: Tue, 28 Apr 2020 14:26:46 -0500 +Subject: [PATCH 255/709] block: Add blk_new_with_bs() helper + +There are several callers that need to create a new block backend from +an existing BDS; make the task slightly easier with a common helper +routine. + +Suggested-by: Max Reitz +Signed-off-by: Eric Blake +Message-Id: <20200424190903.522087-2-eblake@redhat.com> +[mreitz: Set @ret only in error paths, see + https://lists.nongnu.org/archive/html/qemu-block/2020-04/msg01216.html] +Signed-off-by: Max Reitz +Message-Id: <20200428192648.749066-2-eblake@redhat.com> +Signed-off-by: Max Reitz +--- + block/block-backend.c | 23 +++++++++++++++++++++++ + block/crypto.c | 9 ++++----- + block/parallels.c | 8 ++++---- + block/qcow.c | 8 ++++---- + block/qcow2.c | 18 ++++++++---------- + block/qed.c | 8 ++++---- + block/sheepdog.c | 10 +++++----- + block/vdi.c | 8 ++++---- + block/vhdx.c | 8 ++++---- + block/vmdk.c | 9 ++++----- + block/vpc.c | 8 ++++---- + blockdev.c | 6 ++---- + blockjob.c | 7 ++----- + include/sysemu/block-backend.h | 2 ++ + 14 files changed, 75 insertions(+), 59 deletions(-) + +diff --git a/block/block-backend.c b/block/block-backend.c +index 17ed6d8c5b..f4944861fa 100644 +--- a/block/block-backend.c ++++ b/block/block-backend.c +@@ -355,6 +355,29 @@ BlockBackend *blk_new(AioContext *ctx, uint64_t perm, uint64_t shared_perm) + return blk; + } + ++/* ++ * Create a new BlockBackend connected to an existing BlockDriverState. ++ * ++ * @perm is a bitmasks of BLK_PERM_* constants which describes the ++ * permissions to request for @bs that is attached to this ++ * BlockBackend. @shared_perm is a bitmask which describes which ++ * permissions may be granted to other users of the attached node. ++ * Both sets of permissions can be changed later using blk_set_perm(). ++ * ++ * Return the new BlockBackend on success, null on failure. ++ */ ++BlockBackend *blk_new_with_bs(BlockDriverState *bs, uint64_t perm, ++ uint64_t shared_perm, Error **errp) ++{ ++ BlockBackend *blk = blk_new(bdrv_get_aio_context(bs), perm, shared_perm); ++ ++ if (blk_insert_bs(blk, bs, errp) < 0) { ++ blk_unref(blk); ++ return NULL; ++ } ++ return blk; ++} ++ + /* + * Creates a new BlockBackend, opens a new BlockDriverState, and connects both. + * The new BlockBackend is in the main AioContext. +diff --git a/block/crypto.c b/block/crypto.c +index e02f343590..ca44dae4f7 100644 +--- a/block/crypto.c ++++ b/block/crypto.c +@@ -261,11 +261,10 @@ static int block_crypto_co_create_generic(BlockDriverState *bs, + QCryptoBlock *crypto = NULL; + struct BlockCryptoCreateData data; + +- blk = blk_new(bdrv_get_aio_context(bs), +- BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL); +- +- ret = blk_insert_bs(blk, bs, errp); +- if (ret < 0) { ++ blk = blk_new_with_bs(bs, BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL, ++ errp); ++ if (!blk) { ++ ret = -EPERM; + goto cleanup; + } + +diff --git a/block/parallels.c b/block/parallels.c +index 2be92cf417..8db64a55e3 100644 +--- a/block/parallels.c ++++ b/block/parallels.c +@@ -559,10 +559,10 @@ static int coroutine_fn parallels_co_create(BlockdevCreateOptions* opts, + return -EIO; + } + +- blk = blk_new(bdrv_get_aio_context(bs), +- BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL); +- ret = blk_insert_bs(blk, bs, errp); +- if (ret < 0) { ++ blk = blk_new_with_bs(bs, BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL, ++ errp); ++ if (!blk) { ++ ret = -EPERM; + goto out; + } + blk_set_allow_write_beyond_eof(blk, true); +diff --git a/block/qcow.c b/block/qcow.c +index 6b5f2269f0..b0475b73a5 100644 +--- a/block/qcow.c ++++ b/block/qcow.c +@@ -849,10 +849,10 @@ static int coroutine_fn qcow_co_create(BlockdevCreateOptions *opts, + return -EIO; + } + +- qcow_blk = blk_new(bdrv_get_aio_context(bs), +- BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL); +- ret = blk_insert_bs(qcow_blk, bs, errp); +- if (ret < 0) { ++ qcow_blk = blk_new_with_bs(bs, BLK_PERM_WRITE | BLK_PERM_RESIZE, ++ BLK_PERM_ALL, errp); ++ if (!qcow_blk) { ++ ret = -EPERM; + goto exit; + } + blk_set_allow_write_beyond_eof(qcow_blk, true); +diff --git a/block/qcow2.c b/block/qcow2.c +index 2ba0b17c39..0edc7f4643 100644 +--- a/block/qcow2.c ++++ b/block/qcow2.c +@@ -3405,10 +3405,10 @@ qcow2_co_create(BlockdevCreateOptions *create_options, Error **errp) + } + + /* Create BlockBackend to write to the image */ +- blk = blk_new(bdrv_get_aio_context(bs), +- BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL); +- ret = blk_insert_bs(blk, bs, errp); +- if (ret < 0) { ++ blk = blk_new_with_bs(bs, BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL, ++ errp); ++ if (!blk) { ++ ret = -EPERM; + goto out; + } + blk_set_allow_write_beyond_eof(blk, true); +@@ -5412,12 +5412,10 @@ static int qcow2_amend_options(BlockDriverState *bs, QemuOpts *opts, + } + + if (new_size) { +- BlockBackend *blk = blk_new(bdrv_get_aio_context(bs), +- BLK_PERM_RESIZE, BLK_PERM_ALL); +- ret = blk_insert_bs(blk, bs, errp); +- if (ret < 0) { +- blk_unref(blk); +- return ret; ++ BlockBackend *blk = blk_new_with_bs(bs, BLK_PERM_RESIZE, BLK_PERM_ALL, ++ errp); ++ if (!blk) { ++ return -EPERM; + } + + /* +diff --git a/block/qed.c b/block/qed.c +index b0fdb8f565..fb609cfba1 100644 +--- a/block/qed.c ++++ b/block/qed.c +@@ -651,10 +651,10 @@ static int coroutine_fn bdrv_qed_co_create(BlockdevCreateOptions *opts, + return -EIO; + } + +- blk = blk_new(bdrv_get_aio_context(bs), +- BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL); +- ret = blk_insert_bs(blk, bs, errp); +- if (ret < 0) { ++ blk = blk_new_with_bs(bs, BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL, ++ errp); ++ if (!blk) { ++ ret = -EPERM; + goto out; + } + blk_set_allow_write_beyond_eof(blk, true); +diff --git a/block/sheepdog.c b/block/sheepdog.c +index 76729f40a4..2eb61938ff 100644 +--- a/block/sheepdog.c ++++ b/block/sheepdog.c +@@ -1803,12 +1803,12 @@ static int sd_prealloc(BlockDriverState *bs, int64_t old_size, int64_t new_size, + void *buf = NULL; + int ret; + +- blk = blk_new(bdrv_get_aio_context(bs), +- BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE | BLK_PERM_RESIZE, +- BLK_PERM_ALL); ++ blk = blk_new_with_bs(bs, ++ BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE | BLK_PERM_RESIZE, ++ BLK_PERM_ALL, errp); + +- ret = blk_insert_bs(blk, bs, errp); +- if (ret < 0) { ++ if (!blk) { ++ ret = -EPERM; + goto out_with_err_set; + } + +diff --git a/block/vdi.c b/block/vdi.c +index 0c7835ae70..2d28046615 100644 +--- a/block/vdi.c ++++ b/block/vdi.c +@@ -804,10 +804,10 @@ static int coroutine_fn vdi_co_do_create(BlockdevCreateOptions *create_options, + goto exit; + } + +- blk = blk_new(bdrv_get_aio_context(bs_file), +- BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL); +- ret = blk_insert_bs(blk, bs_file, errp); +- if (ret < 0) { ++ blk = blk_new_with_bs(bs_file, BLK_PERM_WRITE | BLK_PERM_RESIZE, ++ BLK_PERM_ALL, errp); ++ if (!blk) { ++ ret = -EPERM; + goto exit; + } + +diff --git a/block/vhdx.c b/block/vhdx.c +index 45be0a4321..9d3951f4ee 100644 +--- a/block/vhdx.c ++++ b/block/vhdx.c +@@ -1984,10 +1984,10 @@ static int coroutine_fn vhdx_co_create(BlockdevCreateOptions *opts, + return -EIO; + } + +- blk = blk_new(bdrv_get_aio_context(bs), +- BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL); +- ret = blk_insert_bs(blk, bs, errp); +- if (ret < 0) { ++ blk = blk_new_with_bs(bs, BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL, ++ errp); ++ if (!blk) { ++ ret = -EPERM; + goto delete_and_exit; + } + blk_set_allow_write_beyond_eof(blk, true); +diff --git a/block/vmdk.c b/block/vmdk.c +index 8ec18f35a5..b02fdd14b2 100644 +--- a/block/vmdk.c ++++ b/block/vmdk.c +@@ -2717,11 +2717,10 @@ static BlockBackend *vmdk_co_create_cb(int64_t size, int idx, + if (!bs) { + return NULL; + } +- blk = blk_new(bdrv_get_aio_context(bs), +- BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE | BLK_PERM_RESIZE, +- BLK_PERM_ALL); +- if (blk_insert_bs(blk, bs, errp)) { +- bdrv_unref(bs); ++ blk = blk_new_with_bs(bs, ++ BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE | BLK_PERM_RESIZE, ++ BLK_PERM_ALL, errp); ++ if (!blk) { + return NULL; + } + blk_set_allow_write_beyond_eof(blk, true); +diff --git a/block/vpc.c b/block/vpc.c +index 2d1eade146..5e31dd1e47 100644 +--- a/block/vpc.c ++++ b/block/vpc.c +@@ -1012,10 +1012,10 @@ static int coroutine_fn vpc_co_create(BlockdevCreateOptions *opts, + return -EIO; + } + +- blk = blk_new(bdrv_get_aio_context(bs), +- BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL); +- ret = blk_insert_bs(blk, bs, errp); +- if (ret < 0) { ++ blk = blk_new_with_bs(bs, BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL, ++ errp); ++ if (!blk) { ++ ret = -EPERM; + goto out; + } + blk_set_allow_write_beyond_eof(blk, true); +diff --git a/blockdev.c b/blockdev.c +index dc1a0c7c2f..b3c840ec03 100644 +--- a/blockdev.c ++++ b/blockdev.c +@@ -2711,7 +2711,6 @@ void qmp_block_resize(bool has_device, const char *device, + BlockBackend *blk = NULL; + BlockDriverState *bs; + AioContext *aio_context; +- int ret; + + bs = bdrv_lookup_bs(has_device ? device : NULL, + has_node_name ? node_name : NULL, +@@ -2734,9 +2733,8 @@ void qmp_block_resize(bool has_device, const char *device, + goto out; + } + +- blk = blk_new(bdrv_get_aio_context(bs), BLK_PERM_RESIZE, BLK_PERM_ALL); +- ret = blk_insert_bs(blk, bs, errp); +- if (ret < 0) { ++ blk = blk_new_with_bs(bs, BLK_PERM_RESIZE, BLK_PERM_ALL, errp); ++ if (!blk) { + goto out; + } + +diff --git a/blockjob.c b/blockjob.c +index fc850312c1..2affa1844d 100644 +--- a/blockjob.c ++++ b/blockjob.c +@@ -397,16 +397,13 @@ void *block_job_create(const char *job_id, const BlockJobDriver *driver, + { + BlockBackend *blk; + BlockJob *job; +- int ret; + + if (job_id == NULL && !(flags & JOB_INTERNAL)) { + job_id = bdrv_get_device_name(bs); + } + +- blk = blk_new(bdrv_get_aio_context(bs), perm, shared_perm); +- ret = blk_insert_bs(blk, bs, errp); +- if (ret < 0) { +- blk_unref(blk); ++ blk = blk_new_with_bs(bs, perm, shared_perm, errp); ++ if (!blk) { + return NULL; + } + +diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h +index 34de7faa81..0917663d89 100644 +--- a/include/sysemu/block-backend.h ++++ b/include/sysemu/block-backend.h +@@ -77,6 +77,8 @@ typedef struct BlockBackendPublic { + } BlockBackendPublic; + + BlockBackend *blk_new(AioContext *ctx, uint64_t perm, uint64_t shared_perm); ++BlockBackend *blk_new_with_bs(BlockDriverState *bs, uint64_t perm, ++ uint64_t shared_perm, Error **errp); + BlockBackend *blk_new_open(const char *filename, const char *reference, + QDict *options, int flags, Error **errp); + int blk_get_refcnt(BlockBackend *blk); +-- +2.23.0 + diff --git a/block-Add-child_of_bds.patch b/block-Add-child_of_bds.patch new file mode 100644 index 0000000000000000000000000000000000000000..dc40e1939290416cfbe1d416012544357852ba6e --- /dev/null +++ b/block-Add-child_of_bds.patch @@ -0,0 +1,70 @@ +From 4348355032c027d0029994fc62da395e68afb60d Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Wed, 13 May 2020 13:05:24 +0200 +Subject: [PATCH 546/709] block: Add child_of_bds + +Any current user of child_file, child_format, and child_backing can and +should use this generic BdrvChildClass instead, as it can handle all of +these cases. However, to be able to do so, the users must pass the +appropriate BdrvChildRole when the child is created/attached. (The +following commits will take care of that.) + +Signed-off-by: Max Reitz +Message-Id: <20200513110544.176672-15-mreitz@redhat.com> +Reviewed-by: Eric Blake +Signed-off-by: Kevin Wolf +--- + block.c | 24 ++++++++++++++++++++++++ + include/block/block_int.h | 1 + + 2 files changed, 25 insertions(+) + +diff --git a/block.c b/block.c +index f63417c06d..be9bfa9d46 100644 +--- a/block.c ++++ b/block.c +@@ -1429,6 +1429,30 @@ static void bdrv_child_cb_detach(BdrvChild *child) + bdrv_unapply_subtree_drain(child, bs); + } + ++static int bdrv_child_cb_update_filename(BdrvChild *c, BlockDriverState *base, ++ const char *filename, Error **errp) ++{ ++ if (c->role & BDRV_CHILD_COW) { ++ return bdrv_backing_update_filename(c, base, filename, errp); ++ } ++ return 0; ++} ++ ++const BdrvChildClass child_of_bds = { ++ .parent_is_bds = true, ++ .get_parent_desc = bdrv_child_get_parent_desc, ++ .inherit_options = bdrv_inherited_options, ++ .drained_begin = bdrv_child_cb_drained_begin, ++ .drained_poll = bdrv_child_cb_drained_poll, ++ .drained_end = bdrv_child_cb_drained_end, ++ .attach = bdrv_child_cb_attach, ++ .detach = bdrv_child_cb_detach, ++ .inactivate = bdrv_child_cb_inactivate, ++ .can_set_aio_ctx = bdrv_child_cb_can_set_aio_ctx, ++ .set_aio_ctx = bdrv_child_cb_set_aio_ctx, ++ .update_filename = bdrv_child_cb_update_filename, ++}; ++ + static int bdrv_open_flags(BlockDriverState *bs, int flags) + { + int open_flags = flags; +diff --git a/include/block/block_int.h b/include/block/block_int.h +index 6245d8a18d..54df821d61 100644 +--- a/include/block/block_int.h ++++ b/include/block/block_int.h +@@ -740,6 +740,7 @@ struct BdrvChildClass { + void (*set_aio_ctx)(BdrvChild *child, AioContext *ctx, GSList **ignore); + }; + ++extern const BdrvChildClass child_of_bds; + extern const BdrvChildClass child_file; + extern const BdrvChildClass child_format; + extern const BdrvChildClass child_backing; +-- +2.23.0 + diff --git a/block-Add-flags-to-BlockDriver.bdrv_co_truncate.patch b/block-Add-flags-to-BlockDriver.bdrv_co_truncate.patch new file mode 100644 index 0000000000000000000000000000000000000000..9ee2274254679f57ae6d386a52813334910dd0c8 --- /dev/null +++ b/block-Add-flags-to-BlockDriver.bdrv_co_truncate.patch @@ -0,0 +1,271 @@ +From 92b92799dc8662b6f71809100a4aabc1ae408ebb Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Fri, 24 Apr 2020 14:54:39 +0200 +Subject: [PATCH 126/709] block: Add flags to BlockDriver.bdrv_co_truncate() + +This adds a new BdrvRequestFlags parameter to the .bdrv_co_truncate() +driver callbacks, and a supported_truncate_flags field in +BlockDriverState that allows drivers to advertise support for request +flags in the context of truncate. + +For now, we always pass 0 and no drivers declare support for any flag. + +Signed-off-by: Kevin Wolf +Reviewed-by: Vladimir Sementsov-Ogievskiy +Reviewed-by: Alberto Garcia +Reviewed-by: Max Reitz +Message-Id: <20200424125448.63318-2-kwolf@redhat.com> +Signed-off-by: Kevin Wolf +--- + block/crypto.c | 3 ++- + block/file-posix.c | 2 +- + block/file-win32.c | 2 +- + block/gluster.c | 1 + + block/io.c | 8 +++++++- + block/iscsi.c | 2 +- + block/nfs.c | 3 ++- + block/qcow2.c | 2 +- + block/qed.c | 1 + + block/raw-format.c | 2 +- + block/rbd.c | 1 + + block/sheepdog.c | 4 ++-- + block/ssh.c | 2 +- + include/block/block_int.h | 10 +++++++++- + tests/test-block-iothread.c | 3 ++- + 15 files changed, 33 insertions(+), 13 deletions(-) + +diff --git a/block/crypto.c b/block/crypto.c +index d577f89659..3721a8495c 100644 +--- a/block/crypto.c ++++ b/block/crypto.c +@@ -299,7 +299,8 @@ static int block_crypto_co_create_generic(BlockDriverState *bs, + + static int coroutine_fn + block_crypto_co_truncate(BlockDriverState *bs, int64_t offset, bool exact, +- PreallocMode prealloc, Error **errp) ++ PreallocMode prealloc, BdrvRequestFlags flags, ++ Error **errp) + { + BlockCrypto *crypto = bs->opaque; + uint64_t payload_offset = +diff --git a/block/file-posix.c b/block/file-posix.c +index 094e3b0212..58326a0a60 100644 +--- a/block/file-posix.c ++++ b/block/file-posix.c +@@ -2080,7 +2080,7 @@ raw_regular_truncate(BlockDriverState *bs, int fd, int64_t offset, + + static int coroutine_fn raw_co_truncate(BlockDriverState *bs, int64_t offset, + bool exact, PreallocMode prealloc, +- Error **errp) ++ BdrvRequestFlags flags, Error **errp) + { + BDRVRawState *s = bs->opaque; + struct stat st; +diff --git a/block/file-win32.c b/block/file-win32.c +index 15859839a1..a6b0dda5c3 100644 +--- a/block/file-win32.c ++++ b/block/file-win32.c +@@ -469,7 +469,7 @@ static void raw_close(BlockDriverState *bs) + + static int coroutine_fn raw_co_truncate(BlockDriverState *bs, int64_t offset, + bool exact, PreallocMode prealloc, +- Error **errp) ++ BdrvRequestFlags flags, Error **errp) + { + BDRVRawState *s = bs->opaque; + LONG low, high; +diff --git a/block/gluster.c b/block/gluster.c +index 0aa1f2cda4..d06df900f6 100644 +--- a/block/gluster.c ++++ b/block/gluster.c +@@ -1228,6 +1228,7 @@ static coroutine_fn int qemu_gluster_co_truncate(BlockDriverState *bs, + int64_t offset, + bool exact, + PreallocMode prealloc, ++ BdrvRequestFlags flags, + Error **errp) + { + BDRVGlusterState *s = bs->opaque; +diff --git a/block/io.c b/block/io.c +index aba67f66b9..04ac5cf023 100644 +--- a/block/io.c ++++ b/block/io.c +@@ -3344,6 +3344,7 @@ int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact, + BlockDriverState *bs = child->bs; + BlockDriver *drv = bs->drv; + BdrvTrackedRequest req; ++ BdrvRequestFlags flags = 0; + int64_t old_size, new_bytes; + int ret; + +@@ -3394,7 +3395,12 @@ int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact, + } + + if (drv->bdrv_co_truncate) { +- ret = drv->bdrv_co_truncate(bs, offset, exact, prealloc, errp); ++ if (flags & ~bs->supported_truncate_flags) { ++ error_setg(errp, "Block driver does not support requested flags"); ++ ret = -ENOTSUP; ++ goto out; ++ } ++ ret = drv->bdrv_co_truncate(bs, offset, exact, prealloc, flags, errp); + } else if (bs->file && drv->is_filter) { + ret = bdrv_co_truncate(bs->file, offset, exact, prealloc, errp); + } else { +diff --git a/block/iscsi.c b/block/iscsi.c +index 0b4b7210df..914a1de9fb 100644 +--- a/block/iscsi.c ++++ b/block/iscsi.c +@@ -2124,7 +2124,7 @@ static void iscsi_reopen_commit(BDRVReopenState *reopen_state) + + static int coroutine_fn iscsi_co_truncate(BlockDriverState *bs, int64_t offset, + bool exact, PreallocMode prealloc, +- Error **errp) ++ BdrvRequestFlags flags, Error **errp) + { + IscsiLun *iscsilun = bs->opaque; + int64_t cur_length; +diff --git a/block/nfs.c b/block/nfs.c +index cc2413d5ab..2393fbfe6b 100644 +--- a/block/nfs.c ++++ b/block/nfs.c +@@ -755,7 +755,8 @@ static int64_t nfs_get_allocated_file_size(BlockDriverState *bs) + + static int coroutine_fn + nfs_file_co_truncate(BlockDriverState *bs, int64_t offset, bool exact, +- PreallocMode prealloc, Error **errp) ++ PreallocMode prealloc, BdrvRequestFlags flags, ++ Error **errp) + { + NFSClient *client = bs->opaque; + int ret; +diff --git a/block/qcow2.c b/block/qcow2.c +index b524b0c53f..0b406b22fb 100644 +--- a/block/qcow2.c ++++ b/block/qcow2.c +@@ -3964,7 +3964,7 @@ fail: + + static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset, + bool exact, PreallocMode prealloc, +- Error **errp) ++ BdrvRequestFlags flags, Error **errp) + { + BDRVQcow2State *s = bs->opaque; + uint64_t old_length; +diff --git a/block/qed.c b/block/qed.c +index 1af9b3cb1d..fb6100bd20 100644 +--- a/block/qed.c ++++ b/block/qed.c +@@ -1467,6 +1467,7 @@ static int coroutine_fn bdrv_qed_co_truncate(BlockDriverState *bs, + int64_t offset, + bool exact, + PreallocMode prealloc, ++ BdrvRequestFlags flags, + Error **errp) + { + BDRVQEDState *s = bs->opaque; +diff --git a/block/raw-format.c b/block/raw-format.c +index 93b25e1b6b..9331368f43 100644 +--- a/block/raw-format.c ++++ b/block/raw-format.c +@@ -371,7 +371,7 @@ static void raw_refresh_limits(BlockDriverState *bs, Error **errp) + + static int coroutine_fn raw_co_truncate(BlockDriverState *bs, int64_t offset, + bool exact, PreallocMode prealloc, +- Error **errp) ++ BdrvRequestFlags flags, Error **errp) + { + BDRVRawState *s = bs->opaque; + +diff --git a/block/rbd.c b/block/rbd.c +index e637639a07..f2d52091c7 100644 +--- a/block/rbd.c ++++ b/block/rbd.c +@@ -1108,6 +1108,7 @@ static int coroutine_fn qemu_rbd_co_truncate(BlockDriverState *bs, + int64_t offset, + bool exact, + PreallocMode prealloc, ++ BdrvRequestFlags flags, + Error **errp) + { + int r; +diff --git a/block/sheepdog.c b/block/sheepdog.c +index 5f3aead038..76729f40a4 100644 +--- a/block/sheepdog.c ++++ b/block/sheepdog.c +@@ -2281,7 +2281,7 @@ static int64_t sd_getlength(BlockDriverState *bs) + + static int coroutine_fn sd_co_truncate(BlockDriverState *bs, int64_t offset, + bool exact, PreallocMode prealloc, +- Error **errp) ++ BdrvRequestFlags flags, Error **errp) + { + BDRVSheepdogState *s = bs->opaque; + int ret, fd; +@@ -2597,7 +2597,7 @@ static coroutine_fn int sd_co_writev(BlockDriverState *bs, int64_t sector_num, + + assert(!flags); + if (offset > s->inode.vdi_size) { +- ret = sd_co_truncate(bs, offset, false, PREALLOC_MODE_OFF, NULL); ++ ret = sd_co_truncate(bs, offset, false, PREALLOC_MODE_OFF, 0, NULL); + if (ret < 0) { + return ret; + } +diff --git a/block/ssh.c b/block/ssh.c +index 84e92821c0..9eb33df859 100644 +--- a/block/ssh.c ++++ b/block/ssh.c +@@ -1298,7 +1298,7 @@ static int64_t ssh_getlength(BlockDriverState *bs) + + static int coroutine_fn ssh_co_truncate(BlockDriverState *bs, int64_t offset, + bool exact, PreallocMode prealloc, +- Error **errp) ++ BdrvRequestFlags flags, Error **errp) + { + BDRVSSHState *s = bs->opaque; + +diff --git a/include/block/block_int.h b/include/block/block_int.h +index 4c3587ea19..92335f33c7 100644 +--- a/include/block/block_int.h ++++ b/include/block/block_int.h +@@ -355,7 +355,7 @@ struct BlockDriver { + */ + int coroutine_fn (*bdrv_co_truncate)(BlockDriverState *bs, int64_t offset, + bool exact, PreallocMode prealloc, +- Error **errp); ++ BdrvRequestFlags flags, Error **errp); + + int64_t (*bdrv_getlength)(BlockDriverState *bs); + bool has_variable_length; +@@ -847,6 +847,14 @@ struct BlockDriverState { + /* Flags honored during pwrite_zeroes (so far: BDRV_REQ_FUA, + * BDRV_REQ_MAY_UNMAP, BDRV_REQ_WRITE_UNCHANGED) */ + unsigned int supported_zero_flags; ++ /* ++ * Flags honoured during truncate (so far: BDRV_REQ_ZERO_WRITE). ++ * ++ * If BDRV_REQ_ZERO_WRITE is given, the truncate operation must make sure ++ * that any added space reads as all zeros. If this can't be guaranteed, ++ * the operation must fail. ++ */ ++ unsigned int supported_truncate_flags; + + /* the following member gives a name to every node on the bs graph. */ + char node_name[32]; +diff --git a/tests/test-block-iothread.c b/tests/test-block-iothread.c +index 0c861809f0..2f3b76323d 100644 +--- a/tests/test-block-iothread.c ++++ b/tests/test-block-iothread.c +@@ -46,7 +46,8 @@ static int coroutine_fn bdrv_test_co_pdiscard(BlockDriverState *bs, + + static int coroutine_fn + bdrv_test_co_truncate(BlockDriverState *bs, int64_t offset, bool exact, +- PreallocMode prealloc, Error **errp) ++ PreallocMode prealloc, BdrvRequestFlags flags, ++ Error **errp) + { + return 0; + } +-- +2.23.0 + diff --git a/block-Add-flags-to-bdrv-_co-_truncate.patch b/block-Add-flags-to-bdrv-_co-_truncate.patch new file mode 100644 index 0000000000000000000000000000000000000000..749b0d3a84ca6d2c61238c09dfd190f8b9151203 --- /dev/null +++ b/block-Add-flags-to-bdrv-_co-_truncate.patch @@ -0,0 +1,341 @@ +From 7b8e4857426f2e2de2441749996c6161b550bada Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Fri, 24 Apr 2020 14:54:40 +0200 +Subject: [PATCH 127/709] block: Add flags to bdrv(_co)_truncate() + +Now that block drivers can support flags for .bdrv_co_truncate, expose +the parameter in the node level interfaces bdrv_co_truncate() and +bdrv_truncate(). + +Signed-off-by: Kevin Wolf +Reviewed-by: Vladimir Sementsov-Ogievskiy +Reviewed-by: Alberto Garcia +Reviewed-by: Max Reitz +Message-Id: <20200424125448.63318-3-kwolf@redhat.com> +Signed-off-by: Kevin Wolf +--- + block/block-backend.c | 2 +- + block/crypto.c | 2 +- + block/io.c | 12 +++++++----- + block/parallels.c | 6 +++--- + block/qcow.c | 4 ++-- + block/qcow2-refcount.c | 2 +- + block/qcow2.c | 15 +++++++++------ + block/raw-format.c | 2 +- + block/vhdx-log.c | 2 +- + block/vhdx.c | 2 +- + block/vmdk.c | 2 +- + include/block/block.h | 5 +++-- + tests/test-block-iothread.c | 6 +++--- + 13 files changed, 34 insertions(+), 28 deletions(-) + +diff --git a/block/block-backend.c b/block/block-backend.c +index 38ae413826..8be20060d3 100644 +--- a/block/block-backend.c ++++ b/block/block-backend.c +@@ -2144,7 +2144,7 @@ int blk_truncate(BlockBackend *blk, int64_t offset, bool exact, + return -ENOMEDIUM; + } + +- return bdrv_truncate(blk->root, offset, exact, prealloc, errp); ++ return bdrv_truncate(blk->root, offset, exact, prealloc, 0, errp); + } + + int blk_save_vmstate(BlockBackend *blk, const uint8_t *buf, +diff --git a/block/crypto.c b/block/crypto.c +index 3721a8495c..ab33545c92 100644 +--- a/block/crypto.c ++++ b/block/crypto.c +@@ -313,7 +313,7 @@ block_crypto_co_truncate(BlockDriverState *bs, int64_t offset, bool exact, + + offset += payload_offset; + +- return bdrv_co_truncate(bs->file, offset, exact, prealloc, errp); ++ return bdrv_co_truncate(bs->file, offset, exact, prealloc, 0, errp); + } + + static void block_crypto_close(BlockDriverState *bs) +diff --git a/block/io.c b/block/io.c +index 04ac5cf023..795075954e 100644 +--- a/block/io.c ++++ b/block/io.c +@@ -3339,12 +3339,12 @@ static void bdrv_parent_cb_resize(BlockDriverState *bs) + * 'offset' bytes in length. + */ + int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact, +- PreallocMode prealloc, Error **errp) ++ PreallocMode prealloc, BdrvRequestFlags flags, ++ Error **errp) + { + BlockDriverState *bs = child->bs; + BlockDriver *drv = bs->drv; + BdrvTrackedRequest req; +- BdrvRequestFlags flags = 0; + int64_t old_size, new_bytes; + int ret; + +@@ -3402,7 +3402,7 @@ int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact, + } + ret = drv->bdrv_co_truncate(bs, offset, exact, prealloc, flags, errp); + } else if (bs->file && drv->is_filter) { +- ret = bdrv_co_truncate(bs->file, offset, exact, prealloc, errp); ++ ret = bdrv_co_truncate(bs->file, offset, exact, prealloc, flags, errp); + } else { + error_setg(errp, "Image format driver does not support resize"); + ret = -ENOTSUP; +@@ -3435,6 +3435,7 @@ typedef struct TruncateCo { + int64_t offset; + bool exact; + PreallocMode prealloc; ++ BdrvRequestFlags flags; + Error **errp; + int ret; + } TruncateCo; +@@ -3443,12 +3444,12 @@ static void coroutine_fn bdrv_truncate_co_entry(void *opaque) + { + TruncateCo *tco = opaque; + tco->ret = bdrv_co_truncate(tco->child, tco->offset, tco->exact, +- tco->prealloc, tco->errp); ++ tco->prealloc, tco->flags, tco->errp); + aio_wait_kick(); + } + + int bdrv_truncate(BdrvChild *child, int64_t offset, bool exact, +- PreallocMode prealloc, Error **errp) ++ PreallocMode prealloc, BdrvRequestFlags flags, Error **errp) + { + Coroutine *co; + TruncateCo tco = { +@@ -3456,6 +3457,7 @@ int bdrv_truncate(BdrvChild *child, int64_t offset, bool exact, + .offset = offset, + .exact = exact, + .prealloc = prealloc, ++ .flags = flags, + .errp = errp, + .ret = NOT_DONE, + }; +diff --git a/block/parallels.c b/block/parallels.c +index 6d4ed77f16..2be92cf417 100644 +--- a/block/parallels.c ++++ b/block/parallels.c +@@ -203,7 +203,7 @@ static int64_t allocate_clusters(BlockDriverState *bs, int64_t sector_num, + } else { + ret = bdrv_truncate(bs->file, + (s->data_end + space) << BDRV_SECTOR_BITS, +- false, PREALLOC_MODE_OFF, NULL); ++ false, PREALLOC_MODE_OFF, 0, NULL); + } + if (ret < 0) { + return ret; +@@ -493,7 +493,7 @@ static int coroutine_fn parallels_co_check(BlockDriverState *bs, + * That means we have to pass exact=true. + */ + ret = bdrv_truncate(bs->file, res->image_end_offset, true, +- PREALLOC_MODE_OFF, &local_err); ++ PREALLOC_MODE_OFF, 0, &local_err); + if (ret < 0) { + error_report_err(local_err); + res->check_errors++; +@@ -889,7 +889,7 @@ static void parallels_close(BlockDriverState *bs) + + /* errors are ignored, so we might as well pass exact=true */ + bdrv_truncate(bs->file, s->data_end << BDRV_SECTOR_BITS, true, +- PREALLOC_MODE_OFF, NULL); ++ PREALLOC_MODE_OFF, 0, NULL); + } + + g_free(s->bat_dirty_bmap); +diff --git a/block/qcow.c b/block/qcow.c +index 8973e4e565..6b5f2269f0 100644 +--- a/block/qcow.c ++++ b/block/qcow.c +@@ -480,7 +480,7 @@ static int get_cluster_offset(BlockDriverState *bs, + return -E2BIG; + } + ret = bdrv_truncate(bs->file, cluster_offset + s->cluster_size, +- false, PREALLOC_MODE_OFF, NULL); ++ false, PREALLOC_MODE_OFF, 0, NULL); + if (ret < 0) { + return ret; + } +@@ -1035,7 +1035,7 @@ static int qcow_make_empty(BlockDriverState *bs) + l1_length) < 0) + return -1; + ret = bdrv_truncate(bs->file, s->l1_table_offset + l1_length, false, +- PREALLOC_MODE_OFF, NULL); ++ PREALLOC_MODE_OFF, 0, NULL); + if (ret < 0) + return ret; + +diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c +index 7ef1c0e42a..d9650b9b6c 100644 +--- a/block/qcow2-refcount.c ++++ b/block/qcow2-refcount.c +@@ -2018,7 +2018,7 @@ static int check_refblocks(BlockDriverState *bs, BdrvCheckResult *res, + } + + ret = bdrv_truncate(bs->file, offset + s->cluster_size, false, +- PREALLOC_MODE_OFF, &local_err); ++ PREALLOC_MODE_OFF, 0, &local_err); + if (ret < 0) { + error_report_err(local_err); + goto resize_fail; +diff --git a/block/qcow2.c b/block/qcow2.c +index 0b406b22fb..c5b0711357 100644 +--- a/block/qcow2.c ++++ b/block/qcow2.c +@@ -3095,7 +3095,7 @@ static int coroutine_fn preallocate_co(BlockDriverState *bs, uint64_t offset, + mode = PREALLOC_MODE_OFF; + } + ret = bdrv_co_truncate(s->data_file, host_offset + cur_bytes, false, +- mode, errp); ++ mode, 0, errp); + if (ret < 0) { + return ret; + } +@@ -4061,7 +4061,7 @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset, + * always fulfilled, so there is no need to pass it on.) + */ + bdrv_co_truncate(bs->file, (last_cluster + 1) * s->cluster_size, +- false, PREALLOC_MODE_OFF, &local_err); ++ false, PREALLOC_MODE_OFF, 0, &local_err); + if (local_err) { + warn_reportf_err(local_err, + "Failed to truncate the tail of the image: "); +@@ -4083,7 +4083,8 @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset, + * file should be resized to the exact target size, too, + * so we pass @exact here. + */ +- ret = bdrv_co_truncate(s->data_file, offset, exact, prealloc, errp); ++ ret = bdrv_co_truncate(s->data_file, offset, exact, prealloc, 0, ++ errp); + if (ret < 0) { + goto fail; + } +@@ -4169,7 +4170,8 @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset, + new_file_size = allocation_start + + nb_new_data_clusters * s->cluster_size; + /* Image file grows, so @exact does not matter */ +- ret = bdrv_co_truncate(bs->file, new_file_size, false, prealloc, errp); ++ ret = bdrv_co_truncate(bs->file, new_file_size, false, prealloc, 0, ++ errp); + if (ret < 0) { + error_prepend(errp, "Failed to resize underlying file: "); + qcow2_free_clusters(bs, allocation_start, +@@ -4348,7 +4350,8 @@ qcow2_co_pwritev_compressed_part(BlockDriverState *bs, + if (len < 0) { + return len; + } +- return bdrv_co_truncate(bs->file, len, false, PREALLOC_MODE_OFF, NULL); ++ return bdrv_co_truncate(bs->file, len, false, PREALLOC_MODE_OFF, 0, ++ NULL); + } + + if (offset_into_cluster(s, offset)) { +@@ -4563,7 +4566,7 @@ static int make_completely_empty(BlockDriverState *bs) + } + + ret = bdrv_truncate(bs->file, (3 + l1_clusters) * s->cluster_size, false, +- PREALLOC_MODE_OFF, &local_err); ++ PREALLOC_MODE_OFF, 0, &local_err); + if (ret < 0) { + error_report_err(local_err); + goto fail; +diff --git a/block/raw-format.c b/block/raw-format.c +index 9331368f43..3465c9a865 100644 +--- a/block/raw-format.c ++++ b/block/raw-format.c +@@ -387,7 +387,7 @@ static int coroutine_fn raw_co_truncate(BlockDriverState *bs, int64_t offset, + + s->size = offset; + offset += s->offset; +- return bdrv_co_truncate(bs->file, offset, exact, prealloc, errp); ++ return bdrv_co_truncate(bs->file, offset, exact, prealloc, 0, errp); + } + + static void raw_eject(BlockDriverState *bs, bool eject_flag) +diff --git a/block/vhdx-log.c b/block/vhdx-log.c +index 13a49c2a33..404fb5f3cb 100644 +--- a/block/vhdx-log.c ++++ b/block/vhdx-log.c +@@ -558,7 +558,7 @@ static int vhdx_log_flush(BlockDriverState *bs, BDRVVHDXState *s, + goto exit; + } + ret = bdrv_truncate(bs->file, new_file_size, false, +- PREALLOC_MODE_OFF, NULL); ++ PREALLOC_MODE_OFF, 0, NULL); + if (ret < 0) { + goto exit; + } +diff --git a/block/vhdx.c b/block/vhdx.c +index e16fdc2f2d..3a33eda99c 100644 +--- a/block/vhdx.c ++++ b/block/vhdx.c +@@ -1264,7 +1264,7 @@ static int vhdx_allocate_block(BlockDriverState *bs, BDRVVHDXState *s, + } + + return bdrv_truncate(bs->file, *new_offset + s->block_size, false, +- PREALLOC_MODE_OFF, NULL); ++ PREALLOC_MODE_OFF, 0, NULL); + } + + /* +diff --git a/block/vmdk.c b/block/vmdk.c +index 218d9c9800..5de99fe813 100644 +--- a/block/vmdk.c ++++ b/block/vmdk.c +@@ -2077,7 +2077,7 @@ vmdk_co_pwritev_compressed(BlockDriverState *bs, uint64_t offset, + } + length = QEMU_ALIGN_UP(length, BDRV_SECTOR_SIZE); + ret = bdrv_truncate(s->extents[i].file, length, false, +- PREALLOC_MODE_OFF, NULL); ++ PREALLOC_MODE_OFF, 0, NULL); + if (ret < 0) { + return ret; + } +diff --git a/include/block/block.h b/include/block/block.h +index b05995fe9c..8b62429aa4 100644 +--- a/include/block/block.h ++++ b/include/block/block.h +@@ -339,9 +339,10 @@ BlockDriverState *bdrv_find_backing_image(BlockDriverState *bs, + void bdrv_refresh_filename(BlockDriverState *bs); + + int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact, +- PreallocMode prealloc, Error **errp); ++ PreallocMode prealloc, BdrvRequestFlags flags, ++ Error **errp); + int bdrv_truncate(BdrvChild *child, int64_t offset, bool exact, +- PreallocMode prealloc, Error **errp); ++ PreallocMode prealloc, BdrvRequestFlags flags, Error **errp); + + int64_t bdrv_nb_sectors(BlockDriverState *bs); + int64_t bdrv_getlength(BlockDriverState *bs); +diff --git a/tests/test-block-iothread.c b/tests/test-block-iothread.c +index 2f3b76323d..71e9bce3b1 100644 +--- a/tests/test-block-iothread.c ++++ b/tests/test-block-iothread.c +@@ -186,18 +186,18 @@ static void test_sync_op_truncate(BdrvChild *c) + int ret; + + /* Normal success path */ +- ret = bdrv_truncate(c, 65536, false, PREALLOC_MODE_OFF, NULL); ++ ret = bdrv_truncate(c, 65536, false, PREALLOC_MODE_OFF, 0, NULL); + g_assert_cmpint(ret, ==, 0); + + /* Early error: Negative offset */ +- ret = bdrv_truncate(c, -2, false, PREALLOC_MODE_OFF, NULL); ++ ret = bdrv_truncate(c, -2, false, PREALLOC_MODE_OFF, 0, NULL); + g_assert_cmpint(ret, ==, -EINVAL); + + /* Error: Read-only image */ + c->bs->read_only = true; + c->bs->open_flags &= ~BDRV_O_RDWR; + +- ret = bdrv_truncate(c, 65536, false, PREALLOC_MODE_OFF, NULL); ++ ret = bdrv_truncate(c, 65536, false, PREALLOC_MODE_OFF, 0, NULL); + g_assert_cmpint(ret, ==, -EACCES); + + c->bs->read_only = false; +-- +2.23.0 + diff --git a/block-Add-generic-bdrv_inherited_options.patch b/block-Add-generic-bdrv_inherited_options.patch new file mode 100644 index 0000000000000000000000000000000000000000..f9bc2edd70d97848ff0fd00529a27a7798c2de3d --- /dev/null +++ b/block-Add-generic-bdrv_inherited_options.patch @@ -0,0 +1,117 @@ +From fae8bd3904642dd7ff582f4ad4e5e63b0cacbe6f Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Wed, 13 May 2020 13:05:20 +0200 +Subject: [PATCH 542/709] block: Add generic bdrv_inherited_options() + +After the series this patch belongs to, we want to have a common +BdrvChildClass that encompasses all of child_file, child_format, and +child_backing. Such a single class needs a single .inherit_options() +implementation, and this patch introduces it. + +The next patch will show how the existing implementations can fall back +to it just by passing appropriate BdrvChildRole and parent_is_format +values. + +Signed-off-by: Max Reitz +Message-Id: <20200513110544.176672-11-mreitz@redhat.com> +Reviewed-by: Eric Blake +Signed-off-by: Kevin Wolf +--- + block.c | 81 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 81 insertions(+) + +diff --git a/block.c b/block.c +index a17c29f54b..9b0e13d537 100644 +--- a/block.c ++++ b/block.c +@@ -1356,6 +1356,87 @@ const BdrvChildClass child_backing = { + .set_aio_ctx = bdrv_child_cb_set_aio_ctx, + }; + ++/* ++ * Returns the options and flags that a generic child of a BDS should ++ * get, based on the given options and flags for the parent BDS. ++ */ ++static void __attribute__((unused)) ++ bdrv_inherited_options(BdrvChildRole role, bool parent_is_format, ++ int *child_flags, QDict *child_options, ++ int parent_flags, QDict *parent_options) ++{ ++ int flags = parent_flags; ++ ++ /* ++ * First, decide whether to set, clear, or leave BDRV_O_PROTOCOL. ++ * Generally, the question to answer is: Should this child be ++ * format-probed by default? ++ */ ++ ++ /* ++ * Pure and non-filtered data children of non-format nodes should ++ * be probed by default (even when the node itself has BDRV_O_PROTOCOL ++ * set). This only affects a very limited set of drivers (namely ++ * quorum and blkverify when this comment was written). ++ * Force-clear BDRV_O_PROTOCOL then. ++ */ ++ if (!parent_is_format && ++ (role & BDRV_CHILD_DATA) && ++ !(role & (BDRV_CHILD_METADATA | BDRV_CHILD_FILTERED))) ++ { ++ flags &= ~BDRV_O_PROTOCOL; ++ } ++ ++ /* ++ * All children of format nodes (except for COW children) and all ++ * metadata children in general should never be format-probed. ++ * Force-set BDRV_O_PROTOCOL then. ++ */ ++ if ((parent_is_format && !(role & BDRV_CHILD_COW)) || ++ (role & BDRV_CHILD_METADATA)) ++ { ++ flags |= BDRV_O_PROTOCOL; ++ } ++ ++ /* ++ * If the cache mode isn't explicitly set, inherit direct and no-flush from ++ * the parent. ++ */ ++ qdict_copy_default(child_options, parent_options, BDRV_OPT_CACHE_DIRECT); ++ qdict_copy_default(child_options, parent_options, BDRV_OPT_CACHE_NO_FLUSH); ++ qdict_copy_default(child_options, parent_options, BDRV_OPT_FORCE_SHARE); ++ ++ if (role & BDRV_CHILD_COW) { ++ /* backing files are opened read-only by default */ ++ qdict_set_default_str(child_options, BDRV_OPT_READ_ONLY, "on"); ++ qdict_set_default_str(child_options, BDRV_OPT_AUTO_READ_ONLY, "off"); ++ } else { ++ /* Inherit the read-only option from the parent if it's not set */ ++ qdict_copy_default(child_options, parent_options, BDRV_OPT_READ_ONLY); ++ qdict_copy_default(child_options, parent_options, ++ BDRV_OPT_AUTO_READ_ONLY); ++ } ++ ++ /* ++ * bdrv_co_pdiscard() respects unmap policy for the parent, so we ++ * can default to enable it on lower layers regardless of the ++ * parent option. ++ */ ++ qdict_set_default_str(child_options, BDRV_OPT_DISCARD, "unmap"); ++ ++ /* Clear flags that only apply to the top layer */ ++ flags &= ~(BDRV_O_SNAPSHOT | BDRV_O_NO_BACKING | BDRV_O_COPY_ON_READ); ++ ++ if (role & BDRV_CHILD_METADATA) { ++ flags &= ~BDRV_O_NO_IO; ++ } ++ if (role & BDRV_CHILD_COW) { ++ flags &= ~BDRV_O_TEMPORARY; ++ } ++ ++ *child_flags = flags; ++} ++ + static int bdrv_open_flags(BlockDriverState *bs, int flags) + { + int open_flags = flags; +-- +2.23.0 + diff --git a/block-Avoid-dead-assignment.patch b/block-Avoid-dead-assignment.patch new file mode 100644 index 0000000000000000000000000000000000000000..f18f5d875f5834e6f367f81baadfe14562677924 --- /dev/null +++ b/block-Avoid-dead-assignment.patch @@ -0,0 +1,42 @@ +From dfde483ea38ce221e8e634823620308550b8f7f0 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Wed, 22 Apr 2020 15:31:44 +0200 +Subject: [PATCH 195/709] block: Avoid dead assignment +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Fix warning reported by Clang static code analyzer: + + block.c:3167:5: warning: Value stored to 'ret' is never read + ret = bdrv_fill_options(&options, filename, &flags, &local_err); + ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Fixes: 462f5bcf6 +Reported-by: Clang Static Analyzer +Suggested-by: Markus Armbruster +Reviewed-by: Alistair Francis +Signed-off-by: Philippe Mathieu-Daudé +Reviewed-by: Max Reitz +Message-Id: <20200422133152.16770-2-philmd@redhat.com> +Signed-off-by: Laurent Vivier +--- + block.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/block.c b/block.c +index 301ec588bd..cf5c19b1db 100644 +--- a/block.c ++++ b/block.c +@@ -3165,7 +3165,7 @@ static BlockDriverState *bdrv_open_inherit(const char *filename, + } + + ret = bdrv_fill_options(&options, filename, &flags, &local_err); +- if (local_err) { ++ if (ret < 0) { + goto fail; + } + +-- +2.23.0 + diff --git a/block-Comment-cleanups.patch b/block-Comment-cleanups.patch new file mode 100644 index 0000000000000000000000000000000000000000..4787132dea33db34ff56e39d05ad50191c4e0a5a --- /dev/null +++ b/block-Comment-cleanups.patch @@ -0,0 +1,146 @@ +From f4649069517b71c4038add8d977a41644fb117dc Mon Sep 17 00:00:00 2001 +From: Eric Blake +Date: Tue, 28 Apr 2020 16:38:07 -0500 +Subject: [PATCH 258/709] block: Comment cleanups + +It's been a while since we got rid of the sector-based bdrv_read and +bdrv_write (commit 2e11d756); let's finish the job on a few remaining +comments. + +Signed-off-by: Eric Blake +Message-Id: <20200428213807.776655-1-eblake@redhat.com> +Reviewed-by: Alberto Garcia +Signed-off-by: Max Reitz +--- + block/io.c | 3 ++- + block/qcow2-refcount.c | 2 +- + block/vvfat.c | 10 +++++----- + tests/qemu-iotests/001 | 2 +- + tests/qemu-iotests/052 | 2 +- + tests/qemu-iotests/134 | 2 +- + tests/qemu-iotests/188 | 2 +- + 7 files changed, 12 insertions(+), 11 deletions(-) + +diff --git a/block/io.c b/block/io.c +index a4f9714230..7d30e61edc 100644 +--- a/block/io.c ++++ b/block/io.c +@@ -960,7 +960,7 @@ int bdrv_pwrite_zeroes(BdrvChild *child, int64_t offset, + * flags are passed through to bdrv_pwrite_zeroes (e.g. BDRV_REQ_MAY_UNMAP, + * BDRV_REQ_FUA). + * +- * Returns < 0 on error, 0 on success. For error codes see bdrv_write(). ++ * Returns < 0 on error, 0 on success. For error codes see bdrv_pwrite(). + */ + int bdrv_make_zero(BdrvChild *child, BdrvRequestFlags flags) + { +@@ -994,6 +994,7 @@ int bdrv_make_zero(BdrvChild *child, BdrvRequestFlags flags) + } + } + ++/* return < 0 if error. See bdrv_pwrite() for the return codes */ + int bdrv_preadv(BdrvChild *child, int64_t offset, QEMUIOVector *qiov) + { + int ret; +diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c +index d9650b9b6c..0457a6060d 100644 +--- a/block/qcow2-refcount.c ++++ b/block/qcow2-refcount.c +@@ -2660,7 +2660,7 @@ fail: + * - 0 if writing to this offset will not affect the mentioned metadata + * - a positive QCow2MetadataOverlap value indicating one overlapping section + * - a negative value (-errno) indicating an error while performing a check, +- * e.g. when bdrv_read failed on QCOW2_OL_INACTIVE_L2 ++ * e.g. when bdrv_pread failed on QCOW2_OL_INACTIVE_L2 + */ + int qcow2_check_metadata_overlap(BlockDriverState *bs, int ign, int64_t offset, + int64_t size) +diff --git a/block/vvfat.c b/block/vvfat.c +index ab800c4887..6d5c090dec 100644 +--- a/block/vvfat.c ++++ b/block/vvfat.c +@@ -2148,7 +2148,7 @@ DLOG(checkpoint()); + * - get modified FAT + * - compare the two FATs (TODO) + * - get buffer for marking used clusters +- * - recurse direntries from root (using bs->bdrv_read to make ++ * - recurse direntries from root (using bs->bdrv_pread to make + * sure to get the new data) + * - check that the FAT agrees with the size + * - count the number of clusters occupied by this directory and +@@ -2913,9 +2913,9 @@ static int handle_deletes(BDRVVVFATState* s) + /* + * synchronize mapping with new state: + * +- * - copy FAT (with bdrv_read) ++ * - copy FAT (with bdrv_pread) + * - mark all filenames corresponding to mappings as deleted +- * - recurse direntries from root (using bs->bdrv_read) ++ * - recurse direntries from root (using bs->bdrv_pread) + * - delete files corresponding to mappings marked as deleted + */ + static int do_commit(BDRVVVFATState* s) +@@ -2935,10 +2935,10 @@ static int do_commit(BDRVVVFATState* s) + return ret; + } + +- /* copy FAT (with bdrv_read) */ ++ /* copy FAT (with bdrv_pread) */ + memcpy(s->fat.pointer, s->fat2, 0x200 * s->sectors_per_fat); + +- /* recurse direntries from root (using bs->bdrv_read) */ ++ /* recurse direntries from root (using bs->bdrv_pread) */ + ret = commit_direntries(s, 0, -1); + if (ret) { + fprintf(stderr, "Fatal: error while committing (%d)\n", ret); +diff --git a/tests/qemu-iotests/001 b/tests/qemu-iotests/001 +index d87a535c33..696726e45f 100755 +--- a/tests/qemu-iotests/001 ++++ b/tests/qemu-iotests/001 +@@ -1,6 +1,6 @@ + #!/usr/bin/env bash + # +-# Test simple read/write using plain bdrv_read/bdrv_write ++# Test simple read/write using plain bdrv_pread/bdrv_pwrite + # + # Copyright (C) 2009 Red Hat, Inc. + # +diff --git a/tests/qemu-iotests/052 b/tests/qemu-iotests/052 +index 45a140910d..8d5c10601f 100755 +--- a/tests/qemu-iotests/052 ++++ b/tests/qemu-iotests/052 +@@ -1,6 +1,6 @@ + #!/usr/bin/env bash + # +-# Test bdrv_read/bdrv_write using BDRV_O_SNAPSHOT ++# Test bdrv_pread/bdrv_pwrite using BDRV_O_SNAPSHOT + # + # Copyright (C) 2013 Red Hat, Inc. + # +diff --git a/tests/qemu-iotests/134 b/tests/qemu-iotests/134 +index 5f0fb86211..5162d21662 100755 +--- a/tests/qemu-iotests/134 ++++ b/tests/qemu-iotests/134 +@@ -1,6 +1,6 @@ + #!/usr/bin/env bash + # +-# Test encrypted read/write using plain bdrv_read/bdrv_write ++# Test encrypted read/write using plain bdrv_pread/bdrv_pwrite + # + # Copyright (C) 2015 Red Hat, Inc. + # +diff --git a/tests/qemu-iotests/188 b/tests/qemu-iotests/188 +index afca44df54..09b9b6083a 100755 +--- a/tests/qemu-iotests/188 ++++ b/tests/qemu-iotests/188 +@@ -1,6 +1,6 @@ + #!/usr/bin/env bash + # +-# Test encrypted read/write using plain bdrv_read/bdrv_write ++# Test encrypted read/write using plain bdrv_pread/bdrv_pwrite + # + # Copyright (C) 2017 Red Hat, Inc. + # +-- +2.23.0 + diff --git a/block-Distinguish-paths-in-_format_default_perms.patch b/block-Distinguish-paths-in-_format_default_perms.patch new file mode 100644 index 0000000000000000000000000000000000000000..591d8779c2c586782b1618aa88748e6265df7065 --- /dev/null +++ b/block-Distinguish-paths-in-_format_default_perms.patch @@ -0,0 +1,60 @@ +From 33f2663bd58696ab836731830f9fb6a878a5b944 Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Wed, 13 May 2020 13:05:25 +0200 +Subject: [PATCH 547/709] block: Distinguish paths in *_format_default_perms + +bdrv_format_default_perms() has one code path for backing files, and one +for storage files. We want to pull them out into their own functions, +so make sure they are completely distinct before so the next patches +will be a bit cleaner. + +Signed-off-by: Max Reitz +Reviewed-by: Eric Blake +Message-Id: <20200513110544.176672-16-mreitz@redhat.com> +Signed-off-by: Kevin Wolf +--- + block.c | 19 +++++++++++++------ + 1 file changed, 13 insertions(+), 6 deletions(-) + +diff --git a/block.c b/block.c +index be9bfa9d46..b3e7ae70c7 100644 +--- a/block.c ++++ b/block.c +@@ -2497,6 +2497,13 @@ void bdrv_format_default_perms(BlockDriverState *bs, BdrvChild *c, + perm |= BLK_PERM_CONSISTENT_READ; + } + shared &= ~(BLK_PERM_WRITE | BLK_PERM_RESIZE); ++ ++ if (bs->open_flags & BDRV_O_INACTIVE) { ++ shared |= BLK_PERM_WRITE | BLK_PERM_RESIZE; ++ } ++ ++ *nperm = perm; ++ *nshared = shared; + } else { + /* We want consistent read from backing files if the parent needs it. + * No other operations are performed on backing files. */ +@@ -2513,14 +2520,14 @@ void bdrv_format_default_perms(BlockDriverState *bs, BdrvChild *c, + + shared |= BLK_PERM_CONSISTENT_READ | BLK_PERM_GRAPH_MOD | + BLK_PERM_WRITE_UNCHANGED; +- } + +- if (bs->open_flags & BDRV_O_INACTIVE) { +- shared |= BLK_PERM_WRITE | BLK_PERM_RESIZE; +- } ++ if (bs->open_flags & BDRV_O_INACTIVE) { ++ shared |= BLK_PERM_WRITE | BLK_PERM_RESIZE; ++ } + +- *nperm = perm; +- *nshared = shared; ++ *nperm = perm; ++ *nshared = shared; ++ } + } + + uint64_t bdrv_qapi_perm_to_blk_perm(BlockPermission qapi_perm) +-- +2.23.0 + diff --git a/block-Drop-bdrv_format_default_perms.patch b/block-Drop-bdrv_format_default_perms.patch new file mode 100644 index 0000000000000000000000000000000000000000..b77efedb334f8a9e83e3f3c53aae924c83bba2de --- /dev/null +++ b/block-Drop-bdrv_format_default_perms.patch @@ -0,0 +1,69 @@ +From 9aab945e9cad484d668dbd26b023261223a4b02f Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Wed, 13 May 2020 13:05:41 +0200 +Subject: [PATCH 563/709] block: Drop bdrv_format_default_perms() + +Signed-off-by: Max Reitz +Reviewed-by: Eric Blake +Message-Id: <20200513110544.176672-32-mreitz@redhat.com> +Signed-off-by: Kevin Wolf +--- + block.c | 19 ------------------- + include/block/block_int.h | 11 ----------- + 2 files changed, 30 deletions(-) + +diff --git a/block.c b/block.c +index 54bc1c3b2d..e79fe6e07e 100644 +--- a/block.c ++++ b/block.c +@@ -2517,25 +2517,6 @@ static void bdrv_default_perms_for_storage(BlockDriverState *bs, BdrvChild *c, + *nshared = shared; + } + +-void bdrv_format_default_perms(BlockDriverState *bs, BdrvChild *c, +- const BdrvChildClass *child_class, +- BdrvChildRole role, +- BlockReopenQueue *reopen_queue, +- uint64_t perm, uint64_t shared, +- uint64_t *nperm, uint64_t *nshared) +-{ +- if (child_class == &child_of_bds) { +- bdrv_default_perms(bs, c, child_class, role, reopen_queue, +- perm, shared, nperm, nshared); +- return; +- } +- +- assert(child_class == &child_file); +- +- bdrv_default_perms_for_storage(bs, c, child_class, role, reopen_queue, +- perm, shared, nperm, nshared); +-} +- + void bdrv_default_perms(BlockDriverState *bs, BdrvChild *c, + const BdrvChildClass *child_class, BdrvChildRole role, + BlockReopenQueue *reopen_queue, +diff --git a/include/block/block_int.h b/include/block/block_int.h +index 6fc5f0d333..e791c40496 100644 +--- a/include/block/block_int.h ++++ b/include/block/block_int.h +@@ -1262,17 +1262,6 @@ int bdrv_child_try_set_perm(BdrvChild *c, uint64_t perm, uint64_t shared, + */ + int bdrv_child_refresh_perms(BlockDriverState *bs, BdrvChild *c, Error **errp); + +-/* Default implementation for BlockDriver.bdrv_child_perm() that can be used by +- * (non-raw) image formats: Like above for bs->backing, but for bs->file it +- * requires WRITE | RESIZE for read-write images, always requires +- * CONSISTENT_READ and doesn't share WRITE. */ +-void bdrv_format_default_perms(BlockDriverState *bs, BdrvChild *c, +- const BdrvChildClass *child_class, +- BdrvChildRole child_role, +- BlockReopenQueue *reopen_queue, +- uint64_t perm, uint64_t shared, +- uint64_t *nperm, uint64_t *nshared); +- + bool bdrv_recurse_can_replace(BlockDriverState *bs, + BlockDriverState *to_replace); + +-- +2.23.0 + diff --git a/block-Drop-child_backing.patch b/block-Drop-child_backing.patch new file mode 100644 index 0000000000000000000000000000000000000000..f37e25c6a631e75fbd602af2dd68ef40b23a4a38 --- /dev/null +++ b/block-Drop-child_backing.patch @@ -0,0 +1,136 @@ +From ff3541c4e27030fe681d0613ef69bdffb0e29f3a Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Wed, 13 May 2020 13:05:34 +0200 +Subject: [PATCH 556/709] block: Drop child_backing + +Signed-off-by: Max Reitz +Message-Id: <20200513110544.176672-25-mreitz@redhat.com> +Reviewed-by: Eric Blake +Signed-off-by: Kevin Wolf +--- + block.c | 60 ++------------------------------------- + include/block/block_int.h | 1 - + 2 files changed, 3 insertions(+), 58 deletions(-) + +diff --git a/block.c b/block.c +index 131ae20ffc..d138a3c261 100644 +--- a/block.c ++++ b/block.c +@@ -1215,15 +1215,6 @@ static void bdrv_backing_attach(BdrvChild *c) + parent->backing_blocker); + } + +-/* XXX: Will be removed along with child_backing */ +-static void bdrv_child_cb_attach_backing(BdrvChild *c) +-{ +- if (!(c->role & BDRV_CHILD_COW)) { +- bdrv_backing_attach(c); +- } +- bdrv_child_cb_attach(c); +-} +- + static void bdrv_backing_detach(BdrvChild *c) + { + BlockDriverState *parent = c->opaque; +@@ -1234,28 +1225,6 @@ static void bdrv_backing_detach(BdrvChild *c) + parent->backing_blocker = NULL; + } + +-/* XXX: Will be removed along with child_backing */ +-static void bdrv_child_cb_detach_backing(BdrvChild *c) +-{ +- if (!(c->role & BDRV_CHILD_COW)) { +- bdrv_backing_detach(c); +- } +- bdrv_child_cb_detach(c); +-} +- +-/* +- * Returns the options and flags that bs->backing should get, based on the +- * given options and flags for the parent BDS +- */ +-static void bdrv_backing_options(BdrvChildRole role, bool parent_is_format, +- int *child_flags, QDict *child_options, +- int parent_flags, QDict *parent_options) +-{ +- bdrv_inherited_options(BDRV_CHILD_COW, true, +- child_flags, child_options, +- parent_flags, parent_options); +-} +- + static int bdrv_backing_update_filename(BdrvChild *c, BlockDriverState *base, + const char *filename, Error **errp) + { +@@ -1283,21 +1252,6 @@ static int bdrv_backing_update_filename(BdrvChild *c, BlockDriverState *base, + return ret; + } + +-const BdrvChildClass child_backing = { +- .parent_is_bds = true, +- .get_parent_desc = bdrv_child_get_parent_desc, +- .attach = bdrv_child_cb_attach_backing, +- .detach = bdrv_child_cb_detach_backing, +- .inherit_options = bdrv_backing_options, +- .drained_begin = bdrv_child_cb_drained_begin, +- .drained_poll = bdrv_child_cb_drained_poll, +- .drained_end = bdrv_child_cb_drained_end, +- .inactivate = bdrv_child_cb_inactivate, +- .update_filename = bdrv_backing_update_filename, +- .can_set_aio_ctx = bdrv_child_cb_can_set_aio_ctx, +- .set_aio_ctx = bdrv_child_cb_set_aio_ctx, +-}; +- + /* + * Returns the options and flags that a generic child of a BDS should + * get, based on the given options and flags for the parent BDS. +@@ -2446,8 +2400,7 @@ static void bdrv_default_perms_for_cow(BlockDriverState *bs, BdrvChild *c, + uint64_t perm, uint64_t shared, + uint64_t *nperm, uint64_t *nshared) + { +- assert(child_class == &child_backing || +- (child_class == &child_of_bds && (role & BDRV_CHILD_COW))); ++ assert(child_class == &child_of_bds && (role & BDRV_CHILD_COW)); + + /* + * We want consistent read from backing files if the parent needs it. +@@ -2566,23 +2519,16 @@ void bdrv_format_default_perms(BlockDriverState *bs, BdrvChild *c, + uint64_t perm, uint64_t shared, + uint64_t *nperm, uint64_t *nshared) + { +- bool backing = (child_class == &child_backing); +- + if (child_class == &child_of_bds) { + bdrv_default_perms(bs, c, child_class, role, reopen_queue, + perm, shared, nperm, nshared); + return; + } + +- assert(child_class == &child_backing || child_class == &child_file); ++ assert(child_class == &child_file); + +- if (!backing) { +- bdrv_default_perms_for_storage(bs, c, child_class, role, reopen_queue, +- perm, shared, nperm, nshared); +- } else { +- bdrv_default_perms_for_cow(bs, c, child_class, role, reopen_queue, ++ bdrv_default_perms_for_storage(bs, c, child_class, role, reopen_queue, + perm, shared, nperm, nshared); +- } + } + + void bdrv_default_perms(BlockDriverState *bs, BdrvChild *c, +diff --git a/include/block/block_int.h b/include/block/block_int.h +index 4b09fa1124..0781d43af5 100644 +--- a/include/block/block_int.h ++++ b/include/block/block_int.h +@@ -742,7 +742,6 @@ struct BdrvChildClass { + + extern const BdrvChildClass child_of_bds; + extern const BdrvChildClass child_file; +-extern const BdrvChildClass child_backing; + + struct BdrvChild { + BlockDriverState *bs; +-- +2.23.0 + diff --git a/block-Drop-child_class-from-bdrv_child_perm.patch b/block-Drop-child_class-from-bdrv_child_perm.patch new file mode 100644 index 0000000000000000000000000000000000000000..730c7cefcb3db6781a17acfe9deefaad1844d1a5 --- /dev/null +++ b/block-Drop-child_class-from-bdrv_child_perm.patch @@ -0,0 +1,400 @@ +From e5d8a4068526d3fb692e3402485edd03bc11c084 Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Wed, 13 May 2020 13:05:44 +0200 +Subject: [PATCH 566/709] block: Drop @child_class from bdrv_child_perm() + +Implementations should decide the necessary permissions based on @role. + +Signed-off-by: Max Reitz +Message-Id: <20200513110544.176672-35-mreitz@redhat.com> +Reviewed-by: Eric Blake +Signed-off-by: Kevin Wolf +--- + block.c | 39 +++++++++++++++---------------------- + block/backup-top.c | 3 +-- + block/blkdebug.c | 3 +-- + block/blklogwrites.c | 3 +-- + block/commit.c | 1 - + block/copy-on-read.c | 1 - + block/mirror.c | 1 - + block/quorum.c | 1 - + block/replication.c | 1 - + block/vvfat.c | 4 +--- + include/block/block_int.h | 4 +--- + tests/test-bdrv-drain.c | 19 +----------------- + tests/test-bdrv-graph-mod.c | 1 - + 13 files changed, 22 insertions(+), 59 deletions(-) + +diff --git a/block.c b/block.c +index 6a24b23d51..8416376c9b 100644 +--- a/block.c ++++ b/block.c +@@ -1947,13 +1947,13 @@ bool bdrv_is_writable(BlockDriverState *bs) + } + + static void bdrv_child_perm(BlockDriverState *bs, BlockDriverState *child_bs, +- BdrvChild *c, const BdrvChildClass *child_class, +- BdrvChildRole role, BlockReopenQueue *reopen_queue, ++ BdrvChild *c, BdrvChildRole role, ++ BlockReopenQueue *reopen_queue, + uint64_t parent_perm, uint64_t parent_shared, + uint64_t *nperm, uint64_t *nshared) + { + assert(bs->drv && bs->drv->bdrv_child_perm); +- bs->drv->bdrv_child_perm(bs, c, child_class, role, reopen_queue, ++ bs->drv->bdrv_child_perm(bs, c, role, reopen_queue, + parent_perm, parent_shared, + nperm, nshared); + /* TODO Take force_share from reopen_queue */ +@@ -2047,7 +2047,7 @@ static int bdrv_check_perm(BlockDriverState *bs, BlockReopenQueue *q, + uint64_t cur_perm, cur_shared; + bool child_tighten_restr; + +- bdrv_child_perm(bs, c->bs, c, c->klass, c->role, q, ++ bdrv_child_perm(bs, c->bs, c, c->role, q, + cumulative_perms, cumulative_shared_perms, + &cur_perm, &cur_shared); + ret = bdrv_child_check_perm(c, q, cur_perm, cur_shared, ignore_children, +@@ -2114,7 +2114,7 @@ static void bdrv_set_perm(BlockDriverState *bs, uint64_t cumulative_perms, + /* Update all children */ + QLIST_FOREACH(c, &bs->children, next) { + uint64_t cur_perm, cur_shared; +- bdrv_child_perm(bs, c->bs, c, c->klass, c->role, NULL, ++ bdrv_child_perm(bs, c->bs, c, c->role, NULL, + cumulative_perms, cumulative_shared_perms, + &cur_perm, &cur_shared); + bdrv_child_set_perm(c, cur_perm, cur_shared); +@@ -2342,7 +2342,7 @@ int bdrv_child_refresh_perms(BlockDriverState *bs, BdrvChild *c, Error **errp) + uint64_t perms, shared; + + bdrv_get_cumulative_perm(bs, &parent_perms, &parent_shared); +- bdrv_child_perm(bs, c->bs, c, c->klass, c->role, NULL, ++ bdrv_child_perm(bs, c->bs, c, c->role, NULL, + parent_perms, parent_shared, &perms, &shared); + + return bdrv_child_try_set_perm(c, perms, shared, errp); +@@ -2354,7 +2354,6 @@ int bdrv_child_refresh_perms(BlockDriverState *bs, BdrvChild *c, Error **errp) + * filtered child. + */ + static void bdrv_filter_default_perms(BlockDriverState *bs, BdrvChild *c, +- const BdrvChildClass *child_class, + BdrvChildRole role, + BlockReopenQueue *reopen_queue, + uint64_t perm, uint64_t shared, +@@ -2365,13 +2364,12 @@ static void bdrv_filter_default_perms(BlockDriverState *bs, BdrvChild *c, + } + + static void bdrv_default_perms_for_cow(BlockDriverState *bs, BdrvChild *c, +- const BdrvChildClass *child_class, + BdrvChildRole role, + BlockReopenQueue *reopen_queue, + uint64_t perm, uint64_t shared, + uint64_t *nperm, uint64_t *nshared) + { +- assert(child_class == &child_of_bds && (role & BDRV_CHILD_COW)); ++ assert(role & BDRV_CHILD_COW); + + /* + * We want consistent read from backing files if the parent needs it. +@@ -2402,7 +2400,6 @@ static void bdrv_default_perms_for_cow(BlockDriverState *bs, BdrvChild *c, + } + + static void bdrv_default_perms_for_storage(BlockDriverState *bs, BdrvChild *c, +- const BdrvChildClass *child_class, + BdrvChildRole role, + BlockReopenQueue *reopen_queue, + uint64_t perm, uint64_t shared, +@@ -2410,8 +2407,7 @@ static void bdrv_default_perms_for_storage(BlockDriverState *bs, BdrvChild *c, + { + int flags; + +- assert(child_class == &child_of_bds && +- (role & (BDRV_CHILD_METADATA | BDRV_CHILD_DATA))); ++ assert(role & (BDRV_CHILD_METADATA | BDRV_CHILD_DATA)); + + flags = bdrv_reopen_get_flags(reopen_queue, bs); + +@@ -2419,7 +2415,7 @@ static void bdrv_default_perms_for_storage(BlockDriverState *bs, BdrvChild *c, + * Apart from the modifications below, the same permissions are + * forwarded and left alone as for filters + */ +- bdrv_filter_default_perms(bs, c, child_class, role, reopen_queue, ++ bdrv_filter_default_perms(bs, c, role, reopen_queue, + perm, shared, &perm, &shared); + + if (role & BDRV_CHILD_METADATA) { +@@ -2483,24 +2479,21 @@ static void bdrv_default_perms_for_storage(BlockDriverState *bs, BdrvChild *c, + } + + void bdrv_default_perms(BlockDriverState *bs, BdrvChild *c, +- const BdrvChildClass *child_class, BdrvChildRole role, +- BlockReopenQueue *reopen_queue, ++ BdrvChildRole role, BlockReopenQueue *reopen_queue, + uint64_t perm, uint64_t shared, + uint64_t *nperm, uint64_t *nshared) + { +- assert(child_class == &child_of_bds); +- + if (role & BDRV_CHILD_FILTERED) { + assert(!(role & (BDRV_CHILD_DATA | BDRV_CHILD_METADATA | + BDRV_CHILD_COW))); +- bdrv_filter_default_perms(bs, c, child_class, role, reopen_queue, ++ bdrv_filter_default_perms(bs, c, role, reopen_queue, + perm, shared, nperm, nshared); + } else if (role & BDRV_CHILD_COW) { + assert(!(role & (BDRV_CHILD_DATA | BDRV_CHILD_METADATA))); +- bdrv_default_perms_for_cow(bs, c, child_class, role, reopen_queue, ++ bdrv_default_perms_for_cow(bs, c, role, reopen_queue, + perm, shared, nperm, nshared); + } else if (role & (BDRV_CHILD_METADATA | BDRV_CHILD_DATA)) { +- bdrv_default_perms_for_storage(bs, c, child_class, role, reopen_queue, ++ bdrv_default_perms_for_storage(bs, c, role, reopen_queue, + perm, shared, nperm, nshared); + } else { + g_assert_not_reached(); +@@ -2744,7 +2737,7 @@ BdrvChild *bdrv_attach_child(BlockDriverState *parent_bs, + bdrv_get_cumulative_perm(parent_bs, &perm, &shared_perm); + + assert(parent_bs->drv); +- bdrv_child_perm(parent_bs, child_bs, NULL, child_class, child_role, NULL, ++ bdrv_child_perm(parent_bs, child_bs, NULL, child_role, NULL, + perm, shared_perm, &perm, &shared_perm); + + child = bdrv_root_attach_child(child_bs, child_name, child_class, +@@ -3807,7 +3800,7 @@ int bdrv_reopen_multiple(BlockReopenQueue *bs_queue, Error **errp) + if (state->replace_backing_bs && state->new_backing_bs) { + uint64_t nperm, nshared; + bdrv_child_perm(state->bs, state->new_backing_bs, +- NULL, &child_of_bds, bdrv_backing_role(state->bs), ++ NULL, bdrv_backing_role(state->bs), + bs_queue, state->perm, state->shared_perm, + &nperm, &nshared); + ret = bdrv_check_update_perm(state->new_backing_bs, NULL, +@@ -3930,7 +3923,7 @@ static void bdrv_reopen_perm(BlockReopenQueue *q, BlockDriverState *bs, + } else { + uint64_t nperm, nshared; + +- bdrv_child_perm(parent->state.bs, bs, c, c->klass, c->role, q, ++ bdrv_child_perm(parent->state.bs, bs, c, c->role, q, + parent->state.perm, parent->state.shared_perm, + &nperm, &nshared); + +diff --git a/block/backup-top.c b/block/backup-top.c +index f0efec18b5..af2f20f346 100644 +--- a/block/backup-top.c ++++ b/block/backup-top.c +@@ -122,7 +122,6 @@ static void backup_top_refresh_filename(BlockDriverState *bs) + } + + static void backup_top_child_perm(BlockDriverState *bs, BdrvChild *c, +- const BdrvChildClass *child_class, + BdrvChildRole role, + BlockReopenQueue *reopen_queue, + uint64_t perm, uint64_t shared, +@@ -156,7 +155,7 @@ static void backup_top_child_perm(BlockDriverState *bs, BdrvChild *c, + *nperm = BLK_PERM_WRITE; + } else { + /* Source child */ +- bdrv_default_perms(bs, c, child_class, role, reopen_queue, ++ bdrv_default_perms(bs, c, role, reopen_queue, + perm, shared, nperm, nshared); + + if (perm & BLK_PERM_WRITE) { +diff --git a/block/blkdebug.c b/block/blkdebug.c +index a925d8295e..7194bc7f06 100644 +--- a/block/blkdebug.c ++++ b/block/blkdebug.c +@@ -995,7 +995,6 @@ static int blkdebug_reopen_prepare(BDRVReopenState *reopen_state, + } + + static void blkdebug_child_perm(BlockDriverState *bs, BdrvChild *c, +- const BdrvChildClass *child_class, + BdrvChildRole role, + BlockReopenQueue *reopen_queue, + uint64_t perm, uint64_t shared, +@@ -1003,7 +1002,7 @@ static void blkdebug_child_perm(BlockDriverState *bs, BdrvChild *c, + { + BDRVBlkdebugState *s = bs->opaque; + +- bdrv_default_perms(bs, c, child_class, role, reopen_queue, ++ bdrv_default_perms(bs, c, role, reopen_queue, + perm, shared, nperm, nshared); + + *nperm |= s->take_child_perms; +diff --git a/block/blklogwrites.c b/block/blklogwrites.c +index 8684fb1c74..6753bd9a3e 100644 +--- a/block/blklogwrites.c ++++ b/block/blklogwrites.c +@@ -283,7 +283,6 @@ static int64_t blk_log_writes_getlength(BlockDriverState *bs) + } + + static void blk_log_writes_child_perm(BlockDriverState *bs, BdrvChild *c, +- const BdrvChildClass *child_class, + BdrvChildRole role, + BlockReopenQueue *ro_q, + uint64_t perm, uint64_t shrd, +@@ -295,7 +294,7 @@ static void blk_log_writes_child_perm(BlockDriverState *bs, BdrvChild *c, + return; + } + +- bdrv_default_perms(bs, c, child_class, role, ro_q, perm, shrd, ++ bdrv_default_perms(bs, c, role, ro_q, perm, shrd, + nperm, nshrd); + } + +diff --git a/block/commit.c b/block/commit.c +index 6af1c808bc..7732d02dfe 100644 +--- a/block/commit.c ++++ b/block/commit.c +@@ -223,7 +223,6 @@ static void bdrv_commit_top_refresh_filename(BlockDriverState *bs) + } + + static void bdrv_commit_top_child_perm(BlockDriverState *bs, BdrvChild *c, +- const BdrvChildClass *child_class, + BdrvChildRole role, + BlockReopenQueue *reopen_queue, + uint64_t perm, uint64_t shared, +diff --git a/block/copy-on-read.c b/block/copy-on-read.c +index c857ea0da7..a6e3c74a68 100644 +--- a/block/copy-on-read.c ++++ b/block/copy-on-read.c +@@ -52,7 +52,6 @@ static int cor_open(BlockDriverState *bs, QDict *options, int flags, + #define PERM_UNCHANGED (BLK_PERM_ALL & ~PERM_PASSTHROUGH) + + static void cor_child_perm(BlockDriverState *bs, BdrvChild *c, +- const BdrvChildClass *child_class, + BdrvChildRole role, + BlockReopenQueue *reopen_queue, + uint64_t perm, uint64_t shared, +diff --git a/block/mirror.c b/block/mirror.c +index cb4bdad32a..e8e8844afc 100644 +--- a/block/mirror.c ++++ b/block/mirror.c +@@ -1492,7 +1492,6 @@ static void bdrv_mirror_top_refresh_filename(BlockDriverState *bs) + } + + static void bdrv_mirror_top_child_perm(BlockDriverState *bs, BdrvChild *c, +- const BdrvChildClass *child_class, + BdrvChildRole role, + BlockReopenQueue *reopen_queue, + uint64_t perm, uint64_t shared, +diff --git a/block/quorum.c b/block/quorum.c +index 616ac3a927..7cf7ab1546 100644 +--- a/block/quorum.c ++++ b/block/quorum.c +@@ -1153,7 +1153,6 @@ static char *quorum_dirname(BlockDriverState *bs, Error **errp) + } + + static void quorum_child_perm(BlockDriverState *bs, BdrvChild *c, +- const BdrvChildClass *child_class, + BdrvChildRole role, + BlockReopenQueue *reopen_queue, + uint64_t perm, uint64_t shared, +diff --git a/block/replication.c b/block/replication.c +index cc9c473ad1..ccf7b78160 100644 +--- a/block/replication.c ++++ b/block/replication.c +@@ -164,7 +164,6 @@ static void replication_close(BlockDriverState *bs) + } + + static void replication_child_perm(BlockDriverState *bs, BdrvChild *c, +- const BdrvChildClass *child_class, + BdrvChildRole role, + BlockReopenQueue *reopen_queue, + uint64_t perm, uint64_t shared, +diff --git a/block/vvfat.c b/block/vvfat.c +index 089abe1e29..c65a98e3ee 100644 +--- a/block/vvfat.c ++++ b/block/vvfat.c +@@ -3213,7 +3213,6 @@ err: + } + + static void vvfat_child_perm(BlockDriverState *bs, BdrvChild *c, +- const BdrvChildClass *child_class, + BdrvChildRole role, + BlockReopenQueue *reopen_queue, + uint64_t perm, uint64_t shared, +@@ -3221,8 +3220,7 @@ static void vvfat_child_perm(BlockDriverState *bs, BdrvChild *c, + { + BDRVVVFATState *s = bs->opaque; + +- assert(c == s->qcow || +- (child_class == &child_of_bds && (role & BDRV_CHILD_COW))); ++ assert(c == s->qcow || (role & BDRV_CHILD_COW)); + + if (c == s->qcow) { + /* This is a private node, nobody should try to attach to it */ +diff --git a/include/block/block_int.h b/include/block/block_int.h +index 7fbe3206b4..5e4f4c348c 100644 +--- a/include/block/block_int.h ++++ b/include/block/block_int.h +@@ -563,7 +563,6 @@ struct BlockDriver { + * @reopen_queue. + */ + void (*bdrv_child_perm)(BlockDriverState *bs, BdrvChild *c, +- const BdrvChildClass *child_class, + BdrvChildRole role, + BlockReopenQueue *reopen_queue, + uint64_t parent_perm, uint64_t parent_shared, +@@ -1270,8 +1269,7 @@ bool bdrv_recurse_can_replace(BlockDriverState *bs, + * child_of_bds child class and set an appropriate BdrvChildRole. + */ + void bdrv_default_perms(BlockDriverState *bs, BdrvChild *c, +- const BdrvChildClass *child_class, BdrvChildRole role, +- BlockReopenQueue *reopen_queue, ++ BdrvChildRole role, BlockReopenQueue *reopen_queue, + uint64_t perm, uint64_t shared, + uint64_t *nperm, uint64_t *nshared); + +diff --git a/tests/test-bdrv-drain.c b/tests/test-bdrv-drain.c +index 655fd0d085..1107271840 100644 +--- a/tests/test-bdrv-drain.c ++++ b/tests/test-bdrv-drain.c +@@ -85,23 +85,6 @@ static int coroutine_fn bdrv_test_co_preadv(BlockDriverState *bs, + return 0; + } + +-static void bdrv_test_child_perm(BlockDriverState *bs, BdrvChild *c, +- const BdrvChildClass *child_class, +- BdrvChildRole role, +- BlockReopenQueue *reopen_queue, +- uint64_t perm, uint64_t shared, +- uint64_t *nperm, uint64_t *nshared) +-{ +- /* +- * bdrv_default_perms() accepts nothing else, so disguise +- * detach_by_driver_cb_parent. +- */ +- child_class = &child_of_bds; +- +- bdrv_default_perms(bs, c, child_class, role, reopen_queue, +- perm, shared, nperm, nshared); +-} +- + static int bdrv_test_change_backing_file(BlockDriverState *bs, + const char *backing_file, + const char *backing_fmt) +@@ -119,7 +102,7 @@ static BlockDriver bdrv_test = { + .bdrv_co_drain_begin = bdrv_test_co_drain_begin, + .bdrv_co_drain_end = bdrv_test_co_drain_end, + +- .bdrv_child_perm = bdrv_test_child_perm, ++ .bdrv_child_perm = bdrv_default_perms, + + .bdrv_change_backing_file = bdrv_test_change_backing_file, + }; +diff --git a/tests/test-bdrv-graph-mod.c b/tests/test-bdrv-graph-mod.c +index a2d0318b16..f93f3168b0 100644 +--- a/tests/test-bdrv-graph-mod.c ++++ b/tests/test-bdrv-graph-mod.c +@@ -30,7 +30,6 @@ static BlockDriver bdrv_pass_through = { + }; + + static void no_perm_default_perms(BlockDriverState *bs, BdrvChild *c, +- const BdrvChildClass *child_class, + BdrvChildRole role, + BlockReopenQueue *reopen_queue, + uint64_t perm, uint64_t shared, +-- +2.23.0 + diff --git a/block-Drop-child_file.patch b/block-Drop-child_file.patch new file mode 100644 index 0000000000000000000000000000000000000000..100a7ff1dd17430e0fd5a044fdbd4f33178e768d --- /dev/null +++ b/block-Drop-child_file.patch @@ -0,0 +1,114 @@ +From f6de853fa3d76b4b92032dc6cdc06bedacbf9466 Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Wed, 13 May 2020 13:05:42 +0200 +Subject: [PATCH 564/709] block: Drop child_file + +Signed-off-by: Max Reitz +Message-Id: <20200513110544.176672-33-mreitz@redhat.com> +Reviewed-by: Eric Blake +Signed-off-by: Kevin Wolf +--- + block.c | 39 ++------------------------------------- + include/block/block_int.h | 1 - + tests/test-bdrv-drain.c | 8 +++----- + 3 files changed, 5 insertions(+), 43 deletions(-) + +diff --git a/block.c b/block.c +index e79fe6e07e..6a24b23d51 100644 +--- a/block.c ++++ b/block.c +@@ -80,13 +80,6 @@ static BlockDriverState *bdrv_open_inherit(const char *filename, + BdrvChildRole child_role, + Error **errp); + +-/* TODO: Remove when no longer needed */ +-static void bdrv_inherited_options(BdrvChildRole role, bool parent_is_format, +- int *child_flags, QDict *child_options, +- int parent_flags, QDict *parent_options); +-static void bdrv_child_cb_attach(BdrvChild *child); +-static void bdrv_child_cb_detach(BdrvChild *child); +- + /* If non-zero, use only whitelisted block drivers */ + static int use_bdrv_whitelist; + +@@ -1145,33 +1138,6 @@ static void bdrv_temp_snapshot_options(int *child_flags, QDict *child_options, + *child_flags &= ~BDRV_O_NATIVE_AIO; + } + +-/* +- * Returns the options and flags that bs->file should get if a protocol driver +- * is expected, based on the given options and flags for the parent BDS +- */ +-static void bdrv_protocol_options(BdrvChildRole role, bool parent_is_format, +- int *child_flags, QDict *child_options, +- int parent_flags, QDict *parent_options) +-{ +- bdrv_inherited_options(BDRV_CHILD_IMAGE, true, +- child_flags, child_options, +- parent_flags, parent_options); +-} +- +-const BdrvChildClass child_file = { +- .parent_is_bds = true, +- .get_parent_desc = bdrv_child_get_parent_desc, +- .inherit_options = bdrv_protocol_options, +- .drained_begin = bdrv_child_cb_drained_begin, +- .drained_poll = bdrv_child_cb_drained_poll, +- .drained_end = bdrv_child_cb_drained_end, +- .attach = bdrv_child_cb_attach, +- .detach = bdrv_child_cb_detach, +- .inactivate = bdrv_child_cb_inactivate, +- .can_set_aio_ctx = bdrv_child_cb_can_set_aio_ctx, +- .set_aio_ctx = bdrv_child_cb_set_aio_ctx, +-}; +- + static void bdrv_backing_attach(BdrvChild *c) + { + BlockDriverState *parent = c->opaque; +@@ -2444,9 +2410,8 @@ static void bdrv_default_perms_for_storage(BlockDriverState *bs, BdrvChild *c, + { + int flags; + +- assert(child_class == &child_file || +- (child_class == &child_of_bds && +- (role & (BDRV_CHILD_METADATA | BDRV_CHILD_DATA)))); ++ assert(child_class == &child_of_bds && ++ (role & (BDRV_CHILD_METADATA | BDRV_CHILD_DATA))); + + flags = bdrv_reopen_get_flags(reopen_queue, bs); + +diff --git a/include/block/block_int.h b/include/block/block_int.h +index e791c40496..7fbe3206b4 100644 +--- a/include/block/block_int.h ++++ b/include/block/block_int.h +@@ -741,7 +741,6 @@ struct BdrvChildClass { + }; + + extern const BdrvChildClass child_of_bds; +-extern const BdrvChildClass child_file; + + struct BdrvChild { + BlockDriverState *bs; +diff --git a/tests/test-bdrv-drain.c b/tests/test-bdrv-drain.c +index 0da5a3a6a1..655fd0d085 100644 +--- a/tests/test-bdrv-drain.c ++++ b/tests/test-bdrv-drain.c +@@ -93,12 +93,10 @@ static void bdrv_test_child_perm(BlockDriverState *bs, BdrvChild *c, + uint64_t *nperm, uint64_t *nshared) + { + /* +- * bdrv_default_perms() accepts only these two, so disguise +- * detach_by_driver_cb_parent as one of them. ++ * bdrv_default_perms() accepts nothing else, so disguise ++ * detach_by_driver_cb_parent. + */ +- if (child_class != &child_file && child_class != &child_of_bds) { +- child_class = &child_of_bds; +- } ++ child_class = &child_of_bds; + + bdrv_default_perms(bs, c, child_class, role, reopen_queue, + perm, shared, nperm, nshared); +-- +2.23.0 + diff --git a/block-Drop-child_format.patch b/block-Drop-child_format.patch new file mode 100644 index 0000000000000000000000000000000000000000..6414b7650d90c926fd8776d0d8aadb47f2b398e8 --- /dev/null +++ b/block-Drop-child_format.patch @@ -0,0 +1,69 @@ +From f34ade114818c5a011a743ebd899c91b9ebbe040 Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Wed, 13 May 2020 13:05:32 +0200 +Subject: [PATCH 554/709] block: Drop child_format + +Signed-off-by: Max Reitz +Reviewed-by: Eric Blake +Message-Id: <20200513110544.176672-23-mreitz@redhat.com> +Signed-off-by: Kevin Wolf +--- + block.c | 29 ----------------------------- + include/block/block_int.h | 1 - + 2 files changed, 30 deletions(-) + +diff --git a/block.c b/block.c +index 088727fdbe..85b4f947ba 100644 +--- a/block.c ++++ b/block.c +@@ -1172,35 +1172,6 @@ const BdrvChildClass child_file = { + .set_aio_ctx = bdrv_child_cb_set_aio_ctx, + }; + +-/* +- * Returns the options and flags that bs->file should get if the use of formats +- * (and not only protocols) is permitted for it, based on the given options and +- * flags for the parent BDS +- */ +-static void bdrv_inherited_fmt_options(BdrvChildRole role, +- bool parent_is_format, +- int *child_flags, QDict *child_options, +- int parent_flags, QDict *parent_options) +-{ +- bdrv_inherited_options(BDRV_CHILD_DATA, false, +- child_flags, child_options, +- parent_flags, parent_options); +-} +- +-const BdrvChildClass child_format = { +- .parent_is_bds = true, +- .get_parent_desc = bdrv_child_get_parent_desc, +- .inherit_options = bdrv_inherited_fmt_options, +- .drained_begin = bdrv_child_cb_drained_begin, +- .drained_poll = bdrv_child_cb_drained_poll, +- .drained_end = bdrv_child_cb_drained_end, +- .attach = bdrv_child_cb_attach, +- .detach = bdrv_child_cb_detach, +- .inactivate = bdrv_child_cb_inactivate, +- .can_set_aio_ctx = bdrv_child_cb_can_set_aio_ctx, +- .set_aio_ctx = bdrv_child_cb_set_aio_ctx, +-}; +- + static void bdrv_backing_attach(BdrvChild *c) + { + BlockDriverState *parent = c->opaque; +diff --git a/include/block/block_int.h b/include/block/block_int.h +index 3a9dda9be7..4b09fa1124 100644 +--- a/include/block/block_int.h ++++ b/include/block/block_int.h +@@ -742,7 +742,6 @@ struct BdrvChildClass { + + extern const BdrvChildClass child_of_bds; + extern const BdrvChildClass child_file; +-extern const BdrvChildClass child_format; + extern const BdrvChildClass child_backing; + + struct BdrvChild { +-- +2.23.0 + diff --git a/block-Drop-unused-.bdrv_has_zero_init_truncate.patch b/block-Drop-unused-.bdrv_has_zero_init_truncate.patch new file mode 100644 index 0000000000000000000000000000000000000000..84d1f4c971ee7c172ee831ca91693948e445c071 --- /dev/null +++ b/block-Drop-unused-.bdrv_has_zero_init_truncate.patch @@ -0,0 +1,239 @@ +From 47e0b38a13935cb666f88964c3096654092f42d6 Mon Sep 17 00:00:00 2001 +From: Eric Blake +Date: Tue, 28 Apr 2020 15:29:05 -0500 +Subject: [PATCH 357/709] block: Drop unused .bdrv_has_zero_init_truncate + +Now that there are no clients of bdrv_has_zero_init_truncate, none of +the drivers need to worry about providing it. + +What's more, this eliminates a source of some confusion: a literal +reading of the documentation as written in ceaca56f and implemented in +commit 1dcaf527 claims that a driver which returns 0 for +bdrv_has_zero_init_truncate() must not return 1 for +bdrv_has_zero_init(); this condition was violated for parallels, qcow, +and sometimes for vdi, although in practice it did not matter since +those drivers also lacked .bdrv_co_truncate. + +Signed-off-by: Eric Blake +Message-Id: <20200428202905.770727-10-eblake@redhat.com> +Acked-by: Richard W.M. Jones +Signed-off-by: Kevin Wolf +--- + block.c | 21 --------------------- + block/file-posix.c | 1 - + block/file-win32.c | 1 - + block/nfs.c | 1 - + block/qcow2.c | 1 - + block/qed.c | 1 - + block/raw-format.c | 6 ------ + block/rbd.c | 1 - + block/sheepdog.c | 3 --- + block/ssh.c | 1 - + include/block/block.h | 1 - + include/block/block_int.h | 7 ------- + 12 files changed, 45 deletions(-) + +diff --git a/block.c b/block.c +index cf5c19b1db..0653ccb913 100644 +--- a/block.c ++++ b/block.c +@@ -5284,27 +5284,6 @@ int bdrv_has_zero_init(BlockDriverState *bs) + return 0; + } + +-int bdrv_has_zero_init_truncate(BlockDriverState *bs) +-{ +- if (!bs->drv) { +- return 0; +- } +- +- if (bs->backing) { +- /* Depends on the backing image length, but better safe than sorry */ +- return 0; +- } +- if (bs->drv->bdrv_has_zero_init_truncate) { +- return bs->drv->bdrv_has_zero_init_truncate(bs); +- } +- if (bs->file && bs->drv->is_filter) { +- return bdrv_has_zero_init_truncate(bs->file->bs); +- } +- +- /* safe default */ +- return 0; +-} +- + bool bdrv_unallocated_blocks_are_zero(BlockDriverState *bs) + { + BlockDriverInfo bdi; +diff --git a/block/file-posix.c b/block/file-posix.c +index 05e094be29..3ab8f5a0fa 100644 +--- a/block/file-posix.c ++++ b/block/file-posix.c +@@ -3100,7 +3100,6 @@ BlockDriver bdrv_file = { + .bdrv_co_create = raw_co_create, + .bdrv_co_create_opts = raw_co_create_opts, + .bdrv_has_zero_init = bdrv_has_zero_init_1, +- .bdrv_has_zero_init_truncate = bdrv_has_zero_init_1, + .bdrv_co_block_status = raw_co_block_status, + .bdrv_co_invalidate_cache = raw_co_invalidate_cache, + .bdrv_co_pwrite_zeroes = raw_co_pwrite_zeroes, +diff --git a/block/file-win32.c b/block/file-win32.c +index fa569685d8..221aaf713e 100644 +--- a/block/file-win32.c ++++ b/block/file-win32.c +@@ -641,7 +641,6 @@ BlockDriver bdrv_file = { + .bdrv_close = raw_close, + .bdrv_co_create_opts = raw_co_create_opts, + .bdrv_has_zero_init = bdrv_has_zero_init_1, +- .bdrv_has_zero_init_truncate = bdrv_has_zero_init_1, + + .bdrv_aio_preadv = raw_aio_preadv, + .bdrv_aio_pwritev = raw_aio_pwritev, +diff --git a/block/nfs.c b/block/nfs.c +index 76daa7c9f6..b1718d125a 100644 +--- a/block/nfs.c ++++ b/block/nfs.c +@@ -872,7 +872,6 @@ static BlockDriver bdrv_nfs = { + .create_opts = &nfs_create_opts, + + .bdrv_has_zero_init = nfs_has_zero_init, +- .bdrv_has_zero_init_truncate = nfs_has_zero_init, + .bdrv_get_allocated_file_size = nfs_get_allocated_file_size, + .bdrv_co_truncate = nfs_file_co_truncate, + +diff --git a/block/qcow2.c b/block/qcow2.c +index 11903fb547..1ad95ff048 100644 +--- a/block/qcow2.c ++++ b/block/qcow2.c +@@ -5621,7 +5621,6 @@ BlockDriver bdrv_qcow2 = { + .bdrv_co_create_opts = qcow2_co_create_opts, + .bdrv_co_create = qcow2_co_create, + .bdrv_has_zero_init = qcow2_has_zero_init, +- .bdrv_has_zero_init_truncate = bdrv_has_zero_init_1, + .bdrv_co_block_status = qcow2_co_block_status, + + .bdrv_co_preadv_part = qcow2_co_preadv_part, +diff --git a/block/qed.c b/block/qed.c +index fb609cfba1..5da9726518 100644 +--- a/block/qed.c ++++ b/block/qed.c +@@ -1675,7 +1675,6 @@ static BlockDriver bdrv_qed = { + .bdrv_co_create = bdrv_qed_co_create, + .bdrv_co_create_opts = bdrv_qed_co_create_opts, + .bdrv_has_zero_init = bdrv_has_zero_init_1, +- .bdrv_has_zero_init_truncate = bdrv_has_zero_init_1, + .bdrv_co_block_status = bdrv_qed_co_block_status, + .bdrv_co_readv = bdrv_qed_co_readv, + .bdrv_co_writev = bdrv_qed_co_writev, +diff --git a/block/raw-format.c b/block/raw-format.c +index 351f2d91c6..9108e43696 100644 +--- a/block/raw-format.c ++++ b/block/raw-format.c +@@ -414,11 +414,6 @@ static int raw_has_zero_init(BlockDriverState *bs) + return bdrv_has_zero_init(bs->file->bs); + } + +-static int raw_has_zero_init_truncate(BlockDriverState *bs) +-{ +- return bdrv_has_zero_init_truncate(bs->file->bs); +-} +- + static int coroutine_fn raw_co_create_opts(BlockDriver *drv, + const char *filename, + QemuOpts *opts, +@@ -582,7 +577,6 @@ BlockDriver bdrv_raw = { + .bdrv_co_ioctl = &raw_co_ioctl, + .create_opts = &raw_create_opts, + .bdrv_has_zero_init = &raw_has_zero_init, +- .bdrv_has_zero_init_truncate = &raw_has_zero_init_truncate, + .strong_runtime_opts = raw_strong_runtime_opts, + .mutable_opts = mutable_opts, + }; +diff --git a/block/rbd.c b/block/rbd.c +index 331c45adb2..617553b022 100644 +--- a/block/rbd.c ++++ b/block/rbd.c +@@ -1313,7 +1313,6 @@ static BlockDriver bdrv_rbd = { + .bdrv_co_create = qemu_rbd_co_create, + .bdrv_co_create_opts = qemu_rbd_co_create_opts, + .bdrv_has_zero_init = bdrv_has_zero_init_1, +- .bdrv_has_zero_init_truncate = bdrv_has_zero_init_1, + .bdrv_get_info = qemu_rbd_getinfo, + .create_opts = &qemu_rbd_create_opts, + .bdrv_getlength = qemu_rbd_getlength, +diff --git a/block/sheepdog.c b/block/sheepdog.c +index 739e6dee30..27a30d17f4 100644 +--- a/block/sheepdog.c ++++ b/block/sheepdog.c +@@ -3226,7 +3226,6 @@ static BlockDriver bdrv_sheepdog = { + .bdrv_co_create = sd_co_create, + .bdrv_co_create_opts = sd_co_create_opts, + .bdrv_has_zero_init = bdrv_has_zero_init_1, +- .bdrv_has_zero_init_truncate = bdrv_has_zero_init_1, + .bdrv_getlength = sd_getlength, + .bdrv_get_allocated_file_size = sd_get_allocated_file_size, + .bdrv_co_truncate = sd_co_truncate, +@@ -3265,7 +3264,6 @@ static BlockDriver bdrv_sheepdog_tcp = { + .bdrv_co_create = sd_co_create, + .bdrv_co_create_opts = sd_co_create_opts, + .bdrv_has_zero_init = bdrv_has_zero_init_1, +- .bdrv_has_zero_init_truncate = bdrv_has_zero_init_1, + .bdrv_getlength = sd_getlength, + .bdrv_get_allocated_file_size = sd_get_allocated_file_size, + .bdrv_co_truncate = sd_co_truncate, +@@ -3304,7 +3302,6 @@ static BlockDriver bdrv_sheepdog_unix = { + .bdrv_co_create = sd_co_create, + .bdrv_co_create_opts = sd_co_create_opts, + .bdrv_has_zero_init = bdrv_has_zero_init_1, +- .bdrv_has_zero_init_truncate = bdrv_has_zero_init_1, + .bdrv_getlength = sd_getlength, + .bdrv_get_allocated_file_size = sd_get_allocated_file_size, + .bdrv_co_truncate = sd_co_truncate, +diff --git a/block/ssh.c b/block/ssh.c +index f9e08a4900..098dbe03c1 100644 +--- a/block/ssh.c ++++ b/block/ssh.c +@@ -1397,7 +1397,6 @@ static BlockDriver bdrv_ssh = { + .bdrv_co_create_opts = ssh_co_create_opts, + .bdrv_close = ssh_close, + .bdrv_has_zero_init = ssh_has_zero_init, +- .bdrv_has_zero_init_truncate = ssh_has_zero_init, + .bdrv_co_readv = ssh_co_readv, + .bdrv_co_writev = ssh_co_writev, + .bdrv_getlength = ssh_getlength, +diff --git a/include/block/block.h b/include/block/block.h +index 8b62429aa4..4de8d8f8a6 100644 +--- a/include/block/block.h ++++ b/include/block/block.h +@@ -430,7 +430,6 @@ int bdrv_pdiscard(BdrvChild *child, int64_t offset, int64_t bytes); + int bdrv_co_pdiscard(BdrvChild *child, int64_t offset, int64_t bytes); + int bdrv_has_zero_init_1(BlockDriverState *bs); + int bdrv_has_zero_init(BlockDriverState *bs); +-int bdrv_has_zero_init_truncate(BlockDriverState *bs); + bool bdrv_unallocated_blocks_are_zero(BlockDriverState *bs); + bool bdrv_can_write_zeroes_with_unmap(BlockDriverState *bs); + int bdrv_block_status(BlockDriverState *bs, int64_t offset, +diff --git a/include/block/block_int.h b/include/block/block_int.h +index 92335f33c7..df6d0273d6 100644 +--- a/include/block/block_int.h ++++ b/include/block/block_int.h +@@ -449,16 +449,9 @@ struct BlockDriver { + /* + * Returns 1 if newly created images are guaranteed to contain only + * zeros, 0 otherwise. +- * Must return 0 if .bdrv_has_zero_init_truncate() returns 0. + */ + int (*bdrv_has_zero_init)(BlockDriverState *bs); + +- /* +- * Returns 1 if new areas added by growing the image with +- * PREALLOC_MODE_OFF contain only zeros, 0 otherwise. +- */ +- int (*bdrv_has_zero_init_truncate)(BlockDriverState *bs); +- + /* Remove fd handlers, timers, and other event loop callbacks so the event + * loop is no longer in use. Called with no in-flight requests and in + * depth-first traversal order with parents before child nodes. +-- +2.23.0 + diff --git a/block-Fix-AioContext-switch-for-bs-drv-NULL.patch b/block-Fix-AioContext-switch-for-bs-drv-NULL.patch deleted file mode 100644 index c1702d0287be4703ac46104d1d7acf28cb37cd47..0000000000000000000000000000000000000000 --- a/block-Fix-AioContext-switch-for-bs-drv-NULL.patch +++ /dev/null @@ -1,107 +0,0 @@ -From 1bffe1ae7a7b707c3a14ea2ccd00d3609d3ce4d8 Mon Sep 17 00:00:00 2001 -From: Kevin Wolf -Date: Wed, 17 Apr 2019 17:15:25 +0200 -Subject: [PATCH] block: Fix AioContext switch for bs->drv == NULL - -Even for block nodes with bs->drv == NULL, we can't just ignore a -bdrv_set_aio_context() call. Leaving the node in its old context can -mean that it's still in an iothread context in bdrv_close_all() during -shutdown, resulting in an attempted unlock of the AioContext lock which -we don't hold. - -This is an example stack trace of a related crash: - - #0 0x00007ffff59da57f in raise () at /lib64/libc.so.6 - #1 0x00007ffff59c4895 in abort () at /lib64/libc.so.6 - #2 0x0000555555b97b1e in error_exit (err=, msg=msg@entry=0x555555d386d0 <__func__.19059> "qemu_mutex_unlock_impl") at util/qemu-thread-posix.c:36 - #3 0x0000555555b97f7f in qemu_mutex_unlock_impl (mutex=mutex@entry=0x5555568002f0, file=file@entry=0x555555d378df "util/async.c", line=line@entry=507) at util/qemu-thread-posix.c:97 - #4 0x0000555555b92f55 in aio_context_release (ctx=ctx@entry=0x555556800290) at util/async.c:507 - #5 0x0000555555b05cf8 in bdrv_prwv_co (child=child@entry=0x7fffc80012f0, offset=offset@entry=131072, qiov=qiov@entry=0x7fffffffd4f0, is_write=is_write@entry=true, flags=flags@entry=0) - at block/io.c:833 - #6 0x0000555555b060a9 in bdrv_pwritev (qiov=0x7fffffffd4f0, offset=131072, child=0x7fffc80012f0) at block/io.c:990 - #7 0x0000555555b060a9 in bdrv_pwrite (child=0x7fffc80012f0, offset=131072, buf=, bytes=) at block/io.c:990 - #8 0x0000555555ae172b in qcow2_cache_entry_flush (bs=bs@entry=0x555556810680, c=c@entry=0x5555568cc740, i=i@entry=0) at block/qcow2-cache.c:51 - #9 0x0000555555ae18dd in qcow2_cache_write (bs=bs@entry=0x555556810680, c=0x5555568cc740) at block/qcow2-cache.c:248 - #10 0x0000555555ae15de in qcow2_cache_flush (bs=0x555556810680, c=) at block/qcow2-cache.c:259 - #11 0x0000555555ae16b1 in qcow2_cache_flush_dependency (c=0x5555568a1700, c=0x5555568a1700, bs=0x555556810680) at block/qcow2-cache.c:194 - #12 0x0000555555ae16b1 in qcow2_cache_entry_flush (bs=bs@entry=0x555556810680, c=c@entry=0x5555568a1700, i=i@entry=0) at block/qcow2-cache.c:194 - #13 0x0000555555ae18dd in qcow2_cache_write (bs=bs@entry=0x555556810680, c=0x5555568a1700) at block/qcow2-cache.c:248 - #14 0x0000555555ae15de in qcow2_cache_flush (bs=bs@entry=0x555556810680, c=) at block/qcow2-cache.c:259 - #15 0x0000555555ad242c in qcow2_inactivate (bs=bs@entry=0x555556810680) at block/qcow2.c:2124 - #16 0x0000555555ad2590 in qcow2_close (bs=0x555556810680) at block/qcow2.c:2153 - #17 0x0000555555ab0c62 in bdrv_close (bs=0x555556810680) at block.c:3358 - #18 0x0000555555ab0c62 in bdrv_delete (bs=0x555556810680) at block.c:3542 - #19 0x0000555555ab0c62 in bdrv_unref (bs=0x555556810680) at block.c:4598 - #20 0x0000555555af4d72 in blk_remove_bs (blk=blk@entry=0x5555568103d0) at block/block-backend.c:785 - #21 0x0000555555af4dbb in blk_remove_all_bs () at block/block-backend.c:483 - #22 0x0000555555aae02f in bdrv_close_all () at block.c:3412 - #23 0x00005555557f9796 in main (argc=, argv=, envp=) at vl.c:4776 - -The reproducer I used is a qcow2 image on gluster volume, where the -virtual disk size (4 GB) is larger than the gluster volume size (64M), -so we can easily trigger an ENOSPC. This backend is assigned to a -virtio-blk device using an iothread, and then from the guest a -'dd if=/dev/zero of=/dev/vda bs=1G count=1' causes the VM to stop -because of an I/O error. qemu_gluster_co_flush_to_disk() sets -bs->drv = NULL on error, so when virtio-blk stops the dataplane, the -block nodes stay in the iothread AioContext. A 'quit' monitor command -issued from this paused state crashes the process. - -Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1631227 -Cc: qemu-stable@nongnu.org -Signed-off-by: Kevin Wolf -Reviewed-by: Eric Blake -Reviewed-by: Max Reitz -Reviewed-by: Stefano Garzarella -(cherry-picked from commit 1bffe1ae7a7b707c3a14ea2ccd00d3609d3ce4d8) ---- - block.c | 12 ++---------- - 1 file changed, 2 insertions(+), 10 deletions(-) - -diff --git a/block.c b/block.c -index 16615bc876..9ae5c0ed2f 100644 ---- a/block.c -+++ b/block.c -@@ -5672,10 +5672,6 @@ void bdrv_detach_aio_context(BlockDriverState *bs) - BdrvAioNotifier *baf, *baf_tmp; - BdrvChild *child; - -- if (!bs->drv) { -- return; -- } -- - assert(!bs->walking_aio_notifiers); - bs->walking_aio_notifiers = true; - QLIST_FOREACH_SAFE(baf, &bs->aio_notifiers, list, baf_tmp) { -@@ -5690,7 +5686,7 @@ void bdrv_detach_aio_context(BlockDriverState *bs) - */ - bs->walking_aio_notifiers = false; - -- if (bs->drv->bdrv_detach_aio_context) { -+ if (bs->drv && bs->drv->bdrv_detach_aio_context) { - bs->drv->bdrv_detach_aio_context(bs); - } - QLIST_FOREACH(child, &bs->children, next) { -@@ -5709,10 +5705,6 @@ void bdrv_attach_aio_context(BlockDriverState *bs, - BdrvAioNotifier *ban, *ban_tmp; - BdrvChild *child; - -- if (!bs->drv) { -- return; -- } -- - if (bs->quiesce_counter) { - aio_disable_external(new_context); - } -@@ -5722,7 +5714,7 @@ void bdrv_attach_aio_context(BlockDriverState *bs, - QLIST_FOREACH(child, &bs->children, next) { - bdrv_attach_aio_context(child->bs, new_context); - } -- if (bs->drv->bdrv_attach_aio_context) { -+ if (bs->drv && bs->drv->bdrv_attach_aio_context) { - bs->drv->bdrv_attach_aio_context(bs, new_context); - } - --- -2.19.1 - diff --git a/block-Make-backing-files-child_of_bds-children.patch b/block-Make-backing-files-child_of_bds-children.patch new file mode 100644 index 0000000000000000000000000000000000000000..1ce43dbcc01878032a56086dd38dbdb631565944 --- /dev/null +++ b/block-Make-backing-files-child_of_bds-children.patch @@ -0,0 +1,168 @@ +From 25191e5ff0804bbd3b9e9dd86fb538c06710cee2 Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Wed, 13 May 2020 13:05:33 +0200 +Subject: [PATCH 555/709] block: Make backing files child_of_bds children + +Make all parents of backing files pass the appropriate BdrvChildRole. +By doing so, we can switch their BdrvChildClass over to the generic +child_of_bds, which will do the right thing when given a correct +BdrvChildRole. + +Signed-off-by: Max Reitz +Message-Id: <20200513110544.176672-24-mreitz@redhat.com> +Reviewed-by: Eric Blake +Signed-off-by: Kevin Wolf +--- + block.c | 26 ++++++++++++++++++++------ + block/backup-top.c | 2 +- + block/vvfat.c | 3 ++- + tests/test-bdrv-drain.c | 13 +++++++------ + 4 files changed, 30 insertions(+), 14 deletions(-) + +diff --git a/block.c b/block.c +index 85b4f947ba..131ae20ffc 100644 +--- a/block.c ++++ b/block.c +@@ -2941,6 +2941,20 @@ static bool bdrv_inherits_from_recursive(BlockDriverState *child, + return child != NULL; + } + ++/* ++ * Return the BdrvChildRole for @bs's backing child. bs->backing is ++ * mostly used for COW backing children (role = COW), but also for ++ * filtered children (role = FILTERED | PRIMARY). ++ */ ++static BdrvChildRole bdrv_backing_role(BlockDriverState *bs) ++{ ++ if (bs->drv && bs->drv->is_filter) { ++ return BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY; ++ } else { ++ return BDRV_CHILD_COW; ++ } ++} ++ + /* + * Sets the backing file link of a BDS. A new reference is created; callers + * which don't need their own reference any more must call bdrv_unref(). +@@ -2968,8 +2982,8 @@ void bdrv_set_backing_hd(BlockDriverState *bs, BlockDriverState *backing_hd, + goto out; + } + +- bs->backing = bdrv_attach_child(bs, backing_hd, "backing", &child_backing, +- 0, errp); ++ bs->backing = bdrv_attach_child(bs, backing_hd, "backing", &child_of_bds, ++ bdrv_backing_role(bs), errp); + /* If backing_hd was already part of bs's backing chain, and + * inherits_from pointed recursively to bs then let's update it to + * point directly to bs (else it will become NULL). */ +@@ -3066,7 +3080,7 @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *parent_options, + } + + backing_hd = bdrv_open_inherit(backing_filename, reference, options, 0, bs, +- &child_backing, 0, errp); ++ &child_of_bds, bdrv_backing_role(bs), errp); + if (!backing_hd) { + bs->open_flags |= BDRV_O_NO_BACKING; + error_prepend(errp, "Could not open backing file: "); +@@ -3895,8 +3909,8 @@ int bdrv_reopen_multiple(BlockReopenQueue *bs_queue, Error **errp) + if (state->replace_backing_bs && state->new_backing_bs) { + uint64_t nperm, nshared; + bdrv_child_perm(state->bs, state->new_backing_bs, +- NULL, &child_backing, 0, bs_queue, +- state->perm, state->shared_perm, ++ NULL, &child_of_bds, bdrv_backing_role(state->bs), ++ bs_queue, state->perm, state->shared_perm, + &nperm, &nshared); + ret = bdrv_check_update_perm(state->new_backing_bs, NULL, + nperm, nshared, NULL, NULL, errp); +@@ -6852,7 +6866,7 @@ void bdrv_refresh_filename(BlockDriverState *bs) + drv->bdrv_gather_child_options(bs, opts, backing_overridden); + } else { + QLIST_FOREACH(child, &bs->children, next) { +- if (child->klass == &child_backing && !backing_overridden) { ++ if (child == bs->backing && !backing_overridden) { + /* We can skip the backing BDS if it has not been overridden */ + continue; + } +diff --git a/block/backup-top.c b/block/backup-top.c +index e2b4d2acd3..f059617095 100644 +--- a/block/backup-top.c ++++ b/block/backup-top.c +@@ -143,7 +143,7 @@ static void backup_top_child_perm(BlockDriverState *bs, BdrvChild *c, + return; + } + +- if (child_class == &child_file) { ++ if (!(role & BDRV_CHILD_FILTERED)) { + /* + * Target child + * +diff --git a/block/vvfat.c b/block/vvfat.c +index b4c8417dbd..e8848a0497 100644 +--- a/block/vvfat.c ++++ b/block/vvfat.c +@@ -3219,7 +3219,8 @@ static void vvfat_child_perm(BlockDriverState *bs, BdrvChild *c, + { + BDRVVVFATState *s = bs->opaque; + +- assert(c == s->qcow || child_class == &child_backing); ++ assert(c == s->qcow || ++ (child_class == &child_of_bds && (role & BDRV_CHILD_COW))); + + if (c == s->qcow) { + /* This is a private node, nobody should try to attach to it */ +diff --git a/tests/test-bdrv-drain.c b/tests/test-bdrv-drain.c +index b3d7960bd0..15393a0140 100644 +--- a/tests/test-bdrv-drain.c ++++ b/tests/test-bdrv-drain.c +@@ -96,7 +96,7 @@ static void bdrv_test_child_perm(BlockDriverState *bs, BdrvChild *c, + * bdrv_format_default_perms() accepts only these two, so disguise + * detach_by_driver_cb_parent as one of them. + */ +- if (child_class != &child_file && child_class != &child_backing) { ++ if (child_class != &child_file && child_class != &child_of_bds) { + child_class = &child_file; + } + +@@ -1399,8 +1399,8 @@ static void test_detach_indirect(bool by_parent_cb) + bdrv_ref(a); + child_b = bdrv_attach_child(parent_b, b, "PB-B", &child_file, 0, + &error_abort); +- child_a = bdrv_attach_child(parent_b, a, "PB-A", &child_backing, 0, +- &error_abort); ++ child_a = bdrv_attach_child(parent_b, a, "PB-A", &child_of_bds, ++ BDRV_CHILD_COW, &error_abort); + + bdrv_ref(a); + bdrv_attach_child(parent_a, a, "PA-A", +@@ -1793,7 +1793,7 @@ static void test_drop_intermediate_poll(void) + int i; + int ret; + +- chain_child_class = child_backing; ++ chain_child_class = child_of_bds; + chain_child_class.update_filename = drop_intermediate_poll_update_filename; + + for (i = 0; i < 3; i++) { +@@ -1816,7 +1816,7 @@ static void test_drop_intermediate_poll(void) + /* Takes the reference to chain[i - 1] */ + chain[i]->backing = bdrv_attach_child(chain[i], chain[i - 1], + "chain", &chain_child_class, +- 0, &error_abort); ++ BDRV_CHILD_COW, &error_abort); + } + } + +@@ -2034,7 +2034,8 @@ static void do_test_replace_child_mid_drain(int old_drain_count, + + bdrv_ref(old_child_bs); + parent_bs->backing = bdrv_attach_child(parent_bs, old_child_bs, "child", +- &child_backing, 0, &error_abort); ++ &child_of_bds, BDRV_CHILD_COW, ++ &error_abort); + + for (i = 0; i < old_drain_count; i++) { + bdrv_drained_begin(old_child_bs); +-- +2.23.0 + diff --git a/block-Make-bdrv_filter_default_perms-static.patch b/block-Make-bdrv_filter_default_perms-static.patch new file mode 100644 index 0000000000000000000000000000000000000000..7845ee2cc89a48e5b00778450cad15eca5276648 --- /dev/null +++ b/block-Make-bdrv_filter_default_perms-static.patch @@ -0,0 +1,66 @@ +From 87278af1d9bac404e1c64ee2b652193a4c2628a6 Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Wed, 13 May 2020 13:05:40 +0200 +Subject: [PATCH 562/709] block: Make bdrv_filter_default_perms() static + +Signed-off-by: Max Reitz +Reviewed-by: Eric Blake +Message-Id: <20200513110544.176672-31-mreitz@redhat.com> +Signed-off-by: Kevin Wolf +--- + block.c | 17 +++++++++++------ + include/block/block_int.h | 10 ---------- + 2 files changed, 11 insertions(+), 16 deletions(-) + +diff --git a/block.c b/block.c +index fb94adcca4..54bc1c3b2d 100644 +--- a/block.c ++++ b/block.c +@@ -2382,12 +2382,17 @@ int bdrv_child_refresh_perms(BlockDriverState *bs, BdrvChild *c, Error **errp) + return bdrv_child_try_set_perm(c, perms, shared, errp); + } + +-void bdrv_filter_default_perms(BlockDriverState *bs, BdrvChild *c, +- const BdrvChildClass *child_class, +- BdrvChildRole role, +- BlockReopenQueue *reopen_queue, +- uint64_t perm, uint64_t shared, +- uint64_t *nperm, uint64_t *nshared) ++/* ++ * Default implementation for .bdrv_child_perm() for block filters: ++ * Forward CONSISTENT_READ, WRITE, WRITE_UNCHANGED, and RESIZE to the ++ * filtered child. ++ */ ++static void bdrv_filter_default_perms(BlockDriverState *bs, BdrvChild *c, ++ const BdrvChildClass *child_class, ++ BdrvChildRole role, ++ BlockReopenQueue *reopen_queue, ++ uint64_t perm, uint64_t shared, ++ uint64_t *nperm, uint64_t *nshared) + { + *nperm = perm & DEFAULT_PERM_PASSTHROUGH; + *nshared = (shared & DEFAULT_PERM_PASSTHROUGH) | DEFAULT_PERM_UNCHANGED; +diff --git a/include/block/block_int.h b/include/block/block_int.h +index 0781d43af5..6fc5f0d333 100644 +--- a/include/block/block_int.h ++++ b/include/block/block_int.h +@@ -1262,16 +1262,6 @@ int bdrv_child_try_set_perm(BdrvChild *c, uint64_t perm, uint64_t shared, + */ + int bdrv_child_refresh_perms(BlockDriverState *bs, BdrvChild *c, Error **errp); + +-/* Default implementation for BlockDriver.bdrv_child_perm() that can be used by +- * block filters: Forward CONSISTENT_READ, WRITE, WRITE_UNCHANGED and RESIZE to +- * all children */ +-void bdrv_filter_default_perms(BlockDriverState *bs, BdrvChild *c, +- const BdrvChildClass *child_class, +- BdrvChildRole child_role, +- BlockReopenQueue *reopen_queue, +- uint64_t perm, uint64_t shared, +- uint64_t *nperm, uint64_t *nshared); +- + /* Default implementation for BlockDriver.bdrv_child_perm() that can be used by + * (non-raw) image formats: Like above for bs->backing, but for bs->file it + * requires WRITE | RESIZE for read-write images, always requires +-- +2.23.0 + diff --git a/block-Make-filter-drivers-use-child_of_bds.patch b/block-Make-filter-drivers-use-child_of_bds.patch new file mode 100644 index 0000000000000000000000000000000000000000..e8dfc44ed7836f52ada53eab312e06afe21b0889 --- /dev/null +++ b/block-Make-filter-drivers-use-child_of_bds.patch @@ -0,0 +1,161 @@ +From b3af2af43b2bf85191cf40fa84b33df1268a08fd Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Wed, 13 May 2020 13:05:36 +0200 +Subject: [PATCH 558/709] block: Make filter drivers use child_of_bds + +Note that some filters have secondary children, namely blkverify (the +image to be verified) and blklogwrites (the log). This patch does not +touch those children. + +Note that for blkverify, the filtered child should not be format-probed. +While there is nothing enforcing this here, in practice, it will not be: +blkverify implements .bdrv_file_open. The block layer ensures (and in +fact, asserts) that BDRV_O_PROTOCOL is set for every BDS whose driver +implements .bdrv_file_open. This flag will then be bequeathed to +blkverify's children, and they will thus (by default) not be probed +either. + +("By default" refers to the fact that blkverify's other child (the +non-filtered one) will have BDRV_O_PROTOCOL force-unset, because that is +what happens for all non-filtered children of non-format drivers.) + +Signed-off-by: Max Reitz +Message-Id: <20200513110544.176672-27-mreitz@redhat.com> +Reviewed-by: Eric Blake +Signed-off-by: Kevin Wolf +--- + block/blkdebug.c | 4 +++- + block/blklogwrites.c | 3 ++- + block/blkreplay.c | 5 +++-- + block/blkverify.c | 4 +++- + block/copy-on-read.c | 5 +++-- + block/filter-compress.c | 5 +++-- + block/replication.c | 3 ++- + block/throttle.c | 5 +++-- + 8 files changed, 22 insertions(+), 12 deletions(-) + +diff --git a/block/blkdebug.c b/block/blkdebug.c +index 8dd8ed6055..b31fa40b0e 100644 +--- a/block/blkdebug.c ++++ b/block/blkdebug.c +@@ -497,7 +497,9 @@ static int blkdebug_open(BlockDriverState *bs, QDict *options, int flags, + + /* Open the image file */ + bs->file = bdrv_open_child(qemu_opt_get(opts, "x-image"), options, "image", +- bs, &child_file, 0, false, &local_err); ++ bs, &child_of_bds, ++ BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY, ++ false, &local_err); + if (local_err) { + ret = -EINVAL; + error_propagate(errp, local_err); +diff --git a/block/blklogwrites.c b/block/blklogwrites.c +index 4faf912ef1..78b0c49460 100644 +--- a/block/blklogwrites.c ++++ b/block/blklogwrites.c +@@ -157,7 +157,8 @@ static int blk_log_writes_open(BlockDriverState *bs, QDict *options, int flags, + } + + /* Open the file */ +- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, 0, false, ++ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds, ++ BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY, false, + &local_err); + if (local_err) { + ret = -EINVAL; +diff --git a/block/blkreplay.c b/block/blkreplay.c +index 9b2814fc58..20d6139baa 100644 +--- a/block/blkreplay.c ++++ b/block/blkreplay.c +@@ -27,8 +27,9 @@ static int blkreplay_open(BlockDriverState *bs, QDict *options, int flags, + int ret; + + /* Open the image file */ +- bs->file = bdrv_open_child(NULL, options, "image", +- bs, &child_file, 0, false, &local_err); ++ bs->file = bdrv_open_child(NULL, options, "image", bs, &child_of_bds, ++ BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY, ++ false, &local_err); + if (local_err) { + ret = -EINVAL; + error_propagate(errp, local_err); +diff --git a/block/blkverify.c b/block/blkverify.c +index 1684b7aa2e..5c3b29244a 100644 +--- a/block/blkverify.c ++++ b/block/blkverify.c +@@ -125,7 +125,9 @@ static int blkverify_open(BlockDriverState *bs, QDict *options, int flags, + + /* Open the raw file */ + bs->file = bdrv_open_child(qemu_opt_get(opts, "x-raw"), options, "raw", +- bs, &child_file, 0, false, &local_err); ++ bs, &child_of_bds, ++ BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY, ++ false, &local_err); + if (local_err) { + ret = -EINVAL; + error_propagate(errp, local_err); +diff --git a/block/copy-on-read.c b/block/copy-on-read.c +index a2d92ac394..c857ea0da7 100644 +--- a/block/copy-on-read.c ++++ b/block/copy-on-read.c +@@ -28,8 +28,9 @@ + static int cor_open(BlockDriverState *bs, QDict *options, int flags, + Error **errp) + { +- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, 0, false, +- errp); ++ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds, ++ BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY, ++ false, errp); + if (!bs->file) { + return -EINVAL; + } +diff --git a/block/filter-compress.c b/block/filter-compress.c +index 4dc5f9fb8c..9edd937645 100644 +--- a/block/filter-compress.c ++++ b/block/filter-compress.c +@@ -30,8 +30,9 @@ + static int compress_open(BlockDriverState *bs, QDict *options, int flags, + Error **errp) + { +- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, 0, false, +- errp); ++ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds, ++ BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY, ++ false, errp); + if (!bs->file) { + return -EINVAL; + } +diff --git a/block/replication.c b/block/replication.c +index ea87b1a4f0..cc9c473ad1 100644 +--- a/block/replication.c ++++ b/block/replication.c +@@ -90,7 +90,8 @@ static int replication_open(BlockDriverState *bs, QDict *options, + const char *mode; + const char *top_id; + +- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, 0, ++ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds, ++ BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY, + false, errp); + if (!bs->file) { + return -EINVAL; +diff --git a/block/throttle.c b/block/throttle.c +index 2dea913be7..47b0a3522d 100644 +--- a/block/throttle.c ++++ b/block/throttle.c +@@ -81,8 +81,9 @@ static int throttle_open(BlockDriverState *bs, QDict *options, + char *group; + int ret; + +- bs->file = bdrv_open_child(NULL, options, "file", bs, +- &child_file, 0, false, errp); ++ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds, ++ BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY, ++ false, errp); + if (!bs->file) { + return -EINVAL; + } +-- +2.23.0 + diff --git a/block-Make-format-drivers-use-child_of_bds.patch b/block-Make-format-drivers-use-child_of_bds.patch new file mode 100644 index 0000000000000000000000000000000000000000..49c59636bf0e04bf9d8328075a71062c6ab5b32d --- /dev/null +++ b/block-Make-format-drivers-use-child_of_bds.patch @@ -0,0 +1,285 @@ +From 8b1869daad17f313bf9a68fd3275448df0ecb7fb Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Wed, 13 May 2020 13:05:35 +0200 +Subject: [PATCH 557/709] block: Make format drivers use child_of_bds + +Commonly, they need to pass the BDRV_CHILD_IMAGE set as the +BdrvChildRole; but there are exceptions for drivers with external data +files (qcow2 and vmdk). + +Signed-off-by: Max Reitz +Reviewed-by: Eric Blake +Message-Id: <20200513110544.176672-26-mreitz@redhat.com> +Signed-off-by: Kevin Wolf +--- + block/bochs.c | 4 ++-- + block/cloop.c | 4 ++-- + block/crypto.c | 4 ++-- + block/dmg.c | 4 ++-- + block/parallels.c | 4 ++-- + block/qcow.c | 4 ++-- + block/qcow2.c | 19 +++++++++++++------ + block/qed.c | 4 ++-- + block/vdi.c | 4 ++-- + block/vhdx.c | 4 ++-- + block/vmdk.c | 20 +++++++++++++++++--- + block/vpc.c | 4 ++-- + 12 files changed, 50 insertions(+), 29 deletions(-) + +diff --git a/block/bochs.c b/block/bochs.c +index b013e73063..62c3f42548 100644 +--- a/block/bochs.c ++++ b/block/bochs.c +@@ -110,8 +110,8 @@ static int bochs_open(BlockDriverState *bs, QDict *options, int flags, + return ret; + } + +- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, 0, +- false, errp); ++ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds, ++ BDRV_CHILD_IMAGE, false, errp); + if (!bs->file) { + return -EINVAL; + } +diff --git a/block/cloop.c b/block/cloop.c +index 3ed9fa63cc..d374a8427d 100644 +--- a/block/cloop.c ++++ b/block/cloop.c +@@ -71,8 +71,8 @@ static int cloop_open(BlockDriverState *bs, QDict *options, int flags, + return ret; + } + +- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, 0, +- false, errp); ++ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds, ++ BDRV_CHILD_IMAGE, false, errp); + if (!bs->file) { + return -EINVAL; + } +diff --git a/block/crypto.c b/block/crypto.c +index 8b516bfee2..457f3a06a5 100644 +--- a/block/crypto.c ++++ b/block/crypto.c +@@ -218,8 +218,8 @@ static int block_crypto_open_generic(QCryptoBlockFormat format, + unsigned int cflags = 0; + QDict *cryptoopts = NULL; + +- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, 0, +- false, errp); ++ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds, ++ BDRV_CHILD_IMAGE, false, errp); + if (!bs->file) { + return -EINVAL; + } +diff --git a/block/dmg.c b/block/dmg.c +index af8188638c..bc64194577 100644 +--- a/block/dmg.c ++++ b/block/dmg.c +@@ -439,8 +439,8 @@ static int dmg_open(BlockDriverState *bs, QDict *options, int flags, + return ret; + } + +- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, 0, +- false, errp); ++ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds, ++ BDRV_CHILD_IMAGE, false, errp); + if (!bs->file) { + return -EINVAL; + } +diff --git a/block/parallels.c b/block/parallels.c +index 9855ac1162..168d6c531a 100644 +--- a/block/parallels.c ++++ b/block/parallels.c +@@ -739,8 +739,8 @@ static int parallels_open(BlockDriverState *bs, QDict *options, int flags, + Error *local_err = NULL; + char *buf; + +- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, 0, +- false, errp); ++ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds, ++ BDRV_CHILD_IMAGE, false, errp); + if (!bs->file) { + return -EINVAL; + } +diff --git a/block/qcow.c b/block/qcow.c +index 13583f0339..5347037720 100644 +--- a/block/qcow.c ++++ b/block/qcow.c +@@ -130,8 +130,8 @@ static int qcow_open(BlockDriverState *bs, QDict *options, int flags, + qdict_extract_subqdict(options, &encryptopts, "encrypt."); + encryptfmt = qdict_get_try_str(encryptopts, "format"); + +- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, 0, +- false, errp); ++ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds, ++ BDRV_CHILD_IMAGE, false, errp); + if (!bs->file) { + ret = -EINVAL; + goto fail; +diff --git a/block/qcow2.c b/block/qcow2.c +index 86335d9403..8d7230dca8 100644 +--- a/block/qcow2.c ++++ b/block/qcow2.c +@@ -1590,8 +1590,9 @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options, + } + + /* Open external data file */ +- s->data_file = bdrv_open_child(NULL, options, "data-file", bs, &child_file, +- 0, true, &local_err); ++ s->data_file = bdrv_open_child(NULL, options, "data-file", bs, ++ &child_of_bds, BDRV_CHILD_DATA, ++ true, &local_err); + if (local_err) { + error_propagate(errp, local_err); + ret = -EINVAL; +@@ -1601,8 +1602,8 @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options, + if (s->incompatible_features & QCOW2_INCOMPAT_DATA_FILE) { + if (!s->data_file && s->image_data_file) { + s->data_file = bdrv_open_child(s->image_data_file, options, +- "data-file", bs, &child_file, 0, +- false, errp); ++ "data-file", bs, &child_of_bds, ++ BDRV_CHILD_DATA, false, errp); + if (!s->data_file) { + ret = -EINVAL; + goto fail; +@@ -1613,6 +1614,12 @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options, + ret = -EINVAL; + goto fail; + } ++ ++ /* No data here */ ++ bs->file->role &= ~BDRV_CHILD_DATA; ++ ++ /* Must succeed because we have given up permissions if anything */ ++ bdrv_child_refresh_perms(bs, bs->file, &error_abort); + } else { + if (s->data_file) { + error_setg(errp, "'data-file' can only be set for images with an " +@@ -1863,8 +1870,8 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags, + .ret = -EINPROGRESS + }; + +- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, 0, +- false, errp); ++ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds, ++ BDRV_CHILD_IMAGE, false, errp); + if (!bs->file) { + return -EINVAL; + } +diff --git a/block/qed.c b/block/qed.c +index 1ad2aba810..ef6463b48d 100644 +--- a/block/qed.c ++++ b/block/qed.c +@@ -547,8 +547,8 @@ static int bdrv_qed_open(BlockDriverState *bs, QDict *options, int flags, + .ret = -EINPROGRESS + }; + +- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, 0, +- false, errp); ++ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds, ++ BDRV_CHILD_IMAGE, false, errp); + if (!bs->file) { + return -EINVAL; + } +diff --git a/block/vdi.c b/block/vdi.c +index 653acb5fc1..d20698b3cc 100644 +--- a/block/vdi.c ++++ b/block/vdi.c +@@ -378,8 +378,8 @@ static int vdi_open(BlockDriverState *bs, QDict *options, int flags, + Error *local_err = NULL; + QemuUUID uuid_link, uuid_parent; + +- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, 0, +- false, errp); ++ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds, ++ BDRV_CHILD_IMAGE, false, errp); + if (!bs->file) { + return -EINVAL; + } +diff --git a/block/vhdx.c b/block/vhdx.c +index dde156c97b..62c6bd69ff 100644 +--- a/block/vhdx.c ++++ b/block/vhdx.c +@@ -996,8 +996,8 @@ static int vhdx_open(BlockDriverState *bs, QDict *options, int flags, + uint64_t signature; + Error *local_err = NULL; + +- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, 0, +- false, errp); ++ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds, ++ BDRV_CHILD_IMAGE, false, errp); + if (!bs->file) { + return -EINVAL; + } +diff --git a/block/vmdk.c b/block/vmdk.c +index c2cb741e2d..fadc98a262 100644 +--- a/block/vmdk.c ++++ b/block/vmdk.c +@@ -1089,6 +1089,7 @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs, + char *desc_file_dir = NULL; + char *extent_path; + BdrvChild *extent_file; ++ BdrvChildRole extent_role; + BDRVVmdkState *s = bs->opaque; + VmdkExtent *extent; + char extent_opt_prefix[32]; +@@ -1151,8 +1152,15 @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs, + ret = snprintf(extent_opt_prefix, 32, "extents.%d", s->num_extents); + assert(ret < 32); + ++ extent_role = BDRV_CHILD_DATA; ++ if (strcmp(type, "FLAT") != 0 && strcmp(type, "VMFS") != 0) { ++ /* non-flat extents have metadata */ ++ extent_role |= BDRV_CHILD_METADATA; ++ } ++ + extent_file = bdrv_open_child(extent_path, options, extent_opt_prefix, +- bs, &child_file, 0, false, &local_err); ++ bs, &child_of_bds, extent_role, false, ++ &local_err); + g_free(extent_path); + if (local_err) { + error_propagate(errp, local_err); +@@ -1257,8 +1265,8 @@ static int vmdk_open(BlockDriverState *bs, QDict *options, int flags, + uint32_t magic; + Error *local_err = NULL; + +- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, 0, +- false, errp); ++ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds, ++ BDRV_CHILD_IMAGE, false, errp); + if (!bs->file) { + return -EINVAL; + } +@@ -1277,6 +1285,12 @@ static int vmdk_open(BlockDriverState *bs, QDict *options, int flags, + s->desc_offset = 0x200; + break; + default: ++ /* No data in the descriptor file */ ++ bs->file->role &= ~BDRV_CHILD_DATA; ++ ++ /* Must succeed because we have given up permissions if anything */ ++ bdrv_child_refresh_perms(bs, bs->file, &error_abort); ++ + ret = vmdk_open_desc_file(bs, flags, buf, options, errp); + break; + } +diff --git a/block/vpc.c b/block/vpc.c +index b2a86074a5..651a6737b6 100644 +--- a/block/vpc.c ++++ b/block/vpc.c +@@ -228,8 +228,8 @@ static int vpc_open(BlockDriverState *bs, QDict *options, int flags, + int ret; + int64_t bs_size; + +- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, 0, +- false, errp); ++ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds, ++ BDRV_CHILD_IMAGE, false, errp); + if (!bs->file) { + return -EINVAL; + } +-- +2.23.0 + diff --git a/block-Make-it-easier-to-learn-which-BDS-support-bitm.patch b/block-Make-it-easier-to-learn-which-BDS-support-bitm.patch new file mode 100644 index 0000000000000000000000000000000000000000..829e2564b4f37886068673270d3034d233a4c226 --- /dev/null +++ b/block-Make-it-easier-to-learn-which-BDS-support-bitm.patch @@ -0,0 +1,129 @@ +From ef893b5c84f3199d777e33966dc28839f71b1a5c Mon Sep 17 00:00:00 2001 +From: Eric Blake +Date: Tue, 12 May 2020 20:16:42 -0500 +Subject: [PATCH 589/709] block: Make it easier to learn which BDS support + bitmaps + +Upcoming patches will enhance bitmap support in qemu-img, but in doing +so, it turns out to be nice to suppress output when persistent bitmaps +make no sense (such as on a qcow2 v2 image). Add a hook to make this +easier to query. + +This patch adds a new callback .bdrv_supports_persistent_dirty_bitmap, +rather than trying to shoehorn the answer in via existing callbacks. +In particular, while it might have been possible to overload +.bdrv_co_can_store_new_dirty_bitmap to special-case a NULL input to +answer whether any persistent bitmaps are supported, that is at odds +with whether a particular bitmap can be stored (for example, even on +an image that supports persistent bitmaps but has currently filled up +the maximum number of bitmaps, attempts to store another one should +fail); and the new functionality doesn't require coroutine safety. +Similarly, we could have added one more piece of information to +.bdrv_get_info, but then again, most callers to that function tend to +already discard extraneous information, and making it a catch-all +rather than a series of dedicated scalar queries hasn't really +simplified life. + +In the future, when we improve the ability to look up bitmaps through +a filter, we will probably also want to teach the block layer to +automatically let filters pass this request on through. + +Signed-off-by: Eric Blake +Message-Id: <20200513011648.166876-4-eblake@redhat.com> +Reviewed-by: Vladimir Sementsov-Ogievskiy +--- + block/dirty-bitmap.c | 9 +++++++++ + block/qcow2-bitmap.c | 7 +++++++ + block/qcow2.c | 2 ++ + block/qcow2.h | 1 + + include/block/block_int.h | 1 + + include/block/dirty-bitmap.h | 1 + + 6 files changed, 21 insertions(+) + +diff --git a/block/dirty-bitmap.c b/block/dirty-bitmap.c +index 063793e316..f9bfc77985 100644 +--- a/block/dirty-bitmap.c ++++ b/block/dirty-bitmap.c +@@ -478,6 +478,15 @@ int bdrv_remove_persistent_dirty_bitmap(BlockDriverState *bs, const char *name, + } + } + ++bool ++bdrv_supports_persistent_dirty_bitmap(BlockDriverState *bs) ++{ ++ if (bs->drv && bs->drv->bdrv_supports_persistent_dirty_bitmap) { ++ return bs->drv->bdrv_supports_persistent_dirty_bitmap(bs); ++ } ++ return false; ++} ++ + static bool coroutine_fn + bdrv_co_can_store_new_dirty_bitmap(BlockDriverState *bs, const char *name, + uint32_t granularity, Error **errp) +diff --git a/block/qcow2-bitmap.c b/block/qcow2-bitmap.c +index cb06954b4a..1cf6d2ab77 100644 +--- a/block/qcow2-bitmap.c ++++ b/block/qcow2-bitmap.c +@@ -1748,3 +1748,10 @@ fail: + name, bdrv_get_device_or_node_name(bs)); + return false; + } ++ ++bool qcow2_supports_persistent_dirty_bitmap(BlockDriverState *bs) ++{ ++ BDRVQcow2State *s = bs->opaque; ++ ++ return s->qcow_version >= 3; ++} +diff --git a/block/qcow2.c b/block/qcow2.c +index fe0ce39799..dfab8d2f6c 100644 +--- a/block/qcow2.c ++++ b/block/qcow2.c +@@ -5791,6 +5791,8 @@ BlockDriver bdrv_qcow2 = { + .bdrv_detach_aio_context = qcow2_detach_aio_context, + .bdrv_attach_aio_context = qcow2_attach_aio_context, + ++ .bdrv_supports_persistent_dirty_bitmap = ++ qcow2_supports_persistent_dirty_bitmap, + .bdrv_co_can_store_new_dirty_bitmap = qcow2_co_can_store_new_dirty_bitmap, + .bdrv_co_remove_persistent_dirty_bitmap = + qcow2_co_remove_persistent_dirty_bitmap, +diff --git a/block/qcow2.h b/block/qcow2.h +index 6a8b82e6cc..402e8acb1c 100644 +--- a/block/qcow2.h ++++ b/block/qcow2.h +@@ -782,6 +782,7 @@ bool qcow2_co_can_store_new_dirty_bitmap(BlockDriverState *bs, + int qcow2_co_remove_persistent_dirty_bitmap(BlockDriverState *bs, + const char *name, + Error **errp); ++bool qcow2_supports_persistent_dirty_bitmap(BlockDriverState *bs); + + ssize_t coroutine_fn + qcow2_co_compress(BlockDriverState *bs, void *dest, size_t dest_size, +diff --git a/include/block/block_int.h b/include/block/block_int.h +index 5e4f4c348c..33a12916f4 100644 +--- a/include/block/block_int.h ++++ b/include/block/block_int.h +@@ -568,6 +568,7 @@ struct BlockDriver { + uint64_t parent_perm, uint64_t parent_shared, + uint64_t *nperm, uint64_t *nshared); + ++ bool (*bdrv_supports_persistent_dirty_bitmap)(BlockDriverState *bs); + bool (*bdrv_co_can_store_new_dirty_bitmap)(BlockDriverState *bs, + const char *name, + uint32_t granularity, +diff --git a/include/block/dirty-bitmap.h b/include/block/dirty-bitmap.h +index 8a10029418..5a8d52e4de 100644 +--- a/include/block/dirty-bitmap.h ++++ b/include/block/dirty-bitmap.h +@@ -16,6 +16,7 @@ typedef enum BitmapCheckFlags { + + #define BDRV_BITMAP_MAX_NAME_SIZE 1023 + ++bool bdrv_supports_persistent_dirty_bitmap(BlockDriverState *bs); + BdrvDirtyBitmap *bdrv_create_dirty_bitmap(BlockDriverState *bs, + uint32_t granularity, + const char *name, +-- +2.23.0 + diff --git a/block-Mark-commit-mirror-blkreplay-as-filters.patch b/block-Mark-commit-mirror-blkreplay-as-filters.patch new file mode 100644 index 0000000000000000000000000000000000000000..90a616b9267a2101f45371fb0ccb3db6d1aa5687 --- /dev/null +++ b/block-Mark-commit-mirror-blkreplay-as-filters.patch @@ -0,0 +1,58 @@ +From 6540fd153ca9d4cff31b1cc3f5ced271eca9296c Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Wed, 13 May 2020 13:05:11 +0200 +Subject: [PATCH 533/709] block: Mark commit, mirror, blkreplay as filters + +The commit, mirror, and blkreplay block nodes are filters, so they should +be marked as such. + +Signed-off-by: Max Reitz +Message-Id: <20200513110544.176672-2-mreitz@redhat.com> +Signed-off-by: Kevin Wolf +--- + block/blkreplay.c | 1 + + block/commit.c | 2 ++ + block/mirror.c | 2 ++ + 3 files changed, 5 insertions(+) + +diff --git a/block/blkreplay.c b/block/blkreplay.c +index c96ac8f4bc..131c9e8477 100644 +--- a/block/blkreplay.c ++++ b/block/blkreplay.c +@@ -135,6 +135,7 @@ static int blkreplay_snapshot_goto(BlockDriverState *bs, + static BlockDriver bdrv_blkreplay = { + .format_name = "blkreplay", + .instance_size = 0, ++ .is_filter = true, + + .bdrv_open = blkreplay_open, + .bdrv_child_perm = bdrv_filter_default_perms, +diff --git a/block/commit.c b/block/commit.c +index ba60fb7955..b0a8a793cd 100644 +--- a/block/commit.c ++++ b/block/commit.c +@@ -240,6 +240,8 @@ static BlockDriver bdrv_commit_top = { + .bdrv_co_block_status = bdrv_co_block_status_from_backing, + .bdrv_refresh_filename = bdrv_commit_top_refresh_filename, + .bdrv_child_perm = bdrv_commit_top_child_perm, ++ ++ .is_filter = true, + }; + + void commit_start(const char *job_id, BlockDriverState *bs, +diff --git a/block/mirror.c b/block/mirror.c +index 201ffa26f9..55e992670a 100644 +--- a/block/mirror.c ++++ b/block/mirror.c +@@ -1530,6 +1530,8 @@ static BlockDriver bdrv_mirror_top = { + .bdrv_co_block_status = bdrv_co_block_status_from_backing, + .bdrv_refresh_filename = bdrv_mirror_top_refresh_filename, + .bdrv_child_perm = bdrv_mirror_top_child_perm, ++ ++ .is_filter = true, + }; + + static BlockJob *mirror_start_job( +-- +2.23.0 + diff --git a/block-Pass-BdrvChildRole-in-remaining-cases.patch b/block-Pass-BdrvChildRole-in-remaining-cases.patch new file mode 100644 index 0000000000000000000000000000000000000000..7113ab52a441ff5cb689f2376177e66500cbe5ab --- /dev/null +++ b/block-Pass-BdrvChildRole-in-remaining-cases.patch @@ -0,0 +1,68 @@ +From 1f38f04eacd4c3b9409dcb411525f203cce168a1 Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Wed, 13 May 2020 13:05:43 +0200 +Subject: [PATCH 565/709] block: Pass BdrvChildRole in remaining cases + +These calls have no real use for the child role yet, but it will not +harm to give one. + +Notably, the bdrv_root_attach_child() call in blockjob.c is left +unmodified because there is not much the generic BlockJob object wants +from its children. + +Signed-off-by: Max Reitz +Message-Id: <20200513110544.176672-34-mreitz@redhat.com> +Reviewed-by: Eric Blake +Signed-off-by: Kevin Wolf +--- + block/block-backend.c | 11 +++++++---- + block/vvfat.c | 4 +++- + 2 files changed, 10 insertions(+), 5 deletions(-) + +diff --git a/block/block-backend.c b/block/block-backend.c +index f2e81af27d..6936b25c83 100644 +--- a/block/block-backend.c ++++ b/block/block-backend.c +@@ -424,8 +424,9 @@ BlockBackend *blk_new_open(const char *filename, const char *reference, + return NULL; + } + +- blk->root = bdrv_root_attach_child(bs, "root", &child_root, 0, blk->ctx, +- perm, BLK_PERM_ALL, blk, errp); ++ blk->root = bdrv_root_attach_child(bs, "root", &child_root, ++ BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY, ++ blk->ctx, perm, BLK_PERM_ALL, blk, errp); + if (!blk->root) { + blk_unref(blk); + return NULL; +@@ -835,8 +836,10 @@ int blk_insert_bs(BlockBackend *blk, BlockDriverState *bs, Error **errp) + { + ThrottleGroupMember *tgm = &blk->public.throttle_group_member; + bdrv_ref(bs); +- blk->root = bdrv_root_attach_child(bs, "root", &child_root, 0, blk->ctx, +- blk->perm, blk->shared_perm, blk, errp); ++ blk->root = bdrv_root_attach_child(bs, "root", &child_root, ++ BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY, ++ blk->ctx, blk->perm, blk->shared_perm, ++ blk, errp); + if (blk->root == NULL) { + return -EPERM; + } +diff --git a/block/vvfat.c b/block/vvfat.c +index e8848a0497..089abe1e29 100644 +--- a/block/vvfat.c ++++ b/block/vvfat.c +@@ -3184,7 +3184,9 @@ static int enable_write_target(BlockDriverState *bs, Error **errp) + options = qdict_new(); + qdict_put_str(options, "write-target.driver", "qcow"); + s->qcow = bdrv_open_child(s->qcow_filename, options, "write-target", bs, +- &child_vvfat_qcow, 0, false, errp); ++ &child_vvfat_qcow, ++ BDRV_CHILD_DATA | BDRV_CHILD_METADATA, ++ false, errp); + qobject_unref(options); + if (!s->qcow) { + ret = -EINVAL; +-- +2.23.0 + diff --git a/block-Pass-BdrvChildRole-to-.inherit_options.patch b/block-Pass-BdrvChildRole-to-.inherit_options.patch new file mode 100644 index 0000000000000000000000000000000000000000..5376c31fceb531d4500817c6ef9fc0c8fc483a01 --- /dev/null +++ b/block-Pass-BdrvChildRole-to-.inherit_options.patch @@ -0,0 +1,236 @@ +From 272c02eaef0388225c1dcdbec99b2e838bb64d23 Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Wed, 13 May 2020 13:05:17 +0200 +Subject: [PATCH 539/709] block: Pass BdrvChildRole to .inherit_options() + +For now, all callers (effectively) pass 0 and no callee evaluates thie +value. Later patches will change both. + +Signed-off-by: Max Reitz +Reviewed-by: Eric Blake +Message-Id: <20200513110544.176672-8-mreitz@redhat.com> +Signed-off-by: Kevin Wolf +--- + block.c | 40 +++++++++++++++++++++++---------------- + block/block-backend.c | 3 ++- + block/vvfat.c | 3 ++- + include/block/block_int.h | 3 ++- + 4 files changed, 30 insertions(+), 19 deletions(-) + +diff --git a/block.c b/block.c +index 5d9a331f5b..40db0b78b9 100644 +--- a/block.c ++++ b/block.c +@@ -77,6 +77,7 @@ static BlockDriverState *bdrv_open_inherit(const char *filename, + QDict *options, int flags, + BlockDriverState *parent, + const BdrvChildClass *child_class, ++ BdrvChildRole child_role, + Error **errp); + + /* If non-zero, use only whitelisted block drivers */ +@@ -1153,7 +1154,8 @@ static void bdrv_temp_snapshot_options(int *child_flags, QDict *child_options, + * Returns the options and flags that bs->file should get if a protocol driver + * is expected, based on the given options and flags for the parent BDS + */ +-static void bdrv_inherited_options(int *child_flags, QDict *child_options, ++static void bdrv_inherited_options(BdrvChildRole role, ++ int *child_flags, QDict *child_options, + int parent_flags, QDict *parent_options) + { + int flags = parent_flags; +@@ -1202,10 +1204,11 @@ const BdrvChildClass child_file = { + * (and not only protocols) is permitted for it, based on the given options and + * flags for the parent BDS + */ +-static void bdrv_inherited_fmt_options(int *child_flags, QDict *child_options, ++static void bdrv_inherited_fmt_options(BdrvChildRole role, ++ int *child_flags, QDict *child_options, + int parent_flags, QDict *parent_options) + { +- child_file.inherit_options(child_flags, child_options, ++ child_file.inherit_options(role, child_flags, child_options, + parent_flags, parent_options); + + *child_flags &= ~(BDRV_O_PROTOCOL | BDRV_O_NO_IO); +@@ -1286,7 +1289,8 @@ static void bdrv_backing_detach(BdrvChild *c) + * Returns the options and flags that bs->backing should get, based on the + * given options and flags for the parent BDS + */ +-static void bdrv_backing_options(int *child_flags, QDict *child_options, ++static void bdrv_backing_options(BdrvChildRole role, ++ int *child_flags, QDict *child_options, + int parent_flags, QDict *parent_options) + { + int flags = parent_flags; +@@ -2876,7 +2880,7 @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *parent_options, + } + + backing_hd = bdrv_open_inherit(backing_filename, reference, options, 0, bs, +- &child_backing, errp); ++ &child_backing, 0, errp); + if (!backing_hd) { + bs->open_flags |= BDRV_O_NO_BACKING; + error_prepend(errp, "Could not open backing file: "); +@@ -2911,7 +2915,7 @@ free_exit: + static BlockDriverState * + bdrv_open_child_bs(const char *filename, QDict *options, const char *bdref_key, + BlockDriverState *parent, const BdrvChildClass *child_class, +- bool allow_none, Error **errp) ++ BdrvChildRole child_role, bool allow_none, Error **errp) + { + BlockDriverState *bs = NULL; + QDict *image_options; +@@ -2942,7 +2946,7 @@ bdrv_open_child_bs(const char *filename, QDict *options, const char *bdref_key, + } + + bs = bdrv_open_inherit(filename, reference, image_options, 0, +- parent, child_class, errp); ++ parent, child_class, child_role, errp); + if (!bs) { + goto done; + } +@@ -2976,7 +2980,7 @@ BdrvChild *bdrv_open_child(const char *filename, + BlockDriverState *bs; + + bs = bdrv_open_child_bs(filename, options, bdref_key, parent, child_class, +- allow_none, errp); ++ child_role, allow_none, errp); + if (bs == NULL) { + return NULL; + } +@@ -3020,7 +3024,7 @@ BlockDriverState *bdrv_open_blockdev_ref(BlockdevRef *ref, Error **errp) + + } + +- bs = bdrv_open_inherit(NULL, reference, qdict, 0, NULL, NULL, errp); ++ bs = bdrv_open_inherit(NULL, reference, qdict, 0, NULL, NULL, 0, errp); + obj = NULL; + qobject_unref(obj); + visit_free(v); +@@ -3117,6 +3121,7 @@ static BlockDriverState *bdrv_open_inherit(const char *filename, + QDict *options, int flags, + BlockDriverState *parent, + const BdrvChildClass *child_class, ++ BdrvChildRole child_role, + Error **errp) + { + int ret; +@@ -3169,7 +3174,7 @@ static BlockDriverState *bdrv_open_inherit(const char *filename, + + if (child_class) { + bs->inherits_from = parent; +- child_class->inherit_options(&flags, options, ++ child_class->inherit_options(child_role, &flags, options, + parent->open_flags, parent->options); + } + +@@ -3198,7 +3203,7 @@ static BlockDriverState *bdrv_open_inherit(const char *filename, + flags, options); + /* Let bdrv_backing_options() override "read-only" */ + qdict_del(options, BDRV_OPT_READ_ONLY); +- bdrv_backing_options(&flags, options, flags, options); ++ bdrv_backing_options(0, &flags, options, flags, options); + } + + bs->open_flags = flags; +@@ -3240,7 +3245,7 @@ static BlockDriverState *bdrv_open_inherit(const char *filename, + BlockDriverState *file_bs; + + file_bs = bdrv_open_child_bs(filename, options, "file", bs, +- &child_file, true, &local_err); ++ &child_file, 0, true, &local_err); + if (local_err) { + goto fail; + } +@@ -3385,7 +3390,7 @@ BlockDriverState *bdrv_open(const char *filename, const char *reference, + QDict *options, int flags, Error **errp) + { + return bdrv_open_inherit(filename, reference, options, flags, NULL, +- NULL, errp); ++ NULL, 0, errp); + } + + /* Return true if the NULL-terminated @list contains @str */ +@@ -3482,6 +3487,7 @@ static BlockReopenQueue *bdrv_reopen_queue_child(BlockReopenQueue *bs_queue, + BlockDriverState *bs, + QDict *options, + const BdrvChildClass *klass, ++ BdrvChildRole role, + QDict *parent_options, + int parent_flags, + bool keep_old_opts) +@@ -3537,7 +3543,8 @@ static BlockReopenQueue *bdrv_reopen_queue_child(BlockReopenQueue *bs_queue, + /* Inherit from parent node */ + if (parent_options) { + flags = 0; +- klass->inherit_options(&flags, options, parent_flags, parent_options); ++ klass->inherit_options(role, &flags, options, ++ parent_flags, parent_options); + } else { + flags = bdrv_get_flags(bs); + } +@@ -3628,7 +3635,8 @@ static BlockReopenQueue *bdrv_reopen_queue_child(BlockReopenQueue *bs_queue, + } + + bdrv_reopen_queue_child(bs_queue, child->bs, new_child_options, +- child->klass, options, flags, child_keep_old); ++ child->klass, child->role, options, flags, ++ child_keep_old); + } + + return bs_queue; +@@ -3638,7 +3646,7 @@ BlockReopenQueue *bdrv_reopen_queue(BlockReopenQueue *bs_queue, + BlockDriverState *bs, + QDict *options, bool keep_old_opts) + { +- return bdrv_reopen_queue_child(bs_queue, bs, options, NULL, NULL, 0, ++ return bdrv_reopen_queue_child(bs_queue, bs, options, NULL, 0, NULL, 0, + keep_old_opts); + } + +diff --git a/block/block-backend.c b/block/block-backend.c +index efc7acb3d8..5539ca8816 100644 +--- a/block/block-backend.c ++++ b/block/block-backend.c +@@ -120,7 +120,8 @@ static QTAILQ_HEAD(, BlockBackend) block_backends = + static QTAILQ_HEAD(, BlockBackend) monitor_block_backends = + QTAILQ_HEAD_INITIALIZER(monitor_block_backends); + +-static void blk_root_inherit_options(int *child_flags, QDict *child_options, ++static void blk_root_inherit_options(BdrvChildRole role, ++ int *child_flags, QDict *child_options, + int parent_flags, QDict *parent_options) + { + /* We're not supposed to call this function for root nodes */ +diff --git a/block/vvfat.c b/block/vvfat.c +index 6cf3c74fe3..4033e4f369 100644 +--- a/block/vvfat.c ++++ b/block/vvfat.c +@@ -3128,7 +3128,8 @@ static BlockDriver vvfat_write_target = { + .bdrv_co_pwritev = write_target_commit, + }; + +-static void vvfat_qcow_options(int *child_flags, QDict *child_options, ++static void vvfat_qcow_options(BdrvChildRole role, ++ int *child_flags, QDict *child_options, + int parent_flags, QDict *parent_options) + { + qdict_set_default_str(child_options, BDRV_OPT_READ_ONLY, "off"); +diff --git a/include/block/block_int.h b/include/block/block_int.h +index dc4bc486d6..8c1160a577 100644 +--- a/include/block/block_int.h ++++ b/include/block/block_int.h +@@ -677,7 +677,8 @@ struct BdrvChildClass { + * non-BDS parents. */ + bool parent_is_bds; + +- void (*inherit_options)(int *child_flags, QDict *child_options, ++ void (*inherit_options)(BdrvChildRole role, ++ int *child_flags, QDict *child_options, + int parent_flags, QDict *parent_options); + + void (*change_media)(BdrvChild *child, bool load); +-- +2.23.0 + diff --git a/block-Pass-BdrvChildRole-to-bdrv_child_perm.patch b/block-Pass-BdrvChildRole-to-bdrv_child_perm.patch new file mode 100644 index 0000000000000000000000000000000000000000..22d37be318733c1d92505e5757af129fde73aafb --- /dev/null +++ b/block-Pass-BdrvChildRole-to-bdrv_child_perm.patch @@ -0,0 +1,345 @@ +From bf8e925eb569f31466eb5c9d935959a58772eec6 Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Wed, 13 May 2020 13:05:16 +0200 +Subject: [PATCH 538/709] block: Pass BdrvChildRole to bdrv_child_perm() + +For now, all callers pass 0 and no callee evaluates this value. Later +patches will change both. + +Signed-off-by: Max Reitz +Reviewed-by: Eric Blake +Message-Id: <20200513110544.176672-7-mreitz@redhat.com> +Signed-off-by: Kevin Wolf +--- + block.c | 22 ++++++++++++---------- + block/backup-top.c | 3 ++- + block/blkdebug.c | 5 +++-- + block/blklogwrites.c | 9 +++++---- + block/commit.c | 1 + + block/copy-on-read.c | 1 + + block/mirror.c | 1 + + block/quorum.c | 1 + + block/replication.c | 1 + + block/vvfat.c | 1 + + include/block/block_int.h | 5 ++++- + tests/test-bdrv-drain.c | 5 +++-- + tests/test-bdrv-graph-mod.c | 1 + + 13 files changed, 36 insertions(+), 20 deletions(-) + +diff --git a/block.c b/block.c +index 14810e0426..5d9a331f5b 100644 +--- a/block.c ++++ b/block.c +@@ -1954,12 +1954,12 @@ bool bdrv_is_writable(BlockDriverState *bs) + + static void bdrv_child_perm(BlockDriverState *bs, BlockDriverState *child_bs, + BdrvChild *c, const BdrvChildClass *child_class, +- BlockReopenQueue *reopen_queue, ++ BdrvChildRole role, BlockReopenQueue *reopen_queue, + uint64_t parent_perm, uint64_t parent_shared, + uint64_t *nperm, uint64_t *nshared) + { + assert(bs->drv && bs->drv->bdrv_child_perm); +- bs->drv->bdrv_child_perm(bs, c, child_class, reopen_queue, ++ bs->drv->bdrv_child_perm(bs, c, child_class, role, reopen_queue, + parent_perm, parent_shared, + nperm, nshared); + /* TODO Take force_share from reopen_queue */ +@@ -2053,7 +2053,7 @@ static int bdrv_check_perm(BlockDriverState *bs, BlockReopenQueue *q, + uint64_t cur_perm, cur_shared; + bool child_tighten_restr; + +- bdrv_child_perm(bs, c->bs, c, c->klass, q, ++ bdrv_child_perm(bs, c->bs, c, c->klass, c->role, q, + cumulative_perms, cumulative_shared_perms, + &cur_perm, &cur_shared); + ret = bdrv_child_check_perm(c, q, cur_perm, cur_shared, ignore_children, +@@ -2120,7 +2120,7 @@ static void bdrv_set_perm(BlockDriverState *bs, uint64_t cumulative_perms, + /* Update all children */ + QLIST_FOREACH(c, &bs->children, next) { + uint64_t cur_perm, cur_shared; +- bdrv_child_perm(bs, c->bs, c, c->klass, NULL, ++ bdrv_child_perm(bs, c->bs, c, c->klass, c->role, NULL, + cumulative_perms, cumulative_shared_perms, + &cur_perm, &cur_shared); + bdrv_child_set_perm(c, cur_perm, cur_shared); +@@ -2348,14 +2348,15 @@ int bdrv_child_refresh_perms(BlockDriverState *bs, BdrvChild *c, Error **errp) + uint64_t perms, shared; + + bdrv_get_cumulative_perm(bs, &parent_perms, &parent_shared); +- bdrv_child_perm(bs, c->bs, c, c->klass, NULL, parent_perms, parent_shared, +- &perms, &shared); ++ bdrv_child_perm(bs, c->bs, c, c->klass, c->role, NULL, ++ parent_perms, parent_shared, &perms, &shared); + + return bdrv_child_try_set_perm(c, perms, shared, errp); + } + + void bdrv_filter_default_perms(BlockDriverState *bs, BdrvChild *c, + const BdrvChildClass *child_class, ++ BdrvChildRole role, + BlockReopenQueue *reopen_queue, + uint64_t perm, uint64_t shared, + uint64_t *nperm, uint64_t *nshared) +@@ -2366,6 +2367,7 @@ void bdrv_filter_default_perms(BlockDriverState *bs, BdrvChild *c, + + void bdrv_format_default_perms(BlockDriverState *bs, BdrvChild *c, + const BdrvChildClass *child_class, ++ BdrvChildRole role, + BlockReopenQueue *reopen_queue, + uint64_t perm, uint64_t shared, + uint64_t *nperm, uint64_t *nshared) +@@ -2378,7 +2380,7 @@ void bdrv_format_default_perms(BlockDriverState *bs, BdrvChild *c, + + /* Apart from the modifications below, the same permissions are + * forwarded and left alone as for filters */ +- bdrv_filter_default_perms(bs, c, child_class, reopen_queue, ++ bdrv_filter_default_perms(bs, c, child_class, role, reopen_queue, + perm, shared, &perm, &shared); + + /* Format drivers may touch metadata even if the guest doesn't write */ +@@ -2655,7 +2657,7 @@ BdrvChild *bdrv_attach_child(BlockDriverState *parent_bs, + bdrv_get_cumulative_perm(parent_bs, &perm, &shared_perm); + + assert(parent_bs->drv); +- bdrv_child_perm(parent_bs, child_bs, NULL, child_class, NULL, ++ bdrv_child_perm(parent_bs, child_bs, NULL, child_class, child_role, NULL, + perm, shared_perm, &perm, &shared_perm); + + child = bdrv_root_attach_child(child_bs, child_name, child_class, +@@ -3683,7 +3685,7 @@ int bdrv_reopen_multiple(BlockReopenQueue *bs_queue, Error **errp) + if (state->replace_backing_bs && state->new_backing_bs) { + uint64_t nperm, nshared; + bdrv_child_perm(state->bs, state->new_backing_bs, +- NULL, &child_backing, bs_queue, ++ NULL, &child_backing, 0, bs_queue, + state->perm, state->shared_perm, + &nperm, &nshared); + ret = bdrv_check_update_perm(state->new_backing_bs, NULL, +@@ -3806,7 +3808,7 @@ static void bdrv_reopen_perm(BlockReopenQueue *q, BlockDriverState *bs, + } else { + uint64_t nperm, nshared; + +- bdrv_child_perm(parent->state.bs, bs, c, c->klass, q, ++ bdrv_child_perm(parent->state.bs, bs, c, c->klass, c->role, q, + parent->state.perm, parent->state.shared_perm, + &nperm, &nshared); + +diff --git a/block/backup-top.c b/block/backup-top.c +index f891dd7838..e2b4d2acd3 100644 +--- a/block/backup-top.c ++++ b/block/backup-top.c +@@ -123,6 +123,7 @@ static void backup_top_refresh_filename(BlockDriverState *bs) + + static void backup_top_child_perm(BlockDriverState *bs, BdrvChild *c, + const BdrvChildClass *child_class, ++ BdrvChildRole role, + BlockReopenQueue *reopen_queue, + uint64_t perm, uint64_t shared, + uint64_t *nperm, uint64_t *nshared) +@@ -155,7 +156,7 @@ static void backup_top_child_perm(BlockDriverState *bs, BdrvChild *c, + *nperm = BLK_PERM_WRITE; + } else { + /* Source child */ +- bdrv_filter_default_perms(bs, c, child_class, reopen_queue, ++ bdrv_filter_default_perms(bs, c, child_class, role, reopen_queue, + perm, shared, nperm, nshared); + + if (perm & BLK_PERM_WRITE) { +diff --git a/block/blkdebug.c b/block/blkdebug.c +index c91e78d5c8..8dd8ed6055 100644 +--- a/block/blkdebug.c ++++ b/block/blkdebug.c +@@ -994,14 +994,15 @@ static int blkdebug_reopen_prepare(BDRVReopenState *reopen_state, + + static void blkdebug_child_perm(BlockDriverState *bs, BdrvChild *c, + const BdrvChildClass *child_class, ++ BdrvChildRole role, + BlockReopenQueue *reopen_queue, + uint64_t perm, uint64_t shared, + uint64_t *nperm, uint64_t *nshared) + { + BDRVBlkdebugState *s = bs->opaque; + +- bdrv_filter_default_perms(bs, c, child_class, reopen_queue, perm, shared, +- nperm, nshared); ++ bdrv_filter_default_perms(bs, c, child_class, role, reopen_queue, ++ perm, shared, nperm, nshared); + + *nperm |= s->take_child_perms; + *nshared &= ~s->unshare_child_perms; +diff --git a/block/blklogwrites.c b/block/blklogwrites.c +index 739db6dcf6..4faf912ef1 100644 +--- a/block/blklogwrites.c ++++ b/block/blklogwrites.c +@@ -283,6 +283,7 @@ static int64_t blk_log_writes_getlength(BlockDriverState *bs) + + static void blk_log_writes_child_perm(BlockDriverState *bs, BdrvChild *c, + const BdrvChildClass *child_class, ++ BdrvChildRole role, + BlockReopenQueue *ro_q, + uint64_t perm, uint64_t shrd, + uint64_t *nperm, uint64_t *nshrd) +@@ -294,11 +295,11 @@ static void blk_log_writes_child_perm(BlockDriverState *bs, BdrvChild *c, + } + + if (!strcmp(c->name, "log")) { +- bdrv_format_default_perms(bs, c, child_class, ro_q, perm, shrd, nperm, +- nshrd); ++ bdrv_format_default_perms(bs, c, child_class, role, ro_q, perm, shrd, ++ nperm, nshrd); + } else { +- bdrv_filter_default_perms(bs, c, child_class, ro_q, perm, shrd, nperm, +- nshrd); ++ bdrv_filter_default_perms(bs, c, child_class, role, ro_q, perm, shrd, ++ nperm, nshrd); + } + } + +diff --git a/block/commit.c b/block/commit.c +index 834eeae412..6af1c808bc 100644 +--- a/block/commit.c ++++ b/block/commit.c +@@ -224,6 +224,7 @@ static void bdrv_commit_top_refresh_filename(BlockDriverState *bs) + + static void bdrv_commit_top_child_perm(BlockDriverState *bs, BdrvChild *c, + const BdrvChildClass *child_class, ++ BdrvChildRole role, + BlockReopenQueue *reopen_queue, + uint64_t perm, uint64_t shared, + uint64_t *nperm, uint64_t *nshared) +diff --git a/block/copy-on-read.c b/block/copy-on-read.c +index a2c4e6dc58..a2d92ac394 100644 +--- a/block/copy-on-read.c ++++ b/block/copy-on-read.c +@@ -52,6 +52,7 @@ static int cor_open(BlockDriverState *bs, QDict *options, int flags, + + static void cor_child_perm(BlockDriverState *bs, BdrvChild *c, + const BdrvChildClass *child_class, ++ BdrvChildRole role, + BlockReopenQueue *reopen_queue, + uint64_t perm, uint64_t shared, + uint64_t *nperm, uint64_t *nshared) +diff --git a/block/mirror.c b/block/mirror.c +index d6598463d5..cb4bdad32a 100644 +--- a/block/mirror.c ++++ b/block/mirror.c +@@ -1493,6 +1493,7 @@ static void bdrv_mirror_top_refresh_filename(BlockDriverState *bs) + + static void bdrv_mirror_top_child_perm(BlockDriverState *bs, BdrvChild *c, + const BdrvChildClass *child_class, ++ BdrvChildRole role, + BlockReopenQueue *reopen_queue, + uint64_t perm, uint64_t shared, + uint64_t *nperm, uint64_t *nshared) +diff --git a/block/quorum.c b/block/quorum.c +index 024de76e6f..d37b77a522 100644 +--- a/block/quorum.c ++++ b/block/quorum.c +@@ -1152,6 +1152,7 @@ static char *quorum_dirname(BlockDriverState *bs, Error **errp) + + static void quorum_child_perm(BlockDriverState *bs, BdrvChild *c, + const BdrvChildClass *child_class, ++ BdrvChildRole role, + BlockReopenQueue *reopen_queue, + uint64_t perm, uint64_t shared, + uint64_t *nperm, uint64_t *nshared) +diff --git a/block/replication.c b/block/replication.c +index 052c7ef601..ea87b1a4f0 100644 +--- a/block/replication.c ++++ b/block/replication.c +@@ -164,6 +164,7 @@ static void replication_close(BlockDriverState *bs) + + static void replication_child_perm(BlockDriverState *bs, BdrvChild *c, + const BdrvChildClass *child_class, ++ BdrvChildRole role, + BlockReopenQueue *reopen_queue, + uint64_t perm, uint64_t shared, + uint64_t *nperm, uint64_t *nshared) +diff --git a/block/vvfat.c b/block/vvfat.c +index cd8ae50a2c..6cf3c74fe3 100644 +--- a/block/vvfat.c ++++ b/block/vvfat.c +@@ -3211,6 +3211,7 @@ err: + + static void vvfat_child_perm(BlockDriverState *bs, BdrvChild *c, + const BdrvChildClass *child_class, ++ BdrvChildRole role, + BlockReopenQueue *reopen_queue, + uint64_t perm, uint64_t shared, + uint64_t *nperm, uint64_t *nshared) +diff --git a/include/block/block_int.h b/include/block/block_int.h +index 1c6641c17a..dc4bc486d6 100644 +--- a/include/block/block_int.h ++++ b/include/block/block_int.h +@@ -556,7 +556,7 @@ struct BlockDriver { + * the parents in @parent_perm and @parent_shared. + * + * If @c is NULL, return the permissions for attaching a new child for the +- * given @child_class. ++ * given @child_class and @role. + * + * If @reopen_queue is non-NULL, don't return the currently needed + * permissions, but those that will be needed after applying the +@@ -564,6 +564,7 @@ struct BlockDriver { + */ + void (*bdrv_child_perm)(BlockDriverState *bs, BdrvChild *c, + const BdrvChildClass *child_class, ++ BdrvChildRole role, + BlockReopenQueue *reopen_queue, + uint64_t parent_perm, uint64_t parent_shared, + uint64_t *nperm, uint64_t *nshared); +@@ -1266,6 +1267,7 @@ int bdrv_child_refresh_perms(BlockDriverState *bs, BdrvChild *c, Error **errp); + * all children */ + void bdrv_filter_default_perms(BlockDriverState *bs, BdrvChild *c, + const BdrvChildClass *child_class, ++ BdrvChildRole child_role, + BlockReopenQueue *reopen_queue, + uint64_t perm, uint64_t shared, + uint64_t *nperm, uint64_t *nshared); +@@ -1276,6 +1278,7 @@ void bdrv_filter_default_perms(BlockDriverState *bs, BdrvChild *c, + * CONSISTENT_READ and doesn't share WRITE. */ + void bdrv_format_default_perms(BlockDriverState *bs, BdrvChild *c, + const BdrvChildClass *child_class, ++ BdrvChildRole child_role, + BlockReopenQueue *reopen_queue, + uint64_t perm, uint64_t shared, + uint64_t *nperm, uint64_t *nshared); +diff --git a/tests/test-bdrv-drain.c b/tests/test-bdrv-drain.c +index c03705ea37..b3d7960bd0 100644 +--- a/tests/test-bdrv-drain.c ++++ b/tests/test-bdrv-drain.c +@@ -87,6 +87,7 @@ static int coroutine_fn bdrv_test_co_preadv(BlockDriverState *bs, + + static void bdrv_test_child_perm(BlockDriverState *bs, BdrvChild *c, + const BdrvChildClass *child_class, ++ BdrvChildRole role, + BlockReopenQueue *reopen_queue, + uint64_t perm, uint64_t shared, + uint64_t *nperm, uint64_t *nshared) +@@ -99,8 +100,8 @@ static void bdrv_test_child_perm(BlockDriverState *bs, BdrvChild *c, + child_class = &child_file; + } + +- bdrv_format_default_perms(bs, c, child_class, reopen_queue, perm, shared, +- nperm, nshared); ++ bdrv_format_default_perms(bs, c, child_class, role, reopen_queue, ++ perm, shared, nperm, nshared); + } + + static int bdrv_test_change_backing_file(BlockDriverState *bs, +diff --git a/tests/test-bdrv-graph-mod.c b/tests/test-bdrv-graph-mod.c +index 8b8c186c9f..3707e2533c 100644 +--- a/tests/test-bdrv-graph-mod.c ++++ b/tests/test-bdrv-graph-mod.c +@@ -31,6 +31,7 @@ static BlockDriver bdrv_pass_through = { + + static void no_perm_default_perms(BlockDriverState *bs, BdrvChild *c, + const BdrvChildClass *child_class, ++ BdrvChildRole role, + BlockReopenQueue *reopen_queue, + uint64_t perm, uint64_t shared, + uint64_t *nperm, uint64_t *nshared) +-- +2.23.0 + diff --git a/block-Pass-parent_is_format-to-.inherit_options.patch b/block-Pass-parent_is_format-to-.inherit_options.patch new file mode 100644 index 0000000000000000000000000000000000000000..8d200e5421edfdc9e3ce03c9a21f8e7d1d0c34d3 --- /dev/null +++ b/block-Pass-parent_is_format-to-.inherit_options.patch @@ -0,0 +1,173 @@ +From 3cdc69d31b49bed603adc973cf06ac898a9b2914 Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Wed, 13 May 2020 13:05:18 +0200 +Subject: [PATCH 540/709] block: Pass parent_is_format to .inherit_options() + +We plan to unify the generic .inherit_options() functions. The +resulting common function will need to decide whether to force-enable +format probing, force-disable it, or leave it as-is. To make this +decision, it will need to know whether the parent node is a format node +or not (because we never want format probing if the parent is a format +node already (except for the backing chain)). + +Signed-off-by: Max Reitz +Reviewed-by: Eric Blake +Message-Id: <20200513110544.176672-9-mreitz@redhat.com> +Signed-off-by: Kevin Wolf +--- + block.c | 37 +++++++++++++++++++++++++++---------- + block/block-backend.c | 2 +- + block/vvfat.c | 2 +- + include/block/block_int.h | 2 +- + 4 files changed, 30 insertions(+), 13 deletions(-) + +diff --git a/block.c b/block.c +index 40db0b78b9..b78e2dc141 100644 +--- a/block.c ++++ b/block.c +@@ -1154,7 +1154,7 @@ static void bdrv_temp_snapshot_options(int *child_flags, QDict *child_options, + * Returns the options and flags that bs->file should get if a protocol driver + * is expected, based on the given options and flags for the parent BDS + */ +-static void bdrv_inherited_options(BdrvChildRole role, ++static void bdrv_inherited_options(BdrvChildRole role, bool parent_is_format, + int *child_flags, QDict *child_options, + int parent_flags, QDict *parent_options) + { +@@ -1205,10 +1205,12 @@ const BdrvChildClass child_file = { + * flags for the parent BDS + */ + static void bdrv_inherited_fmt_options(BdrvChildRole role, ++ bool parent_is_format, + int *child_flags, QDict *child_options, + int parent_flags, QDict *parent_options) + { +- child_file.inherit_options(role, child_flags, child_options, ++ child_file.inherit_options(role, parent_is_format, ++ child_flags, child_options, + parent_flags, parent_options); + + *child_flags &= ~(BDRV_O_PROTOCOL | BDRV_O_NO_IO); +@@ -1289,7 +1291,7 @@ static void bdrv_backing_detach(BdrvChild *c) + * Returns the options and flags that bs->backing should get, based on the + * given options and flags for the parent BDS + */ +-static void bdrv_backing_options(BdrvChildRole role, ++static void bdrv_backing_options(BdrvChildRole role, bool parent_is_format, + int *child_flags, QDict *child_options, + int parent_flags, QDict *parent_options) + { +@@ -3173,8 +3175,22 @@ static BlockDriverState *bdrv_open_inherit(const char *filename, + bs->explicit_options = qdict_clone_shallow(options); + + if (child_class) { ++ bool parent_is_format; ++ ++ if (parent->drv) { ++ parent_is_format = parent->drv->is_format; ++ } else { ++ /* ++ * parent->drv is not set yet because this node is opened for ++ * (potential) format probing. That means that @parent is going ++ * to be a format node. ++ */ ++ parent_is_format = true; ++ } ++ + bs->inherits_from = parent; +- child_class->inherit_options(child_role, &flags, options, ++ child_class->inherit_options(child_role, parent_is_format, ++ &flags, options, + parent->open_flags, parent->options); + } + +@@ -3203,7 +3219,7 @@ static BlockDriverState *bdrv_open_inherit(const char *filename, + flags, options); + /* Let bdrv_backing_options() override "read-only" */ + qdict_del(options, BDRV_OPT_READ_ONLY); +- bdrv_backing_options(0, &flags, options, flags, options); ++ bdrv_backing_options(0, true, &flags, options, flags, options); + } + + bs->open_flags = flags; +@@ -3488,6 +3504,7 @@ static BlockReopenQueue *bdrv_reopen_queue_child(BlockReopenQueue *bs_queue, + QDict *options, + const BdrvChildClass *klass, + BdrvChildRole role, ++ bool parent_is_format, + QDict *parent_options, + int parent_flags, + bool keep_old_opts) +@@ -3543,7 +3560,7 @@ static BlockReopenQueue *bdrv_reopen_queue_child(BlockReopenQueue *bs_queue, + /* Inherit from parent node */ + if (parent_options) { + flags = 0; +- klass->inherit_options(role, &flags, options, ++ klass->inherit_options(role, parent_is_format, &flags, options, + parent_flags, parent_options); + } else { + flags = bdrv_get_flags(bs); +@@ -3635,8 +3652,8 @@ static BlockReopenQueue *bdrv_reopen_queue_child(BlockReopenQueue *bs_queue, + } + + bdrv_reopen_queue_child(bs_queue, child->bs, new_child_options, +- child->klass, child->role, options, flags, +- child_keep_old); ++ child->klass, child->role, bs->drv->is_format, ++ options, flags, child_keep_old); + } + + return bs_queue; +@@ -3646,8 +3663,8 @@ BlockReopenQueue *bdrv_reopen_queue(BlockReopenQueue *bs_queue, + BlockDriverState *bs, + QDict *options, bool keep_old_opts) + { +- return bdrv_reopen_queue_child(bs_queue, bs, options, NULL, 0, NULL, 0, +- keep_old_opts); ++ return bdrv_reopen_queue_child(bs_queue, bs, options, NULL, 0, false, ++ NULL, 0, keep_old_opts); + } + + /* +diff --git a/block/block-backend.c b/block/block-backend.c +index 5539ca8816..f2e81af27d 100644 +--- a/block/block-backend.c ++++ b/block/block-backend.c +@@ -120,7 +120,7 @@ static QTAILQ_HEAD(, BlockBackend) block_backends = + static QTAILQ_HEAD(, BlockBackend) monitor_block_backends = + QTAILQ_HEAD_INITIALIZER(monitor_block_backends); + +-static void blk_root_inherit_options(BdrvChildRole role, ++static void blk_root_inherit_options(BdrvChildRole role, bool parent_is_format, + int *child_flags, QDict *child_options, + int parent_flags, QDict *parent_options) + { +diff --git a/block/vvfat.c b/block/vvfat.c +index 4033e4f369..b4c8417dbd 100644 +--- a/block/vvfat.c ++++ b/block/vvfat.c +@@ -3128,7 +3128,7 @@ static BlockDriver vvfat_write_target = { + .bdrv_co_pwritev = write_target_commit, + }; + +-static void vvfat_qcow_options(BdrvChildRole role, ++static void vvfat_qcow_options(BdrvChildRole role, bool parent_is_format, + int *child_flags, QDict *child_options, + int parent_flags, QDict *parent_options) + { +diff --git a/include/block/block_int.h b/include/block/block_int.h +index 8c1160a577..6245d8a18d 100644 +--- a/include/block/block_int.h ++++ b/include/block/block_int.h +@@ -677,7 +677,7 @@ struct BdrvChildClass { + * non-BDS parents. */ + bool parent_is_bds; + +- void (*inherit_options)(BdrvChildRole role, ++ void (*inherit_options)(BdrvChildRole role, bool parent_is_format, + int *child_flags, QDict *child_options, + int parent_flags, QDict *parent_options); + +-- +2.23.0 + diff --git a/block-Pull-out-bdrv_default_perms_for_cow.patch b/block-Pull-out-bdrv_default_perms_for_cow.patch new file mode 100644 index 0000000000000000000000000000000000000000..517c7ccfb935429e2edd433ad4b59cfd2a91b363 --- /dev/null +++ b/block-Pull-out-bdrv_default_perms_for_cow.patch @@ -0,0 +1,102 @@ +From 70082db4efab1bc91467a9207c6e3f554a8e6bac Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Wed, 13 May 2020 13:05:26 +0200 +Subject: [PATCH 548/709] block: Pull out bdrv_default_perms_for_cow() + +Right now, bdrv_format_default_perms() is used by format parents +(generally). We want to switch to a model where most parents use a +single BdrvChildClass, which then decides the permissions based on the +child role. To do so, we have to split bdrv_format_default_perms() into +separate functions for each such role. + +Signed-off-by: Max Reitz +Message-Id: <20200513110544.176672-17-mreitz@redhat.com> +Reviewed-by: Eric Blake +Signed-off-by: Kevin Wolf +--- + block.c | 62 +++++++++++++++++++++++++++++++++++++-------------------- + 1 file changed, 40 insertions(+), 22 deletions(-) + +diff --git a/block.c b/block.c +index b3e7ae70c7..b12222a471 100644 +--- a/block.c ++++ b/block.c +@@ -2468,6 +2468,44 @@ void bdrv_filter_default_perms(BlockDriverState *bs, BdrvChild *c, + *nshared = (shared & DEFAULT_PERM_PASSTHROUGH) | DEFAULT_PERM_UNCHANGED; + } + ++static void bdrv_default_perms_for_cow(BlockDriverState *bs, BdrvChild *c, ++ const BdrvChildClass *child_class, ++ BdrvChildRole role, ++ BlockReopenQueue *reopen_queue, ++ uint64_t perm, uint64_t shared, ++ uint64_t *nperm, uint64_t *nshared) ++{ ++ assert(child_class == &child_backing || ++ (child_class == &child_of_bds && (role & BDRV_CHILD_COW))); ++ ++ /* ++ * We want consistent read from backing files if the parent needs it. ++ * No other operations are performed on backing files. ++ */ ++ perm &= BLK_PERM_CONSISTENT_READ; ++ ++ /* ++ * If the parent can deal with changing data, we're okay with a ++ * writable and resizable backing file. ++ * TODO Require !(perm & BLK_PERM_CONSISTENT_READ), too? ++ */ ++ if (shared & BLK_PERM_WRITE) { ++ shared = BLK_PERM_WRITE | BLK_PERM_RESIZE; ++ } else { ++ shared = 0; ++ } ++ ++ shared |= BLK_PERM_CONSISTENT_READ | BLK_PERM_GRAPH_MOD | ++ BLK_PERM_WRITE_UNCHANGED; ++ ++ if (bs->open_flags & BDRV_O_INACTIVE) { ++ shared |= BLK_PERM_WRITE | BLK_PERM_RESIZE; ++ } ++ ++ *nperm = perm; ++ *nshared = shared; ++} ++ + void bdrv_format_default_perms(BlockDriverState *bs, BdrvChild *c, + const BdrvChildClass *child_class, + BdrvChildRole role, +@@ -2505,28 +2543,8 @@ void bdrv_format_default_perms(BlockDriverState *bs, BdrvChild *c, + *nperm = perm; + *nshared = shared; + } else { +- /* We want consistent read from backing files if the parent needs it. +- * No other operations are performed on backing files. */ +- perm &= BLK_PERM_CONSISTENT_READ; +- +- /* If the parent can deal with changing data, we're okay with a +- * writable and resizable backing file. */ +- /* TODO Require !(perm & BLK_PERM_CONSISTENT_READ), too? */ +- if (shared & BLK_PERM_WRITE) { +- shared = BLK_PERM_WRITE | BLK_PERM_RESIZE; +- } else { +- shared = 0; +- } +- +- shared |= BLK_PERM_CONSISTENT_READ | BLK_PERM_GRAPH_MOD | +- BLK_PERM_WRITE_UNCHANGED; +- +- if (bs->open_flags & BDRV_O_INACTIVE) { +- shared |= BLK_PERM_WRITE | BLK_PERM_RESIZE; +- } +- +- *nperm = perm; +- *nshared = shared; ++ bdrv_default_perms_for_cow(bs, c, child_class, role, reopen_queue, ++ perm, shared, nperm, nshared); + } + } + +-- +2.23.0 + diff --git a/block-Pull-out-bdrv_default_perms_for_storage.patch b/block-Pull-out-bdrv_default_perms_for_storage.patch new file mode 100644 index 0000000000000000000000000000000000000000..97d0369bb77b471340ec3d71d9a690342f14a5b1 --- /dev/null +++ b/block-Pull-out-bdrv_default_perms_for_storage.patch @@ -0,0 +1,115 @@ +From 6f838a4b73d9c85e498f94c28109dde0efc1cb9d Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Wed, 13 May 2020 13:05:27 +0200 +Subject: [PATCH 549/709] block: Pull out bdrv_default_perms_for_storage() + +Right now, bdrv_format_default_perms() is used by format parents +(generally). We want to switch to a model where most parents use a +single BdrvChildClass, which then decides the permissions based on the +child role. To do so, we have to split bdrv_format_default_perms() into +separate functions for each such role. + +Note that bdrv_default_perms_for_storage() currently handles all DATA | +METADATA children. A follow-up patch is going to split it further into +one function for each case. + +Signed-off-by: Max Reitz +Reviewed-by: Eric Blake +Message-Id: <20200513110544.176672-18-mreitz@redhat.com> +Signed-off-by: Kevin Wolf +--- + block.c | 71 +++++++++++++++++++++++++++++++++++++-------------------- + 1 file changed, 46 insertions(+), 25 deletions(-) + +diff --git a/block.c b/block.c +index b12222a471..5d17aa1cc3 100644 +--- a/block.c ++++ b/block.c +@@ -2506,6 +2506,50 @@ static void bdrv_default_perms_for_cow(BlockDriverState *bs, BdrvChild *c, + *nshared = shared; + } + ++static void bdrv_default_perms_for_storage(BlockDriverState *bs, BdrvChild *c, ++ const BdrvChildClass *child_class, ++ BdrvChildRole role, ++ BlockReopenQueue *reopen_queue, ++ uint64_t perm, uint64_t shared, ++ uint64_t *nperm, uint64_t *nshared) ++{ ++ int flags; ++ ++ assert(child_class == &child_file || ++ (child_class == &child_of_bds && ++ (role & (BDRV_CHILD_METADATA | BDRV_CHILD_DATA)))); ++ ++ flags = bdrv_reopen_get_flags(reopen_queue, bs); ++ ++ /* ++ * Apart from the modifications below, the same permissions are ++ * forwarded and left alone as for filters ++ */ ++ bdrv_filter_default_perms(bs, c, child_class, role, reopen_queue, ++ perm, shared, &perm, &shared); ++ ++ /* Format drivers may touch metadata even if the guest doesn't write */ ++ if (bdrv_is_writable_after_reopen(bs, reopen_queue)) { ++ perm |= BLK_PERM_WRITE | BLK_PERM_RESIZE; ++ } ++ ++ /* ++ * bs->file always needs to be consistent because of the metadata. We ++ * can never allow other users to resize or write to it. ++ */ ++ if (!(flags & BDRV_O_NO_IO)) { ++ perm |= BLK_PERM_CONSISTENT_READ; ++ } ++ shared &= ~(BLK_PERM_WRITE | BLK_PERM_RESIZE); ++ ++ if (bs->open_flags & BDRV_O_INACTIVE) { ++ shared |= BLK_PERM_WRITE | BLK_PERM_RESIZE; ++ } ++ ++ *nperm = perm; ++ *nshared = shared; ++} ++ + void bdrv_format_default_perms(BlockDriverState *bs, BdrvChild *c, + const BdrvChildClass *child_class, + BdrvChildRole role, +@@ -2517,31 +2561,8 @@ void bdrv_format_default_perms(BlockDriverState *bs, BdrvChild *c, + assert(child_class == &child_backing || child_class == &child_file); + + if (!backing) { +- int flags = bdrv_reopen_get_flags(reopen_queue, bs); +- +- /* Apart from the modifications below, the same permissions are +- * forwarded and left alone as for filters */ +- bdrv_filter_default_perms(bs, c, child_class, role, reopen_queue, +- perm, shared, &perm, &shared); +- +- /* Format drivers may touch metadata even if the guest doesn't write */ +- if (bdrv_is_writable_after_reopen(bs, reopen_queue)) { +- perm |= BLK_PERM_WRITE | BLK_PERM_RESIZE; +- } +- +- /* bs->file always needs to be consistent because of the metadata. We +- * can never allow other users to resize or write to it. */ +- if (!(flags & BDRV_O_NO_IO)) { +- perm |= BLK_PERM_CONSISTENT_READ; +- } +- shared &= ~(BLK_PERM_WRITE | BLK_PERM_RESIZE); +- +- if (bs->open_flags & BDRV_O_INACTIVE) { +- shared |= BLK_PERM_WRITE | BLK_PERM_RESIZE; +- } +- +- *nperm = perm; +- *nshared = shared; ++ bdrv_default_perms_for_storage(bs, c, child_class, role, reopen_queue, ++ perm, shared, nperm, nshared); + } else { + bdrv_default_perms_for_cow(bs, c, child_class, role, reopen_queue, + perm, shared, nperm, nshared); +-- +2.23.0 + diff --git a/block-Relax-perms_for_storage-for-data-children.patch b/block-Relax-perms_for_storage-for-data-children.patch new file mode 100644 index 0000000000000000000000000000000000000000..58b98151ec9051aa261814a8ed04af8af64ded19 --- /dev/null +++ b/block-Relax-perms_for_storage-for-data-children.patch @@ -0,0 +1,100 @@ +From f889054f031f2f01ae97bdc7579fbdf3a30e4e0e Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Wed, 13 May 2020 13:05:28 +0200 +Subject: [PATCH 550/709] block: Relax *perms_for_storage for data children + +We can be less restrictive about pure data children than those with +metadata on them, so let bdrv_default_perms_for_storage() handle +metadata children differently from pure data children. + +As explained in the code, the restrictions on metadata children are +strictly stricter than those for pure data children, so in theory we +just have to distinguish between pure-data and all other storage +children (pure metadata or data+metadata). In practice, that is not +obvious, though, so we have two independent code paths for metadata and +for data children, and data+metadata children will go through both +(without the path for data children doing anything meaningful). + +Signed-off-by: Max Reitz +Message-Id: <20200513110544.176672-19-mreitz@redhat.com> +Reviewed-by: Eric Blake +Signed-off-by: Kevin Wolf +--- + block.c | 58 +++++++++++++++++++++++++++++++++++++++++++++++---------- + 1 file changed, 48 insertions(+), 10 deletions(-) + +diff --git a/block.c b/block.c +index 5d17aa1cc3..5ff6cbd796 100644 +--- a/block.c ++++ b/block.c +@@ -2528,19 +2528,57 @@ static void bdrv_default_perms_for_storage(BlockDriverState *bs, BdrvChild *c, + bdrv_filter_default_perms(bs, c, child_class, role, reopen_queue, + perm, shared, &perm, &shared); + +- /* Format drivers may touch metadata even if the guest doesn't write */ +- if (bdrv_is_writable_after_reopen(bs, reopen_queue)) { +- perm |= BLK_PERM_WRITE | BLK_PERM_RESIZE; ++ if (role & BDRV_CHILD_METADATA) { ++ /* Format drivers may touch metadata even if the guest doesn't write */ ++ if (bdrv_is_writable_after_reopen(bs, reopen_queue)) { ++ perm |= BLK_PERM_WRITE | BLK_PERM_RESIZE; ++ } ++ ++ /* ++ * bs->file always needs to be consistent because of the ++ * metadata. We can never allow other users to resize or write ++ * to it. ++ */ ++ if (!(flags & BDRV_O_NO_IO)) { ++ perm |= BLK_PERM_CONSISTENT_READ; ++ } ++ shared &= ~(BLK_PERM_WRITE | BLK_PERM_RESIZE); + } + +- /* +- * bs->file always needs to be consistent because of the metadata. We +- * can never allow other users to resize or write to it. +- */ +- if (!(flags & BDRV_O_NO_IO)) { +- perm |= BLK_PERM_CONSISTENT_READ; ++ if (role & BDRV_CHILD_DATA) { ++ /* ++ * Technically, everything in this block is a subset of the ++ * BDRV_CHILD_METADATA path taken above, and so this could ++ * be an "else if" branch. However, that is not obvious, and ++ * this function is not performance critical, therefore we let ++ * this be an independent "if". ++ */ ++ ++ /* ++ * We cannot allow other users to resize the file because the ++ * format driver might have some assumptions about the size ++ * (e.g. because it is stored in metadata, or because the file ++ * is split into fixed-size data files). ++ */ ++ shared &= ~BLK_PERM_RESIZE; ++ ++ /* ++ * WRITE_UNCHANGED often cannot be performed as such on the ++ * data file. For example, the qcow2 driver may still need to ++ * write copied clusters on copy-on-read. ++ */ ++ if (perm & BLK_PERM_WRITE_UNCHANGED) { ++ perm |= BLK_PERM_WRITE; ++ } ++ ++ /* ++ * If the data file is written to, the format driver may ++ * expect to be able to resize it by writing beyond the EOF. ++ */ ++ if (perm & BLK_PERM_WRITE) { ++ perm |= BLK_PERM_RESIZE; ++ } + } +- shared &= ~(BLK_PERM_WRITE | BLK_PERM_RESIZE); + + if (bs->open_flags & BDRV_O_INACTIVE) { + shared |= BLK_PERM_WRITE | BLK_PERM_RESIZE; +-- +2.23.0 + diff --git a/block-Rename-BdrvChildRole-to-BdrvChildClass.patch b/block-Rename-BdrvChildRole-to-BdrvChildClass.patch new file mode 100644 index 0000000000000000000000000000000000000000..46f4aa1ce395e247ac4e5d79e56e27562ecb5701 --- /dev/null +++ b/block-Rename-BdrvChildRole-to-BdrvChildClass.patch @@ -0,0 +1,1052 @@ +From bd86fb990cfedc50d9705b8ed31d183f01942035 Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Wed, 13 May 2020 13:05:13 +0200 +Subject: [PATCH 535/709] block: Rename BdrvChildRole to BdrvChildClass + +This structure nearly only contains parent callbacks for child state +changes. It cannot really reflect a child's role, because different +roles may overlap (as we will see when real roles are introduced), and +because parents can have custom callbacks even when the child fulfills a +standard role. + +Signed-off-by: Max Reitz +Reviewed-by: Eric Blake +Reviewed-by: Alberto Garcia +Message-Id: <20200513110544.176672-4-mreitz@redhat.com> +Signed-off-by: Kevin Wolf +--- + block.c | 142 ++++++++++++++++++------------------ + block/backup-top.c | 8 +- + block/blkdebug.c | 4 +- + block/blklogwrites.c | 8 +- + block/block-backend.c | 6 +- + block/commit.c | 2 +- + block/copy-on-read.c | 2 +- + block/io.c | 22 +++--- + block/mirror.c | 2 +- + block/quorum.c | 2 +- + block/replication.c | 2 +- + block/vvfat.c | 6 +- + blockjob.c | 2 +- + include/block/block.h | 6 +- + include/block/block_int.h | 22 +++--- + tests/test-bdrv-drain.c | 36 ++++----- + tests/test-bdrv-graph-mod.c | 2 +- + 17 files changed, 141 insertions(+), 133 deletions(-) + +diff --git a/block.c b/block.c +index c6a5c144b7..0ce9b61c97 100644 +--- a/block.c ++++ b/block.c +@@ -76,7 +76,7 @@ static BlockDriverState *bdrv_open_inherit(const char *filename, + const char *reference, + QDict *options, int flags, + BlockDriverState *parent, +- const BdrvChildRole *child_role, ++ const BdrvChildClass *child_class, + Error **errp); + + /* If non-zero, use only whitelisted block drivers */ +@@ -1183,7 +1183,7 @@ static void bdrv_inherited_options(int *child_flags, QDict *child_options, + *child_flags = flags; + } + +-const BdrvChildRole child_file = { ++const BdrvChildClass child_file = { + .parent_is_bds = true, + .get_parent_desc = bdrv_child_get_parent_desc, + .inherit_options = bdrv_inherited_options, +@@ -1211,7 +1211,7 @@ static void bdrv_inherited_fmt_options(int *child_flags, QDict *child_options, + *child_flags &= ~(BDRV_O_PROTOCOL | BDRV_O_NO_IO); + } + +-const BdrvChildRole child_format = { ++const BdrvChildClass child_format = { + .parent_is_bds = true, + .get_parent_desc = bdrv_child_get_parent_desc, + .inherit_options = bdrv_inherited_fmt_options, +@@ -1335,7 +1335,7 @@ static int bdrv_backing_update_filename(BdrvChild *c, BlockDriverState *base, + return ret; + } + +-const BdrvChildRole child_backing = { ++const BdrvChildClass child_backing = { + .parent_is_bds = true, + .get_parent_desc = bdrv_child_get_parent_desc, + .attach = bdrv_backing_attach, +@@ -1953,13 +1953,13 @@ bool bdrv_is_writable(BlockDriverState *bs) + } + + static void bdrv_child_perm(BlockDriverState *bs, BlockDriverState *child_bs, +- BdrvChild *c, const BdrvChildRole *role, ++ BdrvChild *c, const BdrvChildClass *child_class, + BlockReopenQueue *reopen_queue, + uint64_t parent_perm, uint64_t parent_shared, + uint64_t *nperm, uint64_t *nshared) + { + assert(bs->drv && bs->drv->bdrv_child_perm); +- bs->drv->bdrv_child_perm(bs, c, role, reopen_queue, ++ bs->drv->bdrv_child_perm(bs, c, child_class, reopen_queue, + parent_perm, parent_shared, + nperm, nshared); + /* TODO Take force_share from reopen_queue */ +@@ -2053,7 +2053,7 @@ static int bdrv_check_perm(BlockDriverState *bs, BlockReopenQueue *q, + uint64_t cur_perm, cur_shared; + bool child_tighten_restr; + +- bdrv_child_perm(bs, c->bs, c, c->role, q, ++ bdrv_child_perm(bs, c->bs, c, c->klass, q, + cumulative_perms, cumulative_shared_perms, + &cur_perm, &cur_shared); + ret = bdrv_child_check_perm(c, q, cur_perm, cur_shared, ignore_children, +@@ -2120,7 +2120,7 @@ static void bdrv_set_perm(BlockDriverState *bs, uint64_t cumulative_perms, + /* Update all children */ + QLIST_FOREACH(c, &bs->children, next) { + uint64_t cur_perm, cur_shared; +- bdrv_child_perm(bs, c->bs, c, c->role, NULL, ++ bdrv_child_perm(bs, c->bs, c, c->klass, NULL, + cumulative_perms, cumulative_shared_perms, + &cur_perm, &cur_shared); + bdrv_child_set_perm(c, cur_perm, cur_shared); +@@ -2145,8 +2145,8 @@ void bdrv_get_cumulative_perm(BlockDriverState *bs, uint64_t *perm, + + static char *bdrv_child_user_desc(BdrvChild *c) + { +- if (c->role->get_parent_desc) { +- return c->role->get_parent_desc(c); ++ if (c->klass->get_parent_desc) { ++ return c->klass->get_parent_desc(c); + } + + return g_strdup("another user"); +@@ -2348,14 +2348,14 @@ int bdrv_child_refresh_perms(BlockDriverState *bs, BdrvChild *c, Error **errp) + uint64_t perms, shared; + + bdrv_get_cumulative_perm(bs, &parent_perms, &parent_shared); +- bdrv_child_perm(bs, c->bs, c, c->role, NULL, parent_perms, parent_shared, ++ bdrv_child_perm(bs, c->bs, c, c->klass, NULL, parent_perms, parent_shared, + &perms, &shared); + + return bdrv_child_try_set_perm(c, perms, shared, errp); + } + + void bdrv_filter_default_perms(BlockDriverState *bs, BdrvChild *c, +- const BdrvChildRole *role, ++ const BdrvChildClass *child_class, + BlockReopenQueue *reopen_queue, + uint64_t perm, uint64_t shared, + uint64_t *nperm, uint64_t *nshared) +@@ -2365,21 +2365,21 @@ void bdrv_filter_default_perms(BlockDriverState *bs, BdrvChild *c, + } + + void bdrv_format_default_perms(BlockDriverState *bs, BdrvChild *c, +- const BdrvChildRole *role, ++ const BdrvChildClass *child_class, + BlockReopenQueue *reopen_queue, + uint64_t perm, uint64_t shared, + uint64_t *nperm, uint64_t *nshared) + { +- bool backing = (role == &child_backing); +- assert(role == &child_backing || role == &child_file); ++ bool backing = (child_class == &child_backing); ++ assert(child_class == &child_backing || child_class == &child_file); + + if (!backing) { + int flags = bdrv_reopen_get_flags(reopen_queue, bs); + + /* Apart from the modifications below, the same permissions are + * forwarded and left alone as for filters */ +- bdrv_filter_default_perms(bs, c, role, reopen_queue, perm, shared, +- &perm, &shared); ++ bdrv_filter_default_perms(bs, c, child_class, reopen_queue, ++ perm, shared, &perm, &shared); + + /* Format drivers may touch metadata even if the guest doesn't write */ + if (bdrv_is_writable_after_reopen(bs, reopen_queue)) { +@@ -2456,7 +2456,7 @@ static void bdrv_replace_child_noperm(BdrvChild *child, + * If the new child node is drained but the old one was not, flush + * all outstanding requests to the old child node. + */ +- while (drain_saldo > 0 && child->role->drained_begin) { ++ while (drain_saldo > 0 && child->klass->drained_begin) { + bdrv_parent_drained_begin_single(child, true); + drain_saldo--; + } +@@ -2465,8 +2465,8 @@ static void bdrv_replace_child_noperm(BdrvChild *child, + /* Detach first so that the recursive drain sections coming from @child + * are already gone and we only end the drain sections that came from + * elsewhere. */ +- if (child->role->detach) { +- child->role->detach(child); ++ if (child->klass->detach) { ++ child->klass->detach(child); + } + QLIST_REMOVE(child, next_parent); + } +@@ -2488,8 +2488,8 @@ static void bdrv_replace_child_noperm(BdrvChild *child, + /* Attach only after starting new drained sections, so that recursive + * drain sections coming from @child don't get an extra .drained_begin + * callback. */ +- if (child->role->attach) { +- child->role->attach(child); ++ if (child->klass->attach) { ++ child->klass->attach(child); + } + } + +@@ -2497,7 +2497,7 @@ static void bdrv_replace_child_noperm(BdrvChild *child, + * If the old child node was drained but the new one is not, allow + * requests to come in only after the new node has been attached. + */ +- while (drain_saldo < 0 && child->role->drained_end) { ++ while (drain_saldo < 0 && child->klass->drained_end) { + bdrv_parent_drained_end_single(child); + drain_saldo++; + } +@@ -2570,7 +2570,7 @@ static void bdrv_replace_child(BdrvChild *child, BlockDriverState *new_bs) + */ + BdrvChild *bdrv_root_attach_child(BlockDriverState *child_bs, + const char *child_name, +- const BdrvChildRole *child_role, ++ const BdrvChildClass *child_class, + AioContext *ctx, + uint64_t perm, uint64_t shared_perm, + void *opaque, Error **errp) +@@ -2591,7 +2591,7 @@ BdrvChild *bdrv_root_attach_child(BlockDriverState *child_bs, + *child = (BdrvChild) { + .bs = NULL, + .name = g_strdup(child_name), +- .role = child_role, ++ .klass = child_class, + .perm = perm, + .shared_perm = shared_perm, + .opaque = opaque, +@@ -2602,15 +2602,15 @@ BdrvChild *bdrv_root_attach_child(BlockDriverState *child_bs, + * try moving the parent into the AioContext of child_bs instead. */ + if (bdrv_get_aio_context(child_bs) != ctx) { + ret = bdrv_try_set_aio_context(child_bs, ctx, &local_err); +- if (ret < 0 && child_role->can_set_aio_ctx) { ++ if (ret < 0 && child_class->can_set_aio_ctx) { + GSList *ignore = g_slist_prepend(NULL, child); + ctx = bdrv_get_aio_context(child_bs); +- if (child_role->can_set_aio_ctx(child, ctx, &ignore, NULL)) { ++ if (child_class->can_set_aio_ctx(child, ctx, &ignore, NULL)) { + error_free(local_err); + ret = 0; + g_slist_free(ignore); + ignore = g_slist_prepend(NULL, child); +- child_role->set_aio_ctx(child, ctx, &ignore); ++ child_class->set_aio_ctx(child, ctx, &ignore); + } + g_slist_free(ignore); + } +@@ -2643,7 +2643,7 @@ BdrvChild *bdrv_root_attach_child(BlockDriverState *child_bs, + BdrvChild *bdrv_attach_child(BlockDriverState *parent_bs, + BlockDriverState *child_bs, + const char *child_name, +- const BdrvChildRole *child_role, ++ const BdrvChildClass *child_class, + Error **errp) + { + BdrvChild *child; +@@ -2652,10 +2652,10 @@ BdrvChild *bdrv_attach_child(BlockDriverState *parent_bs, + bdrv_get_cumulative_perm(parent_bs, &perm, &shared_perm); + + assert(parent_bs->drv); +- bdrv_child_perm(parent_bs, child_bs, NULL, child_role, NULL, ++ bdrv_child_perm(parent_bs, child_bs, NULL, child_class, NULL, + perm, shared_perm, &perm, &shared_perm); + +- child = bdrv_root_attach_child(child_bs, child_name, child_role, ++ child = bdrv_root_attach_child(child_bs, child_name, child_class, + bdrv_get_aio_context(parent_bs), + perm, shared_perm, parent_bs, errp); + if (child == NULL) { +@@ -2728,8 +2728,8 @@ static void bdrv_parent_cb_change_media(BlockDriverState *bs, bool load) + { + BdrvChild *c; + QLIST_FOREACH(c, &bs->parents, next_parent) { +- if (c->role->change_media) { +- c->role->change_media(c, load); ++ if (c->klass->change_media) { ++ c->klass->change_media(c, load); + } + } + } +@@ -2905,7 +2905,7 @@ free_exit: + + static BlockDriverState * + bdrv_open_child_bs(const char *filename, QDict *options, const char *bdref_key, +- BlockDriverState *parent, const BdrvChildRole *child_role, ++ BlockDriverState *parent, const BdrvChildClass *child_class, + bool allow_none, Error **errp) + { + BlockDriverState *bs = NULL; +@@ -2913,7 +2913,7 @@ bdrv_open_child_bs(const char *filename, QDict *options, const char *bdref_key, + char *bdref_key_dot; + const char *reference; + +- assert(child_role != NULL); ++ assert(child_class != NULL); + + bdref_key_dot = g_strdup_printf("%s.", bdref_key); + qdict_extract_subqdict(options, &image_options, bdref_key_dot); +@@ -2937,7 +2937,7 @@ bdrv_open_child_bs(const char *filename, QDict *options, const char *bdref_key, + } + + bs = bdrv_open_inherit(filename, reference, image_options, 0, +- parent, child_role, errp); ++ parent, child_class, errp); + if (!bs) { + goto done; + } +@@ -2964,22 +2964,24 @@ done: + BdrvChild *bdrv_open_child(const char *filename, + QDict *options, const char *bdref_key, + BlockDriverState *parent, +- const BdrvChildRole *child_role, ++ const BdrvChildClass *child_class, + bool allow_none, Error **errp) + { + BlockDriverState *bs; + +- bs = bdrv_open_child_bs(filename, options, bdref_key, parent, child_role, ++ bs = bdrv_open_child_bs(filename, options, bdref_key, parent, child_class, + allow_none, errp); + if (bs == NULL) { + return NULL; + } + +- return bdrv_attach_child(parent, bs, bdref_key, child_role, errp); ++ return bdrv_attach_child(parent, bs, bdref_key, child_class, errp); + } + +-/* TODO Future callers may need to specify parent/child_role in order for +- * option inheritance to work. Existing callers use it for the root node. */ ++/* ++ * TODO Future callers may need to specify parent/child_class in order for ++ * option inheritance to work. Existing callers use it for the root node. ++ */ + BlockDriverState *bdrv_open_blockdev_ref(BlockdevRef *ref, Error **errp) + { + BlockDriverState *bs = NULL; +@@ -3107,7 +3109,7 @@ static BlockDriverState *bdrv_open_inherit(const char *filename, + const char *reference, + QDict *options, int flags, + BlockDriverState *parent, +- const BdrvChildRole *child_role, ++ const BdrvChildClass *child_class, + Error **errp) + { + int ret; +@@ -3121,8 +3123,8 @@ static BlockDriverState *bdrv_open_inherit(const char *filename, + QDict *snapshot_options = NULL; + int snapshot_flags = 0; + +- assert(!child_role || !flags); +- assert(!child_role == !parent); ++ assert(!child_class || !flags); ++ assert(!child_class == !parent); + + if (reference) { + bool options_non_empty = options ? qdict_size(options) : false; +@@ -3158,10 +3160,10 @@ static BlockDriverState *bdrv_open_inherit(const char *filename, + + bs->explicit_options = qdict_clone_shallow(options); + +- if (child_role) { ++ if (child_class) { + bs->inherits_from = parent; +- child_role->inherit_options(&flags, options, +- parent->open_flags, parent->options); ++ child_class->inherit_options(&flags, options, ++ parent->open_flags, parent->options); + } + + ret = bdrv_fill_options(&options, filename, &flags, &local_err); +@@ -3472,7 +3474,7 @@ static bool bdrv_recurse_has_child(BlockDriverState *bs, + static BlockReopenQueue *bdrv_reopen_queue_child(BlockReopenQueue *bs_queue, + BlockDriverState *bs, + QDict *options, +- const BdrvChildRole *role, ++ const BdrvChildClass *klass, + QDict *parent_options, + int parent_flags, + bool keep_old_opts) +@@ -3528,7 +3530,7 @@ static BlockReopenQueue *bdrv_reopen_queue_child(BlockReopenQueue *bs_queue, + /* Inherit from parent node */ + if (parent_options) { + flags = 0; +- role->inherit_options(&flags, options, parent_flags, parent_options); ++ klass->inherit_options(&flags, options, parent_flags, parent_options); + } else { + flags = bdrv_get_flags(bs); + } +@@ -3619,7 +3621,7 @@ static BlockReopenQueue *bdrv_reopen_queue_child(BlockReopenQueue *bs_queue, + } + + bdrv_reopen_queue_child(bs_queue, child->bs, new_child_options, +- child->role, options, flags, child_keep_old); ++ child->klass, options, flags, child_keep_old); + } + + return bs_queue; +@@ -3799,7 +3801,7 @@ static void bdrv_reopen_perm(BlockReopenQueue *q, BlockDriverState *bs, + } else { + uint64_t nperm, nshared; + +- bdrv_child_perm(parent->state.bs, bs, c, c->role, q, ++ bdrv_child_perm(parent->state.bs, bs, c, c->klass, q, + parent->state.perm, parent->state.shared_perm, + &nperm, &nshared); + +@@ -4305,7 +4307,7 @@ static bool should_update_child(BdrvChild *c, BlockDriverState *to) + GHashTable *found; + bool ret; + +- if (c->role->stay_at_node) { ++ if (c->klass->stay_at_node) { + return false; + } + +@@ -4776,9 +4778,9 @@ int bdrv_drop_intermediate(BlockDriverState *top, BlockDriverState *base, + } + + /* If so, update the backing file path in the image file */ +- if (c->role->update_filename) { +- ret = c->role->update_filename(c, base, backing_file_str, +- &local_err); ++ if (c->klass->update_filename) { ++ ret = c->klass->update_filename(c, base, backing_file_str, ++ &local_err); + if (ret < 0) { + bdrv_abort_perm_update(base); + error_report_err(local_err); +@@ -5226,8 +5228,8 @@ const char *bdrv_get_parent_name(const BlockDriverState *bs) + + /* If multiple parents have a name, just pick the first one. */ + QLIST_FOREACH(c, &bs->parents, next_parent) { +- if (c->role->get_name) { +- name = c->role->get_name(c); ++ if (c->klass->get_name) { ++ name = c->klass->get_name(c); + if (name && *name) { + return name; + } +@@ -5586,8 +5588,8 @@ static void coroutine_fn bdrv_co_invalidate_cache(BlockDriverState *bs, + } + + QLIST_FOREACH(parent, &bs->parents, next_parent) { +- if (parent->role->activate) { +- parent->role->activate(parent, &local_err); ++ if (parent->klass->activate) { ++ parent->klass->activate(parent, &local_err); + if (local_err) { + bs->open_flags |= BDRV_O_INACTIVE; + error_propagate(errp, local_err); +@@ -5655,7 +5657,7 @@ static bool bdrv_has_bds_parent(BlockDriverState *bs, bool only_active) + BdrvChild *parent; + + QLIST_FOREACH(parent, &bs->parents, next_parent) { +- if (parent->role->parent_is_bds) { ++ if (parent->klass->parent_is_bds) { + BlockDriverState *parent_bs = parent->opaque; + if (!only_active || !(parent_bs->open_flags & BDRV_O_INACTIVE)) { + return true; +@@ -5694,8 +5696,8 @@ static int bdrv_inactivate_recurse(BlockDriverState *bs) + } + + QLIST_FOREACH(parent, &bs->parents, next_parent) { +- if (parent->role->inactivate) { +- ret = parent->role->inactivate(parent); ++ if (parent->klass->inactivate) { ++ ret = parent->klass->inactivate(parent); + if (ret < 0) { + return ret; + } +@@ -6195,9 +6197,9 @@ void bdrv_set_aio_context_ignore(BlockDriverState *bs, + if (g_slist_find(*ignore, child)) { + continue; + } +- assert(child->role->set_aio_ctx); ++ assert(child->klass->set_aio_ctx); + *ignore = g_slist_prepend(*ignore, child); +- child->role->set_aio_ctx(child, new_context, ignore); ++ child->klass->set_aio_ctx(child, new_context, ignore); + } + + bdrv_detach_aio_context(bs); +@@ -6237,15 +6239,17 @@ static bool bdrv_parent_can_set_aio_context(BdrvChild *c, AioContext *ctx, + } + *ignore = g_slist_prepend(*ignore, c); + +- /* A BdrvChildRole that doesn't handle AioContext changes cannot +- * tolerate any AioContext changes */ +- if (!c->role->can_set_aio_ctx) { ++ /* ++ * A BdrvChildClass that doesn't handle AioContext changes cannot ++ * tolerate any AioContext changes ++ */ ++ if (!c->klass->can_set_aio_ctx) { + char *user = bdrv_child_user_desc(c); + error_setg(errp, "Changing iothreads is not supported by %s", user); + g_free(user); + return false; + } +- if (!c->role->can_set_aio_ctx(c, ctx, ignore, errp)) { ++ if (!c->klass->can_set_aio_ctx(c, ctx, ignore, errp)) { + assert(!errp || *errp); + return false; + } +@@ -6631,7 +6635,7 @@ void bdrv_refresh_filename(BlockDriverState *bs) + drv->bdrv_gather_child_options(bs, opts, backing_overridden); + } else { + QLIST_FOREACH(child, &bs->children, next) { +- if (child->role == &child_backing && !backing_overridden) { ++ if (child->klass == &child_backing && !backing_overridden) { + /* We can skip the backing BDS if it has not been overridden */ + continue; + } +diff --git a/block/backup-top.c b/block/backup-top.c +index 79b268e6dc..282845a410 100644 +--- a/block/backup-top.c ++++ b/block/backup-top.c +@@ -122,7 +122,7 @@ static void backup_top_refresh_filename(BlockDriverState *bs) + } + + static void backup_top_child_perm(BlockDriverState *bs, BdrvChild *c, +- const BdrvChildRole *role, ++ const BdrvChildClass *child_class, + BlockReopenQueue *reopen_queue, + uint64_t perm, uint64_t shared, + uint64_t *nperm, uint64_t *nshared) +@@ -142,7 +142,7 @@ static void backup_top_child_perm(BlockDriverState *bs, BdrvChild *c, + return; + } + +- if (role == &child_file) { ++ if (child_class == &child_file) { + /* + * Target child + * +@@ -155,8 +155,8 @@ static void backup_top_child_perm(BlockDriverState *bs, BdrvChild *c, + *nperm = BLK_PERM_WRITE; + } else { + /* Source child */ +- bdrv_filter_default_perms(bs, c, role, reopen_queue, perm, shared, +- nperm, nshared); ++ bdrv_filter_default_perms(bs, c, child_class, reopen_queue, ++ perm, shared, nperm, nshared); + + if (perm & BLK_PERM_WRITE) { + *nperm = *nperm | BLK_PERM_CONSISTENT_READ; +diff --git a/block/blkdebug.c b/block/blkdebug.c +index af44aa973f..f369d54ee4 100644 +--- a/block/blkdebug.c ++++ b/block/blkdebug.c +@@ -993,14 +993,14 @@ static int blkdebug_reopen_prepare(BDRVReopenState *reopen_state, + } + + static void blkdebug_child_perm(BlockDriverState *bs, BdrvChild *c, +- const BdrvChildRole *role, ++ const BdrvChildClass *child_class, + BlockReopenQueue *reopen_queue, + uint64_t perm, uint64_t shared, + uint64_t *nperm, uint64_t *nshared) + { + BDRVBlkdebugState *s = bs->opaque; + +- bdrv_filter_default_perms(bs, c, role, reopen_queue, perm, shared, ++ bdrv_filter_default_perms(bs, c, child_class, reopen_queue, perm, shared, + nperm, nshared); + + *nperm |= s->take_child_perms; +diff --git a/block/blklogwrites.c b/block/blklogwrites.c +index 04d8b33607..f3b3259d8d 100644 +--- a/block/blklogwrites.c ++++ b/block/blklogwrites.c +@@ -282,7 +282,7 @@ static int64_t blk_log_writes_getlength(BlockDriverState *bs) + } + + static void blk_log_writes_child_perm(BlockDriverState *bs, BdrvChild *c, +- const BdrvChildRole *role, ++ const BdrvChildClass *child_class, + BlockReopenQueue *ro_q, + uint64_t perm, uint64_t shrd, + uint64_t *nperm, uint64_t *nshrd) +@@ -294,9 +294,11 @@ static void blk_log_writes_child_perm(BlockDriverState *bs, BdrvChild *c, + } + + if (!strcmp(c->name, "log")) { +- bdrv_format_default_perms(bs, c, role, ro_q, perm, shrd, nperm, nshrd); ++ bdrv_format_default_perms(bs, c, child_class, ro_q, perm, shrd, nperm, ++ nshrd); + } else { +- bdrv_filter_default_perms(bs, c, role, ro_q, perm, shrd, nperm, nshrd); ++ bdrv_filter_default_perms(bs, c, child_class, ro_q, perm, shrd, nperm, ++ nshrd); + } + } + +diff --git a/block/block-backend.c b/block/block-backend.c +index 47bd56244d..c0af79147a 100644 +--- a/block/block-backend.c ++++ b/block/block-backend.c +@@ -297,7 +297,7 @@ static void blk_root_detach(BdrvChild *child) + } + } + +-static const BdrvChildRole child_root = { ++static const BdrvChildClass child_root = { + .inherit_options = blk_root_inherit_options, + + .change_media = blk_root_change_media, +@@ -716,7 +716,7 @@ static BlockBackend *bdrv_first_blk(BlockDriverState *bs) + { + BdrvChild *child; + QLIST_FOREACH(child, &bs->parents, next_parent) { +- if (child->role == &child_root) { ++ if (child->klass == &child_root) { + return child->opaque; + } + } +@@ -740,7 +740,7 @@ bool bdrv_is_root_node(BlockDriverState *bs) + BdrvChild *c; + + QLIST_FOREACH(c, &bs->parents, next_parent) { +- if (c->role != &child_root) { ++ if (c->klass != &child_root) { + return false; + } + } +diff --git a/block/commit.c b/block/commit.c +index b0a8a793cd..834eeae412 100644 +--- a/block/commit.c ++++ b/block/commit.c +@@ -223,7 +223,7 @@ static void bdrv_commit_top_refresh_filename(BlockDriverState *bs) + } + + static void bdrv_commit_top_child_perm(BlockDriverState *bs, BdrvChild *c, +- const BdrvChildRole *role, ++ const BdrvChildClass *child_class, + BlockReopenQueue *reopen_queue, + uint64_t perm, uint64_t shared, + uint64_t *nperm, uint64_t *nshared) +diff --git a/block/copy-on-read.c b/block/copy-on-read.c +index 242d3ff055..7504ca6ffc 100644 +--- a/block/copy-on-read.c ++++ b/block/copy-on-read.c +@@ -51,7 +51,7 @@ static int cor_open(BlockDriverState *bs, QDict *options, int flags, + #define PERM_UNCHANGED (BLK_PERM_ALL & ~PERM_PASSTHROUGH) + + static void cor_child_perm(BlockDriverState *bs, BdrvChild *c, +- const BdrvChildRole *role, ++ const BdrvChildClass *child_class, + BlockReopenQueue *reopen_queue, + uint64_t perm, uint64_t shared, + uint64_t *nperm, uint64_t *nshared) +diff --git a/block/io.c b/block/io.c +index 7d30e61edc..121ce17a49 100644 +--- a/block/io.c ++++ b/block/io.c +@@ -50,7 +50,7 @@ static void bdrv_parent_drained_begin(BlockDriverState *bs, BdrvChild *ignore, + BdrvChild *c, *next; + + QLIST_FOREACH_SAFE(c, &bs->parents, next_parent, next) { +- if (c == ignore || (ignore_bds_parents && c->role->parent_is_bds)) { ++ if (c == ignore || (ignore_bds_parents && c->klass->parent_is_bds)) { + continue; + } + bdrv_parent_drained_begin_single(c, false); +@@ -62,8 +62,8 @@ static void bdrv_parent_drained_end_single_no_poll(BdrvChild *c, + { + assert(c->parent_quiesce_counter > 0); + c->parent_quiesce_counter--; +- if (c->role->drained_end) { +- c->role->drained_end(c, drained_end_counter); ++ if (c->klass->drained_end) { ++ c->klass->drained_end(c, drained_end_counter); + } + } + +@@ -81,7 +81,7 @@ static void bdrv_parent_drained_end(BlockDriverState *bs, BdrvChild *ignore, + BdrvChild *c; + + QLIST_FOREACH(c, &bs->parents, next_parent) { +- if (c == ignore || (ignore_bds_parents && c->role->parent_is_bds)) { ++ if (c == ignore || (ignore_bds_parents && c->klass->parent_is_bds)) { + continue; + } + bdrv_parent_drained_end_single_no_poll(c, drained_end_counter); +@@ -90,8 +90,8 @@ static void bdrv_parent_drained_end(BlockDriverState *bs, BdrvChild *ignore, + + static bool bdrv_parent_drained_poll_single(BdrvChild *c) + { +- if (c->role->drained_poll) { +- return c->role->drained_poll(c); ++ if (c->klass->drained_poll) { ++ return c->klass->drained_poll(c); + } + return false; + } +@@ -103,7 +103,7 @@ static bool bdrv_parent_drained_poll(BlockDriverState *bs, BdrvChild *ignore, + bool busy = false; + + QLIST_FOREACH_SAFE(c, &bs->parents, next_parent, next) { +- if (c == ignore || (ignore_bds_parents && c->role->parent_is_bds)) { ++ if (c == ignore || (ignore_bds_parents && c->klass->parent_is_bds)) { + continue; + } + busy |= bdrv_parent_drained_poll_single(c); +@@ -115,8 +115,8 @@ static bool bdrv_parent_drained_poll(BlockDriverState *bs, BdrvChild *ignore, + void bdrv_parent_drained_begin_single(BdrvChild *c, bool poll) + { + c->parent_quiesce_counter++; +- if (c->role->drained_begin) { +- c->role->drained_begin(c); ++ if (c->klass->drained_begin) { ++ c->klass->drained_begin(c); + } + if (poll) { + BDRV_POLL_WHILE(c->bs, bdrv_parent_drained_poll_single(c)); +@@ -3326,8 +3326,8 @@ static void bdrv_parent_cb_resize(BlockDriverState *bs) + { + BdrvChild *c; + QLIST_FOREACH(c, &bs->parents, next_parent) { +- if (c->role->resize) { +- c->role->resize(c); ++ if (c->klass->resize) { ++ c->klass->resize(c); + } + } + } +diff --git a/block/mirror.c b/block/mirror.c +index 55e992670a..d6598463d5 100644 +--- a/block/mirror.c ++++ b/block/mirror.c +@@ -1492,7 +1492,7 @@ static void bdrv_mirror_top_refresh_filename(BlockDriverState *bs) + } + + static void bdrv_mirror_top_child_perm(BlockDriverState *bs, BdrvChild *c, +- const BdrvChildRole *role, ++ const BdrvChildClass *child_class, + BlockReopenQueue *reopen_queue, + uint64_t perm, uint64_t shared, + uint64_t *nperm, uint64_t *nshared) +diff --git a/block/quorum.c b/block/quorum.c +index 6d7a56bd93..a0824c300d 100644 +--- a/block/quorum.c ++++ b/block/quorum.c +@@ -1151,7 +1151,7 @@ static char *quorum_dirname(BlockDriverState *bs, Error **errp) + } + + static void quorum_child_perm(BlockDriverState *bs, BdrvChild *c, +- const BdrvChildRole *role, ++ const BdrvChildClass *child_class, + BlockReopenQueue *reopen_queue, + uint64_t perm, uint64_t shared, + uint64_t *nperm, uint64_t *nshared) +diff --git a/block/replication.c b/block/replication.c +index 9a9f36e524..af428c5b66 100644 +--- a/block/replication.c ++++ b/block/replication.c +@@ -163,7 +163,7 @@ static void replication_close(BlockDriverState *bs) + } + + static void replication_child_perm(BlockDriverState *bs, BdrvChild *c, +- const BdrvChildRole *role, ++ const BdrvChildClass *child_class, + BlockReopenQueue *reopen_queue, + uint64_t perm, uint64_t shared, + uint64_t *nperm, uint64_t *nshared) +diff --git a/block/vvfat.c b/block/vvfat.c +index 34c121c07a..f845d9b485 100644 +--- a/block/vvfat.c ++++ b/block/vvfat.c +@@ -3136,7 +3136,7 @@ static void vvfat_qcow_options(int *child_flags, QDict *child_options, + qdict_set_default_str(child_options, BDRV_OPT_CACHE_NO_FLUSH, "on"); + } + +-static const BdrvChildRole child_vvfat_qcow = { ++static const BdrvChildClass child_vvfat_qcow = { + .parent_is_bds = true, + .inherit_options = vvfat_qcow_options, + }; +@@ -3210,14 +3210,14 @@ err: + } + + static void vvfat_child_perm(BlockDriverState *bs, BdrvChild *c, +- const BdrvChildRole *role, ++ const BdrvChildClass *child_class, + BlockReopenQueue *reopen_queue, + uint64_t perm, uint64_t shared, + uint64_t *nperm, uint64_t *nshared) + { + BDRVVVFATState *s = bs->opaque; + +- assert(c == s->qcow || role == &child_backing); ++ assert(c == s->qcow || child_class == &child_backing); + + if (c == s->qcow) { + /* This is a private node, nobody should try to attach to it */ +diff --git a/blockjob.c b/blockjob.c +index 2affa1844d..be38c8c550 100644 +--- a/blockjob.c ++++ b/blockjob.c +@@ -163,7 +163,7 @@ static void child_job_set_aio_ctx(BdrvChild *c, AioContext *ctx, + job->job.aio_context = ctx; + } + +-static const BdrvChildRole child_job = { ++static const BdrvChildClass child_job = { + .get_parent_desc = child_job_get_parent_desc, + .drained_begin = child_job_drained_begin, + .drained_poll = child_job_drained_poll, +diff --git a/include/block/block.h b/include/block/block.h +index 8f3eb70df4..bc42e507bb 100644 +--- a/include/block/block.h ++++ b/include/block/block.h +@@ -13,7 +13,7 @@ + /* block.c */ + typedef struct BlockDriver BlockDriver; + typedef struct BdrvChild BdrvChild; +-typedef struct BdrvChildRole BdrvChildRole; ++typedef struct BdrvChildClass BdrvChildClass; + + typedef struct BlockDriverInfo { + /* in bytes, 0 if irrelevant */ +@@ -296,7 +296,7 @@ int bdrv_parse_discard_flags(const char *mode, int *flags); + BdrvChild *bdrv_open_child(const char *filename, + QDict *options, const char *bdref_key, + BlockDriverState* parent, +- const BdrvChildRole *child_role, ++ const BdrvChildClass *child_class, + bool allow_none, Error **errp); + BlockDriverState *bdrv_open_blockdev_ref(BlockdevRef *ref, Error **errp); + void bdrv_set_backing_hd(BlockDriverState *bs, BlockDriverState *backing_hd, +@@ -541,7 +541,7 @@ void bdrv_unref_child(BlockDriverState *parent, BdrvChild *child); + BdrvChild *bdrv_attach_child(BlockDriverState *parent_bs, + BlockDriverState *child_bs, + const char *child_name, +- const BdrvChildRole *child_role, ++ const BdrvChildClass *child_class, + Error **errp); + + bool bdrv_op_is_blocked(BlockDriverState *bs, BlockOpType op, Error **errp); +diff --git a/include/block/block_int.h b/include/block/block_int.h +index 1c24df53fd..9a78b981e4 100644 +--- a/include/block/block_int.h ++++ b/include/block/block_int.h +@@ -556,14 +556,14 @@ struct BlockDriver { + * the parents in @parent_perm and @parent_shared. + * + * If @c is NULL, return the permissions for attaching a new child for the +- * given @role. ++ * given @child_class. + * + * If @reopen_queue is non-NULL, don't return the currently needed + * permissions, but those that will be needed after applying the + * @reopen_queue. + */ + void (*bdrv_child_perm)(BlockDriverState *bs, BdrvChild *c, +- const BdrvChildRole *role, ++ const BdrvChildClass *child_class, + BlockReopenQueue *reopen_queue, + uint64_t parent_perm, uint64_t parent_shared, + uint64_t *nperm, uint64_t *nshared); +@@ -665,7 +665,7 @@ typedef struct BdrvAioNotifier { + QLIST_ENTRY(BdrvAioNotifier) list; + } BdrvAioNotifier; + +-struct BdrvChildRole { ++struct BdrvChildClass { + /* If true, bdrv_replace_node() doesn't change the node this BdrvChild + * points to. */ + bool stay_at_node; +@@ -738,14 +738,14 @@ struct BdrvChildRole { + void (*set_aio_ctx)(BdrvChild *child, AioContext *ctx, GSList **ignore); + }; + +-extern const BdrvChildRole child_file; +-extern const BdrvChildRole child_format; +-extern const BdrvChildRole child_backing; ++extern const BdrvChildClass child_file; ++extern const BdrvChildClass child_format; ++extern const BdrvChildClass child_backing; + + struct BdrvChild { + BlockDriverState *bs; + char *name; +- const BdrvChildRole *role; ++ const BdrvChildClass *klass; + void *opaque; + + /** +@@ -772,7 +772,7 @@ struct BdrvChild { + + /* + * How many times the parent of this child has been drained +- * (through role->drained_*). ++ * (through klass->drained_*). + * Usually, this is equal to bs->quiesce_counter (potentially + * reduced by bdrv_drain_all_count). It may differ while the + * child is entering or leaving a drained section. +@@ -1232,7 +1232,7 @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs, + + BdrvChild *bdrv_root_attach_child(BlockDriverState *child_bs, + const char *child_name, +- const BdrvChildRole *child_role, ++ const BdrvChildClass *child_class, + AioContext *ctx, + uint64_t perm, uint64_t shared_perm, + void *opaque, Error **errp); +@@ -1263,7 +1263,7 @@ int bdrv_child_refresh_perms(BlockDriverState *bs, BdrvChild *c, Error **errp); + * block filters: Forward CONSISTENT_READ, WRITE, WRITE_UNCHANGED and RESIZE to + * all children */ + void bdrv_filter_default_perms(BlockDriverState *bs, BdrvChild *c, +- const BdrvChildRole *role, ++ const BdrvChildClass *child_class, + BlockReopenQueue *reopen_queue, + uint64_t perm, uint64_t shared, + uint64_t *nperm, uint64_t *nshared); +@@ -1273,7 +1273,7 @@ void bdrv_filter_default_perms(BlockDriverState *bs, BdrvChild *c, + * requires WRITE | RESIZE for read-write images, always requires + * CONSISTENT_READ and doesn't share WRITE. */ + void bdrv_format_default_perms(BlockDriverState *bs, BdrvChild *c, +- const BdrvChildRole *role, ++ const BdrvChildClass *child_class, + BlockReopenQueue *reopen_queue, + uint64_t perm, uint64_t shared, + uint64_t *nperm, uint64_t *nshared); +diff --git a/tests/test-bdrv-drain.c b/tests/test-bdrv-drain.c +index fa0e6a648b..9d683a6c11 100644 +--- a/tests/test-bdrv-drain.c ++++ b/tests/test-bdrv-drain.c +@@ -86,18 +86,20 @@ static int coroutine_fn bdrv_test_co_preadv(BlockDriverState *bs, + } + + static void bdrv_test_child_perm(BlockDriverState *bs, BdrvChild *c, +- const BdrvChildRole *role, ++ const BdrvChildClass *child_class, + BlockReopenQueue *reopen_queue, + uint64_t perm, uint64_t shared, + uint64_t *nperm, uint64_t *nshared) + { +- /* bdrv_format_default_perms() accepts only these two, so disguise +- * detach_by_driver_cb_role as one of them. */ +- if (role != &child_file && role != &child_backing) { +- role = &child_file; ++ /* ++ * bdrv_format_default_perms() accepts only these two, so disguise ++ * detach_by_driver_cb_parent as one of them. ++ */ ++ if (child_class != &child_file && child_class != &child_backing) { ++ child_class = &child_file; + } + +- bdrv_format_default_perms(bs, c, role, reopen_queue, perm, shared, ++ bdrv_format_default_perms(bs, c, child_class, reopen_queue, perm, shared, + nperm, nshared); + } + +@@ -1332,7 +1334,7 @@ static void detach_by_driver_cb_drained_begin(BdrvChild *child) + child_file.drained_begin(child); + } + +-static BdrvChildRole detach_by_driver_cb_role; ++static BdrvChildClass detach_by_driver_cb_class; + + /* + * Initial graph: +@@ -1349,7 +1351,7 @@ static BdrvChildRole detach_by_driver_cb_role; + * + * by_parent_cb == false: Test that bdrv_drain_invoke() doesn't poll + * +- * PA's BdrvChildRole has a .drained_begin callback that schedules a BH ++ * PA's BdrvChildClass has a .drained_begin callback that schedules a BH + * that does the same graph change. If bdrv_drain_invoke() calls it, the + * state is messed up, but if it is only polled in the single + * BDRV_POLL_WHILE() at the end of the drain, this should work fine. +@@ -1364,8 +1366,8 @@ static void test_detach_indirect(bool by_parent_cb) + QEMUIOVector qiov = QEMU_IOVEC_INIT_BUF(qiov, NULL, 0); + + if (!by_parent_cb) { +- detach_by_driver_cb_role = child_file; +- detach_by_driver_cb_role.drained_begin = ++ detach_by_driver_cb_class = child_file; ++ detach_by_driver_cb_class.drained_begin = + detach_by_driver_cb_drained_begin; + } + +@@ -1399,7 +1401,7 @@ static void test_detach_indirect(bool by_parent_cb) + + bdrv_ref(a); + bdrv_attach_child(parent_a, a, "PA-A", +- by_parent_cb ? &child_file : &detach_by_driver_cb_role, ++ by_parent_cb ? &child_file : &detach_by_driver_cb_class, + &error_abort); + + g_assert_cmpint(parent_a->refcnt, ==, 1); +@@ -1735,7 +1737,7 @@ static int drop_intermediate_poll_update_filename(BdrvChild *child, + /** + * Test a poll in the midst of bdrv_drop_intermediate(). + * +- * bdrv_drop_intermediate() calls BdrvChildRole.update_filename(), ++ * bdrv_drop_intermediate() calls BdrvChildClass.update_filename(), + * which can yield or poll. This may lead to graph changes, unless + * the whole subtree in question is drained. + * +@@ -1772,7 +1774,7 @@ static int drop_intermediate_poll_update_filename(BdrvChild *child, + * + * The solution is for bdrv_drop_intermediate() to drain top's + * subtree. This prevents graph changes from happening just because +- * BdrvChildRole.update_filename() yields or polls. Thus, the block ++ * BdrvChildClass.update_filename() yields or polls. Thus, the block + * job is paused during that drained section and must finish before or + * after. + * +@@ -1780,7 +1782,7 @@ static int drop_intermediate_poll_update_filename(BdrvChild *child, + */ + static void test_drop_intermediate_poll(void) + { +- static BdrvChildRole chain_child_role; ++ static BdrvChildClass chain_child_class; + BlockDriverState *chain[3]; + TestSimpleBlockJob *job; + BlockDriverState *job_node; +@@ -1788,8 +1790,8 @@ static void test_drop_intermediate_poll(void) + int i; + int ret; + +- chain_child_role = child_backing; +- chain_child_role.update_filename = drop_intermediate_poll_update_filename; ++ chain_child_class = child_backing; ++ chain_child_class.update_filename = drop_intermediate_poll_update_filename; + + for (i = 0; i < 3; i++) { + char name[32]; +@@ -1810,7 +1812,7 @@ static void test_drop_intermediate_poll(void) + if (i) { + /* Takes the reference to chain[i - 1] */ + chain[i]->backing = bdrv_attach_child(chain[i], chain[i - 1], +- "chain", &chain_child_role, ++ "chain", &chain_child_class, + &error_abort); + } + } +diff --git a/tests/test-bdrv-graph-mod.c b/tests/test-bdrv-graph-mod.c +index a007754d9e..fef42cb294 100644 +--- a/tests/test-bdrv-graph-mod.c ++++ b/tests/test-bdrv-graph-mod.c +@@ -30,7 +30,7 @@ static BlockDriver bdrv_pass_through = { + }; + + static void no_perm_default_perms(BlockDriverState *bs, BdrvChild *c, +- const BdrvChildRole *role, ++ const BdrvChildClass *child_class, + BlockReopenQueue *reopen_queue, + uint64_t perm, uint64_t shared, + uint64_t *nperm, uint64_t *nshared) +-- +2.23.0 + diff --git a/block-Rename-bdrv_inherited_options.patch b/block-Rename-bdrv_inherited_options.patch new file mode 100644 index 0000000000000000000000000000000000000000..5bbd21d48cc32f44d920d15030df9aac7a34ce3f --- /dev/null +++ b/block-Rename-bdrv_inherited_options.patch @@ -0,0 +1,48 @@ +From b054ff73547b6e032bde1e98c9a4f8240ce9dd30 Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Wed, 13 May 2020 13:05:19 +0200 +Subject: [PATCH 541/709] block: Rename bdrv_inherited_options() + +The other two .inherit_options implementations specify exactly for what +case they are used in their name, so do it for this one as well. + +(The actual intention behind this patch is to follow it up with a +generic bdrv_inherited_options() that works for all three cases.) + +Signed-off-by: Max Reitz +Reviewed-by: Eric Blake +Message-Id: <20200513110544.176672-10-mreitz@redhat.com> +Signed-off-by: Kevin Wolf +--- + block.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/block.c b/block.c +index b78e2dc141..a17c29f54b 100644 +--- a/block.c ++++ b/block.c +@@ -1154,9 +1154,9 @@ static void bdrv_temp_snapshot_options(int *child_flags, QDict *child_options, + * Returns the options and flags that bs->file should get if a protocol driver + * is expected, based on the given options and flags for the parent BDS + */ +-static void bdrv_inherited_options(BdrvChildRole role, bool parent_is_format, +- int *child_flags, QDict *child_options, +- int parent_flags, QDict *parent_options) ++static void bdrv_protocol_options(BdrvChildRole role, bool parent_is_format, ++ int *child_flags, QDict *child_options, ++ int parent_flags, QDict *parent_options) + { + int flags = parent_flags; + +@@ -1188,7 +1188,7 @@ static void bdrv_inherited_options(BdrvChildRole role, bool parent_is_format, + const BdrvChildClass child_file = { + .parent_is_bds = true, + .get_parent_desc = bdrv_child_get_parent_desc, +- .inherit_options = bdrv_inherited_options, ++ .inherit_options = bdrv_protocol_options, + .drained_begin = bdrv_child_cb_drained_begin, + .drained_poll = bdrv_child_cb_drained_poll, + .drained_end = bdrv_child_cb_drained_end, +-- +2.23.0 + diff --git a/block-Switch-child_format-users-to-child_of_bds.patch b/block-Switch-child_format-users-to-child_of_bds.patch new file mode 100644 index 0000000000000000000000000000000000000000..6b8b9fd4505e084c14371bc1362ccd871c574b91 --- /dev/null +++ b/block-Switch-child_format-users-to-child_of_bds.patch @@ -0,0 +1,61 @@ +From 36ee58d13bbcb75c72385bee6e262afed3acce47 Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Wed, 13 May 2020 13:05:31 +0200 +Subject: [PATCH 553/709] block: Switch child_format users to child_of_bds + +Both users (quorum and blkverify) use child_format for +not-really-filtered children, so the appropriate BdrvChildRole in both +cases is DATA. (Note that this will cause bdrv_inherited_options() to +force-allow format probing.) + +Signed-off-by: Max Reitz +Reviewed-by: Eric Blake +Message-Id: <20200513110544.176672-22-mreitz@redhat.com> +Signed-off-by: Kevin Wolf +--- + block/blkverify.c | 4 ++-- + block/quorum.c | 6 ++++-- + 2 files changed, 6 insertions(+), 4 deletions(-) + +diff --git a/block/blkverify.c b/block/blkverify.c +index ba4f6d7b7c..1684b7aa2e 100644 +--- a/block/blkverify.c ++++ b/block/blkverify.c +@@ -134,8 +134,8 @@ static int blkverify_open(BlockDriverState *bs, QDict *options, int flags, + + /* Open the test file */ + s->test_file = bdrv_open_child(qemu_opt_get(opts, "x-image"), options, +- "test", bs, &child_format, 0, false, +- &local_err); ++ "test", bs, &child_of_bds, BDRV_CHILD_DATA, ++ false, &local_err); + if (local_err) { + ret = -EINVAL; + error_propagate(errp, local_err); +diff --git a/block/quorum.c b/block/quorum.c +index d37b77a522..616ac3a927 100644 +--- a/block/quorum.c ++++ b/block/quorum.c +@@ -977,7 +977,8 @@ static int quorum_open(BlockDriverState *bs, QDict *options, int flags, + assert(ret < 32); + + s->children[i] = bdrv_open_child(NULL, options, indexstr, bs, +- &child_format, 0, false, &local_err); ++ &child_of_bds, BDRV_CHILD_DATA, false, ++ &local_err); + if (local_err) { + ret = -EINVAL; + goto close_exit; +@@ -1053,7 +1054,8 @@ static void quorum_add_child(BlockDriverState *bs, BlockDriverState *child_bs, + /* We can safely add the child now */ + bdrv_ref(child_bs); + +- child = bdrv_attach_child(bs, child_bs, indexstr, &child_format, 0, errp); ++ child = bdrv_attach_child(bs, child_bs, indexstr, &child_of_bds, ++ BDRV_CHILD_DATA, errp); + if (child == NULL) { + s->next_child_index--; + goto out; +-- +2.23.0 + diff --git a/block-Unify-bdrv_child_cb_attach.patch b/block-Unify-bdrv_child_cb_attach.patch new file mode 100644 index 0000000000000000000000000000000000000000..2f261d54e32d966c2695199fbf3259acc24a289e --- /dev/null +++ b/block-Unify-bdrv_child_cb_attach.patch @@ -0,0 +1,94 @@ +From ca2f1234c3c051f416fb0a1d09eecde328a6dd51 Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Wed, 13 May 2020 13:05:22 +0200 +Subject: [PATCH 544/709] block: Unify bdrv_child_cb_attach() + +Make bdrv_child_cb_attach() call bdrv_backing_attach() for children with +a COW role (and drop the reverse call from bdrv_backing_attach()), so it +can be used for any child (with a proper role set). + +Because so far no child has a proper role set, we need a temporary new +callback for child_backing.attach that ensures bdrv_backing_attach() is +called for all COW children that do not have their role set yet. + +(Also, move bdrv_child_cb_attach() down to group it with +bdrv_inherited_options().) + +Signed-off-by: Max Reitz +Message-Id: <20200513110544.176672-13-mreitz@redhat.com> +Reviewed-by: Eric Blake +Signed-off-by: Kevin Wolf +--- + block.c | 27 ++++++++++++++++++++------- + 1 file changed, 20 insertions(+), 7 deletions(-) + +diff --git a/block.c b/block.c +index b3b978a092..755704a54c 100644 +--- a/block.c ++++ b/block.c +@@ -84,6 +84,7 @@ static BlockDriverState *bdrv_open_inherit(const char *filename, + static void bdrv_inherited_options(BdrvChildRole role, bool parent_is_format, + int *child_flags, QDict *child_options, + int parent_flags, QDict *parent_options); ++static void bdrv_child_cb_attach(BdrvChild *child); + + /* If non-zero, use only whitelisted block drivers */ + static int use_bdrv_whitelist; +@@ -1099,12 +1100,6 @@ static void bdrv_child_cb_drained_end(BdrvChild *child, + bdrv_drained_end_no_poll(bs, drained_end_counter); + } + +-static void bdrv_child_cb_attach(BdrvChild *child) +-{ +- BlockDriverState *bs = child->opaque; +- bdrv_apply_subtree_drain(child, bs); +-} +- + static void bdrv_child_cb_detach(BdrvChild *child) + { + BlockDriverState *bs = child->opaque; +@@ -1252,7 +1247,14 @@ static void bdrv_backing_attach(BdrvChild *c) + parent->backing_blocker); + bdrv_op_unblock(backing_hd, BLOCK_OP_TYPE_BACKUP_TARGET, + parent->backing_blocker); ++} + ++/* XXX: Will be removed along with child_backing */ ++static void bdrv_child_cb_attach_backing(BdrvChild *c) ++{ ++ if (!(c->role & BDRV_CHILD_COW)) { ++ bdrv_backing_attach(c); ++ } + bdrv_child_cb_attach(c); + } + +@@ -1311,7 +1313,7 @@ static int bdrv_backing_update_filename(BdrvChild *c, BlockDriverState *base, + const BdrvChildClass child_backing = { + .parent_is_bds = true, + .get_parent_desc = bdrv_child_get_parent_desc, +- .attach = bdrv_backing_attach, ++ .attach = bdrv_child_cb_attach_backing, + .detach = bdrv_backing_detach, + .inherit_options = bdrv_backing_options, + .drained_begin = bdrv_child_cb_drained_begin, +@@ -1403,6 +1405,17 @@ static void bdrv_inherited_options(BdrvChildRole role, bool parent_is_format, + *child_flags = flags; + } + ++static void bdrv_child_cb_attach(BdrvChild *child) ++{ ++ BlockDriverState *bs = child->opaque; ++ ++ if (child->role & BDRV_CHILD_COW) { ++ bdrv_backing_attach(child); ++ } ++ ++ bdrv_apply_subtree_drain(child, bs); ++} ++ + static int bdrv_open_flags(BlockDriverState *bs, int flags) + { + int open_flags = flags; +-- +2.23.0 + diff --git a/block-Unify-bdrv_child_cb_detach.patch b/block-Unify-bdrv_child_cb_detach.patch new file mode 100644 index 0000000000000000000000000000000000000000..bb731a8ea57cb0f2664746492f8dc775fd27b2cf --- /dev/null +++ b/block-Unify-bdrv_child_cb_detach.patch @@ -0,0 +1,94 @@ +From 48e082886132f49e883d96ce39fb926f53868e26 Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Wed, 13 May 2020 13:05:23 +0200 +Subject: [PATCH 545/709] block: Unify bdrv_child_cb_detach() + +Make bdrv_child_cb_detach() call bdrv_backing_detach() for children with +a COW role (and drop the reverse call from bdrv_backing_detach()), so it +can be used for any child (with a proper role set). + +Because so far no child has a proper role set, we need a temporary new +callback for child_backing.detach that ensures bdrv_backing_detach() is +called for all COW children that do not have their role set yet. + +(Also, move bdrv_child_cb_detach() down to group it with +bdrv_inherited_options() and bdrv_child_cb_attach().) + +Signed-off-by: Max Reitz +Message-Id: <20200513110544.176672-14-mreitz@redhat.com> +Reviewed-by: Eric Blake +Signed-off-by: Kevin Wolf +--- + block.c | 27 ++++++++++++++++++++------- + 1 file changed, 20 insertions(+), 7 deletions(-) + +diff --git a/block.c b/block.c +index 755704a54c..f63417c06d 100644 +--- a/block.c ++++ b/block.c +@@ -85,6 +85,7 @@ static void bdrv_inherited_options(BdrvChildRole role, bool parent_is_format, + int *child_flags, QDict *child_options, + int parent_flags, QDict *parent_options); + static void bdrv_child_cb_attach(BdrvChild *child); ++static void bdrv_child_cb_detach(BdrvChild *child); + + /* If non-zero, use only whitelisted block drivers */ + static int use_bdrv_whitelist; +@@ -1100,12 +1101,6 @@ static void bdrv_child_cb_drained_end(BdrvChild *child, + bdrv_drained_end_no_poll(bs, drained_end_counter); + } + +-static void bdrv_child_cb_detach(BdrvChild *child) +-{ +- BlockDriverState *bs = child->opaque; +- bdrv_unapply_subtree_drain(child, bs); +-} +- + static int bdrv_child_cb_inactivate(BdrvChild *child) + { + BlockDriverState *bs = child->opaque; +@@ -1266,7 +1261,14 @@ static void bdrv_backing_detach(BdrvChild *c) + bdrv_op_unblock_all(c->bs, parent->backing_blocker); + error_free(parent->backing_blocker); + parent->backing_blocker = NULL; ++} + ++/* XXX: Will be removed along with child_backing */ ++static void bdrv_child_cb_detach_backing(BdrvChild *c) ++{ ++ if (!(c->role & BDRV_CHILD_COW)) { ++ bdrv_backing_detach(c); ++ } + bdrv_child_cb_detach(c); + } + +@@ -1314,7 +1316,7 @@ const BdrvChildClass child_backing = { + .parent_is_bds = true, + .get_parent_desc = bdrv_child_get_parent_desc, + .attach = bdrv_child_cb_attach_backing, +- .detach = bdrv_backing_detach, ++ .detach = bdrv_child_cb_detach_backing, + .inherit_options = bdrv_backing_options, + .drained_begin = bdrv_child_cb_drained_begin, + .drained_poll = bdrv_child_cb_drained_poll, +@@ -1416,6 +1418,17 @@ static void bdrv_child_cb_attach(BdrvChild *child) + bdrv_apply_subtree_drain(child, bs); + } + ++static void bdrv_child_cb_detach(BdrvChild *child) ++{ ++ BlockDriverState *bs = child->opaque; ++ ++ if (child->role & BDRV_CHILD_COW) { ++ bdrv_backing_detach(child); ++ } ++ ++ bdrv_unapply_subtree_drain(child, bs); ++} ++ + static int bdrv_open_flags(BlockDriverState *bs, int flags) + { + int open_flags = flags; +-- +2.23.0 + diff --git a/block-Use-bdrv_default_perms.patch b/block-Use-bdrv_default_perms.patch new file mode 100644 index 0000000000000000000000000000000000000000..ccf7a580b15fba0a9a96f728dc89ee314cce3aba --- /dev/null +++ b/block-Use-bdrv_default_perms.patch @@ -0,0 +1,409 @@ +From 69dca43d6b6819b3d0895364692e2d0445674916 Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Wed, 13 May 2020 13:05:39 +0200 +Subject: [PATCH 561/709] block: Use bdrv_default_perms() + +bdrv_default_perms() can decide which permission profile to use based on +the BdrvChildRole, so block drivers do not need to select it explicitly. + +The blkverify driver now no longer shares the WRITE permission for the +image to verify. We thus have to adjust two places in +test-block-iothread not to take it. (Note that in theory, blkverify +should behave like quorum in this regard and share neither WRITE nor +RESIZE for both of its children. In practice, it does not really +matter, because blkverify is used only for debugging, so we might as +well keep its permissions rather liberal.) + +Signed-off-by: Max Reitz +Reviewed-by: Eric Blake +Message-Id: <20200513110544.176672-30-mreitz@redhat.com> +Signed-off-by: Kevin Wolf +--- + block/backup-top.c | 4 ++-- + block/blkdebug.c | 4 ++-- + block/blklogwrites.c | 9 ++------- + block/blkreplay.c | 2 +- + block/blkverify.c | 2 +- + block/bochs.c | 2 +- + block/cloop.c | 2 +- + block/crypto.c | 2 +- + block/dmg.c | 2 +- + block/filter-compress.c | 2 +- + block/parallels.c | 2 +- + block/qcow.c | 2 +- + block/qcow2.c | 2 +- + block/qed.c | 2 +- + block/raw-format.c | 2 +- + block/throttle.c | 2 +- + block/vdi.c | 2 +- + block/vhdx.c | 2 +- + block/vmdk.c | 2 +- + block/vpc.c | 2 +- + tests/test-bdrv-drain.c | 10 +++++----- + tests/test-bdrv-graph-mod.c | 2 +- + tests/test-block-iothread.c | 17 ++++++++++++++--- + 23 files changed, 43 insertions(+), 37 deletions(-) + +diff --git a/block/backup-top.c b/block/backup-top.c +index 8af2c5fe9b..f0efec18b5 100644 +--- a/block/backup-top.c ++++ b/block/backup-top.c +@@ -156,8 +156,8 @@ static void backup_top_child_perm(BlockDriverState *bs, BdrvChild *c, + *nperm = BLK_PERM_WRITE; + } else { + /* Source child */ +- bdrv_filter_default_perms(bs, c, child_class, role, reopen_queue, +- perm, shared, nperm, nshared); ++ bdrv_default_perms(bs, c, child_class, role, reopen_queue, ++ perm, shared, nperm, nshared); + + if (perm & BLK_PERM_WRITE) { + *nperm = *nperm | BLK_PERM_CONSISTENT_READ; +diff --git a/block/blkdebug.c b/block/blkdebug.c +index b31fa40b0e..a925d8295e 100644 +--- a/block/blkdebug.c ++++ b/block/blkdebug.c +@@ -1003,8 +1003,8 @@ static void blkdebug_child_perm(BlockDriverState *bs, BdrvChild *c, + { + BDRVBlkdebugState *s = bs->opaque; + +- bdrv_filter_default_perms(bs, c, child_class, role, reopen_queue, +- perm, shared, nperm, nshared); ++ bdrv_default_perms(bs, c, child_class, role, reopen_queue, ++ perm, shared, nperm, nshared); + + *nperm |= s->take_child_perms; + *nshared &= ~s->unshare_child_perms; +diff --git a/block/blklogwrites.c b/block/blklogwrites.c +index 3a57b273fc..8684fb1c74 100644 +--- a/block/blklogwrites.c ++++ b/block/blklogwrites.c +@@ -295,13 +295,8 @@ static void blk_log_writes_child_perm(BlockDriverState *bs, BdrvChild *c, + return; + } + +- if (!strcmp(c->name, "log")) { +- bdrv_format_default_perms(bs, c, child_class, role, ro_q, perm, shrd, +- nperm, nshrd); +- } else { +- bdrv_filter_default_perms(bs, c, child_class, role, ro_q, perm, shrd, +- nperm, nshrd); +- } ++ bdrv_default_perms(bs, c, child_class, role, ro_q, perm, shrd, ++ nperm, nshrd); + } + + static void blk_log_writes_refresh_limits(BlockDriverState *bs, Error **errp) +diff --git a/block/blkreplay.c b/block/blkreplay.c +index 20d6139baa..30a0f5d57a 100644 +--- a/block/blkreplay.c ++++ b/block/blkreplay.c +@@ -139,7 +139,7 @@ static BlockDriver bdrv_blkreplay = { + .is_filter = true, + + .bdrv_open = blkreplay_open, +- .bdrv_child_perm = bdrv_filter_default_perms, ++ .bdrv_child_perm = bdrv_default_perms, + .bdrv_getlength = blkreplay_getlength, + + .bdrv_co_preadv = blkreplay_co_preadv, +diff --git a/block/blkverify.c b/block/blkverify.c +index 5c3b29244a..2f261de24b 100644 +--- a/block/blkverify.c ++++ b/block/blkverify.c +@@ -319,7 +319,7 @@ static BlockDriver bdrv_blkverify = { + .bdrv_parse_filename = blkverify_parse_filename, + .bdrv_file_open = blkverify_open, + .bdrv_close = blkverify_close, +- .bdrv_child_perm = bdrv_filter_default_perms, ++ .bdrv_child_perm = bdrv_default_perms, + .bdrv_getlength = blkverify_getlength, + .bdrv_refresh_filename = blkverify_refresh_filename, + .bdrv_dirname = blkverify_dirname, +diff --git a/block/bochs.c b/block/bochs.c +index 62c3f42548..2f010ab40a 100644 +--- a/block/bochs.c ++++ b/block/bochs.c +@@ -297,7 +297,7 @@ static BlockDriver bdrv_bochs = { + .instance_size = sizeof(BDRVBochsState), + .bdrv_probe = bochs_probe, + .bdrv_open = bochs_open, +- .bdrv_child_perm = bdrv_format_default_perms, ++ .bdrv_child_perm = bdrv_default_perms, + .bdrv_refresh_limits = bochs_refresh_limits, + .bdrv_co_preadv = bochs_co_preadv, + .bdrv_close = bochs_close, +diff --git a/block/cloop.c b/block/cloop.c +index d374a8427d..c99192a57f 100644 +--- a/block/cloop.c ++++ b/block/cloop.c +@@ -293,7 +293,7 @@ static BlockDriver bdrv_cloop = { + .instance_size = sizeof(BDRVCloopState), + .bdrv_probe = cloop_probe, + .bdrv_open = cloop_open, +- .bdrv_child_perm = bdrv_format_default_perms, ++ .bdrv_child_perm = bdrv_default_perms, + .bdrv_refresh_limits = cloop_refresh_limits, + .bdrv_co_preadv = cloop_co_preadv, + .bdrv_close = cloop_close, +diff --git a/block/crypto.c b/block/crypto.c +index 457f3a06a5..b216e12c31 100644 +--- a/block/crypto.c ++++ b/block/crypto.c +@@ -756,7 +756,7 @@ static BlockDriver bdrv_crypto_luks = { + .bdrv_close = block_crypto_close, + /* This driver doesn't modify LUKS metadata except when creating image. + * Allow share-rw=on as a special case. */ +- .bdrv_child_perm = bdrv_filter_default_perms, ++ .bdrv_child_perm = bdrv_default_perms, + .bdrv_co_create = block_crypto_co_create_luks, + .bdrv_co_create_opts = block_crypto_co_create_opts_luks, + .bdrv_co_truncate = block_crypto_co_truncate, +diff --git a/block/dmg.c b/block/dmg.c +index bc64194577..0d6c317296 100644 +--- a/block/dmg.c ++++ b/block/dmg.c +@@ -750,7 +750,7 @@ static BlockDriver bdrv_dmg = { + .bdrv_probe = dmg_probe, + .bdrv_open = dmg_open, + .bdrv_refresh_limits = dmg_refresh_limits, +- .bdrv_child_perm = bdrv_format_default_perms, ++ .bdrv_child_perm = bdrv_default_perms, + .bdrv_co_preadv = dmg_co_preadv, + .bdrv_close = dmg_close, + .is_format = true, +diff --git a/block/filter-compress.c b/block/filter-compress.c +index 9edd937645..8ec1991c1f 100644 +--- a/block/filter-compress.c ++++ b/block/filter-compress.c +@@ -133,7 +133,7 @@ static BlockDriver bdrv_compress = { + .format_name = "compress", + + .bdrv_open = compress_open, +- .bdrv_child_perm = bdrv_filter_default_perms, ++ .bdrv_child_perm = bdrv_default_perms, + + .bdrv_getlength = compress_getlength, + +diff --git a/block/parallels.c b/block/parallels.c +index 168d6c531a..63a1cde8af 100644 +--- a/block/parallels.c ++++ b/block/parallels.c +@@ -912,7 +912,7 @@ static BlockDriver bdrv_parallels = { + .bdrv_probe = parallels_probe, + .bdrv_open = parallels_open, + .bdrv_close = parallels_close, +- .bdrv_child_perm = bdrv_format_default_perms, ++ .bdrv_child_perm = bdrv_default_perms, + .bdrv_co_block_status = parallels_co_block_status, + .bdrv_has_zero_init = bdrv_has_zero_init_1, + .bdrv_co_flush_to_os = parallels_co_flush_to_os, +diff --git a/block/qcow.c b/block/qcow.c +index 5347037720..ee5d35fe20 100644 +--- a/block/qcow.c ++++ b/block/qcow.c +@@ -1180,7 +1180,7 @@ static BlockDriver bdrv_qcow = { + .bdrv_probe = qcow_probe, + .bdrv_open = qcow_open, + .bdrv_close = qcow_close, +- .bdrv_child_perm = bdrv_format_default_perms, ++ .bdrv_child_perm = bdrv_default_perms, + .bdrv_reopen_prepare = qcow_reopen_prepare, + .bdrv_co_create = qcow_co_create, + .bdrv_co_create_opts = qcow_co_create_opts, +diff --git a/block/qcow2.c b/block/qcow2.c +index 8d7230dca8..fe0ce39799 100644 +--- a/block/qcow2.c ++++ b/block/qcow2.c +@@ -5744,7 +5744,7 @@ BlockDriver bdrv_qcow2 = { + .bdrv_reopen_commit_post = qcow2_reopen_commit_post, + .bdrv_reopen_abort = qcow2_reopen_abort, + .bdrv_join_options = qcow2_join_options, +- .bdrv_child_perm = bdrv_format_default_perms, ++ .bdrv_child_perm = bdrv_default_perms, + .bdrv_co_create_opts = qcow2_co_create_opts, + .bdrv_co_create = qcow2_co_create, + .bdrv_has_zero_init = qcow2_has_zero_init, +diff --git a/block/qed.c b/block/qed.c +index ef6463b48d..c0c65015c7 100644 +--- a/block/qed.c ++++ b/block/qed.c +@@ -1672,7 +1672,7 @@ static BlockDriver bdrv_qed = { + .bdrv_open = bdrv_qed_open, + .bdrv_close = bdrv_qed_close, + .bdrv_reopen_prepare = bdrv_qed_reopen_prepare, +- .bdrv_child_perm = bdrv_format_default_perms, ++ .bdrv_child_perm = bdrv_default_perms, + .bdrv_co_create = bdrv_qed_co_create, + .bdrv_co_create_opts = bdrv_qed_co_create_opts, + .bdrv_has_zero_init = bdrv_has_zero_init_1, +diff --git a/block/raw-format.c b/block/raw-format.c +index bfb4d7ddb7..018441bddf 100644 +--- a/block/raw-format.c ++++ b/block/raw-format.c +@@ -586,7 +586,7 @@ BlockDriver bdrv_raw = { + .bdrv_reopen_commit = &raw_reopen_commit, + .bdrv_reopen_abort = &raw_reopen_abort, + .bdrv_open = &raw_open, +- .bdrv_child_perm = bdrv_filter_default_perms, ++ .bdrv_child_perm = bdrv_default_perms, + .bdrv_co_create_opts = &raw_co_create_opts, + .bdrv_co_preadv = &raw_co_preadv, + .bdrv_co_pwritev = &raw_co_pwritev, +diff --git a/block/throttle.c b/block/throttle.c +index 47b0a3522d..0ebbad0743 100644 +--- a/block/throttle.c ++++ b/block/throttle.c +@@ -237,7 +237,7 @@ static BlockDriver bdrv_throttle = { + .bdrv_close = throttle_close, + .bdrv_co_flush = throttle_co_flush, + +- .bdrv_child_perm = bdrv_filter_default_perms, ++ .bdrv_child_perm = bdrv_default_perms, + + .bdrv_getlength = throttle_getlength, + +diff --git a/block/vdi.c b/block/vdi.c +index d20698b3cc..2f506a01ba 100644 +--- a/block/vdi.c ++++ b/block/vdi.c +@@ -1039,7 +1039,7 @@ static BlockDriver bdrv_vdi = { + .bdrv_open = vdi_open, + .bdrv_close = vdi_close, + .bdrv_reopen_prepare = vdi_reopen_prepare, +- .bdrv_child_perm = bdrv_format_default_perms, ++ .bdrv_child_perm = bdrv_default_perms, + .bdrv_co_create = vdi_co_create, + .bdrv_co_create_opts = vdi_co_create_opts, + .bdrv_has_zero_init = vdi_has_zero_init, +diff --git a/block/vhdx.c b/block/vhdx.c +index 62c6bd69ff..fa9e544a5e 100644 +--- a/block/vhdx.c ++++ b/block/vhdx.c +@@ -2245,7 +2245,7 @@ static BlockDriver bdrv_vhdx = { + .bdrv_open = vhdx_open, + .bdrv_close = vhdx_close, + .bdrv_reopen_prepare = vhdx_reopen_prepare, +- .bdrv_child_perm = bdrv_format_default_perms, ++ .bdrv_child_perm = bdrv_default_perms, + .bdrv_co_readv = vhdx_co_readv, + .bdrv_co_writev = vhdx_co_writev, + .bdrv_co_create = vhdx_co_create, +diff --git a/block/vmdk.c b/block/vmdk.c +index fadc98a262..62da465126 100644 +--- a/block/vmdk.c ++++ b/block/vmdk.c +@@ -3067,7 +3067,7 @@ static BlockDriver bdrv_vmdk = { + .bdrv_open = vmdk_open, + .bdrv_co_check = vmdk_co_check, + .bdrv_reopen_prepare = vmdk_reopen_prepare, +- .bdrv_child_perm = bdrv_format_default_perms, ++ .bdrv_child_perm = bdrv_default_perms, + .bdrv_co_preadv = vmdk_co_preadv, + .bdrv_co_pwritev = vmdk_co_pwritev, + .bdrv_co_pwritev_compressed = vmdk_co_pwritev_compressed, +diff --git a/block/vpc.c b/block/vpc.c +index 651a6737b6..c055591641 100644 +--- a/block/vpc.c ++++ b/block/vpc.c +@@ -1240,7 +1240,7 @@ static BlockDriver bdrv_vpc = { + .bdrv_open = vpc_open, + .bdrv_close = vpc_close, + .bdrv_reopen_prepare = vpc_reopen_prepare, +- .bdrv_child_perm = bdrv_format_default_perms, ++ .bdrv_child_perm = bdrv_default_perms, + .bdrv_co_create = vpc_co_create, + .bdrv_co_create_opts = vpc_co_create_opts, + +diff --git a/tests/test-bdrv-drain.c b/tests/test-bdrv-drain.c +index 91567ca97d..0da5a3a6a1 100644 +--- a/tests/test-bdrv-drain.c ++++ b/tests/test-bdrv-drain.c +@@ -93,15 +93,15 @@ static void bdrv_test_child_perm(BlockDriverState *bs, BdrvChild *c, + uint64_t *nperm, uint64_t *nshared) + { + /* +- * bdrv_format_default_perms() accepts only these two, so disguise ++ * bdrv_default_perms() accepts only these two, so disguise + * detach_by_driver_cb_parent as one of them. + */ + if (child_class != &child_file && child_class != &child_of_bds) { + child_class = &child_of_bds; + } + +- bdrv_format_default_perms(bs, c, child_class, role, reopen_queue, +- perm, shared, nperm, nshared); ++ bdrv_default_perms(bs, c, child_class, role, reopen_queue, ++ perm, shared, nperm, nshared); + } + + static int bdrv_test_change_backing_file(BlockDriverState *bs, +@@ -1137,7 +1137,7 @@ static BlockDriver bdrv_test_top_driver = { + .bdrv_close = bdrv_test_top_close, + .bdrv_co_preadv = bdrv_test_top_co_preadv, + +- .bdrv_child_perm = bdrv_format_default_perms, ++ .bdrv_child_perm = bdrv_default_perms, + }; + + typedef struct TestCoDeleteByDrainData { +@@ -1966,7 +1966,7 @@ static BlockDriver bdrv_replace_test = { + .bdrv_co_drain_begin = bdrv_replace_test_co_drain_begin, + .bdrv_co_drain_end = bdrv_replace_test_co_drain_end, + +- .bdrv_child_perm = bdrv_format_default_perms, ++ .bdrv_child_perm = bdrv_default_perms, + }; + + static void coroutine_fn test_replace_child_mid_drain_read_co(void *opaque) +diff --git a/tests/test-bdrv-graph-mod.c b/tests/test-bdrv-graph-mod.c +index 6ae91ff171..a2d0318b16 100644 +--- a/tests/test-bdrv-graph-mod.c ++++ b/tests/test-bdrv-graph-mod.c +@@ -26,7 +26,7 @@ + + static BlockDriver bdrv_pass_through = { + .format_name = "pass-through", +- .bdrv_child_perm = bdrv_filter_default_perms, ++ .bdrv_child_perm = bdrv_default_perms, + }; + + static void no_perm_default_perms(BlockDriverState *bs, BdrvChild *c, +diff --git a/tests/test-block-iothread.c b/tests/test-block-iothread.c +index 71e9bce3b1..a953794be2 100644 +--- a/tests/test-block-iothread.c ++++ b/tests/test-block-iothread.c +@@ -482,8 +482,13 @@ static void test_propagate_basic(void) + BlockDriverState *bs_a, *bs_b, *bs_verify; + QDict *options; + +- /* Create bs_a and its BlockBackend */ +- blk = blk_new(qemu_get_aio_context(), BLK_PERM_ALL, BLK_PERM_ALL); ++ /* ++ * Create bs_a and its BlockBackend. We cannot take the RESIZE ++ * permission because blkverify will not share it on the test ++ * image. ++ */ ++ blk = blk_new(qemu_get_aio_context(), BLK_PERM_ALL & ~BLK_PERM_RESIZE, ++ BLK_PERM_ALL); + bs_a = bdrv_new_open_driver(&bdrv_test, "bs_a", BDRV_O_RDWR, &error_abort); + blk_insert_bs(blk, bs_a, &error_abort); + +@@ -566,7 +571,13 @@ static void test_propagate_diamond(void) + qdict_put_str(options, "raw", "bs_c"); + + bs_verify = bdrv_open(NULL, NULL, options, BDRV_O_RDWR, &error_abort); +- blk = blk_new(qemu_get_aio_context(), BLK_PERM_ALL, BLK_PERM_ALL); ++ /* ++ * Do not take the RESIZE permission: This would require the same ++ * from bs_c and thus from bs_a; however, blkverify will not share ++ * it on bs_b, and thus it will not be available for bs_a. ++ */ ++ blk = blk_new(qemu_get_aio_context(), BLK_PERM_ALL & ~BLK_PERM_RESIZE, ++ BLK_PERM_ALL); + blk_insert_bs(blk, bs_verify, &error_abort); + + /* Switch the AioContext */ +-- +2.23.0 + diff --git a/block-Use-bdrv_inherited_options.patch b/block-Use-bdrv_inherited_options.patch new file mode 100644 index 0000000000000000000000000000000000000000..1ac706c82cbdf4aecd9be1a8e7e8f957d069473f --- /dev/null +++ b/block-Use-bdrv_inherited_options.patch @@ -0,0 +1,157 @@ +From 00ff7ffd67c50fe45a1e313765d416d082541128 Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Wed, 13 May 2020 13:05:21 +0200 +Subject: [PATCH 543/709] block: Use bdrv_inherited_options() + +Let child_file's, child_format's, and child_backing's .inherit_options() +implementations fall back to bdrv_inherited_options() to show that it +would really work for all of these cases, if only the parents passed the +appropriate BdrvChildRole and parent_is_format values. + +(Also, make bdrv_open_inherit(), the only place to explicitly call +bdrv_backing_options(), call bdrv_inherited_options() instead.) + +This patch should incur only two visible changes, both for child_format +children, both of which are effectively bug fixes: + +First, they no longer have discard=unmap set by default. This reason it +was set is because bdrv_inherited_fmt_options() fell through to +bdrv_protocol_options(), and that set it because "format drivers take +care to send flushes and respect unmap policy". None of the drivers +that use child_format for their children (quorum and blkverify) are +format drivers, though, so this reasoning does not apply here. + +Second, they no longer have BDRV_O_NO_IO force-cleared. child_format +was used solely for children that do not store any metadata and as such +will not be accessed by their parents as long as those parents do not +receive I/O themselves. Thus, such children should inherit +BDRV_O_NO_IO. + +Signed-off-by: Max Reitz +Message-Id: <20200513110544.176672-12-mreitz@redhat.com> +Reviewed-by: Eric Blake +Signed-off-by: Kevin Wolf +--- + block.c | 71 +++++++++++++++------------------------------------------ + 1 file changed, 19 insertions(+), 52 deletions(-) + +diff --git a/block.c b/block.c +index 9b0e13d537..b3b978a092 100644 +--- a/block.c ++++ b/block.c +@@ -80,6 +80,11 @@ static BlockDriverState *bdrv_open_inherit(const char *filename, + BdrvChildRole child_role, + Error **errp); + ++/* TODO: Remove when no longer needed */ ++static void bdrv_inherited_options(BdrvChildRole role, bool parent_is_format, ++ int *child_flags, QDict *child_options, ++ int parent_flags, QDict *parent_options); ++ + /* If non-zero, use only whitelisted block drivers */ + static int use_bdrv_whitelist; + +@@ -1158,31 +1163,9 @@ static void bdrv_protocol_options(BdrvChildRole role, bool parent_is_format, + int *child_flags, QDict *child_options, + int parent_flags, QDict *parent_options) + { +- int flags = parent_flags; +- +- /* Enable protocol handling, disable format probing for bs->file */ +- flags |= BDRV_O_PROTOCOL; +- +- /* If the cache mode isn't explicitly set, inherit direct and no-flush from +- * the parent. */ +- qdict_copy_default(child_options, parent_options, BDRV_OPT_CACHE_DIRECT); +- qdict_copy_default(child_options, parent_options, BDRV_OPT_CACHE_NO_FLUSH); +- qdict_copy_default(child_options, parent_options, BDRV_OPT_FORCE_SHARE); +- +- /* Inherit the read-only option from the parent if it's not set */ +- qdict_copy_default(child_options, parent_options, BDRV_OPT_READ_ONLY); +- qdict_copy_default(child_options, parent_options, BDRV_OPT_AUTO_READ_ONLY); +- +- /* Our block drivers take care to send flushes and respect unmap policy, +- * so we can default to enable both on lower layers regardless of the +- * corresponding parent options. */ +- qdict_set_default_str(child_options, BDRV_OPT_DISCARD, "unmap"); +- +- /* Clear flags that only apply to the top layer */ +- flags &= ~(BDRV_O_SNAPSHOT | BDRV_O_NO_BACKING | BDRV_O_COPY_ON_READ | +- BDRV_O_NO_IO); +- +- *child_flags = flags; ++ bdrv_inherited_options(BDRV_CHILD_IMAGE, true, ++ child_flags, child_options, ++ parent_flags, parent_options); + } + + const BdrvChildClass child_file = { +@@ -1209,11 +1192,9 @@ static void bdrv_inherited_fmt_options(BdrvChildRole role, + int *child_flags, QDict *child_options, + int parent_flags, QDict *parent_options) + { +- child_file.inherit_options(role, parent_is_format, +- child_flags, child_options, +- parent_flags, parent_options); +- +- *child_flags &= ~(BDRV_O_PROTOCOL | BDRV_O_NO_IO); ++ bdrv_inherited_options(BDRV_CHILD_DATA, false, ++ child_flags, child_options, ++ parent_flags, parent_options); + } + + const BdrvChildClass child_format = { +@@ -1295,23 +1276,9 @@ static void bdrv_backing_options(BdrvChildRole role, bool parent_is_format, + int *child_flags, QDict *child_options, + int parent_flags, QDict *parent_options) + { +- int flags = parent_flags; +- +- /* The cache mode is inherited unmodified for backing files; except WCE, +- * which is only applied on the top level (BlockBackend) */ +- qdict_copy_default(child_options, parent_options, BDRV_OPT_CACHE_DIRECT); +- qdict_copy_default(child_options, parent_options, BDRV_OPT_CACHE_NO_FLUSH); +- qdict_copy_default(child_options, parent_options, BDRV_OPT_FORCE_SHARE); +- +- /* backing files always opened read-only */ +- qdict_set_default_str(child_options, BDRV_OPT_READ_ONLY, "on"); +- qdict_set_default_str(child_options, BDRV_OPT_AUTO_READ_ONLY, "off"); +- flags &= ~BDRV_O_COPY_ON_READ; +- +- /* snapshot=on is handled on the top layer */ +- flags &= ~(BDRV_O_SNAPSHOT | BDRV_O_TEMPORARY); +- +- *child_flags = flags; ++ bdrv_inherited_options(BDRV_CHILD_COW, true, ++ child_flags, child_options, ++ parent_flags, parent_options); + } + + static int bdrv_backing_update_filename(BdrvChild *c, BlockDriverState *base, +@@ -1360,10 +1327,9 @@ const BdrvChildClass child_backing = { + * Returns the options and flags that a generic child of a BDS should + * get, based on the given options and flags for the parent BDS. + */ +-static void __attribute__((unused)) +- bdrv_inherited_options(BdrvChildRole role, bool parent_is_format, +- int *child_flags, QDict *child_options, +- int parent_flags, QDict *parent_options) ++static void bdrv_inherited_options(BdrvChildRole role, bool parent_is_format, ++ int *child_flags, QDict *child_options, ++ int parent_flags, QDict *parent_options) + { + int flags = parent_flags; + +@@ -3300,7 +3266,8 @@ static BlockDriverState *bdrv_open_inherit(const char *filename, + flags, options); + /* Let bdrv_backing_options() override "read-only" */ + qdict_del(options, BDRV_OPT_READ_ONLY); +- bdrv_backing_options(0, true, &flags, options, flags, options); ++ bdrv_inherited_options(BDRV_CHILD_COW, true, ++ &flags, options, flags, options); + } + + bs->open_flags = flags; +-- +2.23.0 + diff --git a/block-Use-bdrv_make_empty-where-possible.patch b/block-Use-bdrv_make_empty-where-possible.patch new file mode 100644 index 0000000000000000000000000000000000000000..94137b7508321c6a1c51907b4e436683742ae1a4 --- /dev/null +++ b/block-Use-bdrv_make_empty-where-possible.patch @@ -0,0 +1,48 @@ +From f844ec01b36797e0e5f31f56bfbe49f8c24cc7d4 Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Wed, 29 Apr 2020 16:11:24 +0200 +Subject: [PATCH 532/709] block: Use bdrv_make_empty() where possible + +Signed-off-by: Max Reitz +Reviewed-by: Eric Blake +Reviewed-by: Kevin Wolf +Message-Id: <20200429141126.85159-3-mreitz@redhat.com> +Signed-off-by: Kevin Wolf +--- + block/replication.c | 3 +-- + block/vvfat.c | 4 +--- + 2 files changed, 2 insertions(+), 5 deletions(-) + +diff --git a/block/replication.c b/block/replication.c +index eb480a8e08..9a9f36e524 100644 +--- a/block/replication.c ++++ b/block/replication.c +@@ -331,9 +331,8 @@ static void secondary_do_checkpoint(BDRVReplicationState *s, Error **errp) + return; + } + +- ret = s->active_disk->bs->drv->bdrv_make_empty(s->active_disk->bs); ++ ret = bdrv_make_empty(s->active_disk, errp); + if (ret < 0) { +- error_setg(errp, "Cannot make active disk empty"); + return; + } + +diff --git a/block/vvfat.c b/block/vvfat.c +index 6d5c090dec..34c121c07a 100644 +--- a/block/vvfat.c ++++ b/block/vvfat.c +@@ -2960,9 +2960,7 @@ static int do_commit(BDRVVVFATState* s) + return ret; + } + +- if (s->qcow->bs->drv && s->qcow->bs->drv->bdrv_make_empty) { +- s->qcow->bs->drv->bdrv_make_empty(s->qcow->bs); +- } ++ bdrv_make_empty(s->qcow, NULL); + + memset(s->used_clusters, 0, sector2cluster(s, s->sector_count)); + +-- +2.23.0 + diff --git a/block-Use-blk_make_empty-after-commits.patch b/block-Use-blk_make_empty-after-commits.patch new file mode 100644 index 0000000000000000000000000000000000000000..a11cd605938e6b3c16377e3bcf0aa87caae366ca --- /dev/null +++ b/block-Use-blk_make_empty-after-commits.patch @@ -0,0 +1,134 @@ +From 2d97fde43991829f74e1e258bb82031605bf9bca Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Wed, 29 Apr 2020 16:11:26 +0200 +Subject: [PATCH 530/709] block: Use blk_make_empty() after commits + +bdrv_commit() already has a BlockBackend pointing to the BDS that we +want to empty, it just has the wrong permissions. + +qemu-img commit has no BlockBackend pointing to the old backing file +yet, but introducing one is simple. + +After this commit, bdrv_make_empty() is the only remaining caller of +BlockDriver.bdrv_make_empty(). + +Signed-off-by: Max Reitz +Message-Id: <20200429141126.85159-5-mreitz@redhat.com> +Reviewed-by: Eric Blake +[kwolf: Fixed up reference output for 098] +Signed-off-by: Kevin Wolf +--- + block/commit.c | 16 +++++++++------- + qemu-img.c | 19 ++++++++++++++----- + tests/qemu-iotests/098.out | 8 ++++---- + 3 files changed, 27 insertions(+), 16 deletions(-) + +diff --git a/block/commit.c b/block/commit.c +index 87f6096d90..ba60fb7955 100644 +--- a/block/commit.c ++++ b/block/commit.c +@@ -414,7 +414,9 @@ int bdrv_commit(BlockDriverState *bs) + } + + ctx = bdrv_get_aio_context(bs); +- src = blk_new(ctx, BLK_PERM_CONSISTENT_READ, BLK_PERM_ALL); ++ /* WRITE_UNCHANGED is required for bdrv_make_empty() */ ++ src = blk_new(ctx, BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE_UNCHANGED, ++ BLK_PERM_ALL); + backing = blk_new(ctx, BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL); + + ret = blk_insert_bs(src, bs, &local_err); +@@ -492,14 +494,14 @@ int bdrv_commit(BlockDriverState *bs) + } + } + +- if (drv->bdrv_make_empty) { +- ret = drv->bdrv_make_empty(bs); +- if (ret < 0) { +- goto ro_cleanup; +- } +- blk_flush(src); ++ ret = blk_make_empty(src, NULL); ++ /* Ignore -ENOTSUP */ ++ if (ret < 0 && ret != -ENOTSUP) { ++ goto ro_cleanup; + } + ++ blk_flush(src); ++ + /* + * Make sure all data we wrote to the backing device is actually + * stable on disk. +diff --git a/qemu-img.c b/qemu-img.c +index 6a4327aaba..f1795c788c 100644 +--- a/qemu-img.c ++++ b/qemu-img.c +@@ -1104,11 +1104,20 @@ static int img_commit(int argc, char **argv) + goto unref_backing; + } + +- if (!drop && bs->drv->bdrv_make_empty) { +- ret = bs->drv->bdrv_make_empty(bs); +- if (ret) { +- error_setg_errno(&local_err, -ret, "Could not empty %s", +- filename); ++ if (!drop) { ++ BlockBackend *old_backing_blk; ++ ++ old_backing_blk = blk_new_with_bs(bs, BLK_PERM_WRITE, BLK_PERM_ALL, ++ &local_err); ++ if (!old_backing_blk) { ++ goto unref_backing; ++ } ++ ret = blk_make_empty(old_backing_blk, &local_err); ++ blk_unref(old_backing_blk); ++ if (ret == -ENOTSUP) { ++ error_free(local_err); ++ local_err = NULL; ++ } else if (ret < 0) { + goto unref_backing; + } + } +diff --git a/tests/qemu-iotests/098.out b/tests/qemu-iotests/098.out +index 7634d0e8b0..23cf371f53 100644 +--- a/tests/qemu-iotests/098.out ++++ b/tests/qemu-iotests/098.out +@@ -6,7 +6,7 @@ Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=67108864 + Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file=TEST_DIR/t.IMGFMT.base + wrote 65536/65536 bytes at offset 0 + 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +-qemu-img: Could not empty blkdebug:TEST_DIR/blkdebug.conf:TEST_DIR/t.IMGFMT: Input/output error ++qemu-img: Failed to empty blkdebug:TEST_DIR/blkdebug.conf:TEST_DIR/t.IMGFMT: Input/output error + No errors were found on the image. + + === empty_image_prepare === +@@ -15,7 +15,7 @@ Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=67108864 + Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file=TEST_DIR/t.IMGFMT.base + wrote 65536/65536 bytes at offset 0 + 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +-qemu-img: Could not empty blkdebug:TEST_DIR/blkdebug.conf:TEST_DIR/t.IMGFMT: Input/output error ++qemu-img: Failed to empty blkdebug:TEST_DIR/blkdebug.conf:TEST_DIR/t.IMGFMT: Input/output error + Leaked cluster 4 refcount=1 reference=0 + Leaked cluster 5 refcount=1 reference=0 + Repairing cluster 4 refcount=1 reference=0 +@@ -28,7 +28,7 @@ Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=67108864 + Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file=TEST_DIR/t.IMGFMT.base + wrote 65536/65536 bytes at offset 0 + 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +-qemu-img: Could not empty blkdebug:TEST_DIR/blkdebug.conf:TEST_DIR/t.IMGFMT: Input/output error ++qemu-img: Failed to empty blkdebug:TEST_DIR/blkdebug.conf:TEST_DIR/t.IMGFMT: Input/output error + ERROR cluster 0 refcount=0 reference=1 + ERROR cluster 1 refcount=0 reference=1 + ERROR cluster 3 refcount=0 reference=1 +@@ -42,7 +42,7 @@ Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=67108864 + Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file=TEST_DIR/t.IMGFMT.base + wrote 65536/65536 bytes at offset 0 + 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +-qemu-img: Could not empty blkdebug:TEST_DIR/blkdebug.conf:TEST_DIR/t.IMGFMT: Input/output error ++qemu-img: Failed to empty blkdebug:TEST_DIR/blkdebug.conf:TEST_DIR/t.IMGFMT: Input/output error + ERROR cluster 0 refcount=0 reference=1 + ERROR cluster 1 refcount=0 reference=1 + ERROR cluster 3 refcount=0 reference=1 +-- +2.23.0 + diff --git a/block-Use-child_of_bds-in-remaining-places.patch b/block-Use-child_of_bds-in-remaining-places.patch new file mode 100644 index 0000000000000000000000000000000000000000..3d4361d38cfc54fbb23da0745df2b2d69b755a21 --- /dev/null +++ b/block-Use-child_of_bds-in-remaining-places.patch @@ -0,0 +1,99 @@ +From 58944401d661f22fef15af5a0270ef808a1f4791 Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Wed, 13 May 2020 13:05:37 +0200 +Subject: [PATCH 559/709] block: Use child_of_bds in remaining places + +Replace child_file by child_of_bds in all remaining places (excluding +tests). + +Signed-off-by: Max Reitz +Message-Id: <20200513110544.176672-28-mreitz@redhat.com> +Reviewed-by: Eric Blake +Signed-off-by: Kevin Wolf +--- + block.c | 3 ++- + block/backup-top.c | 4 ++-- + block/blklogwrites.c | 4 ++-- + block/raw-format.c | 15 +++++++++++++-- + 4 files changed, 19 insertions(+), 7 deletions(-) + +diff --git a/block.c b/block.c +index d138a3c261..fb94adcca4 100644 +--- a/block.c ++++ b/block.c +@@ -3406,7 +3406,8 @@ static BlockDriverState *bdrv_open_inherit(const char *filename, + BlockDriverState *file_bs; + + file_bs = bdrv_open_child_bs(filename, options, "file", bs, +- &child_file, 0, true, &local_err); ++ &child_of_bds, BDRV_CHILD_IMAGE, ++ true, &local_err); + if (local_err) { + goto fail; + } +diff --git a/block/backup-top.c b/block/backup-top.c +index f059617095..8af2c5fe9b 100644 +--- a/block/backup-top.c ++++ b/block/backup-top.c +@@ -215,8 +215,8 @@ BlockDriverState *bdrv_backup_top_append(BlockDriverState *source, + source->supported_zero_flags); + + bdrv_ref(target); +- state->target = bdrv_attach_child(top, target, "target", &child_file, 0, +- errp); ++ state->target = bdrv_attach_child(top, target, "target", &child_of_bds, ++ BDRV_CHILD_DATA, errp); + if (!state->target) { + bdrv_unref(target); + bdrv_unref(top); +diff --git a/block/blklogwrites.c b/block/blklogwrites.c +index 78b0c49460..3a57b273fc 100644 +--- a/block/blklogwrites.c ++++ b/block/blklogwrites.c +@@ -167,8 +167,8 @@ static int blk_log_writes_open(BlockDriverState *bs, QDict *options, int flags, + } + + /* Open the log file */ +- s->log_file = bdrv_open_child(NULL, options, "log", bs, &child_file, 0, +- false, &local_err); ++ s->log_file = bdrv_open_child(NULL, options, "log", bs, &child_of_bds, ++ BDRV_CHILD_METADATA, false, &local_err); + if (local_err) { + ret = -EINVAL; + error_propagate(errp, local_err); +diff --git a/block/raw-format.c b/block/raw-format.c +index 824fe70686..bfb4d7ddb7 100644 +--- a/block/raw-format.c ++++ b/block/raw-format.c +@@ -441,6 +441,7 @@ static int raw_open(BlockDriverState *bs, QDict *options, int flags, + BDRVRawState *s = bs->opaque; + bool has_size; + uint64_t offset, size; ++ BdrvChildRole file_role; + int ret; + + ret = raw_read_options(options, &offset, &has_size, &size, errp); +@@ -448,8 +449,18 @@ static int raw_open(BlockDriverState *bs, QDict *options, int flags, + return ret; + } + +- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, 0, +- false, errp); ++ /* ++ * Without offset and a size limit, this driver behaves very much ++ * like a filter. With any such limit, it does not. ++ */ ++ if (offset || has_size) { ++ file_role = BDRV_CHILD_DATA | BDRV_CHILD_PRIMARY; ++ } else { ++ file_role = BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY; ++ } ++ ++ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds, ++ file_role, false, errp); + if (!bs->file) { + return -EINVAL; + } +-- +2.23.0 + diff --git a/block-backend-Add-flags-to-blk_truncate.patch b/block-backend-Add-flags-to-blk_truncate.patch new file mode 100644 index 0000000000000000000000000000000000000000..3173570286f298deb62ad596fff53e3abc0c3d21 --- /dev/null +++ b/block-backend-Add-flags-to-blk_truncate.patch @@ -0,0 +1,282 @@ +From 8c6242b6f383e43fd11d2c50f8bcdd2bba1100fc Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Fri, 24 Apr 2020 14:54:41 +0200 +Subject: [PATCH 128/709] block-backend: Add flags to blk_truncate() + +Now that node level interface bdrv_truncate() supports passing request +flags to the block driver, expose this on the BlockBackend level, too. + +Signed-off-by: Kevin Wolf +Reviewed-by: Vladimir Sementsov-Ogievskiy +Reviewed-by: Alberto Garcia +Reviewed-by: Max Reitz +Message-Id: <20200424125448.63318-4-kwolf@redhat.com> +Signed-off-by: Kevin Wolf +--- + block.c | 3 ++- + block/block-backend.c | 4 ++-- + block/commit.c | 4 ++-- + block/crypto.c | 2 +- + block/mirror.c | 2 +- + block/qcow2.c | 4 ++-- + block/qed.c | 2 +- + block/vdi.c | 2 +- + block/vhdx.c | 4 ++-- + block/vmdk.c | 6 +++--- + block/vpc.c | 2 +- + blockdev.c | 2 +- + include/sysemu/block-backend.h | 2 +- + qemu-img.c | 2 +- + qemu-io-cmds.c | 2 +- + 15 files changed, 22 insertions(+), 21 deletions(-) + +diff --git a/block.c b/block.c +index c11385ae05..301ec588bd 100644 +--- a/block.c ++++ b/block.c +@@ -548,7 +548,8 @@ static int64_t create_file_fallback_truncate(BlockBackend *blk, + int64_t size; + int ret; + +- ret = blk_truncate(blk, minimum_size, false, PREALLOC_MODE_OFF, &local_err); ++ ret = blk_truncate(blk, minimum_size, false, PREALLOC_MODE_OFF, 0, ++ &local_err); + if (ret < 0 && ret != -ENOTSUP) { + error_propagate(errp, local_err); + return ret; +diff --git a/block/block-backend.c b/block/block-backend.c +index 8be20060d3..17ed6d8c5b 100644 +--- a/block/block-backend.c ++++ b/block/block-backend.c +@@ -2137,14 +2137,14 @@ int blk_pwrite_compressed(BlockBackend *blk, int64_t offset, const void *buf, + } + + int blk_truncate(BlockBackend *blk, int64_t offset, bool exact, +- PreallocMode prealloc, Error **errp) ++ PreallocMode prealloc, BdrvRequestFlags flags, Error **errp) + { + if (!blk_is_available(blk)) { + error_setg(errp, "No medium inserted"); + return -ENOMEDIUM; + } + +- return bdrv_truncate(blk->root, offset, exact, prealloc, 0, errp); ++ return bdrv_truncate(blk->root, offset, exact, prealloc, flags, errp); + } + + int blk_save_vmstate(BlockBackend *blk, const uint8_t *buf, +diff --git a/block/commit.c b/block/commit.c +index 8e672799af..87f6096d90 100644 +--- a/block/commit.c ++++ b/block/commit.c +@@ -133,7 +133,7 @@ static int coroutine_fn commit_run(Job *job, Error **errp) + } + + if (base_len < len) { +- ret = blk_truncate(s->base, len, false, PREALLOC_MODE_OFF, NULL); ++ ret = blk_truncate(s->base, len, false, PREALLOC_MODE_OFF, 0, NULL); + if (ret) { + goto out; + } +@@ -458,7 +458,7 @@ int bdrv_commit(BlockDriverState *bs) + * grow the backing file image if possible. If not possible, + * we must return an error */ + if (length > backing_length) { +- ret = blk_truncate(backing, length, false, PREALLOC_MODE_OFF, ++ ret = blk_truncate(backing, length, false, PREALLOC_MODE_OFF, 0, + &local_err); + if (ret < 0) { + error_report_err(local_err); +diff --git a/block/crypto.c b/block/crypto.c +index ab33545c92..e02f343590 100644 +--- a/block/crypto.c ++++ b/block/crypto.c +@@ -115,7 +115,7 @@ static ssize_t block_crypto_init_func(QCryptoBlock *block, + * which will be used by the crypto header + */ + return blk_truncate(data->blk, data->size + headerlen, false, +- data->prealloc, errp); ++ data->prealloc, 0, errp); + } + + +diff --git a/block/mirror.c b/block/mirror.c +index c26fd9260d..aca95c9bc9 100644 +--- a/block/mirror.c ++++ b/block/mirror.c +@@ -900,7 +900,7 @@ static int coroutine_fn mirror_run(Job *job, Error **errp) + + if (s->bdev_length > base_length) { + ret = blk_truncate(s->target, s->bdev_length, false, +- PREALLOC_MODE_OFF, NULL); ++ PREALLOC_MODE_OFF, 0, NULL); + if (ret < 0) { + goto immediate_exit; + } +diff --git a/block/qcow2.c b/block/qcow2.c +index c5b0711357..9cfbdfc939 100644 +--- a/block/qcow2.c ++++ b/block/qcow2.c +@@ -3511,7 +3511,7 @@ qcow2_co_create(BlockdevCreateOptions *create_options, Error **errp) + + /* Okay, now that we have a valid image, let's give it the right size */ + ret = blk_truncate(blk, qcow2_opts->size, false, qcow2_opts->preallocation, +- errp); ++ 0, errp); + if (ret < 0) { + error_prepend(errp, "Could not resize image: "); + goto out; +@@ -5374,7 +5374,7 @@ static int qcow2_amend_options(BlockDriverState *bs, QemuOpts *opts, + * Amending image options should ensure that the image has + * exactly the given new values, so pass exact=true here. + */ +- ret = blk_truncate(blk, new_size, true, PREALLOC_MODE_OFF, errp); ++ ret = blk_truncate(blk, new_size, true, PREALLOC_MODE_OFF, 0, errp); + blk_unref(blk); + if (ret < 0) { + return ret; +diff --git a/block/qed.c b/block/qed.c +index fb6100bd20..b0fdb8f565 100644 +--- a/block/qed.c ++++ b/block/qed.c +@@ -677,7 +677,7 @@ static int coroutine_fn bdrv_qed_co_create(BlockdevCreateOptions *opts, + * The QED format associates file length with allocation status, + * so a new file (which is empty) must have a length of 0. + */ +- ret = blk_truncate(blk, 0, true, PREALLOC_MODE_OFF, errp); ++ ret = blk_truncate(blk, 0, true, PREALLOC_MODE_OFF, 0, errp); + if (ret < 0) { + goto out; + } +diff --git a/block/vdi.c b/block/vdi.c +index e1a11f2aa0..0c7835ae70 100644 +--- a/block/vdi.c ++++ b/block/vdi.c +@@ -875,7 +875,7 @@ static int coroutine_fn vdi_co_do_create(BlockdevCreateOptions *create_options, + + if (image_type == VDI_TYPE_STATIC) { + ret = blk_truncate(blk, offset + blocks * block_size, false, +- PREALLOC_MODE_OFF, errp); ++ PREALLOC_MODE_OFF, 0, errp); + if (ret < 0) { + error_prepend(errp, "Failed to statically allocate file"); + goto exit; +diff --git a/block/vhdx.c b/block/vhdx.c +index 3a33eda99c..45be0a4321 100644 +--- a/block/vhdx.c ++++ b/block/vhdx.c +@@ -1703,13 +1703,13 @@ static int vhdx_create_bat(BlockBackend *blk, BDRVVHDXState *s, + /* All zeroes, so we can just extend the file - the end of the BAT + * is the furthest thing we have written yet */ + ret = blk_truncate(blk, data_file_offset, false, PREALLOC_MODE_OFF, +- errp); ++ 0, errp); + if (ret < 0) { + goto exit; + } + } else if (type == VHDX_TYPE_FIXED) { + ret = blk_truncate(blk, data_file_offset + image_size, false, +- PREALLOC_MODE_OFF, errp); ++ PREALLOC_MODE_OFF, 0, errp); + if (ret < 0) { + goto exit; + } +diff --git a/block/vmdk.c b/block/vmdk.c +index 5de99fe813..8ec18f35a5 100644 +--- a/block/vmdk.c ++++ b/block/vmdk.c +@@ -2118,7 +2118,7 @@ static int vmdk_init_extent(BlockBackend *blk, + int gd_buf_size; + + if (flat) { +- ret = blk_truncate(blk, filesize, false, PREALLOC_MODE_OFF, errp); ++ ret = blk_truncate(blk, filesize, false, PREALLOC_MODE_OFF, 0, errp); + goto exit; + } + magic = cpu_to_be32(VMDK4_MAGIC); +@@ -2182,7 +2182,7 @@ static int vmdk_init_extent(BlockBackend *blk, + } + + ret = blk_truncate(blk, le64_to_cpu(header.grain_offset) << 9, false, +- PREALLOC_MODE_OFF, errp); ++ PREALLOC_MODE_OFF, 0, errp); + if (ret < 0) { + goto exit; + } +@@ -2523,7 +2523,7 @@ static int coroutine_fn vmdk_co_do_create(int64_t size, + /* bdrv_pwrite write padding zeros to align to sector, we don't need that + * for description file */ + if (desc_offset == 0) { +- ret = blk_truncate(blk, desc_len, false, PREALLOC_MODE_OFF, errp); ++ ret = blk_truncate(blk, desc_len, false, PREALLOC_MODE_OFF, 0, errp); + if (ret < 0) { + goto exit; + } +diff --git a/block/vpc.c b/block/vpc.c +index d8141b52da..2d1eade146 100644 +--- a/block/vpc.c ++++ b/block/vpc.c +@@ -898,7 +898,7 @@ static int create_fixed_disk(BlockBackend *blk, uint8_t *buf, + /* Add footer to total size */ + total_size += HEADER_SIZE; + +- ret = blk_truncate(blk, total_size, false, PREALLOC_MODE_OFF, errp); ++ ret = blk_truncate(blk, total_size, false, PREALLOC_MODE_OFF, 0, errp); + if (ret < 0) { + return ret; + } +diff --git a/blockdev.c b/blockdev.c +index 9da960b1e7..dc1a0c7c2f 100644 +--- a/blockdev.c ++++ b/blockdev.c +@@ -2741,7 +2741,7 @@ void qmp_block_resize(bool has_device, const char *device, + } + + bdrv_drained_begin(bs); +- ret = blk_truncate(blk, size, false, PREALLOC_MODE_OFF, errp); ++ ret = blk_truncate(blk, size, false, PREALLOC_MODE_OFF, 0, errp); + bdrv_drained_end(bs); + + out: +diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h +index 9bbdbd63d7..34de7faa81 100644 +--- a/include/sysemu/block-backend.h ++++ b/include/sysemu/block-backend.h +@@ -237,7 +237,7 @@ int coroutine_fn blk_co_pwrite_zeroes(BlockBackend *blk, int64_t offset, + int blk_pwrite_compressed(BlockBackend *blk, int64_t offset, const void *buf, + int bytes); + int blk_truncate(BlockBackend *blk, int64_t offset, bool exact, +- PreallocMode prealloc, Error **errp); ++ PreallocMode prealloc, BdrvRequestFlags flags, Error **errp); + int blk_pdiscard(BlockBackend *blk, int64_t offset, int bytes); + int blk_save_vmstate(BlockBackend *blk, const uint8_t *buf, + int64_t pos, int size); +diff --git a/qemu-img.c b/qemu-img.c +index a2369766f0..6a4327aaba 100644 +--- a/qemu-img.c ++++ b/qemu-img.c +@@ -3897,7 +3897,7 @@ static int img_resize(int argc, char **argv) + * resizing, so pass @exact=true. It is of no use to report + * success when the image has not actually been resized. + */ +- ret = blk_truncate(blk, total_size, true, prealloc, &err); ++ ret = blk_truncate(blk, total_size, true, prealloc, 0, &err); + if (!ret) { + qprintf(quiet, "Image resized.\n"); + } else { +diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c +index 1b7e700020..851f07e8f8 100644 +--- a/qemu-io-cmds.c ++++ b/qemu-io-cmds.c +@@ -1715,7 +1715,7 @@ static int truncate_f(BlockBackend *blk, int argc, char **argv) + * exact=true. It is better to err on the "emit more errors" side + * than to be overly permissive. + */ +- ret = blk_truncate(blk, offset, true, PREALLOC_MODE_OFF, &local_err); ++ ret = blk_truncate(blk, offset, true, PREALLOC_MODE_OFF, 0, &local_err); + if (ret < 0) { + error_report_err(local_err); + return ret; +-- +2.23.0 + diff --git a/block-block-copy-Fix-uninitialized-variable-in-block.patch b/block-block-copy-Fix-uninitialized-variable-in-block.patch new file mode 100644 index 0000000000000000000000000000000000000000..28f917f2394bb9cb1c20dd835503a384c13d6743 --- /dev/null +++ b/block-block-copy-Fix-uninitialized-variable-in-block.patch @@ -0,0 +1,41 @@ +From c78dd00e3529f923280e2ab51e60dfcdad2c6094 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Thu, 7 May 2020 14:11:28 +0200 +Subject: [PATCH 567/709] block/block-copy: Fix uninitialized variable in + block_copy_task_entry +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Fix when building with -Os: + + CC block/block-copy.o + block/block-copy.c: In function ‘block_copy_task_entry’: + block/block-copy.c:428:38: error: ‘error_is_read’ may be used uninitialized in this function [-Werror=maybe-uninitialized] + 428 | t->call_state->error_is_read = error_is_read; + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~ + +Signed-off-by: Philippe Mathieu-Daudé +Message-Id: <20200507121129.29760-2-philmd@redhat.com> +Reviewed-by: Eric Blake +Signed-off-by: Kevin Wolf +--- + block/block-copy.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/block/block-copy.c b/block/block-copy.c +index 4713c8f2a3..7c7f7acbae 100644 +--- a/block/block-copy.c ++++ b/block/block-copy.c +@@ -418,7 +418,7 @@ out: + static coroutine_fn int block_copy_task_entry(AioTask *task) + { + BlockCopyTask *t = container_of(task, BlockCopyTask, task); +- bool error_is_read; ++ bool error_is_read = false; + int ret; + + ret = block_copy_do_copy(t->s, t->offset, t->bytes, t->zeroes, +-- +2.23.0 + diff --git a/block-block-copy-Simplify-block_copy_do_copy.patch b/block-block-copy-Simplify-block_copy_do_copy.patch new file mode 100644 index 0000000000000000000000000000000000000000..6ab30ee145be576aa298896e7673125c784cb089 --- /dev/null +++ b/block-block-copy-Simplify-block_copy_do_copy.patch @@ -0,0 +1,60 @@ +From d7eca542228bf3ca03c615c46ea2253590d57cb7 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Thu, 7 May 2020 14:11:29 +0200 +Subject: [PATCH 568/709] block/block-copy: Simplify block_copy_do_copy() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +block_copy_do_copy() is static, only used in block_copy_task_entry +with the error_is_read argument set. No need to check for it, +simplify. + +Signed-off-by: Philippe Mathieu-Daudé +Message-Id: <20200507121129.29760-3-philmd@redhat.com> +Reviewed-by: Eric Blake +Signed-off-by: Kevin Wolf +--- + block/block-copy.c | 12 +++--------- + 1 file changed, 3 insertions(+), 9 deletions(-) + +diff --git a/block/block-copy.c b/block/block-copy.c +index 7c7f7acbae..bb8d0569f2 100644 +--- a/block/block-copy.c ++++ b/block/block-copy.c +@@ -343,9 +343,7 @@ static int coroutine_fn block_copy_do_copy(BlockCopyState *s, + ~BDRV_REQ_WRITE_COMPRESSED); + if (ret < 0) { + trace_block_copy_write_zeroes_fail(s, offset, ret); +- if (error_is_read) { +- *error_is_read = false; +- } ++ *error_is_read = false; + } + return ret; + } +@@ -393,9 +391,7 @@ static int coroutine_fn block_copy_do_copy(BlockCopyState *s, + ret = bdrv_co_pread(s->source, offset, nbytes, bounce_buffer, 0); + if (ret < 0) { + trace_block_copy_read_fail(s, offset, ret); +- if (error_is_read) { +- *error_is_read = true; +- } ++ *error_is_read = true; + goto out; + } + +@@ -403,9 +399,7 @@ static int coroutine_fn block_copy_do_copy(BlockCopyState *s, + s->write_flags); + if (ret < 0) { + trace_block_copy_write_fail(s, offset, ret); +- if (error_is_read) { +- *error_is_read = false; +- } ++ *error_is_read = false; + goto out; + } + +-- +2.23.0 + diff --git a/block-block-copy-add-state-pointer-to-BlockCopyTask.patch b/block-block-copy-add-state-pointer-to-BlockCopyTask.patch new file mode 100644 index 0000000000000000000000000000000000000000..ec07ca3137309e8a0a6bf9eb9cfb9c7c2fcda022 --- /dev/null +++ b/block-block-copy-add-state-pointer-to-BlockCopyTask.patch @@ -0,0 +1,102 @@ +From 1348a65774d2a5bfbf8ba5c52a07b02126326e17 Mon Sep 17 00:00:00 2001 +From: Vladimir Sementsov-Ogievskiy +Date: Wed, 29 Apr 2020 16:08:45 +0300 +Subject: [PATCH 262/709] block/block-copy: add state pointer to BlockCopyTask + +We are going to use aio-task-pool API, so we'll need state pointer in +BlockCopyTask anyway. Add it now and use where possible. + +Signed-off-by: Vladimir Sementsov-Ogievskiy +Reviewed-by: Max Reitz +Message-Id: <20200429130847.28124-4-vsementsov@virtuozzo.com> +Signed-off-by: Max Reitz +--- + block/block-copy.c | 28 +++++++++++++++------------- + 1 file changed, 15 insertions(+), 13 deletions(-) + +diff --git a/block/block-copy.c b/block/block-copy.c +index 8d1b9ab9f0..35ff9cc3ef 100644 +--- a/block/block-copy.c ++++ b/block/block-copy.c +@@ -25,6 +25,7 @@ + #define BLOCK_COPY_MAX_MEM (128 * MiB) + + typedef struct BlockCopyTask { ++ BlockCopyState *s; + int64_t offset; + int64_t bytes; + QLIST_ENTRY(BlockCopyTask) list; +@@ -116,8 +117,11 @@ static BlockCopyTask *block_copy_task_create(BlockCopyState *s, + bdrv_reset_dirty_bitmap(s->copy_bitmap, offset, bytes); + s->in_flight_bytes += bytes; + +- task->offset = offset; +- task->bytes = bytes; ++ *task = (BlockCopyTask) { ++ .s = s, ++ .offset = offset, ++ .bytes = bytes, ++ }; + qemu_co_queue_init(&task->wait_queue); + QLIST_INSERT_HEAD(&s->tasks, task, list); + +@@ -131,8 +135,7 @@ static BlockCopyTask *block_copy_task_create(BlockCopyState *s, + * wake up all tasks waiting for us (may be some of them are not intersecting + * with shrunk task) + */ +-static void coroutine_fn block_copy_task_shrink(BlockCopyState *s, +- BlockCopyTask *task, ++static void coroutine_fn block_copy_task_shrink(BlockCopyTask *task, + int64_t new_bytes) + { + if (new_bytes == task->bytes) { +@@ -141,20 +144,19 @@ static void coroutine_fn block_copy_task_shrink(BlockCopyState *s, + + assert(new_bytes > 0 && new_bytes < task->bytes); + +- s->in_flight_bytes -= task->bytes - new_bytes; +- bdrv_set_dirty_bitmap(s->copy_bitmap, ++ task->s->in_flight_bytes -= task->bytes - new_bytes; ++ bdrv_set_dirty_bitmap(task->s->copy_bitmap, + task->offset + new_bytes, task->bytes - new_bytes); + + task->bytes = new_bytes; + qemu_co_queue_restart_all(&task->wait_queue); + } + +-static void coroutine_fn block_copy_task_end(BlockCopyState *s, +- BlockCopyTask *task, int ret) ++static void coroutine_fn block_copy_task_end(BlockCopyTask *task, int ret) + { +- s->in_flight_bytes -= task->bytes; ++ task->s->in_flight_bytes -= task->bytes; + if (ret < 0) { +- bdrv_set_dirty_bitmap(s->copy_bitmap, task->offset, task->bytes); ++ bdrv_set_dirty_bitmap(task->s->copy_bitmap, task->offset, task->bytes); + } + QLIST_REMOVE(task, list); + qemu_co_queue_restart_all(&task->wait_queue); +@@ -502,9 +504,9 @@ static int coroutine_fn block_copy_dirty_clusters(BlockCopyState *s, + ret = block_copy_block_status(s, offset, cur_bytes, &status_bytes); + assert(ret >= 0); /* never fail */ + cur_bytes = MIN(cur_bytes, status_bytes); +- block_copy_task_shrink(s, task, cur_bytes); ++ block_copy_task_shrink(task, cur_bytes); + if (s->skip_unallocated && !(ret & BDRV_BLOCK_ALLOCATED)) { +- block_copy_task_end(s, task, 0); ++ block_copy_task_end(task, 0); + progress_set_remaining(s->progress, + bdrv_get_dirty_count(s->copy_bitmap) + + s->in_flight_bytes); +@@ -520,7 +522,7 @@ static int coroutine_fn block_copy_dirty_clusters(BlockCopyState *s, + ret = block_copy_do_copy(s, offset, cur_bytes, ret & BDRV_BLOCK_ZERO, + error_is_read); + co_put_to_shres(s->mem, cur_bytes); +- block_copy_task_end(s, task, ret); ++ block_copy_task_end(task, ret); + if (ret < 0) { + return ret; + } +-- +2.23.0 + diff --git a/block-block-copy-alloc-task-on-each-iteration.patch b/block-block-copy-alloc-task-on-each-iteration.patch new file mode 100644 index 0000000000000000000000000000000000000000..433ab79a0de3fd29fcfc03a4a62039718dbb63ff --- /dev/null +++ b/block-block-copy-alloc-task-on-each-iteration.patch @@ -0,0 +1,83 @@ +From f13e60a973216edc1d793555607533305713c74d Mon Sep 17 00:00:00 2001 +From: Vladimir Sementsov-Ogievskiy +Date: Wed, 29 Apr 2020 16:08:44 +0300 +Subject: [PATCH 261/709] block/block-copy: alloc task on each iteration + +We are going to use aio-task-pool API, so tasks will be handled in +parallel. We need therefore separate allocated task on each iteration. +Introduce this logic now. + +Signed-off-by: Vladimir Sementsov-Ogievskiy +Reviewed-by: Max Reitz +Message-Id: <20200429130847.28124-3-vsementsov@virtuozzo.com> +Signed-off-by: Max Reitz +--- + block/block-copy.c | 18 +++++++++++------- + 1 file changed, 11 insertions(+), 7 deletions(-) + +diff --git a/block/block-copy.c b/block/block-copy.c +index bbb29366dc..8d1b9ab9f0 100644 +--- a/block/block-copy.c ++++ b/block/block-copy.c +@@ -106,9 +106,11 @@ static bool coroutine_fn block_copy_wait_one(BlockCopyState *s, int64_t offset, + } + + /* Called only on full-dirty region */ +-static void block_copy_task_begin(BlockCopyState *s, BlockCopyTask *task, +- int64_t offset, int64_t bytes) ++static BlockCopyTask *block_copy_task_create(BlockCopyState *s, ++ int64_t offset, int64_t bytes) + { ++ BlockCopyTask *task = g_new(BlockCopyTask, 1); ++ + assert(!find_conflicting_task(s, offset, bytes)); + + bdrv_reset_dirty_bitmap(s->copy_bitmap, offset, bytes); +@@ -118,6 +120,8 @@ static void block_copy_task_begin(BlockCopyState *s, BlockCopyTask *task, + task->bytes = bytes; + qemu_co_queue_init(&task->wait_queue); + QLIST_INSERT_HEAD(&s->tasks, task, list); ++ ++ return task; + } + + /* +@@ -472,7 +476,7 @@ static int coroutine_fn block_copy_dirty_clusters(BlockCopyState *s, + assert(QEMU_IS_ALIGNED(bytes, s->cluster_size)); + + while (bytes) { +- BlockCopyTask task; ++ g_autofree BlockCopyTask *task = NULL; + int64_t next_zero, cur_bytes, status_bytes; + + if (!bdrv_dirty_bitmap_get(s->copy_bitmap, offset)) { +@@ -493,14 +497,14 @@ static int coroutine_fn block_copy_dirty_clusters(BlockCopyState *s, + assert(next_zero < offset + cur_bytes); /* no need to do MIN() */ + cur_bytes = next_zero - offset; + } +- block_copy_task_begin(s, &task, offset, cur_bytes); ++ task = block_copy_task_create(s, offset, cur_bytes); + + ret = block_copy_block_status(s, offset, cur_bytes, &status_bytes); + assert(ret >= 0); /* never fail */ + cur_bytes = MIN(cur_bytes, status_bytes); +- block_copy_task_shrink(s, &task, cur_bytes); ++ block_copy_task_shrink(s, task, cur_bytes); + if (s->skip_unallocated && !(ret & BDRV_BLOCK_ALLOCATED)) { +- block_copy_task_end(s, &task, 0); ++ block_copy_task_end(s, task, 0); + progress_set_remaining(s->progress, + bdrv_get_dirty_count(s->copy_bitmap) + + s->in_flight_bytes); +@@ -516,7 +520,7 @@ static int coroutine_fn block_copy_dirty_clusters(BlockCopyState *s, + ret = block_copy_do_copy(s, offset, cur_bytes, ret & BDRV_BLOCK_ZERO, + error_is_read); + co_put_to_shres(s->mem, cur_bytes); +- block_copy_task_end(s, &task, ret); ++ block_copy_task_end(s, task, ret); + if (ret < 0) { + return ret; + } +-- +2.23.0 + diff --git a/block-block-copy-fix-use-after-free-of-task-pointer.patch b/block-block-copy-fix-use-after-free-of-task-pointer.patch new file mode 100644 index 0000000000000000000000000000000000000000..f77f653cd42c2e41213b427998d67ae59553bcd2 --- /dev/null +++ b/block-block-copy-fix-use-after-free-of-task-pointer.patch @@ -0,0 +1,40 @@ +From fc9aefc8c0d3c6392656ea661ce72c1583b70bbd Mon Sep 17 00:00:00 2001 +From: Vladimir Sementsov-Ogievskiy +Date: Thu, 7 May 2020 21:38:00 +0300 +Subject: [PATCH 397/709] block/block-copy: fix use-after-free of task pointer + +Obviously, we should g_free the task after trace point and offset +update. + +Reported-by: Coverity (CID 1428756) +Fixes: 4ce5dd3e9b5ee0fac18625860eb3727399ee965e +Signed-off-by: Vladimir Sementsov-Ogievskiy +Message-Id: <20200507183800.22626-1-vsementsov@virtuozzo.com> +Reviewed-by: Eric Blake +Signed-off-by: Max Reitz +--- + block/block-copy.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/block/block-copy.c b/block/block-copy.c +index 03500680f7..4713c8f2a3 100644 +--- a/block/block-copy.c ++++ b/block/block-copy.c +@@ -591,13 +591,13 @@ static int coroutine_fn block_copy_dirty_clusters(BlockCopyState *s, + } + if (s->skip_unallocated && !(ret & BDRV_BLOCK_ALLOCATED)) { + block_copy_task_end(task, 0); +- g_free(task); + progress_set_remaining(s->progress, + bdrv_get_dirty_count(s->copy_bitmap) + + s->in_flight_bytes); + trace_block_copy_skip_range(s, task->offset, task->bytes); + offset = task_end(task); + bytes = end - offset; ++ g_free(task); + continue; + } + task->zeroes = ret & BDRV_BLOCK_ZERO; +-- +2.23.0 + diff --git a/block-block-copy-refactor-task-creation.patch b/block-block-copy-refactor-task-creation.patch new file mode 100644 index 0000000000000000000000000000000000000000..4974024ba5eb5a6c5ff630f4872db3458a54ac71 --- /dev/null +++ b/block-block-copy-refactor-task-creation.patch @@ -0,0 +1,163 @@ +From 42ac214406e092038b13f02c2ff9768d4dd41e1b Mon Sep 17 00:00:00 2001 +From: Vladimir Sementsov-Ogievskiy +Date: Wed, 29 Apr 2020 16:08:46 +0300 +Subject: [PATCH 263/709] block/block-copy: refactor task creation + +Instead of just relying on the comment "Called only on full-dirty +region" in block_copy_task_create() let's move initial dirty area +search directly to block_copy_task_create(). Let's also use effective +bdrv_dirty_bitmap_next_dirty_area instead of looping through all +non-dirty clusters. + +Signed-off-by: Vladimir Sementsov-Ogievskiy +Reviewed-by: Max Reitz +Message-Id: <20200429130847.28124-5-vsementsov@virtuozzo.com> +Signed-off-by: Max Reitz +--- + block/block-copy.c | 80 ++++++++++++++++++++++++++-------------------- + 1 file changed, 46 insertions(+), 34 deletions(-) + +diff --git a/block/block-copy.c b/block/block-copy.c +index 35ff9cc3ef..f560338647 100644 +--- a/block/block-copy.c ++++ b/block/block-copy.c +@@ -32,6 +32,11 @@ typedef struct BlockCopyTask { + CoQueue wait_queue; /* coroutines blocked on this task */ + } BlockCopyTask; + ++static int64_t task_end(BlockCopyTask *task) ++{ ++ return task->offset + task->bytes; ++} ++ + typedef struct BlockCopyState { + /* + * BdrvChild objects are not owned or managed by block-copy. They are +@@ -106,17 +111,29 @@ static bool coroutine_fn block_copy_wait_one(BlockCopyState *s, int64_t offset, + return true; + } + +-/* Called only on full-dirty region */ ++/* ++ * Search for the first dirty area in offset/bytes range and create task at ++ * the beginning of it. ++ */ + static BlockCopyTask *block_copy_task_create(BlockCopyState *s, + int64_t offset, int64_t bytes) + { +- BlockCopyTask *task = g_new(BlockCopyTask, 1); ++ BlockCopyTask *task; + ++ if (!bdrv_dirty_bitmap_next_dirty_area(s->copy_bitmap, ++ offset, offset + bytes, ++ s->copy_size, &offset, &bytes)) ++ { ++ return NULL; ++ } ++ ++ /* region is dirty, so no existent tasks possible in it */ + assert(!find_conflicting_task(s, offset, bytes)); + + bdrv_reset_dirty_bitmap(s->copy_bitmap, offset, bytes); + s->in_flight_bytes += bytes; + ++ task = g_new(BlockCopyTask, 1); + *task = (BlockCopyTask) { + .s = s, + .offset = offset, +@@ -466,6 +483,7 @@ static int coroutine_fn block_copy_dirty_clusters(BlockCopyState *s, + { + int ret = 0; + bool found_dirty = false; ++ int64_t end = offset + bytes; + + /* + * block_copy() user is responsible for keeping source and target in same +@@ -479,58 +497,52 @@ static int coroutine_fn block_copy_dirty_clusters(BlockCopyState *s, + + while (bytes) { + g_autofree BlockCopyTask *task = NULL; +- int64_t next_zero, cur_bytes, status_bytes; ++ int64_t status_bytes; + +- if (!bdrv_dirty_bitmap_get(s->copy_bitmap, offset)) { +- trace_block_copy_skip(s, offset); +- offset += s->cluster_size; +- bytes -= s->cluster_size; +- continue; /* already copied */ ++ task = block_copy_task_create(s, offset, bytes); ++ if (!task) { ++ /* No more dirty bits in the bitmap */ ++ trace_block_copy_skip_range(s, offset, bytes); ++ break; ++ } ++ if (task->offset > offset) { ++ trace_block_copy_skip_range(s, offset, task->offset - offset); + } + + found_dirty = true; + +- cur_bytes = MIN(bytes, s->copy_size); +- +- next_zero = bdrv_dirty_bitmap_next_zero(s->copy_bitmap, offset, +- cur_bytes); +- if (next_zero >= 0) { +- assert(next_zero > offset); /* offset is dirty */ +- assert(next_zero < offset + cur_bytes); /* no need to do MIN() */ +- cur_bytes = next_zero - offset; +- } +- task = block_copy_task_create(s, offset, cur_bytes); +- +- ret = block_copy_block_status(s, offset, cur_bytes, &status_bytes); ++ ret = block_copy_block_status(s, task->offset, task->bytes, ++ &status_bytes); + assert(ret >= 0); /* never fail */ +- cur_bytes = MIN(cur_bytes, status_bytes); +- block_copy_task_shrink(task, cur_bytes); ++ if (status_bytes < task->bytes) { ++ block_copy_task_shrink(task, status_bytes); ++ } + if (s->skip_unallocated && !(ret & BDRV_BLOCK_ALLOCATED)) { + block_copy_task_end(task, 0); + progress_set_remaining(s->progress, + bdrv_get_dirty_count(s->copy_bitmap) + + s->in_flight_bytes); +- trace_block_copy_skip_range(s, offset, status_bytes); +- offset += status_bytes; +- bytes -= status_bytes; ++ trace_block_copy_skip_range(s, task->offset, task->bytes); ++ offset = task_end(task); ++ bytes = end - offset; + continue; + } + +- trace_block_copy_process(s, offset); ++ trace_block_copy_process(s, task->offset); + +- co_get_from_shres(s->mem, cur_bytes); +- ret = block_copy_do_copy(s, offset, cur_bytes, ret & BDRV_BLOCK_ZERO, +- error_is_read); +- co_put_to_shres(s->mem, cur_bytes); ++ co_get_from_shres(s->mem, task->bytes); ++ ret = block_copy_do_copy(s, task->offset, task->bytes, ++ ret & BDRV_BLOCK_ZERO, error_is_read); ++ co_put_to_shres(s->mem, task->bytes); + block_copy_task_end(task, ret); + if (ret < 0) { + return ret; + } + +- progress_work_done(s->progress, cur_bytes); +- s->progress_bytes_callback(cur_bytes, s->progress_opaque); +- offset += cur_bytes; +- bytes -= cur_bytes; ++ progress_work_done(s->progress, task->bytes); ++ s->progress_bytes_callback(task->bytes, s->progress_opaque); ++ offset = task_end(task); ++ bytes = end - offset; + } + + return found_dirty; +-- +2.23.0 + diff --git a/block-block-copy-rename-in-flight-requests-to-tasks.patch b/block-block-copy-rename-in-flight-requests-to-tasks.patch new file mode 100644 index 0000000000000000000000000000000000000000..2141395b4da9ecf21f2c8b04d28d9a644c1b6d87 --- /dev/null +++ b/block-block-copy-rename-in-flight-requests-to-tasks.patch @@ -0,0 +1,221 @@ +From e9407785cce67cab85a76727d393dbf7d924f6d7 Mon Sep 17 00:00:00 2001 +From: Vladimir Sementsov-Ogievskiy +Date: Wed, 29 Apr 2020 16:08:43 +0300 +Subject: [PATCH 260/709] block/block-copy: rename in-flight requests to tasks + +We are going to use aio-task-pool API and extend in-flight request +structure to be a successor of AioTask, so rename things appropriately. + +Signed-off-by: Vladimir Sementsov-Ogievskiy +Reviewed-by: Max Reitz +Message-Id: <20200429130847.28124-2-vsementsov@virtuozzo.com> +Signed-off-by: Max Reitz +--- + block/block-copy.c | 98 +++++++++++++++++++++++----------------------- + 1 file changed, 48 insertions(+), 50 deletions(-) + +diff --git a/block/block-copy.c b/block/block-copy.c +index 05227e18bf..bbb29366dc 100644 +--- a/block/block-copy.c ++++ b/block/block-copy.c +@@ -24,12 +24,12 @@ + #define BLOCK_COPY_MAX_BUFFER (1 * MiB) + #define BLOCK_COPY_MAX_MEM (128 * MiB) + +-typedef struct BlockCopyInFlightReq { ++typedef struct BlockCopyTask { + int64_t offset; + int64_t bytes; +- QLIST_ENTRY(BlockCopyInFlightReq) list; +- CoQueue wait_queue; /* coroutines blocked on this request */ +-} BlockCopyInFlightReq; ++ QLIST_ENTRY(BlockCopyTask) list; ++ CoQueue wait_queue; /* coroutines blocked on this task */ ++} BlockCopyTask; + + typedef struct BlockCopyState { + /* +@@ -45,7 +45,7 @@ typedef struct BlockCopyState { + bool use_copy_range; + int64_t copy_size; + uint64_t len; +- QLIST_HEAD(, BlockCopyInFlightReq) inflight_reqs; ++ QLIST_HEAD(, BlockCopyTask) tasks; + + BdrvRequestFlags write_flags; + +@@ -73,15 +73,14 @@ typedef struct BlockCopyState { + SharedResource *mem; + } BlockCopyState; + +-static BlockCopyInFlightReq *find_conflicting_inflight_req(BlockCopyState *s, +- int64_t offset, +- int64_t bytes) ++static BlockCopyTask *find_conflicting_task(BlockCopyState *s, ++ int64_t offset, int64_t bytes) + { +- BlockCopyInFlightReq *req; ++ BlockCopyTask *t; + +- QLIST_FOREACH(req, &s->inflight_reqs, list) { +- if (offset + bytes > req->offset && offset < req->offset + req->bytes) { +- return req; ++ QLIST_FOREACH(t, &s->tasks, list) { ++ if (offset + bytes > t->offset && offset < t->offset + t->bytes) { ++ return t; + } + } + +@@ -89,73 +88,72 @@ static BlockCopyInFlightReq *find_conflicting_inflight_req(BlockCopyState *s, + } + + /* +- * If there are no intersecting requests return false. Otherwise, wait for the +- * first found intersecting request to finish and return true. ++ * If there are no intersecting tasks return false. Otherwise, wait for the ++ * first found intersecting tasks to finish and return true. + */ + static bool coroutine_fn block_copy_wait_one(BlockCopyState *s, int64_t offset, + int64_t bytes) + { +- BlockCopyInFlightReq *req = find_conflicting_inflight_req(s, offset, bytes); ++ BlockCopyTask *task = find_conflicting_task(s, offset, bytes); + +- if (!req) { ++ if (!task) { + return false; + } + +- qemu_co_queue_wait(&req->wait_queue, NULL); ++ qemu_co_queue_wait(&task->wait_queue, NULL); + + return true; + } + + /* Called only on full-dirty region */ +-static void block_copy_inflight_req_begin(BlockCopyState *s, +- BlockCopyInFlightReq *req, +- int64_t offset, int64_t bytes) ++static void block_copy_task_begin(BlockCopyState *s, BlockCopyTask *task, ++ int64_t offset, int64_t bytes) + { +- assert(!find_conflicting_inflight_req(s, offset, bytes)); ++ assert(!find_conflicting_task(s, offset, bytes)); + + bdrv_reset_dirty_bitmap(s->copy_bitmap, offset, bytes); + s->in_flight_bytes += bytes; + +- req->offset = offset; +- req->bytes = bytes; +- qemu_co_queue_init(&req->wait_queue); +- QLIST_INSERT_HEAD(&s->inflight_reqs, req, list); ++ task->offset = offset; ++ task->bytes = bytes; ++ qemu_co_queue_init(&task->wait_queue); ++ QLIST_INSERT_HEAD(&s->tasks, task, list); + } + + /* +- * block_copy_inflight_req_shrink ++ * block_copy_task_shrink + * +- * Drop the tail of the request to be handled later. Set dirty bits back and +- * wake up all requests waiting for us (may be some of them are not intersecting +- * with shrunk request) ++ * Drop the tail of the task to be handled later. Set dirty bits back and ++ * wake up all tasks waiting for us (may be some of them are not intersecting ++ * with shrunk task) + */ +-static void coroutine_fn block_copy_inflight_req_shrink(BlockCopyState *s, +- BlockCopyInFlightReq *req, int64_t new_bytes) ++static void coroutine_fn block_copy_task_shrink(BlockCopyState *s, ++ BlockCopyTask *task, ++ int64_t new_bytes) + { +- if (new_bytes == req->bytes) { ++ if (new_bytes == task->bytes) { + return; + } + +- assert(new_bytes > 0 && new_bytes < req->bytes); ++ assert(new_bytes > 0 && new_bytes < task->bytes); + +- s->in_flight_bytes -= req->bytes - new_bytes; ++ s->in_flight_bytes -= task->bytes - new_bytes; + bdrv_set_dirty_bitmap(s->copy_bitmap, +- req->offset + new_bytes, req->bytes - new_bytes); ++ task->offset + new_bytes, task->bytes - new_bytes); + +- req->bytes = new_bytes; +- qemu_co_queue_restart_all(&req->wait_queue); ++ task->bytes = new_bytes; ++ qemu_co_queue_restart_all(&task->wait_queue); + } + +-static void coroutine_fn block_copy_inflight_req_end(BlockCopyState *s, +- BlockCopyInFlightReq *req, +- int ret) ++static void coroutine_fn block_copy_task_end(BlockCopyState *s, ++ BlockCopyTask *task, int ret) + { +- s->in_flight_bytes -= req->bytes; ++ s->in_flight_bytes -= task->bytes; + if (ret < 0) { +- bdrv_set_dirty_bitmap(s->copy_bitmap, req->offset, req->bytes); ++ bdrv_set_dirty_bitmap(s->copy_bitmap, task->offset, task->bytes); + } +- QLIST_REMOVE(req, list); +- qemu_co_queue_restart_all(&req->wait_queue); ++ QLIST_REMOVE(task, list); ++ qemu_co_queue_restart_all(&task->wait_queue); + } + + void block_copy_state_free(BlockCopyState *s) +@@ -223,7 +221,7 @@ BlockCopyState *block_copy_state_new(BdrvChild *source, BdrvChild *target, + s->copy_size = MAX(s->cluster_size, BLOCK_COPY_MAX_BUFFER); + } + +- QLIST_INIT(&s->inflight_reqs); ++ QLIST_INIT(&s->tasks); + + return s; + } +@@ -474,7 +472,7 @@ static int coroutine_fn block_copy_dirty_clusters(BlockCopyState *s, + assert(QEMU_IS_ALIGNED(bytes, s->cluster_size)); + + while (bytes) { +- BlockCopyInFlightReq req; ++ BlockCopyTask task; + int64_t next_zero, cur_bytes, status_bytes; + + if (!bdrv_dirty_bitmap_get(s->copy_bitmap, offset)) { +@@ -495,14 +493,14 @@ static int coroutine_fn block_copy_dirty_clusters(BlockCopyState *s, + assert(next_zero < offset + cur_bytes); /* no need to do MIN() */ + cur_bytes = next_zero - offset; + } +- block_copy_inflight_req_begin(s, &req, offset, cur_bytes); ++ block_copy_task_begin(s, &task, offset, cur_bytes); + + ret = block_copy_block_status(s, offset, cur_bytes, &status_bytes); + assert(ret >= 0); /* never fail */ + cur_bytes = MIN(cur_bytes, status_bytes); +- block_copy_inflight_req_shrink(s, &req, cur_bytes); ++ block_copy_task_shrink(s, &task, cur_bytes); + if (s->skip_unallocated && !(ret & BDRV_BLOCK_ALLOCATED)) { +- block_copy_inflight_req_end(s, &req, 0); ++ block_copy_task_end(s, &task, 0); + progress_set_remaining(s->progress, + bdrv_get_dirty_count(s->copy_bitmap) + + s->in_flight_bytes); +@@ -518,7 +516,7 @@ static int coroutine_fn block_copy_dirty_clusters(BlockCopyState *s, + ret = block_copy_do_copy(s, offset, cur_bytes, ret & BDRV_BLOCK_ZERO, + error_is_read); + co_put_to_shres(s->mem, cur_bytes); +- block_copy_inflight_req_end(s, &req, ret); ++ block_copy_task_end(s, &task, ret); + if (ret < 0) { + return ret; + } +-- +2.23.0 + diff --git a/block-block-copy-use-aio-task-pool-API.patch b/block-block-copy-use-aio-task-pool-API.patch new file mode 100644 index 0000000000000000000000000000000000000000..098bdde34f6067ba6cf55ffdf0e3d23b3eb78aa0 --- /dev/null +++ b/block-block-copy-use-aio-task-pool-API.patch @@ -0,0 +1,232 @@ +From 4ce5dd3e9b5ee0fac18625860eb3727399ee965e Mon Sep 17 00:00:00 2001 +From: Vladimir Sementsov-Ogievskiy +Date: Wed, 29 Apr 2020 16:08:47 +0300 +Subject: [PATCH 264/709] block/block-copy: use aio-task-pool API + +Run block_copy iterations in parallel in aio tasks. + +Changes: + - BlockCopyTask becomes aio task structure. Add zeroes field to pass + it to block_copy_do_copy + - add call state - it's a state of one call of block_copy(), shared + between parallel tasks. For now used only to keep information about + first error: is it read or not. + - convert block_copy_dirty_clusters to aio-task loop. + +Signed-off-by: Vladimir Sementsov-Ogievskiy +Message-Id: <20200429130847.28124-6-vsementsov@virtuozzo.com> +Signed-off-by: Max Reitz +--- + block/block-copy.c | 119 ++++++++++++++++++++++++++++++++++++++++----- + 1 file changed, 106 insertions(+), 13 deletions(-) + +diff --git a/block/block-copy.c b/block/block-copy.c +index f560338647..03500680f7 100644 +--- a/block/block-copy.c ++++ b/block/block-copy.c +@@ -19,15 +19,29 @@ + #include "block/block-copy.h" + #include "sysemu/block-backend.h" + #include "qemu/units.h" ++#include "qemu/coroutine.h" ++#include "block/aio_task.h" + + #define BLOCK_COPY_MAX_COPY_RANGE (16 * MiB) + #define BLOCK_COPY_MAX_BUFFER (1 * MiB) + #define BLOCK_COPY_MAX_MEM (128 * MiB) ++#define BLOCK_COPY_MAX_WORKERS 64 ++ ++static coroutine_fn int block_copy_task_entry(AioTask *task); ++ ++typedef struct BlockCopyCallState { ++ bool failed; ++ bool error_is_read; ++} BlockCopyCallState; + + typedef struct BlockCopyTask { ++ AioTask task; ++ + BlockCopyState *s; ++ BlockCopyCallState *call_state; + int64_t offset; + int64_t bytes; ++ bool zeroes; + QLIST_ENTRY(BlockCopyTask) list; + CoQueue wait_queue; /* coroutines blocked on this task */ + } BlockCopyTask; +@@ -116,6 +130,7 @@ static bool coroutine_fn block_copy_wait_one(BlockCopyState *s, int64_t offset, + * the beginning of it. + */ + static BlockCopyTask *block_copy_task_create(BlockCopyState *s, ++ BlockCopyCallState *call_state, + int64_t offset, int64_t bytes) + { + BlockCopyTask *task; +@@ -135,7 +150,9 @@ static BlockCopyTask *block_copy_task_create(BlockCopyState *s, + + task = g_new(BlockCopyTask, 1); + *task = (BlockCopyTask) { ++ .task.func = block_copy_task_entry, + .s = s, ++ .call_state = call_state, + .offset = offset, + .bytes = bytes, + }; +@@ -263,6 +280,38 @@ void block_copy_set_progress_meter(BlockCopyState *s, ProgressMeter *pm) + s->progress = pm; + } + ++/* ++ * Takes ownership of @task ++ * ++ * If pool is NULL directly run the task, otherwise schedule it into the pool. ++ * ++ * Returns: task.func return code if pool is NULL ++ * otherwise -ECANCELED if pool status is bad ++ * otherwise 0 (successfully scheduled) ++ */ ++static coroutine_fn int block_copy_task_run(AioTaskPool *pool, ++ BlockCopyTask *task) ++{ ++ if (!pool) { ++ int ret = task->task.func(&task->task); ++ ++ g_free(task); ++ return ret; ++ } ++ ++ aio_task_pool_wait_slot(pool); ++ if (aio_task_pool_status(pool) < 0) { ++ co_put_to_shres(task->s->mem, task->bytes); ++ block_copy_task_end(task, -ECANCELED); ++ g_free(task); ++ return -ECANCELED; ++ } ++ ++ aio_task_pool_start_task(pool, &task->task); ++ ++ return 0; ++} ++ + /* + * block_copy_do_copy + * +@@ -366,6 +415,27 @@ out: + return ret; + } + ++static coroutine_fn int block_copy_task_entry(AioTask *task) ++{ ++ BlockCopyTask *t = container_of(task, BlockCopyTask, task); ++ bool error_is_read; ++ int ret; ++ ++ ret = block_copy_do_copy(t->s, t->offset, t->bytes, t->zeroes, ++ &error_is_read); ++ if (ret < 0 && !t->call_state->failed) { ++ t->call_state->failed = true; ++ t->call_state->error_is_read = error_is_read; ++ } else { ++ progress_work_done(t->s->progress, t->bytes); ++ t->s->progress_bytes_callback(t->bytes, t->s->progress_opaque); ++ } ++ co_put_to_shres(t->s->mem, t->bytes); ++ block_copy_task_end(t, ret); ++ ++ return ret; ++} ++ + static int block_copy_block_status(BlockCopyState *s, int64_t offset, + int64_t bytes, int64_t *pnum) + { +@@ -484,6 +554,8 @@ static int coroutine_fn block_copy_dirty_clusters(BlockCopyState *s, + int ret = 0; + bool found_dirty = false; + int64_t end = offset + bytes; ++ AioTaskPool *aio = NULL; ++ BlockCopyCallState call_state = {false, false}; + + /* + * block_copy() user is responsible for keeping source and target in same +@@ -495,11 +567,11 @@ static int coroutine_fn block_copy_dirty_clusters(BlockCopyState *s, + assert(QEMU_IS_ALIGNED(offset, s->cluster_size)); + assert(QEMU_IS_ALIGNED(bytes, s->cluster_size)); + +- while (bytes) { +- g_autofree BlockCopyTask *task = NULL; ++ while (bytes && aio_task_pool_status(aio) == 0) { ++ BlockCopyTask *task; + int64_t status_bytes; + +- task = block_copy_task_create(s, offset, bytes); ++ task = block_copy_task_create(s, &call_state, offset, bytes); + if (!task) { + /* No more dirty bits in the bitmap */ + trace_block_copy_skip_range(s, offset, bytes); +@@ -519,6 +591,7 @@ static int coroutine_fn block_copy_dirty_clusters(BlockCopyState *s, + } + if (s->skip_unallocated && !(ret & BDRV_BLOCK_ALLOCATED)) { + block_copy_task_end(task, 0); ++ g_free(task); + progress_set_remaining(s->progress, + bdrv_get_dirty_count(s->copy_bitmap) + + s->in_flight_bytes); +@@ -527,25 +600,45 @@ static int coroutine_fn block_copy_dirty_clusters(BlockCopyState *s, + bytes = end - offset; + continue; + } ++ task->zeroes = ret & BDRV_BLOCK_ZERO; + + trace_block_copy_process(s, task->offset); + + co_get_from_shres(s->mem, task->bytes); +- ret = block_copy_do_copy(s, task->offset, task->bytes, +- ret & BDRV_BLOCK_ZERO, error_is_read); +- co_put_to_shres(s->mem, task->bytes); +- block_copy_task_end(task, ret); +- if (ret < 0) { +- return ret; +- } + +- progress_work_done(s->progress, task->bytes); +- s->progress_bytes_callback(task->bytes, s->progress_opaque); + offset = task_end(task); + bytes = end - offset; ++ ++ if (!aio && bytes) { ++ aio = aio_task_pool_new(BLOCK_COPY_MAX_WORKERS); ++ } ++ ++ ret = block_copy_task_run(aio, task); ++ if (ret < 0) { ++ goto out; ++ } ++ } ++ ++out: ++ if (aio) { ++ aio_task_pool_wait_all(aio); ++ ++ /* ++ * We are not really interested in -ECANCELED returned from ++ * block_copy_task_run. If it fails, it means some task already failed ++ * for real reason, let's return first failure. ++ * Still, assert that we don't rewrite failure by success. ++ */ ++ assert(ret == 0 || aio_task_pool_status(aio) < 0); ++ ret = aio_task_pool_status(aio); ++ ++ aio_task_pool_free(aio); ++ } ++ if (error_is_read && ret < 0) { ++ *error_is_read = call_state.error_is_read; + } + +- return found_dirty; ++ return ret < 0 ? ret : found_dirty; + } + + /* +-- +2.23.0 + diff --git a/block-create-Do-not-abort-if-a-block-driver-is-not-available.patch b/block-create-Do-not-abort-if-a-block-driver-is-not-available.patch deleted file mode 100644 index ef0a880e9ae3b75de51578bd9bce2bd6da846ccf..0000000000000000000000000000000000000000 --- a/block-create-Do-not-abort-if-a-block-driver-is-not-available.patch +++ /dev/null @@ -1,96 +0,0 @@ -From c24d971c130d889d4d001d2ae2cb02b9a34d51b6 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= -Date: Thu, 12 Sep 2019 00:08:49 +0200 -Subject: [PATCH] block/create: Do not abort if a block driver is not available -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -The 'blockdev-create' QMP command was introduced as experimental -feature in commit b0292b851b8, using the assert() debug call. -It got promoted to 'stable' command in 3fb588a0f2c, but the -assert call was not removed. - -Some block drivers are optional, and bdrv_find_format() might -return a NULL value, triggering the assertion. - -Stable code is not expected to abort, so return an error instead. - -This is easily reproducible when libnfs is not installed: - - ./configure - [...] - module support no - Block whitelist (rw) - Block whitelist (ro) - libiscsi support yes - libnfs support no - [...] - -Start QEMU: - - $ qemu-system-x86_64 -S -qmp unix:/tmp/qemu.qmp,server,nowait - -Send the 'blockdev-create' with the 'nfs' driver: - - $ ( cat << 'EOF' - {'execute': 'qmp_capabilities'} - {'execute': 'blockdev-create', 'arguments': {'job-id': 'x', 'options': {'size': 0, 'driver': 'nfs', 'location': {'path': '/', 'server': {'host': '::1', 'type': 'inet'}}}}, 'id': 'x'} - EOF - ) | socat STDIO UNIX:/tmp/qemu.qmp - {"QMP": {"version": {"qemu": {"micro": 50, "minor": 1, "major": 4}, "package": "v4.1.0-733-g89ea03a7dc"}, "capabilities": ["oob"]}} - {"return": {}} - -QEMU crashes: - - $ gdb qemu-system-x86_64 core - Program received signal SIGSEGV, Segmentation fault. - (gdb) bt - #0 0x00007ffff510957f in raise () at /lib64/libc.so.6 - #1 0x00007ffff50f3895 in abort () at /lib64/libc.so.6 - #2 0x00007ffff50f3769 in _nl_load_domain.cold.0 () at /lib64/libc.so.6 - #3 0x00007ffff5101a26 in .annobin_assert.c_end () at /lib64/libc.so.6 - #4 0x0000555555d7e1f1 in qmp_blockdev_create (job_id=0x555556baee40 "x", options=0x555557666610, errp=0x7fffffffc770) at block/create.c:69 - #5 0x0000555555c96b52 in qmp_marshal_blockdev_create (args=0x7fffdc003830, ret=0x7fffffffc7f8, errp=0x7fffffffc7f0) at qapi/qapi-commands-block-core.c:1314 - #6 0x0000555555deb0a0 in do_qmp_dispatch (cmds=0x55555645de70 , request=0x7fffdc005c70, allow_oob=false, errp=0x7fffffffc898) at qapi/qmp-dispatch.c:131 - #7 0x0000555555deb2a1 in qmp_dispatch (cmds=0x55555645de70 , request=0x7fffdc005c70, allow_oob=false) at qapi/qmp-dispatch.c:174 - -With this patch applied, QEMU returns a QMP error: - - {'execute': 'blockdev-create', 'arguments': {'job-id': 'x', 'options': {'size': 0, 'driver': 'nfs', 'location': {'path': '/', 'server': {'host': '::1', 'type': 'inet'}}}}, 'id': 'x'} - {"id": "x", "error": {"class": "GenericError", "desc": "Block driver 'nfs' not found or not supported"}} - -Cc: qemu-stable@nongnu.org -Reported-by: Xu Tian -Signed-off-by: Philippe Mathieu-Daudé -Reviewed-by: Eric Blake -Reviewed-by: John Snow -Signed-off-by: Kevin Wolf -(cherry picked from commit d90d5cae2b10efc0e8d0b3cc91ff16201853d3ba) -Signed-off-by: Michael Roth ---- - block/create.c | 6 +++++- - 1 file changed, 5 insertions(+), 1 deletion(-) - -diff --git a/block/create.c b/block/create.c -index 95341219ef..de5e97bb18 100644 ---- a/block/create.c -+++ b/block/create.c -@@ -63,9 +63,13 @@ void qmp_blockdev_create(const char *job_id, BlockdevCreateOptions *options, - const char *fmt = BlockdevDriver_str(options->driver); - BlockDriver *drv = bdrv_find_format(fmt); - -+ if (!drv) { -+ error_setg(errp, "Block driver '%s' not found or not supported", fmt); -+ return; -+ } -+ - /* If the driver is in the schema, we know that it exists. But it may not - * be whitelisted. */ -- assert(drv); - if (bdrv_uses_whitelist() && !bdrv_is_whitelisted(drv, false)) { - error_setg(errp, "Driver is not whitelisted"); - return; --- -2.19.1 - diff --git a/block-file-posix-Fix-check_cache_dropped-error-handl.patch b/block-file-posix-Fix-check_cache_dropped-error-handl.patch new file mode 100644 index 0000000000000000000000000000000000000000..be5fbaa3002093d6aeec7a52ee16cae5b2acb008 --- /dev/null +++ b/block-file-posix-Fix-check_cache_dropped-error-handl.patch @@ -0,0 +1,49 @@ +From 77ed971b9d96a288e497509054e1e59493ffd1fc Mon Sep 17 00:00:00 2001 +From: Markus Armbruster +Date: Wed, 22 Apr 2020 15:07:07 +0200 +Subject: [PATCH 015/709] block/file-posix: Fix check_cache_dropped() error + handling + +The Error ** argument must be NULL, &error_abort, &error_fatal, or a +pointer to a variable containing NULL. Passing an argument of the +latter kind twice without clearing it in between is wrong: if the +first call sets an error, it no longer points to NULL for the second +call. + +check_cache_dropped() calls error_setg() in a loop. It fails to break +the loop in one instance. If a subsequent iteration error_setg()s +again, it trips error_setv()'s assertion. + +Fix it to break the loop. + +Fixes: 31be8a2a97ecba7d31a82932286489cac318e9e9 +Cc: Stefan Hajnoczi +Signed-off-by: Markus Armbruster +Reviewed-by: Eric Blake +Message-Id: <20200422130719.28225-3-armbru@redhat.com> +--- + block/file-posix.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/block/file-posix.c b/block/file-posix.c +index 7e19bbff5f..094e3b0212 100644 +--- a/block/file-posix.c ++++ b/block/file-posix.c +@@ -2691,10 +2691,13 @@ static void check_cache_dropped(BlockDriverState *bs, Error **errp) + vec_end = DIV_ROUND_UP(length, page_size); + for (i = 0; i < vec_end; i++) { + if (vec[i] & 0x1) { +- error_setg(errp, "page cache still in use!"); + break; + } + } ++ if (i < vec_end) { ++ error_setg(errp, "page cache still in use!"); ++ break; ++ } + } + + if (window) { +-- +2.23.0 + diff --git a/block-file-posix-Unaligned-O_DIRECT-block-status.patch b/block-file-posix-Unaligned-O_DIRECT-block-status.patch deleted file mode 100644 index 40d84c8e501223cba411ca2beb10ec3345673823..0000000000000000000000000000000000000000 --- a/block-file-posix-Unaligned-O_DIRECT-block-status.patch +++ /dev/null @@ -1,87 +0,0 @@ -From 9c3db310ff0b7473272ae8dce5e04e2f8a825390 Mon Sep 17 00:00:00 2001 -From: Max Reitz -Date: Wed, 15 May 2019 06:15:40 +0200 -Subject: [PATCH] block/file-posix: Unaligned O_DIRECT block-status - -Currently, qemu crashes whenever someone queries the block status of an -unaligned image tail of an O_DIRECT image: -$ echo > foo -$ qemu-img map --image-opts driver=file,filename=foo,cache.direct=on -Offset Length Mapped to File -qemu-img: block/io.c:2093: bdrv_co_block_status: Assertion `*pnum && -QEMU_IS_ALIGNED(*pnum, align) && align > offset - aligned_offset' -failed. - -This is because bdrv_co_block_status() checks that the result returned -by the driver's implementation is aligned to the request_alignment, but -file-posix can fail to do so, which is actually mentioned in a comment -there: "[...] possibly including a partial sector at EOF". - -Fix this by rounding up those partial sectors. - -There are two possible alternative fixes: -(1) We could refuse to open unaligned image files with O_DIRECT - altogether. That sounds reasonable until you realize that qcow2 - does necessarily not fill up its metadata clusters, and that nobody - runs qemu-img create with O_DIRECT. Therefore, unpreallocated qcow2 - files usually have an unaligned image tail. - -(2) bdrv_co_block_status() could ignore unaligned tails. It actually - throws away everything past the EOF already, so that sounds - reasonable. - Unfortunately, the block layer knows file lengths only with a - granularity of BDRV_SECTOR_SIZE, so bdrv_co_block_status() usually - would have to guess whether its file length information is inexact - or whether the driver is broken. - -Fixing what raw_co_block_status() returns is the safest thing to do. - -There seems to be no other block driver that sets request_alignment and -does not make sure that it always returns aligned values. - -Cc: qemu-stable@nongnu.org -Signed-off-by: Max Reitz -Reviewed-by: Eric Blake -Signed-off-by: Kevin Wolf -(cherry-picked from commit 9c3db310ff0b7473272ae8dce5e04e2f8a825390) ---- - block/file-posix.c | 16 ++++++++++++++++ - 1 file changed, 16 insertions(+) - -diff --git a/block/file-posix.c b/block/file-posix.c -index e09e15bbf8..d018429672 100644 ---- a/block/file-posix.c -+++ b/block/file-posix.c -@@ -2488,6 +2488,8 @@ static int coroutine_fn raw_co_block_status(BlockDriverState *bs, - off_t data = 0, hole = 0; - int ret; - -+ assert(QEMU_IS_ALIGNED(offset | bytes, bs->bl.request_alignment)); -+ - ret = fd_open(bs); - if (ret < 0) { - return ret; -@@ -2513,6 +2515,20 @@ static int coroutine_fn raw_co_block_status(BlockDriverState *bs, - /* On a data extent, compute bytes to the end of the extent, - * possibly including a partial sector at EOF. */ - *pnum = MIN(bytes, hole - offset); -+ -+ /* -+ * We are not allowed to return partial sectors, though, so -+ * round up if necessary. -+ */ -+ if (!QEMU_IS_ALIGNED(*pnum, bs->bl.request_alignment)) { -+ int64_t file_length = raw_getlength(bs); -+ if (file_length > 0) { -+ /* Ignore errors, this is just a safeguard */ -+ assert(hole == file_length); -+ } -+ *pnum = ROUND_UP(*pnum, bs->bl.request_alignment); -+ } -+ - ret = BDRV_BLOCK_DATA; - } else { - /* On a hole, compute bytes to the beginning of the next extent. */ --- -2.19.1 - diff --git a/block-fix-memleaks-in-bdrv_refresh_filename.patch b/block-fix-memleaks-in-bdrv_refresh_filename.patch deleted file mode 100644 index 48682054e6d7db02048c7538f8f1963447020c85..0000000000000000000000000000000000000000 --- a/block-fix-memleaks-in-bdrv_refresh_filename.patch +++ /dev/null @@ -1,56 +0,0 @@ -From d09b8364d9f89c9d5f36dc983c4d4a36bb7388b9 Mon Sep 17 00:00:00 2001 -From: Pan Nengyuan -Date: Thu, 16 Jan 2020 17:29:29 +0800 -Subject: [PATCH] block: fix memleaks in bdrv_refresh_filename - -If we call the qmp 'query-block' while qemu is working on 'block-commit', -it will cause memleaks. The memory leak stack is as follow: - -Indirect leak of 12360 byte(s) in 3 object(s) allocated from: - #0 0x7f80f0b6d970 in __interceptor_calloc (/lib64/libasan.so.5+0xef970) - #1 0x7f80ee86049d in g_malloc0 (/lib64/libglib-2.0.so.0+0x5249d) - #2 0x55ea95b5bb67 in qdict_new /mnt/sdb/qemu/qobject/qdict.c - #3 0x55ea956cd043 in bdrv_refresh_filename /mnt/sdb/qemu/block.c - #4 0x55ea956cc950 in bdrv_refresh_filename /mnt/sdb/qemu/block.c - #5 0x55ea956cc950 in bdrv_refresh_filename /mnt/sdb/qemu/block.c - #6 0x55ea956cc950 in bdrv_refresh_filename /mnt/sdb/qemu/block.c - #7 0x55ea958818ea in bdrv_block_device_info /mnt/sdb/qemu/block/qapi.c - #8 0x55ea958879de in bdrv_query_info /mnt/sdb/qemu/block/qapi.c - #9 0x55ea9588b58f in qmp_query_block /mnt/sdb/qemu/block/qapi.c - #10 0x55ea95567392 in qmp_marshal_query_block qapi/qapi-commands-block-core.c - -Indirect leak of 4120 byte(s) in 1 object(s) allocated from: - #0 0x7f80f0b6d970 in __interceptor_calloc (/lib64/libasan.so.5+0xef970) - #1 0x7f80ee86049d in g_malloc0 (/lib64/libglib-2.0.so.0+0x5249d) - #2 0x55ea95b5bb67 in qdict_new /mnt/sdb/qemu/qobject/qdict.c - #3 0x55ea956cd043 in bdrv_refresh_filename /mnt/sdb/qemu/block.c - #4 0x55ea956cc950 in bdrv_refresh_filename /mnt/sdb/qemu/block.c - #5 0x55ea956cc950 in bdrv_refresh_filename /mnt/sdb/qemu/block.c - #6 0x55ea9569f301 in bdrv_backing_attach /mnt/sdb/qemu/block.c - #7 0x55ea956a99dd in bdrv_replace_child_noperm /mnt/sdb/qemu/block.c - #8 0x55ea956b9b53 in bdrv_replace_node /mnt/sdb/qemu/block.c - #9 0x55ea956b9e49 in bdrv_append /mnt/sdb/qemu/block.c - #10 0x55ea958c3472 in commit_start /mnt/sdb/qemu/block/commit.c - #11 0x55ea94b68ab0 in qmp_block_commit /mnt/sdb/qemu/blockdev.c - -Reported-by: Euler Robot -Signed-off-by: Pan Nengyuan ---- - block.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/block.c b/block.c -index 9ae5c0e..52bad05 100644 ---- a/block.c -+++ b/block.c -@@ -6048,6 +6048,7 @@ void bdrv_refresh_filename(BlockDriverState *bs) - child->bs->exact_filename); - pstrcpy(bs->filename, sizeof(bs->filename), child->bs->filename); - -+ qobject_unref(bs->full_open_options); - bs->full_open_options = qobject_ref(child->bs->full_open_options); - - return; --- -1.8.3.1 - diff --git a/block-luks-better-error-message-when-creating-too-la.patch b/block-luks-better-error-message-when-creating-too-la.patch new file mode 100644 index 0000000000000000000000000000000000000000..5a26180989cbfcdadf9decb708bfc43016d61242 --- /dev/null +++ b/block-luks-better-error-message-when-creating-too-la.patch @@ -0,0 +1,86 @@ +From 3d1900a471c89ebdd9ea7f3582fe487e2f494419 Mon Sep 17 00:00:00 2001 +From: Maxim Levitsky +Date: Thu, 26 Sep 2019 00:35:27 +0300 +Subject: [PATCH 314/709] block: luks: better error message when creating too + large files +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Currently if you attampt to create too large file with luks you +get the following error message: + +Formatting 'test.luks', fmt=luks size=17592186044416 key-secret=sec0 +qemu-img: test.luks: Could not resize file: File too large + +While for raw format the error message is +qemu-img: test.img: The image size is too large for file format 'raw' + +The reason for this is that qemu-img checks for errono of the failure, +and presents the later error when it is -EFBIG + +However crypto generic code 'swallows' the errno and replaces it +with -EIO. + +As an attempt to make it better, we can make luks driver, +detect -EFBIG and in this case present a better error message, +which is what this patch does + +The new error message is: + +qemu-img: error creating test.luks: The requested file size is too large + +Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1534898 +Signed-off-by: Maxim Levitsky +Signed-off-by: Daniel P. Berrangé +--- + block/crypto.c | 25 +++++++++++++++++++++---- + 1 file changed, 21 insertions(+), 4 deletions(-) + +diff --git a/block/crypto.c b/block/crypto.c +index ca44dae4f7..6b21d6bf6c 100644 +--- a/block/crypto.c ++++ b/block/crypto.c +@@ -104,18 +104,35 @@ static ssize_t block_crypto_init_func(QCryptoBlock *block, + Error **errp) + { + struct BlockCryptoCreateData *data = opaque; ++ Error *local_error = NULL; ++ int ret; + + if (data->size > INT64_MAX || headerlen > INT64_MAX - data->size) { +- error_setg(errp, "The requested file size is too large"); +- return -EFBIG; ++ ret = -EFBIG; ++ goto error; + } + + /* User provided size should reflect amount of space made + * available to the guest, so we must take account of that + * which will be used by the crypto header + */ +- return blk_truncate(data->blk, data->size + headerlen, false, +- data->prealloc, 0, errp); ++ ret = blk_truncate(data->blk, data->size + headerlen, false, ++ data->prealloc, 0, &local_error); ++ ++ if (ret >= 0) { ++ return ret; ++ } ++ ++error: ++ if (ret == -EFBIG) { ++ /* Replace the error message with a better one */ ++ error_free(local_error); ++ error_setg(errp, "The requested file size is too large"); ++ } else { ++ error_propagate(errp, local_error); ++ } ++ ++ return ret; + } + + +-- +2.23.0 + diff --git a/block-nbd-client-drop-max_block-restriction-from-blo.patch b/block-nbd-client-drop-max_block-restriction-from-blo.patch new file mode 100644 index 0000000000000000000000000000000000000000..51d464cf5eb29dd45a2e1f40ed06c4d13be9129d --- /dev/null +++ b/block-nbd-client-drop-max_block-restriction-from-blo.patch @@ -0,0 +1,37 @@ +From 6bf792b4643bd88153b2d473f735f93638cac521 Mon Sep 17 00:00:00 2001 +From: Vladimir Sementsov-Ogievskiy +Date: Wed, 1 Apr 2020 18:01:07 +0300 +Subject: [PATCH 239/709] block/nbd-client: drop max_block restriction from + block_status + +The NBD spec was updated (see nbd.git commit 9f30fedb) so that +max_block doesn't relate to NBD_CMD_BLOCK_STATUS. So, drop the +restriction. + +Signed-off-by: Vladimir Sementsov-Ogievskiy +Reviewed-by: Eric Blake +Message-Id: <20200401150112.9557-2-vsementsov@virtuozzo.com> +[eblake: tweak commit message to call out NBD commit] +Signed-off-by: Eric Blake +--- + block/nbd.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +diff --git a/block/nbd.c b/block/nbd.c +index 2160859f64..d4d518a780 100644 +--- a/block/nbd.c ++++ b/block/nbd.c +@@ -1320,9 +1320,7 @@ static int coroutine_fn nbd_client_co_block_status( + NBDRequest request = { + .type = NBD_CMD_BLOCK_STATUS, + .from = offset, +- .len = MIN(MIN_NON_ZERO(QEMU_ALIGN_DOWN(INT_MAX, +- bs->bl.request_alignment), +- s->info.max_block), ++ .len = MIN(QEMU_ALIGN_DOWN(INT_MAX, bs->bl.request_alignment), + MIN(bytes, s->info.size - offset)), + .flags = NBD_CMD_FLAG_REQ_ONE, + }; +-- +2.23.0 + diff --git a/block-nbd-client-drop-max_block-restriction-from-dis.patch b/block-nbd-client-drop-max_block-restriction-from-dis.patch new file mode 100644 index 0000000000000000000000000000000000000000..b0953b9cb290cb4a52f8bc6df9c0d7ba70fdcbd0 --- /dev/null +++ b/block-nbd-client-drop-max_block-restriction-from-dis.patch @@ -0,0 +1,34 @@ +From 714eb0dbc5480c8a9d9f39eb931cb5d2acc1b6c6 Mon Sep 17 00:00:00 2001 +From: Vladimir Sementsov-Ogievskiy +Date: Wed, 1 Apr 2020 18:01:08 +0300 +Subject: [PATCH 240/709] block/nbd-client: drop max_block restriction from + discard + +The NBD spec was updated (see nbd.git commit 9f30fedb) so that +max_block doesn't relate to NBD_CMD_TRIM. So, drop the restriction. + +Signed-off-by: Vladimir Sementsov-Ogievskiy +Message-Id: <20200401150112.9557-3-vsementsov@virtuozzo.com> +Reviewed-by: Eric Blake +[eblake: tweak commit message to call out NBD commit] +Signed-off-by: Eric Blake +--- + block/nbd.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/block/nbd.c b/block/nbd.c +index d4d518a780..4ac23c8f62 100644 +--- a/block/nbd.c ++++ b/block/nbd.c +@@ -1955,7 +1955,7 @@ static void nbd_refresh_limits(BlockDriverState *bs, Error **errp) + } + + bs->bl.request_alignment = min; +- bs->bl.max_pdiscard = max; ++ bs->bl.max_pdiscard = QEMU_ALIGN_DOWN(INT_MAX, min); + bs->bl.max_pwrite_zeroes = max; + bs->bl.max_transfer = max; + +-- +2.23.0 + diff --git a/block-nfs-tear-down-aio-before-nfs_close.patch b/block-nfs-tear-down-aio-before-nfs_close.patch deleted file mode 100644 index a22a7ee7380906a189b99ecbe008958072611631..0000000000000000000000000000000000000000 --- a/block-nfs-tear-down-aio-before-nfs_close.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 6cb3e9e4f17c182c43ded773a04b1072c881aa78 Mon Sep 17 00:00:00 2001 -From: Peter Lieven -Date: Tue, 10 Sep 2019 17:41:09 +0200 -Subject: [PATCH] block/nfs: tear down aio before nfs_close - -nfs_close is a sync call from libnfs and has its own event -handler polling on the nfs FD. Avoid that both QEMU and libnfs -are intefering here. - -CC: qemu-stable@nongnu.org -Signed-off-by: Peter Lieven -Signed-off-by: Kevin Wolf -(cherry picked from commit 601dc6559725f7a614b6f893611e17ff0908e914) -Signed-off-by: Michael Roth ---- - block/nfs.c | 6 ++++-- - 1 file changed, 4 insertions(+), 2 deletions(-) - -diff --git a/block/nfs.c b/block/nfs.c -index 531903610b..f04f675c63 100644 ---- a/block/nfs.c -+++ b/block/nfs.c -@@ -389,12 +389,14 @@ static void nfs_attach_aio_context(BlockDriverState *bs, - static void nfs_client_close(NFSClient *client) - { - if (client->context) { -+ qemu_mutex_lock(&client->mutex); -+ aio_set_fd_handler(client->aio_context, nfs_get_fd(client->context), -+ false, NULL, NULL, NULL, NULL); -+ qemu_mutex_unlock(&client->mutex); - if (client->fh) { - nfs_close(client->context, client->fh); - client->fh = NULL; - } -- aio_set_fd_handler(client->aio_context, nfs_get_fd(client->context), -- false, NULL, NULL, NULL, NULL); - nfs_destroy_context(client->context); - client->context = NULL; - } --- -2.19.1 - diff --git a/block-replication.c-Avoid-cancelling-the-job-twice.patch b/block-replication.c-Avoid-cancelling-the-job-twice.patch new file mode 100644 index 0000000000000000000000000000000000000000..3c079fdb7ff82668714e44b600395a53aa70a9a0 --- /dev/null +++ b/block-replication.c-Avoid-cancelling-the-job-twice.patch @@ -0,0 +1,36 @@ +From e140f4b7b8c0fdda866ba3d8b4aa184b6ba6d6b8 Mon Sep 17 00:00:00 2001 +From: Lukas Straub +Date: Mon, 11 May 2020 09:08:01 +0200 +Subject: [PATCH 525/709] block/replication.c: Avoid cancelling the job twice + +If qemu in colo secondary mode is stopped, it crashes because +s->backup_job is canceled twice: First with job_cancel_sync_all() +in qemu_cleanup() and then in replication_stop(). + +Fix this by assigning NULL to s->backup_job when the job completes +so replication_stop() and replication_do_checkpoint() won't touch +the job. + +Signed-off-by: Lukas Straub +Message-Id: <20200511090801.7ed5d8f3@luklap> +Signed-off-by: Kevin Wolf +--- + block/replication.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/block/replication.c b/block/replication.c +index 971f0fe266..c03980a192 100644 +--- a/block/replication.c ++++ b/block/replication.c +@@ -398,6 +398,8 @@ static void backup_job_cleanup(BlockDriverState *bs) + BDRVReplicationState *s = bs->opaque; + BlockDriverState *top_bs; + ++ s->backup_job = NULL; ++ + top_bs = bdrv_lookup_bs(s->top_id, s->top_id, NULL); + if (!top_bs) { + return; +-- +2.23.0 + diff --git a/block-truncate-Don-t-make-backing-file-data-visible.patch b/block-truncate-Don-t-make-backing-file-data-visible.patch new file mode 100644 index 0000000000000000000000000000000000000000..6c486c994f3d87ca29b0bf1d9071c72514fd6282 --- /dev/null +++ b/block-truncate-Don-t-make-backing-file-data-visible.patch @@ -0,0 +1,82 @@ +From 955c7d6687fefcd903900a1e597fcbc896c661cd Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Fri, 24 Apr 2020 14:54:45 +0200 +Subject: [PATCH 132/709] block: truncate: Don't make backing file data visible + +When extending the size of an image that has a backing file larger than +its old size, make sure that the backing file data doesn't become +visible in the guest, but the added area is properly zeroed out. + +Consider the following scenario where the overlay is shorter than its +backing file: + + base.qcow2: AAAAAAAA + overlay.qcow2: BBBB + +When resizing (extending) overlay.qcow2, the new blocks should not stay +unallocated and make the additional As from base.qcow2 visible like +before this patch, but zeros should be read. + +A similar case happens with the various variants of a commit job when an +intermediate file is short (- for unallocated): + + base.qcow2: A-A-AAAA + mid.qcow2: BB-B + top.qcow2: C--C--C- + +After commit top.qcow2 to mid.qcow2, the following happens: + + mid.qcow2: CB-C00C0 (correct result) + mid.qcow2: CB-C--C- (before this fix) + +Without the fix, blocks that previously read as zeros on top.qcow2 +suddenly turn into A. + +Signed-off-by: Kevin Wolf +Reviewed-by: Vladimir Sementsov-Ogievskiy +Message-Id: <20200424125448.63318-8-kwolf@redhat.com> +Reviewed-by: Max Reitz +Signed-off-by: Kevin Wolf +--- + block/io.c | 25 +++++++++++++++++++++++++ + 1 file changed, 25 insertions(+) + +diff --git a/block/io.c b/block/io.c +index 795075954e..a4f9714230 100644 +--- a/block/io.c ++++ b/block/io.c +@@ -3394,6 +3394,31 @@ int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact, + goto out; + } + ++ /* ++ * If the image has a backing file that is large enough that it would ++ * provide data for the new area, we cannot leave it unallocated because ++ * then the backing file content would become visible. Instead, zero-fill ++ * the new area. ++ * ++ * Note that if the image has a backing file, but was opened without the ++ * backing file, taking care of keeping things consistent with that backing ++ * file is the user's responsibility. ++ */ ++ if (new_bytes && bs->backing) { ++ int64_t backing_len; ++ ++ backing_len = bdrv_getlength(backing_bs(bs)); ++ if (backing_len < 0) { ++ ret = backing_len; ++ error_setg_errno(errp, -ret, "Could not get backing file size"); ++ goto out; ++ } ++ ++ if (backing_len > old_size) { ++ flags |= BDRV_REQ_ZERO_WRITE; ++ } ++ } ++ + if (drv->bdrv_co_truncate) { + if (flags & ~bs->supported_truncate_flags) { + error_setg(errp, "Block driver does not support requested flags"); +-- +2.23.0 + diff --git a/blockdev-Promote-several-bitmap-functions-to-non-sta.patch b/blockdev-Promote-several-bitmap-functions-to-non-sta.patch new file mode 100644 index 0000000000000000000000000000000000000000..e16d1d99395b6b93815e3072c305dcd3949478ba --- /dev/null +++ b/blockdev-Promote-several-bitmap-functions-to-non-sta.patch @@ -0,0 +1,163 @@ +From c6996cf9a6c759c29919642be9a73ac64b38301b Mon Sep 17 00:00:00 2001 +From: Eric Blake +Date: Tue, 12 May 2020 20:16:43 -0500 +Subject: [PATCH 590/709] blockdev: Promote several bitmap functions to + non-static + +The next patch will split blockdev.c, which will require accessing +some previously-static functions from more than one .c file. But part +of promoting a function to public is picking a naming scheme that does +not reek of exposing too many internals (two of the three functions +were named starting with 'do_'). To make future code motion easier, +perform the function rename and non-static promotion into its own +patch. + +Signed-off-by: Eric Blake +Reviewed-by: Max Reitz +Message-Id: <20200513011648.166876-5-eblake@redhat.com> +Reviewed-by: Vladimir Sementsov-Ogievskiy +--- + blockdev.c | 47 ++++++++++++++++----------------------- + include/block/block_int.h | 12 ++++++++++ + 2 files changed, 31 insertions(+), 28 deletions(-) + +diff --git a/blockdev.c b/blockdev.c +index b3c840ec03..69a30613a3 100644 +--- a/blockdev.c ++++ b/blockdev.c +@@ -1197,10 +1197,10 @@ out_aio_context: + * + * @return: A bitmap object on success, or NULL on failure. + */ +-static BdrvDirtyBitmap *block_dirty_bitmap_lookup(const char *node, +- const char *name, +- BlockDriverState **pbs, +- Error **errp) ++BdrvDirtyBitmap *block_dirty_bitmap_lookup(const char *node, ++ const char *name, ++ BlockDriverState **pbs, ++ Error **errp) + { + BlockDriverState *bs; + BdrvDirtyBitmap *bitmap; +@@ -2171,11 +2171,6 @@ static void block_dirty_bitmap_disable_abort(BlkActionState *common) + } + } + +-static BdrvDirtyBitmap *do_block_dirty_bitmap_merge( +- const char *node, const char *target, +- BlockDirtyBitmapMergeSourceList *bitmaps, +- HBitmap **backup, Error **errp); +- + static void block_dirty_bitmap_merge_prepare(BlkActionState *common, + Error **errp) + { +@@ -2189,15 +2184,11 @@ static void block_dirty_bitmap_merge_prepare(BlkActionState *common, + + action = common->action->u.block_dirty_bitmap_merge.data; + +- state->bitmap = do_block_dirty_bitmap_merge(action->node, action->target, +- action->bitmaps, &state->backup, +- errp); ++ state->bitmap = block_dirty_bitmap_merge(action->node, action->target, ++ action->bitmaps, &state->backup, ++ errp); + } + +-static BdrvDirtyBitmap *do_block_dirty_bitmap_remove( +- const char *node, const char *name, bool release, +- BlockDriverState **bitmap_bs, Error **errp); +- + static void block_dirty_bitmap_remove_prepare(BlkActionState *common, + Error **errp) + { +@@ -2211,8 +2202,8 @@ static void block_dirty_bitmap_remove_prepare(BlkActionState *common, + + action = common->action->u.block_dirty_bitmap_remove.data; + +- state->bitmap = do_block_dirty_bitmap_remove(action->node, action->name, +- false, &state->bs, errp); ++ state->bitmap = block_dirty_bitmap_remove(action->node, action->name, ++ false, &state->bs, errp); + if (state->bitmap) { + bdrv_dirty_bitmap_skip_store(state->bitmap, true); + bdrv_dirty_bitmap_set_busy(state->bitmap, true); +@@ -2504,9 +2495,10 @@ out: + aio_context_release(aio_context); + } + +-static BdrvDirtyBitmap *do_block_dirty_bitmap_remove( +- const char *node, const char *name, bool release, +- BlockDriverState **bitmap_bs, Error **errp) ++BdrvDirtyBitmap *block_dirty_bitmap_remove(const char *node, const char *name, ++ bool release, ++ BlockDriverState **bitmap_bs, ++ Error **errp) + { + BlockDriverState *bs; + BdrvDirtyBitmap *bitmap; +@@ -2548,7 +2540,7 @@ static BdrvDirtyBitmap *do_block_dirty_bitmap_remove( + void qmp_block_dirty_bitmap_remove(const char *node, const char *name, + Error **errp) + { +- do_block_dirty_bitmap_remove(node, name, true, NULL, errp); ++ block_dirty_bitmap_remove(node, name, true, NULL, errp); + } + + /** +@@ -2609,10 +2601,9 @@ void qmp_block_dirty_bitmap_disable(const char *node, const char *name, + bdrv_disable_dirty_bitmap(bitmap); + } + +-static BdrvDirtyBitmap *do_block_dirty_bitmap_merge( +- const char *node, const char *target, +- BlockDirtyBitmapMergeSourceList *bitmaps, +- HBitmap **backup, Error **errp) ++BdrvDirtyBitmap *block_dirty_bitmap_merge(const char *node, const char *target, ++ BlockDirtyBitmapMergeSourceList *bms, ++ HBitmap **backup, Error **errp) + { + BlockDriverState *bs; + BdrvDirtyBitmap *dst, *src, *anon; +@@ -2630,7 +2621,7 @@ static BdrvDirtyBitmap *do_block_dirty_bitmap_merge( + return NULL; + } + +- for (lst = bitmaps; lst; lst = lst->next) { ++ for (lst = bms; lst; lst = lst->next) { + switch (lst->value->type) { + const char *name, *node; + case QTYPE_QSTRING: +@@ -2675,7 +2666,7 @@ void qmp_block_dirty_bitmap_merge(const char *node, const char *target, + BlockDirtyBitmapMergeSourceList *bitmaps, + Error **errp) + { +- do_block_dirty_bitmap_merge(node, target, bitmaps, NULL, errp); ++ block_dirty_bitmap_merge(node, target, bitmaps, NULL, errp); + } + + BlockDirtyBitmapSha256 *qmp_x_debug_block_dirty_bitmap_sha256(const char *node, +diff --git a/include/block/block_int.h b/include/block/block_int.h +index 33a12916f4..791de6a59c 100644 +--- a/include/block/block_int.h ++++ b/include/block/block_int.h +@@ -1344,4 +1344,16 @@ int coroutine_fn bdrv_co_create_opts_simple(BlockDriver *drv, + Error **errp); + extern QemuOptsList bdrv_create_opts_simple; + ++BdrvDirtyBitmap *block_dirty_bitmap_lookup(const char *node, ++ const char *name, ++ BlockDriverState **pbs, ++ Error **errp); ++BdrvDirtyBitmap *block_dirty_bitmap_merge(const char *node, const char *target, ++ BlockDirtyBitmapMergeSourceList *bms, ++ HBitmap **backup, Error **errp); ++BdrvDirtyBitmap *block_dirty_bitmap_remove(const char *node, const char *name, ++ bool release, ++ BlockDriverState **bitmap_bs, ++ Error **errp); ++ + #endif /* BLOCK_INT_H */ +-- +2.23.0 + diff --git a/blockdev-Remove-dead-assignment.patch b/blockdev-Remove-dead-assignment.patch new file mode 100644 index 0000000000000000000000000000000000000000..1b0f5fc7c41a970def6f576e15f8bbf4ce60ef16 --- /dev/null +++ b/blockdev-Remove-dead-assignment.patch @@ -0,0 +1,41 @@ +From 1fe5a8c2cd5dc0da03a4246474abf37f0e8cc8c0 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Wed, 22 Apr 2020 15:31:45 +0200 +Subject: [PATCH 196/709] blockdev: Remove dead assignment +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Fix warning reported by Clang static code analyzer: + + CC blockdev.o + blockdev.c:2744:5: warning: Value stored to 'ret' is never read + ret = blk_truncate(blk, size, false, PREALLOC_MODE_OFF, errp); + ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Reported-by: Clang Static Analyzer +Signed-off-by: Philippe Mathieu-Daudé +Reviewed-by: Max Reitz +Message-Id: <20200422133152.16770-3-philmd@redhat.com> +[lv: fix conflict because of "Add flags to blk_truncate()"] +Signed-off-by: Laurent Vivier +--- + blockdev.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/blockdev.c b/blockdev.c +index dc1a0c7c2f..708d0c323f 100644 +--- a/blockdev.c ++++ b/blockdev.c +@@ -2741,7 +2741,7 @@ void qmp_block_resize(bool has_device, const char *device, + } + + bdrv_drained_begin(bs); +- ret = blk_truncate(blk, size, false, PREALLOC_MODE_OFF, 0, errp); ++ blk_truncate(blk, size, false, PREALLOC_MODE_OFF, 0, errp); + bdrv_drained_end(bs); + + out: +-- +2.23.0 + diff --git a/blockdev-Split-off-basic-bitmap-operations-for-qemu-.patch b/blockdev-Split-off-basic-bitmap-operations-for-qemu-.patch new file mode 100644 index 0000000000000000000000000000000000000000..a04c6c7b9ece8d79d22ce9f4afa9ecf10e15b523 --- /dev/null +++ b/blockdev-Split-off-basic-bitmap-operations-for-qemu-.patch @@ -0,0 +1,699 @@ +From bb4e58c6137e80129b955789dd4b66c1504f20dc Mon Sep 17 00:00:00 2001 +From: Eric Blake +Date: Mon, 18 May 2020 13:53:07 -0500 +Subject: [PATCH 591/709] blockdev: Split off basic bitmap operations for + qemu-img + +Upcoming patches want to add some basic bitmap manipulation abilities +to qemu-img. But blockdev.o is too heavyweight to link into qemu-img +(among other things, it would drag in block jobs and transaction +support - qemu-img does offline manipulation, where atomicity is less +important because there are no concurrent modifications to compete +with), so it's time to split off the bare bones of what we will need +into a new file block/monitor/bitmap-qmp-cmds.o. + +This is sufficient to expose 6 QMP commands for use by qemu-img (add, +remove, clear, enable, disable, merge), as well as move the three +helper functions touched in the previous patch. Regarding +MAINTAINERS, the new file is automatically part of block core, but +also makes sense as related to other dirty bitmap files. + +Signed-off-by: Eric Blake +Reviewed-by: Max Reitz +Message-Id: <20200513011648.166876-6-eblake@redhat.com> +Reviewed-by: Vladimir Sementsov-Ogievskiy +--- + MAINTAINERS | 1 + + Makefile.objs | 3 +- + block/monitor/Makefile.objs | 1 + + block/monitor/bitmap-qmp-cmds.c | 321 ++++++++++++++++++++++++++++++++ + blockdev.c | 284 ---------------------------- + 5 files changed, 324 insertions(+), 286 deletions(-) + create mode 100644 block/monitor/bitmap-qmp-cmds.c + +diff --git a/MAINTAINERS b/MAINTAINERS +index 4e99bb05da..87a412c229 100644 +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -2018,6 +2018,7 @@ L: qemu-block@nongnu.org + S: Supported + F: include/qemu/hbitmap.h + F: include/block/dirty-bitmap.h ++F: block/monitor/bitmap-qmp-cmds.c + F: block/dirty-bitmap.c + F: block/qcow2-bitmap.c + F: migration/block-dirty-bitmap.c +diff --git a/Makefile.objs b/Makefile.objs +index a7c967633a..99774cfd25 100644 +--- a/Makefile.objs ++++ b/Makefile.objs +@@ -13,9 +13,8 @@ chardev-obj-y = chardev/ + + authz-obj-y = authz/ + +-block-obj-y = nbd/ ++block-obj-y = block/ block/monitor/ nbd/ scsi/ + block-obj-y += block.o blockjob.o job.o +-block-obj-y += block/ scsi/ + block-obj-y += qemu-io-cmds.o + block-obj-$(CONFIG_REPLICATION) += replication.o + +diff --git a/block/monitor/Makefile.objs b/block/monitor/Makefile.objs +index 0a74f9a8b5..39acf85022 100644 +--- a/block/monitor/Makefile.objs ++++ b/block/monitor/Makefile.objs +@@ -1 +1,2 @@ + common-obj-y += block-hmp-cmds.o ++block-obj-y += bitmap-qmp-cmds.o +diff --git a/block/monitor/bitmap-qmp-cmds.c b/block/monitor/bitmap-qmp-cmds.c +new file mode 100644 +index 0000000000..9f11deec64 +--- /dev/null ++++ b/block/monitor/bitmap-qmp-cmds.c +@@ -0,0 +1,321 @@ ++/* ++ * QEMU block dirty bitmap QMP commands ++ * ++ * Copyright (c) 2003-2008 Fabrice Bellard ++ * ++ * This work is licensed under the terms of the GNU GPL, version 2 or ++ * later. See the COPYING file in the top-level directory. ++ * ++ * This file incorporates work covered by the following copyright and ++ * permission notice: ++ * ++ * Copyright (c) 2003-2008 Fabrice Bellard ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a copy ++ * of this software and associated documentation files (the "Software"), to deal ++ * in the Software without restriction, including without limitation the rights ++ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ++ * copies of the Software, and to permit persons to whom the Software is ++ * furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ++ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ * 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. ++ */ ++ ++#include "qemu/osdep.h" ++ ++#include "block/block_int.h" ++#include "qapi/qapi-commands-block.h" ++#include "qapi/error.h" ++ ++/** ++ * block_dirty_bitmap_lookup: ++ * Return a dirty bitmap (if present), after validating ++ * the node reference and bitmap names. ++ * ++ * @node: The name of the BDS node to search for bitmaps ++ * @name: The name of the bitmap to search for ++ * @pbs: Output pointer for BDS lookup, if desired. Can be NULL. ++ * @errp: Output pointer for error information. Can be NULL. ++ * ++ * @return: A bitmap object on success, or NULL on failure. ++ */ ++BdrvDirtyBitmap *block_dirty_bitmap_lookup(const char *node, ++ const char *name, ++ BlockDriverState **pbs, ++ Error **errp) ++{ ++ BlockDriverState *bs; ++ BdrvDirtyBitmap *bitmap; ++ ++ if (!node) { ++ error_setg(errp, "Node cannot be NULL"); ++ return NULL; ++ } ++ if (!name) { ++ error_setg(errp, "Bitmap name cannot be NULL"); ++ return NULL; ++ } ++ bs = bdrv_lookup_bs(node, node, NULL); ++ if (!bs) { ++ error_setg(errp, "Node '%s' not found", node); ++ return NULL; ++ } ++ ++ bitmap = bdrv_find_dirty_bitmap(bs, name); ++ if (!bitmap) { ++ error_setg(errp, "Dirty bitmap '%s' not found", name); ++ return NULL; ++ } ++ ++ if (pbs) { ++ *pbs = bs; ++ } ++ ++ return bitmap; ++} ++ ++void qmp_block_dirty_bitmap_add(const char *node, const char *name, ++ bool has_granularity, uint32_t granularity, ++ bool has_persistent, bool persistent, ++ bool has_disabled, bool disabled, ++ Error **errp) ++{ ++ BlockDriverState *bs; ++ BdrvDirtyBitmap *bitmap; ++ AioContext *aio_context; ++ ++ if (!name || name[0] == '\0') { ++ error_setg(errp, "Bitmap name cannot be empty"); ++ return; ++ } ++ ++ bs = bdrv_lookup_bs(node, node, errp); ++ if (!bs) { ++ return; ++ } ++ ++ aio_context = bdrv_get_aio_context(bs); ++ aio_context_acquire(aio_context); ++ ++ if (has_granularity) { ++ if (granularity < 512 || !is_power_of_2(granularity)) { ++ error_setg(errp, "Granularity must be power of 2 " ++ "and at least 512"); ++ goto out; ++ } ++ } else { ++ /* Default to cluster size, if available: */ ++ granularity = bdrv_get_default_bitmap_granularity(bs); ++ } ++ ++ if (!has_persistent) { ++ persistent = false; ++ } ++ ++ if (!has_disabled) { ++ disabled = false; ++ } ++ ++ if (persistent && ++ !bdrv_can_store_new_dirty_bitmap(bs, name, granularity, errp)) ++ { ++ goto out; ++ } ++ ++ bitmap = bdrv_create_dirty_bitmap(bs, granularity, name, errp); ++ if (bitmap == NULL) { ++ goto out; ++ } ++ ++ if (disabled) { ++ bdrv_disable_dirty_bitmap(bitmap); ++ } ++ ++ bdrv_dirty_bitmap_set_persistence(bitmap, persistent); ++ ++out: ++ aio_context_release(aio_context); ++} ++ ++BdrvDirtyBitmap *block_dirty_bitmap_remove(const char *node, const char *name, ++ bool release, ++ BlockDriverState **bitmap_bs, ++ Error **errp) ++{ ++ BlockDriverState *bs; ++ BdrvDirtyBitmap *bitmap; ++ AioContext *aio_context; ++ ++ bitmap = block_dirty_bitmap_lookup(node, name, &bs, errp); ++ if (!bitmap || !bs) { ++ return NULL; ++ } ++ ++ aio_context = bdrv_get_aio_context(bs); ++ aio_context_acquire(aio_context); ++ ++ if (bdrv_dirty_bitmap_check(bitmap, BDRV_BITMAP_BUSY | BDRV_BITMAP_RO, ++ errp)) { ++ aio_context_release(aio_context); ++ return NULL; ++ } ++ ++ if (bdrv_dirty_bitmap_get_persistence(bitmap) && ++ bdrv_remove_persistent_dirty_bitmap(bs, name, errp) < 0) ++ { ++ aio_context_release(aio_context); ++ return NULL; ++ } ++ ++ if (release) { ++ bdrv_release_dirty_bitmap(bitmap); ++ } ++ ++ if (bitmap_bs) { ++ *bitmap_bs = bs; ++ } ++ ++ aio_context_release(aio_context); ++ return release ? NULL : bitmap; ++} ++ ++void qmp_block_dirty_bitmap_remove(const char *node, const char *name, ++ Error **errp) ++{ ++ block_dirty_bitmap_remove(node, name, true, NULL, errp); ++} ++ ++/** ++ * Completely clear a bitmap, for the purposes of synchronizing a bitmap ++ * immediately after a full backup operation. ++ */ ++void qmp_block_dirty_bitmap_clear(const char *node, const char *name, ++ Error **errp) ++{ ++ BdrvDirtyBitmap *bitmap; ++ BlockDriverState *bs; ++ ++ bitmap = block_dirty_bitmap_lookup(node, name, &bs, errp); ++ if (!bitmap || !bs) { ++ return; ++ } ++ ++ if (bdrv_dirty_bitmap_check(bitmap, BDRV_BITMAP_DEFAULT, errp)) { ++ return; ++ } ++ ++ bdrv_clear_dirty_bitmap(bitmap, NULL); ++} ++ ++void qmp_block_dirty_bitmap_enable(const char *node, const char *name, ++ Error **errp) ++{ ++ BlockDriverState *bs; ++ BdrvDirtyBitmap *bitmap; ++ ++ bitmap = block_dirty_bitmap_lookup(node, name, &bs, errp); ++ if (!bitmap) { ++ return; ++ } ++ ++ if (bdrv_dirty_bitmap_check(bitmap, BDRV_BITMAP_ALLOW_RO, errp)) { ++ return; ++ } ++ ++ bdrv_enable_dirty_bitmap(bitmap); ++} ++ ++void qmp_block_dirty_bitmap_disable(const char *node, const char *name, ++ Error **errp) ++{ ++ BlockDriverState *bs; ++ BdrvDirtyBitmap *bitmap; ++ ++ bitmap = block_dirty_bitmap_lookup(node, name, &bs, errp); ++ if (!bitmap) { ++ return; ++ } ++ ++ if (bdrv_dirty_bitmap_check(bitmap, BDRV_BITMAP_ALLOW_RO, errp)) { ++ return; ++ } ++ ++ bdrv_disable_dirty_bitmap(bitmap); ++} ++ ++BdrvDirtyBitmap *block_dirty_bitmap_merge(const char *node, const char *target, ++ BlockDirtyBitmapMergeSourceList *bms, ++ HBitmap **backup, Error **errp) ++{ ++ BlockDriverState *bs; ++ BdrvDirtyBitmap *dst, *src, *anon; ++ BlockDirtyBitmapMergeSourceList *lst; ++ Error *local_err = NULL; ++ ++ dst = block_dirty_bitmap_lookup(node, target, &bs, errp); ++ if (!dst) { ++ return NULL; ++ } ++ ++ anon = bdrv_create_dirty_bitmap(bs, bdrv_dirty_bitmap_granularity(dst), ++ NULL, errp); ++ if (!anon) { ++ return NULL; ++ } ++ ++ for (lst = bms; lst; lst = lst->next) { ++ switch (lst->value->type) { ++ const char *name, *node; ++ case QTYPE_QSTRING: ++ name = lst->value->u.local; ++ src = bdrv_find_dirty_bitmap(bs, name); ++ if (!src) { ++ error_setg(errp, "Dirty bitmap '%s' not found", name); ++ dst = NULL; ++ goto out; ++ } ++ break; ++ case QTYPE_QDICT: ++ node = lst->value->u.external.node; ++ name = lst->value->u.external.name; ++ src = block_dirty_bitmap_lookup(node, name, NULL, errp); ++ if (!src) { ++ dst = NULL; ++ goto out; ++ } ++ break; ++ default: ++ abort(); ++ } ++ ++ bdrv_merge_dirty_bitmap(anon, src, NULL, &local_err); ++ if (local_err) { ++ error_propagate(errp, local_err); ++ dst = NULL; ++ goto out; ++ } ++ } ++ ++ /* Merge into dst; dst is unchanged on failure. */ ++ bdrv_merge_dirty_bitmap(dst, anon, backup, errp); ++ ++ out: ++ bdrv_release_dirty_bitmap(anon); ++ return dst; ++} ++ ++void qmp_block_dirty_bitmap_merge(const char *node, const char *target, ++ BlockDirtyBitmapMergeSourceList *bitmaps, ++ Error **errp) ++{ ++ block_dirty_bitmap_merge(node, target, bitmaps, NULL, errp); ++} +diff --git a/blockdev.c b/blockdev.c +index 69a30613a3..72df193ca7 100644 +--- a/blockdev.c ++++ b/blockdev.c +@@ -1185,53 +1185,6 @@ out_aio_context: + return NULL; + } + +-/** +- * block_dirty_bitmap_lookup: +- * Return a dirty bitmap (if present), after validating +- * the node reference and bitmap names. +- * +- * @node: The name of the BDS node to search for bitmaps +- * @name: The name of the bitmap to search for +- * @pbs: Output pointer for BDS lookup, if desired. Can be NULL. +- * @errp: Output pointer for error information. Can be NULL. +- * +- * @return: A bitmap object on success, or NULL on failure. +- */ +-BdrvDirtyBitmap *block_dirty_bitmap_lookup(const char *node, +- const char *name, +- BlockDriverState **pbs, +- Error **errp) +-{ +- BlockDriverState *bs; +- BdrvDirtyBitmap *bitmap; +- +- if (!node) { +- error_setg(errp, "Node cannot be NULL"); +- return NULL; +- } +- if (!name) { +- error_setg(errp, "Bitmap name cannot be NULL"); +- return NULL; +- } +- bs = bdrv_lookup_bs(node, node, NULL); +- if (!bs) { +- error_setg(errp, "Node '%s' not found", node); +- return NULL; +- } +- +- bitmap = bdrv_find_dirty_bitmap(bs, name); +- if (!bitmap) { +- error_setg(errp, "Dirty bitmap '%s' not found", name); +- return NULL; +- } +- +- if (pbs) { +- *pbs = bs; +- } +- +- return bitmap; +-} +- + /* New and old BlockDriverState structs for atomic group operations */ + + typedef struct BlkActionState BlkActionState; +@@ -2432,243 +2385,6 @@ void qmp_block_passwd(bool has_device, const char *device, + "Setting block passwords directly is no longer supported"); + } + +-void qmp_block_dirty_bitmap_add(const char *node, const char *name, +- bool has_granularity, uint32_t granularity, +- bool has_persistent, bool persistent, +- bool has_disabled, bool disabled, +- Error **errp) +-{ +- BlockDriverState *bs; +- BdrvDirtyBitmap *bitmap; +- AioContext *aio_context; +- +- if (!name || name[0] == '\0') { +- error_setg(errp, "Bitmap name cannot be empty"); +- return; +- } +- +- bs = bdrv_lookup_bs(node, node, errp); +- if (!bs) { +- return; +- } +- +- aio_context = bdrv_get_aio_context(bs); +- aio_context_acquire(aio_context); +- +- if (has_granularity) { +- if (granularity < 512 || !is_power_of_2(granularity)) { +- error_setg(errp, "Granularity must be power of 2 " +- "and at least 512"); +- goto out; +- } +- } else { +- /* Default to cluster size, if available: */ +- granularity = bdrv_get_default_bitmap_granularity(bs); +- } +- +- if (!has_persistent) { +- persistent = false; +- } +- +- if (!has_disabled) { +- disabled = false; +- } +- +- if (persistent && +- !bdrv_can_store_new_dirty_bitmap(bs, name, granularity, errp)) +- { +- goto out; +- } +- +- bitmap = bdrv_create_dirty_bitmap(bs, granularity, name, errp); +- if (bitmap == NULL) { +- goto out; +- } +- +- if (disabled) { +- bdrv_disable_dirty_bitmap(bitmap); +- } +- +- bdrv_dirty_bitmap_set_persistence(bitmap, persistent); +- +-out: +- aio_context_release(aio_context); +-} +- +-BdrvDirtyBitmap *block_dirty_bitmap_remove(const char *node, const char *name, +- bool release, +- BlockDriverState **bitmap_bs, +- Error **errp) +-{ +- BlockDriverState *bs; +- BdrvDirtyBitmap *bitmap; +- AioContext *aio_context; +- +- bitmap = block_dirty_bitmap_lookup(node, name, &bs, errp); +- if (!bitmap || !bs) { +- return NULL; +- } +- +- aio_context = bdrv_get_aio_context(bs); +- aio_context_acquire(aio_context); +- +- if (bdrv_dirty_bitmap_check(bitmap, BDRV_BITMAP_BUSY | BDRV_BITMAP_RO, +- errp)) { +- aio_context_release(aio_context); +- return NULL; +- } +- +- if (bdrv_dirty_bitmap_get_persistence(bitmap) && +- bdrv_remove_persistent_dirty_bitmap(bs, name, errp) < 0) +- { +- aio_context_release(aio_context); +- return NULL; +- } +- +- if (release) { +- bdrv_release_dirty_bitmap(bitmap); +- } +- +- if (bitmap_bs) { +- *bitmap_bs = bs; +- } +- +- aio_context_release(aio_context); +- return release ? NULL : bitmap; +-} +- +-void qmp_block_dirty_bitmap_remove(const char *node, const char *name, +- Error **errp) +-{ +- block_dirty_bitmap_remove(node, name, true, NULL, errp); +-} +- +-/** +- * Completely clear a bitmap, for the purposes of synchronizing a bitmap +- * immediately after a full backup operation. +- */ +-void qmp_block_dirty_bitmap_clear(const char *node, const char *name, +- Error **errp) +-{ +- BdrvDirtyBitmap *bitmap; +- BlockDriverState *bs; +- +- bitmap = block_dirty_bitmap_lookup(node, name, &bs, errp); +- if (!bitmap || !bs) { +- return; +- } +- +- if (bdrv_dirty_bitmap_check(bitmap, BDRV_BITMAP_DEFAULT, errp)) { +- return; +- } +- +- bdrv_clear_dirty_bitmap(bitmap, NULL); +-} +- +-void qmp_block_dirty_bitmap_enable(const char *node, const char *name, +- Error **errp) +-{ +- BlockDriverState *bs; +- BdrvDirtyBitmap *bitmap; +- +- bitmap = block_dirty_bitmap_lookup(node, name, &bs, errp); +- if (!bitmap) { +- return; +- } +- +- if (bdrv_dirty_bitmap_check(bitmap, BDRV_BITMAP_ALLOW_RO, errp)) { +- return; +- } +- +- bdrv_enable_dirty_bitmap(bitmap); +-} +- +-void qmp_block_dirty_bitmap_disable(const char *node, const char *name, +- Error **errp) +-{ +- BlockDriverState *bs; +- BdrvDirtyBitmap *bitmap; +- +- bitmap = block_dirty_bitmap_lookup(node, name, &bs, errp); +- if (!bitmap) { +- return; +- } +- +- if (bdrv_dirty_bitmap_check(bitmap, BDRV_BITMAP_ALLOW_RO, errp)) { +- return; +- } +- +- bdrv_disable_dirty_bitmap(bitmap); +-} +- +-BdrvDirtyBitmap *block_dirty_bitmap_merge(const char *node, const char *target, +- BlockDirtyBitmapMergeSourceList *bms, +- HBitmap **backup, Error **errp) +-{ +- BlockDriverState *bs; +- BdrvDirtyBitmap *dst, *src, *anon; +- BlockDirtyBitmapMergeSourceList *lst; +- Error *local_err = NULL; +- +- dst = block_dirty_bitmap_lookup(node, target, &bs, errp); +- if (!dst) { +- return NULL; +- } +- +- anon = bdrv_create_dirty_bitmap(bs, bdrv_dirty_bitmap_granularity(dst), +- NULL, errp); +- if (!anon) { +- return NULL; +- } +- +- for (lst = bms; lst; lst = lst->next) { +- switch (lst->value->type) { +- const char *name, *node; +- case QTYPE_QSTRING: +- name = lst->value->u.local; +- src = bdrv_find_dirty_bitmap(bs, name); +- if (!src) { +- error_setg(errp, "Dirty bitmap '%s' not found", name); +- dst = NULL; +- goto out; +- } +- break; +- case QTYPE_QDICT: +- node = lst->value->u.external.node; +- name = lst->value->u.external.name; +- src = block_dirty_bitmap_lookup(node, name, NULL, errp); +- if (!src) { +- dst = NULL; +- goto out; +- } +- break; +- default: +- abort(); +- } +- +- bdrv_merge_dirty_bitmap(anon, src, NULL, &local_err); +- if (local_err) { +- error_propagate(errp, local_err); +- dst = NULL; +- goto out; +- } +- } +- +- /* Merge into dst; dst is unchanged on failure. */ +- bdrv_merge_dirty_bitmap(dst, anon, backup, errp); +- +- out: +- bdrv_release_dirty_bitmap(anon); +- return dst; +-} +- +-void qmp_block_dirty_bitmap_merge(const char *node, const char *target, +- BlockDirtyBitmapMergeSourceList *bitmaps, +- Error **errp) +-{ +- block_dirty_bitmap_merge(node, target, bitmaps, NULL, errp); +-} +- + BlockDirtyBitmapSha256 *qmp_x_debug_block_dirty_bitmap_sha256(const char *node, + const char *name, + Error **errp) +-- +2.23.0 + diff --git a/blockdev-backup-don-t-check-aio_context-too-early.patch b/blockdev-backup-don-t-check-aio_context-too-early.patch deleted file mode 100644 index aa793d59a2dbf74c9c1aa03cbd076217cd8ca63f..0000000000000000000000000000000000000000 --- a/blockdev-backup-don-t-check-aio_context-too-early.patch +++ /dev/null @@ -1,53 +0,0 @@ -From 2429dc4eea91b381ff67a4d25ea9f6bbfe87c784 Mon Sep 17 00:00:00 2001 -From: John Snow -Date: Thu, 23 May 2019 13:06:39 -0400 -Subject: [PATCH] blockdev-backup: don't check aio_context too early - -in blockdev_backup_prepare, we check to make sure that the target is -associated with a compatible aio context. However, do_blockdev_backup is -called later and has some logic to move the target to a compatible -aio_context. The transaction version will fail certain commands -needlessly early as a result. - -Allow blockdev_backup_prepare to simply call do_blockdev_backup, which -will ultimately decide if the contexts are compatible or not. - -Note: the transaction version has always disallowed this operation since -its initial commit bd8baecd (2014), whereas the version of -qmp_blockdev_backup at the time, from commit c29c1dd312f, tried to -enforce the aio_context switch instead. It's not clear, and I can't see -from the mailing list archives at the time, why the two functions take a -different approach. It wasn't until later in efd7556708b (2016) that the -standalone version tried to determine if it could set the context or -not. - -Reported-by: aihua liang -Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1683498 -Signed-off-by: John Snow -Message-id: 20190523170643.20794-2-jsnow@redhat.com -Reviewed-by: Max Reitz -Signed-off-by: Max Reitz -(cherry picked from commit d81e1efbea7d19c2f142d300df56538c73800590) -Signed-off-by: Michael Roth ---- - blockdev.c | 4 ---- - 1 file changed, 4 deletions(-) - -diff --git a/blockdev.c b/blockdev.c -index 4775a07d93..d358169995 100644 ---- a/blockdev.c -+++ b/blockdev.c -@@ -1871,10 +1871,6 @@ static void blockdev_backup_prepare(BlkActionState *common, Error **errp) - } - - aio_context = bdrv_get_aio_context(bs); -- if (aio_context != bdrv_get_aio_context(target)) { -- error_setg(errp, "Backup between two IO threads is not implemented"); -- return; -- } - aio_context_acquire(aio_context); - state->bs = bs; - --- -2.19.1 - diff --git a/blockjob-update-nodes-head-while-removing-all-bdrv.patch b/blockjob-update-nodes-head-while-removing-all-bdrv.patch deleted file mode 100644 index 4ad76d41e0d18d249c88dff2b28d237243828df9..0000000000000000000000000000000000000000 --- a/blockjob-update-nodes-head-while-removing-all-bdrv.patch +++ /dev/null @@ -1,62 +0,0 @@ -From b9405afb0956fe2c293a94bdc4440579e5c0efee Mon Sep 17 00:00:00 2001 -From: Sergio Lopez -Date: Wed, 11 Sep 2019 12:03:16 +0200 -Subject: [PATCH] blockjob: update nodes head while removing all bdrv - -block_job_remove_all_bdrv() iterates through job->nodes, calling -bdrv_root_unref_child() for each entry. The call to the latter may -reach child_job_[can_]set_aio_ctx(), which will also attempt to -traverse job->nodes, potentially finding entries that where freed -on previous iterations. - -To avoid this situation, update job->nodes head on each iteration to -ensure that already freed entries are no longer linked to the list. - -RHBZ: https://bugzilla.redhat.com/show_bug.cgi?id=1746631 -Signed-off-by: Sergio Lopez -Cc: qemu-stable@nongnu.org -Signed-off-by: Max Reitz -Message-id: 20190911100316.32282-1-mreitz@redhat.com -Reviewed-by: Sergio Lopez -Signed-off-by: Max Reitz -(cherry picked from commit d876bf676f5e7c6aa9ac64555e48cba8734ecb2f) -Signed-off-by: Michael Roth ---- - blockjob.c | 17 +++++++++++++---- - 1 file changed, 13 insertions(+), 4 deletions(-) - -diff --git a/blockjob.c b/blockjob.c -index 730101d282..d770144fd6 100644 ---- a/blockjob.c -+++ b/blockjob.c -@@ -193,14 +193,23 @@ static const BdrvChildRole child_job = { - - void block_job_remove_all_bdrv(BlockJob *job) - { -- GSList *l; -- for (l = job->nodes; l; l = l->next) { -+ /* -+ * bdrv_root_unref_child() may reach child_job_[can_]set_aio_ctx(), -+ * which will also traverse job->nodes, so consume the list one by -+ * one to make sure that such a concurrent access does not attempt -+ * to process an already freed BdrvChild. -+ */ -+ while (job->nodes) { -+ GSList *l = job->nodes; - BdrvChild *c = l->data; -+ -+ job->nodes = l->next; -+ - bdrv_op_unblock_all(c->bs, job->blocker); - bdrv_root_unref_child(c); -+ -+ g_slist_free_1(l); - } -- g_slist_free(job->nodes); -- job->nodes = NULL; - } - - int block_job_add_bdrv(BlockJob *job, const char *name, BlockDriverState *bs, --- -2.19.1 - diff --git a/bochs-display-Fix-vgamem-SIZE-error-handling.patch b/bochs-display-Fix-vgamem-SIZE-error-handling.patch new file mode 100644 index 0000000000000000000000000000000000000000..202c5ed8ad07119005a1d208ef8a489a7f700e2b --- /dev/null +++ b/bochs-display-Fix-vgamem-SIZE-error-handling.patch @@ -0,0 +1,60 @@ +From ee29f6e92d987bd7f37e3a0002dd839f8431adb1 Mon Sep 17 00:00:00 2001 +From: Markus Armbruster +Date: Wed, 22 Apr 2020 15:07:12 +0200 +Subject: [PATCH 020/709] bochs-display: Fix vgamem=SIZE error handling +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +bochs_display_realize() rejects out-of-range vgamem. The error +handling is broken: + + $ qemu-system-x86_64 -S -display none -monitor stdio + QEMU 4.2.93 monitor - type 'help' for more information + (qemu) device_add bochs-display,vgamem=1 + Error: bochs-display: video memory too small + (qemu) device_add bochs-display,vgamem=1 + RAMBlock "0000:00:04.0/bochs-display-vram" already registered, abort! + Aborted (core dumped) + +Cause: bochs_display_realize() neglects to bail out after setting the +error. Fix that. + +Fixes: 765c94290863eef1fc4a67819d452cc13b7854a1 +Cc: Gerd Hoffmann +Signed-off-by: Markus Armbruster +Reviewed-by: Philippe Mathieu-Daudé +Message-Id: <20200422130719.28225-8-armbru@redhat.com> +Reviewed-by: Gerd Hoffmann +--- + hw/display/bochs-display.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/hw/display/bochs-display.c b/hw/display/bochs-display.c +index 70eb619ef4..e763a0a72d 100644 +--- a/hw/display/bochs-display.c ++++ b/hw/display/bochs-display.c +@@ -267,16 +267,18 @@ static void bochs_display_realize(PCIDevice *dev, Error **errp) + Object *obj = OBJECT(dev); + int ret; + +- s->con = graphic_console_init(DEVICE(dev), 0, &bochs_display_gfx_ops, s); +- + if (s->vgamem < 4 * MiB) { + error_setg(errp, "bochs-display: video memory too small"); ++ return; + } + if (s->vgamem > 256 * MiB) { + error_setg(errp, "bochs-display: video memory too big"); ++ return; + } + s->vgamem = pow2ceil(s->vgamem); + ++ s->con = graphic_console_init(DEVICE(dev), 0, &bochs_display_gfx_ops, s); ++ + memory_region_init_ram(&s->vram, obj, "bochs-display-vram", s->vgamem, + &error_fatal); + memory_region_init_io(&s->vbe, obj, &bochs_display_vbe_ops, s, +-- +2.23.0 + diff --git a/bridge.conf b/bridge.conf deleted file mode 100644 index a573665d37fbc5246f9200e3a2de8be729d3e177..0000000000000000000000000000000000000000 --- a/bridge.conf +++ /dev/null @@ -1 +0,0 @@ -allow virbr0 diff --git a/bugfix-Use-gicr_typer-in-arm_gicv3_icc_reset.patch b/bugfix-Use-gicr_typer-in-arm_gicv3_icc_reset.patch new file mode 100644 index 0000000000000000000000000000000000000000..afca76f10f447a5cd19edf84d6dc9e0e2960e685 --- /dev/null +++ b/bugfix-Use-gicr_typer-in-arm_gicv3_icc_reset.patch @@ -0,0 +1,48 @@ +From 1e11a139bfed55cb2de7b2eaa1e53f3cf6180d13 Mon Sep 17 00:00:00 2001 +From: Keqian Zhu +Date: Mon, 13 Apr 2020 17:15:50 +0800 +Subject: [PATCH 097/709] bugfix: Use gicr_typer in arm_gicv3_icc_reset + +The KVM_VGIC_ATTR macro expect the second parameter as gicr_typer, +of which high 32bit is constructed by mp_affinity. For most case, +the high 32bit of mp_affinity is zero, so it will always access the +ICC_CTLR_EL1 of CPU0. + +Signed-off-by: Keqian Zhu +Message-id: 20200413091552.62748-2-zhukeqian1@huawei.com +Reviewed-by: Peter Maydell +Signed-off-by: Peter Maydell +--- + hw/intc/arm_gicv3_kvm.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +diff --git a/hw/intc/arm_gicv3_kvm.c b/hw/intc/arm_gicv3_kvm.c +index 49304ca589..ca43bf87ca 100644 +--- a/hw/intc/arm_gicv3_kvm.c ++++ b/hw/intc/arm_gicv3_kvm.c +@@ -658,13 +658,11 @@ static void kvm_arm_gicv3_get(GICv3State *s) + + static void arm_gicv3_icc_reset(CPUARMState *env, const ARMCPRegInfo *ri) + { +- ARMCPU *cpu; + GICv3State *s; + GICv3CPUState *c; + + c = (GICv3CPUState *)env->gicv3state; + s = c->gic; +- cpu = ARM_CPU(c->cpu); + + c->icc_pmr_el1 = 0; + c->icc_bpr[GICV3_G0] = GIC_MIN_BPR; +@@ -681,7 +679,7 @@ static void arm_gicv3_icc_reset(CPUARMState *env, const ARMCPRegInfo *ri) + + /* Initialize to actual HW supported configuration */ + kvm_device_access(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS, +- KVM_VGIC_ATTR(ICC_CTLR_EL1, cpu->mp_affinity), ++ KVM_VGIC_ATTR(ICC_CTLR_EL1, c->gicr_typer), + &c->icc_ctlr_el1[GICV3_NS], false, &error_abort); + + c->icc_ctlr_el1[GICV3_S] = c->icc_ctlr_el1[GICV3_NS]; +-- +2.23.0 + diff --git a/chardev-Add-macOS-to-list-of-OSes-that-support-chard.patch b/chardev-Add-macOS-to-list-of-OSes-that-support-chard.patch new file mode 100644 index 0000000000000000000000000000000000000000..e860d2886dcdde23376b4dcd31241e24248f5856 --- /dev/null +++ b/chardev-Add-macOS-to-list-of-OSes-that-support-chard.patch @@ -0,0 +1,50 @@ +From 949da1eb9db9df0d998ad2f3086979e4e23a44a1 Mon Sep 17 00:00:00 2001 +From: Mikhail Gusarov +Date: Sun, 26 Apr 2020 23:09:58 +0200 +Subject: [PATCH 193/709] chardev: Add macOS to list of OSes that support + -chardev serial +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +macOS API for dealing with serial ports/ttys is identical to BSDs. + +Signed-off-by: Mikhail Gusarov +Reviewed-by: Philippe Mathieu-Daudé +Tested-by: Philippe Mathieu-Daudé +Message-Id: <20200426210956.17324-1-dottedmag@dottedmag.net> +Signed-off-by: Laurent Vivier +--- + chardev/char-serial.c | 2 +- + include/qemu/osdep.h | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/chardev/char-serial.c b/chardev/char-serial.c +index 5b833ea077..7c3d84ae24 100644 +--- a/chardev/char-serial.c ++++ b/chardev/char-serial.c +@@ -53,7 +53,7 @@ static void qmp_chardev_open_serial(Chardev *chr, + + #elif defined(__linux__) || defined(__sun__) || defined(__FreeBSD__) \ + || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) \ +- || defined(__GLIBC__) ++ || defined(__GLIBC__) || defined(__APPLE__) + + static void tty_serial_init(int fd, int speed, + int parity, int data_bits, int stop_bits) +diff --git a/include/qemu/osdep.h b/include/qemu/osdep.h +index 20f5c5f197..ff7c17b857 100644 +--- a/include/qemu/osdep.h ++++ b/include/qemu/osdep.h +@@ -379,7 +379,7 @@ void qemu_anon_ram_free(void *ptr, size_t size); + #define HAVE_CHARDEV_SERIAL 1 + #elif defined(__linux__) || defined(__sun__) || defined(__FreeBSD__) \ + || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) \ +- || defined(__GLIBC__) ++ || defined(__GLIBC__) || defined(__APPLE__) + #define HAVE_CHARDEV_SERIAL 1 + #endif + +-- +2.23.0 + diff --git a/checkpatch-fix-acpi-check-with-multiple-file-name.patch b/checkpatch-fix-acpi-check-with-multiple-file-name.patch new file mode 100644 index 0000000000000000000000000000000000000000..5039b78a758cf1ba78705b7c214ba84f9a12106a --- /dev/null +++ b/checkpatch-fix-acpi-check-with-multiple-file-name.patch @@ -0,0 +1,86 @@ +From e625ba2a413f2bfdbb71c71008b627fede20fcbb Mon Sep 17 00:00:00 2001 +From: "Michael S. Tsirkin" +Date: Mon, 4 May 2020 07:22:49 -0400 +Subject: [PATCH 215/709] checkpatch: fix acpi check with multiple file name + +Using global expected/nonexpected values causes +false positives when testing multiple patches in one +checkpatch run: one patch can change expected, +another one non-expected. + +Use local variables within process() to fix that. + +Signed-off-by: Michael S. Tsirkin +--- + scripts/checkpatch.pl | 22 ++++++++++++---------- + 1 file changed, 12 insertions(+), 10 deletions(-) + +diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl +index e658e6546f..c3d08aa99f 100755 +--- a/scripts/checkpatch.pl ++++ b/scripts/checkpatch.pl +@@ -35,8 +35,6 @@ my $summary_file = 0; + my $root; + my %debug; + my $help = 0; +-my $acpi_testexpected; +-my $acpi_nontestexpected; + + sub help { + my ($exitcode) = @_; +@@ -1261,21 +1259,22 @@ sub WARN { + # According to tests/qtest/bios-tables-test.c: do not + # change expected file in the same commit with adding test + sub checkfilename { +- my ($name) = @_; ++ my ($name, $acpi_testexpected, $acpi_nontestexpected) = @_; ++ + if ($name =~ m#^tests/data/acpi/# and + # make exception for a shell script that rebuilds the files + not $name =~ m#^\.sh$# or + $name =~ m#^tests/qtest/bios-tables-test-allowed-diff.h$#) { +- $acpi_testexpected = $name; ++ $$acpi_testexpected = $name; + } else { +- $acpi_nontestexpected = $name; ++ $$acpi_nontestexpected = $name; + } +- if (defined $acpi_testexpected and defined $acpi_nontestexpected) { ++ if (defined $$acpi_testexpected and defined $$acpi_nontestexpected) { + ERROR("Do not add expected files together with tests, " . + "follow instructions in " . + "tests/qtest/bios-tables-test.c: both " . +- $acpi_testexpected . " and " . +- $acpi_nontestexpected . " found\n"); ++ $$acpi_testexpected . " and " . ++ $$acpi_nontestexpected . " found\n"); + } + } + +@@ -1325,6 +1324,9 @@ sub process { + my %suppress_whiletrailers; + my %suppress_export; + ++ my $acpi_testexpected; ++ my $acpi_nontestexpected; ++ + # Pre-scan the patch sanitizing the lines. + + sanitise_line_reset(); +@@ -1454,11 +1456,11 @@ sub process { + if ($line =~ /^diff --git.*?(\S+)$/) { + $realfile = $1; + $realfile =~ s@^([^/]*)/@@ if (!$file); +- checkfilename($realfile); ++ checkfilename($realfile, \$acpi_testexpected, \$acpi_nontestexpected); + } elsif ($line =~ /^\+\+\+\s+(\S+)/) { + $realfile = $1; + $realfile =~ s@^([^/]*)/@@ if (!$file); +- checkfilename($realfile); ++ checkfilename($realfile, \$acpi_testexpected, \$acpi_nontestexpected); + + $p1_prefix = $1; + if (!$file && $tree && $p1_prefix ne '' && +-- +2.23.0 + diff --git a/checkpatch-ignore-allowed-diff-list.patch b/checkpatch-ignore-allowed-diff-list.patch new file mode 100644 index 0000000000000000000000000000000000000000..704c69fac1807a65563d6ea9572b4b43339da695 --- /dev/null +++ b/checkpatch-ignore-allowed-diff-list.patch @@ -0,0 +1,42 @@ +From e11b06a880caa1630fcfdca7d2fc3c9e597792a1 Mon Sep 17 00:00:00 2001 +From: "Michael S. Tsirkin" +Date: Mon, 4 May 2020 07:47:17 -0400 +Subject: [PATCH 216/709] checkpatch: ignore allowed diff list + +Allow changing allowed diff list at any point: +- when changing code under test +- when adding expected files + +It's just a list of files so easy to review and merge anyway. + +Signed-off-by: Michael S. Tsirkin +--- + scripts/checkpatch.pl | 11 ++++++----- + 1 file changed, 6 insertions(+), 5 deletions(-) + +diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl +index c3d08aa99f..0ba213e9f2 100755 +--- a/scripts/checkpatch.pl ++++ b/scripts/checkpatch.pl +@@ -1261,12 +1261,13 @@ sub WARN { + sub checkfilename { + my ($name, $acpi_testexpected, $acpi_nontestexpected) = @_; + +- if ($name =~ m#^tests/data/acpi/# and +- # make exception for a shell script that rebuilds the files +- not $name =~ m#^\.sh$# or +- $name =~ m#^tests/qtest/bios-tables-test-allowed-diff.h$#) { ++ # Note: shell script that rebuilds the expected files is in the same ++ # directory as files themselves. ++ # Note: allowed diff list can be changed both when changing expected ++ # files and when changing tests. ++ if ($name =~ m#^tests/data/acpi/# and not $name =~ m#^\.sh$#) { + $$acpi_testexpected = $name; +- } else { ++ } elsif ($name =~ m#^tests/qtest/bios-tables-test-allowed-diff.h$#) { + $$acpi_nontestexpected = $name; + } + if (defined $$acpi_testexpected and defined $$acpi_nontestexpected) { +-- +2.23.0 + diff --git a/cirrus.yml-bootstrap-pkg-unconditionally.patch b/cirrus.yml-bootstrap-pkg-unconditionally.patch new file mode 100644 index 0000000000000000000000000000000000000000..5f2fce5110aa82287af8f7b627db35e2477ff34e --- /dev/null +++ b/cirrus.yml-bootstrap-pkg-unconditionally.patch @@ -0,0 +1,37 @@ +From ae52862970bb9f372d6ddebd0e34dc7927b6a7f7 Mon Sep 17 00:00:00 2001 +From: Li-Wen Hsu +Date: Mon, 4 May 2020 17:23:50 +0800 +Subject: [PATCH 269/709] .cirrus.yml: bootstrap pkg unconditionally +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This ensures compatibility with pkg repo so a change in upstream +doesn't break setup. See: + + https://lists.freebsd.org/pipermail/freebsd-cloud/2020-April/000234.html + +Message-Id: +Signed-off-by: Li-Wen Hsu +[AJB: applied from Li-Wen's github, applied sob, tweaked commit message] +Signed-off-by: Alex Bennée +--- + .cirrus.yml | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/.cirrus.yml b/.cirrus.yml +index f06f5af2b9..de0727cb09 100644 +--- a/.cirrus.yml ++++ b/.cirrus.yml +@@ -6,7 +6,7 @@ freebsd_12_task: + image_family: freebsd-12-1 + cpu: 8 + memory: 8G +- install_script: pkg install -y ++ install_script: ASSUME_ALWAYS_YES=yes pkg bootstrap -f ; pkg install -y + bash bison curl cyrus-sasl git glib gmake gnutls gsed + nettle perl5 pixman pkgconf png usbredir + script: +-- +2.23.0 + diff --git a/cirrus.yml-bump-FreeBSD-to-the-current-stable-relea.patch b/cirrus.yml-bump-FreeBSD-to-the-current-stable-relea.patch new file mode 100644 index 0000000000000000000000000000000000000000..c561fa1134105e3e5a77d489aa9305636fee296d --- /dev/null +++ b/cirrus.yml-bump-FreeBSD-to-the-current-stable-relea.patch @@ -0,0 +1,36 @@ +From 8f3e2968f696968787d7607adc5d2b31fc7fe1a1 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Alex=20Benn=C3=A9e?= +Date: Fri, 1 May 2020 12:15:04 +0100 +Subject: [PATCH 268/709] .cirrus.yml: bump FreeBSD to the current stable + release +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Hopefully this will un-stick the test which has been broken for a long +time. + +Signed-off-by: Alex Bennée +Reviewed-by: Li-Wen Hsu +Tested-by: Li-Wen Hsu +Message-Id: <20200501111505.4225-4-alex.bennee@linaro.org> +--- + .cirrus.yml | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/.cirrus.yml b/.cirrus.yml +index 90645fede6..f06f5af2b9 100644 +--- a/.cirrus.yml ++++ b/.cirrus.yml +@@ -3,7 +3,7 @@ env: + + freebsd_12_task: + freebsd_instance: +- image: freebsd-12-0-release-amd64 ++ image_family: freebsd-12-1 + cpu: 8 + memory: 8G + install_script: pkg install -y +-- +2.23.0 + diff --git a/configure-favour-gdb-multiarch-if-we-have-it.patch b/configure-favour-gdb-multiarch-if-we-have-it.patch new file mode 100644 index 0000000000000000000000000000000000000000..804846978a697e5a4495a38ca732f5ad1509f42f --- /dev/null +++ b/configure-favour-gdb-multiarch-if-we-have-it.patch @@ -0,0 +1,34 @@ +From f2385398b2f02eec9ea78ea4aa88c5ee66cd1ded Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Alex=20Benn=C3=A9e?= +Date: Thu, 30 Apr 2020 20:01:14 +0100 +Subject: [PATCH 271/709] configure: favour gdb-multiarch if we have it +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +As gdb will generally be talking to "foreign" guests lets use that if +we can. Otherwise the chances of gdb barfing are considerably higher. + +Signed-off-by: Alex Bennée +Reviewed-by: Philippe Mathieu-Daudé +Message-Id: <20200430190122.4592-2-alex.bennee@linaro.org> +--- + configure | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/configure b/configure +index 23b5e93752..c58787100f 100755 +--- a/configure ++++ b/configure +@@ -303,7 +303,7 @@ libs_qga="" + debug_info="yes" + stack_protector="" + use_containers="yes" +-gdb_bin=$(command -v "gdb") ++gdb_bin=$(command -v "gdb-multiarch" || command -v "gdb") + + if test -e "$source_path/.git" + then +-- +2.23.0 + diff --git a/cpu-add-Cortex-A72-processor-kvm-target-support.patch b/cpu-add-Cortex-A72-processor-kvm-target-support.patch deleted file mode 100644 index a310c37de95cb5fac446418afcd1efe3650180af..0000000000000000000000000000000000000000 --- a/cpu-add-Cortex-A72-processor-kvm-target-support.patch +++ /dev/null @@ -1,58 +0,0 @@ -From 4304d1de2c790ac75ed2f5984c4a3a2760c08fff Mon Sep 17 00:00:00 2001 -From: Xu Yandong -Date: Mon, 23 Sep 2019 14:35:25 +0800 -Subject: [PATCH] cpu: add Cortex-A72 processor kvm target support - -The ARM Cortex-A72 is ARMv8-A micro-architecture, -add kvm target to ARM Cortex-A72 processor definition. - -Signed-off-by: Xu Yandong ---- - target/arm/cpu64.c | 2 +- - target/arm/kvm-consts.h | 3 +++ - 2 files changed, 4 insertions(+), 1 deletion(-) - -diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c -index e408f50d..afbfd1ec 100644 ---- a/target/arm/cpu64.c -+++ b/target/arm/cpu64.c -@@ -212,6 +212,7 @@ static void aarch64_a72_initfn(Object *obj) - ARMCPU *cpu = ARM_CPU(obj); - - cpu->dtb_compatible = "arm,cortex-a72"; -+ cpu->kvm_target = QEMU_KVM_ARM_TARGET_GENERIC_V8; - set_feature(&cpu->env, ARM_FEATURE_V8); - set_feature(&cpu->env, ARM_FEATURE_VFP4); - set_feature(&cpu->env, ARM_FEATURE_NEON); -@@ -276,7 +277,6 @@ static void aarch64_kunpeng_t82_initfn(Object *obj) - cpu->id_aa64dfr0 = 0x110305408; - cpu->isar.id_aa64isar0 = 0x10211120; - cpu->isar.id_aa64mmfr0 = 0x101125; -- cpu->kvm_target = KVM_ARM_TARGET_GENERIC_V8; - } - - static void cpu_max_get_sve_vq(Object *obj, Visitor *v, const char *name, -diff --git a/target/arm/kvm-consts.h b/target/arm/kvm-consts.h -index aad28258..b7dac596 100644 ---- a/target/arm/kvm-consts.h -+++ b/target/arm/kvm-consts.h -@@ -130,6 +130,8 @@ MISMATCH_CHECK(QEMU_PSCI_RET_DISABLED, PSCI_RET_DISABLED); - #define QEMU_KVM_ARM_TARGET_CORTEX_A57 2 - #define QEMU_KVM_ARM_TARGET_XGENE_POTENZA 3 - #define QEMU_KVM_ARM_TARGET_CORTEX_A53 4 -+/* Generic ARM v8 target */ -+#define QEMU_KVM_ARM_TARGET_GENERIC_V8 5 - - /* There's no kernel define for this: sentinel value which - * matches no KVM target value for either 64 or 32 bit -@@ -142,6 +144,7 @@ MISMATCH_CHECK(QEMU_KVM_ARM_TARGET_FOUNDATION_V8, KVM_ARM_TARGET_FOUNDATION_V8); - MISMATCH_CHECK(QEMU_KVM_ARM_TARGET_CORTEX_A57, KVM_ARM_TARGET_CORTEX_A57); - MISMATCH_CHECK(QEMU_KVM_ARM_TARGET_XGENE_POTENZA, KVM_ARM_TARGET_XGENE_POTENZA); - MISMATCH_CHECK(QEMU_KVM_ARM_TARGET_CORTEX_A53, KVM_ARM_TARGET_CORTEX_A53); -+MISMATCH_CHECK(QEMU_KVM_ARM_TARGET_GENERIC_V8, KVM_ARM_TARGET_GENERIC_V8); - #else - MISMATCH_CHECK(QEMU_KVM_ARM_TARGET_CORTEX_A15, KVM_ARM_TARGET_CORTEX_A15); - MISMATCH_CHECK(QEMU_KVM_ARM_TARGET_CORTEX_A7, KVM_ARM_TARGET_CORTEX_A7); --- -2.23.0 - diff --git a/cpu-add-Kunpeng-920-cpu-support.patch b/cpu-add-Kunpeng-920-cpu-support.patch deleted file mode 100644 index 149a1a123e8deae9de1e634aa025618518c7f56f..0000000000000000000000000000000000000000 --- a/cpu-add-Kunpeng-920-cpu-support.patch +++ /dev/null @@ -1,65 +0,0 @@ -From 70063948181062161a341a8738a53708d8ed0a0b Mon Sep 17 00:00:00 2001 -From: Xu Yandong -Date: Wed, 28 Aug 2019 01:36:21 -0400 -Subject: [PATCH] cpu: add Kunpeng-920 cpu support - -Signed-off-by: Xu Yandong ---- - hw/arm/virt.c | 1 + - target/arm/cpu64.c | 21 +++++++++++++++++++++ - 2 files changed, 22 insertions(+) - -diff --git a/hw/arm/virt.c b/hw/arm/virt.c -index f89757df..11468b72 100644 ---- a/hw/arm/virt.c -+++ b/hw/arm/virt.c -@@ -179,6 +179,7 @@ static const char *valid_cpus[] = { - ARM_CPU_TYPE_NAME("cortex-a53"), - ARM_CPU_TYPE_NAME("cortex-a57"), - ARM_CPU_TYPE_NAME("cortex-a72"), -+ ARM_CPU_TYPE_NAME("Kunpeng-920"), - ARM_CPU_TYPE_NAME("host"), - ARM_CPU_TYPE_NAME("max"), - }; -diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c -index 228906f2..5581d5e1 100644 ---- a/target/arm/cpu64.c -+++ b/target/arm/cpu64.c -@@ -258,6 +258,26 @@ static void aarch64_a72_initfn(Object *obj) - define_arm_cp_regs(cpu, cortex_a72_a57_a53_cp_reginfo); - } - -+static void aarch64_kunpeng_920_initfn(Object *obj) -+{ -+ ARMCPU *cpu = ARM_CPU(obj); -+ -+ /* -+ * Hisilicon Kunpeng-920 CPU is similar to cortex-a72, -+ * so first initialize cpu data as cortex-a72 CPU, -+ * and then update the special registers. -+ */ -+ aarch64_a72_initfn(obj); -+ -+ cpu->midr = 0x480fd010; -+ cpu->ctr = 0x84448004; -+ cpu->isar.id_aa64pfr0 = 0x11001111; -+ cpu->id_aa64dfr0 = 0x110305408; -+ cpu->isar.id_aa64isar0 = 0x10211120; -+ cpu->isar.id_aa64mmfr0 = 0x101125; -+ cpu->kvm_target = KVM_ARM_TARGET_GENERIC_V8; -+} -+ - static void cpu_max_get_sve_vq(Object *obj, Visitor *v, const char *name, - void *opaque, Error **errp) - { -@@ -388,6 +408,7 @@ static const ARMCPUInfo aarch64_cpus[] = { - { .name = "cortex-a57", .initfn = aarch64_a57_initfn }, - { .name = "cortex-a53", .initfn = aarch64_a53_initfn }, - { .name = "cortex-a72", .initfn = aarch64_a72_initfn }, -+ { .name = "Kunpeng-920", .initfn = aarch64_kunpeng_920_initfn }, - { .name = "max", .initfn = aarch64_max_initfn }, - { .name = NULL } - }; --- -2.19.1 - diff --git a/cpu-parse-feature-to-avoid-failure.patch b/cpu-parse-feature-to-avoid-failure.patch deleted file mode 100644 index a241a5f140c371f792a75839c53fb5b8779f7060..0000000000000000000000000000000000000000 --- a/cpu-parse-feature-to-avoid-failure.patch +++ /dev/null @@ -1,72 +0,0 @@ -From ba1ca232cfa2ca273c610beda40bee2143f11964 Mon Sep 17 00:00:00 2001 -From: rpm-build -Date: Tue, 3 Sep 2019 16:27:39 +0800 -Subject: [PATCH] cpu: parse +/- feature to avoid failure - ---- - target/arm/cpu64.c | 38 ++++++++++++++++++++++++++++++++++++++ - 1 file changed, 38 insertions(+) - -diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c -index 0d492877..6ce87ce0 100644 ---- a/target/arm/cpu64.c -+++ b/target/arm/cpu64.c -@@ -30,6 +30,7 @@ - #include "sysemu/kvm.h" - #include "kvm_arm.h" - #include "qapi/visitor.h" -+#include "hw/qdev-properties.h" - - static inline void set_feature(CPUARMState *env, int feature) - { -@@ -455,10 +456,47 @@ static gchar *aarch64_gdb_arch_name(CPUState *cs) - return g_strdup("aarch64"); - } - -+/* Parse "+feature,-feature,feature=foo" CPU feature string -+ */ -+static void arm_cpu_parse_featurestr(const char *typename, char *features, -+ Error **errp) -+{ -+ char *featurestr; -+ char *val; -+ static bool cpu_globals_initialized; -+ -+ if (cpu_globals_initialized) { -+ return; -+ } -+ cpu_globals_initialized = true; -+ -+ featurestr = features ? strtok(features, ",") : NULL; -+ while (featurestr) { -+ val = strchr(featurestr, '='); -+ if (val) { -+ GlobalProperty *prop = g_new0(typeof(*prop), 1); -+ *val = 0; -+ val++; -+ prop->driver = typename; -+ prop->property = g_strdup(featurestr); -+ prop->value = g_strdup(val); -+ qdev_prop_register_global(prop); -+ } else if (featurestr[0] == '+' || featurestr[0] == '-') { -+ warn_report("Ignore %s feature\n", featurestr); -+ } else { -+ error_setg(errp, "Expected key=value format, found %s.", -+ featurestr); -+ return; -+ } -+ featurestr = strtok(NULL, ","); -+ } -+} -+ - static void aarch64_cpu_class_init(ObjectClass *oc, void *data) - { - CPUClass *cc = CPU_CLASS(oc); - -+ cc->parse_features = arm_cpu_parse_featurestr; - cc->cpu_exec_interrupt = arm_cpu_exec_interrupt; - cc->gdb_read_register = aarch64_cpu_gdb_read_register; - cc->gdb_write_register = aarch64_cpu_gdb_write_register; --- -2.19.1 - diff --git a/cpus-Fix-configure_icount-error-API-violation.patch b/cpus-Fix-configure_icount-error-API-violation.patch new file mode 100644 index 0000000000000000000000000000000000000000..cd1e0dae16d89bfc117ff1365eceedf2e3b32514 --- /dev/null +++ b/cpus-Fix-configure_icount-error-API-violation.patch @@ -0,0 +1,101 @@ +From abc9bf69a66a11499a801ff545b8fe7adbb3a04c Mon Sep 17 00:00:00 2001 +From: Markus Armbruster +Date: Wed, 22 Apr 2020 15:07:08 +0200 +Subject: [PATCH 016/709] cpus: Fix configure_icount() error API violation + +The Error ** argument must be NULL, &error_abort, &error_fatal, or a +pointer to a variable containing NULL. Passing an argument of the +latter kind twice without clearing it in between is wrong: if the +first call sets an error, it no longer points to NULL for the second +call. + +configure_icount() is wrong that way. Harmless, because its @errp is +always &error_abort or &error_fatal. + +Just as wrong (and just as harmless): when it fails, it can still +update global state. + +Fix all that. + +Cc: Paolo Bonzini +Signed-off-by: Markus Armbruster +Message-Id: <20200422130719.28225-4-armbru@redhat.com> +--- + cpus.c | 45 +++++++++++++++++++++++++++------------------ + 1 file changed, 27 insertions(+), 18 deletions(-) + +diff --git a/cpus.c b/cpus.c +index ef441bdf62..1b542b37f9 100644 +--- a/cpus.c ++++ b/cpus.c +@@ -797,40 +797,49 @@ void cpu_ticks_init(void) + + void configure_icount(QemuOpts *opts, Error **errp) + { +- const char *option; ++ const char *option = qemu_opt_get(opts, "shift"); ++ bool sleep = qemu_opt_get_bool(opts, "sleep", true); ++ bool align = qemu_opt_get_bool(opts, "align", false); ++ long time_shift = -1; + char *rem_str = NULL; + +- option = qemu_opt_get(opts, "shift"); +- if (!option) { +- if (qemu_opt_get(opts, "align") != NULL) { +- error_setg(errp, "Please specify shift option when using align"); +- } ++ if (!option && qemu_opt_get(opts, "align")) { ++ error_setg(errp, "Please specify shift option when using align"); + return; + } + +- icount_sleep = qemu_opt_get_bool(opts, "sleep", true); +- if (icount_sleep) { +- timers_state.icount_warp_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL_RT, +- icount_timer_cb, NULL); +- } +- +- icount_align_option = qemu_opt_get_bool(opts, "align", false); +- +- if (icount_align_option && !icount_sleep) { ++ if (align && !sleep) { + error_setg(errp, "align=on and sleep=off are incompatible"); ++ return; + } ++ + if (strcmp(option, "auto") != 0) { + errno = 0; +- timers_state.icount_time_shift = strtol(option, &rem_str, 0); ++ time_shift = strtol(option, &rem_str, 0); + if (errno != 0 || *rem_str != '\0' || !strlen(option)) { + error_setg(errp, "icount: Invalid shift value"); ++ return; + } +- use_icount = 1; +- return; + } else if (icount_align_option) { + error_setg(errp, "shift=auto and align=on are incompatible"); ++ return; + } else if (!icount_sleep) { + error_setg(errp, "shift=auto and sleep=off are incompatible"); ++ return; ++ } ++ ++ icount_sleep = sleep; ++ if (icount_sleep) { ++ timers_state.icount_warp_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL_RT, ++ icount_timer_cb, NULL); ++ } ++ ++ icount_align_option = align; ++ ++ if (time_shift >= 0) { ++ timers_state.icount_time_shift = time_shift; ++ use_icount = 1; ++ return; + } + + use_icount = 2; +-- +2.23.0 + diff --git a/cpus-Proper-range-checking-for-icount-shift-N.patch b/cpus-Proper-range-checking-for-icount-shift-N.patch new file mode 100644 index 0000000000000000000000000000000000000000..1231a05b94b112b6c6666ce1b5861bf0d7abe252 --- /dev/null +++ b/cpus-Proper-range-checking-for-icount-shift-N.patch @@ -0,0 +1,53 @@ +From 9ec374a781c34daa6e70fcd885ef30e090cc2384 Mon Sep 17 00:00:00 2001 +From: Markus Armbruster +Date: Wed, 22 Apr 2020 15:07:09 +0200 +Subject: [PATCH 017/709] cpus: Proper range-checking for -icount shift=N + +timers_state.icount_time_shift must be in [0,63] to avoid undefined +behavior when shifting by it, e.g. in cpu_icount_to_ns(). +icount_adjust() clamps it to [0,MAX_ICOUNT_SHIFT], with +MAX_ICOUNT_SHIFT = 10. configure_icount() doesn't. Fix that. + +Fixes: a8bfac37085c3372366d722f131a7e18d664ee4d +Cc: Paolo Bonzini +Signed-off-by: Markus Armbruster +Message-Id: <20200422130719.28225-5-armbru@redhat.com> +--- + cpus.c | 7 +++---- + 1 file changed, 3 insertions(+), 4 deletions(-) + +diff --git a/cpus.c b/cpus.c +index 1b542b37f9..5670c96bcf 100644 +--- a/cpus.c ++++ b/cpus.c +@@ -25,6 +25,7 @@ + #include "qemu/osdep.h" + #include "qemu-common.h" + #include "qemu/config-file.h" ++#include "qemu/cutils.h" + #include "migration/vmstate.h" + #include "monitor/monitor.h" + #include "qapi/error.h" +@@ -801,7 +802,6 @@ void configure_icount(QemuOpts *opts, Error **errp) + bool sleep = qemu_opt_get_bool(opts, "sleep", true); + bool align = qemu_opt_get_bool(opts, "align", false); + long time_shift = -1; +- char *rem_str = NULL; + + if (!option && qemu_opt_get(opts, "align")) { + error_setg(errp, "Please specify shift option when using align"); +@@ -814,9 +814,8 @@ void configure_icount(QemuOpts *opts, Error **errp) + } + + if (strcmp(option, "auto") != 0) { +- errno = 0; +- time_shift = strtol(option, &rem_str, 0); +- if (errno != 0 || *rem_str != '\0' || !strlen(option)) { ++ if (qemu_strtol(option, NULL, 0, &time_shift) < 0 ++ || time_shift < 0 || time_shift > MAX_ICOUNT_SHIFT) { + error_setg(errp, "icount: Invalid shift value"); + return; + } +-- +2.23.0 + diff --git a/crypto-Redundant-type-conversion-for-AES_KEY-pointer.patch b/crypto-Redundant-type-conversion-for-AES_KEY-pointer.patch new file mode 100644 index 0000000000000000000000000000000000000000..950d269b65b86d5d0319d2461a2a6738982ff0c1 --- /dev/null +++ b/crypto-Redundant-type-conversion-for-AES_KEY-pointer.patch @@ -0,0 +1,64 @@ +From ccebb5f3735edcbcbf9429b605fcb9399a0dd72c Mon Sep 17 00:00:00 2001 +From: Chen Qun +Date: Tue, 5 May 2020 16:59:40 +0800 +Subject: [PATCH 313/709] crypto: Redundant type conversion for AES_KEY pointer +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +We can delete the redundant type conversion if +we set the the AES_KEY parameter with 'const' in +qcrypto_cipher_aes_ecb_(en|de)crypt() function. + +Reported-by: Euler Robot +Signed-off-by: Chen Qun +Signed-off-by: Daniel P. Berrangé +--- + crypto/cipher-builtin.c | 10 ++++------ + 1 file changed, 4 insertions(+), 6 deletions(-) + +diff --git a/crypto/cipher-builtin.c b/crypto/cipher-builtin.c +index bf8413e71a..35cf7820d9 100644 +--- a/crypto/cipher-builtin.c ++++ b/crypto/cipher-builtin.c +@@ -74,7 +74,7 @@ static void qcrypto_cipher_free_aes(QCryptoCipher *cipher) + } + + +-static void qcrypto_cipher_aes_ecb_encrypt(AES_KEY *key, ++static void qcrypto_cipher_aes_ecb_encrypt(const AES_KEY *key, + const void *in, + void *out, + size_t len) +@@ -100,7 +100,7 @@ static void qcrypto_cipher_aes_ecb_encrypt(AES_KEY *key, + } + + +-static void qcrypto_cipher_aes_ecb_decrypt(AES_KEY *key, ++static void qcrypto_cipher_aes_ecb_decrypt(const AES_KEY *key, + const void *in, + void *out, + size_t len) +@@ -133,8 +133,7 @@ static void qcrypto_cipher_aes_xts_encrypt(const void *ctx, + { + const QCryptoCipherBuiltinAESContext *aesctx = ctx; + +- qcrypto_cipher_aes_ecb_encrypt((AES_KEY *)&aesctx->enc, +- src, dst, length); ++ qcrypto_cipher_aes_ecb_encrypt(&aesctx->enc, src, dst, length); + } + + +@@ -145,8 +144,7 @@ static void qcrypto_cipher_aes_xts_decrypt(const void *ctx, + { + const QCryptoCipherBuiltinAESContext *aesctx = ctx; + +- qcrypto_cipher_aes_ecb_decrypt((AES_KEY *)&aesctx->dec, +- src, dst, length); ++ qcrypto_cipher_aes_ecb_decrypt(&aesctx->dec, src, dst, length); + } + + +-- +2.23.0 + diff --git a/crypto-extend-hash-benchmark-to-cover-more-algorithm.patch b/crypto-extend-hash-benchmark-to-cover-more-algorithm.patch new file mode 100644 index 0000000000000000000000000000000000000000..e80a6f1d00bbe9276eb37d2dc939e3e0879d3999 --- /dev/null +++ b/crypto-extend-hash-benchmark-to-cover-more-algorithm.patch @@ -0,0 +1,139 @@ +From 6022e15d146d8bba9610a9d134afa4bc6e5d9275 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= +Date: Thu, 22 Aug 2019 16:40:03 +0100 +Subject: [PATCH 315/709] crypto: extend hash benchmark to cover more + algorithms +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Extend the hash benchmark so that it can validate all algorithms +supported by QEMU instead of being limited to sha256. + +Reviewed-by: Eric Blake +Signed-off-by: Daniel P. Berrangé +--- + tests/benchmark-crypto-hash.c | 73 ++++++++++++++++++++++++++++------- + 1 file changed, 59 insertions(+), 14 deletions(-) + +diff --git a/tests/benchmark-crypto-hash.c b/tests/benchmark-crypto-hash.c +index 7f659f7323..d16837d00a 100644 +--- a/tests/benchmark-crypto-hash.c ++++ b/tests/benchmark-crypto-hash.c +@@ -15,9 +15,14 @@ + #include "crypto/init.h" + #include "crypto/hash.h" + ++typedef struct QCryptoHashOpts { ++ size_t chunk_size; ++ QCryptoHashAlgorithm alg; ++} QCryptoHashOpts; ++ + static void test_hash_speed(const void *opaque) + { +- size_t chunk_size = (size_t)opaque; ++ const QCryptoHashOpts *opts = opaque; + uint8_t *in = NULL, *out = NULL; + size_t out_len = 0; + const size_t total = 2 * GiB; +@@ -25,26 +30,24 @@ static void test_hash_speed(const void *opaque) + struct iovec iov; + int ret; + +- in = g_new0(uint8_t, chunk_size); +- memset(in, g_test_rand_int(), chunk_size); ++ in = g_new0(uint8_t, opts->chunk_size); ++ memset(in, g_test_rand_int(), opts->chunk_size); + + iov.iov_base = (char *)in; +- iov.iov_len = chunk_size; ++ iov.iov_len = opts->chunk_size; + + g_test_timer_start(); + remain = total; + while (remain) { +- ret = qcrypto_hash_bytesv(QCRYPTO_HASH_ALG_SHA256, ++ ret = qcrypto_hash_bytesv(opts->alg, + &iov, 1, &out, &out_len, + NULL); + g_assert(ret == 0); + +- remain -= chunk_size; ++ remain -= opts->chunk_size; + } + g_test_timer_elapsed(); + +- g_print("sha256: "); +- g_print("Hash %zu GB chunk size %zu bytes ", total / GiB, chunk_size); + g_print("%.2f MB/sec ", (double)total / MiB / g_test_timer_last()); + + g_free(out); +@@ -53,17 +56,59 @@ static void test_hash_speed(const void *opaque) + + int main(int argc, char **argv) + { +- size_t i; + char name[64]; + + g_test_init(&argc, &argv, NULL); + g_assert(qcrypto_init(NULL) == 0); + +- for (i = 512; i <= 64 * KiB; i *= 2) { +- memset(name, 0 , sizeof(name)); +- snprintf(name, sizeof(name), "/crypto/hash/speed-%zu", i); +- g_test_add_data_func(name, (void *)i, test_hash_speed); +- } ++#define TEST_ONE(a, c) \ ++ QCryptoHashOpts opts ## a ## c = { \ ++ .alg = QCRYPTO_HASH_ALG_ ## a, .chunk_size = c, \ ++ }; \ ++ memset(name, 0 , sizeof(name)); \ ++ snprintf(name, sizeof(name), \ ++ "/crypto/benchmark/hash/%s/bufsize-%d", \ ++ QCryptoHashAlgorithm_str(QCRYPTO_HASH_ALG_ ## a), \ ++ c); \ ++ if (qcrypto_hash_supports(QCRYPTO_HASH_ALG_ ## a)) \ ++ g_test_add_data_func(name, \ ++ &opts ## a ## c, \ ++ test_hash_speed); ++ ++ TEST_ONE(MD5, 512); ++ TEST_ONE(MD5, 1024); ++ TEST_ONE(MD5, 4096); ++ TEST_ONE(MD5, 16384); ++ ++ TEST_ONE(SHA1, 512); ++ TEST_ONE(SHA1, 1024); ++ TEST_ONE(SHA1, 4096); ++ TEST_ONE(SHA1, 16384); ++ ++ TEST_ONE(SHA224, 512); ++ TEST_ONE(SHA224, 1024); ++ TEST_ONE(SHA224, 4096); ++ TEST_ONE(SHA224, 16384); ++ ++ TEST_ONE(SHA384, 512); ++ TEST_ONE(SHA384, 1024); ++ TEST_ONE(SHA384, 4096); ++ TEST_ONE(SHA384, 16384); ++ ++ TEST_ONE(SHA256, 512); ++ TEST_ONE(SHA256, 1024); ++ TEST_ONE(SHA256, 4096); ++ TEST_ONE(SHA256, 16384); ++ ++ TEST_ONE(SHA512, 512); ++ TEST_ONE(SHA512, 1024); ++ TEST_ONE(SHA512, 4096); ++ TEST_ONE(SHA512, 16384); ++ ++ TEST_ONE(RIPEMD160, 512); ++ TEST_ONE(RIPEMD160, 1024); ++ TEST_ONE(RIPEMD160, 4096); ++ TEST_ONE(RIPEMD160, 16384); + + return g_test_run(); + } +-- +2.23.0 + diff --git a/crypto-fix-getter-of-a-QCryptoSecret-s-property.patch b/crypto-fix-getter-of-a-QCryptoSecret-s-property.patch new file mode 100644 index 0000000000000000000000000000000000000000..b3d060ffb25cc144f6efc6b09dc4c8b195cbee10 --- /dev/null +++ b/crypto-fix-getter-of-a-QCryptoSecret-s-property.patch @@ -0,0 +1,42 @@ +From 569644f761f704901b70bd259762c60b7cb28634 Mon Sep 17 00:00:00 2001 +From: Tong Ho +Date: Thu, 9 Jan 2020 12:09:58 -0800 +Subject: [PATCH 311/709] crypto: fix getter of a QCryptoSecret's property +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This fixes the condition-check done by the "loaded" property +getter, such that the property returns true even when the +secret is loaded by the 'file' option. + +Signed-off-by: Tong Ho +Signed-off-by: Daniel P. Berrangé +--- + crypto/secret.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/crypto/secret.c b/crypto/secret.c +index 1cf0ad0ce8..5fb6bbe59c 100644 +--- a/crypto/secret.c ++++ b/crypto/secret.c +@@ -221,6 +221,7 @@ qcrypto_secret_prop_set_loaded(Object *obj, + secret->rawlen = inputlen; + } else { + g_free(secret->rawdata); ++ secret->rawdata = NULL; + secret->rawlen = 0; + } + } +@@ -231,7 +232,7 @@ qcrypto_secret_prop_get_loaded(Object *obj, + Error **errp G_GNUC_UNUSED) + { + QCryptoSecret *secret = QCRYPTO_SECRET(obj); +- return secret->data != NULL; ++ return secret->rawdata != NULL; + } + + +-- +2.23.0 + diff --git a/crypto-secret-fix-inconsequential-errors.patch b/crypto-secret-fix-inconsequential-errors.patch new file mode 100644 index 0000000000000000000000000000000000000000..614010d607fc7de764dd80ac1773cab497c6b819 --- /dev/null +++ b/crypto-secret-fix-inconsequential-errors.patch @@ -0,0 +1,35 @@ +From 861c50bf5db3c18f5cd74ea929d4e018fdcedc64 Mon Sep 17 00:00:00 2001 +From: Alexey Krasikov +Date: Wed, 15 Apr 2020 23:13:35 +0300 +Subject: [PATCH 312/709] crypto/secret: fix inconsequential errors. +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Change condition from QCRYPTO_SECRET_FORMAT_RAW +to QCRYPTO_SECRET_FORMAT_BASE64 in if-operator, because +this is potential error if you add another format value. + +Reviewed-by: Philippe Mathieu-Daudé +Signed-off-by: Alexey Krasikov +Signed-off-by: Daniel P. Berrangé +--- + crypto/secret.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/crypto/secret.c b/crypto/secret.c +index 5fb6bbe59c..a846a3c87c 100644 +--- a/crypto/secret.c ++++ b/crypto/secret.c +@@ -204,7 +204,7 @@ qcrypto_secret_prop_set_loaded(Object *obj, + input = output; + inputlen = outputlen; + } else { +- if (secret->format != QCRYPTO_SECRET_FORMAT_RAW) { ++ if (secret->format == QCRYPTO_SECRET_FORMAT_BASE64) { + qcrypto_secret_decode(input, inputlen, + &output, &outputlen, &local_err); + g_free(input); +-- +2.23.0 + diff --git a/cryptodev-Fix-cryptodev_builtin_cleanup-error-API-vi.patch b/cryptodev-Fix-cryptodev_builtin_cleanup-error-API-vi.patch new file mode 100644 index 0000000000000000000000000000000000000000..dc82bb4f3521028bd4e8626b569f1c9b023abc57 --- /dev/null +++ b/cryptodev-Fix-cryptodev_builtin_cleanup-error-API-vi.patch @@ -0,0 +1,55 @@ +From 2a340b67bd0a702e6d2102691cb2cb2177b7e210 Mon Sep 17 00:00:00 2001 +From: Markus Armbruster +Date: Wed, 22 Apr 2020 15:07:06 +0200 +Subject: [PATCH 014/709] cryptodev: Fix cryptodev_builtin_cleanup() error API + violation + +The Error ** argument must be NULL, &error_abort, &error_fatal, or a +pointer to a variable containing NULL. Passing an argument of the +latter kind twice without clearing it in between is wrong: if the +first call sets an error, it no longer points to NULL for the second +call. + +cryptodev_builtin_cleanup() passes @errp to +cryptodev_builtin_sym_close_session() in a loop. Harmless, because +cryptodev_builtin_sym_close_session() can't actually fail. Fix it +anyway. + +Cc: Gonglei +Signed-off-by: Markus Armbruster +Message-Id: <20200422130719.28225-2-armbru@redhat.com> +--- + backends/cryptodev-builtin.c | 10 ++-------- + 1 file changed, 2 insertions(+), 8 deletions(-) + +diff --git a/backends/cryptodev-builtin.c b/backends/cryptodev-builtin.c +index c8ae3b9742..14316333fe 100644 +--- a/backends/cryptodev-builtin.c ++++ b/backends/cryptodev-builtin.c +@@ -282,12 +282,7 @@ static int cryptodev_builtin_sym_close_session( + CryptoDevBackendBuiltin *builtin = + CRYPTODEV_BACKEND_BUILTIN(backend); + +- if (session_id >= MAX_NUM_SESSIONS || +- builtin->sessions[session_id] == NULL) { +- error_setg(errp, "Cannot find a valid session id: %" PRIu64 "", +- session_id); +- return -1; +- } ++ assert(session_id < MAX_NUM_SESSIONS && builtin->sessions[session_id]); + + qcrypto_cipher_free(builtin->sessions[session_id]->cipher); + g_free(builtin->sessions[session_id]); +@@ -356,8 +351,7 @@ static void cryptodev_builtin_cleanup( + + for (i = 0; i < MAX_NUM_SESSIONS; i++) { + if (builtin->sessions[i] != NULL) { +- cryptodev_builtin_sym_close_session( +- backend, i, 0, errp); ++ cryptodev_builtin_sym_close_session(backend, i, 0, &error_abort); + } + } + +-- +2.23.0 + diff --git a/cutils-Fix-size_to_str-on-32-bit-platforms.patch b/cutils-Fix-size_to_str-on-32-bit-platforms.patch deleted file mode 100644 index aaf02e3a18dea2497b2fee9b7b29de088a4a7521..0000000000000000000000000000000000000000 --- a/cutils-Fix-size_to_str-on-32-bit-platforms.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 754da86714d550c3f995f11a2587395081362e0a Mon Sep 17 00:00:00 2001 -From: Eric Blake -Date: Wed, 17 Apr 2019 12:11:00 -0500 -Subject: [PATCH] cutils: Fix size_to_str() on 32-bit platforms - -When extracting a human-readable size formatter, we changed 'uint64_t -div' pre-patch to 'unsigned long div' post-patch. Which breaks on -32-bit platforms, resulting in 'inf' instead of intended values larger -than 999GB. - -Fixes: 22951aaa -CC: qemu-stable@nongnu.org -Reported-by: Max Reitz -Signed-off-by: Eric Blake -Reviewed-by: Max Reitz -Signed-off-by: Kevin Wolf -(cherry-picked from commit 754da86714d550c3f995f11a2587395081362e0a) ---- - util/cutils.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/util/cutils.c b/util/cutils.c -index e098debdc0..d682c90901 100644 ---- a/util/cutils.c -+++ b/util/cutils.c -@@ -825,7 +825,7 @@ const char *qemu_ether_ntoa(const MACAddr *mac) - char *size_to_str(uint64_t val) - { - static const char *suffixes[] = { "", "Ki", "Mi", "Gi", "Ti", "Pi", "Ei" }; -- unsigned long div; -+ uint64_t div; - int i; - - /* --- -2.19.1 - diff --git a/device_tree-Allow-name-wildcards-in-qemu_fdt_node_pa.patch b/device_tree-Allow-name-wildcards-in-qemu_fdt_node_pa.patch new file mode 100644 index 0000000000000000000000000000000000000000..dabc708126abfdb403fbd7c5895d65641b9d822f --- /dev/null +++ b/device_tree-Allow-name-wildcards-in-qemu_fdt_node_pa.patch @@ -0,0 +1,48 @@ +From 80972d3bb2dbc6a47bae84b694c14acba9c1de64 Mon Sep 17 00:00:00 2001 +From: "Edgar E. Iglesias" +Date: Thu, 23 Apr 2020 14:11:11 +0200 +Subject: [PATCH 120/709] device_tree: Allow name wildcards in + qemu_fdt_node_path() + +Allow name wildcards in qemu_fdt_node_path(). This is useful +to find all nodes with a given compatibility string. + +Reviewed-by: Alistair Francis +Signed-off-by: Edgar E. Iglesias +Message-id: 20200423121114.4274-2-edgar.iglesias@gmail.com +Signed-off-by: Peter Maydell +--- + device_tree.c | 2 +- + include/sysemu/device_tree.h | 3 +++ + 2 files changed, 4 insertions(+), 1 deletion(-) + +diff --git a/device_tree.c b/device_tree.c +index bba6cc2164..f5b4699aed 100644 +--- a/device_tree.c ++++ b/device_tree.c +@@ -308,7 +308,7 @@ char **qemu_fdt_node_path(void *fdt, const char *name, char *compat, + offset = len; + break; + } +- if (!strcmp(iter_name, name)) { ++ if (!name || !strcmp(iter_name, name)) { + char *path; + + path = g_malloc(path_len); +diff --git a/include/sysemu/device_tree.h b/include/sysemu/device_tree.h +index c16fd69bc0..7c53ef7634 100644 +--- a/include/sysemu/device_tree.h ++++ b/include/sysemu/device_tree.h +@@ -39,6 +39,9 @@ void *load_device_tree_from_sysfs(void); + * NULL. If there is no error but no matching node was found, the + * returned array contains a single element equal to NULL. If an error + * was encountered when parsing the blob, the function returns NULL ++ * ++ * @name may be NULL to wildcard names and only match compatibility ++ * strings. + */ + char **qemu_fdt_node_path(void *fdt, const char *name, char *compat, + Error **errp); +-- +2.23.0 + diff --git a/device_tree-Constify-compat-in-qemu_fdt_node_path.patch b/device_tree-Constify-compat-in-qemu_fdt_node_path.patch new file mode 100644 index 0000000000000000000000000000000000000000..bfae3113199ed9c22de9868d85d0231ada63a2b0 --- /dev/null +++ b/device_tree-Constify-compat-in-qemu_fdt_node_path.patch @@ -0,0 +1,45 @@ +From 958bae18b26ea7183865c8876c04441edfed3760 Mon Sep 17 00:00:00 2001 +From: "Edgar E. Iglesias" +Date: Thu, 23 Apr 2020 14:11:12 +0200 +Subject: [PATCH 121/709] device_tree: Constify compat in qemu_fdt_node_path() + +Make compat in qemu_fdt_node_path() const char *. + +Signed-off-by: Edgar E. Iglesias +Message-id: 20200423121114.4274-3-edgar.iglesias@gmail.com +Reviewed-by: Peter Maydell +Signed-off-by: Peter Maydell +--- + device_tree.c | 2 +- + include/sysemu/device_tree.h | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/device_tree.c b/device_tree.c +index f5b4699aed..b335dae707 100644 +--- a/device_tree.c ++++ b/device_tree.c +@@ -291,7 +291,7 @@ char **qemu_fdt_node_unit_path(void *fdt, const char *name, Error **errp) + return path_array; + } + +-char **qemu_fdt_node_path(void *fdt, const char *name, char *compat, ++char **qemu_fdt_node_path(void *fdt, const char *name, const char *compat, + Error **errp) + { + int offset, len, ret; +diff --git a/include/sysemu/device_tree.h b/include/sysemu/device_tree.h +index 7c53ef7634..982c89345f 100644 +--- a/include/sysemu/device_tree.h ++++ b/include/sysemu/device_tree.h +@@ -43,7 +43,7 @@ void *load_device_tree_from_sysfs(void); + * @name may be NULL to wildcard names and only match compatibility + * strings. + */ +-char **qemu_fdt_node_path(void *fdt, const char *name, char *compat, ++char **qemu_fdt_node_path(void *fdt, const char *name, const char *compat, + Error **errp); + + /** +-- +2.23.0 + diff --git a/disas-add-optional-note-support-to-cap_disas.patch b/disas-add-optional-note-support-to-cap_disas.patch new file mode 100644 index 0000000000000000000000000000000000000000..19bffeec1d0a206299030e1c6ec62ce7b695fc3a --- /dev/null +++ b/disas-add-optional-note-support-to-cap_disas.patch @@ -0,0 +1,105 @@ +From 16b22e02b57e403568b471511e0b2a70789c94df Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Alex=20Benn=C3=A9e?= +Date: Wed, 13 May 2020 18:51:33 +0100 +Subject: [PATCH 497/709] disas: add optional note support to cap_disas +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Include support for outputting a note at the top of a chunk of +disassembly to capstone as well. + +Signed-off-by: Alex Bennée +Reviewed-by: Philippe Mathieu-Daudé + +Message-Id: <20200513175134.19619-10-alex.bennee@linaro.org> +--- + disas.c | 23 +++++++++++++++-------- + 1 file changed, 15 insertions(+), 8 deletions(-) + +diff --git a/disas.c b/disas.c +index 7e8692de30..45285d3f63 100644 +--- a/disas.c ++++ b/disas.c +@@ -260,7 +260,8 @@ static void cap_dump_insn_units(disassemble_info *info, cs_insn *insn, + } + } + +-static void cap_dump_insn(disassemble_info *info, cs_insn *insn) ++static void cap_dump_insn(disassemble_info *info, cs_insn *insn, ++ const char *note) + { + fprintf_function print = info->fprintf_func; + int i, n, split; +@@ -281,7 +282,11 @@ static void cap_dump_insn(disassemble_info *info, cs_insn *insn) + } + + /* Print the actual instruction. */ +- print(info->stream, " %-8s %s\n", insn->mnemonic, insn->op_str); ++ print(info->stream, " %-8s %s", insn->mnemonic, insn->op_str); ++ if (note) { ++ print(info->stream, "\t\t%s", note); ++ } ++ print(info->stream, "\n"); + + /* Dump any remaining part of the insn on subsequent lines. */ + for (i = split; i < n; i += split) { +@@ -313,7 +318,7 @@ static bool cap_disas_target(disassemble_info *info, uint64_t pc, size_t size) + size -= tsize; + + while (cs_disasm_iter(handle, &cbuf, &csize, &pc, insn)) { +- cap_dump_insn(info, insn); ++ cap_dump_insn(info, insn, NULL); + } + + /* If the target memory is not consumed, go back for more... */ +@@ -342,7 +347,8 @@ static bool cap_disas_target(disassemble_info *info, uint64_t pc, size_t size) + } + + /* Disassemble SIZE bytes at CODE for the host. */ +-static bool cap_disas_host(disassemble_info *info, void *code, size_t size) ++static bool cap_disas_host(disassemble_info *info, void *code, size_t size, ++ const char *note) + { + csh handle; + const uint8_t *cbuf; +@@ -358,7 +364,8 @@ static bool cap_disas_host(disassemble_info *info, void *code, size_t size) + pc = (uintptr_t)code; + + while (cs_disasm_iter(handle, &cbuf, &size, &pc, insn)) { +- cap_dump_insn(info, insn); ++ cap_dump_insn(info, insn, note); ++ note = NULL; + } + if (size != 0) { + (*info->fprintf_func)(info->stream, +@@ -402,7 +409,7 @@ static bool cap_disas_monitor(disassemble_info *info, uint64_t pc, int count) + csize += tsize; + + if (cs_disasm_iter(handle, &cbuf, &csize, &pc, insn)) { +- cap_dump_insn(info, insn); ++ cap_dump_insn(info, insn, NULL); + if (--count <= 0) { + break; + } +@@ -416,7 +423,7 @@ static bool cap_disas_monitor(disassemble_info *info, uint64_t pc, int count) + #endif /* !CONFIG_USER_ONLY */ + #else + # define cap_disas_target(i, p, s) false +-# define cap_disas_host(i, p, s) false ++# define cap_disas_host(i, p, s, n) false + # define cap_disas_monitor(i, p, c) false + # define cap_disas_plugin(i, p, c) false + #endif /* CONFIG_CAPSTONE */ +@@ -664,7 +671,7 @@ void disas(FILE *out, void *code, unsigned long size, const char *note) + print_insn = print_insn_hppa; + #endif + +- if (s.info.cap_arch >= 0 && cap_disas_host(&s.info, code, size)) { ++ if (s.info.cap_arch >= 0 && cap_disas_host(&s.info, code, size, note)) { + return; + } + +-- +2.23.0 + diff --git a/disas-include-an-optional-note-for-the-start-of-disa.patch b/disas-include-an-optional-note-for-the-start-of-disa.patch new file mode 100644 index 0000000000000000000000000000000000000000..d4696f167392c7d79c7d1c21e071d74e3b3ecbbb --- /dev/null +++ b/disas-include-an-optional-note-for-the-start-of-disa.patch @@ -0,0 +1,138 @@ +From e5ef4ec28b801155e20fdb3a4cd21920ffc5f1af Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Alex=20Benn=C3=A9e?= +Date: Wed, 13 May 2020 18:51:32 +0100 +Subject: [PATCH 496/709] disas: include an optional note for the start of + disassembly +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This will become useful shortly for providing more information about +output assembly inline. While there fix up the indenting and code +formatting in disas(). + +Signed-off-by: Alex Bennée +Reviewed-by: Philippe Mathieu-Daudé + +Message-Id: <20200513175134.19619-9-alex.bennee@linaro.org> +--- + accel/tcg/translate-all.c | 4 ++-- + disas.c | 14 ++++++++++---- + include/disas/disas.h | 2 +- + include/exec/log.h | 4 ++-- + tcg/tcg.c | 4 ++-- + 5 files changed, 17 insertions(+), 11 deletions(-) + +diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c +index e4f703a7e6..cdf58bb420 100644 +--- a/accel/tcg/translate-all.c ++++ b/accel/tcg/translate-all.c +@@ -1800,7 +1800,7 @@ TranslationBlock *tb_gen_code(CPUState *cpu, + size_t data_size = gen_code_size - code_size; + size_t i; + +- log_disas(tb->tc.ptr, code_size); ++ log_disas(tb->tc.ptr, code_size, NULL); + + for (i = 0; i < data_size; i += sizeof(tcg_target_ulong)) { + if (sizeof(tcg_target_ulong) == 8) { +@@ -1814,7 +1814,7 @@ TranslationBlock *tb_gen_code(CPUState *cpu, + } + } + } else { +- log_disas(tb->tc.ptr, gen_code_size); ++ log_disas(tb->tc.ptr, gen_code_size, NULL); + } + qemu_log("\n"); + qemu_log_flush(); +diff --git a/disas.c b/disas.c +index 3937da6157..7e8692de30 100644 +--- a/disas.c ++++ b/disas.c +@@ -586,7 +586,7 @@ char *plugin_disas(CPUState *cpu, uint64_t addr, size_t size) + } + + /* Disassemble this for me please... (debugging). */ +-void disas(FILE *out, void *code, unsigned long size) ++void disas(FILE *out, void *code, unsigned long size, const char *note) + { + uintptr_t pc; + int count; +@@ -674,10 +674,16 @@ void disas(FILE *out, void *code, unsigned long size) + for (pc = (uintptr_t)code; size > 0; pc += count, size -= count) { + fprintf(out, "0x%08" PRIxPTR ": ", pc); + count = print_insn(pc, &s.info); +- fprintf(out, "\n"); +- if (count < 0) +- break; ++ if (note) { ++ fprintf(out, "\t\t%s", note); ++ note = NULL; ++ } ++ fprintf(out, "\n"); ++ if (count < 0) { ++ break; ++ } + } ++ + } + + /* Look up symbol for debugging purpose. Returns "" if unknown. */ +diff --git a/include/disas/disas.h b/include/disas/disas.h +index 36c33f6f19..1b6e035e32 100644 +--- a/include/disas/disas.h ++++ b/include/disas/disas.h +@@ -7,7 +7,7 @@ + #include "cpu.h" + + /* Disassemble this for me please... (debugging). */ +-void disas(FILE *out, void *code, unsigned long size); ++void disas(FILE *out, void *code, unsigned long size, const char *note); + void target_disas(FILE *out, CPUState *cpu, target_ulong code, + target_ulong size); + +diff --git a/include/exec/log.h b/include/exec/log.h +index fcc7b9e00b..3ed797c1c8 100644 +--- a/include/exec/log.h ++++ b/include/exec/log.h +@@ -56,13 +56,13 @@ static inline void log_target_disas(CPUState *cpu, target_ulong start, + rcu_read_unlock(); + } + +-static inline void log_disas(void *code, unsigned long size) ++static inline void log_disas(void *code, unsigned long size, const char *note) + { + QemuLogFile *logfile; + rcu_read_lock(); + logfile = atomic_rcu_read(&qemu_logfile); + if (logfile) { +- disas(logfile->fd, code, size); ++ disas(logfile->fd, code, size, note); + } + rcu_read_unlock(); + } +diff --git a/tcg/tcg.c b/tcg/tcg.c +index dd4b3d7684..a2268d9db0 100644 +--- a/tcg/tcg.c ++++ b/tcg/tcg.c +@@ -1092,7 +1092,7 @@ void tcg_prologue_init(TCGContext *s) + size_t data_size = prologue_size - code_size; + size_t i; + +- log_disas(buf0, code_size); ++ log_disas(buf0, code_size, NULL); + + for (i = 0; i < data_size; i += sizeof(tcg_target_ulong)) { + if (sizeof(tcg_target_ulong) == 8) { +@@ -1106,7 +1106,7 @@ void tcg_prologue_init(TCGContext *s) + } + } + } else { +- log_disas(buf0, prologue_size); ++ log_disas(buf0, prologue_size, NULL); + } + qemu_log("\n"); + qemu_log_flush(); +-- +2.23.0 + diff --git a/display-blizzard-use-extract16-for-fix-clang-analyze.patch b/display-blizzard-use-extract16-for-fix-clang-analyze.patch new file mode 100644 index 0000000000000000000000000000000000000000..aee309a6de5ecfb91a4138d81b0da99d118ad764 --- /dev/null +++ b/display-blizzard-use-extract16-for-fix-clang-analyze.patch @@ -0,0 +1,50 @@ +From fd1c220395eab1712e67238d876c72bf3292c153 Mon Sep 17 00:00:00 2001 +From: Chen Qun +Date: Wed, 25 Mar 2020 10:59:18 +0800 +Subject: [PATCH 147/709] display/blizzard: use extract16() for fix clang + analyzer warning in blizzard_draw_line16_32() + +Clang static code analyzer show warning: + hw/display/blizzard.c:940:9: warning: Value stored to 'data' is never read + data >>= 5; + ^ ~ +Reported-by: Euler Robot +Signed-off-by: Chen Qun +Reviewed-by: Laurent Vivier +Message-Id: <20200325025919.21316-3-kuhn.chenqun@huawei.com> +Signed-off-by: Laurent Vivier +--- + hw/display/blizzard.c | 10 ++++------ + 1 file changed, 4 insertions(+), 6 deletions(-) + +diff --git a/hw/display/blizzard.c b/hw/display/blizzard.c +index 359e399c2a..105241577d 100644 +--- a/hw/display/blizzard.c ++++ b/hw/display/blizzard.c +@@ -19,6 +19,7 @@ + */ + + #include "qemu/osdep.h" ++#include "qemu/bitops.h" + #include "ui/console.h" + #include "hw/display/blizzard.h" + #include "ui/pixel_ops.h" +@@ -932,12 +933,9 @@ static void blizzard_draw_line16_32(uint32_t *dest, + const uint16_t *end = (const void *) src + width; + while (src < end) { + data = *src ++; +- b = (data & 0x1f) << 3; +- data >>= 5; +- g = (data & 0x3f) << 2; +- data >>= 6; +- r = (data & 0x1f) << 3; +- data >>= 5; ++ b = extract16(data, 0, 5) << 3; ++ g = extract16(data, 5, 6) << 2; ++ r = extract16(data, 11, 5) << 3; + *dest++ = rgb_to_pixel32(r, g, b); + } + } +-- +2.23.0 + diff --git a/dma-helpers-ensure-AIO-callback-is-invoked-after-can.patch b/dma-helpers-ensure-AIO-callback-is-invoked-after-can.patch deleted file mode 100644 index db01a655e5932faa16b48d136b56a5d3690826d9..0000000000000000000000000000000000000000 --- a/dma-helpers-ensure-AIO-callback-is-invoked-after-can.patch +++ /dev/null @@ -1,80 +0,0 @@ -From 53c641048e0a8da1d2bed76cbd17f259a35e39a0 Mon Sep 17 00:00:00 2001 -From: Paolo Bonzini -Date: Mon, 29 Jul 2019 23:34:16 +0200 -Subject: [PATCH] dma-helpers: ensure AIO callback is invoked after - cancellation - -dma_aio_cancel unschedules the BH if there is one, which corresponds -to the reschedule_dma case of dma_blk_cb. This can stall the DMA -permanently, because dma_complete will never get invoked and therefore -nobody will ever invoke the original AIO callback in dbs->common.cb. - -Fix this by invoking the callback (which is ensured to happen after -a bdrv_aio_cancel_async, or done manually in the dbs->bh case), and -add assertions to check that the DMA state machine is indeed waiting -for dma_complete or reschedule_dma, but never both. - -Reported-by: John Snow -Signed-off-by: Paolo Bonzini -Message-id: 20190729213416.1972-1-pbonzini@redhat.com -Signed-off-by: John Snow -(cherry picked from commit 539343c0a47e19d5dd64d846d64d084d9793681f) -Signed-off-by: Michael Roth ---- - dma-helpers.c | 13 +++++++++---- - 1 file changed, 9 insertions(+), 4 deletions(-) - -diff --git a/dma-helpers.c b/dma-helpers.c -index 2d7e02d35e..d3871dc61e 100644 ---- a/dma-helpers.c -+++ b/dma-helpers.c -@@ -90,6 +90,7 @@ static void reschedule_dma(void *opaque) - { - DMAAIOCB *dbs = (DMAAIOCB *)opaque; - -+ assert(!dbs->acb && dbs->bh); - qemu_bh_delete(dbs->bh); - dbs->bh = NULL; - dma_blk_cb(dbs, 0); -@@ -111,15 +112,12 @@ static void dma_complete(DMAAIOCB *dbs, int ret) - { - trace_dma_complete(dbs, ret, dbs->common.cb); - -+ assert(!dbs->acb && !dbs->bh); - dma_blk_unmap(dbs); - if (dbs->common.cb) { - dbs->common.cb(dbs->common.opaque, ret); - } - qemu_iovec_destroy(&dbs->iov); -- if (dbs->bh) { -- qemu_bh_delete(dbs->bh); -- dbs->bh = NULL; -- } - qemu_aio_unref(dbs); - } - -@@ -179,14 +177,21 @@ static void dma_aio_cancel(BlockAIOCB *acb) - - trace_dma_aio_cancel(dbs); - -+ assert(!(dbs->acb && dbs->bh)); - if (dbs->acb) { -+ /* This will invoke dma_blk_cb. */ - blk_aio_cancel_async(dbs->acb); -+ return; - } -+ - if (dbs->bh) { - cpu_unregister_map_client(dbs->bh); - qemu_bh_delete(dbs->bh); - dbs->bh = NULL; - } -+ if (dbs->common.cb) { -+ dbs->common.cb(dbs->common.opaque, -ECANCELED); -+ } - } - - static AioContext *dma_get_aio_context(BlockAIOCB *acb) --- -2.19.1 - diff --git a/dma-xlnx-zdma-Fix-descriptor-loading-MEM-wrt-endiann.patch b/dma-xlnx-zdma-Fix-descriptor-loading-MEM-wrt-endiann.patch new file mode 100644 index 0000000000000000000000000000000000000000..644170b177f21fca467222359b52f29192edfce0 --- /dev/null +++ b/dma-xlnx-zdma-Fix-descriptor-loading-MEM-wrt-endiann.patch @@ -0,0 +1,63 @@ +From dac717da679938d52be05c8232cd818e7902796c Mon Sep 17 00:00:00 2001 +From: "Edgar E. Iglesias" +Date: Sat, 4 Apr 2020 14:27:17 +0200 +Subject: [PATCH 094/709] dma/xlnx-zdma: Fix descriptor loading (MEM) wrt + endianness +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Fix descriptor loading from memory wrt host endianness. + +Reported-by: Peter Maydell +Signed-off-by: Edgar E. Iglesias +Reviewed-by: Francisco Iglesias +Reviewed-by: Philippe Mathieu-Daudé +Message-id: 20200404122718.25111-2-edgar.iglesias@gmail.com +Signed-off-by: Peter Maydell +--- + hw/dma/xlnx-zdma.c | 11 +++++++---- + 1 file changed, 7 insertions(+), 4 deletions(-) + +diff --git a/hw/dma/xlnx-zdma.c b/hw/dma/xlnx-zdma.c +index 1c45367f3c..5f4775f663 100644 +--- a/hw/dma/xlnx-zdma.c ++++ b/hw/dma/xlnx-zdma.c +@@ -299,19 +299,22 @@ static void zdma_put_regaddr64(XlnxZDMA *s, unsigned int basereg, uint64_t addr) + s->regs[basereg + 1] = addr >> 32; + } + +-static bool zdma_load_descriptor(XlnxZDMA *s, uint64_t addr, void *buf) ++static bool zdma_load_descriptor(XlnxZDMA *s, uint64_t addr, ++ XlnxZDMADescr *descr) + { + /* ZDMA descriptors must be aligned to their own size. */ + if (addr % sizeof(XlnxZDMADescr)) { + qemu_log_mask(LOG_GUEST_ERROR, + "zdma: unaligned descriptor at %" PRIx64, + addr); +- memset(buf, 0x0, sizeof(XlnxZDMADescr)); ++ memset(descr, 0x0, sizeof(XlnxZDMADescr)); + s->error = true; + return false; + } + +- address_space_read(s->dma_as, addr, s->attr, buf, sizeof(XlnxZDMADescr)); ++ descr->addr = address_space_ldq_le(s->dma_as, addr, s->attr, NULL); ++ descr->size = address_space_ldl_le(s->dma_as, addr + 8, s->attr, NULL); ++ descr->attr = address_space_ldl_le(s->dma_as, addr + 12, s->attr, NULL); + return true; + } + +@@ -344,7 +347,7 @@ static void zdma_update_descr_addr(XlnxZDMA *s, bool type, + } else { + addr = zdma_get_regaddr64(s, basereg); + addr += sizeof(s->dsc_dst); +- address_space_read(s->dma_as, addr, s->attr, (void *) &next, 8); ++ next = address_space_ldq_le(s->dma_as, addr, s->attr, NULL); + } + + zdma_put_regaddr64(s, basereg, next); +-- +2.23.0 + diff --git a/dma-xlnx-zdma-Fix-descriptor-loading-REG-wrt-endiann.patch b/dma-xlnx-zdma-Fix-descriptor-loading-REG-wrt-endiann.patch new file mode 100644 index 0000000000000000000000000000000000000000..e7352402754286f8d9feecb76720229096d96b00 --- /dev/null +++ b/dma-xlnx-zdma-Fix-descriptor-loading-REG-wrt-endiann.patch @@ -0,0 +1,59 @@ +From 1633ed1e2de68cc27a1be8ff2a63e09c37e592f5 Mon Sep 17 00:00:00 2001 +From: "Edgar E. Iglesias" +Date: Sat, 4 Apr 2020 14:27:18 +0200 +Subject: [PATCH 095/709] dma/xlnx-zdma: Fix descriptor loading (REG) wrt + endianness + +Fix descriptor loading from registers wrt host endianness. + +Reported-by: Peter Maydell +Signed-off-by: Edgar E. Iglesias +Reviewed-by: Francisco Iglesias +Message-id: 20200404122718.25111-3-edgar.iglesias@gmail.com +Signed-off-by: Peter Maydell +--- + hw/dma/xlnx-zdma.c | 14 ++++++++++---- + 1 file changed, 10 insertions(+), 4 deletions(-) + +diff --git a/hw/dma/xlnx-zdma.c b/hw/dma/xlnx-zdma.c +index 5f4775f663..4121a1b489 100644 +--- a/hw/dma/xlnx-zdma.c ++++ b/hw/dma/xlnx-zdma.c +@@ -299,6 +299,14 @@ static void zdma_put_regaddr64(XlnxZDMA *s, unsigned int basereg, uint64_t addr) + s->regs[basereg + 1] = addr >> 32; + } + ++static void zdma_load_descriptor_reg(XlnxZDMA *s, unsigned int reg, ++ XlnxZDMADescr *descr) ++{ ++ descr->addr = zdma_get_regaddr64(s, reg); ++ descr->size = s->regs[reg + 2]; ++ descr->attr = s->regs[reg + 3]; ++} ++ + static bool zdma_load_descriptor(XlnxZDMA *s, uint64_t addr, + XlnxZDMADescr *descr) + { +@@ -324,8 +332,7 @@ static void zdma_load_src_descriptor(XlnxZDMA *s) + unsigned int ptype = ARRAY_FIELD_EX32(s->regs, ZDMA_CH_CTRL0, POINT_TYPE); + + if (ptype == PT_REG) { +- memcpy(&s->dsc_src, &s->regs[R_ZDMA_CH_SRC_DSCR_WORD0], +- sizeof(s->dsc_src)); ++ zdma_load_descriptor_reg(s, R_ZDMA_CH_SRC_DSCR_WORD0, &s->dsc_src); + return; + } + +@@ -360,8 +367,7 @@ static void zdma_load_dst_descriptor(XlnxZDMA *s) + bool dst_type; + + if (ptype == PT_REG) { +- memcpy(&s->dsc_dst, &s->regs[R_ZDMA_CH_DST_DSCR_WORD0], +- sizeof(s->dsc_dst)); ++ zdma_load_descriptor_reg(s, R_ZDMA_CH_DST_DSCR_WORD0, &s->dsc_dst); + return; + } + +-- +2.23.0 + diff --git a/docs-APEI-GHES-generation-and-CPER-record-descriptio.patch b/docs-APEI-GHES-generation-and-CPER-record-descriptio.patch new file mode 100644 index 0000000000000000000000000000000000000000..2e4ed7c02e0351fffb9c45cb672166d76e2a89bf --- /dev/null +++ b/docs-APEI-GHES-generation-and-CPER-record-descriptio.patch @@ -0,0 +1,148 @@ +From 5fb004a2650dde16ac41b7ee801fc30961524821 Mon Sep 17 00:00:00 2001 +From: Dongjiu Geng +Date: Tue, 12 May 2020 11:06:02 +0800 +Subject: [PATCH 438/709] docs: APEI GHES generation and CPER record + description + +Add APEI/GHES detailed design document + +Signed-off-by: Dongjiu Geng +Signed-off-by: Xiang Zheng +Reviewed-by: Michael S. Tsirkin +Reviewed-by: Igor Mammedov +Message-id: 20200512030609.19593-4-gengdongjiu@huawei.com +Signed-off-by: Peter Maydell +--- + docs/specs/acpi_hest_ghes.rst | 110 ++++++++++++++++++++++++++++++++++ + docs/specs/index.rst | 1 + + 2 files changed, 111 insertions(+) + create mode 100644 docs/specs/acpi_hest_ghes.rst + +diff --git a/docs/specs/acpi_hest_ghes.rst b/docs/specs/acpi_hest_ghes.rst +new file mode 100644 +index 0000000000..68f1fbe0a4 +--- /dev/null ++++ b/docs/specs/acpi_hest_ghes.rst +@@ -0,0 +1,110 @@ ++APEI tables generating and CPER record ++====================================== ++ ++.. ++ Copyright (c) 2020 HUAWEI TECHNOLOGIES CO., LTD. ++ ++ This work is licensed under the terms of the GNU GPL, version 2 or later. ++ See the COPYING file in the top-level directory. ++ ++Design Details ++-------------- ++ ++:: ++ ++ etc/acpi/tables etc/hardware_errors ++ ==================== =============================== ++ + +--------------------------+ +----------------------------+ ++ | | HEST | +--------->| error_block_address1 |------+ ++ | +--------------------------+ | +----------------------------+ | ++ | | GHES1 | | +------->| error_block_address2 |------+-+ ++ | +--------------------------+ | | +----------------------------+ | | ++ | | ................. | | | | .............. | | | ++ | | error_status_address-----+-+ | -----------------------------+ | | ++ | | ................. | | +--->| error_block_addressN |------+-+---+ ++ | | read_ack_register--------+-+ | | +----------------------------+ | | | ++ | | read_ack_preserve | +-+---+--->| read_ack_register1 | | | | ++ | | read_ack_write | | | +----------------------------+ | | | ++ + +--------------------------+ | +-+--->| read_ack_register2 | | | | ++ | | GHES2 | | | | +----------------------------+ | | | ++ + +--------------------------+ | | | | ............. | | | | ++ | | ................. | | | | +----------------------------+ | | | ++ | | error_status_address-----+---+ | | +->| read_ack_registerN | | | | ++ | | ................. | | | | +----------------------------+ | | | ++ | | read_ack_register--------+-----+ | | |Generic Error Status Block 1|<-----+ | | ++ | | read_ack_preserve | | | |-+------------------------+-+ | | ++ | | read_ack_write | | | | | CPER | | | | ++ + +--------------------------| | | | | CPER | | | | ++ | | ............... | | | | | .... | | | | ++ + +--------------------------+ | | | | CPER | | | | ++ | | GHESN | | | |-+------------------------+-| | | ++ + +--------------------------+ | | |Generic Error Status Block 2|<-------+ | ++ | | ................. | | | |-+------------------------+-+ | ++ | | error_status_address-----+-------+ | | | CPER | | | ++ | | ................. | | | | CPER | | | ++ | | read_ack_register--------+---------+ | | .... | | | ++ | | read_ack_preserve | | | CPER | | | ++ | | read_ack_write | +-+------------------------+-+ | ++ + +--------------------------+ | .......... | | ++ |----------------------------+ | ++ |Generic Error Status Block N |<----------+ ++ |-+-------------------------+-+ ++ | | CPER | | ++ | | CPER | | ++ | | .... | | ++ | | CPER | | ++ +-+-------------------------+-+ ++ ++ ++(1) QEMU generates the ACPI HEST table. This table goes in the current ++ "etc/acpi/tables" fw_cfg blob. Each error source has different ++ notification types. ++ ++(2) A new fw_cfg blob called "etc/hardware_errors" is introduced. QEMU ++ also needs to populate this blob. The "etc/hardware_errors" fw_cfg blob ++ contains an address registers table and an Error Status Data Block table. ++ ++(3) The address registers table contains N Error Block Address entries ++ and N Read Ack Register entries. The size for each entry is 8-byte. ++ The Error Status Data Block table contains N Error Status Data Block ++ entries. The size for each entry is 4096(0x1000) bytes. The total size ++ for the "etc/hardware_errors" fw_cfg blob is (N * 8 * 2 + N * 4096) bytes. ++ N is the number of the kinds of hardware error sources. ++ ++(4) QEMU generates the ACPI linker/loader script for the firmware. The ++ firmware pre-allocates memory for "etc/acpi/tables", "etc/hardware_errors" ++ and copies blob contents there. ++ ++(5) QEMU generates N ADD_POINTER commands, which patch addresses in the ++ "error_status_address" fields of the HEST table with a pointer to the ++ corresponding "address registers" in the "etc/hardware_errors" blob. ++ ++(6) QEMU generates N ADD_POINTER commands, which patch addresses in the ++ "read_ack_register" fields of the HEST table with a pointer to the ++ corresponding "read_ack_register" within the "etc/hardware_errors" blob. ++ ++(7) QEMU generates N ADD_POINTER commands for the firmware, which patch ++ addresses in the "error_block_address" fields with a pointer to the ++ respective "Error Status Data Block" in the "etc/hardware_errors" blob. ++ ++(8) QEMU defines a third and write-only fw_cfg blob which is called ++ "etc/hardware_errors_addr". Through that blob, the firmware can send back ++ the guest-side allocation addresses to QEMU. The "etc/hardware_errors_addr" ++ blob contains a 8-byte entry. QEMU generates a single WRITE_POINTER command ++ for the firmware. The firmware will write back the start address of ++ "etc/hardware_errors" blob to the fw_cfg file "etc/hardware_errors_addr". ++ ++(9) When QEMU gets a SIGBUS from the kernel, QEMU writes CPER into corresponding ++ "Error Status Data Block", guest memory, and then injects platform specific ++ interrupt (in case of arm/virt machine it's Synchronous External Abort) as a ++ notification which is necessary for notifying the guest. ++ ++(10) This notification (in virtual hardware) will be handled by the guest ++ kernel, on receiving notification, guest APEI driver could read the CPER error ++ and take appropriate action. ++ ++(11) kvm_arch_on_sigbus_vcpu() uses source_id as index in "etc/hardware_errors" to ++ find out "Error Status Data Block" entry corresponding to error source. So supported ++ source_id values should be assigned here and not be changed afterwards to make sure ++ that guest will write error into expected "Error Status Data Block" even if guest was ++ migrated to a newer QEMU. +diff --git a/docs/specs/index.rst b/docs/specs/index.rst +index de46a8b5e7..426632a475 100644 +--- a/docs/specs/index.rst ++++ b/docs/specs/index.rst +@@ -14,3 +14,4 @@ Contents: + ppc-spapr-xive + acpi_hw_reduced_hotplug + tpm ++ acpi_hest_ghes +-- +2.23.0 + diff --git a/docs-Sort-sections-on-qemu-img-subcommand-parameters.patch b/docs-Sort-sections-on-qemu-img-subcommand-parameters.patch new file mode 100644 index 0000000000000000000000000000000000000000..a0ae2a01ece0d3ae09fb96093caad14c29dfd9fd --- /dev/null +++ b/docs-Sort-sections-on-qemu-img-subcommand-parameters.patch @@ -0,0 +1,86 @@ +From 6edb788f292a83ad5f77b25bf90ed0eb14800639 Mon Sep 17 00:00:00 2001 +From: Eric Blake +Date: Tue, 12 May 2020 20:16:40 -0500 +Subject: [PATCH 587/709] docs: Sort sections on qemu-img subcommand parameters + +We already list the subcommand summaries alphabetically, we should do +the same for the documentation related to subcommand-specific +parameters. + +Signed-off-by: Eric Blake +Reviewed-by: Max Reitz +Message-Id: <20200513011648.166876-2-eblake@redhat.com> +Reviewed-by: Vladimir Sementsov-Ogievskiy +--- + docs/tools/qemu-img.rst | 48 ++++++++++++++++++++--------------------- + 1 file changed, 24 insertions(+), 24 deletions(-) + +diff --git a/docs/tools/qemu-img.rst b/docs/tools/qemu-img.rst +index f4ffe528ea..3b6223b5d6 100644 +--- a/docs/tools/qemu-img.rst ++++ b/docs/tools/qemu-img.rst +@@ -142,30 +142,6 @@ by the used format or see the format descriptions below for details. + the documentation of the emulator's ``-drive cache=...`` option for allowed + values. + +-Parameters to snapshot subcommand: +- +-.. program:: qemu-img-snapshot +- +-.. option:: snapshot +- +- Is the name of the snapshot to create, apply or delete +- +-.. option:: -a +- +- Applies a snapshot (revert disk to saved state) +- +-.. option:: -c +- +- Creates a snapshot +- +-.. option:: -d +- +- Deletes a snapshot +- +-.. option:: -l +- +- Lists all snapshots in the given image +- + Parameters to compare subcommand: + + .. program:: qemu-img-compare +@@ -245,6 +221,30 @@ Parameters to dd subcommand: + + Sets the number of input blocks to skip + ++Parameters to snapshot subcommand: ++ ++.. program:: qemu-img-snapshot ++ ++.. option:: snapshot ++ ++ Is the name of the snapshot to create, apply or delete ++ ++.. option:: -a ++ ++ Applies a snapshot (revert disk to saved state) ++ ++.. option:: -c ++ ++ Creates a snapshot ++ ++.. option:: -d ++ ++ Deletes a snapshot ++ ++.. option:: -l ++ ++ Lists all snapshots in the given image ++ + Command description: + + .. program:: qemu-img-commands +-- +2.23.0 + diff --git a/docs-clocks-add-device-s-clock-documentation.patch b/docs-clocks-add-device-s-clock-documentation.patch new file mode 100644 index 0000000000000000000000000000000000000000..6d618d9ec8780623d0bb24f92ada7dfdf4fc606d --- /dev/null +++ b/docs-clocks-add-device-s-clock-documentation.patch @@ -0,0 +1,432 @@ +From 31e5784a0d822269dc2674495f9f17e3ee0fb68f Mon Sep 17 00:00:00 2001 +From: Peter Maydell +Date: Fri, 17 Apr 2020 16:56:33 +0100 +Subject: [PATCH 106/709] docs/clocks: add device's clock documentation + +Add the documentation about the clock inputs and outputs in devices. + +This is based on the original work of Frederic Konrad. + +Signed-off-by: Damien Hedde +Reviewed-by: Alistair Francis +Reviewed-by: Edgar E. Iglesias +Message-id: 20200406135251.157596-6-damien.hedde@greensocs.com +[PMM: Editing pass for minor grammar, style and Sphinx + formatting fixes] +Reviewed-by: Peter Maydell +Signed-off-by: Peter Maydell +--- + docs/devel/clocks.rst | 391 ++++++++++++++++++++++++++++++++++++++++++ + docs/devel/index.rst | 1 + + 2 files changed, 392 insertions(+) + create mode 100644 docs/devel/clocks.rst + +diff --git a/docs/devel/clocks.rst b/docs/devel/clocks.rst +new file mode 100644 +index 0000000000..e5da28e211 +--- /dev/null ++++ b/docs/devel/clocks.rst +@@ -0,0 +1,391 @@ ++Modelling a clock tree in QEMU ++============================== ++ ++What are clocks? ++---------------- ++ ++Clocks are QOM objects developed for the purpose of modelling the ++distribution of clocks in QEMU. ++ ++They allow us to model the clock distribution of a platform and detect ++configuration errors in the clock tree such as badly configured PLL, clock ++source selection or disabled clock. ++ ++The object is *Clock* and its QOM name is ``clock`` (in C code, the macro ++``TYPE_CLOCK``). ++ ++Clocks are typically used with devices where they are used to model inputs ++and outputs. They are created in a similar way to GPIOs. Inputs and outputs ++of different devices can be connected together. ++ ++In these cases a Clock object is a child of a Device object, but this ++is not a requirement. Clocks can be independent of devices. For ++example it is possible to create a clock outside of any device to ++model the main clock source of a machine. ++ ++Here is an example of clocks:: ++ ++ +---------+ +----------------------+ +--------------+ ++ | Clock 1 | | Device B | | Device C | ++ | | | +-------+ +-------+ | | +-------+ | ++ | |>>-+-->>|Clock 2| |Clock 3|>>--->>|Clock 6| | ++ +---------+ | | | (in) | | (out) | | | | (in) | | ++ | | +-------+ +-------+ | | +-------+ | ++ | | +-------+ | +--------------+ ++ | | |Clock 4|>> ++ | | | (out) | | +--------------+ ++ | | +-------+ | | Device D | ++ | | +-------+ | | +-------+ | ++ | | |Clock 5|>>--->>|Clock 7| | ++ | | | (out) | | | | (in) | | ++ | | +-------+ | | +-------+ | ++ | +----------------------+ | | ++ | | +-------+ | ++ +----------------------------->>|Clock 8| | ++ | | (in) | | ++ | +-------+ | ++ +--------------+ ++ ++Clocks are defined in the ``include/hw/clock.h`` header and device ++related functions are defined in the ``include/hw/qdev-clock.h`` ++header. ++ ++The clock state ++--------------- ++ ++The state of a clock is its period; it is stored as an integer ++representing it in units of 2 :sup:`-32` ns. The special value of 0 is used to ++represent the clock being inactive or gated. The clocks do not model ++the signal itself (pin toggling) or other properties such as the duty ++cycle. ++ ++All clocks contain this state: outputs as well as inputs. This allows ++the current period of a clock to be fetched at any time. When a clock ++is updated, the value is immediately propagated to all connected ++clocks in the tree. ++ ++To ease interaction with clocks, helpers with a unit suffix are defined for ++every clock state setter or getter. The suffixes are: ++ ++- ``_ns`` for handling periods in nanoseconds ++- ``_hz`` for handling frequencies in hertz ++ ++The 0 period value is converted to 0 in hertz and vice versa. 0 always means ++that the clock is disabled. ++ ++Adding a new clock ++------------------ ++ ++Adding clocks to a device must be done during the init method of the Device ++instance. ++ ++To add an input clock to a device, the function ``qdev_init_clock_in()`` ++must be used. It takes the name, a callback and an opaque parameter ++for the callback (this will be explained in a following section). ++Output is simpler; only the name is required. Typically:: ++ ++ qdev_init_clock_in(DEVICE(dev), "clk_in", clk_in_callback, dev); ++ qdev_init_clock_out(DEVICE(dev), "clk_out"); ++ ++Both functions return the created Clock pointer, which should be saved in the ++device's state structure for further use. ++ ++These objects will be automatically deleted by the QOM reference mechanism. ++ ++Note that it is possible to create a static array describing clock inputs and ++outputs. The function ``qdev_init_clocks()`` must be called with the array as ++parameter to initialize the clocks: it has the same behaviour as calling the ++``qdev_init_clock_in/out()`` for each clock in the array. To ease the array ++construction, some macros are defined in ``include/hw/qdev-clock.h``. ++As an example, the following creates 2 clocks to a device: one input and one ++output. ++ ++.. code-block:: c ++ ++ /* device structure containing pointers to the clock objects */ ++ typedef struct MyDeviceState { ++ DeviceState parent_obj; ++ Clock *clk_in; ++ Clock *clk_out; ++ } MyDeviceState; ++ ++ /* ++ * callback for the input clock (see "Callback on input clock ++ * change" section below for more information). ++ */ ++ static void clk_in_callback(void *opaque); ++ ++ /* ++ * static array describing clocks: ++ * + a clock input named "clk_in", whose pointer is stored in ++ * the clk_in field of a MyDeviceState structure with callback ++ * clk_in_callback. ++ * + a clock output named "clk_out" whose pointer is stored in ++ * the clk_out field of a MyDeviceState structure. ++ */ ++ static const ClockPortInitArray mydev_clocks = { ++ QDEV_CLOCK_IN(MyDeviceState, clk_in, clk_in_callback), ++ QDEV_CLOCK_OUT(MyDeviceState, clk_out), ++ QDEV_CLOCK_END ++ }; ++ ++ /* device initialization function */ ++ static void mydev_init(Object *obj) ++ { ++ /* cast to MyDeviceState */ ++ MyDeviceState *mydev = MYDEVICE(obj); ++ /* create and fill the pointer fields in the MyDeviceState */ ++ qdev_init_clocks(mydev, mydev_clocks); ++ [...] ++ } ++ ++An alternative way to create a clock is to simply call ++``object_new(TYPE_CLOCK)``. In that case the clock will neither be an ++input nor an output of a device. After the whole QOM hierarchy of the ++clock has been set ``clock_setup_canonical_path()`` should be called. ++ ++At creation, the period of the clock is 0: the clock is disabled. You can ++change it using ``clock_set_ns()`` or ``clock_set_hz()``. ++ ++Note that if you are creating a clock with a fixed period which will never ++change (for example the main clock source of a board), then you'll have ++nothing else to do. This value will be propagated to other clocks when ++connecting the clocks together and devices will fetch the right value during ++the first reset. ++ ++Retrieving clocks from a device ++------------------------------- ++ ++``qdev_get_clock_in()`` and ``dev_get_clock_out()`` are available to ++get the clock inputs or outputs of a device. For example: ++ ++.. code-block:: c ++ ++ Clock *clk = qdev_get_clock_in(DEVICE(mydev), "clk_in"); ++ ++or: ++ ++.. code-block:: c ++ ++ Clock *clk = qdev_get_clock_out(DEVICE(mydev), "clk_out"); ++ ++Connecting two clocks together ++------------------------------ ++ ++To connect two clocks together, use the ``clock_set_source()`` function. ++Given two clocks ``clk1``, and ``clk2``, ``clock_set_source(clk2, clk1);`` ++configures ``clk2`` to follow the ``clk1`` period changes. Every time ``clk1`` ++is updated, ``clk2`` will be updated too. ++ ++When connecting clock between devices, prefer using the ++``qdev_connect_clock_in()`` function to set the source of an input ++device clock. For example, to connect the input clock ``clk2`` of ++``devB`` to the output clock ``clk1`` of ``devA``, do: ++ ++.. code-block:: c ++ ++ qdev_connect_clock_in(devB, "clk2", qdev_get_clock_out(devA, "clk1")) ++ ++We used ``qdev_get_clock_out()`` above, but any clock can drive an ++input clock, even another input clock. The following diagram shows ++some examples of connections. Note also that a clock can drive several ++other clocks. ++ ++:: ++ ++ +------------+ +--------------------------------------------------+ ++ | Device A | | Device B | ++ | | | +---------------------+ | ++ | | | | Device C | | ++ | +-------+ | | +-------+ | +-------+ +-------+ | +-------+ | ++ | |Clock 1|>>-->>|Clock 2|>>+-->>|Clock 3| |Clock 5|>>>>|Clock 6|>> ++ | | (out) | | | | (in) | | | | (in) | | (out) | | | (out) | | ++ | +-------+ | | +-------+ | | +-------+ +-------+ | +-------+ | ++ +------------+ | | +---------------------+ | ++ | | | ++ | | +--------------+ | ++ | | | Device D | | ++ | | | +-------+ | | ++ | +-->>|Clock 4| | | ++ | | | (in) | | | ++ | | +-------+ | | ++ | +--------------+ | ++ +--------------------------------------------------+ ++ ++In the above example, when *Clock 1* is updated by *Device A*, three ++clocks get the new clock period value: *Clock 2*, *Clock 3* and *Clock 4*. ++ ++It is not possible to disconnect a clock or to change the clock connection ++after it is connected. ++ ++Unconnected input clocks ++------------------------ ++ ++A newly created input clock is disabled (period of 0). This means the ++clock will be considered as disabled until the period is updated. If ++the clock remains unconnected it will always keep its initial value ++of 0. If this is not the desired behaviour, ``clock_set()``, ++``clock_set_ns()`` or ``clock_set_hz()`` should be called on the Clock ++object during device instance init. For example: ++ ++.. code-block:: c ++ ++ clk = qdev_init_clock_in(DEVICE(dev), "clk-in", clk_in_callback, ++ dev); ++ /* set initial value to 10ns / 100MHz */ ++ clock_set_ns(clk, 10); ++ ++Fetching clock frequency/period ++------------------------------- ++ ++To get the current state of a clock, use the functions ``clock_get()``, ++``clock_get_ns()`` or ``clock_get_hz()``. ++ ++It is also possible to register a callback on clock frequency changes. ++Here is an example: ++ ++.. code-block:: c ++ ++ void clock_callback(void *opaque) { ++ MyDeviceState *s = (MyDeviceState *) opaque; ++ /* ++ * 'opaque' is the argument passed to qdev_init_clock_in(); ++ * usually this will be the device state pointer. ++ */ ++ ++ /* do something with the new period */ ++ fprintf(stdout, "device new period is %" PRIu64 "ns\n", ++ clock_get_ns(dev->my_clk_input)); ++ } ++ ++Changing a clock period ++----------------------- ++ ++A device can change its outputs using the ``clock_update()``, ++``clock_update_ns()`` or ``clock_update_hz()`` function. It will trigger ++updates on every connected input. ++ ++For example, let's say that we have an output clock *clkout* and we ++have a pointer to it in the device state because we did the following ++in init phase: ++ ++.. code-block:: c ++ ++ dev->clkout = qdev_init_clock_out(DEVICE(dev), "clkout"); ++ ++Then at any time (apart from the cases listed below), it is possible to ++change the clock value by doing: ++ ++.. code-block:: c ++ ++ clock_update_hz(dev->clkout, 1000 * 1000 * 1000); /* 1GHz */ ++ ++Because updating a clock may trigger any side effects through ++connected clocks and their callbacks, this operation must be done ++while holding the qemu io lock. ++ ++For the same reason, one can update clocks only when it is allowed to have ++side effects on other objects. In consequence, it is forbidden: ++ ++* during migration, ++* and in the enter phase of reset. ++ ++Note that calling ``clock_update[_ns|_hz]()`` is equivalent to calling ++``clock_set[_ns|_hz]()`` (with the same arguments) then ++``clock_propagate()`` on the clock. Thus, setting the clock value can ++be separated from triggering the side-effects. This is often required ++to factorize code to handle reset and migration in devices. ++ ++Aliasing clocks ++--------------- ++ ++Sometimes, one needs to forward, or inherit, a clock from another ++device. Typically, when doing device composition, a device might ++expose a sub-device's clock without interfering with it. The function ++``qdev_alias_clock()`` can be used to achieve this behaviour. Note ++that it is possible to expose the clock under a different name. ++``qdev_alias_clock()`` works for both input and output clocks. ++ ++For example, if device B is a child of device A, ++``device_a_instance_init()`` may do something like this: ++ ++.. code-block:: c ++ ++ void device_a_instance_init(Object *obj) ++ { ++ AState *A = DEVICE_A(obj); ++ BState *B; ++ /* create object B as child of A */ ++ [...] ++ qdev_alias_clock(B, "clk", A, "b_clk"); ++ /* ++ * Now A has a clock "b_clk" which is an alias to ++ * the clock "clk" of its child B. ++ */ ++ } ++ ++This function does not return any clock object. The new clock has the ++same direction (input or output) as the original one. This function ++only adds a link to the existing clock. In the above example, object B ++remains the only object allowed to use the clock and device A must not ++try to change the clock period or set a callback to the clock. This ++diagram describes the example with an input clock:: ++ ++ +--------------------------+ ++ | Device A | ++ | +--------------+ | ++ | | Device B | | ++ | | +-------+ | | ++ >>"b_clk">>>| "clk" | | | ++ | (in) | | (in) | | | ++ | | +-------+ | | ++ | +--------------+ | ++ +--------------------------+ ++ ++Migration ++--------- ++ ++Clock state is not migrated automatically. Every device must handle its ++clock migration. Alias clocks must not be migrated. ++ ++To ensure clock states are restored correctly during migration, there ++are two solutions. ++ ++Clock states can be migrated by adding an entry into the device ++vmstate description. You should use the ``VMSTATE_CLOCK`` macro for this. ++This is typically used to migrate an input clock state. For example: ++ ++.. code-block:: c ++ ++ MyDeviceState { ++ DeviceState parent_obj; ++ [...] /* some fields */ ++ Clock *clk; ++ }; ++ ++ VMStateDescription my_device_vmstate = { ++ .name = "my_device", ++ .fields = (VMStateField[]) { ++ [...], /* other migrated fields */ ++ VMSTATE_CLOCK(clk, MyDeviceState), ++ VMSTATE_END_OF_LIST() ++ } ++ }; ++ ++The second solution is to restore the clock state using information already ++at our disposal. This can be used to restore output clock states using the ++device state. The functions ``clock_set[_ns|_hz]()`` can be used during the ++``post_load()`` migration callback. ++ ++When adding clock support to an existing device, if you care about ++migration compatibility you will need to be careful, as simply adding ++a ``VMSTATE_CLOCK()`` line will break compatibility. Instead, you can ++put the ``VMSTATE_CLOCK()`` line into a vmstate subsection with a ++suitable ``needed`` function, and use ``clock_set()`` in a ++``pre_load()`` function to set the default value that will be used if ++the source virtual machine in the migration does not send the clock ++state. ++ ++Care should be taken not to use ``clock_update[_ns|_hz]()`` or ++``clock_propagate()`` during the whole migration procedure because it ++will trigger side effects to other devices in an unknown state. +diff --git a/docs/devel/index.rst b/docs/devel/index.rst +index a9e1200dff..bb8238c5d6 100644 +--- a/docs/devel/index.rst ++++ b/docs/devel/index.rst +@@ -27,3 +27,4 @@ Contents: + bitops + reset + s390-dasd-ipl ++ clocks +-- +2.23.0 + diff --git a/docs-devel-migration-start-a-debugging-section.patch b/docs-devel-migration-start-a-debugging-section.patch new file mode 100644 index 0000000000000000000000000000000000000000..64e220423bb910c5db552d225b2fe4e439d108f0 --- /dev/null +++ b/docs-devel-migration-start-a-debugging-section.patch @@ -0,0 +1,53 @@ +From 979da8b357903ee8a43017cbf640f43460d1e2f0 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= +Date: Mon, 30 Mar 2020 19:48:52 +0200 +Subject: [PATCH 320/709] docs/devel/migration: start a debugging section +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Explain how to use analyze-migration.py, this may help. + +Signed-off-by: Marc-André Lureau +Message-Id: <20200330174852.456148-1-marcandre.lureau@redhat.com> +Reviewed-by: Dr. David Alan Gilbert +Reviewed-by: Daniel P. Berrangé +Signed-off-by: Dr. David Alan Gilbert +--- + docs/devel/migration.rst | 20 ++++++++++++++++++++ + 1 file changed, 20 insertions(+) + +diff --git a/docs/devel/migration.rst b/docs/devel/migration.rst +index e88918f763..2eb08624fc 100644 +--- a/docs/devel/migration.rst ++++ b/docs/devel/migration.rst +@@ -50,6 +50,26 @@ All these migration protocols use the same infrastructure to + save/restore state devices. This infrastructure is shared with the + savevm/loadvm functionality. + ++Debugging ++========= ++ ++The migration stream can be analyzed thanks to `scripts/analyze_migration.py`. ++ ++Example usage: ++ ++.. code-block:: shell ++ ++ $ qemu-system-x86_64 ++ (qemu) migrate "exec:cat > mig" ++ $ ./scripts/analyze_migration.py -f mig ++ { ++ "ram (3)": { ++ "section sizes": { ++ "pc.ram": "0x0000000008000000", ++ ... ++ ++See also ``analyze_migration.py -h`` help for more options. ++ + Common infrastructure + ===================== + +-- +2.23.0 + diff --git a/docs-system-Add-Arm-to-the-Integrator-CP-document-ti.patch b/docs-system-Add-Arm-to-the-Integrator-CP-document-ti.patch new file mode 100644 index 0000000000000000000000000000000000000000..66e13dfbb21d8b3aa349653aff1bb4cabb29a008 --- /dev/null +++ b/docs-system-Add-Arm-to-the-Integrator-CP-document-ti.patch @@ -0,0 +1,37 @@ +From fc68b1c6755c467e256202a2eed7c145c7b4581e Mon Sep 17 00:00:00 2001 +From: Peter Maydell +Date: Thu, 7 May 2020 16:18:15 +0100 +Subject: [PATCH 607/709] docs/system: Add 'Arm' to the Integrator/CP document + title +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Add 'Arm' to the Integrator/CP document title, for consistency with +the titling of the other documentation of Arm devboard models +(versatile, realview). + +Signed-off-by: Peter Maydell +Reviewed-by: Philippe Mathieu-Daudé +Reviewed-by: Edgar E. Iglesias +Reviewed-by: Alex Bennée +Message-id: 20200507151819.28444-2-peter.maydell@linaro.org +--- + docs/system/arm/integratorcp.rst | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/docs/system/arm/integratorcp.rst b/docs/system/arm/integratorcp.rst +index e6f050f602..594438008e 100644 +--- a/docs/system/arm/integratorcp.rst ++++ b/docs/system/arm/integratorcp.rst +@@ -1,5 +1,5 @@ +-Integrator/CP (``integratorcp``) +-================================ ++Arm Integrator/CP (``integratorcp``) ++==================================== + + The Arm Integrator/CP board is emulated with the following devices: + +-- +2.23.0 + diff --git a/docs-system-Add-protvirt-docs.patch b/docs-system-Add-protvirt-docs.patch new file mode 100644 index 0000000000000000000000000000000000000000..9575af4c23fdfbf1d3a5db47aca026426aa3fd17 --- /dev/null +++ b/docs-system-Add-protvirt-docs.patch @@ -0,0 +1,102 @@ +From 42fc5eae91bb9ec08b816d33d43cc08f96d1b683 Mon Sep 17 00:00:00 2001 +From: Janosch Frank +Date: Thu, 19 Mar 2020 09:19:20 -0400 +Subject: [PATCH 048/709] docs: system: Add protvirt docs + +Let's add some documentation for the Protected VM functionality. + +Signed-off-by: Janosch Frank +Reviewed-by: Claudio Imbrenda +Reviewed-by: Cornelia Huck +Acked-by: David Hildenbrand +Acked-by: Christian Borntraeger +Message-Id: <20200319131921.2367-16-frankja@linux.ibm.com> +Signed-off-by: Cornelia Huck +--- + docs/system/s390x/protvirt.rst | 60 ++++++++++++++++++++++++++++++++++ + docs/system/target-s390x.rst | 5 +++ + 2 files changed, 65 insertions(+) + create mode 100644 docs/system/s390x/protvirt.rst + +diff --git a/docs/system/s390x/protvirt.rst b/docs/system/s390x/protvirt.rst +new file mode 100644 +index 0000000000..712974ad87 +--- /dev/null ++++ b/docs/system/s390x/protvirt.rst +@@ -0,0 +1,60 @@ ++Protected Virtualization on s390x ++================================= ++ ++The memory and most of the registers of Protected Virtual Machines ++(PVMs) are encrypted or inaccessible to the hypervisor, effectively ++prohibiting VM introspection when the VM is running. At rest, PVMs are ++encrypted and can only be decrypted by the firmware, represented by an ++entity called Ultravisor, of specific IBM Z machines. ++ ++ ++Prerequisites ++------------- ++ ++To run PVMs, a machine with the Protected Virtualization feature, as ++indicated by the Ultravisor Call facility (stfle bit 158), is ++required. The Ultravisor needs to be initialized at boot by setting ++`prot_virt=1` on the host's kernel command line. ++ ++Running PVMs requires using the KVM hypervisor. ++ ++If those requirements are met, the capability `KVM_CAP_S390_PROTECTED` ++will indicate that KVM can support PVMs on that LPAR. ++ ++ ++QEMU Settings ++------------- ++ ++To indicate to the VM that it can transition into protected mode, the ++`Unpack facility` (stfle bit 161 represented by the feature ++`unpack`/`S390_FEAT_UNPACK`) needs to be part of the cpu model of ++the VM. ++ ++All I/O devices need to use the IOMMU. ++Passthrough (vfio) devices are currently not supported. ++ ++Host huge page backings are not supported. However guests can use huge ++pages as indicated by its facilities. ++ ++ ++Boot Process ++------------ ++ ++A secure guest image can either be loaded from disk or supplied on the ++QEMU command line. Booting from disk is done by the unmodified ++s390-ccw BIOS. I.e., the bootmap is interpreted, multiple components ++are read into memory and control is transferred to one of the ++components (zipl stage3). Stage3 does some fixups and then transfers ++control to some program residing in guest memory, which is normally ++the OS kernel. The secure image has another component prepended ++(stage3a) that uses the new diag308 subcodes 8 and 10 to trigger the ++transition into secure mode. ++ ++Booting from the image supplied on the QEMU command line requires that ++the file passed via -kernel has the same memory layout as would result ++from the disk boot. This memory layout includes the encrypted ++components (kernel, initrd, cmdline), the stage3a loader and ++metadata. In case this boot method is used, the command line ++options -initrd and -cmdline are ineffective. The preparation of a PVM ++image is done via the `genprotimg` tool from the s390-tools ++collection. +diff --git a/docs/system/target-s390x.rst b/docs/system/target-s390x.rst +index 4c8b7cdd66..7d76ae97b4 100644 +--- a/docs/system/target-s390x.rst ++++ b/docs/system/target-s390x.rst +@@ -24,3 +24,8 @@ or vfio-ap is also available. + .. toctree:: + s390x/vfio-ap + ++Architectural features ++====================== ++ ++.. toctree:: ++ s390x/protvirt +-- +2.23.0 + diff --git a/docs-system-Document-Arm-Versatile-Express-boards.patch b/docs-system-Document-Arm-Versatile-Express-boards.patch new file mode 100644 index 0000000000000000000000000000000000000000..f5a25a195e0e10512577002e20ab1fed48e9777d --- /dev/null +++ b/docs-system-Document-Arm-Versatile-Express-boards.patch @@ -0,0 +1,116 @@ +From 5a1d424487992613582e8ed3d3070833f155cf75 Mon Sep 17 00:00:00 2001 +From: Peter Maydell +Date: Thu, 7 May 2020 16:18:17 +0100 +Subject: [PATCH 609/709] docs/system: Document Arm Versatile Express boards +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Provide a minimal documentation of the Versatile Express boards +(vexpress-a9, vexpress-a15). + +Signed-off-by: Peter Maydell +Reviewed-by: Philippe Mathieu-Daudé +Reviewed-by: Edgar E. Iglesias +Reviewed-by: Alex Bennée +Message-id: 20200507151819.28444-4-peter.maydell@linaro.org +--- + MAINTAINERS | 1 + + docs/system/arm/vexpress.rst | 60 ++++++++++++++++++++++++++++++++++++ + docs/system/target-arm.rst | 1 + + 3 files changed, 62 insertions(+) + create mode 100644 docs/system/arm/vexpress.rst + +diff --git a/MAINTAINERS b/MAINTAINERS +index 1e006c98fa..6a9280c1b0 100644 +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -828,6 +828,7 @@ M: Peter Maydell + L: qemu-arm@nongnu.org + S: Maintained + F: hw/arm/vexpress.c ++F: docs/system/arm/vexpress.rst + + Versatile PB + M: Peter Maydell +diff --git a/docs/system/arm/vexpress.rst b/docs/system/arm/vexpress.rst +new file mode 100644 +index 0000000000..7f1bcbef07 +--- /dev/null ++++ b/docs/system/arm/vexpress.rst +@@ -0,0 +1,60 @@ ++Arm Versatile Express boards (``vexpress-a9``, ``vexpress-a15``) ++================================================================ ++ ++QEMU models two variants of the Arm Versatile Express development ++board family: ++ ++- ``vexpress-a9`` models the combination of the Versatile Express ++ motherboard and the CoreTile Express A9x4 daughterboard ++- ``vexpress-a15`` models the combination of the Versatile Express ++ motherboard and the CoreTile Express A15x2 daughterboard ++ ++Note that as this hardware does not have PCI, IDE or SCSI, ++the only available storage option is emulated SD card. ++ ++Implemented devices: ++ ++- PL041 audio ++- PL181 SD controller ++- PL050 keyboard and mouse ++- PL011 UARTs ++- SP804 timers ++- I2C controller ++- PL031 RTC ++- PL111 LCD display controller ++- Flash memory ++- LAN9118 ethernet ++ ++Unimplemented devices: ++ ++- SP810 system control block ++- PCI-express ++- USB controller (Philips ISP1761) ++- Local DAP ROM ++- CoreSight interfaces ++- PL301 AXI interconnect ++- SCC ++- System counter ++- HDLCD controller (``vexpress-a15``) ++- SP805 watchdog ++- PL341 dynamic memory controller ++- DMA330 DMA controller ++- PL354 static memory controller ++- BP147 TrustZone Protection Controller ++- TrustZone Address Space Controller ++ ++Other differences between the hardware and the QEMU model: ++ ++- QEMU will default to creating one CPU unless you pass a different ++ ``-smp`` argument ++- QEMU allows the amount of RAM provided to be specified with the ++ ``-m`` argument ++- QEMU defaults to providing a CPU which does not provide either ++ TrustZone or the Virtualization Extensions: if you want these you ++ must enable them with ``-machine secure=on`` and ``-machine ++ virtualization=on`` ++- QEMU provides 4 virtio-mmio virtio transports; these start at ++ address ``0x10013000`` for ``vexpress-a9`` and at ``0x1c130000`` for ++ ``vexpress-a15``, and have IRQs from 40 upwards. If a dtb is ++ provided on the command line then QEMU will edit it to include ++ suitable entries describing these transports for the guest. +diff --git a/docs/system/target-arm.rst b/docs/system/target-arm.rst +index d459efb3d2..1c759aa1a0 100644 +--- a/docs/system/target-arm.rst ++++ b/docs/system/target-arm.rst +@@ -78,6 +78,7 @@ undocumented; you can get a complete list by running + arm/integratorcp + arm/realview + arm/versatile ++ arm/vexpress + arm/musicpal + arm/nseries + arm/orangepi +-- +2.23.0 + diff --git a/docs-system-Document-Musca-boards.patch b/docs-system-Document-Musca-boards.patch new file mode 100644 index 0000000000000000000000000000000000000000..92428206077c1b5b5df9fa5a7495f47fb5a78b74 --- /dev/null +++ b/docs-system-Document-Musca-boards.patch @@ -0,0 +1,86 @@ +From 9f8f640eae8a875fa302d64748985bf21dc7f907 Mon Sep 17 00:00:00 2001 +From: Peter Maydell +Date: Thu, 7 May 2020 16:18:19 +0100 +Subject: [PATCH 611/709] docs/system: Document Musca boards +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Provide a minimal documentation of the Musca boards. + +Signed-off-by: Peter Maydell +Reviewed-by: Philippe Mathieu-Daudé +Reviewed-by: Edgar E. Iglesias +Reviewed-by: Alex Bennée +Message-id: 20200507151819.28444-6-peter.maydell@linaro.org +--- + MAINTAINERS | 1 + + docs/system/arm/musca.rst | 31 +++++++++++++++++++++++++++++++ + docs/system/target-arm.rst | 1 + + 3 files changed, 33 insertions(+) + create mode 100644 docs/system/arm/musca.rst + +diff --git a/MAINTAINERS b/MAINTAINERS +index 520a7b74f2..023f48d3ea 100644 +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -708,6 +708,7 @@ M: Peter Maydell + L: qemu-arm@nongnu.org + S: Maintained + F: hw/arm/musca.c ++F: docs/system/arm/musca.rst + + Musicpal + M: Jan Kiszka +diff --git a/docs/system/arm/musca.rst b/docs/system/arm/musca.rst +new file mode 100644 +index 0000000000..81e3dc9219 +--- /dev/null ++++ b/docs/system/arm/musca.rst +@@ -0,0 +1,31 @@ ++Arm Musca boards (``musca-a``, ``musca-b1``) ++============================================ ++ ++The Arm Musca development boards are a reference implementation ++of a system using the SSE-200 Subsystem for Embedded. They are ++dual Cortex-M33 systems. ++ ++QEMU provides models of the A and B1 variants of this board. ++ ++Unimplemented devices: ++ ++- SPI ++- |I2C| ++- |I2S| ++- PWM ++- QSPI ++- Timer ++- SCC ++- GPIO ++- eFlash ++- MHU ++- PVT ++- SDIO ++- CryptoCell ++ ++Note that (like the real hardware) the Musca-A machine is ++asymmetric: CPU 0 does not have the FPU or DSP extensions, ++but CPU 1 does. Also like the real hardware, the memory maps ++for the A and B1 variants differ significantly, so guest ++software must be built for the right variant. ++ +diff --git a/docs/system/target-arm.rst b/docs/system/target-arm.rst +index f2d9366e9b..dce384cb0e 100644 +--- a/docs/system/target-arm.rst ++++ b/docs/system/target-arm.rst +@@ -77,6 +77,7 @@ undocumented; you can get a complete list by running + + arm/integratorcp + arm/mps2 ++ arm/musca + arm/realview + arm/versatile + arm/vexpress +-- +2.23.0 + diff --git a/docs-system-Document-the-various-MPS2-models.patch b/docs-system-Document-the-various-MPS2-models.patch new file mode 100644 index 0000000000000000000000000000000000000000..759f2222255bc8b6fca6734401b2e8a97b3c2695 --- /dev/null +++ b/docs-system-Document-the-various-MPS2-models.patch @@ -0,0 +1,84 @@ +From ba7912a55ae836019a97f0f192222616388fb154 Mon Sep 17 00:00:00 2001 +From: Peter Maydell +Date: Thu, 7 May 2020 16:18:18 +0100 +Subject: [PATCH 610/709] docs/system: Document the various MPS2 models +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Add basic documentation of the MPS2 board models. + +Signed-off-by: Peter Maydell +Reviewed-by: Philippe Mathieu-Daudé +Reviewed-by: Edgar E. Iglesias +Reviewed-by: Alex Bennée +Message-id: 20200507151819.28444-5-peter.maydell@linaro.org +--- + MAINTAINERS | 1 + + docs/system/arm/mps2.rst | 29 +++++++++++++++++++++++++++++ + docs/system/target-arm.rst | 1 + + 3 files changed, 31 insertions(+) + create mode 100644 docs/system/arm/mps2.rst + +diff --git a/MAINTAINERS b/MAINTAINERS +index 6a9280c1b0..520a7b74f2 100644 +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -701,6 +701,7 @@ F: hw/misc/armsse-cpuid.c + F: include/hw/misc/armsse-cpuid.h + F: hw/misc/armsse-mhu.c + F: include/hw/misc/armsse-mhu.h ++F: docs/system/arm/mps2.rst + + Musca + M: Peter Maydell +diff --git a/docs/system/arm/mps2.rst b/docs/system/arm/mps2.rst +new file mode 100644 +index 0000000000..3a98cb59b0 +--- /dev/null ++++ b/docs/system/arm/mps2.rst +@@ -0,0 +1,29 @@ ++Arm MPS2 boards (``mps2-an385``, ``mps2-an505``, ``mps2-an511``, ``mps2-an521``) ++================================================================================ ++ ++These board models all use Arm M-profile CPUs. ++ ++The Arm MPS2 and MPS2+ dev boards are FPGA based (the 2+ has a bigger ++FPGA but is otherwise the same as the 2). Since the CPU itself ++and most of the devices are in the FPGA, the details of the board ++as seen by the guest depend significantly on the FPGA image. ++ ++QEMU models the following FPGA images: ++ ++``mps2-an385`` ++ Cortex-M3 as documented in ARM Application Note AN385 ++``mps2-an511`` ++ Cortex-M3 'DesignStart' as documented in AN511 ++``mps2-an505`` ++ Cortex-M33 as documented in ARM Application Note AN505 ++``mps2-an521`` ++ Dual Cortex-M33 as documented in Application Note AN521 ++ ++Differences between QEMU and real hardware: ++ ++- AN385 remapping of low 16K of memory to either ZBT SSRAM1 or to ++ block RAM is unimplemented (QEMU always maps this to ZBT SSRAM1, as ++ if zbt_boot_ctrl is always zero) ++- QEMU provides a LAN9118 ethernet rather than LAN9220; the only guest ++ visible difference is that the LAN9118 doesn't support checksum ++ offloading +diff --git a/docs/system/target-arm.rst b/docs/system/target-arm.rst +index 1c759aa1a0..f2d9366e9b 100644 +--- a/docs/system/target-arm.rst ++++ b/docs/system/target-arm.rst +@@ -76,6 +76,7 @@ undocumented; you can get a complete list by running + :maxdepth: 1 + + arm/integratorcp ++ arm/mps2 + arm/realview + arm/versatile + arm/vexpress +-- +2.23.0 + diff --git a/docs-system-Sort-Arm-board-index-into-alphabetical-o.patch b/docs-system-Sort-Arm-board-index-into-alphabetical-o.patch new file mode 100644 index 0000000000000000000000000000000000000000..b92f78899f90308baa9cc5d4349a370278d4e5d8 --- /dev/null +++ b/docs-system-Sort-Arm-board-index-into-alphabetical-o.patch @@ -0,0 +1,60 @@ +From b6e50ad0dbda699a2511861d84e313c756baded8 Mon Sep 17 00:00:00 2001 +From: Peter Maydell +Date: Thu, 7 May 2020 16:18:16 +0100 +Subject: [PATCH 608/709] docs/system: Sort Arm board index into alphabetical + order +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Sort the board index into alphabetical order. (Note that we need to +sort alphabetically by the title text of each file, which isn't the +same ordering as sorting by the filename.) + +Signed-off-by: Peter Maydell +Reviewed-by: Philippe Mathieu-Daudé +Reviewed-by: Edgar E. Iglesias +Reviewed-by: Alex Bennée +Message-id: 20200507151819.28444-3-peter.maydell@linaro.org +--- + docs/system/target-arm.rst | 17 +++++++++++------ + 1 file changed, 11 insertions(+), 6 deletions(-) + +diff --git a/docs/system/target-arm.rst b/docs/system/target-arm.rst +index 324e2af1cb..d459efb3d2 100644 +--- a/docs/system/target-arm.rst ++++ b/docs/system/target-arm.rst +@@ -67,19 +67,24 @@ Unfortunately many of the Arm boards QEMU supports are currently + undocumented; you can get a complete list by running + ``qemu-system-aarch64 --machine help``. + ++.. ++ 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 + + arm/integratorcp +- arm/versatile + arm/realview +- arm/xscale +- arm/palm +- arm/nseries +- arm/stellaris ++ arm/versatile + arm/musicpal +- arm/sx1 ++ arm/nseries + arm/orangepi ++ arm/palm ++ arm/xscale ++ arm/sx1 ++ arm/stellaris + + Arm CPU features + ================ +-- +2.23.0 + diff --git a/e1000-Don-t-run-e1000_instance_init-twice.patch b/e1000-Don-t-run-e1000_instance_init-twice.patch new file mode 100644 index 0000000000000000000000000000000000000000..c6a51e051cf1a25ceb0bd5031bb78aa5e2456b55 --- /dev/null +++ b/e1000-Don-t-run-e1000_instance_init-twice.patch @@ -0,0 +1,39 @@ +From a13f20422dc657719c3fa335788300c7ccf464ee Mon Sep 17 00:00:00 2001 +From: Markus Armbruster +Date: Tue, 5 May 2020 17:29:19 +0200 +Subject: [PATCH 473/709] e1000: Don't run e1000_instance_init() twice + +QOM object initialization runs .instance_init() for the type and all +its supertypes; see object_init_with_type(). + +Both TYPE_E1000_BASE and its concrete subtypes set .instance_init() to +e1000_instance_init(). For the concrete subtypes, it duly gets run +twice. The second run fails, but the error gets ignored (a later +commit will change that). + +Remove it from the subtypes. + +Cc: Jason Wang +Signed-off-by: Markus Armbruster +Acked-by: Jason Wang +Reviewed-by: Paolo Bonzini +Message-Id: <20200505152926.18877-12-armbru@redhat.com> +--- + hw/net/e1000.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/hw/net/e1000.c b/hw/net/e1000.c +index 2a69eee63f..0d2c2759e3 100644 +--- a/hw/net/e1000.c ++++ b/hw/net/e1000.c +@@ -1824,7 +1824,6 @@ static void e1000_register_types(void) + type_info.parent = TYPE_E1000_BASE; + type_info.class_data = (void *)info; + type_info.class_init = e1000_class_init; +- type_info.instance_init = e1000_instance_init; + + type_register(&type_info); + } +-- +2.23.0 + diff --git a/ehci-fix-queue-dev-null-ptr-dereference.patch b/ehci-fix-queue-dev-null-ptr-dereference.patch deleted file mode 100644 index 18114e984199f44d7689e939152ed160d6dc0292..0000000000000000000000000000000000000000 --- a/ehci-fix-queue-dev-null-ptr-dereference.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 901ac0dee4b17890db815d143a8efeeac5d105f7 Mon Sep 17 00:00:00 2001 -From: Gerd Hoffmann -Date: Wed, 21 Aug 2019 10:53:19 +0200 -Subject: [PATCH 1/5] ehci: fix queue->dev null ptr dereference - -In case we don't have a device for an active queue, just skip -processing the queue (same we do for inactive queues) and log -a guest bug. - -Reported-by: Guenter Roeck -Signed-off-by: Gerd Hoffmann -Tested-by: Guenter Roeck -Message-id: 20190821085319.13711-1-kraxel@redhat.com -(cherry-picked from commit 1be344b7ad25d572dadeee46d80f0103354352b2) ---- - hw/usb/hcd-ehci.c | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c -index 62dab05..5f089f3 100644 ---- a/hw/usb/hcd-ehci.c -+++ b/hw/usb/hcd-ehci.c -@@ -1834,6 +1834,9 @@ static int ehci_state_fetchqtd(EHCIQueue *q) - ehci_set_state(q->ehci, q->async, EST_EXECUTING); - break; - } -+ } else if (q->dev == NULL) { -+ ehci_trace_guest_bug(q->ehci, "no device attached to queue"); -+ ehci_set_state(q->ehci, q->async, EST_HORIZONTALQH); - } else { - p = ehci_alloc_packet(q); - p->qtdaddr = q->qtdaddr; --- -1.8.3.1 - diff --git a/elf_ops-Don-t-try-to-g_mapped_file_unref-NULL.patch b/elf_ops-Don-t-try-to-g_mapped_file_unref-NULL.patch new file mode 100644 index 0000000000000000000000000000000000000000..55e4e0c8c96d5630a023722495790d6c4e90a7ab --- /dev/null +++ b/elf_ops-Don-t-try-to-g_mapped_file_unref-NULL.patch @@ -0,0 +1,57 @@ +From a1ecb4381829d7eb302bc2d9cb69842c2585601d Mon Sep 17 00:00:00 2001 +From: Peter Maydell +Date: Thu, 23 Apr 2020 21:20:11 +0100 +Subject: [PATCH 191/709] elf_ops: Don't try to g_mapped_file_unref(NULL) +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Calling g_mapped_file_unref() on a NULL pointer is not valid, and +glib will assert if you try it. + +$ qemu-system-arm -M virt -display none -device loader,file=/tmp/bad.elf +qemu-system-arm: -device loader,file=/tmp/bad.elf: GLib: g_mapped_file_unref: assertion 'file != NULL' failed + +(One way to produce an ELF file that fails like this is to copy just +the first 16 bytes of a valid ELF file; this is sufficient to fool +the code in load_elf_ram_sym() into thinking it's an ELF file and +calling load_elf32() or load_elf64().) + +The failure-exit path in load_elf can be reached from various points +in execution, and for some of those we haven't yet called +g_mapped_file_new_from_fd(). Add a condition to the unref call so we +only call it if we successfully created the GMappedFile to start with. + +This will fix the assertion; for the specific case of the generic +loader it will then fall back from "guess this is an ELF file" to +"maybe it's a uImage or a hex file" and eventually to "just load as +a raw data file". + +Reported-by: Randy Yates +Signed-off-by: Peter Maydell +Reviewed-by: Philippe Mathieu-Daudé +Reviewed-by: Stefano Garzarella +Message-Id: <20200423202011.32686-1-peter.maydell@linaro.org> +Signed-off-by: Laurent Vivier +--- + include/hw/elf_ops.h | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/include/hw/elf_ops.h b/include/hw/elf_ops.h +index e0bb47bb67..398a4a2c85 100644 +--- a/include/hw/elf_ops.h ++++ b/include/hw/elf_ops.h +@@ -606,7 +606,9 @@ static int glue(load_elf, SZ)(const char *name, int fd, + *highaddr = (uint64_t)(elf_sword)high; + ret = total_size; + fail: +- g_mapped_file_unref(mapped_file); ++ if (mapped_file) { ++ g_mapped_file_unref(mapped_file); ++ } + g_free(phdr); + return ret; + } +-- +2.23.0 + diff --git a/es1370-check-total-frame-count-against-current-frame.patch b/es1370-check-total-frame-count-against-current-frame.patch new file mode 100644 index 0000000000000000000000000000000000000000..5bff6675b0b9ccfb4e4f1c19a28b0608006b6b86 --- /dev/null +++ b/es1370-check-total-frame-count-against-current-frame.patch @@ -0,0 +1,60 @@ +From 369ff955a8497988d079c4e3fa1e93c2570c1c69 Mon Sep 17 00:00:00 2001 +From: Prasad J Pandit +Date: Fri, 15 May 2020 01:36:08 +0530 +Subject: [PATCH 642/709] es1370: check total frame count against current frame + +A guest user may set channel frame count via es1370_write() +such that, in es1370_transfer_audio(), total frame count +'size' is lesser than the number of frames that are processed +'cnt'. + + int cnt = d->frame_cnt >> 16; + int size = d->frame_cnt & 0xffff; + +if (size < cnt), it results in incorrect calculations leading +to OOB access issue(s). Add check to avoid it. + +Reported-by: Ren Ding +Reported-by: Hanqing Zhao +Signed-off-by: Prasad J Pandit +Message-id: 20200514200608.1744203-1-ppandit@redhat.com +Signed-off-by: Gerd Hoffmann +--- + hw/audio/es1370.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/hw/audio/es1370.c b/hw/audio/es1370.c +index 89c4dabcd4..5f8a83ff56 100644 +--- a/hw/audio/es1370.c ++++ b/hw/audio/es1370.c +@@ -643,6 +643,9 @@ static void es1370_transfer_audio (ES1370State *s, struct chan *d, int loop_sel, + int csc_bytes = (csc + 1) << d->shift; + int cnt = d->frame_cnt >> 16; + int size = d->frame_cnt & 0xffff; ++ if (size < cnt) { ++ return; ++ } + int left = ((size - cnt + 1) << 2) + d->leftover; + int transferred = 0; + int temp = MIN (max, MIN (left, csc_bytes)); +@@ -651,7 +654,7 @@ static void es1370_transfer_audio (ES1370State *s, struct chan *d, int loop_sel, + addr += (cnt << 2) + d->leftover; + + if (index == ADC_CHANNEL) { +- while (temp) { ++ while (temp > 0) { + int acquired, to_copy; + + to_copy = MIN ((size_t) temp, sizeof (tmpbuf)); +@@ -669,7 +672,7 @@ static void es1370_transfer_audio (ES1370State *s, struct chan *d, int loop_sel, + else { + SWVoiceOut *voice = s->dac_voice[index]; + +- while (temp) { ++ while (temp > 0) { + int copied, to_copy; + + to_copy = MIN ((size_t) temp, sizeof (tmpbuf)); +-- +2.23.0 + diff --git a/exec-Add-block-comments-for-watchpoint-routines.patch b/exec-Add-block-comments-for-watchpoint-routines.patch new file mode 100644 index 0000000000000000000000000000000000000000..d00e5a7c62415a79434717d62a5379a0b05251bc --- /dev/null +++ b/exec-Add-block-comments-for-watchpoint-routines.patch @@ -0,0 +1,52 @@ +From 390734a42d003848efc6b73f6b7d8cd8aff8bdab Mon Sep 17 00:00:00 2001 +From: Richard Henderson +Date: Fri, 8 May 2020 08:43:41 -0700 +Subject: [PATCH 365/709] exec: Add block comments for watchpoint routines + +Reviewed-by: Peter Maydell +Signed-off-by: Richard Henderson +Message-id: 20200508154359.7494-2-richard.henderson@linaro.org +Signed-off-by: Peter Maydell +--- + include/hw/core/cpu.h | 23 +++++++++++++++++++++++ + 1 file changed, 23 insertions(+) + +diff --git a/include/hw/core/cpu.h b/include/hw/core/cpu.h +index 5bf94d28cf..07f7698155 100644 +--- a/include/hw/core/cpu.h ++++ b/include/hw/core/cpu.h +@@ -1100,8 +1100,31 @@ int cpu_watchpoint_remove(CPUState *cpu, vaddr addr, + vaddr len, int flags); + void cpu_watchpoint_remove_by_ref(CPUState *cpu, CPUWatchpoint *watchpoint); + void cpu_watchpoint_remove_all(CPUState *cpu, int mask); ++ ++/** ++ * cpu_check_watchpoint: ++ * @cpu: cpu context ++ * @addr: guest virtual address ++ * @len: access length ++ * @attrs: memory access attributes ++ * @flags: watchpoint access type ++ * @ra: unwind return address ++ * ++ * Check for a watchpoint hit in [addr, addr+len) of the type ++ * specified by @flags. Exit via exception with a hit. ++ */ + void cpu_check_watchpoint(CPUState *cpu, vaddr addr, vaddr len, + MemTxAttrs attrs, int flags, uintptr_t ra); ++ ++/** ++ * cpu_watchpoint_address_matches: ++ * @cpu: cpu context ++ * @addr: guest virtual address ++ * @len: access length ++ * ++ * Return the watchpoint flags that apply to [addr, addr+len). ++ * If no watchpoint is registered for the range, the result is 0. ++ */ + int cpu_watchpoint_address_matches(CPUState *cpu, vaddr addr, vaddr len); + #endif + +-- +2.23.0 + diff --git a/exec-Fix-cpu_watchpoint_address_matches-address-leng.patch b/exec-Fix-cpu_watchpoint_address_matches-address-leng.patch new file mode 100644 index 0000000000000000000000000000000000000000..49e159c80942953a75d389e216643c8f3bb521d5 --- /dev/null +++ b/exec-Fix-cpu_watchpoint_address_matches-address-leng.patch @@ -0,0 +1,37 @@ +From 9835936d4450dccd5e6fabd3c34330420036b028 Mon Sep 17 00:00:00 2001 +From: Richard Henderson +Date: Fri, 8 May 2020 08:43:42 -0700 +Subject: [PATCH 366/709] exec: Fix cpu_watchpoint_address_matches address + length +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The only caller of cpu_watchpoint_address_matches passes +TARGET_PAGE_SIZE, so the bug is not currently visible. + +Reviewed-by: Peter Maydell +Signed-off-by: Richard Henderson +Reviewed-by: Philippe Mathieu-Daudé +Message-id: 20200508154359.7494-3-richard.henderson@linaro.org +Signed-off-by: Peter Maydell +--- + exec.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/exec.c b/exec.c +index 2874bb5088..5162f0d12f 100644 +--- a/exec.c ++++ b/exec.c +@@ -1127,7 +1127,7 @@ int cpu_watchpoint_address_matches(CPUState *cpu, vaddr addr, vaddr len) + int ret = 0; + + QTAILQ_FOREACH(wp, &cpu->watchpoints, entry) { +- if (watchpoint_address_matches(wp, addr, TARGET_PAGE_SIZE)) { ++ if (watchpoint_address_matches(wp, addr, len)) { + ret |= wp->flags; + } + } +-- +2.23.0 + diff --git a/exec-cpu-all-Use-bool-for-have_guest_base.patch b/exec-cpu-all-Use-bool-for-have_guest_base.patch new file mode 100644 index 0000000000000000000000000000000000000000..2b5f022a79cdb1616d4778dec067e470c7c8a285 --- /dev/null +++ b/exec-cpu-all-Use-bool-for-have_guest_base.patch @@ -0,0 +1,79 @@ +From e307c192ff95c7c30d1c2fa02409686d450c1ccd Mon Sep 17 00:00:00 2001 +From: Richard Henderson +Date: Wed, 13 May 2020 18:51:29 +0100 +Subject: [PATCH 493/709] exec/cpu-all: Use bool for have_guest_base +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Richard Henderson +Signed-off-by: Alex Bennée +Reviewed-by: Philippe Mathieu-Daudé +Reviewed-by: Laurent Vivier +Message-Id: <20200513175134.19619-6-alex.bennee@linaro.org> +--- + bsd-user/main.c | 4 ++-- + include/exec/cpu-all.h | 2 +- + linux-user/main.c | 4 ++-- + 3 files changed, 5 insertions(+), 5 deletions(-) + +diff --git a/bsd-user/main.c b/bsd-user/main.c +index 28f122b80e..0bfe46cff9 100644 +--- a/bsd-user/main.c ++++ b/bsd-user/main.c +@@ -42,7 +42,7 @@ + int singlestep; + unsigned long mmap_min_addr; + unsigned long guest_base; +-int have_guest_base; ++bool have_guest_base; + unsigned long reserved_va; + + static const char *interp_prefix = CONFIG_QEMU_INTERP_PREFIX; +@@ -828,7 +828,7 @@ int main(int argc, char **argv) + } + } else if (!strcmp(r, "B")) { + guest_base = strtol(argv[optind++], NULL, 0); +- have_guest_base = 1; ++ have_guest_base = true; + } else if (!strcmp(r, "drop-ld-preload")) { + (void) envlist_unsetenv(envlist, "LD_PRELOAD"); + } else if (!strcmp(r, "bsd")) { +diff --git a/include/exec/cpu-all.h b/include/exec/cpu-all.h +index 43ddcf024c..0895a57881 100644 +--- a/include/exec/cpu-all.h ++++ b/include/exec/cpu-all.h +@@ -159,7 +159,7 @@ static inline void tswap64s(uint64_t *s) + * This allows the guest address space to be offset to a convenient location. + */ + extern unsigned long guest_base; +-extern int have_guest_base; ++extern bool have_guest_base; + extern unsigned long reserved_va; + + #if HOST_LONG_BITS <= TARGET_VIRT_ADDR_SPACE_BITS +diff --git a/linux-user/main.c b/linux-user/main.c +index e18c1fb952..3597e99bb1 100644 +--- a/linux-user/main.c ++++ b/linux-user/main.c +@@ -59,7 +59,7 @@ static const char *cpu_type; + static const char *seed_optarg; + unsigned long mmap_min_addr; + unsigned long guest_base; +-int have_guest_base; ++bool have_guest_base; + + /* + * Used to implement backwards-compatibility for the `-strace`, and +@@ -334,7 +334,7 @@ static void handle_arg_cpu(const char *arg) + static void handle_arg_guest_base(const char *arg) + { + guest_base = strtol(arg, NULL, 0); +- have_guest_base = 1; ++ have_guest_base = true; + } + + static void handle_arg_reserved_va(const char *arg) +-- +2.23.0 + diff --git a/fdc-Fix-fallback-auto-error-handling.patch b/fdc-Fix-fallback-auto-error-handling.patch new file mode 100644 index 0000000000000000000000000000000000000000..473a6b7ca19f8fcf04a50cf264bbb17e7bb8453e --- /dev/null +++ b/fdc-Fix-fallback-auto-error-handling.patch @@ -0,0 +1,43 @@ +From 07a978ef376cde544cca564ec225a8eb79ff2d54 Mon Sep 17 00:00:00 2001 +From: Markus Armbruster +Date: Wed, 22 Apr 2020 15:07:11 +0200 +Subject: [PATCH 019/709] fdc: Fix fallback=auto error handling +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +fdctrl_realize_common() rejects fallback=auto. Used by devices +"isa-fdc", "sysbus-fdc", "SUNW,fdtwo". The error handling is broken: + + $ qemu-system-x86_64 -nodefaults -device isa-fdc,fallback=auto,driveA=fd0 -drive if=none,id=fd0 + ** + ERROR:/work/armbru/qemu/hw/block/fdc.c:434:pick_drive_type: assertion failed: (drv->drive != FLOPPY_DRIVE_TYPE_AUTO) + Aborted (core dumped) + +Cause: fdctrl_realize_common() neglects to bail out after setting the +error. Fix that. + +Fixes: a73275dd6fc3bfda33165bebc28e0c33c20cb0a0 +Cc: John Snow +Signed-off-by: Markus Armbruster +Reviewed-by: Philippe Mathieu-Daudé +Message-Id: <20200422130719.28225-7-armbru@redhat.com> +--- + hw/block/fdc.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/hw/block/fdc.c b/hw/block/fdc.c +index 33bc9e2f92..9628cc171e 100644 +--- a/hw/block/fdc.c ++++ b/hw/block/fdc.c +@@ -2615,6 +2615,7 @@ static void fdctrl_realize_common(DeviceState *dev, FDCtrl *fdctrl, + + if (fdctrl->fallback == FLOPPY_DRIVE_TYPE_AUTO) { + error_setg(errp, "Cannot choose a fallback FDrive type of 'auto'"); ++ return; + } + + /* Fill 'command_to_handler' lookup table */ +-- +2.23.0 + diff --git a/file-posix-Support-BDRV_REQ_ZERO_WRITE-for-truncate.patch b/file-posix-Support-BDRV_REQ_ZERO_WRITE-for-truncate.patch new file mode 100644 index 0000000000000000000000000000000000000000..85c2691cc989331094974e9890cb435cc1b58399 --- /dev/null +++ b/file-posix-Support-BDRV_REQ_ZERO_WRITE-for-truncate.patch @@ -0,0 +1,36 @@ +From 2f0c6e7a650de133eccd94e9bb6cf7b2070f07f1 Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Fri, 24 Apr 2020 14:54:44 +0200 +Subject: [PATCH 131/709] file-posix: Support BDRV_REQ_ZERO_WRITE for truncate + +For regular files, we always get BDRV_REQ_ZERO_WRITE behaviour from the +OS, so we can advertise the flag and just ignore it. + +Signed-off-by: Kevin Wolf +Reviewed-by: Vladimir Sementsov-Ogievskiy +Reviewed-by: Alberto Garcia +Reviewed-by: Max Reitz +Message-Id: <20200424125448.63318-7-kwolf@redhat.com> +Signed-off-by: Kevin Wolf +--- + block/file-posix.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/block/file-posix.c b/block/file-posix.c +index 58326a0a60..bf09ad8bc0 100644 +--- a/block/file-posix.c ++++ b/block/file-posix.c +@@ -702,6 +702,10 @@ static int raw_open_common(BlockDriverState *bs, QDict *options, + #endif + + bs->supported_zero_flags = BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK; ++ if (S_ISREG(st.st_mode)) { ++ /* When extending regular files, we get zeros from the OS */ ++ bs->supported_truncate_flags = BDRV_REQ_ZERO_WRITE; ++ } + ret = 0; + fail: + if (filename && (bdrv_flags & BDRV_O_TEMPORARY)) { +-- +2.23.0 + diff --git a/file-win32-Support-BDRV_REQ_ZERO_WRITE-for-truncate.patch b/file-win32-Support-BDRV_REQ_ZERO_WRITE-for-truncate.patch new file mode 100644 index 0000000000000000000000000000000000000000..90debaeb4284a9202fe68c8fcc732c626e61d99a --- /dev/null +++ b/file-win32-Support-BDRV_REQ_ZERO_WRITE-for-truncate.patch @@ -0,0 +1,36 @@ +From 8e519795041e3293ab6b4e67f5416fa80dc0efc4 Mon Sep 17 00:00:00 2001 +From: Eric Blake +Date: Tue, 28 Apr 2020 15:28:58 -0500 +Subject: [PATCH 350/709] file-win32: Support BDRV_REQ_ZERO_WRITE for truncate + +When using bdrv_file, .bdrv_has_zero_init_truncate always returns 1; +therefore, we can behave just like file-posix, and always implement +BDRV_REQ_ZERO_WRITE by ignoring it since the OS gives it to us for +free (note that file-posix.c had to use an 'if' because it shared code +between regular files and block devices, but in file-win32.c, +bdrv_host_device uses a separate .bdrv_file_open). + +Signed-off-by: Eric Blake +Message-Id: <20200428202905.770727-3-eblake@redhat.com> +Signed-off-by: Kevin Wolf +--- + block/file-win32.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/block/file-win32.c b/block/file-win32.c +index a6b0dda5c3..fa569685d8 100644 +--- a/block/file-win32.c ++++ b/block/file-win32.c +@@ -408,6 +408,9 @@ static int raw_open(BlockDriverState *bs, QDict *options, int flags, + win32_aio_attach_aio_context(s->aio, bdrv_get_aio_context(bs)); + } + ++ /* When extending regular files, we get zeros from the OS */ ++ bs->supported_truncate_flags = BDRV_REQ_ZERO_WRITE; ++ + ret = 0; + fail: + qemu_opts_del(opts); +-- +2.23.0 + diff --git a/fuzz-Simplify-how-we-compute-available-machines-and-.patch b/fuzz-Simplify-how-we-compute-available-machines-and-.patch new file mode 100644 index 0000000000000000000000000000000000000000..578f52662b1c570db65b8027947aac4d02fb5719 --- /dev/null +++ b/fuzz-Simplify-how-we-compute-available-machines-and-.patch @@ -0,0 +1,269 @@ +From a56f3cdbdf328d95398c70432bba638a6b3f63fa Mon Sep 17 00:00:00 2001 +From: Markus Armbruster +Date: Fri, 24 Apr 2020 09:11:41 +0200 +Subject: [PATCH 033/709] fuzz: Simplify how we compute available machines and + types +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +apply_to_qlist(), apply_to_node() work with QObjects. This is +designed for use by tests/qtest/qos-test.c, which gets the data in +that form via QMP. Goes back to commit fc281c8020 "tests: qgraph API +for the qtest driver framework". + +Commit 275ab39d86 "fuzz: add support for qos-assisted fuzz targets" +added another user: qtest/fuzz/qos_fuzz.c. To get the data as +QObjects, it uses qmp_marshal_query_machines() and +qmp_marshal_qom_list_types(). + +All this code is rather cumbersome. Switch to working with generated +QAPI types instead: + +* Replace apply_to_qlist() & friends by machines_apply_to_node() and + types_apply_to_node(). + +* Have qos_fuzz.c use qmp_query_machines() and qmp_qom_list_types() + instead. + +* Have qos_test.c convert from QObject to the QAPI types. + +Signed-off-by: Markus Armbruster +Message-Id: <20200424071142.3525-3-armbru@redhat.com> +Reviewed-by: Philippe Mathieu-Daudé +Reviewed-by: Alexander Bulekov +--- + tests/qtest/fuzz/qos_fuzz.c | 34 +++++----------- + tests/qtest/libqos/qos_external.c | 66 +++++++++++-------------------- + tests/qtest/libqos/qos_external.h | 8 +++- + tests/qtest/qos-test.c | 29 +++++++++----- + 4 files changed, 57 insertions(+), 80 deletions(-) + +diff --git a/tests/qtest/fuzz/qos_fuzz.c b/tests/qtest/fuzz/qos_fuzz.c +index af28c92866..87eadb0889 100644 +--- a/tests/qtest/fuzz/qos_fuzz.c ++++ b/tests/qtest/fuzz/qos_fuzz.c +@@ -36,7 +36,6 @@ + + #include "qapi/qapi-commands-machine.h" + #include "qapi/qapi-commands-qom.h" +-#include "qapi/qmp/qlist.h" + + + void *fuzz_qos_obj; +@@ -45,34 +44,19 @@ QGuestAllocator *fuzz_qos_alloc; + static const char *fuzz_target_name; + static char **fuzz_path_vec; + +-/* +- * Replaced the qmp commands with direct qmp_marshal calls. +- * Probably there is a better way to do this +- */ + static void qos_set_machines_devices_available(void) + { +- QDict *req = qdict_new(); +- QObject *response; +- QDict *args = qdict_new(); +- QList *lst; +- +- qmp_marshal_query_machines(NULL, &response, &error_abort); +- lst = qobject_to(QList, response); +- apply_to_qlist(lst, true); +- +- qobject_unref(response); +- ++ MachineInfoList *mach_info; ++ ObjectTypeInfoList *type_info; + +- qdict_put_str(req, "execute", "qom-list-types"); +- qdict_put_str(args, "implements", "device"); +- qdict_put_bool(args, "abstract", true); +- qdict_put_obj(req, "arguments", (QObject *) args); ++ mach_info = qmp_query_machines(&error_abort); ++ machines_apply_to_node(mach_info); ++ qapi_free_MachineInfoList(mach_info); + +- qmp_marshal_qom_list_types(args, &response, &error_abort); +- lst = qobject_to(QList, response); +- apply_to_qlist(lst, false); +- qobject_unref(response); +- qobject_unref(req); ++ type_info = qmp_qom_list_types(true, "device", true, true, ++ &error_abort); ++ types_apply_to_node(type_info); ++ qapi_free_ObjectTypeInfoList(type_info); + } + + static char **current_path; +diff --git a/tests/qtest/libqos/qos_external.c b/tests/qtest/libqos/qos_external.c +index 398556dde0..c707dac3b9 100644 +--- a/tests/qtest/libqos/qos_external.c ++++ b/tests/qtest/libqos/qos_external.c +@@ -29,62 +29,40 @@ + #include "libqos/qgraph_internal.h" + #include "libqos/qos_external.h" + ++static void machine_apply_to_node(const char *name) ++{ ++ char *machine_name = g_strconcat(qtest_get_arch(), "/", name, NULL); + ++ qos_graph_node_set_availability(machine_name, true); ++ g_free(machine_name); ++} + +-void apply_to_node(const char *name, bool is_machine, bool is_abstract) ++void machines_apply_to_node(MachineInfoList *mach_info) + { +- char *machine_name = NULL; +- if (is_machine) { +- const char *arch = qtest_get_arch(); +- machine_name = g_strconcat(arch, "/", name, NULL); +- name = machine_name; ++ MachineInfoList *tail; ++ ++ for (tail = mach_info; tail; tail = tail->next) { ++ machine_apply_to_node(tail->value->name); ++ if (tail->value->alias) { ++ machine_apply_to_node(tail->value->alias); ++ } + } ++} ++ ++static void type_apply_to_node(const char *name, bool is_abstract) ++{ + qos_graph_node_set_availability(name, true); + if (is_abstract) { + qos_delete_cmd_line(name); + } +- g_free(machine_name); + } + +-/** +- * apply_to_qlist(): using QMP queries QEMU for a list of +- * machines and devices available, and sets the respective node +- * as true. If a node is found, also all its produced and contained +- * child are marked available. +- * +- * See qos_graph_node_set_availability() for more info +- */ +-void apply_to_qlist(QList *list, bool is_machine) ++void types_apply_to_node(ObjectTypeInfoList *type_info) + { +- const QListEntry *p; +- const char *name; +- bool abstract; +- QDict *minfo; +- QObject *qobj; +- QString *qstr; +- QBool *qbool; +- +- for (p = qlist_first(list); p; p = qlist_next(p)) { +- minfo = qobject_to(QDict, qlist_entry_obj(p)); +- qobj = qdict_get(minfo, "name"); +- qstr = qobject_to(QString, qobj); +- name = qstring_get_str(qstr); +- +- qobj = qdict_get(minfo, "abstract"); +- if (qobj) { +- qbool = qobject_to(QBool, qobj); +- abstract = qbool_get_bool(qbool); +- } else { +- abstract = false; +- } ++ ObjectTypeInfoList *tail; + +- apply_to_node(name, is_machine, abstract); +- qobj = qdict_get(minfo, "alias"); +- if (qobj) { +- qstr = qobject_to(QString, qobj); +- name = qstring_get_str(qstr); +- apply_to_node(name, is_machine, abstract); +- } ++ for (tail = type_info; tail; tail = tail->next) { ++ type_apply_to_node(tail->value->name, tail->value->abstract); + } + } + +diff --git a/tests/qtest/libqos/qos_external.h b/tests/qtest/libqos/qos_external.h +index 7b44930c55..f63388cb30 100644 +--- a/tests/qtest/libqos/qos_external.h ++++ b/tests/qtest/libqos/qos_external.h +@@ -20,8 +20,12 @@ + #define QOS_EXTERNAL_H + #include "libqos/qgraph.h" + +-void apply_to_node(const char *name, bool is_machine, bool is_abstract); +-void apply_to_qlist(QList *list, bool is_machine); ++#include "libqos/malloc.h" ++#include "qapi/qapi-types-machine.h" ++#include "qapi/qapi-types-qom.h" ++ ++void machines_apply_to_node(MachineInfoList *mach_info); ++void types_apply_to_node(ObjectTypeInfoList *type_info); + QGuestAllocator *get_machine_allocator(QOSGraphObject *obj); + void *allocate_objects(QTestState *qts, char **path, QGuestAllocator **p_alloc); + +diff --git a/tests/qtest/qos-test.c b/tests/qtest/qos-test.c +index ad193f43a5..3062a13557 100644 +--- a/tests/qtest/qos-test.c ++++ b/tests/qtest/qos-test.c +@@ -19,11 +19,12 @@ + #include "qemu/osdep.h" + #include + #include "libqtest-single.h" ++#include "qapi/error.h" + #include "qapi/qmp/qdict.h" +-#include "qapi/qmp/qbool.h" +-#include "qapi/qmp/qstring.h" + #include "qemu/module.h" +-#include "qapi/qmp/qlist.h" ++#include "qapi/qobject-input-visitor.h" ++#include "qapi/qapi-visit-machine.h" ++#include "qapi/qapi-visit-qom.h" + #include "libqos/malloc.h" + #include "libqos/qgraph.h" + #include "libqos/qgraph_internal.h" +@@ -51,13 +52,20 @@ static void qos_set_machines_devices_available(void) + { + QDict *response; + QDict *args = qdict_new(); +- QList *list; ++ QObject *ret; ++ Visitor *v; ++ MachineInfoList *mach_info; ++ ObjectTypeInfoList *type_info; + + qtest_start("-machine none"); + response = qmp("{ 'execute': 'query-machines' }"); +- list = qdict_get_qlist(response, "return"); ++ ret = qdict_get(response, "return"); + +- apply_to_qlist(list, true); ++ v = qobject_input_visitor_new(ret); ++ visit_type_MachineInfoList(v, NULL, &mach_info, &error_abort); ++ visit_free(v); ++ machines_apply_to_node(mach_info); ++ qapi_free_MachineInfoList(mach_info); + + qobject_unref(response); + +@@ -66,10 +74,13 @@ static void qos_set_machines_devices_available(void) + + response = qmp("{'execute': 'qom-list-types'," + " 'arguments': %p }", args); +- g_assert(qdict_haskey(response, "return")); +- list = qdict_get_qlist(response, "return"); ++ ret = qdict_get(response, "return"); + +- apply_to_qlist(list, false); ++ v = qobject_input_visitor_new(ret); ++ visit_type_ObjectTypeInfoList(v, NULL, &type_info, &error_abort); ++ visit_free(v); ++ types_apply_to_node(type_info); ++ qapi_free_ObjectTypeInfoList(type_info); + + qtest_end(); + qobject_unref(response); +-- +2.23.0 + diff --git a/fuzz-select-fuzz-target-using-executable-name.patch b/fuzz-select-fuzz-target-using-executable-name.patch new file mode 100644 index 0000000000000000000000000000000000000000..61aede69ab1742d3129cb6f72f1eccc4b1de429d --- /dev/null +++ b/fuzz-select-fuzz-target-using-executable-name.patch @@ -0,0 +1,68 @@ +From 05509c8e6def8a23878b93eda3163b7b405a5d57 Mon Sep 17 00:00:00 2001 +From: Alexander Bulekov +Date: Tue, 21 Apr 2020 14:22:30 -0400 +Subject: [PATCH 233/709] fuzz: select fuzz target using executable name + +The fuzzers are built into a binary (e.g. qemu-fuzz-i386). To select the +device to fuzz/fuzz target, we usually use the --fuzz-target= argument. +This commit allows the fuzz-target to be specified using the name of the +executable. If the executable name ends with -target-FUZZ_TARGET, then +we select the fuzz target based on this name, rather than the +--fuzz-target argument. This is useful for systems such as oss-fuzz +where we don't have control of the arguments passed to the fuzzer. + +[Fixed incorrect indentation. +--Stefan] + +Signed-off-by: Alexander Bulekov +Reviewed-by: Darren Kenny +Message-id: 20200421182230.6313-1-alxndr@bu.edu +Signed-off-by: Stefan Hajnoczi +--- + tests/qtest/fuzz/fuzz.c | 19 +++++++++++-------- + 1 file changed, 11 insertions(+), 8 deletions(-) + +diff --git a/tests/qtest/fuzz/fuzz.c b/tests/qtest/fuzz/fuzz.c +index 0d78ac8d36..f5c923852e 100644 +--- a/tests/qtest/fuzz/fuzz.c ++++ b/tests/qtest/fuzz/fuzz.c +@@ -91,6 +91,7 @@ static void usage(char *path) + printf(" * %s : %s\n", tmp->target->name, + tmp->target->description); + } ++ printf("Alternatively, add -target-FUZZ_TARGET to the executable name\n"); + exit(0); + } + +@@ -143,18 +144,20 @@ int LLVMFuzzerInitialize(int *argc, char ***argv, char ***envp) + module_call_init(MODULE_INIT_QOM); + module_call_init(MODULE_INIT_LIBQOS); + +- if (*argc <= 1) { ++ target_name = strstr(**argv, "-target-"); ++ if (target_name) { /* The binary name specifies the target */ ++ target_name += strlen("-target-"); ++ } else if (*argc > 1) { /* The target is specified as an argument */ ++ target_name = (*argv)[1]; ++ if (!strstr(target_name, "--fuzz-target=")) { ++ usage(**argv); ++ } ++ target_name += strlen("--fuzz-target="); ++ } else { + usage(**argv); + } + + /* Identify the fuzz target */ +- target_name = (*argv)[1]; +- if (!strstr(target_name, "--fuzz-target=")) { +- usage(**argv); +- } +- +- target_name += strlen("--fuzz-target="); +- + fuzz_target = fuzz_get_target(target_name); + if (!fuzz_target) { + usage(**argv); +-- +2.23.0 + diff --git a/gdbstub-Introduce-gdb_get_float64-to-get-64-bit-floa.patch b/gdbstub-Introduce-gdb_get_float64-to-get-64-bit-floa.patch new file mode 100644 index 0000000000000000000000000000000000000000..31d8d5522d5d953d7a2b527fd46ed1585bb24797 --- /dev/null +++ b/gdbstub-Introduce-gdb_get_float64-to-get-64-bit-floa.patch @@ -0,0 +1,102 @@ +From 38c1c09839c90317314be48f8758e9001ee40b91 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Thu, 30 Apr 2020 20:01:15 +0100 +Subject: [PATCH 272/709] gdbstub: Introduce gdb_get_float64() to get 64-bit + float registers +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +When converted to use GByteArray in commits 462474d760c and +a010bdbe719, the call to stfq_p() was removed. This call +serialize a float. +Since we now use a GByteArray, we can not use stfq_p() directly. +Introduce the gdb_get_float64() helper to load a float64 register. + +Fixes: 462474d760c ("target/m68k: use gdb_get_reg helpers") +Fixes: a010bdbe719 ("extend GByteArray to read register helpers") +Signed-off-by: Philippe Mathieu-Daudé +Signed-off-by: Alex Bennée +Message-Id: <20200414163853.12164-3-philmd@redhat.com> +Message-Id: <20200430190122.4592-3-alex.bennee@linaro.org> +--- + include/exec/gdbstub.h | 11 +++++++++++ + target/m68k/helper.c | 3 ++- + target/ppc/gdbstub.c | 4 ++-- + target/ppc/translate_init.inc.c | 2 +- + 4 files changed, 16 insertions(+), 4 deletions(-) + +diff --git a/include/exec/gdbstub.h b/include/exec/gdbstub.h +index 20e1072692..4a2b8e3089 100644 +--- a/include/exec/gdbstub.h ++++ b/include/exec/gdbstub.h +@@ -134,6 +134,17 @@ static inline int gdb_get_float32(GByteArray *array, float32 val) + + return sizeof(buf); + } ++ ++static inline int gdb_get_float64(GByteArray *array, float64 val) ++{ ++ uint8_t buf[sizeof(CPU_DoubleU)]; ++ ++ stfq_p(buf, val); ++ g_byte_array_append(array, buf, sizeof(buf)); ++ ++ return sizeof(buf); ++} ++ + static inline int gdb_get_zeroes(GByteArray *array, size_t len) + { + guint oldlen = array->len; +diff --git a/target/m68k/helper.c b/target/m68k/helper.c +index cad4083895..79b0b10ea9 100644 +--- a/target/m68k/helper.c ++++ b/target/m68k/helper.c +@@ -72,7 +72,8 @@ static int cf_fpu_gdb_get_reg(CPUM68KState *env, GByteArray *mem_buf, int n) + { + if (n < 8) { + float_status s; +- return gdb_get_reg64(mem_buf, floatx80_to_float64(env->fregs[n].d, &s)); ++ return gdb_get_float64(mem_buf, ++ floatx80_to_float64(env->fregs[n].d, &s)); + } + switch (n) { + case 8: /* fpcontrol */ +diff --git a/target/ppc/gdbstub.c b/target/ppc/gdbstub.c +index eb362dd9ae..5c11c88b2a 100644 +--- a/target/ppc/gdbstub.c ++++ b/target/ppc/gdbstub.c +@@ -130,7 +130,7 @@ int ppc_cpu_gdb_read_register(CPUState *cs, GByteArray *buf, int n) + gdb_get_regl(buf, env->gpr[n]); + } else if (n < 64) { + /* fprs */ +- gdb_get_reg64(buf, *cpu_fpr_ptr(env, n - 32)); ++ gdb_get_float64(buf, *cpu_fpr_ptr(env, n - 32)); + } else { + switch (n) { + case 64: +@@ -184,7 +184,7 @@ int ppc_cpu_gdb_read_register_apple(CPUState *cs, GByteArray *buf, int n) + gdb_get_reg64(buf, env->gpr[n]); + } else if (n < 64) { + /* fprs */ +- gdb_get_reg64(buf, *cpu_fpr_ptr(env, n - 32)); ++ gdb_get_float64(buf, *cpu_fpr_ptr(env, n - 32)); + } else if (n < 96) { + /* Altivec */ + gdb_get_reg64(buf, n - 64); +diff --git a/target/ppc/translate_init.inc.c b/target/ppc/translate_init.inc.c +index fd763e588e..2b6e832c4c 100644 +--- a/target/ppc/translate_init.inc.c ++++ b/target/ppc/translate_init.inc.c +@@ -9881,7 +9881,7 @@ static int gdb_get_float_reg(CPUPPCState *env, GByteArray *buf, int n) + { + uint8_t *mem_buf; + if (n < 32) { +- gdb_get_reg64(buf, *cpu_fpr_ptr(env, n)); ++ gdb_get_float64(buf, *cpu_fpr_ptr(env, n)); + mem_buf = gdb_get_reg_ptr(buf, 8); + ppc_maybe_bswap_register(env, mem_buf, 8); + return 8; +-- +2.23.0 + diff --git a/gdbstub-eliminate-gdbserver_fd-global.patch b/gdbstub-eliminate-gdbserver_fd-global.patch new file mode 100644 index 0000000000000000000000000000000000000000..b0682f24da27c2ca03e77e54f3170c642f7d31ea --- /dev/null +++ b/gdbstub-eliminate-gdbserver_fd-global.patch @@ -0,0 +1,110 @@ +From e0a1e2084779fec1adc72866212bda3549fc4c22 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Alex=20Benn=C3=A9e?= +Date: Thu, 30 Apr 2020 20:01:18 +0100 +Subject: [PATCH 275/709] gdbstub: eliminate gdbserver_fd global +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +We don't really need to track this fd beyond the initial creation of +the socket. We already know if the system has been initialised by +virtue of the gdbserver_state so lets remove it. This makes the later +re-factoring easier. + +Signed-off-by: Alex Bennée +Reviewed-by: Philippe Mathieu-Daudé +Reviewed-by: Richard Henderson +Message-Id: <20200430190122.4592-6-alex.bennee@linaro.org> +--- + gdbstub.c | 24 +++++++++++------------- + 1 file changed, 11 insertions(+), 13 deletions(-) + +diff --git a/gdbstub.c b/gdbstub.c +index 171e150950..b5381aa520 100644 +--- a/gdbstub.c ++++ b/gdbstub.c +@@ -398,8 +398,6 @@ static void reset_gdbserver_state(void) + bool gdb_has_xml; + + #ifdef CONFIG_USER_ONLY +-/* XXX: This is not thread safe. Do we care? */ +-static int gdbserver_fd = -1; + + static int get_char(void) + { +@@ -2964,7 +2962,7 @@ void gdb_exit(CPUArchState *env, int code) + return; + } + #ifdef CONFIG_USER_ONLY +- if (gdbserver_fd < 0 || gdbserver_state.fd < 0) { ++ if (gdbserver_state.fd < 0) { + return; + } + #endif +@@ -3011,7 +3009,7 @@ gdb_handlesig(CPUState *cpu, int sig) + char buf[256]; + int n; + +- if (gdbserver_fd < 0 || gdbserver_state.fd < 0) { ++ if (!gdbserver_state.init || gdbserver_state.fd < 0) { + return sig; + } + +@@ -3060,7 +3058,7 @@ void gdb_signalled(CPUArchState *env, int sig) + { + char buf[4]; + +- if (gdbserver_fd < 0 || gdbserver_state.fd < 0) { ++ if (!gdbserver_state.init || gdbserver_state.fd < 0) { + return; + } + +@@ -3068,7 +3066,7 @@ void gdb_signalled(CPUArchState *env, int sig) + put_packet(buf); + } + +-static bool gdb_accept(void) ++static bool gdb_accept(int gdb_fd) + { + struct sockaddr_in sockaddr; + socklen_t len; +@@ -3076,7 +3074,7 @@ static bool gdb_accept(void) + + for(;;) { + len = sizeof(sockaddr); +- fd = accept(gdbserver_fd, (struct sockaddr *)&sockaddr, &len); ++ fd = accept(gdb_fd, (struct sockaddr *)&sockaddr, &len); + if (fd < 0 && errno != EINTR) { + perror("accept"); + return false; +@@ -3137,13 +3135,13 @@ static int gdbserver_open(int port) + + int gdbserver_start(int port) + { +- gdbserver_fd = gdbserver_open(port); +- if (gdbserver_fd < 0) ++ int gdb_fd = gdbserver_open(port); ++ if (gdb_fd < 0) { + return -1; ++ } + /* accept connections */ +- if (!gdb_accept()) { +- close(gdbserver_fd); +- gdbserver_fd = -1; ++ if (!gdb_accept(gdb_fd)) { ++ close(gdb_fd); + return -1; + } + return 0; +@@ -3152,7 +3150,7 @@ int gdbserver_start(int port) + /* Disable gdb stub for child processes. */ + void gdbserver_fork(CPUState *cpu) + { +- if (gdbserver_fd < 0 || gdbserver_state.fd < 0) { ++ if (!gdbserver_state.init || gdbserver_state.fd < 0) { + return; + } + close(gdbserver_state.fd); +-- +2.23.0 + diff --git a/gdbstub-linux-user-support-debugging-over-a-unix-soc.patch b/gdbstub-linux-user-support-debugging-over-a-unix-soc.patch new file mode 100644 index 0000000000000000000000000000000000000000..4ad8cfdcfa243dcb94c67e9274d822782042eb84 --- /dev/null +++ b/gdbstub-linux-user-support-debugging-over-a-unix-soc.patch @@ -0,0 +1,278 @@ +From fcedd920867b8eb26ec803901a24db53a38882c5 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Alex=20Benn=C3=A9e?= +Date: Thu, 30 Apr 2020 20:01:19 +0100 +Subject: [PATCH 276/709] gdbstub/linux-user: support debugging over a unix + socket +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +While debugging over TCP is fairly straightforward now we have test +cases that want to orchestrate via make and currently a parallel build +fails as two processes can't use the same listening port. While system +emulation offers a wide cornucopia of connection methods thanks to the +chardev abstraction we are a little more limited for linux user. +Thankfully the programming API for a TCP socket and a local UNIX +socket is pretty much the same once it's set up. + +Signed-off-by: Alex Bennée +Reviewed-by: Richard Henderson +Message-Id: <20200430190122.4592-7-alex.bennee@linaro.org> +--- + bsd-user/main.c | 8 ++-- + gdbstub.c | 103 ++++++++++++++++++++++++++++++++++------- + include/exec/gdbstub.h | 14 ++++-- + linux-user/main.c | 12 ++--- + 4 files changed, 106 insertions(+), 31 deletions(-) + +diff --git a/bsd-user/main.c b/bsd-user/main.c +index 770c2b267a..28f122b80e 100644 +--- a/bsd-user/main.c ++++ b/bsd-user/main.c +@@ -738,7 +738,7 @@ int main(int argc, char **argv) + CPUState *cpu; + int optind; + const char *r; +- int gdbstub_port = 0; ++ const char *gdbstub = NULL; + char **target_environ, **wrk; + envlist_t *envlist = NULL; + char *trace_file = NULL; +@@ -814,7 +814,7 @@ int main(int argc, char **argv) + exit(1); + } + } else if (!strcmp(r, "g")) { +- gdbstub_port = atoi(argv[optind++]); ++ gdbstub = g_strdup(argv[optind++]); + } else if (!strcmp(r, "r")) { + qemu_uname_release = argv[optind++]; + } else if (!strcmp(r, "cpu")) { +@@ -1124,8 +1124,8 @@ int main(int argc, char **argv) + #error unsupported target CPU + #endif + +- if (gdbstub_port) { +- gdbserver_start (gdbstub_port); ++ if (gdbstub) { ++ gdbserver_start(gdbstub); + gdb_handlesig(cpu, 0); + } + cpu_loop(env); +diff --git a/gdbstub.c b/gdbstub.c +index b5381aa520..6950fd243f 100644 +--- a/gdbstub.c ++++ b/gdbstub.c +@@ -355,6 +355,7 @@ typedef struct GDBState { + int signal; + #ifdef CONFIG_USER_ONLY + int fd; ++ char *socket_path; + int running_state; + #else + CharBackend chr; +@@ -2962,6 +2963,9 @@ void gdb_exit(CPUArchState *env, int code) + return; + } + #ifdef CONFIG_USER_ONLY ++ if (gdbserver_state.socket_path) { ++ unlink(gdbserver_state.socket_path); ++ } + if (gdbserver_state.fd < 0) { + return; + } +@@ -3066,7 +3070,66 @@ void gdb_signalled(CPUArchState *env, int sig) + put_packet(buf); + } + +-static bool gdb_accept(int gdb_fd) ++static void gdb_accept_init(int fd) ++{ ++ init_gdbserver_state(); ++ create_default_process(&gdbserver_state); ++ gdbserver_state.processes[0].attached = true; ++ gdbserver_state.c_cpu = gdb_first_attached_cpu(); ++ gdbserver_state.g_cpu = gdbserver_state.c_cpu; ++ gdbserver_state.fd = fd; ++ gdb_has_xml = false; ++} ++ ++static bool gdb_accept_socket(int gdb_fd) ++{ ++ int fd; ++ ++ for(;;) { ++ fd = accept(gdb_fd, NULL, NULL); ++ if (fd < 0 && errno != EINTR) { ++ perror("accept socket"); ++ return false; ++ } else if (fd >= 0) { ++ qemu_set_cloexec(fd); ++ break; ++ } ++ } ++ ++ gdb_accept_init(fd); ++ return true; ++} ++ ++static int gdbserver_open_socket(const char *path) ++{ ++ struct sockaddr_un sockaddr; ++ int fd, ret; ++ ++ fd = socket(AF_UNIX, SOCK_STREAM, 0); ++ if (fd < 0) { ++ perror("create socket"); ++ return -1; ++ } ++ ++ sockaddr.sun_family = AF_UNIX; ++ pstrcpy(sockaddr.sun_path, sizeof(sockaddr.sun_path) - 1, path); ++ ret = bind(fd, (struct sockaddr *)&sockaddr, sizeof(sockaddr)); ++ if (ret < 0) { ++ perror("bind socket"); ++ close(fd); ++ return -1; ++ } ++ ret = listen(fd, 1); ++ if (ret < 0) { ++ perror("listen socket"); ++ close(fd); ++ return -1; ++ } ++ ++ return fd; ++} ++ ++static bool gdb_accept_tcp(int gdb_fd) + { + struct sockaddr_in sockaddr; + socklen_t len; +@@ -3091,17 +3154,11 @@ static bool gdb_accept(int gdb_fd) + return false; + } + +- init_gdbserver_state(); +- create_default_process(&gdbserver_state); +- gdbserver_state.processes[0].attached = true; +- gdbserver_state.c_cpu = gdb_first_attached_cpu(); +- gdbserver_state.g_cpu = gdbserver_state.c_cpu; +- gdbserver_state.fd = fd; +- gdb_has_xml = false; ++ gdb_accept_init(fd); + return true; + } + +-static int gdbserver_open(int port) ++static int gdbserver_open_port(int port) + { + struct sockaddr_in sockaddr; + int fd, ret; +@@ -3130,21 +3187,35 @@ static int gdbserver_open(int port) + close(fd); + return -1; + } ++ + return fd; + } + +-int gdbserver_start(int port) ++int gdbserver_start(const char *port_or_path) + { +- int gdb_fd = gdbserver_open(port); ++ int port = g_ascii_strtoull(port_or_path, NULL, 10); ++ int gdb_fd; ++ ++ if (port > 0) { ++ gdb_fd = gdbserver_open_port(port); ++ } else { ++ gdb_fd = gdbserver_open_socket(port_or_path); ++ } ++ + if (gdb_fd < 0) { + return -1; + } +- /* accept connections */ +- if (!gdb_accept(gdb_fd)) { +- close(gdb_fd); +- return -1; ++ ++ if (port > 0 && gdb_accept_tcp(gdb_fd)) { ++ return 0; ++ } else if (gdb_accept_socket(gdb_fd)) { ++ gdbserver_state.socket_path = g_strdup(port_or_path); ++ return 0; + } +- return 0; ++ ++ /* gone wrong */ ++ close(gdb_fd); ++ return -1; + } + + /* Disable gdb stub for child processes. */ +diff --git a/include/exec/gdbstub.h b/include/exec/gdbstub.h +index 4a2b8e3089..94d8f83e92 100644 +--- a/include/exec/gdbstub.h ++++ b/include/exec/gdbstub.h +@@ -177,11 +177,15 @@ static inline uint8_t * gdb_get_reg_ptr(GByteArray *buf, int len) + + #endif + +-#ifdef CONFIG_USER_ONLY +-int gdbserver_start(int); +-#else +-int gdbserver_start(const char *port); +-#endif ++/** ++ * gdbserver_start: start the gdb server ++ * @port_or_device: connection spec for gdb ++ * ++ * For CONFIG_USER this is either a tcp port or a path to a fifo. For ++ * system emulation you can use a full chardev spec for your gdbserver ++ * port. ++ */ ++int gdbserver_start(const char *port_or_device); + + void gdbserver_cleanup(void); + +diff --git a/linux-user/main.c b/linux-user/main.c +index 22578b1633..2cd443237d 100644 +--- a/linux-user/main.c ++++ b/linux-user/main.c +@@ -51,7 +51,7 @@ char *exec_path; + + int singlestep; + static const char *argv0; +-static int gdbstub_port; ++static const char *gdbstub; + static envlist_t *envlist; + static const char *cpu_model; + static const char *cpu_type; +@@ -310,7 +310,7 @@ static void handle_arg_seed(const char *arg) + + static void handle_arg_gdb(const char *arg) + { +- gdbstub_port = atoi(arg); ++ gdbstub = g_strdup(arg); + } + + static void handle_arg_uname(const char *arg) +@@ -861,10 +861,10 @@ int main(int argc, char **argv, char **envp) + + target_cpu_copy_regs(env, regs); + +- if (gdbstub_port) { +- if (gdbserver_start(gdbstub_port) < 0) { +- fprintf(stderr, "qemu: could not open gdbserver on port %d\n", +- gdbstub_port); ++ if (gdbstub) { ++ if (gdbserver_start(gdbstub) < 0) { ++ fprintf(stderr, "qemu: could not open gdbserver on %s\n", ++ gdbstub); + exit(EXIT_FAILURE); + } + gdb_handlesig(cpu, 0); +-- +2.23.0 + diff --git a/gluster-Drop-useless-has_zero_init-callback.patch b/gluster-Drop-useless-has_zero_init-callback.patch new file mode 100644 index 0000000000000000000000000000000000000000..aed4322a49892bcad1fc4051ac53013a7df58c72 --- /dev/null +++ b/gluster-Drop-useless-has_zero_init-callback.patch @@ -0,0 +1,73 @@ +From 5e09bcee5ba2c69f79d59513436fc92db49ec302 Mon Sep 17 00:00:00 2001 +From: Eric Blake +Date: Tue, 28 Apr 2020 15:28:57 -0500 +Subject: [PATCH 349/709] gluster: Drop useless has_zero_init callback + +block.c already defaults to 0 if we don't provide a callback; there's +no need to write a callback that always fails. + +Signed-off-by: Eric Blake +Reviewed-by: Vladimir Sementsov-Ogievskiy +Reviewed-by: Alberto Garcia +Message-Id: <20200428202905.770727-2-eblake@redhat.com> +Signed-off-by: Kevin Wolf +--- + block/gluster.c | 14 -------------- + 1 file changed, 14 deletions(-) + +diff --git a/block/gluster.c b/block/gluster.c +index d06df900f6..31233cac69 100644 +--- a/block/gluster.c ++++ b/block/gluster.c +@@ -1359,12 +1359,6 @@ static int64_t qemu_gluster_allocated_file_size(BlockDriverState *bs) + } + } + +-static int qemu_gluster_has_zero_init(BlockDriverState *bs) +-{ +- /* GlusterFS volume could be backed by a block device */ +- return 0; +-} +- + /* + * Find allocation range in @bs around offset @start. + * May change underlying file descriptor's file offset. +@@ -1569,8 +1563,6 @@ static BlockDriver bdrv_gluster = { + .bdrv_co_readv = qemu_gluster_co_readv, + .bdrv_co_writev = qemu_gluster_co_writev, + .bdrv_co_flush_to_disk = qemu_gluster_co_flush_to_disk, +- .bdrv_has_zero_init = qemu_gluster_has_zero_init, +- .bdrv_has_zero_init_truncate = qemu_gluster_has_zero_init, + #ifdef CONFIG_GLUSTERFS_DISCARD + .bdrv_co_pdiscard = qemu_gluster_co_pdiscard, + #endif +@@ -1601,8 +1593,6 @@ static BlockDriver bdrv_gluster_tcp = { + .bdrv_co_readv = qemu_gluster_co_readv, + .bdrv_co_writev = qemu_gluster_co_writev, + .bdrv_co_flush_to_disk = qemu_gluster_co_flush_to_disk, +- .bdrv_has_zero_init = qemu_gluster_has_zero_init, +- .bdrv_has_zero_init_truncate = qemu_gluster_has_zero_init, + #ifdef CONFIG_GLUSTERFS_DISCARD + .bdrv_co_pdiscard = qemu_gluster_co_pdiscard, + #endif +@@ -1633,8 +1623,6 @@ static BlockDriver bdrv_gluster_unix = { + .bdrv_co_readv = qemu_gluster_co_readv, + .bdrv_co_writev = qemu_gluster_co_writev, + .bdrv_co_flush_to_disk = qemu_gluster_co_flush_to_disk, +- .bdrv_has_zero_init = qemu_gluster_has_zero_init, +- .bdrv_has_zero_init_truncate = qemu_gluster_has_zero_init, + #ifdef CONFIG_GLUSTERFS_DISCARD + .bdrv_co_pdiscard = qemu_gluster_co_pdiscard, + #endif +@@ -1671,8 +1659,6 @@ static BlockDriver bdrv_gluster_rdma = { + .bdrv_co_readv = qemu_gluster_co_readv, + .bdrv_co_writev = qemu_gluster_co_writev, + .bdrv_co_flush_to_disk = qemu_gluster_co_flush_to_disk, +- .bdrv_has_zero_init = qemu_gluster_has_zero_init, +- .bdrv_has_zero_init_truncate = qemu_gluster_has_zero_init, + #ifdef CONFIG_GLUSTERFS_DISCARD + .bdrv_co_pdiscard = qemu_gluster_co_pdiscard, + #endif +-- +2.23.0 + diff --git a/hw-Move-i.MX-watchdog-driver-to-hw-watchdog.patch b/hw-Move-i.MX-watchdog-driver-to-hw-watchdog.patch new file mode 100644 index 0000000000000000000000000000000000000000..f8806e97dd456edca902b20491dac23a0b5949ba --- /dev/null +++ b/hw-Move-i.MX-watchdog-driver-to-hw-watchdog.patch @@ -0,0 +1,168 @@ +From 37f95959c730ff29f58c85b7a98f0b825933bee1 Mon Sep 17 00:00:00 2001 +From: Guenter Roeck +Date: Sun, 17 May 2020 09:21:28 -0700 +Subject: [PATCH 617/709] hw: Move i.MX watchdog driver to hw/watchdog +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +In preparation for a full implementation, move i.MX watchdog driver +from hw/misc to hw/watchdog. While at it, add the watchdog files +to MAINTAINERS. + +Reviewed-by: Philippe Mathieu-Daudé +Signed-off-by: Guenter Roeck +Message-id: 20200517162135.110364-2-linux@roeck-us.net +Signed-off-by: Peter Maydell +--- + MAINTAINERS | 2 ++ + hw/arm/Kconfig | 3 +++ + hw/misc/Makefile.objs | 1 - + hw/watchdog/Kconfig | 3 +++ + hw/watchdog/Makefile.objs | 1 + + hw/{misc/imx2_wdt.c => watchdog/wdt_imx2.c} | 2 +- + include/hw/arm/fsl-imx6.h | 2 +- + include/hw/arm/fsl-imx6ul.h | 2 +- + include/hw/arm/fsl-imx7.h | 2 +- + include/hw/{misc/imx2_wdt.h => watchdog/wdt_imx2.h} | 0 + 10 files changed, 13 insertions(+), 5 deletions(-) + rename hw/{misc/imx2_wdt.c => watchdog/wdt_imx2.c} (98%) + rename include/hw/{misc/imx2_wdt.h => watchdog/wdt_imx2.h} (100%) + +diff --git a/MAINTAINERS b/MAINTAINERS +index 023f48d3ea..3690f313c3 100644 +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -633,8 +633,10 @@ S: Odd Fixes + F: hw/arm/fsl-imx25.c + F: hw/arm/imx25_pdk.c + F: hw/misc/imx25_ccm.c ++F: hw/watchdog/wdt_imx2.c + F: include/hw/arm/fsl-imx25.h + F: include/hw/misc/imx25_ccm.h ++F: include/hw/watchdog/wdt_imx2.h + + i.MX31 (kzm) + M: Peter Chubb +diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig +index 5364172537..3d05dc8538 100644 +--- a/hw/arm/Kconfig ++++ b/hw/arm/Kconfig +@@ -375,6 +375,7 @@ config FSL_IMX6 + select IMX_FEC + select IMX_I2C + select IMX_USBPHY ++ select WDT_IMX2 + select SDHCI + + config ASPEED_SOC +@@ -412,6 +413,7 @@ config FSL_IMX7 + select IMX + select IMX_FEC + select IMX_I2C ++ select WDT_IMX2 + select PCI_EXPRESS_DESIGNWARE + select SDHCI + select UNIMP +@@ -425,6 +427,7 @@ config FSL_IMX6UL + select IMX + select IMX_FEC + select IMX_I2C ++ select WDT_IMX2 + select SDHCI + select UNIMP + +diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs +index 68aae2eabb..b25181b711 100644 +--- a/hw/misc/Makefile.objs ++++ b/hw/misc/Makefile.objs +@@ -44,7 +44,6 @@ common-obj-$(CONFIG_IMX) += imx6_ccm.o + common-obj-$(CONFIG_IMX) += imx6ul_ccm.o + obj-$(CONFIG_IMX) += imx6_src.o + common-obj-$(CONFIG_IMX) += imx7_ccm.o +-common-obj-$(CONFIG_IMX) += imx2_wdt.o + common-obj-$(CONFIG_IMX) += imx7_snvs.o + common-obj-$(CONFIG_IMX) += imx7_gpr.o + common-obj-$(CONFIG_IMX) += imx_rngc.o +diff --git a/hw/watchdog/Kconfig b/hw/watchdog/Kconfig +index 2118d897c9..293209b291 100644 +--- a/hw/watchdog/Kconfig ++++ b/hw/watchdog/Kconfig +@@ -14,3 +14,6 @@ config WDT_IB700 + + config WDT_DIAG288 + bool ++ ++config WDT_IMX2 ++ bool +diff --git a/hw/watchdog/Makefile.objs b/hw/watchdog/Makefile.objs +index 3f536d1cad..631b711d86 100644 +--- a/hw/watchdog/Makefile.objs ++++ b/hw/watchdog/Makefile.objs +@@ -4,3 +4,4 @@ common-obj-$(CONFIG_WDT_IB6300ESB) += wdt_i6300esb.o + common-obj-$(CONFIG_WDT_IB700) += wdt_ib700.o + common-obj-$(CONFIG_WDT_DIAG288) += wdt_diag288.o + common-obj-$(CONFIG_ASPEED_SOC) += wdt_aspeed.o ++common-obj-$(CONFIG_WDT_IMX2) += wdt_imx2.o +diff --git a/hw/misc/imx2_wdt.c b/hw/watchdog/wdt_imx2.c +similarity index 98% +rename from hw/misc/imx2_wdt.c +rename to hw/watchdog/wdt_imx2.c +index 2aedfe803a..ad1ef02e9e 100644 +--- a/hw/misc/imx2_wdt.c ++++ b/hw/watchdog/wdt_imx2.c +@@ -14,7 +14,7 @@ + #include "qemu/module.h" + #include "sysemu/watchdog.h" + +-#include "hw/misc/imx2_wdt.h" ++#include "hw/watchdog/wdt_imx2.h" + + #define IMX2_WDT_WCR_WDA BIT(5) /* -> External Reset WDOG_B */ + #define IMX2_WDT_WCR_SRS BIT(4) /* -> Software Reset Signal */ +diff --git a/include/hw/arm/fsl-imx6.h b/include/hw/arm/fsl-imx6.h +index 973bcb72f7..1ebd751324 100644 +--- a/include/hw/arm/fsl-imx6.h ++++ b/include/hw/arm/fsl-imx6.h +@@ -21,7 +21,7 @@ + #include "hw/cpu/a9mpcore.h" + #include "hw/misc/imx6_ccm.h" + #include "hw/misc/imx6_src.h" +-#include "hw/misc/imx2_wdt.h" ++#include "hw/watchdog/wdt_imx2.h" + #include "hw/char/imx_serial.h" + #include "hw/timer/imx_gpt.h" + #include "hw/timer/imx_epit.h" +diff --git a/include/hw/arm/fsl-imx6ul.h b/include/hw/arm/fsl-imx6ul.h +index 1a0bab8daa..37c89cc5f9 100644 +--- a/include/hw/arm/fsl-imx6ul.h ++++ b/include/hw/arm/fsl-imx6ul.h +@@ -24,7 +24,7 @@ + #include "hw/misc/imx7_snvs.h" + #include "hw/misc/imx7_gpr.h" + #include "hw/intc/imx_gpcv2.h" +-#include "hw/misc/imx2_wdt.h" ++#include "hw/watchdog/wdt_imx2.h" + #include "hw/gpio/imx_gpio.h" + #include "hw/char/imx_serial.h" + #include "hw/timer/imx_gpt.h" +diff --git a/include/hw/arm/fsl-imx7.h b/include/hw/arm/fsl-imx7.h +index 706aef2e7e..3a0041c4c2 100644 +--- a/include/hw/arm/fsl-imx7.h ++++ b/include/hw/arm/fsl-imx7.h +@@ -26,7 +26,7 @@ + #include "hw/misc/imx7_snvs.h" + #include "hw/misc/imx7_gpr.h" + #include "hw/misc/imx6_src.h" +-#include "hw/misc/imx2_wdt.h" ++#include "hw/watchdog/wdt_imx2.h" + #include "hw/gpio/imx_gpio.h" + #include "hw/char/imx_serial.h" + #include "hw/timer/imx_gpt.h" +diff --git a/include/hw/misc/imx2_wdt.h b/include/hw/watchdog/wdt_imx2.h +similarity index 100% +rename from include/hw/misc/imx2_wdt.h +rename to include/hw/watchdog/wdt_imx2.h +-- +2.23.0 + diff --git a/hw-Nuke-hw_compat_4_0_1-and-pc_compat_4_0_1.patch b/hw-Nuke-hw_compat_4_0_1-and-pc_compat_4_0_1.patch deleted file mode 100644 index 15d807769607a5964de8b2869fd53c55e5e16baf..0000000000000000000000000000000000000000 --- a/hw-Nuke-hw_compat_4_0_1-and-pc_compat_4_0_1.patch +++ /dev/null @@ -1,124 +0,0 @@ -From 56deb8f0db72858985ba077cb0f678f2dbc13bba Mon Sep 17 00:00:00 2001 -From: Greg Kurz -Date: Mon, 5 Aug 2019 15:56:58 +0800 -Subject: [PATCH] hw: Nuke hw_compat_4_0_1 and pc_compat_4_0_1 - -Commit c87759ce876a fixed a regression affecting pc-q35 machines by -introducing a new pc-q35-4.0.1 machine version to be used instead -of pc-q35-4.0. The only purpose was to revert the default behaviour -of not using split irqchip, but the change also introduced the usual -hw_compat and pc_compat bits, and wired them for pc-q35 only. - -This raises questions when it comes to add new compat properties for -4.0* machine versions of any architecture. Where to add them ? In -4.0, 4.0.1 or both ? Error prone. Another possibility would be to teach -all other architectures about 4.0.1. This solution isn't satisfying, -especially since this is a pc-q35 specific issue. - -It turns out that the split irqchip default is handled in the machine -option function and doesn't involve compat lists at all. - -Drop all the 4.0.1 compat lists and use the 4.0 ones instead in the 4.0.1 -machine option function. - -Move the compat props that were added to the 4.0.1 since c87759ce876a to -4.0. - -Even if only hw_compat_4_0_1 had an impact on other architectures, -drop pc_compat_4_0_1 as well for consistency. - -Fixes: c87759ce876a "q35: Revert to kernel irqchip" -Suggested-by: Dr. David Alan Gilbert -Signed-off-by: Greg Kurz -Reviewed-by: Dr. David Alan Gilbert -Reviewed-by: Michael S. Tsirkin -Message-Id: <156051774276.244890.8660277280145466396.stgit@bahia.lan> -Signed-off-by: Paolo Bonzini -(cherry-picked from commit 8e8cbed09ad9d577955691b4c061b61b602406d1) ---- - hw/core/machine.c | 3 --- - hw/i386/pc.c | 3 --- - hw/i386/pc_q35.c | 9 +++++++-- - include/hw/boards.h | 3 --- - include/hw/i386/pc.h | 3 --- - 5 files changed, 7 insertions(+), 14 deletions(-) - -diff --git a/hw/core/machine.c b/hw/core/machine.c -index e41e6698..5d046a43 100644 ---- a/hw/core/machine.c -+++ b/hw/core/machine.c -@@ -24,9 +24,6 @@ - #include "hw/pci/pci.h" - #include "hw/mem/nvdimm.h" - --GlobalProperty hw_compat_4_0_1[] = {}; --const size_t hw_compat_4_0_1_len = G_N_ELEMENTS(hw_compat_4_0_1); -- - GlobalProperty hw_compat_4_0[] = {}; - const size_t hw_compat_4_0_len = G_N_ELEMENTS(hw_compat_4_0); - -diff --git a/hw/i386/pc.c b/hw/i386/pc.c -index b5311e7e..d98b737b 100644 ---- a/hw/i386/pc.c -+++ b/hw/i386/pc.c -@@ -115,9 +115,6 @@ struct hpet_fw_config hpet_cfg = {.count = UINT8_MAX}; - /* Physical Address of PVH entry point read from kernel ELF NOTE */ - static size_t pvh_start_addr; - --GlobalProperty pc_compat_4_0_1[] = {}; --const size_t pc_compat_4_0_1_len = G_N_ELEMENTS(pc_compat_4_0_1); -- - GlobalProperty pc_compat_4_0[] = {}; - const size_t pc_compat_4_0_len = G_N_ELEMENTS(pc_compat_4_0); - -diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c -index dcddc646..e3498a45 100644 ---- a/hw/i386/pc_q35.c -+++ b/hw/i386/pc_q35.c -@@ -378,8 +378,13 @@ static void pc_q35_4_0_1_machine_options(MachineClass *m) - { - pc_q35_4_1_machine_options(m); - m->alias = NULL; -- compat_props_add(m->compat_props, hw_compat_4_0_1, hw_compat_4_0_1_len); -- compat_props_add(m->compat_props, pc_compat_4_0_1, pc_compat_4_0_1_len); -+ /* -+ * This is the default machine for the 4.0-stable branch. It is basically -+ * a 4.0 that doesn't use split irqchip by default. It MUST hence apply the -+ * 4.0 compat props. -+ */ -+ compat_props_add(m->compat_props, hw_compat_4_0, hw_compat_4_0_len); -+ compat_props_add(m->compat_props, pc_compat_4_0, pc_compat_4_0_len); - } - - DEFINE_Q35_MACHINE(v4_0_1, "pc-q35-4.0.1", NULL, -diff --git a/include/hw/boards.h b/include/hw/boards.h -index ad3950d3..fe1885cb 100644 ---- a/include/hw/boards.h -+++ b/include/hw/boards.h -@@ -293,9 +293,6 @@ struct MachineState { - } \ - type_init(machine_initfn##_register_types) - --extern GlobalProperty hw_compat_4_0_1[]; --extern const size_t hw_compat_4_0_1_len; -- - extern GlobalProperty hw_compat_4_0[]; - extern const size_t hw_compat_4_0_len; - -diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h -index 5d563624..43df7230 100644 ---- a/include/hw/i386/pc.h -+++ b/include/hw/i386/pc.h -@@ -293,9 +293,6 @@ int e820_add_entry(uint64_t, uint64_t, uint32_t); - int e820_get_num_entries(void); - bool e820_get_entry(int, uint32_t, uint64_t *, uint64_t *); - --extern GlobalProperty pc_compat_4_0_1[]; --extern const size_t pc_compat_4_0_1_len; -- - extern GlobalProperty pc_compat_4_0[]; - extern const size_t pc_compat_4_0_len; - --- -2.19.1 - diff --git a/hw-Remove-unnecessary-DEVICE-cast.patch b/hw-Remove-unnecessary-DEVICE-cast.patch new file mode 100644 index 0000000000000000000000000000000000000000..9c9679704be20d8091021e1054fee17cb4ed677e --- /dev/null +++ b/hw-Remove-unnecessary-DEVICE-cast.patch @@ -0,0 +1,276 @@ +From 8e5c952b370b57beb642826882c80e1b66a9cf12 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Tue, 12 May 2020 09:00:20 +0200 +Subject: [PATCH 483/709] hw: Remove unnecessary DEVICE() cast +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The DEVICE() macro is defined as: + + #define DEVICE(obj) OBJECT_CHECK(DeviceState, (obj), TYPE_DEVICE) + +which expands to: + + ((DeviceState *)object_dynamic_cast_assert((Object *)(obj), (name), + __FILE__, __LINE__, + __func__)) + +This assertion can only fail when @obj points to something other +than its stated type, i.e. when we're in undefined behavior country. + +Remove the unnecessary DEVICE() casts when we already know the +pointer is of DeviceState type. + +Patch created mechanically using spatch with this script: + + @@ + typedef DeviceState; + DeviceState *s; + @@ + - DEVICE(s) + + s + +Acked-by: David Gibson +Acked-by: Paul Durrant +Reviewed-by: Markus Armbruster +Reviewed-by: Cédric Le Goater +Acked-by: John Snow +Reviewed-by: Richard Henderson +Reviewed-by: Markus Armbruster +Signed-off-by: Philippe Mathieu-Daudé +Message-Id: <20200512070020.22782-4-f4bug@amsat.org> +--- + hw/display/artist.c | 2 +- + hw/display/cg3.c | 2 +- + hw/display/sm501.c | 2 +- + hw/display/tcx.c | 4 ++-- + hw/display/vga-isa.c | 2 +- + hw/i2c/imx_i2c.c | 2 +- + hw/i2c/mpc_i2c.c | 2 +- + hw/ide/piix.c | 2 +- + hw/misc/macio/pmu.c | 2 +- + hw/net/ftgmac100.c | 3 +-- + hw/net/imx_fec.c | 2 +- + hw/nubus/nubus-device.c | 2 +- + hw/pci-host/bonito.c | 2 +- + hw/ppc/spapr.c | 2 +- + hw/sh4/sh_pci.c | 2 +- + hw/xen/xen-legacy-backend.c | 2 +- + 16 files changed, 17 insertions(+), 18 deletions(-) + +diff --git a/hw/display/artist.c b/hw/display/artist.c +index 753dbb9a77..7e2a4556bd 100644 +--- a/hw/display/artist.c ++++ b/hw/display/artist.c +@@ -1353,7 +1353,7 @@ static void artist_realizefn(DeviceState *dev, Error **errp) + s->cursor_height = 32; + s->cursor_width = 32; + +- s->con = graphic_console_init(DEVICE(dev), 0, &artist_ops, s); ++ s->con = graphic_console_init(dev, 0, &artist_ops, s); + qemu_console_resize(s->con, s->width, s->height); + } + +diff --git a/hw/display/cg3.c b/hw/display/cg3.c +index a1ede10394..f7f1c199ce 100644 +--- a/hw/display/cg3.c ++++ b/hw/display/cg3.c +@@ -321,7 +321,7 @@ static void cg3_realizefn(DeviceState *dev, Error **errp) + + sysbus_init_irq(sbd, &s->irq); + +- s->con = graphic_console_init(DEVICE(dev), 0, &cg3_ops, s); ++ s->con = graphic_console_init(dev, 0, &cg3_ops, s); + qemu_console_resize(s->con, s->width, s->height); + } + +diff --git a/hw/display/sm501.c b/hw/display/sm501.c +index 296cd56c4a..acc692531a 100644 +--- a/hw/display/sm501.c ++++ b/hw/display/sm501.c +@@ -1839,7 +1839,7 @@ static void sm501_init(SM501State *s, DeviceState *dev, + &s->twoD_engine_region); + + /* create qemu graphic console */ +- s->con = graphic_console_init(DEVICE(dev), 0, &sm501_ops, s); ++ s->con = graphic_console_init(dev, 0, &sm501_ops, s); + } + + static const VMStateDescription vmstate_sm501_state = { +diff --git a/hw/display/tcx.c b/hw/display/tcx.c +index 76de16e8ea..1fb45b1aab 100644 +--- a/hw/display/tcx.c ++++ b/hw/display/tcx.c +@@ -868,9 +868,9 @@ static void tcx_realizefn(DeviceState *dev, Error **errp) + sysbus_init_irq(sbd, &s->irq); + + if (s->depth == 8) { +- s->con = graphic_console_init(DEVICE(dev), 0, &tcx_ops, s); ++ s->con = graphic_console_init(dev, 0, &tcx_ops, s); + } else { +- s->con = graphic_console_init(DEVICE(dev), 0, &tcx24_ops, s); ++ s->con = graphic_console_init(dev, 0, &tcx24_ops, s); + } + s->thcmisc = 0; + +diff --git a/hw/display/vga-isa.c b/hw/display/vga-isa.c +index 0633ed382c..3aaeeeca1e 100644 +--- a/hw/display/vga-isa.c ++++ b/hw/display/vga-isa.c +@@ -74,7 +74,7 @@ static void vga_isa_realizefn(DeviceState *dev, Error **errp) + 0x000a0000, + vga_io_memory, 1); + memory_region_set_coalescing(vga_io_memory); +- s->con = graphic_console_init(DEVICE(dev), 0, s->hw_ops, s); ++ s->con = graphic_console_init(dev, 0, s->hw_ops, s); + + memory_region_add_subregion(isa_address_space(isadev), + VBE_DISPI_LFB_PHYSICAL_ADDRESS, +diff --git a/hw/i2c/imx_i2c.c b/hw/i2c/imx_i2c.c +index 30b9aea247..2e02e1c4fa 100644 +--- a/hw/i2c/imx_i2c.c ++++ b/hw/i2c/imx_i2c.c +@@ -305,7 +305,7 @@ static void imx_i2c_realize(DeviceState *dev, Error **errp) + IMX_I2C_MEM_SIZE); + sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->iomem); + sysbus_init_irq(SYS_BUS_DEVICE(dev), &s->irq); +- s->bus = i2c_init_bus(DEVICE(dev), NULL); ++ s->bus = i2c_init_bus(dev, NULL); + } + + static void imx_i2c_class_init(ObjectClass *klass, void *data) +diff --git a/hw/i2c/mpc_i2c.c b/hw/i2c/mpc_i2c.c +index 0aa1be3ce7..9a724f3a3e 100644 +--- a/hw/i2c/mpc_i2c.c ++++ b/hw/i2c/mpc_i2c.c +@@ -332,7 +332,7 @@ static void mpc_i2c_realize(DeviceState *dev, Error **errp) + memory_region_init_io(&i2c->iomem, OBJECT(i2c), &i2c_ops, i2c, + "mpc-i2c", 0x14); + sysbus_init_mmio(SYS_BUS_DEVICE(dev), &i2c->iomem); +- i2c->bus = i2c_init_bus(DEVICE(dev), "i2c"); ++ i2c->bus = i2c_init_bus(dev, "i2c"); + } + + static void mpc_i2c_class_init(ObjectClass *klass, void *data) +diff --git a/hw/ide/piix.c b/hw/ide/piix.c +index 3b2de4c312..b402a93636 100644 +--- a/hw/ide/piix.c ++++ b/hw/ide/piix.c +@@ -193,7 +193,7 @@ int pci_piix3_xen_ide_unplug(DeviceState *dev, bool aux) + blk_unref(blk); + } + } +- qdev_reset_all(DEVICE(dev)); ++ qdev_reset_all(dev); + return 0; + } + +diff --git a/hw/misc/macio/pmu.c b/hw/misc/macio/pmu.c +index 5fa792846c..9a9cd427e1 100644 +--- a/hw/misc/macio/pmu.c ++++ b/hw/misc/macio/pmu.c +@@ -758,7 +758,7 @@ static void pmu_realize(DeviceState *dev, Error **errp) + + if (s->has_adb) { + qbus_create_inplace(&s->adb_bus, sizeof(s->adb_bus), TYPE_ADB_BUS, +- DEVICE(dev), "adb.0"); ++ dev, "adb.0"); + s->adb_poll_timer = timer_new_ms(QEMU_CLOCK_VIRTUAL, pmu_adb_poll, s); + s->adb_poll_mask = 0xffff; + s->autopoll_rate_ms = 20; +diff --git a/hw/net/ftgmac100.c b/hw/net/ftgmac100.c +index 041ed21017..25ebee7ec2 100644 +--- a/hw/net/ftgmac100.c ++++ b/hw/net/ftgmac100.c +@@ -1035,8 +1035,7 @@ static void ftgmac100_realize(DeviceState *dev, Error **errp) + qemu_macaddr_default_if_unset(&s->conf.macaddr); + + s->nic = qemu_new_nic(&net_ftgmac100_info, &s->conf, +- object_get_typename(OBJECT(dev)), DEVICE(dev)->id, +- s); ++ object_get_typename(OBJECT(dev)), dev->id, s); + qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a); + } + +diff --git a/hw/net/imx_fec.c b/hw/net/imx_fec.c +index a35c33683e..7adcc9df65 100644 +--- a/hw/net/imx_fec.c ++++ b/hw/net/imx_fec.c +@@ -1323,7 +1323,7 @@ static void imx_eth_realize(DeviceState *dev, Error **errp) + + s->nic = qemu_new_nic(&imx_eth_net_info, &s->conf, + object_get_typename(OBJECT(dev)), +- DEVICE(dev)->id, s); ++ dev->id, s); + + qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a); + } +diff --git a/hw/nubus/nubus-device.c b/hw/nubus/nubus-device.c +index 01ccad9e8e..ffe78a8823 100644 +--- a/hw/nubus/nubus-device.c ++++ b/hw/nubus/nubus-device.c +@@ -156,7 +156,7 @@ void nubus_register_rom(NubusDevice *dev, const uint8_t *rom, uint32_t size, + + static void nubus_device_realize(DeviceState *dev, Error **errp) + { +- NubusBus *nubus = NUBUS_BUS(qdev_get_parent_bus(DEVICE(dev))); ++ NubusBus *nubus = NUBUS_BUS(qdev_get_parent_bus(dev)); + NubusDevice *nd = NUBUS_DEVICE(dev); + char *name; + hwaddr slot_offset; +diff --git a/hw/pci-host/bonito.c b/hw/pci-host/bonito.c +index cc6545c8a8..f212796044 100644 +--- a/hw/pci-host/bonito.c ++++ b/hw/pci-host/bonito.c +@@ -606,7 +606,7 @@ static void bonito_pcihost_realize(DeviceState *dev, Error **errp) + BonitoState *bs = BONITO_PCI_HOST_BRIDGE(dev); + + memory_region_init(&bs->pci_mem, OBJECT(dev), "pci.mem", BONITO_PCILO_SIZE); +- phb->bus = pci_register_root_bus(DEVICE(dev), "pci", ++ phb->bus = pci_register_root_bus(dev, "pci", + pci_bonito_set_irq, pci_bonito_map_irq, + dev, &bs->pci_mem, get_system_io(), + 0x28, 32, TYPE_PCI_BUS); +diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c +index c0bf8c8d4f..9b358fcc60 100644 +--- a/hw/ppc/spapr.c ++++ b/hw/ppc/spapr.c +@@ -4013,7 +4013,7 @@ static void spapr_phb_plug(HotplugHandler *hotplug_dev, DeviceState *dev, + /* hotplug hooks should check it's enabled before getting this far */ + assert(drc); + +- spapr_drc_attach(drc, DEVICE(dev), &local_err); ++ spapr_drc_attach(drc, dev, &local_err); + if (local_err) { + error_propagate(errp, local_err); + return; +diff --git a/hw/sh4/sh_pci.c b/hw/sh4/sh_pci.c +index 08f2fc1dde..0a3e86f949 100644 +--- a/hw/sh4/sh_pci.c ++++ b/hw/sh4/sh_pci.c +@@ -129,7 +129,7 @@ static void sh_pci_device_realize(DeviceState *dev, Error **errp) + for (i = 0; i < 4; i++) { + sysbus_init_irq(sbd, &s->irq[i]); + } +- phb->bus = pci_register_root_bus(DEVICE(dev), "pci", ++ phb->bus = pci_register_root_bus(dev, "pci", + sh_pci_set_irq, sh_pci_map_irq, + s->irq, + get_system_memory(), +diff --git a/hw/xen/xen-legacy-backend.c b/hw/xen/xen-legacy-backend.c +index 4a373b2373..f9d013811a 100644 +--- a/hw/xen/xen-legacy-backend.c ++++ b/hw/xen/xen-legacy-backend.c +@@ -705,7 +705,7 @@ int xen_be_init(void) + + xen_sysdev = qdev_create(NULL, TYPE_XENSYSDEV); + qdev_init_nofail(xen_sysdev); +- xen_sysbus = qbus_create(TYPE_XENSYSBUS, DEVICE(xen_sysdev), "xen-sysbus"); ++ xen_sysbus = qbus_create(TYPE_XENSYSBUS, xen_sysdev, "xen-sysbus"); + qbus_set_bus_hotplug_handler(xen_sysbus, &error_abort); + + return 0; +-- +2.23.0 + diff --git a/hw-Use-QEMU_IS_ALIGNED-on-parallel-flash-block-size.patch b/hw-Use-QEMU_IS_ALIGNED-on-parallel-flash-block-size.patch new file mode 100644 index 0000000000000000000000000000000000000000..5938981bde5e77a853f6b7a7dffaf4fb7b11e2ad --- /dev/null +++ b/hw-Use-QEMU_IS_ALIGNED-on-parallel-flash-block-size.patch @@ -0,0 +1,108 @@ +From 4cdd0a774dc35b2ffe6ddb634e0c431f17dfe07e Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Mon, 11 May 2020 22:52:46 +0200 +Subject: [PATCH 572/709] hw: Use QEMU_IS_ALIGNED() on parallel flash block + size +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Use the QEMU_IS_ALIGNED() macro to verify the flash block size +is properly aligned. It is quicker to process when reviewing. + +Signed-off-by: Philippe Mathieu-Daudé +Message-Id: <20200511205246.24621-1-philmd@redhat.com> +Reviewed-by: Alistair Francis +Reviewed-by: Peter Maydell +Acked-by: Paolo Bonzini +Signed-off-by: Kevin Wolf +--- + hw/arm/sbsa-ref.c | 2 +- + hw/arm/virt.c | 2 +- + hw/block/pflash_cfi01.c | 2 +- + hw/block/pflash_cfi02.c | 2 +- + hw/i386/pc_sysfw.c | 2 +- + hw/riscv/virt.c | 2 +- + 6 files changed, 6 insertions(+), 6 deletions(-) + +diff --git a/hw/arm/sbsa-ref.c b/hw/arm/sbsa-ref.c +index a6cdb4fb7b..6a0221a681 100644 +--- a/hw/arm/sbsa-ref.c ++++ b/hw/arm/sbsa-ref.c +@@ -240,7 +240,7 @@ static void sbsa_flash_map1(PFlashCFI01 *flash, + { + DeviceState *dev = DEVICE(flash); + +- assert(size % SBSA_FLASH_SECTOR_SIZE == 0); ++ assert(QEMU_IS_ALIGNED(size, SBSA_FLASH_SECTOR_SIZE)); + assert(size / SBSA_FLASH_SECTOR_SIZE <= UINT32_MAX); + qdev_prop_set_uint32(dev, "num-blocks", size / SBSA_FLASH_SECTOR_SIZE); + qdev_init_nofail(dev); +diff --git a/hw/arm/virt.c b/hw/arm/virt.c +index c41d5f9778..37462a6f78 100644 +--- a/hw/arm/virt.c ++++ b/hw/arm/virt.c +@@ -977,7 +977,7 @@ static void virt_flash_map1(PFlashCFI01 *flash, + { + DeviceState *dev = DEVICE(flash); + +- assert(size % VIRT_FLASH_SECTOR_SIZE == 0); ++ assert(QEMU_IS_ALIGNED(size, VIRT_FLASH_SECTOR_SIZE)); + assert(size / VIRT_FLASH_SECTOR_SIZE <= UINT32_MAX); + qdev_prop_set_uint32(dev, "num-blocks", size / VIRT_FLASH_SECTOR_SIZE); + qdev_init_nofail(dev); +diff --git a/hw/block/pflash_cfi01.c b/hw/block/pflash_cfi01.c +index 24f3bce7ef..8e8887253d 100644 +--- a/hw/block/pflash_cfi01.c ++++ b/hw/block/pflash_cfi01.c +@@ -965,7 +965,7 @@ PFlashCFI01 *pflash_cfi01_register(hwaddr base, + if (blk) { + qdev_prop_set_drive(dev, "drive", blk, &error_abort); + } +- assert(size % sector_len == 0); ++ assert(QEMU_IS_ALIGNED(size, sector_len)); + qdev_prop_set_uint32(dev, "num-blocks", size / sector_len); + qdev_prop_set_uint64(dev, "sector-length", sector_len); + qdev_prop_set_uint8(dev, "width", bank_width); +diff --git a/hw/block/pflash_cfi02.c b/hw/block/pflash_cfi02.c +index f0579ecb17..c277b0309d 100644 +--- a/hw/block/pflash_cfi02.c ++++ b/hw/block/pflash_cfi02.c +@@ -997,7 +997,7 @@ PFlashCFI02 *pflash_cfi02_register(hwaddr base, + if (blk) { + qdev_prop_set_drive(dev, "drive", blk, &error_abort); + } +- assert(size % sector_len == 0); ++ assert(QEMU_IS_ALIGNED(size, sector_len)); + qdev_prop_set_uint32(dev, "num-blocks", size / sector_len); + qdev_prop_set_uint32(dev, "sector-length", sector_len); + qdev_prop_set_uint8(dev, "width", width); +diff --git a/hw/i386/pc_sysfw.c b/hw/i386/pc_sysfw.c +index 2abab3a27c..b8d8ef59eb 100644 +--- a/hw/i386/pc_sysfw.c ++++ b/hw/i386/pc_sysfw.c +@@ -167,7 +167,7 @@ static void pc_system_flash_map(PCMachineState *pcms, + blk_name(blk), strerror(-size)); + exit(1); + } +- if (size == 0 || size % FLASH_SECTOR_SIZE != 0) { ++ if (size == 0 || !QEMU_IS_ALIGNED(size, FLASH_SECTOR_SIZE)) { + error_report("system firmware block device %s has invalid size " + "%" PRId64, + blk_name(blk), size); +diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c +index c695a44979..7ce28895bc 100644 +--- a/hw/riscv/virt.c ++++ b/hw/riscv/virt.c +@@ -111,7 +111,7 @@ static void virt_flash_map1(PFlashCFI01 *flash, + { + DeviceState *dev = DEVICE(flash); + +- assert(size % VIRT_FLASH_SECTOR_SIZE == 0); ++ assert(QEMU_IS_ALIGNED(size, VIRT_FLASH_SECTOR_SIZE)); + assert(size / VIRT_FLASH_SECTOR_SIZE <= UINT32_MAX); + qdev_prop_set_uint32(dev, "num-blocks", size / VIRT_FLASH_SECTOR_SIZE); + qdev_init_nofail(dev); +-- +2.23.0 + diff --git a/hw-acpi-nvdimm-Fix-for-NVDIMM-incorrect-DSM-output-b.patch b/hw-acpi-nvdimm-Fix-for-NVDIMM-incorrect-DSM-output-b.patch new file mode 100644 index 0000000000000000000000000000000000000000..183ff0a41555ed939732dc417f6a3ed42b0acf1e --- /dev/null +++ b/hw-acpi-nvdimm-Fix-for-NVDIMM-incorrect-DSM-output-b.patch @@ -0,0 +1,109 @@ +From 71b0269ae9a80cfd28c3b5946748b92ac8821334 Mon Sep 17 00:00:00 2001 +From: Shameer Kolothum +Date: Tue, 21 Apr 2020 13:59:28 +0100 +Subject: [PATCH 218/709] hw/acpi/nvdimm: Fix for NVDIMM incorrect DSM output + buffer length + +As per ACPI spec 6.3, Table 19-419 Object Conversion Rules, if +the Buffer Field <= to the size of an Integer (in bits), it will +be treated as an integer. Moreover, the integer size depends on +DSDT tables revision number. If revision number is < 2, integer +size is 32 bits, otherwise it is 64 bits. Current NVDIMM common +DSM aml code (NCAL) uses CreateField() for creating DSM output +buffer. This creates an issue in arm/virt platform where DSDT +revision number is 2 and results in DSM buffer with a wrong +size(8 bytes) gets returned when actual length is < 8 bytes. +This causes guest kernel to report, + +"nfit ACPI0012:00: found a zero length table '0' parsing nfit" + +In order to fix this, aml code is now modified such that it builds +the DSM output buffer in a byte by byte fashion when length is +smaller than Integer size. + +Suggested-by: Igor Mammedov +Signed-off-by: Shameer Kolothum +Reviewed-by: Igor Mammedov +Message-Id: <20200421125934.14952-2-shameerali.kolothum.thodi@huawei.com> +Acked-by: Peter Maydell +Tested-by: Eric Auger +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +--- + hw/acpi/nvdimm.c | 40 +++++++++++++++++++-- + tests/qtest/bios-tables-test-allowed-diff.h | 2 ++ + 2 files changed, 39 insertions(+), 3 deletions(-) + +diff --git a/hw/acpi/nvdimm.c b/hw/acpi/nvdimm.c +index eb6a37b14e..df0790719a 100644 +--- a/hw/acpi/nvdimm.c ++++ b/hw/acpi/nvdimm.c +@@ -938,6 +938,7 @@ static void nvdimm_build_common_dsm(Aml *dev) + Aml *method, *ifctx, *function, *handle, *uuid, *dsm_mem, *elsectx2; + Aml *elsectx, *unsupport, *unpatched, *expected_uuid, *uuid_invalid; + Aml *pckg, *pckg_index, *pckg_buf, *field, *dsm_out_buf, *dsm_out_buf_size; ++ Aml *whilectx, *offset; + uint8_t byte_list[1]; + + method = aml_method(NVDIMM_COMMON_DSM, 5, AML_SERIALIZED); +@@ -1091,13 +1092,46 @@ static void nvdimm_build_common_dsm(Aml *dev) + /* RLEN is not included in the payload returned to guest. */ + aml_append(method, aml_subtract(aml_name(NVDIMM_DSM_OUT_BUF_SIZE), + aml_int(4), dsm_out_buf_size)); ++ ++ /* ++ * As per ACPI spec 6.3, Table 19-419 Object Conversion Rules, if ++ * the Buffer Field <= to the size of an Integer (in bits), it will ++ * be treated as an integer. Moreover, the integer size depends on ++ * DSDT tables revision number. If revision number is < 2, integer ++ * size is 32 bits, otherwise it is 64 bits. ++ * Because of this CreateField() canot be used if RLEN < Integer Size. ++ * ++ * Also please note that APCI ASL operator SizeOf() doesn't support ++ * Integer and there isn't any other way to figure out the Integer ++ * size. Hence we assume 8 byte as Integer size and if RLEN < 8 bytes, ++ * build dsm_out_buf byte by byte. ++ */ ++ ifctx = aml_if(aml_lless(dsm_out_buf_size, aml_int(8))); ++ offset = aml_local(2); ++ aml_append(ifctx, aml_store(aml_int(0), offset)); ++ aml_append(ifctx, aml_name_decl("TBUF", aml_buffer(1, NULL))); ++ aml_append(ifctx, aml_store(aml_buffer(0, NULL), dsm_out_buf)); ++ ++ whilectx = aml_while(aml_lless(offset, dsm_out_buf_size)); ++ /* Copy 1 byte at offset from ODAT to temporary buffer(TBUF). */ ++ aml_append(whilectx, aml_store(aml_derefof(aml_index( ++ aml_name(NVDIMM_DSM_OUT_BUF), offset)), ++ aml_index(aml_name("TBUF"), aml_int(0)))); ++ aml_append(whilectx, aml_concatenate(dsm_out_buf, aml_name("TBUF"), ++ dsm_out_buf)); ++ aml_append(whilectx, aml_increment(offset)); ++ aml_append(ifctx, whilectx); ++ ++ aml_append(ifctx, aml_return(dsm_out_buf)); ++ aml_append(method, ifctx); ++ ++ /* If RLEN >= Integer size, just use CreateField() operator */ + aml_append(method, aml_store(aml_shiftleft(dsm_out_buf_size, aml_int(3)), + dsm_out_buf_size)); + aml_append(method, aml_create_field(aml_name(NVDIMM_DSM_OUT_BUF), + aml_int(0), dsm_out_buf_size, "OBUF")); +- aml_append(method, aml_concatenate(aml_buffer(0, NULL), aml_name("OBUF"), +- dsm_out_buf)); +- aml_append(method, aml_return(dsm_out_buf)); ++ aml_append(method, aml_return(aml_name("OBUF"))); ++ + aml_append(dev, method); + } + +diff --git a/tests/qtest/bios-tables-test-allowed-diff.h b/tests/qtest/bios-tables-test-allowed-diff.h +index dfb8523c8b..eb8bae1407 100644 +--- a/tests/qtest/bios-tables-test-allowed-diff.h ++++ b/tests/qtest/bios-tables-test-allowed-diff.h +@@ -1 +1,3 @@ + /* List of comma-separated changed AML files to ignore */ ++"tests/data/acpi/pc/SSDT.dimmpxm", ++"tests/data/acpi/q35/SSDT.dimmpxm", +-- +2.23.0 + diff --git a/hw-add-compat-machines-for-4.1.patch b/hw-add-compat-machines-for-5.1.patch similarity index 31% rename from hw-add-compat-machines-for-4.1.patch rename to hw-add-compat-machines-for-5.1.patch index 67d1ccd9abf62d9e2bafff5f779fa6f8d3218a16..1625eb5bfd7da5efc5a2450c96849b90e9ec563a 100644 --- a/hw-add-compat-machines-for-4.1.patch +++ b/hw-add-compat-machines-for-5.1.patch @@ -1,18 +1,16 @@ -From 9bf2650bc3aab126b85c034bf86e27d564f9a1aa Mon Sep 17 00:00:00 2001 +From 541aaa1df80df465c7dc934dc8cf57c0e3dfd6c3 Mon Sep 17 00:00:00 2001 From: Cornelia Huck -Date: Thu, 11 Apr 2019 12:20:25 +0200 -Subject: [PATCH] hw: add compat machines for 4.1 +Date: Wed, 29 Apr 2020 16:46:05 +0200 +Subject: [PATCH 282/709] hw: add compat machines for 5.1 -Add 4.1 machine types for arm/i440fx/q35/s390x/spapr. +Add 5.1 machine types for arm/i440fx/q35/s390x/spapr. -Signed-off-by: Cornelia Huck -Message-Id: <20190411102025.22559-1-cohuck@redhat.com> -Acked-by: Greg Kurz Acked-by: David Gibson -Signed-off-by: Eduardo Habkost -(cherry-picked from commit 9bf2650bc3aab126b85c034bf86e27d564f9a1aa) +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Cornelia Huck +Message-id: 20200429144605.7262-1-cohuck@redhat.com --- - hw/arm/virt.c | 9 ++++++++- + hw/arm/virt.c | 8 +++++++- hw/core/machine.c | 3 +++ hw/i386/pc.c | 3 +++ hw/i386/pc_piix.c | 14 +++++++++++++- @@ -21,212 +19,214 @@ Signed-off-by: Eduardo Habkost hw/s390x/s390-virtio-ccw.c | 14 +++++++++++++- include/hw/boards.h | 3 +++ include/hw/i386/pc.h | 3 +++ - 9 files changed, 71 insertions(+), 6 deletions(-) + 9 files changed, 70 insertions(+), 6 deletions(-) diff --git a/hw/arm/virt.c b/hw/arm/virt.c -index ce2664a30b..16ba67f7a7 100644 +index dd024d0780..634db0cfe9 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c -@@ -1978,10 +1978,17 @@ static void machvirt_machine_init(void) +@@ -2352,10 +2352,16 @@ static void machvirt_machine_init(void) } type_init(machvirt_machine_init); -+static void virt_machine_4_1_options(MachineClass *mc) ++static void virt_machine_5_1_options(MachineClass *mc) +{ +} -+DEFINE_VIRT_MACHINE_AS_LATEST(4, 1) ++DEFINE_VIRT_MACHINE_AS_LATEST(5, 1) + - static void virt_machine_4_0_options(MachineClass *mc) + static void virt_machine_5_0_options(MachineClass *mc) { -+ virt_machine_4_1_options(mc); -+ compat_props_add(mc->compat_props, hw_compat_4_0, hw_compat_4_0_len); ++ virt_machine_5_1_options(mc); } --DEFINE_VIRT_MACHINE_AS_LATEST(4, 0) -+DEFINE_VIRT_MACHINE(4, 0) +-DEFINE_VIRT_MACHINE_AS_LATEST(5, 0) ++DEFINE_VIRT_MACHINE(5, 0) - static void virt_machine_3_1_options(MachineClass *mc) + static void virt_machine_4_2_options(MachineClass *mc) { diff --git a/hw/core/machine.c b/hw/core/machine.c -index 743fef2898..5d046a43e3 100644 +index c1a444cb75..7a50dd518f 100644 --- a/hw/core/machine.c +++ b/hw/core/machine.c -@@ -24,6 +24,9 @@ - #include "hw/pci/pci.h" +@@ -28,6 +28,9 @@ #include "hw/mem/nvdimm.h" + #include "migration/vmstate.h" -+GlobalProperty hw_compat_4_0[] = {}; -+const size_t hw_compat_4_0_len = G_N_ELEMENTS(hw_compat_4_0); ++GlobalProperty hw_compat_5_0[] = {}; ++const size_t hw_compat_5_0_len = G_N_ELEMENTS(hw_compat_5_0); + - GlobalProperty hw_compat_3_1[] = { - { "pcie-root-port", "x-speed", "2_5" }, - { "pcie-root-port", "x-width", "1" }, + GlobalProperty hw_compat_4_2[] = { + { "virtio-blk-device", "queue-size", "128"}, + { "virtio-scsi-device", "virtqueue_size", "128"}, diff --git a/hw/i386/pc.c b/hw/i386/pc.c -index f2c15bf1f2..d98b737b8f 100644 +index f6b8431c8b..97e345faea 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c -@@ -115,6 +115,9 @@ struct hpet_fw_config hpet_cfg = {.count = UINT8_MAX}; - /* Physical Address of PVH entry point read from kernel ELF NOTE */ - static size_t pvh_start_addr; +@@ -95,6 +95,9 @@ + #include "fw_cfg.h" + #include "trace.h" -+GlobalProperty pc_compat_4_0[] = {}; -+const size_t pc_compat_4_0_len = G_N_ELEMENTS(pc_compat_4_0); ++GlobalProperty pc_compat_5_0[] = {}; ++const size_t pc_compat_5_0_len = G_N_ELEMENTS(pc_compat_5_0); + - GlobalProperty pc_compat_3_1[] = { - { "intel-iommu", "dma-drain", "off" }, - { "Opteron_G3" "-" TYPE_X86_CPU, "rdtscp", "off" }, + GlobalProperty pc_compat_4_2[] = { + { "mch", "smbase-smram", "off" }, + }; diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c -index 8ad8e885c6..2a7700b564 100644 +index b75087d71b..3862e5120e 100644 --- a/hw/i386/pc_piix.c +++ b/hw/i386/pc_piix.c -@@ -428,13 +428,25 @@ static void pc_i440fx_machine_options(MachineClass *m) +@@ -421,7 +421,7 @@ static void pc_i440fx_machine_options(MachineClass *m) machine_class_allow_dynamic_sysbus_dev(m, TYPE_RAMFB_DEVICE); } --static void pc_i440fx_4_0_machine_options(MachineClass *m) -+static void pc_i440fx_4_1_machine_options(MachineClass *m) +-static void pc_i440fx_5_0_machine_options(MachineClass *m) ++static void pc_i440fx_5_1_machine_options(MachineClass *m) { + PCMachineClass *pcmc = PC_MACHINE_CLASS(m); pc_i440fx_machine_options(m); - m->alias = "pc"; - m->is_default = 1; +@@ -430,6 +430,18 @@ static void pc_i440fx_5_0_machine_options(MachineClass *m) + pcmc->default_cpu_version = 1; } -+DEFINE_I440FX_MACHINE(v4_1, "pc-i440fx-4.1", NULL, -+ pc_i440fx_4_1_machine_options); ++DEFINE_I440FX_MACHINE(v5_1, "pc-i440fx-5.1", NULL, ++ pc_i440fx_5_1_machine_options); + -+static void pc_i440fx_4_0_machine_options(MachineClass *m) ++static void pc_i440fx_5_0_machine_options(MachineClass *m) +{ -+ pc_i440fx_4_1_machine_options(m); ++ pc_i440fx_5_1_machine_options(m); + m->alias = NULL; -+ m->is_default = 0; -+ compat_props_add(m->compat_props, hw_compat_4_0, hw_compat_4_0_len); -+ compat_props_add(m->compat_props, pc_compat_4_0, pc_compat_4_0_len); ++ m->is_default = false; ++ compat_props_add(m->compat_props, hw_compat_5_0, hw_compat_5_0_len); ++ compat_props_add(m->compat_props, pc_compat_5_0, pc_compat_5_0_len); +} + - DEFINE_I440FX_MACHINE(v4_0, "pc-i440fx-4.0", NULL, - pc_i440fx_4_0_machine_options); + DEFINE_I440FX_MACHINE(v5_0, "pc-i440fx-5.0", NULL, + pc_i440fx_5_0_machine_options); diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c -index 372c6b73be..37dd350511 100644 +index d2806c1b29..3349e38a4c 100644 --- a/hw/i386/pc_q35.c +++ b/hw/i386/pc_q35.c -@@ -365,12 +365,23 @@ static void pc_q35_machine_options(MachineClass *m) +@@ -351,7 +351,7 @@ static void pc_q35_machine_options(MachineClass *m) m->max_cpus = 288; } --static void pc_q35_4_0_machine_options(MachineClass *m) -+static void pc_q35_4_1_machine_options(MachineClass *m) +-static void pc_q35_5_0_machine_options(MachineClass *m) ++static void pc_q35_5_1_machine_options(MachineClass *m) { + PCMachineClass *pcmc = PC_MACHINE_CLASS(m); pc_q35_machine_options(m); - m->alias = "q35"; +@@ -359,6 +359,17 @@ static void pc_q35_5_0_machine_options(MachineClass *m) + pcmc->default_cpu_version = 1; } -+DEFINE_Q35_MACHINE(v4_1, "pc-q35-4.1", NULL, -+ pc_q35_4_1_machine_options); ++DEFINE_Q35_MACHINE(v5_1, "pc-q35-5.1", NULL, ++ pc_q35_5_1_machine_options); + -+static void pc_q35_4_0_machine_options(MachineClass *m) ++static void pc_q35_5_0_machine_options(MachineClass *m) +{ -+ pc_q35_4_1_machine_options(m); ++ pc_q35_5_1_machine_options(m); + m->alias = NULL; -+ compat_props_add(m->compat_props, hw_compat_4_0, hw_compat_4_0_len); -+ compat_props_add(m->compat_props, pc_compat_4_0, pc_compat_4_0_len); ++ compat_props_add(m->compat_props, hw_compat_5_0, hw_compat_5_0_len); ++ compat_props_add(m->compat_props, pc_compat_5_0, pc_compat_5_0_len); +} + - DEFINE_Q35_MACHINE(v4_0, "pc-q35-4.0", NULL, - pc_q35_4_0_machine_options); + DEFINE_Q35_MACHINE(v5_0, "pc-q35-5.0", NULL, + pc_q35_5_0_machine_options); diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c -index b52b82d298..8438741ec2 100644 +index 9a2bd501aa..fd5bfd11a8 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c -@@ -4344,15 +4344,26 @@ static const TypeInfo spapr_machine_info = { +@@ -4599,15 +4599,26 @@ static void spapr_machine_latest_class_options(MachineClass *mc) } \ type_init(spapr_machine_register_##suffix) +/* -+ * pseries-4.1 ++ * pseries-5.1 + */ -+static void spapr_machine_4_1_class_options(MachineClass *mc) ++static void spapr_machine_5_1_class_options(MachineClass *mc) +{ + /* Defaults for the latest behaviour inherited from the base class */ +} + -+DEFINE_SPAPR_MACHINE(4_1, "4.1", true); ++DEFINE_SPAPR_MACHINE(5_1, "5.1", true); + /* - * pseries-4.0 + * pseries-5.0 */ - static void spapr_machine_4_0_class_options(MachineClass *mc) + static void spapr_machine_5_0_class_options(MachineClass *mc) { - /* Defaults for the latest behaviour inherited from the base class */ -+ spapr_machine_4_1_class_options(mc); -+ compat_props_add(mc->compat_props, hw_compat_4_0, hw_compat_4_0_len); ++ spapr_machine_5_1_class_options(mc); ++ compat_props_add(mc->compat_props, hw_compat_5_0, hw_compat_5_0_len); } --DEFINE_SPAPR_MACHINE(4_0, "4.0", true); -+DEFINE_SPAPR_MACHINE(4_0, "4.0", false); +-DEFINE_SPAPR_MACHINE(5_0, "5.0", true); ++DEFINE_SPAPR_MACHINE(5_0, "5.0", false); /* - * pseries-3.1 + * pseries-4.2 diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c -index d11069b860..02470e78c7 100644 +index 45292fb5a8..f660070d22 100644 --- a/hw/s390x/s390-virtio-ccw.c +++ b/hw/s390x/s390-virtio-ccw.c -@@ -646,14 +646,26 @@ bool css_migration_enabled(void) +@@ -801,14 +801,26 @@ bool css_migration_enabled(void) } \ type_init(ccw_machine_register_##suffix) -+static void ccw_machine_4_1_instance_options(MachineState *machine) ++static void ccw_machine_5_1_instance_options(MachineState *machine) +{ +} + -+static void ccw_machine_4_1_class_options(MachineClass *mc) ++static void ccw_machine_5_1_class_options(MachineClass *mc) +{ +} -+DEFINE_CCW_MACHINE(4_1, "4.1", true); ++DEFINE_CCW_MACHINE(5_1, "5.1", true); + - static void ccw_machine_4_0_instance_options(MachineState *machine) + static void ccw_machine_5_0_instance_options(MachineState *machine) { -+ ccw_machine_4_1_instance_options(machine); ++ ccw_machine_5_1_instance_options(machine); } - static void ccw_machine_4_0_class_options(MachineClass *mc) + static void ccw_machine_5_0_class_options(MachineClass *mc) { -+ ccw_machine_4_1_class_options(mc); -+ compat_props_add(mc->compat_props, hw_compat_4_0, hw_compat_4_0_len); ++ ccw_machine_5_1_class_options(mc); ++ compat_props_add(mc->compat_props, hw_compat_5_0, hw_compat_5_0_len); } --DEFINE_CCW_MACHINE(4_0, "4.0", true); -+DEFINE_CCW_MACHINE(4_0, "4.0", false); +-DEFINE_CCW_MACHINE(5_0, "5.0", true); ++DEFINE_CCW_MACHINE(5_0, "5.0", false); - static void ccw_machine_3_1_instance_options(MachineState *machine) + static void ccw_machine_4_2_instance_options(MachineState *machine) { diff --git a/include/hw/boards.h b/include/hw/boards.h -index e231860666..fe1885cbff 100644 +index fd4d62b501..18815d9be2 100644 --- a/include/hw/boards.h +++ b/include/hw/boards.h -@@ -293,6 +293,9 @@ struct MachineState { +@@ -318,6 +318,9 @@ struct MachineState { } \ type_init(machine_initfn##_register_types) -+extern GlobalProperty hw_compat_4_0[]; -+extern const size_t hw_compat_4_0_len; ++extern GlobalProperty hw_compat_5_0[]; ++extern const size_t hw_compat_5_0_len; + - extern GlobalProperty hw_compat_3_1[]; - extern const size_t hw_compat_3_1_len; + extern GlobalProperty hw_compat_4_2[]; + extern const size_t hw_compat_4_2_len; diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h -index ca65ef18af..43df7230a2 100644 +index 05e19455bb..8d764f965c 100644 --- a/include/hw/i386/pc.h +++ b/include/hw/i386/pc.h -@@ -293,6 +293,9 @@ int e820_add_entry(uint64_t, uint64_t, uint32_t); - int e820_get_num_entries(void); - bool e820_get_entry(int, uint32_t, uint64_t *, uint64_t *); +@@ -191,6 +191,9 @@ void pc_system_firmware_init(PCMachineState *pcms, MemoryRegion *rom_memory); + void pc_madt_cpu_entry(AcpiDeviceIf *adev, int uid, + const CPUArchIdList *apic_ids, GArray *entry); -+extern GlobalProperty pc_compat_4_0[]; -+extern const size_t pc_compat_4_0_len; ++extern GlobalProperty pc_compat_5_0[]; ++extern const size_t pc_compat_5_0_len; + - extern GlobalProperty pc_compat_3_1[]; - extern const size_t pc_compat_3_1_len; + extern GlobalProperty pc_compat_4_2[]; + extern const size_t pc_compat_4_2_len; -- -2.19.1 +2.23.0 diff --git a/hw-arm-bcm2835-Drop-futile-attempts-at-QOM-adopting-.patch b/hw-arm-bcm2835-Drop-futile-attempts-at-QOM-adopting-.patch new file mode 100644 index 0000000000000000000000000000000000000000..c24ac9eab24119d6c8a1f5d69049a3b83ffab6d5 --- /dev/null +++ b/hw-arm-bcm2835-Drop-futile-attempts-at-QOM-adopting-.patch @@ -0,0 +1,47 @@ +From 5462cc8110845f88ae80b82799121d15c9c3a8fc Mon Sep 17 00:00:00 2001 +From: Markus Armbruster +Date: Tue, 5 May 2020 17:29:20 +0200 +Subject: [PATCH 474/709] hw/arm/bcm2835: Drop futile attempts at QOM-adopting + memory +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The "bcm2835-peripherals" device's .instance_init() method +bcm2835_peripherals_init() attempts to make two memory regions QOM +children of the device. This is futile, because memory_region_init() +already did. The errors are ignored (a later commit will change +that). Drop the useless calls. + +Cc: Peter Maydell +Cc: Andrew Baumann +Cc: "Philippe Mathieu-Daudé" +Cc: qemu-arm@nongnu.org +Signed-off-by: Markus Armbruster +Reviewed-by: Philippe Mathieu-Daudé +Reviewed-by: Eric Blake +Message-Id: <20200505152926.18877-13-armbru@redhat.com> +--- + hw/arm/bcm2835_peripherals.c | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/hw/arm/bcm2835_peripherals.c b/hw/arm/bcm2835_peripherals.c +index edcaa4916d..8b399d67ff 100644 +--- a/hw/arm/bcm2835_peripherals.c ++++ b/hw/arm/bcm2835_peripherals.c +@@ -43,12 +43,10 @@ static void bcm2835_peripherals_init(Object *obj) + + /* Memory region for peripheral devices, which we export to our parent */ + memory_region_init(&s->peri_mr, obj,"bcm2835-peripherals", 0x1000000); +- object_property_add_child(obj, "peripheral-io", OBJECT(&s->peri_mr), NULL); + sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->peri_mr); + + /* Internal memory region for peripheral bus addresses (not exported) */ + memory_region_init(&s->gpu_bus_mr, obj, "bcm2835-gpu", (uint64_t)1 << 32); +- object_property_add_child(obj, "gpu-bus", OBJECT(&s->gpu_bus_mr), NULL); + + /* Internal memory region for request/response communication with + * mailbox-addressable peripherals (not exported) +-- +2.23.0 + diff --git a/hw-arm-expose-host-CPU-frequency-info-to-guest.patch b/hw-arm-expose-host-CPU-frequency-info-to-guest.patch deleted file mode 100644 index 0b04076e5478d671dc55937313d677e603d23720..0000000000000000000000000000000000000000 --- a/hw-arm-expose-host-CPU-frequency-info-to-guest.patch +++ /dev/null @@ -1,606 +0,0 @@ -From 773b25c55c7428b64d21b23a6b08fc629a665ca5 Mon Sep 17 00:00:00 2001 -From: zhanghailiang -Date: Mon, 29 Jul 2019 09:54:43 +0800 -Subject: [PATCH] hw/arm: expose host CPU frequency info to guest - -On ARM64, CPU frequency is fetched by ACPI CPPC, so we add virtual -CPPC registers and ACPI _CPC objects. - -The default frequency is set to the nominal frequency of Hi1616, which -will not support CPPC in future. On Hi1620 we are fetching the value -from Host CPPC sys file. - -All performance data are set to the same value for we don't support -guest initiating performance scaling. - -We don't emulate performance counters and simply return 1 for all -counter readings, and guest Linux should fall back to use the desired -performance value as the current performance. - -Signed-off-by: Heyi Guo -Signed-off-by: zhanghailiang ---- - default-configs/aarch64-softmmu.mak | 1 + - hw/acpi/Makefile.objs | 1 + - hw/acpi/aml-build.c | 22 +++ - hw/acpi/cpufreq.c | 278 ++++++++++++++++++++++++++++ - hw/arm/virt-acpi-build.c | 78 +++++++- - hw/arm/virt.c | 13 ++ - hw/char/Kconfig | 4 + - include/hw/acpi/acpi-defs.h | 38 ++++ - include/hw/acpi/aml-build.h | 3 + - include/hw/arm/virt.h | 1 + - 10 files changed, 437 insertions(+), 2 deletions(-) - create mode 100644 hw/acpi/cpufreq.c - -diff --git a/default-configs/aarch64-softmmu.mak b/default-configs/aarch64-softmmu.mak -index 4ea9add0..37399c14 100644 ---- a/default-configs/aarch64-softmmu.mak -+++ b/default-configs/aarch64-softmmu.mak -@@ -10,3 +10,4 @@ CONFIG_XLNX_ZYNQMP=y - CONFIG_XLNX_ZYNQMP_ARM=y - CONFIG_XLNX_VERSAL=y - CONFIG_ARM_SMMUV3=y -+CONFIG_CPUFREQ=y -diff --git a/hw/acpi/Makefile.objs b/hw/acpi/Makefile.objs -index 2d46e378..60979db9 100644 ---- a/hw/acpi/Makefile.objs -+++ b/hw/acpi/Makefile.objs -@@ -12,6 +12,7 @@ common-obj-y += acpi_interface.o - common-obj-y += bios-linker-loader.o - common-obj-y += aml-build.o - common-obj-$(CONFIG_TPM) += tpm.o -+common-obj-$(CONFIG_CPUFREQ) += cpufreq.o - - common-obj-$(CONFIG_IPMI) += ipmi.o - common-obj-$(call lnot,$(CONFIG_IPMI)) += ipmi-stub.o -diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c -index 555c24f2..73f97751 100644 ---- a/hw/acpi/aml-build.c -+++ b/hw/acpi/aml-build.c -@@ -1369,6 +1369,28 @@ Aml *aml_sleep(uint64_t msec) - return var; - } - -+/* ACPI 5.0b: 6.4.3.7 Generic Register Descriptor */ -+Aml *aml_generic_register(AmlRegionSpace rs, uint8_t reg_width, -+ uint8_t reg_offset, AmlAccessType type, uint64_t addr) -+{ -+ int i; -+ Aml *var = aml_alloc(); -+ build_append_byte(var->buf, 0x82); /* Generic Register Descriptor */ -+ build_append_byte(var->buf, 0x0C); /* Length, bits[7:0] value = 0x0C */ -+ build_append_byte(var->buf, 0); /* Length, bits[15:8] value = 0 */ -+ build_append_byte(var->buf, rs); /* Address Space ID */ -+ build_append_byte(var->buf, reg_width); /* Register Bit Width */ -+ build_append_byte(var->buf, reg_offset); /* Register Bit Offset */ -+ build_append_byte(var->buf, type); /* Access Size */ -+ -+ /* Register address */ -+ for (i = 0; i < 8; i++) { -+ build_append_byte(var->buf, extract64(addr, i * 8, 8)); -+ } -+ -+ return var; -+} -+ - static uint8_t Hex2Byte(const char *src) - { - int hi, lo; -diff --git a/hw/acpi/cpufreq.c b/hw/acpi/cpufreq.c -new file mode 100644 -index 00000000..c123a22b ---- /dev/null -+++ b/hw/acpi/cpufreq.c -@@ -0,0 +1,278 @@ -+/* -+ * ACPI CPPC register device -+ * -+ * Support for showing CPU frequency in guest OS. -+ * -+ * Copyright (c) 2019 HUAWEI TECHNOLOGIES CO.,LTD. -+ * -+ * 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 . -+ */ -+ -+#include "qemu/osdep.h" -+#include "hw/sysbus.h" -+#include "chardev/char.h" -+#include "qemu/log.h" -+#include "trace.h" -+#include "qemu/option.h" -+#include "sysemu/sysemu.h" -+#include "hw/acpi/acpi-defs.h" -+#include "qemu/cutils.h" -+#include "qemu/error-report.h" -+ -+#define TYPE_CPUFREQ "cpufreq" -+#define CPUFREQ(obj) OBJECT_CHECK(CpuhzState, (obj), TYPE_CPUFREQ) -+#define NOMINAL_FREQ_FILE "/sys/devices/system/cpu/cpu0/acpi_cppc/nominal_freq" -+#define CPU_MAX_FREQ_FILE "/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq" -+#define HZ_MAX_LENGTH 1024 -+#define MAX_SUPPORT_SPACE 0x10000 -+ -+/* -+ * Since Hi1616 will not support CPPC, we simply use its nominal frequency as -+ * the default. -+ */ -+#define DEFAULT_HZ 2400 -+ -+ -+int cppc_regs_offset[CPPC_REG_COUNT] = { -+ [HIGHEST_PERF] = 0, -+ [NOMINAL_PERF] = 4, -+ [LOW_NON_LINEAR_PERF] = 8, -+ [LOWEST_PERF] = 12, -+ [GUARANTEED_PERF] = 16, -+ [DESIRED_PERF] = 20, -+ [MIN_PERF] = -1, -+ [MAX_PERF] = -1, -+ [PERF_REDUC_TOLERANCE] = -1, -+ [TIME_WINDOW] = -1, -+ [CTR_WRAP_TIME] = -1, -+ [REFERENCE_CTR] = 24, -+ [DELIVERED_CTR] = 32, -+ [PERF_LIMITED] = 40, -+ [ENABLE] = -1, -+ [AUTO_SEL_ENABLE] = -1, -+ [AUTO_ACT_WINDOW] = -1, -+ [ENERGY_PERF] = -1, -+ [REFERENCE_PERF] = -1, -+ [LOWEST_FREQ] = 44, -+ [NOMINAL_FREQ] = 48, -+}; -+ -+typedef struct CpuhzState { -+ SysBusDevice parent_obj; -+ -+ MemoryRegion iomem; -+ uint32_t HighestPerformance; -+ uint32_t NominalPerformance; -+ uint32_t LowestNonlinearPerformance; -+ uint32_t LowestPerformance; -+ uint32_t GuaranteedPerformance; -+ uint32_t DesiredPerformance; -+ uint64_t ReferencePerformanceCounter; -+ uint64_t DeliveredPerformanceCounter; -+ uint32_t PerformanceLimited; -+ uint32_t LowestFreq; -+ uint32_t NominalFreq; -+ uint32_t reg_size; -+} CpuhzState; -+ -+ -+static uint64_t cpufreq_read(void *opaque, hwaddr offset, -+ unsigned size) -+{ -+ CpuhzState *s = (CpuhzState *)opaque; -+ uint64_t r; -+ uint64_t n; -+ -+ if (offset >= smp_cpus * CPPC_REG_PER_CPU_STRIDE) { -+ warn_report("cpufreq_read: offset 0x%lx out of range", offset); -+ return 0; -+ } -+ -+ n = offset % CPPC_REG_PER_CPU_STRIDE; -+ switch (n) { -+ case 0: -+ r = s->HighestPerformance; -+ break; -+ case 4: -+ r = s->NominalPerformance; -+ break; -+ case 8: -+ r = s->LowestNonlinearPerformance; -+ break; -+ case 12: -+ r = s->LowestPerformance; -+ break; -+ case 16: -+ r = s->GuaranteedPerformance; -+ break; -+ case 20: -+ r = s->DesiredPerformance; -+ break; -+ /* -+ * We don't have real counters and it is hard to emulate, so always set the -+ * counter value to 1 to rely on Linux to use the DesiredPerformance value -+ * directly. -+ */ -+ case 24: -+ r = s->ReferencePerformanceCounter; -+ break; -+ /* -+ * Guest may still access the register by 32bit; add the process to -+ * eliminate unnecessary warnings -+ */ -+ case 28: -+ r = s->ReferencePerformanceCounter >> 32; -+ break; -+ case 32: -+ r = s->DeliveredPerformanceCounter; -+ break; -+ case 36: -+ r = s->DeliveredPerformanceCounter >> 32; -+ break; -+ -+ case 40: -+ r = s->PerformanceLimited; -+ break; -+ case 44: -+ r = s->LowestFreq; -+ break; -+ case 48: -+ r = s->NominalFreq; -+ break; -+ default: -+ error_printf("cpufreq_read: Bad offset 0x%lx\n", offset); -+ r = 0; -+ break; -+ } -+ return r; -+} -+ -+ -+static void cpufreq_write(void *opaque, hwaddr offset, -+ uint64_t value, unsigned size) -+{ -+ uint64_t n; -+ -+ if (offset >= smp_cpus * CPPC_REG_PER_CPU_STRIDE) { -+ error_printf("cpufreq_write: offset 0x%lx out of range", offset); -+ return; -+ } -+ -+ n = offset % CPPC_REG_PER_CPU_STRIDE; -+ -+ switch (n) { -+ case 20: -+ break; -+ default: -+ error_printf("cpufreq_write: Bad offset 0x%lx\n", offset); -+ } -+} -+ -+static uint32_t CPPC_Read(const char *hostpath) -+{ -+ int fd; -+ char buffer[HZ_MAX_LENGTH] = { 0 }; -+ uint64_t hz; -+ int len; -+ const char *endptr = NULL; -+ int ret; -+ -+ fd = qemu_open(hostpath, O_RDONLY); -+ if (fd < 0) { -+ return 0; -+ } -+ -+ len = read(fd, buffer, HZ_MAX_LENGTH); -+ qemu_close(fd); -+ if (len <= 0) { -+ return 0; -+ } -+ ret = qemu_strtoul(buffer, &endptr, 0, &hz); -+ if (ret < 0) { -+ return 0; -+ } -+ return (uint32_t)hz; -+} -+ -+static const MemoryRegionOps cpufreq_ops = { -+ .read = cpufreq_read, -+ .write = cpufreq_write, -+ .endianness = DEVICE_NATIVE_ENDIAN, -+}; -+ -+static void hz_init(CpuhzState *s) -+{ -+ uint32_t hz; -+ -+ hz = CPPC_Read(NOMINAL_FREQ_FILE); -+ if (hz == 0) { -+ hz = CPPC_Read(CPU_MAX_FREQ_FILE); -+ if (hz == 0) { -+ hz = DEFAULT_HZ; -+ } else { -+ /* Value in CpuMaxFrequency is in KHz unit; convert to MHz */ -+ hz = hz / 1000; -+ } -+ } -+ -+ s->HighestPerformance = hz; -+ s->NominalPerformance = hz; -+ s->LowestNonlinearPerformance = hz; -+ s->LowestPerformance = hz; -+ s->GuaranteedPerformance = hz; -+ s->DesiredPerformance = hz; -+ s->ReferencePerformanceCounter = 1; -+ s->DeliveredPerformanceCounter = 1; -+ s->PerformanceLimited = 0; -+ s->LowestFreq = hz; -+ s->NominalFreq = hz; -+} -+ -+static void cpufreq_init(Object *obj) -+{ -+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj); -+ CpuhzState *s = CPUFREQ(obj); -+ -+ s->reg_size = smp_cpus * CPPC_REG_PER_CPU_STRIDE; -+ if (s->reg_size > MAX_SUPPORT_SPACE) { -+ error_report("Required space 0x%x excesses the max support 0x%x", -+ s->reg_size, MAX_SUPPORT_SPACE); -+ goto err_end; -+ } -+ -+ memory_region_init_io(&s->iomem, OBJECT(s), &cpufreq_ops, s, "cpufreq", -+ s->reg_size); -+ sysbus_init_mmio(sbd, &s->iomem); -+ hz_init(s); -+ return; -+ -+err_end: -+ /* Set desired perf register offset to -1 to indicate no support for CPPC */ -+ cppc_regs_offset[DESIRED_PERF] = -1; -+} -+ -+static const TypeInfo cpufreq_arm_info = { -+ .name = TYPE_CPUFREQ, -+ .parent = TYPE_SYS_BUS_DEVICE, -+ .instance_size = sizeof(CpuhzState), -+ .instance_init = cpufreq_init, -+}; -+ -+static void cpufreq_register_types(void) -+{ -+ type_register_static(&cpufreq_arm_info); -+} -+ -+type_init(cpufreq_register_types) -+ -diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c -index bf9c0bc2..33a8e2e3 100644 ---- a/hw/arm/virt-acpi-build.c -+++ b/hw/arm/virt-acpi-build.c -@@ -45,11 +45,73 @@ - #include "hw/arm/virt.h" - #include "sysemu/numa.h" - #include "kvm_arm.h" -+#include "hw/acpi/acpi-defs.h" - - #define ARM_SPI_BASE 32 - #define ACPI_POWER_BUTTON_DEVICE "PWRB" - --static void acpi_dsdt_add_cpus(Aml *scope, int smp_cpus) -+static void acpi_dsdt_add_psd(Aml *dev, int cpus) -+{ -+ Aml *pkg; -+ Aml *sub; -+ -+ sub = aml_package(5); -+ aml_append(sub, aml_int(5)); -+ aml_append(sub, aml_int(0)); -+ /* Assume all vCPUs belong to the same domain */ -+ aml_append(sub, aml_int(0)); -+ /* SW_ANY: OSPM coordinate, initiate on any processor */ -+ aml_append(sub, aml_int(0xFD)); -+ aml_append(sub, aml_int(cpus)); -+ -+ pkg = aml_package(1); -+ aml_append(pkg, sub); -+ -+ aml_append(dev, aml_name_decl("_PSD", pkg)); -+} -+ -+static void acpi_dsdt_add_cppc(Aml *dev, uint64_t cpu_base, int *regs_offset) -+{ -+ Aml *cpc; -+ int i; -+ -+ /* Use version 3 of CPPC table from ACPI 6.3 */ -+ cpc = aml_package(23); -+ aml_append(cpc, aml_int(23)); -+ aml_append(cpc, aml_int(3)); -+ -+ for (i = 0; i < CPPC_REG_COUNT; i++) { -+ Aml *res; -+ uint8_t reg_width; -+ uint8_t acc_type; -+ uint64_t addr; -+ -+ if (regs_offset[i] == -1) { -+ reg_width = 0; -+ acc_type = AML_ANY_ACC; -+ addr = 0; -+ } else { -+ addr = cpu_base + regs_offset[i]; -+ if (i == REFERENCE_CTR || i == DELIVERED_CTR) { -+ reg_width = 64; -+ acc_type = AML_QWORD_ACC; -+ } else { -+ reg_width = 32; -+ acc_type = AML_DWORD_ACC; -+ } -+ } -+ -+ res = aml_resource_template(); -+ aml_append(res, aml_generic_register(AML_SYSTEM_MEMORY, reg_width, 0, -+ acc_type, addr)); -+ aml_append(cpc, res); -+ } -+ -+ aml_append(dev, aml_name_decl("_CPC", cpc)); -+} -+ -+static void acpi_dsdt_add_cpus(Aml *scope, int smp_cpus, -+ const MemMapEntry *cppc_memmap) - { - uint16_t i; - -@@ -57,6 +119,18 @@ static void acpi_dsdt_add_cpus(Aml *scope, int smp_cpus) - Aml *dev = aml_device("C%.03X", i); - aml_append(dev, aml_name_decl("_HID", aml_string("ACPI0007"))); - aml_append(dev, aml_name_decl("_UID", aml_int(i))); -+ -+ /* -+ * Append _CPC and _PSD to support CPU frequence show -+ * Check CPPC available by DESIRED_PERF register -+ */ -+ if (cppc_regs_offset[DESIRED_PERF] != -1) { -+ acpi_dsdt_add_cppc(dev, -+ cppc_memmap->base + i * CPPC_REG_PER_CPU_STRIDE, -+ cppc_regs_offset); -+ acpi_dsdt_add_psd(dev, smp_cpus); -+ } -+ - aml_append(scope, dev); - } - } -@@ -740,7 +814,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) - * the RTC ACPI device at all when using UEFI. - */ - scope = aml_scope("\\_SB"); -- acpi_dsdt_add_cpus(scope, vms->smp_cpus); -+ acpi_dsdt_add_cpus(scope, vms->smp_cpus, &memmap[VIRT_CPUFREQ]); - acpi_dsdt_add_uart(scope, &memmap[VIRT_UART], - (irqmap[VIRT_UART] + ARM_SPI_BASE)); - acpi_dsdt_add_flash(scope, &memmap[VIRT_FLASH]); -diff --git a/hw/arm/virt.c b/hw/arm/virt.c -index ce2664a3..ec6f00ab 100644 ---- a/hw/arm/virt.c -+++ b/hw/arm/virt.c -@@ -132,6 +132,7 @@ static const MemMapEntry base_memmap[] = { - [VIRT_SECURE_UART] = { 0x09040000, 0x00001000 }, - [VIRT_SMMU] = { 0x09050000, 0x00020000 }, - [VIRT_MMIO] = { 0x0a000000, 0x00000200 }, -+ [VIRT_CPUFREQ] = { 0x0b000000, 0x00010000 }, - /* ...repeating for a total of NUM_VIRTIO_TRANSPORTS, each of that size */ - [VIRT_PLATFORM_BUS] = { 0x0c000000, 0x02000000 }, - [VIRT_SECURE_MEM] = { 0x0e000000, 0x01000000 }, -@@ -725,6 +726,16 @@ static void create_uart(const VirtMachineState *vms, qemu_irq *pic, int uart, - g_free(nodename); - } - -+static void create_cpufreq(const VirtMachineState *vms, MemoryRegion *mem) -+{ -+ hwaddr base = vms->memmap[VIRT_CPUFREQ].base; -+ DeviceState *dev = qdev_create(NULL, "cpufreq"); -+ SysBusDevice *s = SYS_BUS_DEVICE(dev); -+ -+ qdev_init_nofail(dev); -+ memory_region_add_subregion(mem, base, sysbus_mmio_get_region(s, 0)); -+} -+ - static void create_rtc(const VirtMachineState *vms, qemu_irq *pic) - { - char *nodename; -@@ -1618,6 +1629,8 @@ static void machvirt_init(MachineState *machine) - - create_uart(vms, pic, VIRT_UART, sysmem, serial_hd(0)); - -+ create_cpufreq(vms, sysmem); -+ - if (vms->secure) { - create_secure_ram(vms, secure_sysmem); - create_uart(vms, pic, VIRT_SECURE_UART, secure_sysmem, serial_hd(1)); -diff --git a/hw/char/Kconfig b/hw/char/Kconfig -index 6360c9ff..8cc3ae2a 100644 ---- a/hw/char/Kconfig -+++ b/hw/char/Kconfig -@@ -40,3 +40,7 @@ config SCLPCONSOLE - - config TERMINAL3270 - bool -+ -+config CPUFREQ -+ bool -+ default y -diff --git a/include/hw/acpi/acpi-defs.h b/include/hw/acpi/acpi-defs.h -index f9aa4bd3..b4899a32 100644 ---- a/include/hw/acpi/acpi-defs.h -+++ b/include/hw/acpi/acpi-defs.h -@@ -652,4 +652,42 @@ struct AcpiIortRC { - } QEMU_PACKED; - typedef struct AcpiIortRC AcpiIortRC; - -+/* -+ * CPPC register definition from kernel header -+ * include/acpi/cppc_acpi.h -+ * The last element is newly added for easy use -+ */ -+enum cppc_regs { -+ HIGHEST_PERF, -+ NOMINAL_PERF, -+ LOW_NON_LINEAR_PERF, -+ LOWEST_PERF, -+ GUARANTEED_PERF, -+ DESIRED_PERF, -+ MIN_PERF, -+ MAX_PERF, -+ PERF_REDUC_TOLERANCE, -+ TIME_WINDOW, -+ CTR_WRAP_TIME, -+ REFERENCE_CTR, -+ DELIVERED_CTR, -+ PERF_LIMITED, -+ ENABLE, -+ AUTO_SEL_ENABLE, -+ AUTO_ACT_WINDOW, -+ ENERGY_PERF, -+ REFERENCE_PERF, -+ LOWEST_FREQ, -+ NOMINAL_FREQ, -+ CPPC_REG_COUNT, -+}; -+ -+#define CPPC_REG_PER_CPU_STRIDE 0x40 -+ -+/* -+ * Offset for each CPPC register; -1 for unavailable -+ * The whole register space is unavailable if desired perf offset is -1. -+ */ -+extern int cppc_regs_offset[CPPC_REG_COUNT]; -+ - #endif -diff --git a/include/hw/acpi/aml-build.h b/include/hw/acpi/aml-build.h -index 1a563ad7..375335ab 100644 ---- a/include/hw/acpi/aml-build.h -+++ b/include/hw/acpi/aml-build.h -@@ -347,6 +347,9 @@ Aml *aml_qword_memory(AmlDecode dec, AmlMinFixed min_fixed, - Aml *aml_dma(AmlDmaType typ, AmlDmaBusMaster bm, AmlTransferSize sz, - uint8_t channel); - Aml *aml_sleep(uint64_t msec); -+Aml *aml_generic_register(AmlRegionSpace rs, uint8_t reg_width, -+ uint8_t reg_offset, AmlAccessType type, -+ uint64_t addr); - - /* Block AML object primitives */ - Aml *aml_scope(const char *name_format, ...) GCC_FMT_ATTR(1, 2); -diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h -index 507517c6..8465f9bd 100644 ---- a/include/hw/arm/virt.h -+++ b/include/hw/arm/virt.h -@@ -66,6 +66,7 @@ enum { - VIRT_GIC_REDIST, - VIRT_SMMU, - VIRT_UART, -+ VIRT_CPUFREQ, - VIRT_MMIO, - VIRT_RTC, - VIRT_FW_CFG, --- -2.19.1 - diff --git a/hw-arm-fsl-imx25-Wire-up-watchdog.patch b/hw-arm-fsl-imx25-Wire-up-watchdog.patch new file mode 100644 index 0000000000000000000000000000000000000000..0e767c63b11dcce64820f6e7a5f8b96b6f3414f3 --- /dev/null +++ b/hw-arm-fsl-imx25-Wire-up-watchdog.patch @@ -0,0 +1,100 @@ +From 4f0aff00f964721f8a5917240abbf23d9918069b Mon Sep 17 00:00:00 2001 +From: Guenter Roeck +Date: Sun, 17 May 2020 09:21:30 -0700 +Subject: [PATCH 620/709] hw/arm/fsl-imx25: Wire up watchdog +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +With this commit, the watchdog on imx25-pdk is fully operational, +including pretimeout support. + +Reviewed-by: Philippe Mathieu-Daudé +Signed-off-by: Guenter Roeck +Message-id: 20200517162135.110364-4-linux@roeck-us.net +Signed-off-by: Peter Maydell +--- + hw/arm/Kconfig | 1 + + hw/arm/fsl-imx25.c | 10 ++++++++++ + include/hw/arm/fsl-imx25.h | 5 +++++ + 3 files changed, 16 insertions(+) + +diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig +index 3d05dc8538..8a5eb140f5 100644 +--- a/hw/arm/Kconfig ++++ b/hw/arm/Kconfig +@@ -359,6 +359,7 @@ config FSL_IMX25 + select IMX + select IMX_FEC + select IMX_I2C ++ select WDT_IMX2 + select DS1338 + + config FSL_IMX31 +diff --git a/hw/arm/fsl-imx25.c b/hw/arm/fsl-imx25.c +index 6f1a82ce3d..cdaa79c26b 100644 +--- a/hw/arm/fsl-imx25.c ++++ b/hw/arm/fsl-imx25.c +@@ -87,6 +87,7 @@ static void fsl_imx25_init(Object *obj) + TYPE_CHIPIDEA); + } + ++ sysbus_init_child_obj(obj, "wdt", &s->wdt, sizeof(s->wdt), TYPE_IMX2_WDT); + } + + static void fsl_imx25_realize(DeviceState *dev, Error **errp) +@@ -302,6 +303,15 @@ static void fsl_imx25_realize(DeviceState *dev, Error **errp) + usb_table[i].irq)); + } + ++ /* Watchdog */ ++ object_property_set_bool(OBJECT(&s->wdt), true, "pretimeout-support", ++ &error_abort); ++ object_property_set_bool(OBJECT(&s->wdt), true, "realized", &error_abort); ++ sysbus_mmio_map(SYS_BUS_DEVICE(&s->wdt), 0, FSL_IMX25_WDT_ADDR); ++ sysbus_connect_irq(SYS_BUS_DEVICE(&s->wdt), 0, ++ qdev_get_gpio_in(DEVICE(&s->avic), ++ FSL_IMX25_WDT_IRQ)); ++ + /* initialize 2 x 16 KB ROM */ + memory_region_init_rom(&s->rom[0], OBJECT(dev), "imx25.rom0", + FSL_IMX25_ROM0_SIZE, &err); +diff --git a/include/hw/arm/fsl-imx25.h b/include/hw/arm/fsl-imx25.h +index 5e196bbf05..9e228dacea 100644 +--- a/include/hw/arm/fsl-imx25.h ++++ b/include/hw/arm/fsl-imx25.h +@@ -29,6 +29,7 @@ + #include "hw/gpio/imx_gpio.h" + #include "hw/sd/sdhci.h" + #include "hw/usb/chipidea.h" ++#include "hw/watchdog/wdt_imx2.h" + #include "exec/memory.h" + #include "target/arm/cpu.h" + +@@ -60,6 +61,7 @@ typedef struct FslIMX25State { + IMXGPIOState gpio[FSL_IMX25_NUM_GPIOS]; + SDHCIState esdhc[FSL_IMX25_NUM_ESDHCS]; + ChipideaState usb[FSL_IMX25_NUM_USBS]; ++ IMX2WdtState wdt; + MemoryRegion rom[2]; + MemoryRegion iram; + MemoryRegion iram_alias; +@@ -229,6 +231,8 @@ typedef struct FslIMX25State { + #define FSL_IMX25_GPIO1_SIZE 0x4000 + #define FSL_IMX25_GPIO2_ADDR 0x53FD0000 + #define FSL_IMX25_GPIO2_SIZE 0x4000 ++#define FSL_IMX25_WDT_ADDR 0x53FDC000 ++#define FSL_IMX25_WDT_SIZE 0x4000 + #define FSL_IMX25_USB1_ADDR 0x53FF4000 + #define FSL_IMX25_USB1_SIZE 0x0200 + #define FSL_IMX25_USB2_ADDR 0x53FF4400 +@@ -268,5 +272,6 @@ typedef struct FslIMX25State { + #define FSL_IMX25_ESDHC2_IRQ 8 + #define FSL_IMX25_USB1_IRQ 37 + #define FSL_IMX25_USB2_IRQ 35 ++#define FSL_IMX25_WDT_IRQ 55 + + #endif /* FSL_IMX25_H */ +-- +2.23.0 + diff --git a/hw-arm-fsl-imx31-Wire-up-watchdog.patch b/hw-arm-fsl-imx31-Wire-up-watchdog.patch new file mode 100644 index 0000000000000000000000000000000000000000..2626fc1a8f54aa2a9c3d497181a9efc74670d01a --- /dev/null +++ b/hw-arm-fsl-imx31-Wire-up-watchdog.patch @@ -0,0 +1,88 @@ +From b9e521dda3e6f8246d9ca3285ca372462e94c6d1 Mon Sep 17 00:00:00 2001 +From: Guenter Roeck +Date: Sun, 17 May 2020 09:21:31 -0700 +Subject: [PATCH 621/709] hw/arm/fsl-imx31: Wire up watchdog +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +With this patch, the watchdog on i.MX31 emulations is fully operational. + +Reviewed-by: Philippe Mathieu-Daudé +Signed-off-by: Guenter Roeck +Message-id: 20200517162135.110364-5-linux@roeck-us.net +Signed-off-by: Peter Maydell +--- + hw/arm/Kconfig | 1 + + hw/arm/fsl-imx31.c | 6 ++++++ + include/hw/arm/fsl-imx31.h | 4 ++++ + 3 files changed, 11 insertions(+) + +diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig +index 8a5eb140f5..9afa6eee79 100644 +--- a/hw/arm/Kconfig ++++ b/hw/arm/Kconfig +@@ -367,6 +367,7 @@ config FSL_IMX31 + select SERIAL + select IMX + select IMX_I2C ++ select WDT_IMX2 + select LAN9118 + + config FSL_IMX6 +diff --git a/hw/arm/fsl-imx31.c b/hw/arm/fsl-imx31.c +index 8472d2e911..1e7959863d 100644 +--- a/hw/arm/fsl-imx31.c ++++ b/hw/arm/fsl-imx31.c +@@ -63,6 +63,8 @@ static void fsl_imx31_init(Object *obj) + sysbus_init_child_obj(obj, "gpio[*]", &s->gpio[i], sizeof(s->gpio[i]), + TYPE_IMX_GPIO); + } ++ ++ sysbus_init_child_obj(obj, "wdt", &s->wdt, sizeof(s->wdt), TYPE_IMX2_WDT); + } + + static void fsl_imx31_realize(DeviceState *dev, Error **errp) +@@ -205,6 +207,10 @@ static void fsl_imx31_realize(DeviceState *dev, Error **errp) + gpio_table[i].irq)); + } + ++ /* Watchdog */ ++ object_property_set_bool(OBJECT(&s->wdt), true, "realized", &error_abort); ++ sysbus_mmio_map(SYS_BUS_DEVICE(&s->wdt), 0, FSL_IMX31_WDT_ADDR); ++ + /* On a real system, the first 16k is a `secure boot rom' */ + memory_region_init_rom(&s->secure_rom, OBJECT(dev), "imx31.secure_rom", + FSL_IMX31_SECURE_ROM_SIZE, &err); +diff --git a/include/hw/arm/fsl-imx31.h b/include/hw/arm/fsl-imx31.h +index ac5ca9826a..dd8561b309 100644 +--- a/include/hw/arm/fsl-imx31.h ++++ b/include/hw/arm/fsl-imx31.h +@@ -25,6 +25,7 @@ + #include "hw/timer/imx_epit.h" + #include "hw/i2c/imx_i2c.h" + #include "hw/gpio/imx_gpio.h" ++#include "hw/watchdog/wdt_imx2.h" + #include "exec/memory.h" + #include "target/arm/cpu.h" + +@@ -49,6 +50,7 @@ typedef struct FslIMX31State { + IMXEPITState epit[FSL_IMX31_NUM_EPITS]; + IMXI2CState i2c[FSL_IMX31_NUM_I2CS]; + IMXGPIOState gpio[FSL_IMX31_NUM_GPIOS]; ++ IMX2WdtState wdt; + MemoryRegion secure_rom; + MemoryRegion rom; + MemoryRegion iram; +@@ -87,6 +89,8 @@ typedef struct FslIMX31State { + #define FSL_IMX31_GPIO1_SIZE 0x4000 + #define FSL_IMX31_GPIO2_ADDR 0x53FD0000 + #define FSL_IMX31_GPIO2_SIZE 0x4000 ++#define FSL_IMX31_WDT_ADDR 0x53FDC000 ++#define FSL_IMX31_WDT_SIZE 0x4000 + #define FSL_IMX31_AVIC_ADDR 0x68000000 + #define FSL_IMX31_AVIC_SIZE 0x100 + #define FSL_IMX31_SDRAM0_ADDR 0x80000000 +-- +2.23.0 + diff --git a/hw-arm-fsl-imx6-Connect-watchdog-interrupts.patch b/hw-arm-fsl-imx6-Connect-watchdog-interrupts.patch new file mode 100644 index 0000000000000000000000000000000000000000..72c9ca80479b09803c48b584b491e8b9e597887e --- /dev/null +++ b/hw-arm-fsl-imx6-Connect-watchdog-interrupts.patch @@ -0,0 +1,47 @@ +From bd8045a7044acd78ea5102404a9c16403933ce01 Mon Sep 17 00:00:00 2001 +From: Guenter Roeck +Date: Sun, 17 May 2020 09:21:32 -0700 +Subject: [PATCH 622/709] hw/arm/fsl-imx6: Connect watchdog interrupts +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +With this patch applied, the watchdog in the sabrelite emulation +is fully operational, including pretimeout support. + +Reviewed-by: Philippe Mathieu-Daudé +Signed-off-by: Guenter Roeck +Message-id: 20200517162135.110364-6-linux@roeck-us.net +Signed-off-by: Peter Maydell +--- + hw/arm/fsl-imx6.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/hw/arm/fsl-imx6.c b/hw/arm/fsl-imx6.c +index 13f1bf23a6..f58c85aa8c 100644 +--- a/hw/arm/fsl-imx6.c ++++ b/hw/arm/fsl-imx6.c +@@ -433,11 +433,20 @@ static void fsl_imx6_realize(DeviceState *dev, Error **errp) + FSL_IMX6_WDOG1_ADDR, + FSL_IMX6_WDOG2_ADDR, + }; ++ static const int FSL_IMX6_WDOGn_IRQ[FSL_IMX6_NUM_WDTS] = { ++ FSL_IMX6_WDOG1_IRQ, ++ FSL_IMX6_WDOG2_IRQ, ++ }; + ++ object_property_set_bool(OBJECT(&s->wdt[i]), true, "pretimeout-support", ++ &error_abort); + object_property_set_bool(OBJECT(&s->wdt[i]), true, "realized", + &error_abort); + + sysbus_mmio_map(SYS_BUS_DEVICE(&s->wdt[i]), 0, FSL_IMX6_WDOGn_ADDR[i]); ++ sysbus_connect_irq(SYS_BUS_DEVICE(&s->wdt[i]), 0, ++ qdev_get_gpio_in(DEVICE(&s->a9mpcore), ++ FSL_IMX6_WDOGn_IRQ[i])); + } + + /* ROM memory */ +-- +2.23.0 + diff --git a/hw-arm-fsl-imx6ul-Connect-watchdog-interrupts.patch b/hw-arm-fsl-imx6ul-Connect-watchdog-interrupts.patch new file mode 100644 index 0000000000000000000000000000000000000000..97356e2c329fe6b7e6fa60334e612b25984f6998 --- /dev/null +++ b/hw-arm-fsl-imx6ul-Connect-watchdog-interrupts.patch @@ -0,0 +1,49 @@ +From 5671e960e2d8ea83405fe408b6b613f20985f87e Mon Sep 17 00:00:00 2001 +From: Guenter Roeck +Date: Sun, 17 May 2020 09:21:33 -0700 +Subject: [PATCH 623/709] hw/arm/fsl-imx6ul: Connect watchdog interrupts +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +With this commit, the watchdog on mcimx6ul-evk is fully operational, +including pretimeout support. + +Reviewed-by: Philippe Mathieu-Daudé +Signed-off-by: Guenter Roeck +Message-id: 20200517162135.110364-7-linux@roeck-us.net +Signed-off-by: Peter Maydell +--- + hw/arm/fsl-imx6ul.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/hw/arm/fsl-imx6ul.c b/hw/arm/fsl-imx6ul.c +index 56dfd7cecc..3ecb212da6 100644 +--- a/hw/arm/fsl-imx6ul.c ++++ b/hw/arm/fsl-imx6ul.c +@@ -531,12 +531,22 @@ static void fsl_imx6ul_realize(DeviceState *dev, Error **errp) + FSL_IMX6UL_WDOG2_ADDR, + FSL_IMX6UL_WDOG3_ADDR, + }; ++ static const int FSL_IMX6UL_WDOGn_IRQ[FSL_IMX6UL_NUM_WDTS] = { ++ FSL_IMX6UL_WDOG1_IRQ, ++ FSL_IMX6UL_WDOG2_IRQ, ++ FSL_IMX6UL_WDOG3_IRQ, ++ }; + ++ object_property_set_bool(OBJECT(&s->wdt[i]), true, "pretimeout-support", ++ &error_abort); + object_property_set_bool(OBJECT(&s->wdt[i]), true, "realized", + &error_abort); + + sysbus_mmio_map(SYS_BUS_DEVICE(&s->wdt[i]), 0, + FSL_IMX6UL_WDOGn_ADDR[i]); ++ sysbus_connect_irq(SYS_BUS_DEVICE(&s->wdt[i]), 0, ++ qdev_get_gpio_in(DEVICE(&s->a7mpcore), ++ FSL_IMX6UL_WDOGn_IRQ[i])); + } + + /* +-- +2.23.0 + diff --git a/hw-arm-fsl-imx7-Connect-watchdog-interrupts.patch b/hw-arm-fsl-imx7-Connect-watchdog-interrupts.patch new file mode 100644 index 0000000000000000000000000000000000000000..05474ef312a5ce9b334d5cd320ab35bc40af93b0 --- /dev/null +++ b/hw-arm-fsl-imx7-Connect-watchdog-interrupts.patch @@ -0,0 +1,64 @@ +From c4947e64efcd8abeb6fde4bcd983f7f022c0e9f5 Mon Sep 17 00:00:00 2001 +From: Guenter Roeck +Date: Sun, 17 May 2020 09:21:35 -0700 +Subject: [PATCH 625/709] hw/arm/fsl-imx7: Connect watchdog interrupts + +i.MX7 supports watchdog pretimeout interupts. With this commit, +the watchdog in mcimx7d-sabre is fully operational, including +pretimeout support. + +Reviewed-by: Peter Maydell +Signed-off-by: Guenter Roeck +Message-id: 20200517162135.110364-9-linux@roeck-us.net +Signed-off-by: Peter Maydell +--- + hw/arm/fsl-imx7.c | 11 +++++++++++ + include/hw/arm/fsl-imx7.h | 5 +++++ + 2 files changed, 16 insertions(+) + +diff --git a/hw/arm/fsl-imx7.c b/hw/arm/fsl-imx7.c +index d6cf7c48ce..89c3b64c06 100644 +--- a/hw/arm/fsl-imx7.c ++++ b/hw/arm/fsl-imx7.c +@@ -447,11 +447,22 @@ static void fsl_imx7_realize(DeviceState *dev, Error **errp) + FSL_IMX7_WDOG3_ADDR, + FSL_IMX7_WDOG4_ADDR, + }; ++ static const int FSL_IMX7_WDOGn_IRQ[FSL_IMX7_NUM_WDTS] = { ++ FSL_IMX7_WDOG1_IRQ, ++ FSL_IMX7_WDOG2_IRQ, ++ FSL_IMX7_WDOG3_IRQ, ++ FSL_IMX7_WDOG4_IRQ, ++ }; + ++ object_property_set_bool(OBJECT(&s->wdt[i]), true, "pretimeout-support", ++ &error_abort); + object_property_set_bool(OBJECT(&s->wdt[i]), true, "realized", + &error_abort); + + sysbus_mmio_map(SYS_BUS_DEVICE(&s->wdt[i]), 0, FSL_IMX7_WDOGn_ADDR[i]); ++ sysbus_connect_irq(SYS_BUS_DEVICE(&s->wdt[i]), 0, ++ qdev_get_gpio_in(DEVICE(&s->a7mpcore), ++ FSL_IMX7_WDOGn_IRQ[i])); + } + + /* +diff --git a/include/hw/arm/fsl-imx7.h b/include/hw/arm/fsl-imx7.h +index 47826da2b7..da977f9ffb 100644 +--- a/include/hw/arm/fsl-imx7.h ++++ b/include/hw/arm/fsl-imx7.h +@@ -228,6 +228,11 @@ enum FslIMX7IRQs { + FSL_IMX7_USB2_IRQ = 42, + FSL_IMX7_USB3_IRQ = 40, + ++ FSL_IMX7_WDOG1_IRQ = 78, ++ FSL_IMX7_WDOG2_IRQ = 79, ++ FSL_IMX7_WDOG3_IRQ = 10, ++ FSL_IMX7_WDOG4_IRQ = 109, ++ + FSL_IMX7_PCI_INTA_IRQ = 125, + FSL_IMX7_PCI_INTB_IRQ = 124, + FSL_IMX7_PCI_INTC_IRQ = 123, +-- +2.23.0 + diff --git a/hw-arm-fsl-imx7-Instantiate-various-unimplemented-de.patch b/hw-arm-fsl-imx7-Instantiate-various-unimplemented-de.patch new file mode 100644 index 0000000000000000000000000000000000000000..6ecead4932d16c31fb1607f60324774fb3525122 --- /dev/null +++ b/hw-arm-fsl-imx7-Instantiate-various-unimplemented-de.patch @@ -0,0 +1,95 @@ +From 72465e1ebaa6c850dbc099c6bb301d548bfea92b Mon Sep 17 00:00:00 2001 +From: Guenter Roeck +Date: Sun, 17 May 2020 09:21:34 -0700 +Subject: [PATCH 624/709] hw/arm/fsl-imx7: Instantiate various unimplemented + devices + +Instantiating PWM, CAN, CAAM, and OCOTP devices is necessary to avoid +crashes when booting mainline Linux. + +Reviewed-by: Peter Maydell +Signed-off-by: Guenter Roeck +Message-id: 20200517162135.110364-8-linux@roeck-us.net +Signed-off-by: Peter Maydell +--- + hw/arm/fsl-imx7.c | 24 ++++++++++++++++++++++++ + include/hw/arm/fsl-imx7.h | 16 ++++++++++++++++ + 2 files changed, 40 insertions(+) + +diff --git a/hw/arm/fsl-imx7.c b/hw/arm/fsl-imx7.c +index 119b281a50..d6cf7c48ce 100644 +--- a/hw/arm/fsl-imx7.c ++++ b/hw/arm/fsl-imx7.c +@@ -459,6 +459,30 @@ static void fsl_imx7_realize(DeviceState *dev, Error **errp) + */ + create_unimplemented_device("sdma", FSL_IMX7_SDMA_ADDR, FSL_IMX7_SDMA_SIZE); + ++ /* ++ * CAAM ++ */ ++ create_unimplemented_device("caam", FSL_IMX7_CAAM_ADDR, FSL_IMX7_CAAM_SIZE); ++ ++ /* ++ * PWM ++ */ ++ create_unimplemented_device("pwm1", FSL_IMX7_PWM1_ADDR, FSL_IMX7_PWMn_SIZE); ++ create_unimplemented_device("pwm2", FSL_IMX7_PWM2_ADDR, FSL_IMX7_PWMn_SIZE); ++ create_unimplemented_device("pwm3", FSL_IMX7_PWM3_ADDR, FSL_IMX7_PWMn_SIZE); ++ create_unimplemented_device("pwm4", FSL_IMX7_PWM4_ADDR, FSL_IMX7_PWMn_SIZE); ++ ++ /* ++ * CAN ++ */ ++ create_unimplemented_device("can1", FSL_IMX7_CAN1_ADDR, FSL_IMX7_CANn_SIZE); ++ create_unimplemented_device("can2", FSL_IMX7_CAN2_ADDR, FSL_IMX7_CANn_SIZE); ++ ++ /* ++ * OCOTP ++ */ ++ create_unimplemented_device("ocotp", FSL_IMX7_OCOTP_ADDR, ++ FSL_IMX7_OCOTP_SIZE); + + object_property_set_bool(OBJECT(&s->gpr), true, "realized", + &error_abort); +diff --git a/include/hw/arm/fsl-imx7.h b/include/hw/arm/fsl-imx7.h +index 3a0041c4c2..47826da2b7 100644 +--- a/include/hw/arm/fsl-imx7.h ++++ b/include/hw/arm/fsl-imx7.h +@@ -113,6 +113,9 @@ enum FslIMX7MemoryMap { + FSL_IMX7_IOMUXC_GPR_ADDR = 0x30340000, + FSL_IMX7_IOMUXCn_SIZE = 0x1000, + ++ FSL_IMX7_OCOTP_ADDR = 0x30350000, ++ FSL_IMX7_OCOTP_SIZE = 0x10000, ++ + FSL_IMX7_ANALOG_ADDR = 0x30360000, + FSL_IMX7_SNVS_ADDR = 0x30370000, + FSL_IMX7_CCM_ADDR = 0x30380000, +@@ -124,11 +127,24 @@ enum FslIMX7MemoryMap { + FSL_IMX7_ADC2_ADDR = 0x30620000, + FSL_IMX7_ADCn_SIZE = 0x1000, + ++ FSL_IMX7_PWM1_ADDR = 0x30660000, ++ FSL_IMX7_PWM2_ADDR = 0x30670000, ++ FSL_IMX7_PWM3_ADDR = 0x30680000, ++ FSL_IMX7_PWM4_ADDR = 0x30690000, ++ FSL_IMX7_PWMn_SIZE = 0x10000, ++ + FSL_IMX7_PCIE_PHY_ADDR = 0x306D0000, + FSL_IMX7_PCIE_PHY_SIZE = 0x10000, + + FSL_IMX7_GPC_ADDR = 0x303A0000, + ++ FSL_IMX7_CAAM_ADDR = 0x30900000, ++ FSL_IMX7_CAAM_SIZE = 0x40000, ++ ++ FSL_IMX7_CAN1_ADDR = 0x30A00000, ++ FSL_IMX7_CAN2_ADDR = 0x30A10000, ++ FSL_IMX7_CANn_SIZE = 0x10000, ++ + FSL_IMX7_I2C1_ADDR = 0x30A20000, + FSL_IMX7_I2C2_ADDR = 0x30A30000, + FSL_IMX7_I2C3_ADDR = 0x30A40000, +-- +2.23.0 + diff --git a/hw-arm-integratorcp-Replace-hw_error-by-qemu_log_mas.patch b/hw-arm-integratorcp-Replace-hw_error-by-qemu_log_mas.patch new file mode 100644 index 0000000000000000000000000000000000000000..9ab205a1a1bc32cfbb70851b16e8ce868af2a3b8 --- /dev/null +++ b/hw-arm-integratorcp-Replace-hw_error-by-qemu_log_mas.patch @@ -0,0 +1,102 @@ +From 9904625f1b54190bc6d9c098c2e0d969e67014cf Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Mon, 18 May 2020 16:03:06 +0200 +Subject: [PATCH 626/709] hw/arm/integratorcp: Replace hw_error() by + qemu_log_mask() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +hw_error() calls exit(). This a bit overkill when we can log +the accesses as unimplemented or guest error. + +When fuzzing the devices, we don't want the whole process to +exit. Replace some hw_error() calls by qemu_log_mask(). + +Signed-off-by: Philippe Mathieu-Daudé +Reviewed-by: Alistair Francis +Message-id: 20200518140309.5220-2-f4bug@amsat.org +Signed-off-by: Peter Maydell +--- + hw/arm/integratorcp.c | 23 +++++++++++++++-------- + 1 file changed, 15 insertions(+), 8 deletions(-) + +diff --git a/hw/arm/integratorcp.c b/hw/arm/integratorcp.c +index 6d69010d06..5fb54e5aa7 100644 +--- a/hw/arm/integratorcp.c ++++ b/hw/arm/integratorcp.c +@@ -20,6 +20,7 @@ + #include "exec/address-spaces.h" + #include "sysemu/runstate.h" + #include "sysemu/sysemu.h" ++#include "qemu/log.h" + #include "qemu/error-report.h" + #include "hw/char/pl011.h" + #include "hw/hw.h" +@@ -144,8 +145,9 @@ static uint64_t integratorcm_read(void *opaque, hwaddr offset, + /* ??? Voltage control unimplemented. */ + return 0; + default: +- hw_error("integratorcm_read: Unimplemented offset 0x%x\n", +- (int)offset); ++ qemu_log_mask(LOG_UNIMP, ++ "%s: Unimplemented offset 0x%" HWADDR_PRIX "\n", ++ __func__, offset); + return 0; + } + } +@@ -252,8 +254,9 @@ static void integratorcm_write(void *opaque, hwaddr offset, + /* ??? Voltage control unimplemented. */ + break; + default: +- hw_error("integratorcm_write: Unimplemented offset 0x%x\n", +- (int)offset); ++ qemu_log_mask(LOG_UNIMP, ++ "%s: Unimplemented offset 0x%" HWADDR_PRIX "\n", ++ __func__, offset); + break; + } + } +@@ -394,7 +397,8 @@ static uint64_t icp_pic_read(void *opaque, hwaddr offset, + case 5: /* INT_SOFTCLR */ + case 11: /* FRQ_ENABLECLR */ + default: +- printf ("icp_pic_read: Bad register offset 0x%x\n", (int)offset); ++ qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIX "\n", ++ __func__, offset); + return 0; + } + } +@@ -430,7 +434,8 @@ static void icp_pic_write(void *opaque, hwaddr offset, + case 8: /* FRQ_STATUS */ + case 9: /* FRQ_RAWSTAT */ + default: +- printf ("icp_pic_write: Bad register offset 0x%x\n", (int)offset); ++ qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIX "\n", ++ __func__, offset); + return; + } + icp_pic_update(s); +@@ -504,7 +509,8 @@ static uint64_t icp_control_read(void *opaque, hwaddr offset, + case 3: /* CP_DECODE */ + return 0x11; + default: +- hw_error("icp_control_read: Bad offset %x\n", (int)offset); ++ qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIX "\n", ++ __func__, offset); + return 0; + } + } +@@ -524,7 +530,8 @@ static void icp_control_write(void *opaque, hwaddr offset, + /* Nothing interesting implemented yet. */ + break; + default: +- hw_error("icp_control_write: Bad offset %x\n", (int)offset); ++ qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIX "\n", ++ __func__, offset); + } + } + +-- +2.23.0 + diff --git a/hw-arm-mps2-tz-Use-TYPE_IOTKIT-instead-of-hardcoded-.patch b/hw-arm-mps2-tz-Use-TYPE_IOTKIT-instead-of-hardcoded-.patch new file mode 100644 index 0000000000000000000000000000000000000000..9bc9db889b76c5e257dbc7f1a6e0b719e629d81d --- /dev/null +++ b/hw-arm-mps2-tz-Use-TYPE_IOTKIT-instead-of-hardcoded-.patch @@ -0,0 +1,37 @@ +From 2e256c04c1852efd6a9b48e61fbcaced4b074c4e Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Tue, 28 Apr 2020 17:46:50 +0200 +Subject: [PATCH 150/709] hw/arm/mps2-tz: Use TYPE_IOTKIT instead of hardcoded + string +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +By using the TYPE_* definitions for devices, we can: + - quickly find where devices are used with 'git-grep' + - easily rename a device (one-line change). + +Signed-off-by: Philippe Mathieu-Daudé +Message-id: 20200428154650.21991-1-f4bug@amsat.org +Reviewed-by: Peter Maydell +Signed-off-by: Peter Maydell +--- + hw/arm/mps2-tz.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c +index a8dea7dde1..2c43041564 100644 +--- a/hw/arm/mps2-tz.c ++++ b/hw/arm/mps2-tz.c +@@ -395,7 +395,7 @@ static void mps2tz_common_init(MachineState *machine) + exit(EXIT_FAILURE); + } + +- sysbus_init_child_obj(OBJECT(machine), "iotkit", &mms->iotkit, ++ sysbus_init_child_obj(OBJECT(machine), TYPE_IOTKIT, &mms->iotkit, + sizeof(mms->iotkit), mmc->armsse_type); + iotkitdev = DEVICE(&mms->iotkit); + object_property_set_link(OBJECT(&mms->iotkit), OBJECT(system_memory), +-- +2.23.0 + diff --git a/hw-arm-musicpal-Map-the-UART-devices-unconditionally.patch b/hw-arm-musicpal-Map-the-UART-devices-unconditionally.patch new file mode 100644 index 0000000000000000000000000000000000000000..cbc2bda0f60171cef68a8e80623e89bd050de15f --- /dev/null +++ b/hw-arm-musicpal-Map-the-UART-devices-unconditionally.patch @@ -0,0 +1,48 @@ +From 4758567bc00ee52e0861202206f4b8fab5e1af90 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Tue, 5 May 2020 11:59:45 +0200 +Subject: [PATCH 389/709] hw/arm/musicpal: Map the UART devices unconditionally +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +I can't find proper documentation or datasheet, but it is likely +a MMIO mapped serial device mapped in the 0x80000000..0x8000ffff +range belongs to the SoC address space, thus is always mapped in +the memory bus. +Map the devices on the bus regardless a chardev is attached to it. + +Signed-off-by: Philippe Mathieu-Daudé +Reviewed-by: Jan Kiszka +Message-id: 20200505095945.23146-1-f4bug@amsat.org +Signed-off-by: Peter Maydell +--- + hw/arm/musicpal.c | 12 ++++-------- + 1 file changed, 4 insertions(+), 8 deletions(-) + +diff --git a/hw/arm/musicpal.c b/hw/arm/musicpal.c +index b2d0cfdac8..92f33ed87e 100644 +--- a/hw/arm/musicpal.c ++++ b/hw/arm/musicpal.c +@@ -1619,14 +1619,10 @@ static void musicpal_init(MachineState *machine) + pic[MP_TIMER2_IRQ], pic[MP_TIMER3_IRQ], + pic[MP_TIMER4_IRQ], NULL); + +- if (serial_hd(0)) { +- serial_mm_init(address_space_mem, MP_UART1_BASE, 2, pic[MP_UART1_IRQ], +- 1825000, serial_hd(0), DEVICE_NATIVE_ENDIAN); +- } +- if (serial_hd(1)) { +- serial_mm_init(address_space_mem, MP_UART2_BASE, 2, pic[MP_UART2_IRQ], +- 1825000, serial_hd(1), DEVICE_NATIVE_ENDIAN); +- } ++ serial_mm_init(address_space_mem, MP_UART1_BASE, 2, pic[MP_UART1_IRQ], ++ 1825000, serial_hd(0), DEVICE_NATIVE_ENDIAN); ++ serial_mm_init(address_space_mem, MP_UART2_BASE, 2, pic[MP_UART2_IRQ], ++ 1825000, serial_hd(1), DEVICE_NATIVE_ENDIAN); + + /* Register flash */ + dinfo = drive_get(IF_PFLASH, 0, 0); +-- +2.23.0 + diff --git a/hw-arm-nrf51-Add-NRF51_PERIPHERAL_SIZE-definition.patch b/hw-arm-nrf51-Add-NRF51_PERIPHERAL_SIZE-definition.patch new file mode 100644 index 0000000000000000000000000000000000000000..1a968bf3680bed43b57c7912207be64401f735a2 --- /dev/null +++ b/hw-arm-nrf51-Add-NRF51_PERIPHERAL_SIZE-definition.patch @@ -0,0 +1,104 @@ +From 54595a5731ed7c94491008b0d3835ad3f786dbcc Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Mon, 4 May 2020 09:28:19 +0200 +Subject: [PATCH 362/709] hw/arm/nrf51: Add NRF51_PERIPHERAL_SIZE definition +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +On the NRF51 series, all peripherals have a fixed I/O size +of 4KiB. Define NRF51_PERIPHERAL_SIZE and use it. + +Signed-off-by: Philippe Mathieu-Daudé +Reviewed-by: Richard Henderson +Message-id: 20200504072822.18799-2-f4bug@amsat.org +Signed-off-by: Peter Maydell +--- + hw/arm/nrf51_soc.c | 4 ++-- + hw/i2c/microbit_i2c.c | 2 +- + hw/timer/nrf51_timer.c | 2 +- + include/hw/arm/nrf51.h | 3 +-- + include/hw/i2c/microbit_i2c.h | 2 +- + 5 files changed, 6 insertions(+), 7 deletions(-) + +diff --git a/hw/arm/nrf51_soc.c b/hw/arm/nrf51_soc.c +index 57eff63f0d..e50473fd19 100644 +--- a/hw/arm/nrf51_soc.c ++++ b/hw/arm/nrf51_soc.c +@@ -156,7 +156,7 @@ static void nrf51_soc_realize(DeviceState *dev_soc, Error **errp) + return; + } + +- base_addr = NRF51_TIMER_BASE + i * NRF51_TIMER_SIZE; ++ base_addr = NRF51_TIMER_BASE + i * NRF51_PERIPHERAL_SIZE; + + sysbus_mmio_map(SYS_BUS_DEVICE(&s->timer[i]), 0, base_addr); + sysbus_connect_irq(SYS_BUS_DEVICE(&s->timer[i]), 0, +@@ -166,7 +166,7 @@ static void nrf51_soc_realize(DeviceState *dev_soc, Error **errp) + + /* STUB Peripherals */ + memory_region_init_io(&s->clock, OBJECT(dev_soc), &clock_ops, NULL, +- "nrf51_soc.clock", 0x1000); ++ "nrf51_soc.clock", NRF51_PERIPHERAL_SIZE); + memory_region_add_subregion_overlap(&s->container, + NRF51_IOMEM_BASE, &s->clock, -1); + +diff --git a/hw/i2c/microbit_i2c.c b/hw/i2c/microbit_i2c.c +index 4661f05253..8024739820 100644 +--- a/hw/i2c/microbit_i2c.c ++++ b/hw/i2c/microbit_i2c.c +@@ -100,7 +100,7 @@ static void microbit_i2c_realize(DeviceState *dev, Error **errp) + MicrobitI2CState *s = MICROBIT_I2C(dev); + + memory_region_init_io(&s->iomem, OBJECT(s), µbit_i2c_ops, s, +- "microbit.twi", NRF51_TWI_SIZE); ++ "microbit.twi", NRF51_PERIPHERAL_SIZE); + sysbus_init_mmio(sbd, &s->iomem); + } + +diff --git a/hw/timer/nrf51_timer.c b/hw/timer/nrf51_timer.c +index e04046eb15..bc82c85a6f 100644 +--- a/hw/timer/nrf51_timer.c ++++ b/hw/timer/nrf51_timer.c +@@ -313,7 +313,7 @@ static void nrf51_timer_init(Object *obj) + SysBusDevice *sbd = SYS_BUS_DEVICE(obj); + + memory_region_init_io(&s->iomem, obj, &rng_ops, s, +- TYPE_NRF51_TIMER, NRF51_TIMER_SIZE); ++ TYPE_NRF51_TIMER, NRF51_PERIPHERAL_SIZE); + sysbus_init_mmio(sbd, &s->iomem); + sysbus_init_irq(sbd, &s->irq); + +diff --git a/include/hw/arm/nrf51.h b/include/hw/arm/nrf51.h +index 1008fee6c9..de836beaa4 100644 +--- a/include/hw/arm/nrf51.h ++++ b/include/hw/arm/nrf51.h +@@ -24,11 +24,10 @@ + #define NRF51_IOMEM_BASE 0x40000000 + #define NRF51_IOMEM_SIZE 0x20000000 + ++#define NRF51_PERIPHERAL_SIZE 0x00001000 + #define NRF51_UART_BASE 0x40002000 + #define NRF51_TWI_BASE 0x40003000 +-#define NRF51_TWI_SIZE 0x00001000 + #define NRF51_TIMER_BASE 0x40008000 +-#define NRF51_TIMER_SIZE 0x00001000 + #define NRF51_RNG_BASE 0x4000D000 + #define NRF51_NVMC_BASE 0x4001E000 + #define NRF51_GPIO_BASE 0x50000000 +diff --git a/include/hw/i2c/microbit_i2c.h b/include/hw/i2c/microbit_i2c.h +index aad636127e..2bff36680c 100644 +--- a/include/hw/i2c/microbit_i2c.h ++++ b/include/hw/i2c/microbit_i2c.h +@@ -29,7 +29,7 @@ + #define MICROBIT_I2C(obj) \ + OBJECT_CHECK(MicrobitI2CState, (obj), TYPE_MICROBIT_I2C) + +-#define MICROBIT_I2C_NREGS (NRF51_TWI_SIZE / sizeof(uint32_t)) ++#define MICROBIT_I2C_NREGS (NRF51_PERIPHERAL_SIZE / sizeof(uint32_t)) + + typedef struct { + SysBusDevice parent_obj; +-- +2.23.0 + diff --git a/hw-arm-pxa2xx-Replace-hw_error-by-qemu_log_mask.patch b/hw-arm-pxa2xx-Replace-hw_error-by-qemu_log_mask.patch new file mode 100644 index 0000000000000000000000000000000000000000..fa887b1d0c7bf19d38bc4a7844fabfe50817357e --- /dev/null +++ b/hw-arm-pxa2xx-Replace-hw_error-by-qemu_log_mask.patch @@ -0,0 +1,145 @@ +From 5a0001ec7e0a446b6da86da8ca03211aab0fcd08 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Mon, 18 May 2020 16:03:07 +0200 +Subject: [PATCH 627/709] hw/arm/pxa2xx: Replace hw_error() by qemu_log_mask() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +hw_error() calls exit(). This a bit overkill when we can log +the accesses as unimplemented or guest error. + +When fuzzing the devices, we don't want the whole process to +exit. Replace some hw_error() calls by qemu_log_mask(). + +Signed-off-by: Philippe Mathieu-Daudé +Reviewed-by: Alistair Francis +Message-id: 20200518140309.5220-3-f4bug@amsat.org +Signed-off-by: Peter Maydell +--- + hw/arm/pxa2xx_gpio.c | 7 ++++--- + hw/display/pxa2xx_lcd.c | 8 +++++--- + hw/dma/pxa2xx_dma.c | 14 +++++++++----- + 3 files changed, 18 insertions(+), 11 deletions(-) + +diff --git a/hw/arm/pxa2xx_gpio.c b/hw/arm/pxa2xx_gpio.c +index f8df3cc227..a01db54a51 100644 +--- a/hw/arm/pxa2xx_gpio.c ++++ b/hw/arm/pxa2xx_gpio.c +@@ -9,7 +9,6 @@ + + #include "qemu/osdep.h" + #include "cpu.h" +-#include "hw/hw.h" + #include "hw/irq.h" + #include "hw/qdev-properties.h" + #include "hw/sysbus.h" +@@ -199,7 +198,8 @@ static uint64_t pxa2xx_gpio_read(void *opaque, hwaddr offset, + return s->status[bank]; + + default: +- hw_error("%s: Bad offset " REG_FMT "\n", __func__, offset); ++ qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIX "\n", ++ __func__, offset); + } + + return 0; +@@ -252,7 +252,8 @@ static void pxa2xx_gpio_write(void *opaque, hwaddr offset, + break; + + default: +- hw_error("%s: Bad offset " REG_FMT "\n", __func__, offset); ++ qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIX "\n", ++ __func__, offset); + } + } + +diff --git a/hw/display/pxa2xx_lcd.c b/hw/display/pxa2xx_lcd.c +index 464e93161a..d5f2e82a4e 100644 +--- a/hw/display/pxa2xx_lcd.c ++++ b/hw/display/pxa2xx_lcd.c +@@ -11,7 +11,7 @@ + */ + + #include "qemu/osdep.h" +-#include "hw/hw.h" ++#include "qemu/log.h" + #include "hw/irq.h" + #include "migration/vmstate.h" + #include "ui/console.h" +@@ -407,7 +407,8 @@ static uint64_t pxa2xx_lcdc_read(void *opaque, hwaddr offset, + + default: + fail: +- hw_error("%s: Bad offset " REG_FMT "\n", __func__, offset); ++ qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIX "\n", ++ __func__, offset); + } + + return 0; +@@ -562,7 +563,8 @@ static void pxa2xx_lcdc_write(void *opaque, hwaddr offset, + + default: + fail: +- hw_error("%s: Bad offset " REG_FMT "\n", __func__, offset); ++ qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIX "\n", ++ __func__, offset); + } + } + +diff --git a/hw/dma/pxa2xx_dma.c b/hw/dma/pxa2xx_dma.c +index 88ed4b6ff1..8a2eeb32bc 100644 +--- a/hw/dma/pxa2xx_dma.c ++++ b/hw/dma/pxa2xx_dma.c +@@ -9,6 +9,7 @@ + */ + + #include "qemu/osdep.h" ++#include "qemu/log.h" + #include "hw/hw.h" + #include "hw/irq.h" + #include "hw/qdev-properties.h" +@@ -268,7 +269,8 @@ static uint64_t pxa2xx_dma_read(void *opaque, hwaddr offset, + unsigned int channel; + + if (size != 4) { +- hw_error("%s: Bad access width\n", __func__); ++ qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad access width %u\n", ++ __func__, size); + return 5; + } + +@@ -315,8 +317,8 @@ static uint64_t pxa2xx_dma_read(void *opaque, hwaddr offset, + return s->chan[channel].cmd; + } + } +- +- hw_error("%s: Bad offset 0x" TARGET_FMT_plx "\n", __func__, offset); ++ qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIX "\n", ++ __func__, offset); + return 7; + } + +@@ -327,7 +329,8 @@ static void pxa2xx_dma_write(void *opaque, hwaddr offset, + unsigned int channel; + + if (size != 4) { +- hw_error("%s: Bad access width\n", __func__); ++ qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad access width %u\n", ++ __func__, size); + return; + } + +@@ -420,7 +423,8 @@ static void pxa2xx_dma_write(void *opaque, hwaddr offset, + break; + } + fail: +- hw_error("%s: Bad offset " TARGET_FMT_plx "\n", __func__, offset); ++ qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIX "\n", ++ __func__, offset); + } + } + +-- +2.23.0 + diff --git a/hw-arm-versal-Add-support-for-SD.patch b/hw-arm-versal-Add-support-for-SD.patch new file mode 100644 index 0000000000000000000000000000000000000000..8bb271f0829c74d234881a0ad032784f53f899cb --- /dev/null +++ b/hw-arm-versal-Add-support-for-SD.patch @@ -0,0 +1,124 @@ +From 724c6e12dd77a5e2bacd50fd3e7fb32244b491c1 Mon Sep 17 00:00:00 2001 +From: "Edgar E. Iglesias" +Date: Mon, 27 Apr 2020 20:16:46 +0200 +Subject: [PATCH 164/709] hw/arm: versal: Add support for SD +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Add support for SD. + +Signed-off-by: Edgar E. Iglesias +Reviewed-by: Alistair Francis +Reviewed-by: Philippe Mathieu-Daudé +Reviewed-by: Luc Michel +Message-id: 20200427181649.26851-9-edgar.iglesias@gmail.com +Signed-off-by: Peter Maydell +--- + hw/arm/xlnx-versal.c | 31 +++++++++++++++++++++++++++++++ + include/hw/arm/xlnx-versal.h | 12 ++++++++++++ + 2 files changed, 43 insertions(+) + +diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c +index c8a296e2e0..e263bdf77a 100644 +--- a/hw/arm/xlnx-versal.c ++++ b/hw/arm/xlnx-versal.c +@@ -210,6 +210,36 @@ static void versal_create_admas(Versal *s, qemu_irq *pic) + } + } + ++#define SDHCI_CAPABILITIES 0x280737ec6481 /* Same as on ZynqMP. */ ++static void versal_create_sds(Versal *s, qemu_irq *pic) ++{ ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(s->pmc.iou.sd); i++) { ++ DeviceState *dev; ++ MemoryRegion *mr; ++ ++ sysbus_init_child_obj(OBJECT(s), "sd[*]", ++ &s->pmc.iou.sd[i], sizeof(s->pmc.iou.sd[i]), ++ TYPE_SYSBUS_SDHCI); ++ dev = DEVICE(&s->pmc.iou.sd[i]); ++ ++ object_property_set_uint(OBJECT(dev), ++ 3, "sd-spec-version", &error_fatal); ++ object_property_set_uint(OBJECT(dev), SDHCI_CAPABILITIES, "capareg", ++ &error_fatal); ++ object_property_set_uint(OBJECT(dev), UHS_I, "uhs", &error_fatal); ++ qdev_init_nofail(dev); ++ ++ mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0); ++ memory_region_add_subregion(&s->mr_ps, ++ MM_PMC_SD0 + i * MM_PMC_SD0_SIZE, mr); ++ ++ sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, ++ pic[VERSAL_SD0_IRQ_0 + i * 2]); ++ } ++} ++ + /* This takes the board allocated linear DDR memory and creates aliases + * for each split DDR range/aperture on the Versal address map. + */ +@@ -292,6 +322,7 @@ static void versal_realize(DeviceState *dev, Error **errp) + versal_create_uarts(s, pic); + versal_create_gems(s, pic); + versal_create_admas(s, pic); ++ versal_create_sds(s, pic); + versal_map_ddr(s); + versal_unimp(s); + +diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h +index 426b66449d..e11693e29d 100644 +--- a/include/hw/arm/xlnx-versal.h ++++ b/include/hw/arm/xlnx-versal.h +@@ -14,6 +14,7 @@ + + #include "hw/sysbus.h" + #include "hw/arm/boot.h" ++#include "hw/sd/sdhci.h" + #include "hw/intc/arm_gicv3.h" + #include "hw/char/pl011.h" + #include "hw/dma/xlnx-zdma.h" +@@ -26,6 +27,7 @@ + #define XLNX_VERSAL_NR_UARTS 2 + #define XLNX_VERSAL_NR_GEMS 2 + #define XLNX_VERSAL_NR_ADMAS 8 ++#define XLNX_VERSAL_NR_SDS 2 + #define XLNX_VERSAL_NR_IRQS 192 + + typedef struct Versal { +@@ -58,6 +60,13 @@ typedef struct Versal { + } iou; + } lpd; + ++ /* The Platform Management Controller subsystem. */ ++ struct { ++ struct { ++ SDHCIState sd[XLNX_VERSAL_NR_SDS]; ++ } iou; ++ } pmc; ++ + struct { + MemoryRegion *mr_ddr; + uint32_t psci_conduit; +@@ -80,6 +89,7 @@ typedef struct Versal { + #define VERSAL_GEM1_IRQ_0 58 + #define VERSAL_GEM1_WAKE_IRQ_0 59 + #define VERSAL_ADMA_IRQ_0 60 ++#define VERSAL_SD0_IRQ_0 126 + + /* Architecturally reserved IRQs suitable for virtualization. */ + #define VERSAL_RSVD_IRQ_FIRST 111 +@@ -129,6 +139,8 @@ typedef struct Versal { + #define MM_FPD_CRF 0xfd1a0000U + #define MM_FPD_CRF_SIZE 0x140000 + ++#define MM_PMC_SD0 0xf1040000U ++#define MM_PMC_SD0_SIZE 0x10000 + #define MM_PMC_CRP 0xf1260000U + #define MM_PMC_CRP_SIZE 0x10000 + #endif +-- +2.23.0 + diff --git a/hw-arm-versal-Add-support-for-the-RTC.patch b/hw-arm-versal-Add-support-for-the-RTC.patch new file mode 100644 index 0000000000000000000000000000000000000000..31dab1e03ceaab03cc61cf88d33e1201912b1037 --- /dev/null +++ b/hw-arm-versal-Add-support-for-the-RTC.patch @@ -0,0 +1,102 @@ +From eb1221c52de6a646942a28422a5c56c84364d5b6 Mon Sep 17 00:00:00 2001 +From: "Edgar E. Iglesias" +Date: Mon, 27 Apr 2020 20:16:47 +0200 +Subject: [PATCH 165/709] hw/arm: versal: Add support for the RTC +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +hw/arm: versal: Add support for the RTC. + +Signed-off-by: Edgar E. Iglesias +Reviewed-by: Philippe Mathieu-Daudé +Reviewed-by: Alistair Francis +Reviewed-by: Luc Michel +Message-id: 20200427181649.26851-10-edgar.iglesias@gmail.com +Signed-off-by: Peter Maydell +--- + hw/arm/xlnx-versal.c | 21 +++++++++++++++++++++ + include/hw/arm/xlnx-versal.h | 8 ++++++++ + 2 files changed, 29 insertions(+) + +diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c +index e263bdf77a..321171bcce 100644 +--- a/hw/arm/xlnx-versal.c ++++ b/hw/arm/xlnx-versal.c +@@ -240,6 +240,26 @@ static void versal_create_sds(Versal *s, qemu_irq *pic) + } + } + ++static void versal_create_rtc(Versal *s, qemu_irq *pic) ++{ ++ SysBusDevice *sbd; ++ MemoryRegion *mr; ++ ++ sysbus_init_child_obj(OBJECT(s), "rtc", &s->pmc.rtc, sizeof(s->pmc.rtc), ++ TYPE_XLNX_ZYNQMP_RTC); ++ sbd = SYS_BUS_DEVICE(&s->pmc.rtc); ++ qdev_init_nofail(DEVICE(sbd)); ++ ++ mr = sysbus_mmio_get_region(sbd, 0); ++ memory_region_add_subregion(&s->mr_ps, MM_PMC_RTC, mr); ++ ++ /* ++ * TODO: Connect the ALARM and SECONDS interrupts once our RTC model ++ * supports them. ++ */ ++ sysbus_connect_irq(sbd, 1, pic[VERSAL_RTC_APB_ERR_IRQ]); ++} ++ + /* This takes the board allocated linear DDR memory and creates aliases + * for each split DDR range/aperture on the Versal address map. + */ +@@ -323,6 +343,7 @@ static void versal_realize(DeviceState *dev, Error **errp) + versal_create_gems(s, pic); + versal_create_admas(s, pic); + versal_create_sds(s, pic); ++ versal_create_rtc(s, pic); + versal_map_ddr(s); + versal_unimp(s); + +diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h +index e11693e29d..9c9f47ba9d 100644 +--- a/include/hw/arm/xlnx-versal.h ++++ b/include/hw/arm/xlnx-versal.h +@@ -19,6 +19,7 @@ + #include "hw/char/pl011.h" + #include "hw/dma/xlnx-zdma.h" + #include "hw/net/cadence_gem.h" ++#include "hw/rtc/xlnx-zynqmp-rtc.h" + + #define TYPE_XLNX_VERSAL "xlnx-versal" + #define XLNX_VERSAL(obj) OBJECT_CHECK(Versal, (obj), TYPE_XLNX_VERSAL) +@@ -65,6 +66,8 @@ typedef struct Versal { + struct { + SDHCIState sd[XLNX_VERSAL_NR_SDS]; + } iou; ++ ++ XlnxZynqMPRTC rtc; + } pmc; + + struct { +@@ -89,7 +92,10 @@ typedef struct Versal { + #define VERSAL_GEM1_IRQ_0 58 + #define VERSAL_GEM1_WAKE_IRQ_0 59 + #define VERSAL_ADMA_IRQ_0 60 ++#define VERSAL_RTC_APB_ERR_IRQ 121 + #define VERSAL_SD0_IRQ_0 126 ++#define VERSAL_RTC_ALARM_IRQ 142 ++#define VERSAL_RTC_SECONDS_IRQ 143 + + /* Architecturally reserved IRQs suitable for virtualization. */ + #define VERSAL_RSVD_IRQ_FIRST 111 +@@ -143,4 +149,6 @@ typedef struct Versal { + #define MM_PMC_SD0_SIZE 0x10000 + #define MM_PMC_CRP 0xf1260000U + #define MM_PMC_CRP_SIZE 0x10000 ++#define MM_PMC_RTC 0xf12a0000 ++#define MM_PMC_RTC_SIZE 0x10000 + #endif +-- +2.23.0 + diff --git a/hw-arm-versal-Embed-the-ADMAs-into-the-SoC-type.patch b/hw-arm-versal-Embed-the-ADMAs-into-the-SoC-type.patch new file mode 100644 index 0000000000000000000000000000000000000000..f66ef80b4d5bbff7284d58d4545664c0a468fd7c --- /dev/null +++ b/hw-arm-versal-Embed-the-ADMAs-into-the-SoC-type.patch @@ -0,0 +1,76 @@ +From f4e3fa3726244460c1f3b52e72be6e1e9547f445 Mon Sep 17 00:00:00 2001 +From: "Edgar E. Iglesias" +Date: Mon, 27 Apr 2020 20:16:44 +0200 +Subject: [PATCH 162/709] hw/arm: versal: Embed the ADMAs into the SoC type +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Embed the ADMAs into the SoC type. + +Suggested-by: Peter Maydell +Signed-off-by: Edgar E. Iglesias +Reviewed-by: Alistair Francis +Reviewed-by: Philippe Mathieu-Daudé +Reviewed-by: Luc Michel +Message-id: 20200427181649.26851-7-edgar.iglesias@gmail.com +Signed-off-by: Peter Maydell +--- + hw/arm/xlnx-versal.c | 14 +++++++------- + include/hw/arm/xlnx-versal.h | 3 ++- + 2 files changed, 9 insertions(+), 8 deletions(-) + +diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c +index e424aa789e..ebd2dc51be 100644 +--- a/hw/arm/xlnx-versal.c ++++ b/hw/arm/xlnx-versal.c +@@ -203,18 +203,18 @@ static void versal_create_admas(Versal *s, qemu_irq *pic) + DeviceState *dev; + MemoryRegion *mr; + +- dev = qdev_create(NULL, "xlnx.zdma"); +- s->lpd.iou.adma[i] = SYS_BUS_DEVICE(dev); +- object_property_set_int(OBJECT(s->lpd.iou.adma[i]), 128, "bus-width", +- &error_abort); +- object_property_add_child(OBJECT(s), name, OBJECT(dev), &error_fatal); ++ sysbus_init_child_obj(OBJECT(s), name, ++ &s->lpd.iou.adma[i], sizeof(s->lpd.iou.adma[i]), ++ TYPE_XLNX_ZDMA); ++ dev = DEVICE(&s->lpd.iou.adma[i]); ++ object_property_set_int(OBJECT(dev), 128, "bus-width", &error_abort); + qdev_init_nofail(dev); + +- mr = sysbus_mmio_get_region(s->lpd.iou.adma[i], 0); ++ mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0); + memory_region_add_subregion(&s->mr_ps, + MM_ADMA_CH0 + i * MM_ADMA_CH0_SIZE, mr); + +- sysbus_connect_irq(s->lpd.iou.adma[i], 0, pic[VERSAL_ADMA_IRQ_0 + i]); ++ sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic[VERSAL_ADMA_IRQ_0 + i]); + g_free(name); + } + } +diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h +index 01da736a5b..94b7826fd4 100644 +--- a/include/hw/arm/xlnx-versal.h ++++ b/include/hw/arm/xlnx-versal.h +@@ -16,6 +16,7 @@ + #include "hw/arm/boot.h" + #include "hw/intc/arm_gicv3.h" + #include "hw/char/pl011.h" ++#include "hw/dma/xlnx-zdma.h" + #include "hw/net/cadence_gem.h" + + #define TYPE_XLNX_VERSAL "xlnx-versal" +@@ -53,7 +54,7 @@ typedef struct Versal { + struct { + PL011State uart[XLNX_VERSAL_NR_UARTS]; + CadenceGEMState gem[XLNX_VERSAL_NR_GEMS]; +- SysBusDevice *adma[XLNX_VERSAL_NR_ADMAS]; ++ XlnxZDMA adma[XLNX_VERSAL_NR_ADMAS]; + } iou; + } lpd; + +-- +2.23.0 + diff --git a/hw-arm-versal-Embed-the-APUs-into-the-SoC-type.patch b/hw-arm-versal-Embed-the-APUs-into-the-SoC-type.patch new file mode 100644 index 0000000000000000000000000000000000000000..e2e105c583678d4656c641f80870d5c4ac5eae6c --- /dev/null +++ b/hw-arm-versal-Embed-the-APUs-into-the-SoC-type.patch @@ -0,0 +1,100 @@ +From ced18d5e500eada554b42f39adc1f97b993bc324 Mon Sep 17 00:00:00 2001 +From: "Edgar E. Iglesias" +Date: Mon, 27 Apr 2020 20:16:45 +0200 +Subject: [PATCH 163/709] hw/arm: versal: Embed the APUs into the SoC type +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Embed the APUs into the SoC type. + +Suggested-by: Peter Maydell +Signed-off-by: Edgar E. Iglesias +Reviewed-by: Alistair Francis +Reviewed-by: Philippe Mathieu-Daudé +Reviewed-by: Luc Michel +Message-id: 20200427181649.26851-8-edgar.iglesias@gmail.com +Signed-off-by: Peter Maydell +--- + hw/arm/xlnx-versal-virt.c | 4 ++-- + hw/arm/xlnx-versal.c | 19 +++++-------------- + include/hw/arm/xlnx-versal.h | 2 +- + 3 files changed, 8 insertions(+), 17 deletions(-) + +diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c +index 8a608074d1..d7be1ad494 100644 +--- a/hw/arm/xlnx-versal-virt.c ++++ b/hw/arm/xlnx-versal-virt.c +@@ -469,9 +469,9 @@ static void versal_virt_init(MachineState *machine) + s->binfo.get_dtb = versal_virt_get_dtb; + s->binfo.modify_dtb = versal_virt_modify_dtb; + if (machine->kernel_filename) { +- arm_load_kernel(s->soc.fpd.apu.cpu[0], machine, &s->binfo); ++ arm_load_kernel(&s->soc.fpd.apu.cpu[0], machine, &s->binfo); + } else { +- AddressSpace *as = arm_boot_address_space(s->soc.fpd.apu.cpu[0], ++ AddressSpace *as = arm_boot_address_space(&s->soc.fpd.apu.cpu[0], + &s->binfo); + /* Some boot-loaders (e.g u-boot) don't like blobs at address 0 (NULL). + * Offset things by 4K. */ +diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c +index ebd2dc51be..c8a296e2e0 100644 +--- a/hw/arm/xlnx-versal.c ++++ b/hw/arm/xlnx-versal.c +@@ -31,19 +31,11 @@ static void versal_create_apu_cpus(Versal *s) + + for (i = 0; i < ARRAY_SIZE(s->fpd.apu.cpu); i++) { + Object *obj; +- char *name; +- +- obj = object_new(XLNX_VERSAL_ACPU_TYPE); +- if (!obj) { +- error_report("Unable to create apu.cpu[%d] of type %s", +- i, XLNX_VERSAL_ACPU_TYPE); +- exit(EXIT_FAILURE); +- } +- +- name = g_strdup_printf("apu-cpu[%d]", i); +- object_property_add_child(OBJECT(s), name, obj, &error_fatal); +- g_free(name); + ++ object_initialize_child(OBJECT(s), "apu-cpu[*]", ++ &s->fpd.apu.cpu[i], sizeof(s->fpd.apu.cpu[i]), ++ XLNX_VERSAL_ACPU_TYPE, &error_abort, NULL); ++ obj = OBJECT(&s->fpd.apu.cpu[i]); + object_property_set_int(obj, s->cfg.psci_conduit, + "psci-conduit", &error_abort); + if (i) { +@@ -57,7 +49,6 @@ static void versal_create_apu_cpus(Versal *s) + object_property_set_link(obj, OBJECT(&s->fpd.apu.mr), "memory", + &error_abort); + object_property_set_bool(obj, true, "realized", &error_fatal); +- s->fpd.apu.cpu[i] = ARM_CPU(obj); + } + } + +@@ -95,7 +86,7 @@ static void versal_create_apu_gic(Versal *s, qemu_irq *pic) + } + + for (i = 0; i < nr_apu_cpus; i++) { +- DeviceState *cpudev = DEVICE(s->fpd.apu.cpu[i]); ++ DeviceState *cpudev = DEVICE(&s->fpd.apu.cpu[i]); + int ppibase = XLNX_VERSAL_NR_IRQS + i * GIC_INTERNAL + GIC_NR_SGIS; + qemu_irq maint_irq; + int ti; +diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h +index 94b7826fd4..426b66449d 100644 +--- a/include/hw/arm/xlnx-versal.h ++++ b/include/hw/arm/xlnx-versal.h +@@ -36,7 +36,7 @@ typedef struct Versal { + struct { + struct { + MemoryRegion mr; +- ARMCPU *cpu[XLNX_VERSAL_NR_ACPUS]; ++ ARMCPU cpu[XLNX_VERSAL_NR_ACPUS]; + GICv3State gic; + } apu; + } fpd; +-- +2.23.0 + diff --git a/hw-arm-versal-Embed-the-GEMs-into-the-SoC-type.patch b/hw-arm-versal-Embed-the-GEMs-into-the-SoC-type.patch new file mode 100644 index 0000000000000000000000000000000000000000..90a4986354fcc7b8162c6f496fd5325d49b4ebd9 --- /dev/null +++ b/hw-arm-versal-Embed-the-GEMs-into-the-SoC-type.patch @@ -0,0 +1,84 @@ +From 4bd9b59c05bda9c5a8df84ea63292a9471120b02 Mon Sep 17 00:00:00 2001 +From: "Edgar E. Iglesias" +Date: Mon, 27 Apr 2020 20:16:43 +0200 +Subject: [PATCH 161/709] hw/arm: versal: Embed the GEMs into the SoC type +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Embed the GEMs into the SoC type. + +Suggested-by: Peter Maydell +Signed-off-by: Edgar E. Iglesias +Reviewed-by: Alistair Francis +Reviewed-by: Philippe Mathieu-Daudé +Reviewed-by: Luc Michel +Message-id: 20200427181649.26851-6-edgar.iglesias@gmail.com +Signed-off-by: Peter Maydell +--- + hw/arm/xlnx-versal.c | 15 ++++++++------- + include/hw/arm/xlnx-versal.h | 3 ++- + 2 files changed, 10 insertions(+), 8 deletions(-) + +diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c +index dbde03b7e6..e424aa789e 100644 +--- a/hw/arm/xlnx-versal.c ++++ b/hw/arm/xlnx-versal.c +@@ -170,25 +170,26 @@ static void versal_create_gems(Versal *s, qemu_irq *pic) + DeviceState *dev; + MemoryRegion *mr; + +- dev = qdev_create(NULL, "cadence_gem"); +- s->lpd.iou.gem[i] = SYS_BUS_DEVICE(dev); +- object_property_add_child(OBJECT(s), name, OBJECT(dev), &error_fatal); ++ sysbus_init_child_obj(OBJECT(s), name, ++ &s->lpd.iou.gem[i], sizeof(s->lpd.iou.gem[i]), ++ TYPE_CADENCE_GEM); ++ dev = DEVICE(&s->lpd.iou.gem[i]); + if (nd->used) { + qemu_check_nic_model(nd, "cadence_gem"); + qdev_set_nic_properties(dev, nd); + } +- object_property_set_int(OBJECT(s->lpd.iou.gem[i]), ++ object_property_set_int(OBJECT(dev), + 2, "num-priority-queues", + &error_abort); +- object_property_set_link(OBJECT(s->lpd.iou.gem[i]), ++ object_property_set_link(OBJECT(dev), + OBJECT(&s->mr_ps), "dma", + &error_abort); + qdev_init_nofail(dev); + +- mr = sysbus_mmio_get_region(s->lpd.iou.gem[i], 0); ++ mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0); + memory_region_add_subregion(&s->mr_ps, addrs[i], mr); + +- sysbus_connect_irq(s->lpd.iou.gem[i], 0, pic[irqs[i]]); ++ sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic[irqs[i]]); + g_free(name); + } + } +diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h +index a3dfd064b3..01da736a5b 100644 +--- a/include/hw/arm/xlnx-versal.h ++++ b/include/hw/arm/xlnx-versal.h +@@ -16,6 +16,7 @@ + #include "hw/arm/boot.h" + #include "hw/intc/arm_gicv3.h" + #include "hw/char/pl011.h" ++#include "hw/net/cadence_gem.h" + + #define TYPE_XLNX_VERSAL "xlnx-versal" + #define XLNX_VERSAL(obj) OBJECT_CHECK(Versal, (obj), TYPE_XLNX_VERSAL) +@@ -51,7 +52,7 @@ typedef struct Versal { + + struct { + PL011State uart[XLNX_VERSAL_NR_UARTS]; +- SysBusDevice *gem[XLNX_VERSAL_NR_GEMS]; ++ CadenceGEMState gem[XLNX_VERSAL_NR_GEMS]; + SysBusDevice *adma[XLNX_VERSAL_NR_ADMAS]; + } iou; + } lpd; +-- +2.23.0 + diff --git a/hw-arm-versal-Embed-the-UARTs-into-the-SoC-type.patch b/hw-arm-versal-Embed-the-UARTs-into-the-SoC-type.patch new file mode 100644 index 0000000000000000000000000000000000000000..e5fbd6aea0f64f8a585415e99dd8bf70e48ca1f8 --- /dev/null +++ b/hw-arm-versal-Embed-the-UARTs-into-the-SoC-type.patch @@ -0,0 +1,81 @@ +From 88052ffdd1df6cfe8160662fd4a8cc69f7be63bc Mon Sep 17 00:00:00 2001 +From: "Edgar E. Iglesias" +Date: Mon, 27 Apr 2020 20:16:42 +0200 +Subject: [PATCH 160/709] hw/arm: versal: Embed the UARTs into the SoC type +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Embed the UARTs into the SoC type. + +Suggested-by: Peter Maydell +Signed-off-by: Edgar E. Iglesias +Reviewed-by: Alistair Francis +Reviewed-by: Philippe Mathieu-Daudé +Reviewed-by: Luc Michel +Message-id: 20200427181649.26851-5-edgar.iglesias@gmail.com +Signed-off-by: Peter Maydell +--- + hw/arm/xlnx-versal.c | 12 ++++++------ + include/hw/arm/xlnx-versal.h | 3 ++- + 2 files changed, 8 insertions(+), 7 deletions(-) + +diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c +index cc696e44c0..dbde03b7e6 100644 +--- a/hw/arm/xlnx-versal.c ++++ b/hw/arm/xlnx-versal.c +@@ -21,7 +21,6 @@ + #include "kvm_arm.h" + #include "hw/misc/unimp.h" + #include "hw/arm/xlnx-versal.h" +-#include "hw/char/pl011.h" + + #define XLNX_VERSAL_ACPU_TYPE ARM_CPU_TYPE_NAME("cortex-a72") + #define GEM_REVISION 0x40070106 +@@ -144,16 +143,17 @@ static void versal_create_uarts(Versal *s, qemu_irq *pic) + DeviceState *dev; + MemoryRegion *mr; + +- dev = qdev_create(NULL, TYPE_PL011); +- s->lpd.iou.uart[i] = SYS_BUS_DEVICE(dev); ++ sysbus_init_child_obj(OBJECT(s), name, ++ &s->lpd.iou.uart[i], sizeof(s->lpd.iou.uart[i]), ++ TYPE_PL011); ++ dev = DEVICE(&s->lpd.iou.uart[i]); + qdev_prop_set_chr(dev, "chardev", serial_hd(i)); +- object_property_add_child(OBJECT(s), name, OBJECT(dev), &error_fatal); + qdev_init_nofail(dev); + +- mr = sysbus_mmio_get_region(s->lpd.iou.uart[i], 0); ++ mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0); + memory_region_add_subregion(&s->mr_ps, addrs[i], mr); + +- sysbus_connect_irq(s->lpd.iou.uart[i], 0, pic[irqs[i]]); ++ sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic[irqs[i]]); + g_free(name); + } + } +diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h +index 6c0a692b2f..a3dfd064b3 100644 +--- a/include/hw/arm/xlnx-versal.h ++++ b/include/hw/arm/xlnx-versal.h +@@ -15,6 +15,7 @@ + #include "hw/sysbus.h" + #include "hw/arm/boot.h" + #include "hw/intc/arm_gicv3.h" ++#include "hw/char/pl011.h" + + #define TYPE_XLNX_VERSAL "xlnx-versal" + #define XLNX_VERSAL(obj) OBJECT_CHECK(Versal, (obj), TYPE_XLNX_VERSAL) +@@ -49,7 +50,7 @@ typedef struct Versal { + MemoryRegion mr_ocm; + + struct { +- SysBusDevice *uart[XLNX_VERSAL_NR_UARTS]; ++ PL011State uart[XLNX_VERSAL_NR_UARTS]; + SysBusDevice *gem[XLNX_VERSAL_NR_GEMS]; + SysBusDevice *adma[XLNX_VERSAL_NR_ADMAS]; + } iou; +-- +2.23.0 + diff --git a/hw-arm-versal-Move-misplaced-comment.patch b/hw-arm-versal-Move-misplaced-comment.patch new file mode 100644 index 0000000000000000000000000000000000000000..c823978e2162d436b16da15302edbed735458f36 --- /dev/null +++ b/hw-arm-versal-Move-misplaced-comment.patch @@ -0,0 +1,43 @@ +From c07c0c37ad45c6cd1cd9ef94988a4790bb78e287 Mon Sep 17 00:00:00 2001 +From: "Edgar E. Iglesias" +Date: Mon, 27 Apr 2020 20:16:40 +0200 +Subject: [PATCH 158/709] hw/arm: versal: Move misplaced comment +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Move misplaced comment. + +Signed-off-by: Edgar E. Iglesias +Reviewed-by: Alistair Francis +Reviewed-by: Philippe Mathieu-Daudé +Reviewed-by: Luc Michel +Message-id: 20200427181649.26851-3-edgar.iglesias@gmail.com +Signed-off-by: Peter Maydell +--- + hw/arm/xlnx-versal.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c +index c73b2fe755..cc696e44c0 100644 +--- a/hw/arm/xlnx-versal.c ++++ b/hw/arm/xlnx-versal.c +@@ -36,7 +36,6 @@ static void versal_create_apu_cpus(Versal *s) + + obj = object_new(XLNX_VERSAL_ACPU_TYPE); + if (!obj) { +- /* Secondary CPUs start in PSCI powered-down state */ + error_report("Unable to create apu.cpu[%d] of type %s", + i, XLNX_VERSAL_ACPU_TYPE); + exit(EXIT_FAILURE); +@@ -49,6 +48,7 @@ static void versal_create_apu_cpus(Versal *s) + object_property_set_int(obj, s->cfg.psci_conduit, + "psci-conduit", &error_abort); + if (i) { ++ /* Secondary CPUs start in PSCI powered-down state */ + object_property_set_bool(obj, true, + "start-powered-off", &error_abort); + } +-- +2.23.0 + diff --git a/hw-arm-versal-Remove-inclusion-of-arm_gicv3_common.h.patch b/hw-arm-versal-Remove-inclusion-of-arm_gicv3_common.h.patch new file mode 100644 index 0000000000000000000000000000000000000000..4dca1823d11de941d79ffe7502011627ab625967 --- /dev/null +++ b/hw-arm-versal-Remove-inclusion-of-arm_gicv3_common.h.patch @@ -0,0 +1,33 @@ +From 5995a02511cd147212353ee377905112359b6fc1 Mon Sep 17 00:00:00 2001 +From: "Edgar E. Iglesias" +Date: Mon, 27 Apr 2020 20:16:39 +0200 +Subject: [PATCH 157/709] hw/arm: versal: Remove inclusion of + arm_gicv3_common.h + +Remove inclusion of arm_gicv3_common.h, this already gets +included via xlnx-versal.h. + +Signed-off-by: Edgar E. Iglesias +Reviewed-by: Alistair Francis +Reviewed-by: Luc Michel +Message-id: 20200427181649.26851-2-edgar.iglesias@gmail.com +Signed-off-by: Peter Maydell +--- + hw/arm/xlnx-versal.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c +index 94460f2343..c73b2fe755 100644 +--- a/hw/arm/xlnx-versal.c ++++ b/hw/arm/xlnx-versal.c +@@ -20,7 +20,6 @@ + #include "hw/arm/boot.h" + #include "kvm_arm.h" + #include "hw/misc/unimp.h" +-#include "hw/intc/arm_gicv3_common.h" + #include "hw/arm/xlnx-versal.h" + #include "hw/char/pl011.h" + +-- +2.23.0 + diff --git a/hw-arm-versal-Setup-the-ADMA-with-128bit-bus-width.patch b/hw-arm-versal-Setup-the-ADMA-with-128bit-bus-width.patch new file mode 100644 index 0000000000000000000000000000000000000000..d3f0c6aeac526c1f9bc9f697c46d7a3c10279e8a --- /dev/null +++ b/hw-arm-versal-Setup-the-ADMA-with-128bit-bus-width.patch @@ -0,0 +1,33 @@ +From 681b5bc32322fd0ff4338c550ec24612512d1a2e Mon Sep 17 00:00:00 2001 +From: "Edgar E. Iglesias" +Date: Fri, 17 Apr 2020 17:38:00 +0200 +Subject: [PATCH 111/709] hw/arm: versal: Setup the ADMA with 128bit bus-width + +Setup the ADMA with 128bit bus-width. This matters when +FIXED BURST mode is used. + +Signed-off-by: Edgar E. Iglesias +Reviewed-by: Alistair Francis +Reviewed-by: Luc Michel +Message-id: 20200417153800.27399-2-edgar.iglesias@gmail.com +Signed-off-by: Peter Maydell +--- + hw/arm/xlnx-versal.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c +index cb0122a3a6..94460f2343 100644 +--- a/hw/arm/xlnx-versal.c ++++ b/hw/arm/xlnx-versal.c +@@ -205,6 +205,8 @@ static void versal_create_admas(Versal *s, qemu_irq *pic) + + dev = qdev_create(NULL, "xlnx.zdma"); + s->lpd.iou.adma[i] = SYS_BUS_DEVICE(dev); ++ object_property_set_int(OBJECT(s->lpd.iou.adma[i]), 128, "bus-width", ++ &error_abort); + object_property_add_child(OBJECT(s), name, OBJECT(dev), &error_fatal); + qdev_init_nofail(dev); + +-- +2.23.0 + diff --git a/hw-arm-versal-virt-Add-support-for-SD.patch b/hw-arm-versal-virt-Add-support-for-SD.patch new file mode 100644 index 0000000000000000000000000000000000000000..e3aaa020be0c5c25f034ff041df9c2b1597b942e --- /dev/null +++ b/hw-arm-versal-virt-Add-support-for-SD.patch @@ -0,0 +1,108 @@ +From 3afec85c2e635d1ee06ef2884f13602db733cd5a Mon Sep 17 00:00:00 2001 +From: "Edgar E. Iglesias" +Date: Mon, 27 Apr 2020 20:16:48 +0200 +Subject: [PATCH 166/709] hw/arm: versal-virt: Add support for SD + +Add support for SD. + +Signed-off-by: Edgar E. Iglesias +Reviewed-by: Alistair Francis +Reviewed-by: Luc Michel +Message-id: 20200427181649.26851-11-edgar.iglesias@gmail.com +Signed-off-by: Peter Maydell +--- + hw/arm/xlnx-versal-virt.c | 46 +++++++++++++++++++++++++++++++++++++++ + 1 file changed, 46 insertions(+) + +diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c +index d7be1ad494..0afee48672 100644 +--- a/hw/arm/xlnx-versal-virt.c ++++ b/hw/arm/xlnx-versal-virt.c +@@ -20,6 +20,7 @@ + #include "hw/arm/sysbus-fdt.h" + #include "hw/arm/fdt.h" + #include "cpu.h" ++#include "hw/qdev-properties.h" + #include "hw/arm/xlnx-versal.h" + + #define TYPE_XLNX_VERSAL_VIRT_MACHINE MACHINE_TYPE_NAME("xlnx-versal-virt") +@@ -256,6 +257,32 @@ static void fdt_add_zdma_nodes(VersalVirt *s) + } + } + ++static void fdt_add_sd_nodes(VersalVirt *s) ++{ ++ const char clocknames[] = "clk_xin\0clk_ahb"; ++ const char compat[] = "arasan,sdhci-8.9a"; ++ int i; ++ ++ for (i = ARRAY_SIZE(s->soc.pmc.iou.sd) - 1; i >= 0; i--) { ++ uint64_t addr = MM_PMC_SD0 + MM_PMC_SD0_SIZE * i; ++ char *name = g_strdup_printf("/sdhci@%" PRIx64, addr); ++ ++ qemu_fdt_add_subnode(s->fdt, name); ++ ++ qemu_fdt_setprop_cells(s->fdt, name, "clocks", ++ s->phandle.clk_25Mhz, s->phandle.clk_25Mhz); ++ qemu_fdt_setprop(s->fdt, name, "clock-names", ++ clocknames, sizeof(clocknames)); ++ qemu_fdt_setprop_cells(s->fdt, name, "interrupts", ++ GIC_FDT_IRQ_TYPE_SPI, VERSAL_SD0_IRQ_0 + i * 2, ++ GIC_FDT_IRQ_FLAGS_LEVEL_HI); ++ qemu_fdt_setprop_sized_cells(s->fdt, name, "reg", ++ 2, addr, 2, MM_PMC_SD0_SIZE); ++ qemu_fdt_setprop(s->fdt, name, "compatible", compat, sizeof(compat)); ++ g_free(name); ++ } ++} ++ + static void fdt_nop_memory_nodes(void *fdt, Error **errp) + { + Error *err = NULL; +@@ -411,10 +438,23 @@ static void create_virtio_regions(VersalVirt *s) + } + } + ++static void sd_plugin_card(SDHCIState *sd, DriveInfo *di) ++{ ++ BlockBackend *blk = di ? blk_by_legacy_dinfo(di) : NULL; ++ DeviceState *card; ++ ++ card = qdev_create(qdev_get_child_bus(DEVICE(sd), "sd-bus"), TYPE_SD_CARD); ++ object_property_add_child(OBJECT(sd), "card[*]", OBJECT(card), ++ &error_fatal); ++ qdev_prop_set_drive(card, "drive", blk, &error_fatal); ++ object_property_set_bool(OBJECT(card), true, "realized", &error_fatal); ++} ++ + static void versal_virt_init(MachineState *machine) + { + VersalVirt *s = XLNX_VERSAL_VIRT_MACHINE(machine); + int psci_conduit = QEMU_PSCI_CONDUIT_DISABLED; ++ int i; + + /* + * If the user provides an Operating System to be loaded, we expect them +@@ -455,6 +495,7 @@ static void versal_virt_init(MachineState *machine) + fdt_add_gic_nodes(s); + fdt_add_timer_nodes(s); + fdt_add_zdma_nodes(s); ++ fdt_add_sd_nodes(s); + fdt_add_cpu_nodes(s, psci_conduit); + fdt_add_clk_node(s, "/clk125", 125000000, s->phandle.clk_125Mhz); + fdt_add_clk_node(s, "/clk25", 25000000, s->phandle.clk_25Mhz); +@@ -464,6 +505,11 @@ static void versal_virt_init(MachineState *machine) + memory_region_add_subregion_overlap(get_system_memory(), + 0, &s->soc.fpd.apu.mr, 0); + ++ /* Plugin SD cards. */ ++ for (i = 0; i < ARRAY_SIZE(s->soc.pmc.iou.sd); i++) { ++ sd_plugin_card(&s->soc.pmc.iou.sd[i], drive_get_next(IF_SD)); ++ } ++ + s->binfo.ram_size = machine->ram_size; + s->binfo.loader_start = 0x0; + s->binfo.get_dtb = versal_virt_get_dtb; +-- +2.23.0 + diff --git a/hw-arm-versal-virt-Add-support-for-the-RTC.patch b/hw-arm-versal-virt-Add-support-for-the-RTC.patch new file mode 100644 index 0000000000000000000000000000000000000000..74b53d7d3e775a0ebf559e476ed08fea7f4efd69 --- /dev/null +++ b/hw-arm-versal-virt-Add-support-for-the-RTC.patch @@ -0,0 +1,59 @@ +From 2aca5284b14b7f3bedec7c59e7cc68da26944585 Mon Sep 17 00:00:00 2001 +From: "Edgar E. Iglesias" +Date: Mon, 27 Apr 2020 20:16:49 +0200 +Subject: [PATCH 167/709] hw/arm: versal-virt: Add support for the RTC + +Add support for the RTC. + +Signed-off-by: Edgar E. Iglesias +Reviewed-by: Alistair Francis +Reviewed-by: Luc Michel +Message-id: 20200427181649.26851-12-edgar.iglesias@gmail.com +Signed-off-by: Peter Maydell +--- + hw/arm/xlnx-versal-virt.c | 22 ++++++++++++++++++++++ + 1 file changed, 22 insertions(+) + +diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c +index 0afee48672..7e749e1926 100644 +--- a/hw/arm/xlnx-versal-virt.c ++++ b/hw/arm/xlnx-versal-virt.c +@@ -283,6 +283,27 @@ static void fdt_add_sd_nodes(VersalVirt *s) + } + } + ++static void fdt_add_rtc_node(VersalVirt *s) ++{ ++ const char compat[] = "xlnx,zynqmp-rtc"; ++ const char interrupt_names[] = "alarm\0sec"; ++ char *name = g_strdup_printf("/rtc@%x", MM_PMC_RTC); ++ ++ qemu_fdt_add_subnode(s->fdt, name); ++ ++ qemu_fdt_setprop_cells(s->fdt, name, "interrupts", ++ GIC_FDT_IRQ_TYPE_SPI, VERSAL_RTC_ALARM_IRQ, ++ GIC_FDT_IRQ_FLAGS_LEVEL_HI, ++ GIC_FDT_IRQ_TYPE_SPI, VERSAL_RTC_SECONDS_IRQ, ++ GIC_FDT_IRQ_FLAGS_LEVEL_HI); ++ qemu_fdt_setprop(s->fdt, name, "interrupt-names", ++ interrupt_names, sizeof(interrupt_names)); ++ qemu_fdt_setprop_sized_cells(s->fdt, name, "reg", ++ 2, MM_PMC_RTC, 2, MM_PMC_RTC_SIZE); ++ qemu_fdt_setprop(s->fdt, name, "compatible", compat, sizeof(compat)); ++ g_free(name); ++} ++ + static void fdt_nop_memory_nodes(void *fdt, Error **errp) + { + Error *err = NULL; +@@ -496,6 +517,7 @@ static void versal_virt_init(MachineState *machine) + fdt_add_timer_nodes(s); + fdt_add_zdma_nodes(s); + fdt_add_sd_nodes(s); ++ fdt_add_rtc_node(s); + fdt_add_cpu_nodes(s, psci_conduit); + fdt_add_clk_node(s, "/clk125", 125000000, s->phandle.clk_125Mhz); + fdt_add_clk_node(s, "/clk25", 25000000, s->phandle.clk_25Mhz); +-- +2.23.0 + diff --git a/hw-arm-versal-virt-Fix-typo-xlnx-ve-xlnx-versal.patch b/hw-arm-versal-virt-Fix-typo-xlnx-ve-xlnx-versal.patch new file mode 100644 index 0000000000000000000000000000000000000000..f9502529b3e72b24967fe877a8142b6debdf2ca6 --- /dev/null +++ b/hw-arm-versal-virt-Fix-typo-xlnx-ve-xlnx-versal.patch @@ -0,0 +1,36 @@ +From 0b79d1baeec2044ff3c7f315aff91729d698e24a Mon Sep 17 00:00:00 2001 +From: "Edgar E. Iglesias" +Date: Mon, 27 Apr 2020 20:16:41 +0200 +Subject: [PATCH 159/709] hw/arm: versal-virt: Fix typo xlnx-ve -> xlnx-versal +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Fix typo xlnx-ve -> xlnx-versal. + +Signed-off-by: Edgar E. Iglesias +Reviewed-by: Alistair Francis +Reviewed-by: Philippe Mathieu-Daudé +Reviewed-by: Luc Michel +Message-id: 20200427181649.26851-4-edgar.iglesias@gmail.com +Signed-off-by: Peter Maydell +--- + hw/arm/xlnx-versal-virt.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c +index 878a275140..8a608074d1 100644 +--- a/hw/arm/xlnx-versal-virt.c ++++ b/hw/arm/xlnx-versal-virt.c +@@ -440,7 +440,7 @@ static void versal_virt_init(MachineState *machine) + psci_conduit = QEMU_PSCI_CONDUIT_SMC; + } + +- sysbus_init_child_obj(OBJECT(machine), "xlnx-ve", &s->soc, ++ sysbus_init_child_obj(OBJECT(machine), "xlnx-versal", &s->soc, + sizeof(s->soc), TYPE_XLNX_VERSAL); + object_property_set_link(OBJECT(&s->soc), OBJECT(machine->ram), + "ddr", &error_abort); +-- +2.23.0 + diff --git a/hw-arm-virt-Add-nvdimm-hot-plug-infrastructure.patch b/hw-arm-virt-Add-nvdimm-hot-plug-infrastructure.patch new file mode 100644 index 0000000000000000000000000000000000000000..452027fea9fa03d0c5935edca79052e891ed6d64 --- /dev/null +++ b/hw-arm-virt-Add-nvdimm-hot-plug-infrastructure.patch @@ -0,0 +1,137 @@ +From b5a60bee7425ec2ce9b1aa0577585e8328c1b768 Mon Sep 17 00:00:00 2001 +From: Kwangwoo Lee +Date: Tue, 21 Apr 2020 13:59:30 +0100 +Subject: [PATCH 220/709] hw/arm/virt: Add nvdimm hot-plug infrastructure + +This adds support to init nvdimm acpi state and build nvdimm acpi tables. +Please note nvdimm_support is not yet enabled. + +Signed-off-by: Kwangwoo Lee +Signed-off-by: Eric Auger +Signed-off-by: Shameer Kolothum +Reviewed-by: Igor Mammedov +Message-Id: <20200421125934.14952-4-shameerali.kolothum.thodi@huawei.com> +Acked-by: Peter Maydell +Tested-by: Eric Auger +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +--- + hw/arm/Kconfig | 1 + + hw/arm/virt-acpi-build.c | 6 ++++++ + hw/arm/virt.c | 19 +++++++++++++++++++ + hw/mem/Kconfig | 2 +- + include/hw/arm/virt.h | 1 + + 5 files changed, 28 insertions(+), 1 deletion(-) + +diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig +index 188419dc1e..5364172537 100644 +--- a/hw/arm/Kconfig ++++ b/hw/arm/Kconfig +@@ -25,6 +25,7 @@ config ARM_VIRT + select DIMM + select ACPI_MEMORY_HOTPLUG + select ACPI_HW_REDUCED ++ select ACPI_NVDIMM + + config CHEETAH + bool +diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c +index 81d41a3990..f22b1e6097 100644 +--- a/hw/arm/virt-acpi-build.c ++++ b/hw/arm/virt-acpi-build.c +@@ -44,6 +44,7 @@ + #include "hw/pci/pcie_host.h" + #include "hw/pci/pci.h" + #include "hw/arm/virt.h" ++#include "hw/mem/nvdimm.h" + #include "sysemu/numa.h" + #include "sysemu/reset.h" + #include "kvm_arm.h" +@@ -826,6 +827,11 @@ void virt_acpi_build(VirtMachineState *vms, AcpiBuildTables *tables) + } + } + ++ if (ms->nvdimms_state->is_enabled) { ++ nvdimm_build_acpi(table_offsets, tables_blob, tables->linker, ++ ms->nvdimms_state, ms->ram_slots); ++ } ++ + if (its_class_name() && !vmc->no_its) { + acpi_add_table(table_offsets, tables_blob); + build_iort(tables_blob, tables->linker, vms); +diff --git a/hw/arm/virt.c b/hw/arm/virt.c +index 626822554d..87f29953c4 100644 +--- a/hw/arm/virt.c ++++ b/hw/arm/virt.c +@@ -150,6 +150,7 @@ static const MemMapEntry base_memmap[] = { + [VIRT_SMMU] = { 0x09050000, 0x00020000 }, + [VIRT_PCDIMM_ACPI] = { 0x09070000, MEMORY_HOTPLUG_IO_LEN }, + [VIRT_ACPI_GED] = { 0x09080000, ACPI_GED_EVT_SEL_LEN }, ++ [VIRT_NVDIMM_ACPI] = { 0x09090000, NVDIMM_ACPI_IO_LEN}, + [VIRT_MMIO] = { 0x0a000000, 0x00000200 }, + /* ...repeating for a total of NUM_VIRTIO_TRANSPORTS, each of that size */ + [VIRT_PLATFORM_BUS] = { 0x0c000000, 0x02000000 }, +@@ -1884,6 +1885,18 @@ static void machvirt_init(MachineState *machine) + + create_platform_bus(vms); + ++ if (machine->nvdimms_state->is_enabled) { ++ const struct AcpiGenericAddress arm_virt_nvdimm_acpi_dsmio = { ++ .space_id = AML_AS_SYSTEM_MEMORY, ++ .address = vms->memmap[VIRT_NVDIMM_ACPI].base, ++ .bit_width = NVDIMM_ACPI_IO_LEN << 3 ++ }; ++ ++ nvdimm_init_acpi_state(machine->nvdimms_state, sysmem, ++ arm_virt_nvdimm_acpi_dsmio, ++ vms->fw_cfg, OBJECT(vms)); ++ } ++ + vms->bootinfo.ram_size = machine->ram_size; + vms->bootinfo.nb_cpus = smp_cpus; + vms->bootinfo.board_id = -1; +@@ -2095,6 +2108,8 @@ static void virt_memory_plug(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp) + { + VirtMachineState *vms = VIRT_MACHINE(hotplug_dev); ++ MachineState *ms = MACHINE(hotplug_dev); ++ bool is_nvdimm = object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM); + Error *local_err = NULL; + + pc_dimm_plug(PC_DIMM(dev), MACHINE(vms), &local_err); +@@ -2102,6 +2117,10 @@ static void virt_memory_plug(HotplugHandler *hotplug_dev, + goto out; + } + ++ if (is_nvdimm) { ++ nvdimm_plug(ms->nvdimms_state); ++ } ++ + hotplug_handler_plug(HOTPLUG_HANDLER(vms->acpi_dev), + dev, &error_abort); + +diff --git a/hw/mem/Kconfig b/hw/mem/Kconfig +index 2ad052a536..c27844900d 100644 +--- a/hw/mem/Kconfig ++++ b/hw/mem/Kconfig +@@ -8,4 +8,4 @@ config MEM_DEVICE + config NVDIMM + bool + default y +- depends on (PC || PSERIES) ++ depends on (PC || PSERIES || ARM_VIRT) +diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h +index 60b2f521eb..6d67ace76e 100644 +--- a/include/hw/arm/virt.h ++++ b/include/hw/arm/virt.h +@@ -79,6 +79,7 @@ enum { + VIRT_SECURE_MEM, + VIRT_PCDIMM_ACPI, + VIRT_ACPI_GED, ++ VIRT_NVDIMM_ACPI, + VIRT_LOWMEMMAP_LAST, + }; + +-- +2.23.0 + diff --git a/hw-arm-virt-Add-nvdimm-hotplug-support.patch b/hw-arm-virt-Add-nvdimm-hotplug-support.patch new file mode 100644 index 0000000000000000000000000000000000000000..dfd29f97263a63d087c28e1f845944287ae8e868 --- /dev/null +++ b/hw-arm-virt-Add-nvdimm-hotplug-support.patch @@ -0,0 +1,158 @@ +From c2505d1c56fc4959974985f57f100d90bc82f0ee Mon Sep 17 00:00:00 2001 +From: Shameer Kolothum +Date: Tue, 21 Apr 2020 13:59:31 +0100 +Subject: [PATCH 221/709] hw/arm/virt: Add nvdimm hotplug support + +This adds support for nvdimm hotplug events through GED +and enables nvdimm for the arm/virt. Now Guests with ACPI +can have both cold and hot plug of nvdimms. + +Hot removal functionality is not yet supported. + +Signed-off-by: Shameer Kolothum +Reviewed-by: Igor Mammedov +Reviewed-by: Eric Auger +Message-Id: <20200421125934.14952-5-shameerali.kolothum.thodi@huawei.com> +Acked-by: Peter Maydell +Tested-by: Eric Auger +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +--- + docs/specs/acpi_hw_reduced_hotplug.rst | 3 ++- + hw/acpi/generic_event_device.c | 15 ++++++++++++++- + hw/arm/virt.c | 16 +++++++++++----- + include/hw/acpi/generic_event_device.h | 1 + + 4 files changed, 28 insertions(+), 7 deletions(-) + +diff --git a/docs/specs/acpi_hw_reduced_hotplug.rst b/docs/specs/acpi_hw_reduced_hotplug.rst +index 911a98255b..0bd3f9399f 100644 +--- a/docs/specs/acpi_hw_reduced_hotplug.rst ++++ b/docs/specs/acpi_hw_reduced_hotplug.rst +@@ -63,7 +63,8 @@ GED IO interface (4 byte access) + bits: + 0: Memory hotplug event + 1: System power down event +- 2-31: Reserved ++ 2: NVDIMM hotplug event ++ 3-31: Reserved + + **write_access:** + +diff --git a/hw/acpi/generic_event_device.c b/hw/acpi/generic_event_device.c +index 021ed2bf23..5d17f78a1e 100644 +--- a/hw/acpi/generic_event_device.c ++++ b/hw/acpi/generic_event_device.c +@@ -16,6 +16,7 @@ + #include "hw/acpi/generic_event_device.h" + #include "hw/irq.h" + #include "hw/mem/pc-dimm.h" ++#include "hw/mem/nvdimm.h" + #include "hw/qdev-properties.h" + #include "migration/vmstate.h" + #include "qemu/error-report.h" +@@ -23,6 +24,7 @@ + static const uint32_t ged_supported_events[] = { + ACPI_GED_MEM_HOTPLUG_EVT, + ACPI_GED_PWR_DOWN_EVT, ++ ACPI_GED_NVDIMM_HOTPLUG_EVT, + }; + + /* +@@ -110,6 +112,11 @@ void build_ged_aml(Aml *table, const char *name, HotplugHandler *hotplug_dev, + aml_notify(aml_name(ACPI_POWER_BUTTON_DEVICE), + aml_int(0x80))); + break; ++ case ACPI_GED_NVDIMM_HOTPLUG_EVT: ++ aml_append(if_ctx, ++ aml_notify(aml_name("\\_SB.NVDR"), ++ aml_int(0x80))); ++ break; + default: + /* + * Please make sure all the events in ged_supported_events[] +@@ -175,7 +182,11 @@ static void acpi_ged_device_plug_cb(HotplugHandler *hotplug_dev, + AcpiGedState *s = ACPI_GED(hotplug_dev); + + if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { +- acpi_memory_plug_cb(hotplug_dev, &s->memhp_state, dev, errp); ++ if (object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM)) { ++ nvdimm_acpi_plug_cb(hotplug_dev, dev); ++ } else { ++ acpi_memory_plug_cb(hotplug_dev, &s->memhp_state, dev, errp); ++ } + } else { + error_setg(errp, "virt: device plug request for unsupported device" + " type: %s", object_get_typename(OBJECT(dev))); +@@ -192,6 +203,8 @@ static void acpi_ged_send_event(AcpiDeviceIf *adev, AcpiEventStatusBits ev) + sel = ACPI_GED_MEM_HOTPLUG_EVT; + } else if (ev & ACPI_POWER_DOWN_STATUS) { + sel = ACPI_GED_PWR_DOWN_EVT; ++ } else if (ev & ACPI_NVDIMM_HOTPLUG_STATUS) { ++ sel = ACPI_GED_NVDIMM_HOTPLUG_EVT; + } else { + /* Unknown event. Return without generating interrupt. */ + warn_report("GED: Unsupported event %d. No irq injected", ev); +diff --git a/hw/arm/virt.c b/hw/arm/virt.c +index 87f29953c4..171e6908ec 100644 +--- a/hw/arm/virt.c ++++ b/hw/arm/virt.c +@@ -568,6 +568,10 @@ static inline DeviceState *create_acpi_ged(VirtMachineState *vms) + event |= ACPI_GED_MEM_HOTPLUG_EVT; + } + ++ if (ms->nvdimms_state->is_enabled) { ++ event |= ACPI_GED_NVDIMM_HOTPLUG_EVT; ++ } ++ + dev = qdev_create(NULL, TYPE_ACPI_GED); + qdev_prop_set_uint32(dev, "ged-event", event); + +@@ -2088,19 +2092,20 @@ static void virt_memory_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev, + Error **errp) + { + VirtMachineState *vms = VIRT_MACHINE(hotplug_dev); ++ const MachineState *ms = MACHINE(hotplug_dev); + const bool is_nvdimm = object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM); + +- if (is_nvdimm) { +- error_setg(errp, "nvdimm is not yet supported"); +- return; +- } +- + if (!vms->acpi_dev) { + error_setg(errp, + "memory hotplug is not enabled: missing acpi-ged device"); + return; + } + ++ if (is_nvdimm && !ms->nvdimms_state->is_enabled) { ++ error_setg(errp, "nvdimm is not enabled: add 'nvdimm=on' to '-M'"); ++ return; ++ } ++ + pc_dimm_pre_plug(PC_DIMM(dev), MACHINE(hotplug_dev), NULL, errp); + } + +@@ -2245,6 +2250,7 @@ static void virt_machine_class_init(ObjectClass *oc, void *data) + hc->plug = virt_machine_device_plug_cb; + hc->unplug_request = virt_machine_device_unplug_request_cb; + mc->numa_mem_supported = true; ++ mc->nvdimm_supported = true; + mc->auto_enable_numa_with_memhp = true; + mc->default_ram_id = "mach-virt.ram"; + +diff --git a/include/hw/acpi/generic_event_device.h b/include/hw/acpi/generic_event_device.h +index d157eac088..9eb86ca4fd 100644 +--- a/include/hw/acpi/generic_event_device.h ++++ b/include/hw/acpi/generic_event_device.h +@@ -82,6 +82,7 @@ + */ + #define ACPI_GED_MEM_HOTPLUG_EVT 0x1 + #define ACPI_GED_PWR_DOWN_EVT 0x2 ++#define ACPI_GED_NVDIMM_HOTPLUG_EVT 0x4 + + typedef struct GEDState { + MemoryRegion io; +-- +2.23.0 + diff --git a/hw-arm-virt-Introduce-a-RAS-machine-option.patch b/hw-arm-virt-Introduce-a-RAS-machine-option.patch new file mode 100644 index 0000000000000000000000000000000000000000..17473911f185487df65a9a3ea844164f14fc6050 --- /dev/null +++ b/hw-arm-virt-Introduce-a-RAS-machine-option.patch @@ -0,0 +1,76 @@ +From 2afa8c85192595e2b6a61e2045df7bea66bdea08 Mon Sep 17 00:00:00 2001 +From: Dongjiu Geng +Date: Tue, 12 May 2020 11:06:01 +0800 +Subject: [PATCH 437/709] hw/arm/virt: Introduce a RAS machine option + +RAS Virtualization feature is not supported now, so +add a RAS machine option and disable it by default. + +Reviewed-by: Peter Maydell +Signed-off-by: Dongjiu Geng +Signed-off-by: Xiang Zheng +Reviewed-by: Jonathan Cameron +Reviewed-by: Igor Mammedov +Message-id: 20200512030609.19593-3-gengdongjiu@huawei.com +Signed-off-by: Peter Maydell +--- + hw/arm/virt.c | 23 +++++++++++++++++++++++ + include/hw/arm/virt.h | 1 + + 2 files changed, 24 insertions(+) + +diff --git a/hw/arm/virt.c b/hw/arm/virt.c +index 634db0cfe9..9e76fa7b01 100644 +--- a/hw/arm/virt.c ++++ b/hw/arm/virt.c +@@ -1995,6 +1995,20 @@ static void virt_set_acpi(Object *obj, Visitor *v, const char *name, + visit_type_OnOffAuto(v, name, &vms->acpi, errp); + } + ++static bool virt_get_ras(Object *obj, Error **errp) ++{ ++ VirtMachineState *vms = VIRT_MACHINE(obj); ++ ++ return vms->ras; ++} ++ ++static void virt_set_ras(Object *obj, bool value, Error **errp) ++{ ++ VirtMachineState *vms = VIRT_MACHINE(obj); ++ ++ vms->ras = value; ++} ++ + static char *virt_get_gic_version(Object *obj, Error **errp) + { + VirtMachineState *vms = VIRT_MACHINE(obj); +@@ -2327,6 +2341,15 @@ static void virt_instance_init(Object *obj) + "Valid values are none and smmuv3", + NULL); + ++ /* Default disallows RAS instantiation */ ++ vms->ras = false; ++ object_property_add_bool(obj, "ras", virt_get_ras, ++ virt_set_ras, NULL); ++ object_property_set_description(obj, "ras", ++ "Set on/off to enable/disable reporting host memory errors " ++ "to a KVM guest using ACPI and guest external abort exceptions", ++ NULL); ++ + vms->irqmap = a15irqmap; + + virt_flash_create(vms); +diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h +index 6d67ace76e..31878ddc72 100644 +--- a/include/hw/arm/virt.h ++++ b/include/hw/arm/virt.h +@@ -132,6 +132,7 @@ typedef struct { + bool highmem_ecam; + bool its; + bool virt; ++ bool ras; + OnOffAuto acpi; + VirtGICType gic_version; + VirtIOMMUType iommu; +-- +2.23.0 + diff --git a/hw-arm-virt-Introduce-cpu-topology-support.patch b/hw-arm-virt-Introduce-cpu-topology-support.patch deleted file mode 100644 index 027a5112effa77c9d37642f88cf9d00120bc6f47..0000000000000000000000000000000000000000 --- a/hw-arm-virt-Introduce-cpu-topology-support.patch +++ /dev/null @@ -1,224 +0,0 @@ -From 123b4eb3cb7b9b4e3e0705a9b5f974b37d3b8431 Mon Sep 17 00:00:00 2001 -From: zhanghailiang -Date: Mon, 5 Aug 2019 15:04:31 +0800 -Subject: [PATCH] hw/arm/virt: Introduce cpu topology support - -Add topology support for guest vcpu by cpu-map in dtb when the guest is booted -with dtb, and by pptt table when the guest is booted with acpi. - -Signed-off-by: Honghao -Signed-off-by: zhanghailiang -(picked-from https://patchwork.ozlabs.org/cover/939301/ which is pushed by -Andrew Jones ) ---- - device_tree.c | 32 +++++++++++++++++++++++ - hw/acpi/aml-build.c | 50 ++++++++++++++++++++++++++++++++++++ - hw/arm/virt-acpi-build.c | 4 +++ - hw/arm/virt.c | 29 +++++++++++++++++++++ - include/hw/acpi/aml-build.h | 2 ++ - include/sysemu/device_tree.h | 1 + - 6 files changed, 118 insertions(+) - -diff --git a/device_tree.c b/device_tree.c -index f8b46b3c..03906a14 100644 ---- a/device_tree.c -+++ b/device_tree.c -@@ -524,6 +524,38 @@ int qemu_fdt_add_subnode(void *fdt, const char *name) - return retval; - } - -+/** -+ * qemu_fdt_add_path -+ * @fdt: Flattened Device Tree -+ * @path: Flattened Device Tree node path -+ * -+ * qemu_fdt_add_path works like qemu_fdt_add_subnode, except it -+ * also recursively adds any missing parent nodes. -+ */ -+int qemu_fdt_add_path(void *fdt, const char *path) -+{ -+ char *parent; -+ int offset; -+ -+ offset = fdt_path_offset(fdt, path); -+ if (offset < 0 && offset != -FDT_ERR_NOTFOUND) { -+ error_report("%s Couldn't find node %s: %s", __func__, path, -+ fdt_strerror(offset)); -+ exit(1); -+ } -+ -+ if (offset != -FDT_ERR_NOTFOUND) { -+ return offset; -+ } -+ -+ parent = g_strdup(path); -+ strrchr(parent, '/')[0] = '\0'; -+ qemu_fdt_add_path(fdt, parent); -+ g_free(parent); -+ -+ return qemu_fdt_add_subnode(fdt, path); -+} -+ - void qemu_fdt_dumpdtb(void *fdt, int size) - { - const char *dumpdtb = qemu_opt_get(qemu_get_machine_opts(), "dumpdtb"); -diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c -index 73f97751..9d39ad10 100644 ---- a/hw/acpi/aml-build.c -+++ b/hw/acpi/aml-build.c -@@ -25,6 +25,7 @@ - #include "qemu/bswap.h" - #include "qemu/bitops.h" - #include "sysemu/numa.h" -+#include "sysemu/cpus.h" - - static GArray *build_alloc_array(void) - { -@@ -51,6 +52,55 @@ static void build_append_array(GArray *array, GArray *val) - g_array_append_vals(array, val->data, val->len); - } - -+/* -+ * ACPI 6.2 Processor Properties Topology Table (PPTT) -+ */ -+static void build_cpu_hierarchy(GArray *tbl, uint32_t flags, -+ uint32_t parent, uint32_t id) -+{ -+ build_append_byte(tbl, 0); /* Type 0 - processor */ -+ build_append_byte(tbl, 20); /* Length, no private resources */ -+ build_append_int_noprefix(tbl, 0, 2); /* Reserved */ -+ build_append_int_noprefix(tbl, flags, 4); -+ build_append_int_noprefix(tbl, parent, 4); -+ build_append_int_noprefix(tbl, id, 4); -+ build_append_int_noprefix(tbl, 0, 4); /* Num private resources */ -+} -+ -+void build_pptt(GArray *table_data, BIOSLinker *linker, int possible_cpus) -+{ -+ int pptt_start = table_data->len; -+ int uid = 0, cpus = 0, socket; -+ -+ acpi_data_push(table_data, sizeof(AcpiTableHeader)); -+ -+ for (socket = 0; cpus < possible_cpus; socket++) { -+ uint32_t socket_offset = table_data->len - pptt_start; -+ int core; -+ -+ build_cpu_hierarchy(table_data, 1, 0, socket); -+ -+ for (core = 0; core < smp_cores; core++) { -+ uint32_t core_offset = table_data->len - pptt_start; -+ int thread; -+ -+ if (smp_threads > 1) { -+ build_cpu_hierarchy(table_data, 0, socket_offset, core); -+ for (thread = 0; thread < smp_threads; thread++) { -+ build_cpu_hierarchy(table_data, 2, core_offset, uid++); -+ } -+ } else { -+ build_cpu_hierarchy(table_data, 2, socket_offset, uid++); -+ } -+ } -+ cpus += smp_cores * smp_threads; -+ } -+ -+ build_header(linker, table_data, -+ (void *)(table_data->data + pptt_start), "PPTT", -+ table_data->len - pptt_start, 1, NULL, NULL); -+} -+ - #define ACPI_NAMESEG_LEN 4 - - static void -diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c -index 33a8e2e3..18653e6d 100644 ---- a/hw/arm/virt-acpi-build.c -+++ b/hw/arm/virt-acpi-build.c -@@ -870,6 +870,10 @@ void virt_acpi_build(VirtMachineState *vms, AcpiBuildTables *tables) - acpi_add_table(table_offsets, tables_blob); - build_fadt_rev5(tables_blob, tables->linker, vms, dsdt); - -+ acpi_add_table(table_offsets, tables_blob); -+ -+ build_pptt(tables_blob, tables->linker, vms->smp_cpus); -+ - acpi_add_table(table_offsets, tables_blob); - build_madt(tables_blob, tables->linker, vms); - -diff --git a/hw/arm/virt.c b/hw/arm/virt.c -index 57a78b16..16700a2e 100644 ---- a/hw/arm/virt.c -+++ b/hw/arm/virt.c -@@ -42,6 +42,7 @@ - #include "net/net.h" - #include "sysemu/device_tree.h" - #include "sysemu/numa.h" -+#include "sysemu/cpus.h" - #include "sysemu/sysemu.h" - #include "sysemu/kvm.h" - #include "hw/loader.h" -@@ -364,8 +365,36 @@ static void fdt_add_cpu_nodes(const VirtMachineState *vms) - ms->possible_cpus->cpus[cs->cpu_index].props.node_id); - } - -+ qemu_fdt_setprop_cell(vms->fdt, nodename, "phandle", -+ qemu_fdt_alloc_phandle(vms->fdt)); -+ - g_free(nodename); - } -+ -+ /* Add vcpu topology by fdt node cpu-map. */ -+ qemu_fdt_add_subnode(vms->fdt, "/cpus/cpu-map"); -+ -+ for (cpu = vms->smp_cpus - 1; cpu >= 0; cpu--) { -+ char *cpu_path = g_strdup_printf("/cpus/cpu@%d", cpu); -+ char *map_path; -+ -+ if (smp_threads > 1) { -+ map_path = g_strdup_printf( -+ "/cpus/cpu-map/%s%d/%s%d/%s%d", -+ "cluster", cpu / (smp_cores * smp_threads), -+ "core", (cpu / smp_threads) % smp_cores, -+ "thread", cpu % smp_threads); -+ } else { -+ map_path = g_strdup_printf( -+ "/cpus/cpu-map/%s%d/%s%d", -+ "cluster", cpu / smp_cores, -+ "core", cpu % smp_cores); -+ } -+ qemu_fdt_add_path(vms->fdt, map_path); -+ qemu_fdt_setprop_phandle(vms->fdt, map_path, "cpu", cpu_path); -+ g_free(map_path); -+ g_free(cpu_path); -+ } - } - - static void fdt_add_its_gic_node(VirtMachineState *vms) -diff --git a/include/hw/acpi/aml-build.h b/include/hw/acpi/aml-build.h -index 375335ab..bfb0b100 100644 ---- a/include/hw/acpi/aml-build.h -+++ b/include/hw/acpi/aml-build.h -@@ -417,6 +417,8 @@ build_append_gas_from_struct(GArray *table, const struct AcpiGenericAddress *s) - void build_srat_memory(AcpiSratMemoryAffinity *numamem, uint64_t base, - uint64_t len, int node, MemoryAffinityFlags flags); - -+void build_pptt(GArray *table_data, BIOSLinker *linker, int possible_cpus); -+ - void build_slit(GArray *table_data, BIOSLinker *linker); - - void build_fadt(GArray *tbl, BIOSLinker *linker, const AcpiFadtData *f, -diff --git a/include/sysemu/device_tree.h b/include/sysemu/device_tree.h -index c16fd69b..d62fc873 100644 ---- a/include/sysemu/device_tree.h -+++ b/include/sysemu/device_tree.h -@@ -101,6 +101,7 @@ uint32_t qemu_fdt_get_phandle(void *fdt, const char *path); - uint32_t qemu_fdt_alloc_phandle(void *fdt); - int qemu_fdt_nop_node(void *fdt, const char *node_path); - int qemu_fdt_add_subnode(void *fdt, const char *name); -+int qemu_fdt_add_path(void *fdt, const char *path); - - #define qemu_fdt_setprop_cells(fdt, node_path, property, ...) \ - do { \ --- -2.19.1 - diff --git a/hw-arm-virt-Remove-the-compat-forcing-tpm-tis-device.patch b/hw-arm-virt-Remove-the-compat-forcing-tpm-tis-device.patch new file mode 100644 index 0000000000000000000000000000000000000000..272e9f9834fcdc64b8cd5f1c7d9b6b8c50ceeeba --- /dev/null +++ b/hw-arm-virt-Remove-the-compat-forcing-tpm-tis-device.patch @@ -0,0 +1,38 @@ +From b13d31ca17cc22c79b2dc29abd030802e4cc36f4 Mon Sep 17 00:00:00 2001 +From: Eric Auger +Date: Mon, 27 Apr 2020 16:31:45 +0200 +Subject: [PATCH 281/709] hw/arm/virt: Remove the compat forcing tpm-tis-device + PPI to off + +Now that the tpm-tis-device device PPI property is off by default, +we can remove the compat used for the same goal. + +Signed-off-by: Eric Auger +Reviewed-by: Cornelia Huck +Reviewed-by: Stefan Berger +Reviewed-by: Peter Maydell +Signed-off-by: Stefan Berger +Message-id: 20200427143145.16251-3-eric.auger@redhat.com +--- + hw/arm/virt.c | 5 ----- + 1 file changed, 5 deletions(-) + +diff --git a/hw/arm/virt.c b/hw/arm/virt.c +index 171e6908ec..dd024d0780 100644 +--- a/hw/arm/virt.c ++++ b/hw/arm/virt.c +@@ -2354,11 +2354,6 @@ type_init(machvirt_machine_init); + + static void virt_machine_5_0_options(MachineClass *mc) + { +- static GlobalProperty compat[] = { +- { TYPE_TPM_TIS_SYSBUS, "ppi", "false" }, +- }; +- +- compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat)); + } + DEFINE_VIRT_MACHINE_AS_LATEST(5, 0) + +-- +2.23.0 + diff --git a/hw-arm-virt-dt-add-kaslr-seed-property.patch b/hw-arm-virt-dt-add-kaslr-seed-property.patch new file mode 100644 index 0000000000000000000000000000000000000000..232566c3df34cdf579c44ac61e9a3f95433db3d4 --- /dev/null +++ b/hw-arm-virt-dt-add-kaslr-seed-property.patch @@ -0,0 +1,67 @@ +From 60592cfed2b685ef114a454d176ef539528cb0cf Mon Sep 17 00:00:00 2001 +From: Jerome Forissier +Date: Mon, 20 Apr 2020 14:18:07 +0200 +Subject: [PATCH 116/709] hw/arm/virt: dt: add kaslr-seed property + +Generate random seeds to be used by the non-secure and/or secure OSes +for ASLR. The seeds are 64-bit random values exported via the DT +properties /chosen/kaslr-seed [1] and /secure-chosen/kaslr-seed, the +latter being used by OP-TEE [2]. + +[1] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=e5bc0c37c97e1 +[2] https://github.com/OP-TEE/optee_os/commit/ef262691fe0e + +Signed-off-by: Jerome Forissier +Message-id: 20200420121807.8204-3-jerome@forissier.org +Reviewed-by: Peter Maydell +Signed-off-by: Peter Maydell +--- + hw/arm/virt.c | 15 +++++++++++++++ + 1 file changed, 15 insertions(+) + +diff --git a/hw/arm/virt.c b/hw/arm/virt.c +index 0d92674f32..626822554d 100644 +--- a/hw/arm/virt.c ++++ b/hw/arm/virt.c +@@ -77,6 +77,7 @@ + #include "hw/acpi/generic_event_device.h" + #include "hw/virtio/virtio-iommu.h" + #include "hw/char/pl011.h" ++#include "qemu/guest-random.h" + + #define DEFINE_VIRT_MACHINE_LATEST(major, minor, latest) \ + static void virt_##major##_##minor##_class_init(ObjectClass *oc, \ +@@ -213,6 +214,18 @@ static bool cpu_type_valid(const char *cpu) + return false; + } + ++static void create_kaslr_seed(VirtMachineState *vms, const char *node) ++{ ++ Error *err = NULL; ++ uint64_t seed; ++ ++ if (qemu_guest_getrandom(&seed, sizeof(seed), &err)) { ++ error_free(err); ++ return; ++ } ++ qemu_fdt_setprop_u64(vms->fdt, node, "kaslr-seed", seed); ++} ++ + static void create_fdt(VirtMachineState *vms) + { + MachineState *ms = MACHINE(vms); +@@ -233,9 +246,11 @@ static void create_fdt(VirtMachineState *vms) + + /* /chosen must exist for load_dtb to fill in necessary properties later */ + qemu_fdt_add_subnode(fdt, "/chosen"); ++ create_kaslr_seed(vms, "/chosen"); + + if (vms->secure) { + qemu_fdt_add_subnode(fdt, "/secure-chosen"); ++ create_kaslr_seed(vms, "/secure-chosen"); + } + + /* Clock node, for the benefit of the UART. The kernel device tree +-- +2.23.0 + diff --git a/hw-arm-virt-dt-move-creation-of-secure-chosen-to-cre.patch b/hw-arm-virt-dt-move-creation-of-secure-chosen-to-cre.patch new file mode 100644 index 0000000000000000000000000000000000000000..4accb978ca9f9ee063d981203487f0395bff43d6 --- /dev/null +++ b/hw-arm-virt-dt-move-creation-of-secure-chosen-to-cre.patch @@ -0,0 +1,44 @@ +From ef6a5c71c2f40e253712ad3d8826d5e84e325aeb Mon Sep 17 00:00:00 2001 +From: Jerome Forissier +Date: Mon, 20 Apr 2020 14:18:06 +0200 +Subject: [PATCH 115/709] hw/arm/virt: dt: move creation of /secure-chosen to + create_fdt() + +The /secure-chosen node is currently used only by create_uart(), but +this will change. Therefore move the creation of this node to +create_fdt(). + +Signed-off-by: Jerome Forissier +Message-id: 20200420121807.8204-2-jerome@forissier.org +Reviewed-by: Peter Maydell +Signed-off-by: Peter Maydell +--- + hw/arm/virt.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/hw/arm/virt.c b/hw/arm/virt.c +index cca5316256..0d92674f32 100644 +--- a/hw/arm/virt.c ++++ b/hw/arm/virt.c +@@ -234,6 +234,10 @@ static void create_fdt(VirtMachineState *vms) + /* /chosen must exist for load_dtb to fill in necessary properties later */ + qemu_fdt_add_subnode(fdt, "/chosen"); + ++ if (vms->secure) { ++ qemu_fdt_add_subnode(fdt, "/secure-chosen"); ++ } ++ + /* Clock node, for the benefit of the UART. The kernel device tree + * binding documentation claims the PL011 node clock properties are + * optional but in practice if you omit them the kernel refuses to +@@ -761,7 +765,6 @@ static void create_uart(const VirtMachineState *vms, int uart, + qemu_fdt_setprop_string(vms->fdt, nodename, "status", "disabled"); + qemu_fdt_setprop_string(vms->fdt, nodename, "secure-status", "okay"); + +- qemu_fdt_add_subnode(vms->fdt, "/secure-chosen"); + qemu_fdt_setprop_string(vms->fdt, "/secure-chosen", "stdout-path", + nodename); + } +-- +2.23.0 + diff --git a/hw-arm-xilinx_zynq-connect-uart-clocks-to-slcr.patch b/hw-arm-xilinx_zynq-connect-uart-clocks-to-slcr.patch new file mode 100644 index 0000000000000000000000000000000000000000..a61e8dfcb7513ceb5314325112288ab6b4d8ba21 --- /dev/null +++ b/hw-arm-xilinx_zynq-connect-uart-clocks-to-slcr.patch @@ -0,0 +1,134 @@ +From 5b49a34c6800d0cb917f959d8e75e5775f0fac3f Mon Sep 17 00:00:00 2001 +From: Damien Hedde +Date: Mon, 6 Apr 2020 15:52:50 +0200 +Subject: [PATCH 109/709] hw/arm/xilinx_zynq: connect uart clocks to slcr + +Add the connection between the slcr's output clocks and the uarts inputs. + +Also add the main board clock 'ps_clk', which is hard-coded to 33.33MHz +(the default frequency). This clock is used to feed the slcr's input +clock. + +Signed-off-by: Damien Hedde +Reviewed-by: Alistair Francis +Reviewed-by: Edgar E. Iglesias +Message-id: 20200406135251.157596-9-damien.hedde@greensocs.com +Signed-off-by: Peter Maydell +--- + hw/arm/xilinx_zynq.c | 57 +++++++++++++++++++++++++++++++++++++------- + 1 file changed, 49 insertions(+), 8 deletions(-) + +diff --git a/hw/arm/xilinx_zynq.c b/hw/arm/xilinx_zynq.c +index 571cdcd599..91b498dd5d 100644 +--- a/hw/arm/xilinx_zynq.c ++++ b/hw/arm/xilinx_zynq.c +@@ -35,6 +35,15 @@ + #include "hw/char/cadence_uart.h" + #include "hw/net/cadence_gem.h" + #include "hw/cpu/a9mpcore.h" ++#include "hw/qdev-clock.h" ++#include "sysemu/reset.h" ++ ++#define TYPE_ZYNQ_MACHINE MACHINE_TYPE_NAME("xilinx-zynq-a9") ++#define ZYNQ_MACHINE(obj) \ ++ OBJECT_CHECK(ZynqMachineState, (obj), TYPE_ZYNQ_MACHINE) ++ ++/* board base frequency: 33.333333 MHz */ ++#define PS_CLK_FREQUENCY (100 * 1000 * 1000 / 3) + + #define NUM_SPI_FLASHES 4 + #define NUM_QSPI_FLASHES 2 +@@ -75,6 +84,11 @@ static const int dma_irqs[8] = { + 0xe3401000 + ARMV7_IMM16(extract32((val), 16, 16)), /* movt r1 ... */ \ + 0xe5801000 + (addr) + ++typedef struct ZynqMachineState { ++ MachineState parent; ++ Clock *ps_clk; ++} ZynqMachineState; ++ + static void zynq_write_board_setup(ARMCPU *cpu, + const struct arm_boot_info *info) + { +@@ -159,10 +173,11 @@ static inline void zynq_init_spi_flashes(uint32_t base_addr, qemu_irq irq, + + static void zynq_init(MachineState *machine) + { ++ ZynqMachineState *zynq_machine = ZYNQ_MACHINE(machine); + ARMCPU *cpu; + MemoryRegion *address_space_mem = get_system_memory(); + MemoryRegion *ocm_ram = g_new(MemoryRegion, 1); +- DeviceState *dev; ++ DeviceState *dev, *slcr; + SysBusDevice *busdev; + qemu_irq pic[64]; + int n; +@@ -206,9 +221,18 @@ static void zynq_init(MachineState *machine) + 1, 0x0066, 0x0022, 0x0000, 0x0000, 0x0555, 0x2aa, + 0); + +- dev = qdev_create(NULL, "xilinx,zynq_slcr"); +- qdev_init_nofail(dev); +- sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0xF8000000); ++ /* Create slcr, keep a pointer to connect clocks */ ++ slcr = qdev_create(NULL, "xilinx,zynq_slcr"); ++ qdev_init_nofail(slcr); ++ sysbus_mmio_map(SYS_BUS_DEVICE(slcr), 0, 0xF8000000); ++ ++ /* Create the main clock source, and feed slcr with it */ ++ zynq_machine->ps_clk = CLOCK(object_new(TYPE_CLOCK)); ++ object_property_add_child(OBJECT(zynq_machine), "ps_clk", ++ OBJECT(zynq_machine->ps_clk), &error_abort); ++ object_unref(OBJECT(zynq_machine->ps_clk)); ++ clock_set_hz(zynq_machine->ps_clk, PS_CLK_FREQUENCY); ++ qdev_connect_clock_in(slcr, "ps_clk", zynq_machine->ps_clk); + + dev = qdev_create(NULL, TYPE_A9MPCORE_PRIV); + qdev_prop_set_uint32(dev, "num-cpu", 1); +@@ -229,8 +253,12 @@ static void zynq_init(MachineState *machine) + sysbus_create_simple(TYPE_CHIPIDEA, 0xE0002000, pic[53 - IRQ_OFFSET]); + sysbus_create_simple(TYPE_CHIPIDEA, 0xE0003000, pic[76 - IRQ_OFFSET]); + +- cadence_uart_create(0xE0000000, pic[59 - IRQ_OFFSET], serial_hd(0)); +- cadence_uart_create(0xE0001000, pic[82 - IRQ_OFFSET], serial_hd(1)); ++ dev = cadence_uart_create(0xE0000000, pic[59 - IRQ_OFFSET], serial_hd(0)); ++ qdev_connect_clock_in(dev, "refclk", ++ qdev_get_clock_out(slcr, "uart0_ref_clk")); ++ dev = cadence_uart_create(0xE0001000, pic[82 - IRQ_OFFSET], serial_hd(1)); ++ qdev_connect_clock_in(dev, "refclk", ++ qdev_get_clock_out(slcr, "uart1_ref_clk")); + + sysbus_create_varargs("cadence_ttc", 0xF8001000, + pic[42-IRQ_OFFSET], pic[43-IRQ_OFFSET], pic[44-IRQ_OFFSET], NULL); +@@ -308,8 +336,9 @@ static void zynq_init(MachineState *machine) + arm_load_kernel(ARM_CPU(first_cpu), machine, &zynq_binfo); + } + +-static void zynq_machine_init(MachineClass *mc) ++static void zynq_machine_class_init(ObjectClass *oc, void *data) + { ++ MachineClass *mc = MACHINE_CLASS(oc); + mc->desc = "Xilinx Zynq Platform Baseboard for Cortex-A9"; + mc->init = zynq_init; + mc->max_cpus = 1; +@@ -319,4 +348,16 @@ static void zynq_machine_init(MachineClass *mc) + mc->default_ram_id = "zynq.ext_ram"; + } + +-DEFINE_MACHINE("xilinx-zynq-a9", zynq_machine_init) ++static const TypeInfo zynq_machine_type = { ++ .name = TYPE_ZYNQ_MACHINE, ++ .parent = TYPE_MACHINE, ++ .class_init = zynq_machine_class_init, ++ .instance_size = sizeof(ZynqMachineState), ++}; ++ ++static void zynq_machine_register_types(void) ++{ ++ type_register_static(&zynq_machine_type); ++} ++ ++type_init(zynq_machine_register_types) +-- +2.23.0 + diff --git a/hw-arm-xlnx-zcu102-Disable-unsupported-FDT-firmware-.patch b/hw-arm-xlnx-zcu102-Disable-unsupported-FDT-firmware-.patch new file mode 100644 index 0000000000000000000000000000000000000000..387bd9dfb75da60b159230ad7887504a97d186d4 --- /dev/null +++ b/hw-arm-xlnx-zcu102-Disable-unsupported-FDT-firmware-.patch @@ -0,0 +1,76 @@ +From 6f7b6947a6639fff15c6a0956adf0f5ec004b789 Mon Sep 17 00:00:00 2001 +From: "Edgar E. Iglesias" +Date: Thu, 23 Apr 2020 14:11:14 +0200 +Subject: [PATCH 123/709] hw/arm: xlnx-zcu102: Disable unsupported FDT firmware + nodes + +Disable unsupported FDT firmware nodes if a user passes us +a DTB with nodes enabled that the machine cannot support +due to lack of EL3 or EL2 support. + +Reviewed-by: Alistair Francis +Signed-off-by: Edgar E. Iglesias +Message-id: 20200423121114.4274-5-edgar.iglesias@gmail.com +Signed-off-by: Peter Maydell +--- + hw/arm/xlnx-zcu102.c | 30 ++++++++++++++++++++++++++++++ + 1 file changed, 30 insertions(+) + +diff --git a/hw/arm/xlnx-zcu102.c b/hw/arm/xlnx-zcu102.c +index 4eb117c755..a798e228b7 100644 +--- a/hw/arm/xlnx-zcu102.c ++++ b/hw/arm/xlnx-zcu102.c +@@ -23,6 +23,7 @@ + #include "qemu/error-report.h" + #include "qemu/log.h" + #include "sysemu/qtest.h" ++#include "sysemu/device_tree.h" + + typedef struct XlnxZCU102 { + MachineState parent_obj; +@@ -68,6 +69,34 @@ static void zcu102_set_virt(Object *obj, bool value, Error **errp) + s->virt = value; + } + ++static void zcu102_modify_dtb(const struct arm_boot_info *binfo, void *fdt) ++{ ++ XlnxZCU102 *s = container_of(binfo, XlnxZCU102, binfo); ++ bool method_is_hvc; ++ char **node_path; ++ const char *r; ++ int prop_len; ++ int i; ++ ++ /* If EL3 is enabled, we keep all firmware nodes active. */ ++ if (!s->secure) { ++ node_path = qemu_fdt_node_path(fdt, NULL, "xlnx,zynqmp-firmware", ++ &error_fatal); ++ ++ for (i = 0; node_path && node_path[i]; i++) { ++ r = qemu_fdt_getprop(fdt, node_path[i], "method", &prop_len, NULL); ++ method_is_hvc = r && !strcmp("hvc", r); ++ ++ /* Allow HVC based firmware if EL2 is enabled. */ ++ if (method_is_hvc && s->virt) { ++ continue; ++ } ++ qemu_fdt_setprop_string(fdt, node_path[i], "status", "disabled"); ++ } ++ g_strfreev(node_path); ++ } ++} ++ + static void xlnx_zcu102_init(MachineState *machine) + { + XlnxZCU102 *s = ZCU102_MACHINE(machine); +@@ -169,6 +198,7 @@ static void xlnx_zcu102_init(MachineState *machine) + + s->binfo.ram_size = ram_size; + s->binfo.loader_start = 0; ++ s->binfo.modify_dtb = zcu102_modify_dtb; + arm_load_kernel(s->soc.boot_cpu_ptr, machine, &s->binfo); + } + +-- +2.23.0 + diff --git a/hw-arm-xlnx-zcu102-Move-arm_boot_info-into-XlnxZCU10.patch b/hw-arm-xlnx-zcu102-Move-arm_boot_info-into-XlnxZCU10.patch new file mode 100644 index 0000000000000000000000000000000000000000..11e8221e99efab5ea61d234e45004e882818058d --- /dev/null +++ b/hw-arm-xlnx-zcu102-Move-arm_boot_info-into-XlnxZCU10.patch @@ -0,0 +1,55 @@ +From 4d1ac883a7635c4bd58991bc158eff0c81cb230c Mon Sep 17 00:00:00 2001 +From: "Edgar E. Iglesias" +Date: Thu, 23 Apr 2020 14:11:13 +0200 +Subject: [PATCH 122/709] hw/arm: xlnx-zcu102: Move arm_boot_info into + XlnxZCU102 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Move arm_boot_info into XlnxZCU102. + +Reviewed-by: Philippe Mathieu-Daudé +Signed-off-by: Edgar E. Iglesias +Message-id: 20200423121114.4274-4-edgar.iglesias@gmail.com +Signed-off-by: Peter Maydell +--- + hw/arm/xlnx-zcu102.c | 9 +++++---- + 1 file changed, 5 insertions(+), 4 deletions(-) + +diff --git a/hw/arm/xlnx-zcu102.c b/hw/arm/xlnx-zcu102.c +index bd645ad818..4eb117c755 100644 +--- a/hw/arm/xlnx-zcu102.c ++++ b/hw/arm/xlnx-zcu102.c +@@ -31,13 +31,14 @@ typedef struct XlnxZCU102 { + + bool secure; + bool virt; ++ ++ struct arm_boot_info binfo; + } XlnxZCU102; + + #define TYPE_ZCU102_MACHINE MACHINE_TYPE_NAME("xlnx-zcu102") + #define ZCU102_MACHINE(obj) \ + OBJECT_CHECK(XlnxZCU102, (obj), TYPE_ZCU102_MACHINE) + +-static struct arm_boot_info xlnx_zcu102_binfo; + + static bool zcu102_get_secure(Object *obj, Error **errp) + { +@@ -166,9 +167,9 @@ static void xlnx_zcu102_init(MachineState *machine) + + /* TODO create and connect IDE devices for ide_drive_get() */ + +- xlnx_zcu102_binfo.ram_size = ram_size; +- xlnx_zcu102_binfo.loader_start = 0; +- arm_load_kernel(s->soc.boot_cpu_ptr, machine, &xlnx_zcu102_binfo); ++ s->binfo.ram_size = ram_size; ++ s->binfo.loader_start = 0; ++ arm_load_kernel(s->soc.boot_cpu_ptr, machine, &s->binfo); + } + + static void xlnx_zcu102_machine_instance_init(Object *obj) +-- +2.23.0 + diff --git a/hw-arm64-add-vcpu-cache-info-support.patch b/hw-arm64-add-vcpu-cache-info-support.patch deleted file mode 100644 index c9e843719b59a99112ee1867475846378c84264e..0000000000000000000000000000000000000000 --- a/hw-arm64-add-vcpu-cache-info-support.patch +++ /dev/null @@ -1,318 +0,0 @@ -From 8db6d888e3eb131900111506b93f6101413df5b4 Mon Sep 17 00:00:00 2001 -From: zhanghailiang -Date: Mon, 5 Aug 2019 15:30:05 +0800 -Subject: [PATCH] hw/arm64: add vcpu cache info support - -Support VCPU Cache info by dtb and PPTT table, including L1, L2 and L3 Cache. - -Signed-off-by: zhanghailiang -Signed-off-by: Honghao ---- - hw/acpi/aml-build.c | 124 ++++++++++++++++++++++++++++++++++++ - hw/arm/virt.c | 76 +++++++++++++++++++++- - include/hw/acpi/aml-build.h | 46 +++++++++++++ - 3 files changed, 245 insertions(+), 1 deletion(-) - -diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c -index 9d39ad10..99209c0a 100644 ---- a/hw/acpi/aml-build.c -+++ b/hw/acpi/aml-build.c -@@ -55,6 +55,129 @@ static void build_append_array(GArray *array, GArray *val) - /* - * ACPI 6.2 Processor Properties Topology Table (PPTT) - */ -+#ifdef __aarch64__ -+static void build_cache_head(GArray *tbl, uint32_t next_level) -+{ -+ build_append_byte(tbl, 1); -+ build_append_byte(tbl, 24); -+ build_append_int_noprefix(tbl, 0, 2); -+ build_append_int_noprefix(tbl, 127, 4); -+ build_append_int_noprefix(tbl, next_level, 4); -+} -+ -+static void build_cache_tail(GArray *tbl, uint32_t cache_type) -+{ -+ switch (cache_type) { -+ case ARM_L1D_CACHE: /* L1 dcache info*/ -+ build_append_int_noprefix(tbl, ARM_L1DCACHE_SIZE, 4); -+ build_append_int_noprefix(tbl, ARM_L1DCACHE_SET, 4); -+ build_append_byte(tbl, ARM_L1DCACHE_ASSOCIATIVITY); -+ build_append_byte(tbl, ARM_L1DCACHE_ATTRIBUTES); -+ build_append_int_noprefix(tbl, ARM_L1DCACHE_LINE_SIZE, 2); -+ break; -+ case ARM_L1I_CACHE: /* L1 icache info*/ -+ build_append_int_noprefix(tbl, ARM_L1ICACHE_SIZE, 4); -+ build_append_int_noprefix(tbl, ARM_L1ICACHE_SET, 4); -+ build_append_byte(tbl, ARM_L1ICACHE_ASSOCIATIVITY); -+ build_append_byte(tbl, ARM_L1ICACHE_ATTRIBUTES); -+ build_append_int_noprefix(tbl, ARM_L1ICACHE_LINE_SIZE, 2); -+ break; -+ case ARM_L2_CACHE: /* L2 cache info*/ -+ build_append_int_noprefix(tbl, ARM_L2CACHE_SIZE, 4); -+ build_append_int_noprefix(tbl, ARM_L2CACHE_SET, 4); -+ build_append_byte(tbl, ARM_L2CACHE_ASSOCIATIVITY); -+ build_append_byte(tbl, ARM_L2CACHE_ATTRIBUTES); -+ build_append_int_noprefix(tbl, ARM_L2CACHE_LINE_SIZE, 2); -+ break; -+ case ARM_L3_CACHE: /* L3 cache info*/ -+ build_append_int_noprefix(tbl, ARM_L3CACHE_SIZE, 4); -+ build_append_int_noprefix(tbl, ARM_L3CACHE_SET, 4); -+ build_append_byte(tbl, ARM_L3CACHE_ASSOCIATIVITY); -+ build_append_byte(tbl, ARM_L3CACHE_ATTRIBUTES); -+ build_append_int_noprefix(tbl, ARM_L3CACHE_LINE_SIZE, 2); -+ break; -+ default: -+ build_append_int_noprefix(tbl, 0, 4); -+ build_append_int_noprefix(tbl, 0, 4); -+ build_append_byte(tbl, 0); -+ build_append_byte(tbl, 0); -+ build_append_int_noprefix(tbl, 0, 2); -+ break; -+ } -+} -+ -+static void build_cache_hierarchy(GArray *tbl, -+ uint32_t next_level, uint32_t cache_type) -+{ -+ build_cache_head(tbl, next_level); -+ build_cache_tail(tbl, cache_type); -+} -+ -+static void build_arm_socket_hierarchy(GArray *tbl, -+ uint32_t offset, uint32_t id) -+{ -+ build_append_byte(tbl, 0); /* Type 0 - processor */ -+ build_append_byte(tbl, 24); /* Length, add private resources */ -+ build_append_int_noprefix(tbl, 0, 2); /* Reserved */ -+ build_append_int_noprefix(tbl, 1, 4); /* Processor boundary and id invalid*/ -+ build_append_int_noprefix(tbl, 0, 4); -+ build_append_int_noprefix(tbl, id, 4); -+ build_append_int_noprefix(tbl, 1, 4); /* Num private resources */ -+ build_append_int_noprefix(tbl, offset, 4); -+} -+ -+static void build_arm_cpu_hierarchy(GArray *tbl, -+ struct offset_status *offset, uint32_t id) -+{ -+ if (!offset) { -+ return; -+ } -+ build_append_byte(tbl, 0); /* Type 0 - processor */ -+ build_append_byte(tbl, 32); /* Length, add private resources */ -+ build_append_int_noprefix(tbl, 0, 2); /* Reserved */ -+ build_append_int_noprefix(tbl, 2, 4); /* Valid id*/ -+ build_append_int_noprefix(tbl, offset->parent, 4); -+ build_append_int_noprefix(tbl, id, 4); -+ build_append_int_noprefix(tbl, 3, 4); /* Num private resources */ -+ build_append_int_noprefix(tbl, offset->l1d_offset, 4); -+ build_append_int_noprefix(tbl, offset->l1i_offset, 4); -+ build_append_int_noprefix(tbl, offset->l2_offset, 4); -+} -+ -+void build_pptt(GArray *table_data, BIOSLinker *linker, int possible_cpus) -+{ -+ int pptt_start = table_data->len; -+ int uid = 0, cpus = 0, socket; -+ struct offset_status offset; -+ -+ acpi_data_push(table_data, sizeof(AcpiTableHeader)); -+ -+ for (socket = 0; cpus < possible_cpus; socket++) { -+ int core; -+ uint32_t l3_offset = table_data->len - pptt_start; -+ build_cache_hierarchy(table_data, 0, ARM_L3_CACHE); -+ -+ offset.parent = table_data->len - pptt_start; -+ build_arm_socket_hierarchy(table_data, l3_offset, socket); -+ -+ for (core = 0; core < smp_cores; core++) { -+ offset.l2_offset = table_data->len - pptt_start; -+ build_cache_hierarchy(table_data, 0, ARM_L2_CACHE); -+ offset.l1d_offset = table_data->len - pptt_start; -+ build_cache_hierarchy(table_data, offset.l2_offset, ARM_L1D_CACHE); -+ offset.l1i_offset = table_data->len - pptt_start; -+ build_cache_hierarchy(table_data, offset.l2_offset, ARM_L1I_CACHE); -+ build_arm_cpu_hierarchy(table_data, &offset, uid++); -+ cpus++; -+ } -+ } -+ -+ build_header(linker, table_data, -+ (void *)(table_data->data + pptt_start), "PPTT", -+ table_data->len - pptt_start, 1, NULL, NULL); -+} -+ -+#else - static void build_cpu_hierarchy(GArray *tbl, uint32_t flags, - uint32_t parent, uint32_t id) - { -@@ -100,6 +223,7 @@ void build_pptt(GArray *table_data, BIOSLinker *linker, int possible_cpus) - (void *)(table_data->data + pptt_start), "PPTT", - table_data->len - pptt_start, 1, NULL, NULL); - } -+#endif - - #define ACPI_NAMESEG_LEN 4 - -diff --git a/hw/arm/virt.c b/hw/arm/virt.c -index 16700a2e..96f56e2e 100644 ---- a/hw/arm/virt.c -+++ b/hw/arm/virt.c -@@ -304,6 +304,77 @@ static void fdt_add_timer_nodes(const VirtMachineState *vms) - GIC_FDT_IRQ_TYPE_PPI, ARCH_TIMER_NS_EL2_IRQ, irqflags); - } - -+static void fdt_add_l3cache_nodes(const VirtMachineState *vms) -+{ -+ int i; -+ unsigned int sockets = vms->smp_cpus / smp_cores; -+ -+ /* If current is not equal to max */ -+ if (vms->smp_cpus % smp_cores) -+ sockets++; -+ -+ for (i = 0; i < sockets; i++) { -+ char *nodename = g_strdup_printf("/cpus/l3-cache%d", i); -+ qemu_fdt_add_subnode(vms->fdt, nodename); -+ qemu_fdt_setprop_string(vms->fdt, nodename, "compatible", "cache"); -+ qemu_fdt_setprop_string(vms->fdt, nodename, "cache-unified", "true"); -+ qemu_fdt_setprop_cell(vms->fdt, nodename, "cache-level", 3); -+ qemu_fdt_setprop_cell(vms->fdt, nodename, "cache-size", 0x2000000); -+ qemu_fdt_setprop_cell(vms->fdt, nodename, "cache-line-size", 128); -+ qemu_fdt_setprop_cell(vms->fdt, nodename, "cache-sets", 2048); -+ qemu_fdt_setprop_cell(vms->fdt, nodename, "phandle", -+ qemu_fdt_alloc_phandle(vms->fdt)); -+ g_free(nodename); -+ } -+} -+ -+ -+static void fdt_add_l2cache_nodes(const VirtMachineState *vms) -+{ -+ int i, j; -+ signed int sockets = vms->smp_cpus / smp_cores; -+ -+ /* If current is not equal to max */ -+ if (vms->smp_cpus % smp_cores) -+ sockets++; -+ -+ for (i = 0; i < sockets; i++) { -+ char *next_path = g_strdup_printf("/cpus/l3-cache%d", i); -+ for (j = 0; j < smp_cores; j++) { -+ char *nodename = g_strdup_printf("/cpus/l2-cache%d", -+ i * smp_cores + j); -+ qemu_fdt_add_subnode(vms->fdt, nodename); -+ qemu_fdt_setprop_string(vms->fdt, nodename, "compatible", "cache"); -+ qemu_fdt_setprop_cell(vms->fdt, nodename, "cache-size", 0x80000); -+ qemu_fdt_setprop_cell(vms->fdt, nodename, "cache-line-size", 64); -+ qemu_fdt_setprop_cell(vms->fdt, nodename, "cache-sets", 1024); -+ qemu_fdt_setprop_phandle(vms->fdt, nodename, -+ "next-level-cache", next_path); -+ qemu_fdt_setprop_cell(vms->fdt, nodename, "phandle", -+ qemu_fdt_alloc_phandle(vms->fdt)); -+ g_free(nodename); -+ } -+ g_free(next_path); -+ } -+} -+ -+static void fdt_add_l1cache_prop(const VirtMachineState *vms, -+ char *nodename, int cpu) -+{ -+ char *cachename = g_strdup_printf("/cpus/l2-cache%d", cpu); -+ -+ qemu_fdt_setprop_cell(vms->fdt, nodename, "d-cache-size", 0x10000); -+ qemu_fdt_setprop_cell(vms->fdt, nodename, "d-cache-line-size", 64); -+ qemu_fdt_setprop_cell(vms->fdt, nodename, "d-cache-sets", 256); -+ qemu_fdt_setprop_cell(vms->fdt, nodename, "i-cache-size", 0x10000); -+ qemu_fdt_setprop_cell(vms->fdt, nodename, "i-cache-line-size", 64); -+ qemu_fdt_setprop_cell(vms->fdt, nodename, "i-cache-sets", 256); -+ qemu_fdt_setprop_phandle(vms->fdt, nodename, -+ "next-level-cache", cachename); -+ g_free(cachename); -+} -+ -+ - static void fdt_add_cpu_nodes(const VirtMachineState *vms) - { - int cpu; -@@ -336,6 +407,9 @@ static void fdt_add_cpu_nodes(const VirtMachineState *vms) - qemu_fdt_setprop_cell(vms->fdt, "/cpus", "#address-cells", addr_cells); - qemu_fdt_setprop_cell(vms->fdt, "/cpus", "#size-cells", 0x0); - -+ fdt_add_l3cache_nodes(vms); -+ fdt_add_l2cache_nodes(vms); -+ - for (cpu = vms->smp_cpus - 1; cpu >= 0; cpu--) { - char *nodename = g_strdup_printf("/cpus/cpu@%d", cpu); - ARMCPU *armcpu = ARM_CPU(qemu_get_cpu(cpu)); -@@ -364,7 +438,7 @@ static void fdt_add_cpu_nodes(const VirtMachineState *vms) - qemu_fdt_setprop_cell(vms->fdt, nodename, "numa-node-id", - ms->possible_cpus->cpus[cs->cpu_index].props.node_id); - } -- -+ fdt_add_l1cache_prop(vms, nodename, cpu); - qemu_fdt_setprop_cell(vms->fdt, nodename, "phandle", - qemu_fdt_alloc_phandle(vms->fdt)); - -diff --git a/include/hw/acpi/aml-build.h b/include/hw/acpi/aml-build.h -index bfb0b100..0be3453a 100644 ---- a/include/hw/acpi/aml-build.h -+++ b/include/hw/acpi/aml-build.h -@@ -223,6 +223,52 @@ struct AcpiBuildTables { - BIOSLinker *linker; - } AcpiBuildTables; - -+#ifdef __aarch64__ -+/* Definitions of the hardcoded cache info*/ -+ -+typedef enum { -+ ARM_L1D_CACHE, -+ ARM_L1I_CACHE, -+ ARM_L2_CACHE, -+ ARM_L3_CACHE -+} ArmCacheType; -+ -+/* L1 data cache: */ -+#define ARM_L1DCACHE_SIZE 65536 -+#define ARM_L1DCACHE_SET 256 -+#define ARM_L1DCACHE_ASSOCIATIVITY 4 -+#define ARM_L1DCACHE_ATTRIBUTES 2 -+#define ARM_L1DCACHE_LINE_SIZE 64 -+ -+/* L1 instruction cache: */ -+#define ARM_L1ICACHE_SIZE 65536 -+#define ARM_L1ICACHE_SET 256 -+#define ARM_L1ICACHE_ASSOCIATIVITY 4 -+#define ARM_L1ICACHE_ATTRIBUTES 4 -+#define ARM_L1ICACHE_LINE_SIZE 64 -+ -+/* Level 2 unified cache: */ -+#define ARM_L2CACHE_SIZE 524288 -+#define ARM_L2CACHE_SET 1024 -+#define ARM_L2CACHE_ASSOCIATIVITY 8 -+#define ARM_L2CACHE_ATTRIBUTES 10 -+#define ARM_L2CACHE_LINE_SIZE 64 -+ -+/* Level 3 unified cache: */ -+#define ARM_L3CACHE_SIZE 33554432 -+#define ARM_L3CACHE_SET 2048 -+#define ARM_L3CACHE_ASSOCIATIVITY 15 -+#define ARM_L3CACHE_ATTRIBUTES 10 -+#define ARM_L3CACHE_LINE_SIZE 128 -+ -+struct offset_status { -+ uint32_t parent; -+ uint32_t l2_offset; -+ uint32_t l1d_offset; -+ uint32_t l1i_offset; -+}; -+ -+#endif - /** - * init_aml_allocator: - * --- -2.23.0 - diff --git a/hw-audio-gus-Use-AUDIO_HOST_ENDIANNESS-definition-fr.patch b/hw-audio-gus-Use-AUDIO_HOST_ENDIANNESS-definition-fr.patch new file mode 100644 index 0000000000000000000000000000000000000000..41e258dc6e1aa424a87d350244b65eedb4270858 --- /dev/null +++ b/hw-audio-gus-Use-AUDIO_HOST_ENDIANNESS-definition-fr.patch @@ -0,0 +1,48 @@ +From 2f097e1964dc25a5633a54cae15ff068e9473196 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Tue, 5 May 2020 12:07:50 +0200 +Subject: [PATCH 643/709] hw/audio/gus: Use AUDIO_HOST_ENDIANNESS definition + from 'audio/audio.h' +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Use the generic AUDIO_HOST_ENDIANNESS definition instead +of a custom one. + +Signed-off-by: Philippe Mathieu-Daudé +Message-id: 20200505100750.27332-1-f4bug@amsat.org +Signed-off-by: Gerd Hoffmann +--- + hw/audio/gus.c | 8 +------- + 1 file changed, 1 insertion(+), 7 deletions(-) + +diff --git a/hw/audio/gus.c b/hw/audio/gus.c +index eb4a803fb5..c8df2bde6b 100644 +--- a/hw/audio/gus.c ++++ b/hw/audio/gus.c +@@ -41,12 +41,6 @@ + #define ldebug(...) + #endif + +-#ifdef HOST_WORDS_BIGENDIAN +-#define GUS_ENDIANNESS 1 +-#else +-#define GUS_ENDIANNESS 0 +-#endif +- + #define TYPE_GUS "gus" + #define GUS(obj) OBJECT_CHECK (GUSState, (obj), TYPE_GUS) + +@@ -256,7 +250,7 @@ static void gus_realizefn (DeviceState *dev, Error **errp) + as.freq = s->freq; + as.nchannels = 2; + as.fmt = AUDIO_FORMAT_S16; +- as.endianness = GUS_ENDIANNESS; ++ as.endianness = AUDIO_HOST_ENDIANNESS; + + s->voice = AUD_open_out ( + &s->card, +-- +2.23.0 + diff --git a/hw-block-pflash-Check-return-value-of-blk_pwrite.patch b/hw-block-pflash-Check-return-value-of-blk_pwrite.patch new file mode 100644 index 0000000000000000000000000000000000000000..1daa8609d352085909d41d8b86af1678d2b5e257 --- /dev/null +++ b/hw-block-pflash-Check-return-value-of-blk_pwrite.patch @@ -0,0 +1,88 @@ +From 1857b9db49770590483be44eb90993c42b2a5a99 Mon Sep 17 00:00:00 2001 +From: Mansour Ahmadi +Date: Tue, 7 Apr 2020 20:35:52 -0400 +Subject: [PATCH 639/709] hw/block/pflash: Check return value of blk_pwrite() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +When updating the PFLASH file contents, we should check for a +possible failure of blk_pwrite(). Similar to commit 3a688294e. + +Reported-by: Coverity (CID 1357678 CHECKED_RETURN) +Signed-off-by: Mansour Ahmadi +Message-Id: <20200408003552.58095-1-mansourweb@gmail.com> +[PMD: Add missing "qemu/error-report.h" include and TODO comment] +Signed-off-by: Philippe Mathieu-Daudé +--- + hw/block/pflash_cfi01.c | 8 +++++++- + hw/block/pflash_cfi02.c | 8 +++++++- + 2 files changed, 14 insertions(+), 2 deletions(-) + +diff --git a/hw/block/pflash_cfi01.c b/hw/block/pflash_cfi01.c +index 2ca173aa46..11922c0f96 100644 +--- a/hw/block/pflash_cfi01.c ++++ b/hw/block/pflash_cfi01.c +@@ -42,6 +42,7 @@ + #include "hw/qdev-properties.h" + #include "sysemu/block-backend.h" + #include "qapi/error.h" ++#include "qemu/error-report.h" + #include "qemu/bitops.h" + #include "qemu/error-report.h" + #include "qemu/host-utils.h" +@@ -389,13 +390,18 @@ static void pflash_update(PFlashCFI01 *pfl, int offset, + int size) + { + int offset_end; ++ int ret; + if (pfl->blk) { + offset_end = offset + size; + /* widen to sector boundaries */ + offset = QEMU_ALIGN_DOWN(offset, BDRV_SECTOR_SIZE); + offset_end = QEMU_ALIGN_UP(offset_end, BDRV_SECTOR_SIZE); +- blk_pwrite(pfl->blk, offset, pfl->storage + offset, ++ ret = blk_pwrite(pfl->blk, offset, pfl->storage + offset, + offset_end - offset, 0); ++ if (ret < 0) { ++ /* TODO set error bit in status */ ++ error_report("Could not update PFLASH: %s", strerror(-ret)); ++ } + } + } + +diff --git a/hw/block/pflash_cfi02.c b/hw/block/pflash_cfi02.c +index c277b0309d..ac7e34ecbf 100644 +--- a/hw/block/pflash_cfi02.c ++++ b/hw/block/pflash_cfi02.c +@@ -37,6 +37,7 @@ + #include "hw/block/flash.h" + #include "hw/qdev-properties.h" + #include "qapi/error.h" ++#include "qemu/error-report.h" + #include "qemu/bitmap.h" + #include "qemu/timer.h" + #include "sysemu/block-backend.h" +@@ -393,13 +394,18 @@ static uint64_t pflash_read(void *opaque, hwaddr offset, unsigned int width) + static void pflash_update(PFlashCFI02 *pfl, int offset, int size) + { + int offset_end; ++ int ret; + if (pfl->blk) { + offset_end = offset + size; + /* widen to sector boundaries */ + offset = QEMU_ALIGN_DOWN(offset, BDRV_SECTOR_SIZE); + offset_end = QEMU_ALIGN_UP(offset_end, BDRV_SECTOR_SIZE); +- blk_pwrite(pfl->blk, offset, pfl->storage + offset, ++ ret = blk_pwrite(pfl->blk, offset, pfl->storage + offset, + offset_end - offset, 0); ++ if (ret < 0) { ++ /* TODO set error bit in status */ ++ error_report("Could not update PFLASH: %s", strerror(-ret)); ++ } + } + } + +-- +2.23.0 + diff --git a/hw-block-pflash_cfi01-Document-use-of-non-CFI-compli.patch b/hw-block-pflash_cfi01-Document-use-of-non-CFI-compli.patch new file mode 100644 index 0000000000000000000000000000000000000000..8ad5f4ba0ce57fd46b186d47a8bdfd1ae9f23ea7 --- /dev/null +++ b/hw-block-pflash_cfi01-Document-use-of-non-CFI-compli.patch @@ -0,0 +1,92 @@ +From aba53a12bd56902e874b168b07c2ecd7a99e7878 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Tue, 16 Jul 2019 19:06:56 +0200 +Subject: [PATCH 637/709] hw/block/pflash_cfi01: Document use of non-CFI + compliant command '0x00' +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The command 0x00 is used by this model since its origin (commit +05ee37ebf630). In this commit the command is described with a +amusing '/* ??? */' comment, probably meaning 'FIXME'. + + switch (cmd) { + case 0x00: /* ??? */ + ... + +This comment survived 12 years because the 0x00 value is indeed +not specified by the CFI open standard (as of this commit). + +The 'cmd' field is transfered during migration. To keep the +migration feature working with older QEMU version, we have to +take a lot of care with migrated field. We figured out it is +too late to remove a non-specified value from this model +(this would make migration review very complex). It is however +not too late to improve the documentation. + +Add few comments to remember this is a special value related +to QEMU, and we won't find information about it on the CFI +spec. + +Reviewed-by: Alistair Francis +Message-Id: <20190716221555.11145-3-philmd@redhat.com> +Signed-off-by: Philippe Mathieu-Daudé +--- + hw/block/pflash_cfi01.c | 18 +++++++++++++----- + 1 file changed, 13 insertions(+), 5 deletions(-) + +diff --git a/hw/block/pflash_cfi01.c b/hw/block/pflash_cfi01.c +index d67f84d655..3cd483d26a 100644 +--- a/hw/block/pflash_cfi01.c ++++ b/hw/block/pflash_cfi01.c +@@ -278,9 +278,13 @@ static uint32_t pflash_read(PFlashCFI01 *pfl, hwaddr offset, + /* This should never happen : reset state & treat it as a read */ + DPRINTF("%s: unknown command state: %x\n", __func__, pfl->cmd); + pfl->wcycle = 0; +- pfl->cmd = 0; ++ /* ++ * The command 0x00 is not assigned by the CFI open standard, ++ * but QEMU historically uses it for the READ_ARRAY command (0xff). ++ */ ++ pfl->cmd = 0x00; + /* fall through to read code */ +- case 0x00: ++ case 0x00: /* This model reset value for READ_ARRAY (not CFI compliant) */ + /* Flash area read */ + ret = pflash_data_read(pfl, offset, width, be); + break; +@@ -449,7 +453,7 @@ static void pflash_write(PFlashCFI01 *pfl, hwaddr offset, + case 0: + /* read mode */ + switch (cmd) { +- case 0x00: /* ??? */ ++ case 0x00: /* This model reset value for READ_ARRAY (not CFI) */ + goto reset_flash; + case 0x10: /* Single Byte Program */ + case 0x40: /* Single Byte Program */ +@@ -646,7 +650,7 @@ static void pflash_write(PFlashCFI01 *pfl, hwaddr offset, + trace_pflash_reset(); + memory_region_rom_device_set_romd(&pfl->mem, true); + pfl->wcycle = 0; +- pfl->cmd = 0; ++ pfl->cmd = 0x00; /* This model reset value for READ_ARRAY (not CFI) */ + } + + +@@ -762,7 +766,11 @@ static void pflash_cfi01_realize(DeviceState *dev, Error **errp) + } + + pfl->wcycle = 0; +- pfl->cmd = 0; ++ /* ++ * The command 0x00 is not assigned by the CFI open standard, ++ * but QEMU historically uses it for the READ_ARRAY command (0xff). ++ */ ++ pfl->cmd = 0x00; + pfl->status = 0x80; /* WSM ready */ + /* Hardcoded CFI table */ + /* Standard "QRY" string */ +-- +2.23.0 + diff --git a/hw-block-pflash_cfi01-Removed-an-unused-timer.patch b/hw-block-pflash_cfi01-Removed-an-unused-timer.patch new file mode 100644 index 0000000000000000000000000000000000000000..86d99586c08391ed6342403d2bfb580ecae479e6 --- /dev/null +++ b/hw-block-pflash_cfi01-Removed-an-unused-timer.patch @@ -0,0 +1,78 @@ +From d23048c05cf0a1b9d72b6937a087cb5ed0e14e50 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Sat, 4 May 2019 18:52:40 +0200 +Subject: [PATCH 636/709] hw/block/pflash_cfi01: Removed an unused timer +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The 'CFI02' NOR flash was introduced in commit 29133e9a0fff, with +timing modelled. One year later, the CFI01 model was introduced +(commit 05ee37ebf630) based on the CFI02 model. As noted in the +header, "It does not support timings". 12 years later, we never +had to model the device timings. Time to remove the unused timer, +we can still add it back if required. + +Suggested-by: Laszlo Ersek +Reviewed-by: Wei Yang +Reviewed-by: Laszlo Ersek +Reviewed-by: Alistair Francis +Tested-by: Laszlo Ersek +[Laszlo Ersek: Regression tested EDK2 OVMF IA32X64, ArmVirtQemu Aarch64 +https://lists.gnu.org/archive/html/qemu-devel/2019-07/msg04373.html] +Message-Id: <20190716221555.11145-2-philmd@redhat.com> +Signed-off-by: Philippe Mathieu-Daudé +--- + hw/block/pflash_cfi01.c | 15 --------------- + 1 file changed, 15 deletions(-) + +diff --git a/hw/block/pflash_cfi01.c b/hw/block/pflash_cfi01.c +index 8e8887253d..d67f84d655 100644 +--- a/hw/block/pflash_cfi01.c ++++ b/hw/block/pflash_cfi01.c +@@ -42,7 +42,6 @@ + #include "hw/qdev-properties.h" + #include "sysemu/block-backend.h" + #include "qapi/error.h" +-#include "qemu/timer.h" + #include "qemu/bitops.h" + #include "qemu/error-report.h" + #include "qemu/host-utils.h" +@@ -91,7 +90,6 @@ struct PFlashCFI01 { + uint8_t cfi_table[0x52]; + uint64_t counter; + unsigned int writeblock_size; +- QEMUTimer *timer; + MemoryRegion mem; + char *name; + void *storage; +@@ -115,18 +113,6 @@ static const VMStateDescription vmstate_pflash = { + } + }; + +-static void pflash_timer (void *opaque) +-{ +- PFlashCFI01 *pfl = opaque; +- +- trace_pflash_timer_expired(pfl->cmd); +- /* Reset flash */ +- pfl->status ^= 0x80; +- memory_region_rom_device_set_romd(&pfl->mem, true); +- pfl->wcycle = 0; +- pfl->cmd = 0; +-} +- + /* Perform a CFI query based on the bank width of the flash. + * If this code is called we know we have a device_width set for + * this flash. +@@ -775,7 +761,6 @@ static void pflash_cfi01_realize(DeviceState *dev, Error **errp) + pfl->max_device_width = pfl->device_width; + } + +- pfl->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, pflash_timer, pfl); + pfl->wcycle = 0; + pfl->cmd = 0; + pfl->status = 0x80; /* WSM ready */ +-- +2.23.0 + diff --git a/hw-block-pflash_cfi01-Rename-reset_flash-label-as-mo.patch b/hw-block-pflash_cfi01-Rename-reset_flash-label-as-mo.patch new file mode 100644 index 0000000000000000000000000000000000000000..000a1d122709efc225e2185d756d88bf1f2d4ffa --- /dev/null +++ b/hw-block-pflash_cfi01-Rename-reset_flash-label-as-mo.patch @@ -0,0 +1,121 @@ +From 3072182dc177886edabbdc548b4640bb32d82269 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Tue, 16 Jul 2019 19:11:57 +0200 +Subject: [PATCH 638/709] hw/block/pflash_cfi01: Rename 'reset_flash' label as + 'mode_read_array' +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Rename the 'reset_flash' as 'mode_read_array' to make explicit we +do not reset the device, we simply set its internal state machine +in the READ_ARRAY mode. We do not reset the status register error +bits, as a device reset would do. + +Reviewed-by: John Snow +Reviewed-by: Alistair Francis +Message-Id: <20190716221555.11145-5-philmd@redhat.com> +Signed-off-by: Philippe Mathieu-Daudé +--- + hw/block/pflash_cfi01.c | 30 +++++++++++++++--------------- + 1 file changed, 15 insertions(+), 15 deletions(-) + +diff --git a/hw/block/pflash_cfi01.c b/hw/block/pflash_cfi01.c +index 3cd483d26a..2ca173aa46 100644 +--- a/hw/block/pflash_cfi01.c ++++ b/hw/block/pflash_cfi01.c +@@ -454,7 +454,7 @@ static void pflash_write(PFlashCFI01 *pfl, hwaddr offset, + /* read mode */ + switch (cmd) { + case 0x00: /* This model reset value for READ_ARRAY (not CFI) */ +- goto reset_flash; ++ goto mode_read_array; + case 0x10: /* Single Byte Program */ + case 0x40: /* Single Byte Program */ + DPRINTF("%s: Single Byte Program\n", __func__); +@@ -477,7 +477,7 @@ static void pflash_write(PFlashCFI01 *pfl, hwaddr offset, + case 0x50: /* Clear status bits */ + DPRINTF("%s: Clear status bits\n", __func__); + pfl->status = 0x0; +- goto reset_flash; ++ goto mode_read_array; + case 0x60: /* Block (un)lock */ + DPRINTF("%s: Block unlock\n", __func__); + break; +@@ -502,10 +502,10 @@ static void pflash_write(PFlashCFI01 *pfl, hwaddr offset, + break; + case 0xf0: /* Probe for AMD flash */ + DPRINTF("%s: Probe for AMD flash\n", __func__); +- goto reset_flash; +- case 0xff: /* Read array mode */ ++ goto mode_read_array; ++ case 0xff: /* Read Array */ + DPRINTF("%s: Read array mode\n", __func__); +- goto reset_flash; ++ goto mode_read_array; + default: + goto error_flash; + } +@@ -531,8 +531,8 @@ static void pflash_write(PFlashCFI01 *pfl, hwaddr offset, + if (cmd == 0xd0) { /* confirm */ + pfl->wcycle = 0; + pfl->status |= 0x80; +- } else if (cmd == 0xff) { /* read array mode */ +- goto reset_flash; ++ } else if (cmd == 0xff) { /* Read Array */ ++ goto mode_read_array; + } else + goto error_flash; + +@@ -558,16 +558,16 @@ static void pflash_write(PFlashCFI01 *pfl, hwaddr offset, + } else if (cmd == 0x01) { + pfl->wcycle = 0; + pfl->status |= 0x80; +- } else if (cmd == 0xff) { +- goto reset_flash; ++ } else if (cmd == 0xff) { /* Read Array */ ++ goto mode_read_array; + } else { + DPRINTF("%s: Unknown (un)locking command\n", __func__); +- goto reset_flash; ++ goto mode_read_array; + } + break; + case 0x98: +- if (cmd == 0xff) { +- goto reset_flash; ++ if (cmd == 0xff) { /* Read Array */ ++ goto mode_read_array; + } else { + DPRINTF("%s: leaving query mode\n", __func__); + } +@@ -627,7 +627,7 @@ static void pflash_write(PFlashCFI01 *pfl, hwaddr offset, + " the data is already written to storage!\n" + "Flash device reset into READ mode.\n", + __func__); +- goto reset_flash; ++ goto mode_read_array; + } + break; + default: +@@ -637,7 +637,7 @@ static void pflash_write(PFlashCFI01 *pfl, hwaddr offset, + default: + /* Should never happen */ + DPRINTF("%s: invalid write state\n", __func__); +- goto reset_flash; ++ goto mode_read_array; + } + return; + +@@ -646,7 +646,7 @@ static void pflash_write(PFlashCFI01 *pfl, hwaddr offset, + "(offset " TARGET_FMT_plx ", wcycle 0x%x cmd 0x%x value 0x%x)" + "\n", __func__, offset, pfl->wcycle, pfl->cmd, value); + +- reset_flash: ++ mode_read_array: + trace_pflash_reset(); + memory_region_rom_device_set_romd(&pfl->mem, true); + pfl->wcycle = 0; +-- +2.23.0 + diff --git a/hw-char-cadence_uart-add-clock-support.patch b/hw-char-cadence_uart-add-clock-support.patch new file mode 100644 index 0000000000000000000000000000000000000000..e9db5734a350daa453bf729eb734671eb9192243 --- /dev/null +++ b/hw-char-cadence_uart-add-clock-support.patch @@ -0,0 +1,232 @@ +From b636db306e06ee1c267d6e15e3b5bc109252617f Mon Sep 17 00:00:00 2001 +From: Damien Hedde +Date: Mon, 6 Apr 2020 15:52:49 +0200 +Subject: [PATCH 108/709] hw/char/cadence_uart: add clock support + +Switch the cadence uart to multi-phase reset and add the +reference clock input. + +The input clock frequency is added to the migration structure. + +The reference clock controls the baudrate generation. If it disabled, +any input characters and events are ignored. + +If this clock remains unconnected, the uart behaves as before +(it default to a 50MHz ref clock). + +Signed-off-by: Damien Hedde +Reviewed-by: Edgar E. Iglesias +Reviewed-by: Alistair Francis +Message-id: 20200406135251.157596-8-damien.hedde@greensocs.com +Signed-off-by: Peter Maydell +--- + hw/char/cadence_uart.c | 73 +++++++++++++++++++++++++++++----- + hw/char/trace-events | 3 ++ + include/hw/char/cadence_uart.h | 1 + + 3 files changed, 67 insertions(+), 10 deletions(-) + +diff --git a/hw/char/cadence_uart.c b/hw/char/cadence_uart.c +index 22e47972f1..e196906c92 100644 +--- a/hw/char/cadence_uart.c ++++ b/hw/char/cadence_uart.c +@@ -31,6 +31,8 @@ + #include "qemu/module.h" + #include "hw/char/cadence_uart.h" + #include "hw/irq.h" ++#include "hw/qdev-clock.h" ++#include "trace.h" + + #ifdef CADENCE_UART_ERR_DEBUG + #define DB_PRINT(...) do { \ +@@ -97,7 +99,7 @@ + #define LOCAL_LOOPBACK (0x2 << UART_MR_CHMODE_SH) + #define REMOTE_LOOPBACK (0x3 << UART_MR_CHMODE_SH) + +-#define UART_INPUT_CLK 50000000 ++#define UART_DEFAULT_REF_CLK (50 * 1000 * 1000) + + #define R_CR (0x00/4) + #define R_MR (0x04/4) +@@ -171,12 +173,15 @@ static void uart_send_breaks(CadenceUARTState *s) + static void uart_parameters_setup(CadenceUARTState *s) + { + QEMUSerialSetParams ssp; +- unsigned int baud_rate, packet_size; ++ unsigned int baud_rate, packet_size, input_clk; ++ input_clk = clock_get_hz(s->refclk); + +- baud_rate = (s->r[R_MR] & UART_MR_CLKS) ? +- UART_INPUT_CLK / 8 : UART_INPUT_CLK; ++ baud_rate = (s->r[R_MR] & UART_MR_CLKS) ? input_clk / 8 : input_clk; ++ baud_rate /= (s->r[R_BRGR] * (s->r[R_BDIV] + 1)); ++ trace_cadence_uart_baudrate(baud_rate); ++ ++ ssp.speed = baud_rate; + +- ssp.speed = baud_rate / (s->r[R_BRGR] * (s->r[R_BDIV] + 1)); + packet_size = 1; + + switch (s->r[R_MR] & UART_MR_PAR) { +@@ -215,6 +220,13 @@ static void uart_parameters_setup(CadenceUARTState *s) + } + + packet_size += ssp.data_bits + ssp.stop_bits; ++ if (ssp.speed == 0) { ++ /* ++ * Avoid division-by-zero below. ++ * TODO: find something better ++ */ ++ ssp.speed = 1; ++ } + s->char_tx_time = (NANOSECONDS_PER_SECOND / ssp.speed) * packet_size; + qemu_chr_fe_ioctl(&s->chr, CHR_IOCTL_SERIAL_SET_PARAMS, &ssp); + } +@@ -340,6 +352,11 @@ static void uart_receive(void *opaque, const uint8_t *buf, int size) + CadenceUARTState *s = opaque; + uint32_t ch_mode = s->r[R_MR] & UART_MR_CHMODE; + ++ /* ignore characters when unclocked or in reset */ ++ if (!clock_is_enabled(s->refclk) || device_is_in_reset(DEVICE(s))) { ++ return; ++ } ++ + if (ch_mode == NORMAL_MODE || ch_mode == ECHO_MODE) { + uart_write_rx_fifo(opaque, buf, size); + } +@@ -353,6 +370,11 @@ static void uart_event(void *opaque, QEMUChrEvent event) + CadenceUARTState *s = opaque; + uint8_t buf = '\0'; + ++ /* ignore characters when unclocked or in reset */ ++ if (!clock_is_enabled(s->refclk) || device_is_in_reset(DEVICE(s))) { ++ return; ++ } ++ + if (event == CHR_EVENT_BREAK) { + uart_write_rx_fifo(opaque, &buf, 1); + } +@@ -462,9 +484,9 @@ static const MemoryRegionOps uart_ops = { + .endianness = DEVICE_NATIVE_ENDIAN, + }; + +-static void cadence_uart_reset(DeviceState *dev) ++static void cadence_uart_reset_init(Object *obj, ResetType type) + { +- CadenceUARTState *s = CADENCE_UART(dev); ++ CadenceUARTState *s = CADENCE_UART(obj); + + s->r[R_CR] = 0x00000128; + s->r[R_IMR] = 0; +@@ -473,6 +495,11 @@ static void cadence_uart_reset(DeviceState *dev) + s->r[R_BRGR] = 0x0000028B; + s->r[R_BDIV] = 0x0000000F; + s->r[R_TTRIG] = 0x00000020; ++} ++ ++static void cadence_uart_reset_hold(Object *obj) ++{ ++ CadenceUARTState *s = CADENCE_UART(obj); + + uart_rx_reset(s); + uart_tx_reset(s); +@@ -491,6 +518,14 @@ static void cadence_uart_realize(DeviceState *dev, Error **errp) + uart_event, NULL, s, NULL, true); + } + ++static void cadence_uart_refclk_update(void *opaque) ++{ ++ CadenceUARTState *s = opaque; ++ ++ /* recompute uart's speed on clock change */ ++ uart_parameters_setup(s); ++} ++ + static void cadence_uart_init(Object *obj) + { + SysBusDevice *sbd = SYS_BUS_DEVICE(obj); +@@ -500,9 +535,23 @@ static void cadence_uart_init(Object *obj) + sysbus_init_mmio(sbd, &s->iomem); + sysbus_init_irq(sbd, &s->irq); + ++ s->refclk = qdev_init_clock_in(DEVICE(obj), "refclk", ++ cadence_uart_refclk_update, s); ++ /* initialize the frequency in case the clock remains unconnected */ ++ clock_set_hz(s->refclk, UART_DEFAULT_REF_CLK); ++ + s->char_tx_time = (NANOSECONDS_PER_SECOND / 9600) * 10; + } + ++static int cadence_uart_pre_load(void *opaque) ++{ ++ CadenceUARTState *s = opaque; ++ ++ /* the frequency will be overriden if the refclk field is present */ ++ clock_set_hz(s->refclk, UART_DEFAULT_REF_CLK); ++ return 0; ++} ++ + static int cadence_uart_post_load(void *opaque, int version_id) + { + CadenceUARTState *s = opaque; +@@ -521,8 +570,9 @@ static int cadence_uart_post_load(void *opaque, int version_id) + + static const VMStateDescription vmstate_cadence_uart = { + .name = "cadence_uart", +- .version_id = 2, ++ .version_id = 3, + .minimum_version_id = 2, ++ .pre_load = cadence_uart_pre_load, + .post_load = cadence_uart_post_load, + .fields = (VMStateField[]) { + VMSTATE_UINT32_ARRAY(r, CadenceUARTState, CADENCE_UART_R_MAX), +@@ -534,8 +584,9 @@ static const VMStateDescription vmstate_cadence_uart = { + VMSTATE_UINT32(tx_count, CadenceUARTState), + VMSTATE_UINT32(rx_wpos, CadenceUARTState), + VMSTATE_TIMER_PTR(fifo_trigger_handle, CadenceUARTState), ++ VMSTATE_CLOCK_V(refclk, CadenceUARTState, 3), + VMSTATE_END_OF_LIST() +- } ++ }, + }; + + static Property cadence_uart_properties[] = { +@@ -546,10 +597,12 @@ static Property cadence_uart_properties[] = { + static void cadence_uart_class_init(ObjectClass *klass, void *data) + { + DeviceClass *dc = DEVICE_CLASS(klass); ++ ResettableClass *rc = RESETTABLE_CLASS(klass); + + dc->realize = cadence_uart_realize; + dc->vmsd = &vmstate_cadence_uart; +- dc->reset = cadence_uart_reset; ++ rc->phases.enter = cadence_uart_reset_init; ++ rc->phases.hold = cadence_uart_reset_hold; + device_class_set_props(dc, cadence_uart_properties); + } + +diff --git a/hw/char/trace-events b/hw/char/trace-events +index 6f938301d9..d20eafd56f 100644 +--- a/hw/char/trace-events ++++ b/hw/char/trace-events +@@ -97,3 +97,6 @@ exynos_uart_wo_read(uint32_t channel, const char *name, uint32_t reg) "UART%d: T + exynos_uart_rxsize(uint32_t channel, uint32_t size) "UART%d: Rx FIFO size: %d" + exynos_uart_channel_error(uint32_t channel) "Wrong UART channel number: %d" + exynos_uart_rx_timeout(uint32_t channel, uint32_t stat, uint32_t intsp) "UART%d: Rx timeout stat=0x%x intsp=0x%x" ++ ++# hw/char/cadence_uart.c ++cadence_uart_baudrate(unsigned baudrate) "baudrate %u" +diff --git a/include/hw/char/cadence_uart.h b/include/hw/char/cadence_uart.h +index 47cec956c4..2a179a572f 100644 +--- a/include/hw/char/cadence_uart.h ++++ b/include/hw/char/cadence_uart.h +@@ -49,6 +49,7 @@ typedef struct { + CharBackend chr; + qemu_irq irq; + QEMUTimer *fifo_trigger_handle; ++ Clock *refclk; + } CadenceUARTState; + + static inline DeviceState *cadence_uart_create(hwaddr addr, +-- +2.23.0 + diff --git a/hw-char-xilinx_uartlite-Replace-hw_error-by-qemu_log.patch b/hw-char-xilinx_uartlite-Replace-hw_error-by-qemu_log.patch new file mode 100644 index 0000000000000000000000000000000000000000..da05e177b24f1fd94321556c949ec3627d3428a6 --- /dev/null +++ b/hw-char-xilinx_uartlite-Replace-hw_error-by-qemu_log.patch @@ -0,0 +1,50 @@ +From 492edf3e3038760aa6b7eb6a9bfdb648d4fa9b80 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Mon, 18 May 2020 16:03:08 +0200 +Subject: [PATCH 628/709] hw/char/xilinx_uartlite: Replace hw_error() by + qemu_log_mask() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +hw_error() calls exit(). This a bit overkill when we can log +the accesses as unimplemented or guest error. + +When fuzzing the devices, we don't want the whole process to +exit. Replace some hw_error() calls by qemu_log_mask(). + +Reviewed-by: Edgar E. Iglesias +Signed-off-by: Philippe Mathieu-Daudé +Reviewed-by: Alistair Francis +Message-id: 20200518140309.5220-4-f4bug@amsat.org +Signed-off-by: Peter Maydell +--- + hw/char/xilinx_uartlite.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/hw/char/xilinx_uartlite.c b/hw/char/xilinx_uartlite.c +index c6512285d7..ae4ccd00c7 100644 +--- a/hw/char/xilinx_uartlite.c ++++ b/hw/char/xilinx_uartlite.c +@@ -23,7 +23,7 @@ + */ + + #include "qemu/osdep.h" +-#include "hw/hw.h" ++#include "qemu/log.h" + #include "hw/irq.h" + #include "hw/qdev-properties.h" + #include "hw/sysbus.h" +@@ -135,7 +135,8 @@ uart_write(void *opaque, hwaddr addr, + switch (addr) + { + case R_STATUS: +- hw_error("write to UART STATUS?\n"); ++ qemu_log_mask(LOG_GUEST_ERROR, "%s: write to UART STATUS\n", ++ __func__); + break; + + case R_CTRL: +-- +2.23.0 + diff --git a/hw-core-clock-introduce-clock-object.patch b/hw-core-clock-introduce-clock-object.patch new file mode 100644 index 0000000000000000000000000000000000000000..0e61f7a407890aa9714c24ef6b1066c3d05d5d43 --- /dev/null +++ b/hw-core-clock-introduce-clock-object.patch @@ -0,0 +1,422 @@ +From 4cba075efedde66f0a8658001da7fc09a09024e1 Mon Sep 17 00:00:00 2001 +From: Peter Maydell +Date: Fri, 17 Apr 2020 16:54:28 +0100 +Subject: [PATCH 102/709] hw/core/clock: introduce clock object + +This object may be used to represent a clock inside a clock tree. + +A clock may be connected to another clock so that it receives update, +through a callback, whenever the source/parent clock is updated. + +Although only the root clock of a clock tree controls the values +(represented as periods) of all clocks in tree, each clock holds +a local state containing the current value so that it can be fetched +independently. It will allows us to fullfill migration requirements +by migrating each clock independently of others. + +This is based on the original work of Frederic Konrad. + +Signed-off-by: Damien Hedde +Reviewed-by: Alistair Francis +Reviewed-by: Edgar E. Iglesias +Message-id: 20200406135251.157596-2-damien.hedde@greensocs.com +[PMM: Use uint64_t rather than unsigned long long in trace events; + the dtrace backend can't handle the latter] +Signed-off-by: Peter Maydell +--- + hw/core/Makefile.objs | 1 + + hw/core/clock.c | 130 +++++++++++++++++++++++++ + hw/core/trace-events | 7 ++ + include/hw/clock.h | 216 ++++++++++++++++++++++++++++++++++++++++++ + 4 files changed, 354 insertions(+) + create mode 100644 hw/core/clock.c + create mode 100644 include/hw/clock.h + +diff --git a/hw/core/Makefile.objs b/hw/core/Makefile.objs +index 6215e7c208..1d9b0aa205 100644 +--- a/hw/core/Makefile.objs ++++ b/hw/core/Makefile.objs +@@ -7,6 +7,7 @@ common-obj-y += hotplug.o + common-obj-y += vmstate-if.o + # irq.o needed for qdev GPIO handling: + common-obj-y += irq.o ++common-obj-y += clock.o + + common-obj-$(CONFIG_SOFTMMU) += reset.o + common-obj-$(CONFIG_SOFTMMU) += qdev-fw.o +diff --git a/hw/core/clock.c b/hw/core/clock.c +new file mode 100644 +index 0000000000..3c0daf7d4c +--- /dev/null ++++ b/hw/core/clock.c +@@ -0,0 +1,130 @@ ++/* ++ * Hardware Clocks ++ * ++ * Copyright GreenSocs 2016-2020 ++ * ++ * Authors: ++ * Frederic Konrad ++ * Damien Hedde ++ * ++ * 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 "hw/clock.h" ++#include "trace.h" ++ ++#define CLOCK_PATH(_clk) (_clk->canonical_path) ++ ++void clock_setup_canonical_path(Clock *clk) ++{ ++ g_free(clk->canonical_path); ++ clk->canonical_path = object_get_canonical_path(OBJECT(clk)); ++} ++ ++void clock_set_callback(Clock *clk, ClockCallback *cb, void *opaque) ++{ ++ clk->callback = cb; ++ clk->callback_opaque = opaque; ++} ++ ++void clock_clear_callback(Clock *clk) ++{ ++ clock_set_callback(clk, NULL, NULL); ++} ++ ++void clock_set(Clock *clk, uint64_t period) ++{ ++ trace_clock_set(CLOCK_PATH(clk), CLOCK_PERIOD_TO_NS(clk->period), ++ CLOCK_PERIOD_TO_NS(period)); ++ clk->period = period; ++} ++ ++static void clock_propagate_period(Clock *clk, bool call_callbacks) ++{ ++ Clock *child; ++ ++ QLIST_FOREACH(child, &clk->children, sibling) { ++ if (child->period != clk->period) { ++ child->period = clk->period; ++ trace_clock_update(CLOCK_PATH(child), CLOCK_PATH(clk), ++ CLOCK_PERIOD_TO_NS(clk->period), ++ call_callbacks); ++ if (call_callbacks && child->callback) { ++ child->callback(child->callback_opaque); ++ } ++ clock_propagate_period(child, call_callbacks); ++ } ++ } ++} ++ ++void clock_propagate(Clock *clk) ++{ ++ assert(clk->source == NULL); ++ trace_clock_propagate(CLOCK_PATH(clk)); ++ clock_propagate_period(clk, true); ++} ++ ++void clock_set_source(Clock *clk, Clock *src) ++{ ++ /* changing clock source is not supported */ ++ assert(!clk->source); ++ ++ trace_clock_set_source(CLOCK_PATH(clk), CLOCK_PATH(src)); ++ ++ clk->period = src->period; ++ QLIST_INSERT_HEAD(&src->children, clk, sibling); ++ clk->source = src; ++ clock_propagate_period(clk, false); ++} ++ ++static void clock_disconnect(Clock *clk) ++{ ++ if (clk->source == NULL) { ++ return; ++ } ++ ++ trace_clock_disconnect(CLOCK_PATH(clk)); ++ ++ clk->source = NULL; ++ QLIST_REMOVE(clk, sibling); ++} ++ ++static void clock_initfn(Object *obj) ++{ ++ Clock *clk = CLOCK(obj); ++ ++ QLIST_INIT(&clk->children); ++} ++ ++static void clock_finalizefn(Object *obj) ++{ ++ Clock *clk = CLOCK(obj); ++ Clock *child, *next; ++ ++ /* clear our list of children */ ++ QLIST_FOREACH_SAFE(child, &clk->children, sibling, next) { ++ clock_disconnect(child); ++ } ++ ++ /* remove us from source's children list */ ++ clock_disconnect(clk); ++ ++ g_free(clk->canonical_path); ++} ++ ++static const TypeInfo clock_info = { ++ .name = TYPE_CLOCK, ++ .parent = TYPE_OBJECT, ++ .instance_size = sizeof(Clock), ++ .instance_init = clock_initfn, ++ .instance_finalize = clock_finalizefn, ++}; ++ ++static void clock_register_types(void) ++{ ++ type_register_static(&clock_info); ++} ++ ++type_init(clock_register_types) +diff --git a/hw/core/trace-events b/hw/core/trace-events +index aecd8e160e..1ac60ede6b 100644 +--- a/hw/core/trace-events ++++ b/hw/core/trace-events +@@ -27,3 +27,10 @@ resettable_phase_exit_begin(void *obj, const char *objtype, unsigned count, int + resettable_phase_exit_exec(void *obj, const char *objtype, int has_method) "obj=%p(%s) method=%d" + resettable_phase_exit_end(void *obj, const char *objtype, unsigned count) "obj=%p(%s) count=%d" + resettable_transitional_function(void *obj, const char *objtype) "obj=%p(%s)" ++ ++# clock.c ++clock_set_source(const char *clk, const char *src) "'%s', src='%s'" ++clock_disconnect(const char *clk) "'%s'" ++clock_set(const char *clk, uint64_t old, uint64_t new) "'%s', ns=%"PRIu64"->%"PRIu64 ++clock_propagate(const char *clk) "'%s'" ++clock_update(const char *clk, const char *src, uint64_t val, int cb) "'%s', src='%s', ns=%"PRIu64", cb=%d" +diff --git a/include/hw/clock.h b/include/hw/clock.h +new file mode 100644 +index 0000000000..e0e19db9bd +--- /dev/null ++++ b/include/hw/clock.h +@@ -0,0 +1,216 @@ ++/* ++ * Hardware Clocks ++ * ++ * Copyright GreenSocs 2016-2020 ++ * ++ * Authors: ++ * Frederic Konrad ++ * Damien Hedde ++ * ++ * This work is licensed under the terms of the GNU GPL, version 2 or later. ++ * See the COPYING file in the top-level directory. ++ */ ++ ++#ifndef QEMU_HW_CLOCK_H ++#define QEMU_HW_CLOCK_H ++ ++#include "qom/object.h" ++#include "qemu/queue.h" ++ ++#define TYPE_CLOCK "clock" ++#define CLOCK(obj) OBJECT_CHECK(Clock, (obj), TYPE_CLOCK) ++ ++typedef void ClockCallback(void *opaque); ++ ++/* ++ * clock store a value representing the clock's period in 2^-32ns unit. ++ * It can represent: ++ * + periods from 2^-32ns up to 4seconds ++ * + frequency from ~0.25Hz 2e10Ghz ++ * Resolution of frequency representation decreases with frequency: ++ * + at 100MHz, resolution is ~2mHz ++ * + at 1Ghz, resolution is ~0.2Hz ++ * + at 10Ghz, resolution is ~20Hz ++ */ ++#define CLOCK_PERIOD_1SEC (1000000000llu << 32) ++ ++/* ++ * macro helpers to convert to hertz / nanosecond ++ */ ++#define CLOCK_PERIOD_FROM_NS(ns) ((ns) * (CLOCK_PERIOD_1SEC / 1000000000llu)) ++#define CLOCK_PERIOD_TO_NS(per) ((per) / (CLOCK_PERIOD_1SEC / 1000000000llu)) ++#define CLOCK_PERIOD_FROM_HZ(hz) (((hz) != 0) ? CLOCK_PERIOD_1SEC / (hz) : 0u) ++#define CLOCK_PERIOD_TO_HZ(per) (((per) != 0) ? CLOCK_PERIOD_1SEC / (per) : 0u) ++ ++/** ++ * Clock: ++ * @parent_obj: parent class ++ * @period: unsigned integer representing the period of the clock ++ * @canonical_path: clock path string cache (used for trace purpose) ++ * @callback: called when clock changes ++ * @callback_opaque: argument for @callback ++ * @source: source (or parent in clock tree) of the clock ++ * @children: list of clocks connected to this one (it is their source) ++ * @sibling: structure used to form a clock list ++ */ ++ ++typedef struct Clock Clock; ++ ++struct Clock { ++ /*< private >*/ ++ Object parent_obj; ++ ++ /* all fields are private and should not be modified directly */ ++ ++ /* fields */ ++ uint64_t period; ++ char *canonical_path; ++ ClockCallback *callback; ++ void *callback_opaque; ++ ++ /* Clocks are organized in a clock tree */ ++ Clock *source; ++ QLIST_HEAD(, Clock) children; ++ QLIST_ENTRY(Clock) sibling; ++}; ++ ++/** ++ * clock_setup_canonical_path: ++ * @clk: clock ++ * ++ * compute the canonical path of the clock (used by log messages) ++ */ ++void clock_setup_canonical_path(Clock *clk); ++ ++/** ++ * clock_set_callback: ++ * @clk: the clock to register the callback into ++ * @cb: the callback function ++ * @opaque: the argument to the callback ++ * ++ * Register a callback called on every clock update. ++ */ ++void clock_set_callback(Clock *clk, ClockCallback *cb, void *opaque); ++ ++/** ++ * clock_clear_callback: ++ * @clk: the clock to delete the callback from ++ * ++ * Unregister the callback registered with clock_set_callback. ++ */ ++void clock_clear_callback(Clock *clk); ++ ++/** ++ * clock_set_source: ++ * @clk: the clock. ++ * @src: the source clock ++ * ++ * Setup @src as the clock source of @clk. The current @src period ++ * value is also copied to @clk and its subtree but no callback is ++ * called. ++ * Further @src update will be propagated to @clk and its subtree. ++ */ ++void clock_set_source(Clock *clk, Clock *src); ++ ++/** ++ * clock_set: ++ * @clk: the clock to initialize. ++ * @value: the clock's value, 0 means unclocked ++ * ++ * Set the local cached period value of @clk to @value. ++ */ ++void clock_set(Clock *clk, uint64_t value); ++ ++static inline void clock_set_hz(Clock *clk, unsigned hz) ++{ ++ clock_set(clk, CLOCK_PERIOD_FROM_HZ(hz)); ++} ++ ++static inline void clock_set_ns(Clock *clk, unsigned ns) ++{ ++ clock_set(clk, CLOCK_PERIOD_FROM_NS(ns)); ++} ++ ++/** ++ * clock_propagate: ++ * @clk: the clock ++ * ++ * Propagate the clock period that has been previously configured using ++ * @clock_set(). This will update recursively all connected clocks. ++ * It is an error to call this function on a clock which has a source. ++ * Note: this function must not be called during device inititialization ++ * or migration. ++ */ ++void clock_propagate(Clock *clk); ++ ++/** ++ * clock_update: ++ * @clk: the clock to update. ++ * @value: the new clock's value, 0 means unclocked ++ * ++ * Update the @clk to the new @value. All connected clocks will be informed ++ * of this update. This is equivalent to call @clock_set() then ++ * @clock_propagate(). ++ */ ++static inline void clock_update(Clock *clk, uint64_t value) ++{ ++ clock_set(clk, value); ++ clock_propagate(clk); ++} ++ ++static inline void clock_update_hz(Clock *clk, unsigned hz) ++{ ++ clock_update(clk, CLOCK_PERIOD_FROM_HZ(hz)); ++} ++ ++static inline void clock_update_ns(Clock *clk, unsigned ns) ++{ ++ clock_update(clk, CLOCK_PERIOD_FROM_NS(ns)); ++} ++ ++/** ++ * clock_get: ++ * @clk: the clk to fetch the clock ++ * ++ * @return: the current period. ++ */ ++static inline uint64_t clock_get(const Clock *clk) ++{ ++ return clk->period; ++} ++ ++static inline unsigned clock_get_hz(Clock *clk) ++{ ++ return CLOCK_PERIOD_TO_HZ(clock_get(clk)); ++} ++ ++static inline unsigned clock_get_ns(Clock *clk) ++{ ++ return CLOCK_PERIOD_TO_NS(clock_get(clk)); ++} ++ ++/** ++ * clock_is_enabled: ++ * @clk: a clock ++ * ++ * @return: true if the clock is running. ++ */ ++static inline bool clock_is_enabled(const Clock *clk) ++{ ++ return clock_get(clk) != 0; ++} ++ ++static inline void clock_init(Clock *clk, uint64_t value) ++{ ++ clock_set(clk, value); ++} ++static inline void clock_init_hz(Clock *clk, uint64_t value) ++{ ++ clock_set_hz(clk, value); ++} ++static inline void clock_init_ns(Clock *clk, uint64_t value) ++{ ++ clock_set_ns(clk, value); ++} ++ ++#endif /* QEMU_HW_CLOCK_H */ +-- +2.23.0 + diff --git a/hw-core-clock-vmstate-define-a-vmstate-entry-for-clo.patch b/hw-core-clock-vmstate-define-a-vmstate-entry-for-clo.patch new file mode 100644 index 0000000000000000000000000000000000000000..2ff4ea1daf5c0bfa0ea8db05446103974ebccfc1 --- /dev/null +++ b/hw-core-clock-vmstate-define-a-vmstate-entry-for-clo.patch @@ -0,0 +1,89 @@ +From b8d38bd5256362355cbc115889213e4892e16ea9 Mon Sep 17 00:00:00 2001 +From: Damien Hedde +Date: Mon, 6 Apr 2020 15:52:44 +0200 +Subject: [PATCH 103/709] hw/core/clock-vmstate: define a vmstate entry for + clock state +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Damien Hedde +Reviewed-by: Peter Maydell +Reviewed-by: Philippe Mathieu-Daudé +Reviewed-by: Alistair Francis +Reviewed-by: Edgar E. Iglesias +Message-id: 20200406135251.157596-3-damien.hedde@greensocs.com +Signed-off-by: Peter Maydell +--- + hw/core/Makefile.objs | 1 + + hw/core/clock-vmstate.c | 25 +++++++++++++++++++++++++ + include/hw/clock.h | 9 +++++++++ + 3 files changed, 35 insertions(+) + create mode 100644 hw/core/clock-vmstate.c + +diff --git a/hw/core/Makefile.objs b/hw/core/Makefile.objs +index 1d9b0aa205..115df55087 100644 +--- a/hw/core/Makefile.objs ++++ b/hw/core/Makefile.objs +@@ -21,6 +21,7 @@ common-obj-$(CONFIG_SOFTMMU) += null-machine.o + common-obj-$(CONFIG_SOFTMMU) += loader.o + common-obj-$(CONFIG_SOFTMMU) += machine-hmp-cmds.o + common-obj-$(CONFIG_SOFTMMU) += numa.o ++common-obj-$(CONFIG_SOFTMMU) += clock-vmstate.o + obj-$(CONFIG_SOFTMMU) += machine-qmp-cmds.o + + common-obj-$(CONFIG_EMPTY_SLOT) += empty_slot.o +diff --git a/hw/core/clock-vmstate.c b/hw/core/clock-vmstate.c +new file mode 100644 +index 0000000000..260b13fc2c +--- /dev/null ++++ b/hw/core/clock-vmstate.c +@@ -0,0 +1,25 @@ ++/* ++ * Clock migration structure ++ * ++ * Copyright GreenSocs 2019-2020 ++ * ++ * Authors: ++ * Damien Hedde ++ * ++ * 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 "migration/vmstate.h" ++#include "hw/clock.h" ++ ++const VMStateDescription vmstate_clock = { ++ .name = "clock", ++ .version_id = 0, ++ .minimum_version_id = 0, ++ .fields = (VMStateField[]) { ++ VMSTATE_UINT64(period, Clock), ++ VMSTATE_END_OF_LIST() ++ } ++}; +diff --git a/include/hw/clock.h b/include/hw/clock.h +index e0e19db9bd..f822a94220 100644 +--- a/include/hw/clock.h ++++ b/include/hw/clock.h +@@ -74,6 +74,15 @@ struct Clock { + QLIST_ENTRY(Clock) sibling; + }; + ++/* ++ * vmstate description entry to be added in device vmsd. ++ */ ++extern const VMStateDescription vmstate_clock; ++#define VMSTATE_CLOCK(field, state) \ ++ VMSTATE_CLOCK_V(field, state, 0) ++#define VMSTATE_CLOCK_V(field, state, version) \ ++ VMSTATE_STRUCT_POINTER_V(field, state, version, vmstate_clock, Clock) ++ + /** + * clock_setup_canonical_path: + * @clk: clock +-- +2.23.0 + diff --git a/hw-core-loader-Fix-possible-crash-in-rom_copy.patch b/hw-core-loader-Fix-possible-crash-in-rom_copy.patch deleted file mode 100644 index d4301f79286d65327d1fc80a5b1dbd958fc92933..0000000000000000000000000000000000000000 --- a/hw-core-loader-Fix-possible-crash-in-rom_copy.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 4f1c6cb2f9afafda05eab150fd2bd284edce6676 Mon Sep 17 00:00:00 2001 -From: Thomas Huth -Date: Wed, 25 Sep 2019 14:16:43 +0200 -Subject: [PATCH] hw/core/loader: Fix possible crash in rom_copy() - -Both, "rom->addr" and "addr" are derived from the binary image -that can be loaded with the "-kernel" paramer. The code in -rom_copy() then calculates: - - d = dest + (rom->addr - addr); - -and uses "d" as destination in a memcpy() some lines later. Now with -bad kernel images, it is possible that rom->addr is smaller than addr, -thus "rom->addr - addr" gets negative and the memcpy() then tries to -copy contents from the image to a bad memory location. This could -maybe be used to inject code from a kernel image into the QEMU binary, -so we better fix it with an additional sanity check here. - -Cc: qemu-stable@nongnu.org -Reported-by: Guangming Liu -Buglink: https://bugs.launchpad.net/qemu/+bug/1844635 -Message-Id: <20190925130331.27825-1-thuth@redhat.com> -Reviewed-by: Michael S. Tsirkin -Signed-off-by: Thomas Huth -(cherry picked from commit e423455c4f23a1a828901c78fe6d03b7dde79319) -Signed-off-by: Michael Roth ---- - hw/core/loader.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/hw/core/loader.c b/hw/core/loader.c -index fe5cb24122..4ef2095247 100644 ---- a/hw/core/loader.c -+++ b/hw/core/loader.c -@@ -1240,7 +1240,7 @@ int rom_copy(uint8_t *dest, hwaddr addr, size_t size) - if (rom->addr + rom->romsize < addr) { - continue; - } -- if (rom->addr > end) { -+ if (rom->addr > end || rom->addr < addr) { - break; - } - --- -2.19.1 - diff --git a/hw-core-register-Add-register_init_block8-helper.patch b/hw-core-register-Add-register_init_block8-helper.patch new file mode 100644 index 0000000000000000000000000000000000000000..3b691c77766b86d278be1863f0bd18fc38cb6749 --- /dev/null +++ b/hw-core-register-Add-register_init_block8-helper.patch @@ -0,0 +1,117 @@ +From f08085f49fb66a5cdc86653bd896d0e728bcee50 Mon Sep 17 00:00:00 2001 +From: Joaquin de Andres +Date: Thu, 2 Apr 2020 18:28:39 +0200 +Subject: [PATCH 265/709] hw/core/register: Add register_init_block8 helper. + +There was no support for 8 bits block registers. Changed +register_init_block32 to be generic and static, adding register +size in bits as parameter. Created one helper for each size. + +Signed-off-by: Joaquin de Andres +Message-Id: <20200402162839.76636-1-me@xcancerberox.com.ar> +Reviewed-by: Alistair Francis +Signed-off-by: Alistair Francis +--- + hw/core/register.c | 46 +++++++++++++++++++++++++++++++++---------- + include/hw/register.h | 8 ++++++++ + 2 files changed, 44 insertions(+), 10 deletions(-) + +diff --git a/hw/core/register.c b/hw/core/register.c +index 3c77396587..ddf91eb445 100644 +--- a/hw/core/register.c ++++ b/hw/core/register.c +@@ -246,16 +246,18 @@ uint64_t register_read_memory(void *opaque, hwaddr addr, + return extract64(read_val, 0, size * 8); + } + +-RegisterInfoArray *register_init_block32(DeviceState *owner, +- const RegisterAccessInfo *rae, +- int num, RegisterInfo *ri, +- uint32_t *data, +- const MemoryRegionOps *ops, +- bool debug_enabled, +- uint64_t memory_size) ++static RegisterInfoArray *register_init_block(DeviceState *owner, ++ const RegisterAccessInfo *rae, ++ int num, RegisterInfo *ri, ++ void *data, ++ const MemoryRegionOps *ops, ++ bool debug_enabled, ++ uint64_t memory_size, ++ size_t data_size_bits) + { + const char *device_prefix = object_get_typename(OBJECT(owner)); + RegisterInfoArray *r_array = g_new0(RegisterInfoArray, 1); ++ int data_size = data_size_bits >> 3; + int i; + + r_array->r = g_new0(RegisterInfo *, num); +@@ -264,12 +266,12 @@ RegisterInfoArray *register_init_block32(DeviceState *owner, + r_array->prefix = device_prefix; + + for (i = 0; i < num; i++) { +- int index = rae[i].addr / 4; ++ int index = rae[i].addr / data_size; + RegisterInfo *r = &ri[index]; + + *r = (RegisterInfo) { +- .data = &data[index], +- .data_size = sizeof(uint32_t), ++ .data = data + data_size * index, ++ .data_size = data_size, + .access = &rae[i], + .opaque = owner, + }; +@@ -284,6 +286,30 @@ RegisterInfoArray *register_init_block32(DeviceState *owner, + return r_array; + } + ++RegisterInfoArray *register_init_block8(DeviceState *owner, ++ const RegisterAccessInfo *rae, ++ int num, RegisterInfo *ri, ++ uint8_t *data, ++ const MemoryRegionOps *ops, ++ bool debug_enabled, ++ uint64_t memory_size) ++{ ++ return register_init_block(owner, rae, num, ri, (void *) ++ data, ops, debug_enabled, memory_size, 8); ++} ++ ++RegisterInfoArray *register_init_block32(DeviceState *owner, ++ const RegisterAccessInfo *rae, ++ int num, RegisterInfo *ri, ++ uint32_t *data, ++ const MemoryRegionOps *ops, ++ bool debug_enabled, ++ uint64_t memory_size) ++{ ++ return register_init_block(owner, rae, num, ri, (void *) ++ data, ops, debug_enabled, memory_size, 32); ++} ++ + void register_finalize_block(RegisterInfoArray *r_array) + { + object_unparent(OBJECT(&r_array->mem)); +diff --git a/include/hw/register.h b/include/hw/register.h +index 5796584588..5d2c565ae0 100644 +--- a/include/hw/register.h ++++ b/include/hw/register.h +@@ -185,6 +185,14 @@ uint64_t register_read_memory(void *opaque, hwaddr addr, unsigned size); + * memory region (r_array->mem) the caller should add to a container. + */ + ++RegisterInfoArray *register_init_block8(DeviceState *owner, ++ const RegisterAccessInfo *rae, ++ int num, RegisterInfo *ri, ++ uint8_t *data, ++ const MemoryRegionOps *ops, ++ bool debug_enabled, ++ uint64_t memory_size); ++ + RegisterInfoArray *register_init_block32(DeviceState *owner, + const RegisterAccessInfo *rae, + int num, RegisterInfo *ri, +-- +2.23.0 + diff --git a/hw-core-stream-Add-an-end-of-packet-flag.patch b/hw-core-stream-Add-an-end-of-packet-flag.patch new file mode 100644 index 0000000000000000000000000000000000000000..ccdd8567d6365d8831b2335f1085fb91a2bdcc5d --- /dev/null +++ b/hw-core-stream-Add-an-end-of-packet-flag.patch @@ -0,0 +1,179 @@ +From 51b19950ca62abce05b00eef30d9ebbfb8b15f46 Mon Sep 17 00:00:00 2001 +From: "Edgar E. Iglesias" +Date: Wed, 6 May 2020 10:25:09 +0200 +Subject: [PATCH 406/709] hw/core: stream: Add an end-of-packet flag + +Some stream clients stream an endless stream of data while +other clients stream data in packets. Stream interfaces +usually have a way to signal the end of a packet or the +last beat of a transfer. + +This adds an end-of-packet flag to the push interface. + +Reviewed-by: Alistair Francis +Reviewed-by: Francisco Iglesias +Signed-off-by: Edgar E. Iglesias +Message-Id: <20200506082513.18751-6-edgar.iglesias@gmail.com> +--- + hw/core/stream.c | 4 ++-- + hw/dma/xilinx_axidma.c | 10 ++++++---- + hw/net/xilinx_axienet.c | 14 ++++++++++---- + hw/ssi/xilinx_spips.c | 2 +- + include/hw/stream.h | 5 +++-- + 5 files changed, 22 insertions(+), 13 deletions(-) + +diff --git a/hw/core/stream.c b/hw/core/stream.c +index 39b1e595cd..a65ad1208d 100644 +--- a/hw/core/stream.c ++++ b/hw/core/stream.c +@@ -3,11 +3,11 @@ + #include "qemu/module.h" + + size_t +-stream_push(StreamSlave *sink, uint8_t *buf, size_t len) ++stream_push(StreamSlave *sink, uint8_t *buf, size_t len, bool eop) + { + StreamSlaveClass *k = STREAM_SLAVE_GET_CLASS(sink); + +- return k->push(sink, buf, len); ++ return k->push(sink, buf, len, eop); + } + + bool +diff --git a/hw/dma/xilinx_axidma.c b/hw/dma/xilinx_axidma.c +index 4540051448..a770e12c96 100644 +--- a/hw/dma/xilinx_axidma.c ++++ b/hw/dma/xilinx_axidma.c +@@ -283,7 +283,7 @@ static void stream_process_mem2s(struct Stream *s, StreamSlave *tx_data_dev, + + if (stream_desc_sof(&s->desc)) { + s->pos = 0; +- stream_push(tx_control_dev, s->desc.app, sizeof(s->desc.app)); ++ stream_push(tx_control_dev, s->desc.app, sizeof(s->desc.app), true); + } + + txlen = s->desc.control & SDESC_CTRL_LEN_MASK; +@@ -298,7 +298,7 @@ static void stream_process_mem2s(struct Stream *s, StreamSlave *tx_data_dev, + s->pos += txlen; + + if (stream_desc_eof(&s->desc)) { +- stream_push(tx_data_dev, s->txbuf, s->pos); ++ stream_push(tx_data_dev, s->txbuf, s->pos, true); + s->pos = 0; + stream_complete(s); + } +@@ -384,7 +384,7 @@ static void xilinx_axidma_reset(DeviceState *dev) + + static size_t + xilinx_axidma_control_stream_push(StreamSlave *obj, unsigned char *buf, +- size_t len) ++ size_t len, bool eop) + { + XilinxAXIDMAStreamSlave *cs = XILINX_AXI_DMA_CONTROL_STREAM(obj); + struct Stream *s = &cs->dma->streams[1]; +@@ -416,12 +416,14 @@ xilinx_axidma_data_stream_can_push(StreamSlave *obj, + } + + static size_t +-xilinx_axidma_data_stream_push(StreamSlave *obj, unsigned char *buf, size_t len) ++xilinx_axidma_data_stream_push(StreamSlave *obj, unsigned char *buf, size_t len, ++ bool eop) + { + XilinxAXIDMAStreamSlave *ds = XILINX_AXI_DMA_DATA_STREAM(obj); + struct Stream *s = &ds->dma->streams[1]; + size_t ret; + ++ assert(eop); + ret = stream_process_s2mem(s, buf, len); + stream_update_irq(s); + return ret; +diff --git a/hw/net/xilinx_axienet.c b/hw/net/xilinx_axienet.c +index c8dfcda3ee..bd48305577 100644 +--- a/hw/net/xilinx_axienet.c ++++ b/hw/net/xilinx_axienet.c +@@ -697,14 +697,14 @@ static void axienet_eth_rx_notify(void *opaque) + axienet_eth_rx_notify, s)) { + size_t ret = stream_push(s->tx_control_dev, + (void *)s->rxapp + CONTROL_PAYLOAD_SIZE +- - s->rxappsize, s->rxappsize); ++ - s->rxappsize, s->rxappsize, true); + s->rxappsize -= ret; + } + + while (s->rxsize && stream_can_push(s->tx_data_dev, + axienet_eth_rx_notify, s)) { + size_t ret = stream_push(s->tx_data_dev, (void *)s->rxmem + s->rxpos, +- s->rxsize); ++ s->rxsize, true); + s->rxsize -= ret; + s->rxpos += ret; + if (!s->rxsize) { +@@ -874,12 +874,14 @@ static ssize_t eth_rx(NetClientState *nc, const uint8_t *buf, size_t size) + } + + static size_t +-xilinx_axienet_control_stream_push(StreamSlave *obj, uint8_t *buf, size_t len) ++xilinx_axienet_control_stream_push(StreamSlave *obj, uint8_t *buf, size_t len, ++ bool eop) + { + int i; + XilinxAXIEnetStreamSlave *cs = XILINX_AXI_ENET_CONTROL_STREAM(obj); + XilinxAXIEnet *s = cs->enet; + ++ assert(eop); + if (len != CONTROL_PAYLOAD_SIZE) { + hw_error("AXI Enet requires %d byte control stream payload\n", + (int)CONTROL_PAYLOAD_SIZE); +@@ -894,11 +896,15 @@ xilinx_axienet_control_stream_push(StreamSlave *obj, uint8_t *buf, size_t len) + } + + static size_t +-xilinx_axienet_data_stream_push(StreamSlave *obj, uint8_t *buf, size_t size) ++xilinx_axienet_data_stream_push(StreamSlave *obj, uint8_t *buf, size_t size, ++ bool eop) + { + XilinxAXIEnetStreamSlave *ds = XILINX_AXI_ENET_DATA_STREAM(obj); + XilinxAXIEnet *s = ds->enet; + ++ /* We don't support fragmented packets yet. */ ++ assert(eop); ++ + /* TX enable ? */ + if (!(s->tc & TC_TX)) { + return size; +diff --git a/hw/ssi/xilinx_spips.c b/hw/ssi/xilinx_spips.c +index c57850a505..4cfce882ab 100644 +--- a/hw/ssi/xilinx_spips.c ++++ b/hw/ssi/xilinx_spips.c +@@ -868,7 +868,7 @@ static void xlnx_zynqmp_qspips_notify(void *opaque) + + memcpy(rq->dma_buf, rxd, num); + +- ret = stream_push(rq->dma, rq->dma_buf, num); ++ ret = stream_push(rq->dma, rq->dma_buf, num, false); + assert(ret == num); + xlnx_zynqmp_qspips_check_flush(rq); + } +diff --git a/include/hw/stream.h b/include/hw/stream.h +index d02f62ca89..ed09e83683 100644 +--- a/include/hw/stream.h ++++ b/include/hw/stream.h +@@ -39,12 +39,13 @@ typedef struct StreamSlaveClass { + * @obj: Stream slave to push to + * @buf: Data to write + * @len: Maximum number of bytes to write ++ * @eop: End of packet flag + */ +- size_t (*push)(StreamSlave *obj, unsigned char *buf, size_t len); ++ size_t (*push)(StreamSlave *obj, unsigned char *buf, size_t len, bool eop); + } StreamSlaveClass; + + size_t +-stream_push(StreamSlave *sink, uint8_t *buf, size_t len); ++stream_push(StreamSlave *sink, uint8_t *buf, size_t len, bool eop); + + bool + stream_can_push(StreamSlave *sink, StreamCanPushNotifyFn notify, +-- +2.23.0 + diff --git a/hw-display-Include-local-framebuffer.h.patch b/hw-display-Include-local-framebuffer.h.patch new file mode 100644 index 0000000000000000000000000000000000000000..9f30d5c9d896b93d75fc6f64e32e8a27ed80721f --- /dev/null +++ b/hw-display-Include-local-framebuffer.h.patch @@ -0,0 +1,49 @@ +From 63dc3465d6e2c1c31769b0d099991ee978e6e311 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Mon, 4 May 2020 10:20:02 +0200 +Subject: [PATCH 508/709] hw/display: Include local 'framebuffer.h' +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The "framebuffer.h" header is not an exported include. + +Signed-off-by: Philippe Mathieu-Daudé +Reviewed-by: Thomas Huth +Reviewed-by: Richard Henderson +Message-id: 20200504082003.16298-2-f4bug@amsat.org +Signed-off-by: Gerd Hoffmann +--- + hw/display/artist.c | 2 +- + hw/display/next-fb.c | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/hw/display/artist.c b/hw/display/artist.c +index 7e2a4556bd..6261bfe65b 100644 +--- a/hw/display/artist.c ++++ b/hw/display/artist.c +@@ -21,7 +21,7 @@ + #include "migration/vmstate.h" + #include "ui/console.h" + #include "trace.h" +-#include "hw/display/framebuffer.h" ++#include "framebuffer.h" + + #define TYPE_ARTIST "artist" + #define ARTIST(obj) OBJECT_CHECK(ARTISTState, (obj), TYPE_ARTIST) +diff --git a/hw/display/next-fb.c b/hw/display/next-fb.c +index 2b726a10f8..b0513a8fba 100644 +--- a/hw/display/next-fb.c ++++ b/hw/display/next-fb.c +@@ -27,7 +27,7 @@ + #include "hw/hw.h" + #include "hw/boards.h" + #include "hw/loader.h" +-#include "hw/display/framebuffer.h" ++#include "framebuffer.h" + #include "ui/pixel_ops.h" + #include "hw/m68k/next-cube.h" + +-- +2.23.0 + diff --git a/hw-dma-xilinx_axidma-Add-DMA-memory-region-property.patch b/hw-dma-xilinx_axidma-Add-DMA-memory-region-property.patch new file mode 100644 index 0000000000000000000000000000000000000000..d0c7a26fbd7ff8846c184512cd5ca968840e346a --- /dev/null +++ b/hw-dma-xilinx_axidma-Add-DMA-memory-region-property.patch @@ -0,0 +1,136 @@ +From e3a8926d0e91e6783157a9934bd6f59c7efaa992 Mon Sep 17 00:00:00 2001 +From: "Edgar E. Iglesias" +Date: Wed, 6 May 2020 10:25:08 +0200 +Subject: [PATCH 405/709] hw/dma/xilinx_axidma: Add DMA memory-region property +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Add DMA memory-region property to externally control what +address-space this DMA operates on. + +Reviewed-by: Alistair Francis +Reviewed-by: Francisco Iglesias +Signed-off-by: Edgar E. Iglesias +Reviewed-by: Philippe Mathieu-Daudé +Message-Id: <20200506082513.18751-5-edgar.iglesias@gmail.com> +--- + hw/dma/xilinx_axidma.c | 30 +++++++++++++++++++++++------- + 1 file changed, 23 insertions(+), 7 deletions(-) + +diff --git a/hw/dma/xilinx_axidma.c b/hw/dma/xilinx_axidma.c +index 018f36991b..4540051448 100644 +--- a/hw/dma/xilinx_axidma.c ++++ b/hw/dma/xilinx_axidma.c +@@ -33,6 +33,7 @@ + #include "qemu/log.h" + #include "qemu/module.h" + ++#include "sysemu/dma.h" + #include "hw/stream.h" + + #define D(x) +@@ -103,6 +104,7 @@ enum { + }; + + struct Stream { ++ struct XilinxAXIDMA *dma; + ptimer_state *ptimer; + qemu_irq irq; + +@@ -125,6 +127,9 @@ struct XilinxAXIDMAStreamSlave { + struct XilinxAXIDMA { + SysBusDevice busdev; + MemoryRegion iomem; ++ MemoryRegion *dma_mr; ++ AddressSpace as; ++ + uint32_t freqhz; + StreamSlave *tx_data_dev; + StreamSlave *tx_control_dev; +@@ -186,7 +191,7 @@ static void stream_desc_load(struct Stream *s, hwaddr addr) + { + struct SDesc *d = &s->desc; + +- cpu_physical_memory_read(addr, d, sizeof *d); ++ address_space_read(&s->dma->as, addr, MEMTXATTRS_UNSPECIFIED, d, sizeof *d); + + /* Convert from LE into host endianness. */ + d->buffer_address = le64_to_cpu(d->buffer_address); +@@ -204,7 +209,8 @@ static void stream_desc_store(struct Stream *s, hwaddr addr) + d->nxtdesc = cpu_to_le64(d->nxtdesc); + d->control = cpu_to_le32(d->control); + d->status = cpu_to_le32(d->status); +- cpu_physical_memory_write(addr, d, sizeof *d); ++ address_space_write(&s->dma->as, addr, MEMTXATTRS_UNSPECIFIED, ++ d, sizeof *d); + } + + static void stream_update_irq(struct Stream *s) +@@ -286,8 +292,9 @@ static void stream_process_mem2s(struct Stream *s, StreamSlave *tx_data_dev, + txlen + s->pos); + } + +- cpu_physical_memory_read(s->desc.buffer_address, +- s->txbuf + s->pos, txlen); ++ address_space_read(&s->dma->as, s->desc.buffer_address, ++ MEMTXATTRS_UNSPECIFIED, ++ s->txbuf + s->pos, txlen); + s->pos += txlen; + + if (stream_desc_eof(&s->desc)) { +@@ -336,7 +343,8 @@ static size_t stream_process_s2mem(struct Stream *s, unsigned char *buf, + rxlen = len; + } + +- cpu_physical_memory_write(s->desc.buffer_address, buf + pos, rxlen); ++ address_space_write(&s->dma->as, s->desc.buffer_address, ++ MEMTXATTRS_UNSPECIFIED, buf + pos, rxlen); + len -= rxlen; + pos += rxlen; + +@@ -525,6 +533,7 @@ static void xilinx_axidma_realize(DeviceState *dev, Error **errp) + XilinxAXIDMAStreamSlave *cs = XILINX_AXI_DMA_CONTROL_STREAM( + &s->rx_control_dev); + Error *local_err = NULL; ++ int i; + + object_property_add_link(OBJECT(ds), "dma", TYPE_XILINX_AXI_DMA, + (Object **)&ds->dma, +@@ -545,17 +554,19 @@ static void xilinx_axidma_realize(DeviceState *dev, Error **errp) + goto xilinx_axidma_realize_fail; + } + +- int i; +- + for (i = 0; i < 2; i++) { + struct Stream *st = &s->streams[i]; + ++ st->dma = s; + st->nr = i; + st->ptimer = ptimer_init(timer_hit, st, PTIMER_POLICY_DEFAULT); + ptimer_transaction_begin(st->ptimer); + ptimer_set_freq(st->ptimer, s->freqhz); + ptimer_transaction_commit(st->ptimer); + } ++ ++ address_space_init(&s->as, ++ s->dma_mr ? s->dma_mr : get_system_memory(), "dma"); + return; + + xilinx_axidma_realize_fail: +@@ -575,6 +586,11 @@ static void xilinx_axidma_init(Object *obj) + &s->rx_control_dev, sizeof(s->rx_control_dev), + TYPE_XILINX_AXI_DMA_CONTROL_STREAM, &error_abort, + NULL); ++ object_property_add_link(obj, "dma", TYPE_MEMORY_REGION, ++ (Object **)&s->dma_mr, ++ qdev_prop_allow_set_link_before_realize, ++ OBJ_PROP_LINK_STRONG, ++ &error_abort); + + sysbus_init_irq(sbd, &s->streams[0].irq); + sysbus_init_irq(sbd, &s->streams[1].irq); +-- +2.23.0 + diff --git a/hw-dma-xilinx_axidma-mm2s-Stream-descriptor-by-descr.patch b/hw-dma-xilinx_axidma-mm2s-Stream-descriptor-by-descr.patch new file mode 100644 index 0000000000000000000000000000000000000000..4963830214e64d26662294e1d5bce8f5d9943f4c --- /dev/null +++ b/hw-dma-xilinx_axidma-mm2s-Stream-descriptor-by-descr.patch @@ -0,0 +1,84 @@ +From 471fe8a2520272253adec1cc099e26f04958e301 Mon Sep 17 00:00:00 2001 +From: "Edgar E. Iglesias" +Date: Wed, 6 May 2020 10:25:11 +0200 +Subject: [PATCH 408/709] hw/dma/xilinx_axidma: mm2s: Stream descriptor by + descriptor + +Stream descriptor by descriptor from memory instead of +buffering entire packets before pushing. This enables +non-packet streaming clients to work and also lifts the +limitation that our internal DMA buffer needs to be able +to hold entire packets. + +Reviewed-by: Alistair Francis +Signed-off-by: Edgar E. Iglesias +Message-Id: <20200506082513.18751-8-edgar.iglesias@gmail.com> +--- + hw/dma/xilinx_axidma.c | 31 +++++++++++++++++-------------- + 1 file changed, 17 insertions(+), 14 deletions(-) + +diff --git a/hw/dma/xilinx_axidma.c b/hw/dma/xilinx_axidma.c +index a770e12c96..101d32a965 100644 +--- a/hw/dma/xilinx_axidma.c ++++ b/hw/dma/xilinx_axidma.c +@@ -111,7 +111,6 @@ struct Stream { + int nr; + + struct SDesc desc; +- int pos; + unsigned int complete_cnt; + uint32_t regs[R_MAX]; + uint8_t app[20]; +@@ -267,7 +266,9 @@ static void stream_process_mem2s(struct Stream *s, StreamSlave *tx_data_dev, + StreamSlave *tx_control_dev) + { + uint32_t prev_d; +- unsigned int txlen; ++ uint32_t txlen; ++ uint64_t addr; ++ bool eop; + + if (!stream_running(s) || stream_idle(s)) { + return; +@@ -282,24 +283,26 @@ static void stream_process_mem2s(struct Stream *s, StreamSlave *tx_data_dev, + } + + if (stream_desc_sof(&s->desc)) { +- s->pos = 0; + stream_push(tx_control_dev, s->desc.app, sizeof(s->desc.app), true); + } + + txlen = s->desc.control & SDESC_CTRL_LEN_MASK; +- if ((txlen + s->pos) > sizeof s->txbuf) { +- hw_error("%s: too small internal txbuf! %d\n", __func__, +- txlen + s->pos); +- } + +- address_space_read(&s->dma->as, s->desc.buffer_address, +- MEMTXATTRS_UNSPECIFIED, +- s->txbuf + s->pos, txlen); +- s->pos += txlen; ++ eop = stream_desc_eof(&s->desc); ++ addr = s->desc.buffer_address; ++ while (txlen) { ++ unsigned int len; ++ ++ len = txlen > sizeof s->txbuf ? sizeof s->txbuf : txlen; ++ address_space_read(&s->dma->as, addr, ++ MEMTXATTRS_UNSPECIFIED, ++ s->txbuf, len); ++ stream_push(tx_data_dev, s->txbuf, len, eop && len == txlen); ++ txlen -= len; ++ addr += len; ++ } + +- if (stream_desc_eof(&s->desc)) { +- stream_push(tx_data_dev, s->txbuf, s->pos, true); +- s->pos = 0; ++ if (eop) { + stream_complete(s); + } + +-- +2.23.0 + diff --git a/hw-dma-xilinx_axidma-s2mm-Support-stream-fragments.patch b/hw-dma-xilinx_axidma-s2mm-Support-stream-fragments.patch new file mode 100644 index 0000000000000000000000000000000000000000..95b05b1d3eb949e0ef7c522418a0aca764669116 --- /dev/null +++ b/hw-dma-xilinx_axidma-s2mm-Support-stream-fragments.patch @@ -0,0 +1,81 @@ +From 734e3befc20b699c69a6e20feade8073b1c19838 Mon Sep 17 00:00:00 2001 +From: "Edgar E. Iglesias" +Date: Wed, 6 May 2020 10:25:12 +0200 +Subject: [PATCH 409/709] hw/dma/xilinx_axidma: s2mm: Support stream fragments + +Add support for stream fragments. + +Reviewed-by: Alistair Francis +Signed-off-by: Edgar E. Iglesias +Message-Id: <20200506082513.18751-9-edgar.iglesias@gmail.com> +--- + hw/dma/xilinx_axidma.c | 14 +++++++------- + 1 file changed, 7 insertions(+), 7 deletions(-) + +diff --git a/hw/dma/xilinx_axidma.c b/hw/dma/xilinx_axidma.c +index 101d32a965..87be9cade7 100644 +--- a/hw/dma/xilinx_axidma.c ++++ b/hw/dma/xilinx_axidma.c +@@ -110,6 +110,7 @@ struct Stream { + + int nr; + ++ bool sof; + struct SDesc desc; + unsigned int complete_cnt; + uint32_t regs[R_MAX]; +@@ -174,6 +175,7 @@ static void stream_reset(struct Stream *s) + { + s->regs[R_DMASR] = DMASR_HALTED; /* starts up halted. */ + s->regs[R_DMACR] = 1 << 16; /* Starts with one in compl threshold. */ ++ s->sof = true; + } + + /* Map an offset addr into a channel index. */ +@@ -321,12 +323,11 @@ static void stream_process_mem2s(struct Stream *s, StreamSlave *tx_data_dev, + } + + static size_t stream_process_s2mem(struct Stream *s, unsigned char *buf, +- size_t len) ++ size_t len, bool eop) + { + uint32_t prev_d; + unsigned int rxlen; + size_t pos = 0; +- int sof = 1; + + if (!stream_running(s) || stream_idle(s)) { + return 0; +@@ -352,16 +353,16 @@ static size_t stream_process_s2mem(struct Stream *s, unsigned char *buf, + pos += rxlen; + + /* Update the descriptor. */ +- if (!len) { ++ if (eop) { + stream_complete(s); + memcpy(s->desc.app, s->app, sizeof(s->desc.app)); + s->desc.status |= SDESC_STATUS_EOF; + } + +- s->desc.status |= sof << SDESC_STATUS_SOF_BIT; ++ s->desc.status |= s->sof << SDESC_STATUS_SOF_BIT; + s->desc.status |= SDESC_STATUS_COMPLETE; + stream_desc_store(s, s->regs[R_CURDESC]); +- sof = 0; ++ s->sof = eop; + + /* Advance. */ + prev_d = s->regs[R_CURDESC]; +@@ -426,8 +427,7 @@ xilinx_axidma_data_stream_push(StreamSlave *obj, unsigned char *buf, size_t len, + struct Stream *s = &ds->dma->streams[1]; + size_t ret; + +- assert(eop); +- ret = stream_process_s2mem(s, buf, len); ++ ret = stream_process_s2mem(s, buf, len, eop); + stream_update_irq(s); + return ret; + } +-- +2.23.0 + diff --git a/hw-gpio-aspeed_gpio-Remove-dead-assignment.patch b/hw-gpio-aspeed_gpio-Remove-dead-assignment.patch new file mode 100644 index 0000000000000000000000000000000000000000..bb17ed1fae05b4b98dfe34bbeb6b1c73ad94aec6 --- /dev/null +++ b/hw-gpio-aspeed_gpio-Remove-dead-assignment.patch @@ -0,0 +1,39 @@ +From 6ae1a5a37711c80166b92019174877fc6f73030a Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Wed, 22 Apr 2020 15:31:50 +0200 +Subject: [PATCH 201/709] hw/gpio/aspeed_gpio: Remove dead assignment +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Fix warning reported by Clang static code analyzer: + + hw/gpio/aspeed_gpio.c:717:18: warning: Value stored to 'g_idx' during its initialization is never read + int set_idx, g_idx = *group_idx; + ^~~~~ ~~~~~~~~~~ + +Reported-by: Clang Static Analyzer +Reviewed-by: Cédric Le Goater +Signed-off-by: Philippe Mathieu-Daudé +Message-Id: <20200422133152.16770-8-philmd@redhat.com> +Signed-off-by: Laurent Vivier +--- + hw/gpio/aspeed_gpio.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/hw/gpio/aspeed_gpio.c b/hw/gpio/aspeed_gpio.c +index e52fcfd9a0..4c75b5c80c 100644 +--- a/hw/gpio/aspeed_gpio.c ++++ b/hw/gpio/aspeed_gpio.c +@@ -712,7 +712,7 @@ static void aspeed_gpio_write(void *opaque, hwaddr offset, uint64_t data, + static int get_set_idx(AspeedGPIOState *s, const char *group, int *group_idx) + { + AspeedGPIOClass *agc = ASPEED_GPIO_GET_CLASS(s); +- int set_idx, g_idx = *group_idx; ++ int set_idx, g_idx; + + for (set_idx = 0; set_idx < agc->nr_gpio_sets; set_idx++) { + const GPIOSetProperties *set_props = &agc->props[set_idx]; +-- +2.23.0 + diff --git a/hw-i2c-pm_smbus-Remove-dead-assignment.patch b/hw-i2c-pm_smbus-Remove-dead-assignment.patch new file mode 100644 index 0000000000000000000000000000000000000000..fe1afe2ab8e80ef843fc8df80550d854244797d1 --- /dev/null +++ b/hw-i2c-pm_smbus-Remove-dead-assignment.patch @@ -0,0 +1,39 @@ +From 00d1d29b768d920342c5e33cc56a9e0be596b2b4 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Wed, 22 Apr 2020 15:31:46 +0200 +Subject: [PATCH 197/709] hw/i2c/pm_smbus: Remove dead assignment +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Fix warning reported by Clang static code analyzer: + + CC hw/i2c/pm_smbus.o + hw/i2c/pm_smbus.c:187:17: warning: Value stored to 'ret' is never read + ret = 0; + ^ ~ + +Reported-by: Clang Static Analyzer +Reviewed-by: Alistair Francis +Signed-off-by: Philippe Mathieu-Daudé +Message-Id: <20200422133152.16770-4-philmd@redhat.com> +Signed-off-by: Laurent Vivier +--- + hw/i2c/pm_smbus.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/hw/i2c/pm_smbus.c b/hw/i2c/pm_smbus.c +index 36994ff585..4728540c37 100644 +--- a/hw/i2c/pm_smbus.c ++++ b/hw/i2c/pm_smbus.c +@@ -184,7 +184,6 @@ static void smb_transaction(PMSMBus *s) + s->smb_stat |= STS_HOST_BUSY | STS_BYTE_DONE; + s->smb_data[0] = s->smb_blkdata; + s->smb_index = 0; +- ret = 0; + } + goto out; + } +-- +2.23.0 + diff --git a/hw-i386-Add-vmport.h-local-header.patch b/hw-i386-Add-vmport.h-local-header.patch new file mode 100644 index 0000000000000000000000000000000000000000..81d2179cc18f04d488a563685f4a4438f7a8aa02 --- /dev/null +++ b/hw-i386-Add-vmport.h-local-header.patch @@ -0,0 +1,116 @@ +From e5951129851798620c4f5179dca503a4d6077f50 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Mon, 4 May 2020 10:33:41 +0200 +Subject: [PATCH 231/709] hw/i386: Add 'vmport.h' local header +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Move 'vmport' related declarations in a target-specific header. + +Signed-off-by: Philippe Mathieu-Daudé +Message-Id: <20200504083342.24273-4-f4bug@amsat.org> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +--- + hw/i386/pc.c | 1 + + hw/i386/vmmouse.c | 1 + + hw/i386/vmport.c | 1 + + hw/i386/vmport.h | 34 ++++++++++++++++++++++++++++++++++ + include/hw/i386/pc.h | 3 --- + 5 files changed, 37 insertions(+), 3 deletions(-) + create mode 100644 hw/i386/vmport.h + +diff --git a/hw/i386/pc.c b/hw/i386/pc.c +index 84669ddc84..f6b8431c8b 100644 +--- a/hw/i386/pc.c ++++ b/hw/i386/pc.c +@@ -91,6 +91,7 @@ + #include "qapi/qmp/qerror.h" + #include "config-devices.h" + #include "e820_memory_layout.h" ++#include "vmport.h" + #include "fw_cfg.h" + #include "trace.h" + +diff --git a/hw/i386/vmmouse.c b/hw/i386/vmmouse.c +index e8e62bd96b..78b36f6f5d 100644 +--- a/hw/i386/vmmouse.c ++++ b/hw/i386/vmmouse.c +@@ -29,6 +29,7 @@ + #include "hw/input/i8042.h" + #include "hw/qdev-properties.h" + #include "migration/vmstate.h" ++#include "vmport.h" + + /* debug only vmmouse */ + //#define DEBUG_VMMOUSE +diff --git a/hw/i386/vmport.c b/hw/i386/vmport.c +index 114141c6f3..00d47e0c4c 100644 +--- a/hw/i386/vmport.c ++++ b/hw/i386/vmport.c +@@ -26,6 +26,7 @@ + #include "hw/i386/pc.h" + #include "sysemu/hw_accel.h" + #include "qemu/log.h" ++#include "vmport.h" + #include "trace.h" + + #define VMPORT_CMD_GETVERSION 0x0a +diff --git a/hw/i386/vmport.h b/hw/i386/vmport.h +new file mode 100644 +index 0000000000..47eda7a22b +--- /dev/null ++++ b/hw/i386/vmport.h +@@ -0,0 +1,34 @@ ++/* ++ * QEMU VMPort emulation ++ * ++ * Copyright (C) 2007 Hervé Poussineau ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a copy ++ * of this software and associated documentation files (the "Software"), to deal ++ * in the Software without restriction, including without limitation the rights ++ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ++ * copies of the Software, and to permit persons to whom the Software is ++ * furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ++ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ * 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. ++ */ ++ ++#ifndef HW_I386_VMPORT_H ++#define HW_I386_VMPORT_H ++ ++#define TYPE_VMPORT "vmport" ++ ++typedef uint32_t (VMPortReadFunc)(void *opaque, uint32_t address); ++ ++void vmport_register(unsigned char command, VMPortReadFunc *func, void *opaque); ++ ++#endif +diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h +index 26e2a3d92b..de49a57506 100644 +--- a/include/hw/i386/pc.h ++++ b/include/hw/i386/pc.h +@@ -130,9 +130,6 @@ typedef struct PCMachineClass { + GSIState *pc_gsi_create(qemu_irq **irqs, bool pci_enabled); + + /* vmport.c */ +-#define TYPE_VMPORT "vmport" +-typedef uint32_t (VMPortReadFunc)(void *opaque, uint32_t address); +-void vmport_register(unsigned char command, VMPortReadFunc *func, void *opaque); + void vmmouse_get_data(uint32_t *data); + void vmmouse_set_data(const uint32_t *data); + +-- +2.23.0 + diff --git a/hw-i386-Make-vmmouse-helpers-static.patch b/hw-i386-Make-vmmouse-helpers-static.patch new file mode 100644 index 0000000000000000000000000000000000000000..858d2c8e28050a679e4b002aca25c1880b7deb56 --- /dev/null +++ b/hw-i386-Make-vmmouse-helpers-static.patch @@ -0,0 +1,127 @@ +From d8a05995bd64117bf5219d3ba7956277e608e3ca Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Mon, 4 May 2020 10:33:42 +0200 +Subject: [PATCH 232/709] hw/i386: Make vmmouse helpers static +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The vmmouse helpers are only used in hw/i386/vmmouse.c, +make them static. + +Signed-off-by: Philippe Mathieu-Daudé +Message-Id: <20200504083342.24273-5-f4bug@amsat.org> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +--- + hw/i386/vmmouse.c | 22 +++++++++++++++++++++- + hw/i386/vmport.c | 23 +---------------------- + include/hw/i386/pc.h | 4 ---- + 3 files changed, 22 insertions(+), 27 deletions(-) + +diff --git a/hw/i386/vmmouse.c b/hw/i386/vmmouse.c +index 78b36f6f5d..b3aef41327 100644 +--- a/hw/i386/vmmouse.c ++++ b/hw/i386/vmmouse.c +@@ -25,11 +25,11 @@ + #include "qemu/osdep.h" + #include "qapi/error.h" + #include "ui/console.h" +-#include "hw/i386/pc.h" + #include "hw/input/i8042.h" + #include "hw/qdev-properties.h" + #include "migration/vmstate.h" + #include "vmport.h" ++#include "cpu.h" + + /* debug only vmmouse */ + //#define DEBUG_VMMOUSE +@@ -71,6 +71,26 @@ typedef struct VMMouseState + ISAKBDState *i8042; + } VMMouseState; + ++static void vmmouse_get_data(uint32_t *data) ++{ ++ X86CPU *cpu = X86_CPU(current_cpu); ++ CPUX86State *env = &cpu->env; ++ ++ data[0] = env->regs[R_EAX]; data[1] = env->regs[R_EBX]; ++ data[2] = env->regs[R_ECX]; data[3] = env->regs[R_EDX]; ++ data[4] = env->regs[R_ESI]; data[5] = env->regs[R_EDI]; ++} ++ ++static void vmmouse_set_data(const uint32_t *data) ++{ ++ X86CPU *cpu = X86_CPU(current_cpu); ++ CPUX86State *env = &cpu->env; ++ ++ env->regs[R_EAX] = data[0]; env->regs[R_EBX] = data[1]; ++ env->regs[R_ECX] = data[2]; env->regs[R_EDX] = data[3]; ++ env->regs[R_ESI] = data[4]; env->regs[R_EDI] = data[5]; ++} ++ + static uint32_t vmmouse_get_status(VMMouseState *s) + { + DPRINTF("vmmouse_get_status()\n"); +diff --git a/hw/i386/vmport.c b/hw/i386/vmport.c +index 00d47e0c4c..1aaaab691a 100644 +--- a/hw/i386/vmport.c ++++ b/hw/i386/vmport.c +@@ -23,10 +23,10 @@ + */ + #include "qemu/osdep.h" + #include "hw/isa/isa.h" +-#include "hw/i386/pc.h" + #include "sysemu/hw_accel.h" + #include "qemu/log.h" + #include "vmport.h" ++#include "cpu.h" + #include "trace.h" + + #define VMPORT_CMD_GETVERSION 0x0a +@@ -109,27 +109,6 @@ static uint32_t vmport_cmd_ram_size(void *opaque, uint32_t addr) + return ram_size; + } + +-/* vmmouse helpers */ +-void vmmouse_get_data(uint32_t *data) +-{ +- X86CPU *cpu = X86_CPU(current_cpu); +- CPUX86State *env = &cpu->env; +- +- data[0] = env->regs[R_EAX]; data[1] = env->regs[R_EBX]; +- data[2] = env->regs[R_ECX]; data[3] = env->regs[R_EDX]; +- data[4] = env->regs[R_ESI]; data[5] = env->regs[R_EDI]; +-} +- +-void vmmouse_set_data(const uint32_t *data) +-{ +- X86CPU *cpu = X86_CPU(current_cpu); +- CPUX86State *env = &cpu->env; +- +- env->regs[R_EAX] = data[0]; env->regs[R_EBX] = data[1]; +- env->regs[R_ECX] = data[2]; env->regs[R_EDX] = data[3]; +- env->regs[R_ESI] = data[4]; env->regs[R_EDI] = data[5]; +-} +- + static const MemoryRegionOps vmport_ops = { + .read = vmport_ioport_read, + .write = vmport_ioport_write, +diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h +index de49a57506..05e19455bb 100644 +--- a/include/hw/i386/pc.h ++++ b/include/hw/i386/pc.h +@@ -129,10 +129,6 @@ typedef struct PCMachineClass { + + GSIState *pc_gsi_create(qemu_irq **irqs, bool pci_enabled); + +-/* vmport.c */ +-void vmmouse_get_data(uint32_t *data); +-void vmmouse_set_data(const uint32_t *data); +- + /* pc.c */ + extern int fd_bootchk; + +-- +2.23.0 + diff --git a/hw-i386-pc-Create-vmport-device-in-place.patch b/hw-i386-pc-Create-vmport-device-in-place.patch new file mode 100644 index 0000000000000000000000000000000000000000..a5943e5b074a76f9e69d84fb66fd3a708ddab76c --- /dev/null +++ b/hw-i386-pc-Create-vmport-device-in-place.patch @@ -0,0 +1,50 @@ +From b4fa79eab5eeaaa6fbebeb03723b9b70dd4563c4 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Mon, 4 May 2020 10:33:39 +0200 +Subject: [PATCH 229/709] hw/i386/pc: Create 'vmport' device in place +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Philippe Mathieu-Daudé +Message-Id: <20200504083342.24273-2-f4bug@amsat.org> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +--- + hw/i386/pc.c | 2 +- + include/hw/i386/pc.h | 6 ------ + 2 files changed, 1 insertion(+), 7 deletions(-) + +diff --git a/hw/i386/pc.c b/hw/i386/pc.c +index 5143c51653..84669ddc84 100644 +--- a/hw/i386/pc.c ++++ b/hw/i386/pc.c +@@ -1152,7 +1152,7 @@ static void pc_superio_init(ISABus *isa_bus, bool create_fdctrl, bool no_vmport) + + i8042 = isa_create_simple(isa_bus, "i8042"); + if (!no_vmport) { +- vmport_init(isa_bus); ++ isa_create_simple(isa_bus, TYPE_VMPORT); + vmmouse = isa_try_create(isa_bus, "vmmouse"); + } else { + vmmouse = NULL; +diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h +index 6ab6eda046..26e2a3d92b 100644 +--- a/include/hw/i386/pc.h ++++ b/include/hw/i386/pc.h +@@ -132,12 +132,6 @@ GSIState *pc_gsi_create(qemu_irq **irqs, bool pci_enabled); + /* vmport.c */ + #define TYPE_VMPORT "vmport" + typedef uint32_t (VMPortReadFunc)(void *opaque, uint32_t address); +- +-static inline void vmport_init(ISABus *bus) +-{ +- isa_create_simple(bus, TYPE_VMPORT); +-} +- + void vmport_register(unsigned char command, VMPortReadFunc *func, void *opaque); + void vmmouse_get_data(uint32_t *data); + void vmmouse_set_data(const uint32_t *data); +-- +2.23.0 + diff --git a/hw-i386-vmport-Remove-unused-hw-input-i8042.h-includ.patch b/hw-i386-vmport-Remove-unused-hw-input-i8042.h-includ.patch new file mode 100644 index 0000000000000000000000000000000000000000..69dd3d2f0b36d1150589cdb8b4d92a9216f19846 --- /dev/null +++ b/hw-i386-vmport-Remove-unused-hw-input-i8042.h-includ.patch @@ -0,0 +1,34 @@ +From c7358f4ee13de0e546ff457da95a9026098e37a9 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Mon, 4 May 2020 10:33:40 +0200 +Subject: [PATCH 230/709] hw/i386/vmport: Remove unused 'hw/input/i8042.h' + include +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Remove unused "hw/input/i8042.h" include. + +Signed-off-by: Philippe Mathieu-Daudé +Message-Id: <20200504083342.24273-3-f4bug@amsat.org> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +--- + hw/i386/vmport.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/hw/i386/vmport.c b/hw/i386/vmport.c +index 1f31e27c8a..114141c6f3 100644 +--- a/hw/i386/vmport.c ++++ b/hw/i386/vmport.c +@@ -24,7 +24,6 @@ + #include "qemu/osdep.h" + #include "hw/isa/isa.h" + #include "hw/i386/pc.h" +-#include "hw/input/i8042.h" + #include "sysemu/hw_accel.h" + #include "qemu/log.h" + #include "trace.h" +-- +2.23.0 + diff --git a/hw-ide-ahci-Log-lost-IRQs.patch b/hw-ide-ahci-Log-lost-IRQs.patch new file mode 100644 index 0000000000000000000000000000000000000000..852a0fbdccde1bbb3a1b3083dbde38564f2b091f --- /dev/null +++ b/hw-ide-ahci-Log-lost-IRQs.patch @@ -0,0 +1,34 @@ +From c5f12a80c6472bc158e5092c731bbc7affaca2e5 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Mon, 4 May 2020 11:48:58 +0200 +Subject: [PATCH 570/709] hw/ide/ahci: Log lost IRQs +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +One might find interesting to look at AHCI IRQs. + +Signed-off-by: Philippe Mathieu-Daudé +Message-Id: <20200504094858.5975-1-f4bug@amsat.org> +Reviewed-by: John Snow +Acked-by: John Snow +Signed-off-by: Kevin Wolf +--- + hw/ide/ahci.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c +index 13d91e109a..fc82cbd5f1 100644 +--- a/hw/ide/ahci.c ++++ b/hw/ide/ahci.c +@@ -1509,6 +1509,7 @@ static void ahci_cmd_done(IDEDMA *dma) + + static void ahci_irq_set(void *opaque, int n, int level) + { ++ qemu_log_mask(LOG_UNIMP, "ahci: IRQ#%d level:%d\n", n, level); + } + + static const IDEDMAOps ahci_dma_ops = { +-- +2.23.0 + diff --git a/hw-ide-sii3112-Remove-dead-assignment.patch b/hw-ide-sii3112-Remove-dead-assignment.patch new file mode 100644 index 0000000000000000000000000000000000000000..f175703c73885bb20d794c8111e20604cb3f1a71 --- /dev/null +++ b/hw-ide-sii3112-Remove-dead-assignment.patch @@ -0,0 +1,59 @@ +From 22c9336d3a82d1469796b7421cb5bd5f9bfd9748 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Wed, 22 Apr 2020 15:31:48 +0200 +Subject: [PATCH 199/709] hw/ide/sii3112: Remove dead assignment +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Fix warning reported by Clang static code analyzer: + + CC hw/ide/sii3112.o + hw/ide/sii3112.c:204:9: warning: Value stored to 'val' is never read + val = 0; + ^ ~ + +Fixes: a9dd6604 +Reported-by: Clang Static Analyzer +Reviewed-by: BALATON Zoltan +Acked-by: John Snow +Signed-off-by: Philippe Mathieu-Daudé +Message-Id: <20200422133152.16770-6-philmd@redhat.com> +Signed-off-by: Laurent Vivier +--- + hw/ide/sii3112.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/hw/ide/sii3112.c b/hw/ide/sii3112.c +index d69079c3d9..94d2b57f95 100644 +--- a/hw/ide/sii3112.c ++++ b/hw/ide/sii3112.c +@@ -42,7 +42,7 @@ static uint64_t sii3112_reg_read(void *opaque, hwaddr addr, + unsigned int size) + { + SiI3112PCIState *d = opaque; +- uint64_t val = 0; ++ uint64_t val; + + switch (addr) { + case 0x00: +@@ -126,6 +126,7 @@ static uint64_t sii3112_reg_read(void *opaque, hwaddr addr, + break; + default: + val = 0; ++ break; + } + trace_sii3112_read(size, addr, val); + return val; +@@ -201,7 +202,7 @@ static void sii3112_reg_write(void *opaque, hwaddr addr, + d->regs[1].sien = (val >> 16) & 0x3eed; + break; + default: +- val = 0; ++ break; + } + } + +-- +2.23.0 + diff --git a/hw-input-adb-kbd-Remove-dead-assignment.patch b/hw-input-adb-kbd-Remove-dead-assignment.patch new file mode 100644 index 0000000000000000000000000000000000000000..03b692e1b3e67e4a2e32201a0fa73e25f5f3199e --- /dev/null +++ b/hw-input-adb-kbd-Remove-dead-assignment.patch @@ -0,0 +1,65 @@ +From 1cf5ae5129a8e78b9eb2d6545bcc56a8b136eb79 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Wed, 22 Apr 2020 15:31:47 +0200 +Subject: [PATCH 198/709] hw/input/adb-kbd: Remove dead assignment +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Since commit 5a1f49718 the 'olen' variable is not really +used. Remove it to fix a warning reported by Clang static +code analyzer: + + CC hw/input/adb-kbd.o + hw/input/adb-kbd.c:200:5: warning: Value stored to 'olen' is never read + olen = 0; + ^ ~ + +Fixes: 5a1f49718 (adb: add support for QKeyCode) +Reported-by: Clang Static Analyzer +Suggested-by: BALATON Zoltan +Acked-by: David Gibson +Signed-off-by: Philippe Mathieu-Daudé +Message-Id: <20200422133152.16770-5-philmd@redhat.com> +Signed-off-by: Laurent Vivier +--- + hw/input/adb-kbd.c | 6 +----- + 1 file changed, 1 insertion(+), 5 deletions(-) + +diff --git a/hw/input/adb-kbd.c b/hw/input/adb-kbd.c +index 0ba8207589..a6d5c9b7c9 100644 +--- a/hw/input/adb-kbd.c ++++ b/hw/input/adb-kbd.c +@@ -195,9 +195,7 @@ static int adb_kbd_poll(ADBDevice *d, uint8_t *obuf) + { + KBDState *s = ADB_KEYBOARD(d); + int keycode; +- int olen; + +- olen = 0; + if (s->count == 0) { + return 0; + } +@@ -216,7 +214,6 @@ static int adb_kbd_poll(ADBDevice *d, uint8_t *obuf) + if (keycode == 0x7f) { + obuf[0] = 0x7f; + obuf[1] = 0x7f; +- olen = 2; + } else { + obuf[0] = keycode; + /* NOTE: the power key key-up is the two byte sequence 0xff 0xff; +@@ -224,10 +221,9 @@ static int adb_kbd_poll(ADBDevice *d, uint8_t *obuf) + * byte, but choose not to bother. + */ + obuf[1] = 0xff; +- olen = 2; + } + +- return olen; ++ return 2; + } + + static int adb_kbd_request(ADBDevice *d, uint8_t *obuf, +-- +2.23.0 + diff --git a/hw-isa-i82378-Remove-dead-assignment.patch b/hw-isa-i82378-Remove-dead-assignment.patch new file mode 100644 index 0000000000000000000000000000000000000000..a3161bdc3f4761923446368c904cee4e4f7785b6 --- /dev/null +++ b/hw-isa-i82378-Remove-dead-assignment.patch @@ -0,0 +1,59 @@ +From 2c8ed55f0f615ea825cb30e80e74a07d6945bcf9 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Wed, 22 Apr 2020 15:31:49 +0200 +Subject: [PATCH 200/709] hw/isa/i82378: Remove dead assignment +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Rename the unique variable assigned as 'pit' which better +represents what it holds, to fix a warning reported by the +Clang static code analyzer: + + CC hw/isa/i82378.o + hw/isa/i82378.c:108:5: warning: Value stored to 'isa' is never read + isa = isa_create_simple(isabus, "i82374"); + ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Reported-by: Clang Static Analyzer +Reviewed-by: Alistair Francis +Signed-off-by: Philippe Mathieu-Daudé +Message-Id: <20200422133152.16770-7-philmd@redhat.com> +Signed-off-by: Laurent Vivier +--- + hw/isa/i82378.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/hw/isa/i82378.c b/hw/isa/i82378.c +index dcb6b479ea..d9e6c7fa00 100644 +--- a/hw/isa/i82378.c ++++ b/hw/isa/i82378.c +@@ -67,7 +67,7 @@ static void i82378_realize(PCIDevice *pci, Error **errp) + I82378State *s = I82378(dev); + uint8_t *pci_conf; + ISABus *isabus; +- ISADevice *isa; ++ ISADevice *pit; + + pci_conf = pci->config; + pci_set_word(pci_conf + PCI_COMMAND, +@@ -99,13 +99,13 @@ static void i82378_realize(PCIDevice *pci, Error **errp) + isa_bus_irqs(isabus, s->i8259); + + /* 1 82C54 (pit) */ +- isa = i8254_pit_init(isabus, 0x40, 0, NULL); ++ pit = i8254_pit_init(isabus, 0x40, 0, NULL); + + /* speaker */ +- pcspk_init(isabus, isa); ++ pcspk_init(isabus, pit); + + /* 2 82C37 (dma) */ +- isa = isa_create_simple(isabus, "i82374"); ++ isa_create_simple(isabus, "i82374"); + } + + static void i82378_init(Object *obj) +-- +2.23.0 + diff --git a/hw-isa-superio-Make-the-components-QOM-children.patch b/hw-isa-superio-Make-the-components-QOM-children.patch new file mode 100644 index 0000000000000000000000000000000000000000..178ab24d963e909abb1fddfb1373d803696ce814 --- /dev/null +++ b/hw-isa-superio-Make-the-components-QOM-children.patch @@ -0,0 +1,115 @@ +From e508430619b3b26112117b6e06ebc5f8f1d54aed Mon Sep 17 00:00:00 2001 +From: Markus Armbruster +Date: Tue, 5 May 2020 17:29:18 +0200 +Subject: [PATCH 472/709] hw/isa/superio: Make the components QOM children +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +isa_superio_realize() attempts to make isa-parallel and isa-serial QOM +children, but this does not work, because it calls +object_property_add_child() after realizing with qdev_init_nofail(). +Realizing a device without a parent gives it one: it gets put into the +"/machine/unattached/" orphanage. The extra +object_property_add_child() fails, and isa_superio_realize() ignores +the error. + +Move the object_property_add_child() before qdev_init_nofail(), and +pass &error_abort. + +For the other components, isa_superio_realize() doesn't even try. Add +object_property_add_child() there. + +This affects machines 40p, clipper and fulong2e. + +For instance, fulong2e has its vt82c686b-superio (which is an +isa-superio) at /machine/unattached/device[9]. Before the patch, its +components are at /machine/unattached/device[10] .. [14]. Afterwards, +they are at +/machine/unattached/device[9]/{parallel0,serial0,serial1,isa-fdc,i8042}. + +Cc: Michael S. Tsirkin +Cc: Paolo Bonzini +Signed-off-by: Markus Armbruster +Reviewed-by: Philippe Mathieu-Daudé +Tested-by: Philippe Mathieu-Daudé +Reviewed-by: Paolo Bonzini +Message-Id: <20200505152926.18877-11-armbru@redhat.com> +--- + hw/isa/isa-superio.c | 18 +++++++++++++----- + 1 file changed, 13 insertions(+), 5 deletions(-) + +diff --git a/hw/isa/isa-superio.c b/hw/isa/isa-superio.c +index 180a8b9625..0d9d848280 100644 +--- a/hw/isa/isa-superio.c ++++ b/hw/isa/isa-superio.c +@@ -62,6 +62,8 @@ static void isa_superio_realize(DeviceState *dev, Error **errp) + qdev_prop_set_uint32(d, "irq", k->parallel.get_irq(sio, i)); + } + qdev_prop_set_chr(d, "chardev", chr); ++ object_property_add_child(OBJECT(sio), name, OBJECT(isa), ++ &error_abort); + qdev_init_nofail(d); + sio->parallel[i] = isa; + trace_superio_create_parallel(i, +@@ -69,8 +71,6 @@ static void isa_superio_realize(DeviceState *dev, Error **errp) + k->parallel.get_iobase(sio, i) : -1, + k->parallel.get_irq ? + k->parallel.get_irq(sio, i) : -1); +- object_property_add_child(OBJECT(dev), name, +- OBJECT(sio->parallel[i]), NULL); + g_free(name); + } + } +@@ -102,6 +102,8 @@ static void isa_superio_realize(DeviceState *dev, Error **errp) + qdev_prop_set_uint32(d, "irq", k->serial.get_irq(sio, i)); + } + qdev_prop_set_chr(d, "chardev", chr); ++ object_property_add_child(OBJECT(sio), name, OBJECT(isa), ++ &error_abort); + qdev_init_nofail(d); + sio->serial[i] = isa; + trace_superio_create_serial(i, +@@ -109,8 +111,6 @@ static void isa_superio_realize(DeviceState *dev, Error **errp) + k->serial.get_iobase(sio, i) : -1, + k->serial.get_irq ? + k->serial.get_irq(sio, i) : -1); +- object_property_add_child(OBJECT(dev), name, +- OBJECT(sio->serial[0]), NULL); + g_free(name); + } + } +@@ -137,6 +137,8 @@ static void isa_superio_realize(DeviceState *dev, Error **errp) + qdev_prop_set_drive(d, "driveB", blk_by_legacy_dinfo(drive), + &error_fatal); + } ++ object_property_add_child(OBJECT(sio), "isa-fdc", OBJECT(isa), ++ &error_abort); + qdev_init_nofail(d); + sio->floppy = isa; + trace_superio_create_floppy(0, +@@ -147,7 +149,11 @@ static void isa_superio_realize(DeviceState *dev, Error **errp) + } + + /* Keyboard, mouse */ +- sio->kbc = isa_create_simple(bus, TYPE_I8042); ++ isa = isa_create(bus, TYPE_I8042); ++ object_property_add_child(OBJECT(sio), TYPE_I8042, OBJECT(isa), ++ &error_abort); ++ qdev_init_nofail(DEVICE(isa)); ++ sio->kbc = isa; + + /* IDE */ + if (k->ide.count && (!k->ide.is_enabled || k->ide.is_enabled(sio, 0))) { +@@ -163,6 +169,8 @@ static void isa_superio_realize(DeviceState *dev, Error **errp) + qdev_prop_set_uint32(d, "irq", k->ide.get_irq(sio, 0)); + } + qdev_init_nofail(d); ++ object_property_add_child(OBJECT(sio), "isa-ide", OBJECT(isa), ++ &error_abort); + sio->ide = isa; + trace_superio_create_ide(0, + k->ide.get_iobase ? +-- +2.23.0 + diff --git a/hw-mem-pc-dimm-Fix-line-over-80-characters-warning.patch b/hw-mem-pc-dimm-Fix-line-over-80-characters-warning.patch new file mode 100644 index 0000000000000000000000000000000000000000..017b454d3f8c15de0d0ac53de2c92d63408ae623 --- /dev/null +++ b/hw-mem-pc-dimm-Fix-line-over-80-characters-warning.patch @@ -0,0 +1,29 @@ +From 12d814e901a21fbecc7d34765c02813f187aecef Mon Sep 17 00:00:00 2001 +From: Wainer dos Santos Moschetta +Date: Tue, 10 Mar 2020 15:05:10 -0300 +Subject: [PATCH 190/709] hw/mem/pc-dimm: Fix line over 80 characters warning + +Signed-off-by: Wainer dos Santos Moschetta +Message-Id: <20200310180510.19489-3-wainersm@redhat.com> +Signed-off-by: Laurent Vivier +--- + hw/mem/pc-dimm.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/hw/mem/pc-dimm.c b/hw/mem/pc-dimm.c +index 36edfcf467..6d62588fea 100644 +--- a/hw/mem/pc-dimm.c ++++ b/hw/mem/pc-dimm.c +@@ -218,7 +218,8 @@ static MemoryRegion *pc_dimm_get_memory_region(PCDIMMDevice *dimm, Error **errp) + + static uint64_t pc_dimm_md_get_addr(const MemoryDeviceState *md) + { +- return object_property_get_uint(OBJECT(md), PC_DIMM_ADDR_PROP, &error_abort); ++ return object_property_get_uint(OBJECT(md), PC_DIMM_ADDR_PROP, ++ &error_abort); + } + + static void pc_dimm_md_set_addr(MemoryDeviceState *md, uint64_t addr, +-- +2.23.0 + diff --git a/hw-mem-pc-dimm-Print-slot-number-on-error-at-pc_dimm.patch b/hw-mem-pc-dimm-Print-slot-number-on-error-at-pc_dimm.patch new file mode 100644 index 0000000000000000000000000000000000000000..e8b342c32f4a2d0a4ffb701b0f275d376096585c --- /dev/null +++ b/hw-mem-pc-dimm-Print-slot-number-on-error-at-pc_dimm.patch @@ -0,0 +1,34 @@ +From f4eaf69e45c74b33d092ab53903a8458d197e240 Mon Sep 17 00:00:00 2001 +From: Wainer dos Santos Moschetta +Date: Tue, 10 Mar 2020 15:05:09 -0300 +Subject: [PATCH 189/709] hw/mem/pc-dimm: Print slot number on error at + pc_dimm_pre_plug() + +The error report in pc_dimm_pre_plug() now has the slot +number printed. + +Signed-off-by: Wainer dos Santos Moschetta +Message-Id: <20200310180510.19489-2-wainersm@redhat.com> +Signed-off-by: Laurent Vivier +--- + hw/mem/pc-dimm.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/hw/mem/pc-dimm.c b/hw/mem/pc-dimm.c +index 8f50b8afea..36edfcf467 100644 +--- a/hw/mem/pc-dimm.c ++++ b/hw/mem/pc-dimm.c +@@ -44,8 +44,8 @@ void pc_dimm_pre_plug(PCDIMMDevice *dimm, MachineState *machine, + &error_abort); + if ((slot < 0 || slot >= machine->ram_slots) && + slot != PC_DIMM_UNASSIGNED_SLOT) { +- error_setg(&local_err, "invalid slot number, valid range is [0-%" +- PRIu64 "]", machine->ram_slots - 1); ++ error_setg(&local_err, "invalid slot number %d, valid range is [0-%" ++ PRIu64 "]", slot, machine->ram_slots - 1); + goto out; + } + +-- +2.23.0 + diff --git a/hw-mips-Rename-malta-mipssim-r4k-jazz-files.patch b/hw-mips-Rename-malta-mipssim-r4k-jazz-files.patch new file mode 100644 index 0000000000000000000000000000000000000000..dff6240886fbbfe8ed801c5827d270ed430df96a --- /dev/null +++ b/hw-mips-Rename-malta-mipssim-r4k-jazz-files.patch @@ -0,0 +1,104 @@ +From 5298722edad2d40baac9c2326c6d492ad2b0211a Mon Sep 17 00:00:00 2001 +From: Aleksandar Markovic +Date: Mon, 18 May 2020 22:09:20 +0200 +Subject: [PATCH 663/709] hw/mips: Rename malta/mipssim/r4k/jazz files +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Machine file names should not have prefix "mips_". + +Reviewed-by: Philippe Mathieu-Daudé +Signed-off-by: Aleksandar Markovic +Message-id: <20200518200920.17344-22-aleksandar.qemu.devel@gmail.com> +[PMD: Fixed Fuloong line conflict due to rebase] +Signed-off-by: Philippe Mathieu-Daudé +--- + MAINTAINERS | 8 ++++---- + hw/mips/Makefile.objs | 8 ++++---- + hw/mips/{mips_jazz.c => jazz.c} | 0 + hw/mips/{mips_malta.c => malta.c} | 0 + hw/mips/{mips_mipssim.c => mipssim.c} | 0 + hw/mips/{mips_r4k.c => r4k.c} | 0 + 6 files changed, 8 insertions(+), 8 deletions(-) + rename hw/mips/{mips_jazz.c => jazz.c} (100%) + rename hw/mips/{mips_malta.c => malta.c} (100%) + rename hw/mips/{mips_mipssim.c => mipssim.c} (100%) + rename hw/mips/{mips_r4k.c => r4k.c} (100%) + +diff --git a/MAINTAINERS b/MAINTAINERS +index 8136a0e56c..f46ab150dc 100644 +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -1050,7 +1050,7 @@ Jazz + M: Hervé Poussineau + R: Aleksandar Rikalo + S: Maintained +-F: hw/mips/mips_jazz.c ++F: hw/mips/jazz.c + F: hw/display/jazz_led.c + F: hw/dma/rc4030.c + +@@ -1061,7 +1061,7 @@ R: Aurelien Jarno + S: Maintained + F: hw/isa/piix4.c + F: hw/acpi/piix4.c +-F: hw/mips/mips_malta.c ++F: hw/mips/malta.c + F: hw/mips/gt64xxx_pci.c + F: include/hw/southbridge/piix.h + F: tests/acceptance/linux_ssh_mips_malta.py +@@ -1071,7 +1071,7 @@ Mipssim + M: Aleksandar Markovic + R: Aleksandar Rikalo + S: Odd Fixes +-F: hw/mips/mips_mipssim.c ++F: hw/mips/mipssim.c + F: hw/net/mipsnet.c + + R4000 +@@ -1079,7 +1079,7 @@ M: Aleksandar Markovic + R: Aurelien Jarno + R: Aleksandar Rikalo + S: Obsolete +-F: hw/mips/mips_r4k.c ++F: hw/mips/r4k.c + + Fuloong 2E + M: Huacai Chen +diff --git a/hw/mips/Makefile.objs b/hw/mips/Makefile.objs +index 8ab41edc3f..739e2b7b40 100644 +--- a/hw/mips/Makefile.objs ++++ b/hw/mips/Makefile.objs +@@ -1,8 +1,8 @@ + obj-y += addr.o mips_int.o +-obj-$(CONFIG_R4K) += mips_r4k.o +-obj-$(CONFIG_MALTA) += gt64xxx_pci.o mips_malta.o +-obj-$(CONFIG_MIPSSIM) += mips_mipssim.o +-obj-$(CONFIG_JAZZ) += mips_jazz.o ++obj-$(CONFIG_R4K) += r4k.o ++obj-$(CONFIG_MALTA) += gt64xxx_pci.o malta.o ++obj-$(CONFIG_MIPSSIM) += mipssim.o ++obj-$(CONFIG_JAZZ) += jazz.o + obj-$(CONFIG_FULOONG) += fuloong2e.o + obj-$(CONFIG_MIPS_CPS) += cps.o + obj-$(CONFIG_MIPS_BOSTON) += boston.o +diff --git a/hw/mips/mips_jazz.c b/hw/mips/jazz.c +similarity index 100% +rename from hw/mips/mips_jazz.c +rename to hw/mips/jazz.c +diff --git a/hw/mips/mips_malta.c b/hw/mips/malta.c +similarity index 100% +rename from hw/mips/mips_malta.c +rename to hw/mips/malta.c +diff --git a/hw/mips/mips_mipssim.c b/hw/mips/mipssim.c +similarity index 100% +rename from hw/mips/mips_mipssim.c +rename to hw/mips/mipssim.c +diff --git a/hw/mips/mips_r4k.c b/hw/mips/r4k.c +similarity index 100% +rename from hw/mips/mips_r4k.c +rename to hw/mips/r4k.c +-- +2.23.0 + diff --git a/hw-mips-fuloong2e-Fix-typo-in-Fuloong-machine-name.patch b/hw-mips-fuloong2e-Fix-typo-in-Fuloong-machine-name.patch new file mode 100644 index 0000000000000000000000000000000000000000..8770d375b6f856b229f6b0b5d6f53125caeff7fc --- /dev/null +++ b/hw-mips-fuloong2e-Fix-typo-in-Fuloong-machine-name.patch @@ -0,0 +1,299 @@ +From c3a09ff68ddffd1efd57612706484aa386826518 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Sun, 26 Apr 2020 12:16:37 +0200 +Subject: [PATCH 662/709] hw/mips/fuloong2e: Fix typo in Fuloong machine name +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +We always miswrote the Fuloong machine... Fix its name. +Add an machine alias to the previous name for backward +compatibility. + +Suggested-by: Aleksandar Markovic +Reviewed-by: Aleksandar Markovic +Message-id: <20200526104726.11273-11-f4bug@amsat.org> +Signed-off-by: Philippe Mathieu-Daudé +--- + MAINTAINERS | 4 +-- + default-configs/mips64el-softmmu.mak | 2 +- + docs/system/deprecated.rst | 5 +++ + docs/system/target-mips.rst | 2 +- + hw/isa/vt82c686.c | 2 +- + hw/mips/Kconfig | 2 +- + hw/mips/Makefile.objs | 2 +- + hw/mips/{mips_fulong2e.c => fuloong2e.c} | 41 ++++++++++++------------ + hw/pci-host/bonito.c | 8 ++--- + tests/qtest/endianness-test.c | 2 +- + 10 files changed, 38 insertions(+), 32 deletions(-) + rename hw/mips/{mips_fulong2e.c => fuloong2e.c} (91%) + +diff --git a/MAINTAINERS b/MAINTAINERS +index 8f597aae12..8136a0e56c 100644 +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -1081,13 +1081,13 @@ R: Aleksandar Rikalo + S: Obsolete + F: hw/mips/mips_r4k.c + +-Fulong 2E ++Fuloong 2E + M: Huacai Chen + M: Philippe Mathieu-Daudé + M: Aleksandar Markovic + R: Jiaxun Yang + S: Odd Fixes +-F: hw/mips/mips_fulong2e.c ++F: hw/mips/fuloong2e.c + F: hw/isa/vt82c686.c + F: hw/pci-host/bonito.c + F: include/hw/isa/vt82c686.h +diff --git a/default-configs/mips64el-softmmu.mak b/default-configs/mips64el-softmmu.mak +index 8b0c9b1e15..9f8a3ef156 100644 +--- a/default-configs/mips64el-softmmu.mak ++++ b/default-configs/mips64el-softmmu.mak +@@ -2,7 +2,7 @@ + + include mips-softmmu-common.mak + CONFIG_IDE_VIA=y +-CONFIG_FULONG=y ++CONFIG_FULOONG=y + CONFIG_ATI_VGA=y + CONFIG_RTL8139_PCI=y + CONFIG_JAZZ=y +diff --git a/docs/system/deprecated.rst b/docs/system/deprecated.rst +index 3142fac386..f0061f94aa 100644 +--- a/docs/system/deprecated.rst ++++ b/docs/system/deprecated.rst +@@ -368,6 +368,11 @@ mips ``r4k`` platform (since 5.0) + This machine type is very old and unmaintained. Users should use the ``malta`` + machine type instead. + ++mips ``fulong2e`` machine (since 5.1) ++''''''''''''''''''''''''''''''''''''' ++ ++This machine has been renamed ``fuloong2e``. ++ + ``pc-1.0``, ``pc-1.1``, ``pc-1.2`` and ``pc-1.3`` (since 5.0) + ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' + +diff --git a/docs/system/target-mips.rst b/docs/system/target-mips.rst +index 2736fd0509..cd2a931edf 100644 +--- a/docs/system/target-mips.rst ++++ b/docs/system/target-mips.rst +@@ -74,7 +74,7 @@ The MIPS Magnum R4000 emulation supports: + + - G364 framebuffer + +-The Fulong 2E emulation supports: ++The Fuloong 2E emulation supports: + + - Loongson 2E CPU + +diff --git a/hw/isa/vt82c686.c b/hw/isa/vt82c686.c +index d9b51fce8d..fac4e56b7d 100644 +--- a/hw/isa/vt82c686.c ++++ b/hw/isa/vt82c686.c +@@ -503,7 +503,7 @@ static void via_class_init(ObjectClass *klass, void *data) + dc->vmsd = &vmstate_via; + /* + * Reason: part of VIA VT82C686 southbridge, needs to be wired up, +- * e.g. by mips_fulong2e_init() ++ * e.g. by mips_fuloong2e_init() + */ + dc->user_creatable = false; + } +diff --git a/hw/mips/Kconfig b/hw/mips/Kconfig +index 2240504dff..67d39c56a4 100644 +--- a/hw/mips/Kconfig ++++ b/hw/mips/Kconfig +@@ -41,7 +41,7 @@ config JAZZ + select DS1225Y + select JAZZ_LED + +-config FULONG ++config FULOONG + bool + select PCI_BONITO + +diff --git a/hw/mips/Makefile.objs b/hw/mips/Makefile.objs +index 525809af07..8ab41edc3f 100644 +--- a/hw/mips/Makefile.objs ++++ b/hw/mips/Makefile.objs +@@ -3,6 +3,6 @@ obj-$(CONFIG_R4K) += mips_r4k.o + obj-$(CONFIG_MALTA) += gt64xxx_pci.o mips_malta.o + obj-$(CONFIG_MIPSSIM) += mips_mipssim.o + obj-$(CONFIG_JAZZ) += mips_jazz.o +-obj-$(CONFIG_FULONG) += mips_fulong2e.o ++obj-$(CONFIG_FULOONG) += fuloong2e.o + obj-$(CONFIG_MIPS_CPS) += cps.o + obj-$(CONFIG_MIPS_BOSTON) += boston.o +diff --git a/hw/mips/mips_fulong2e.c b/hw/mips/fuloong2e.c +similarity index 91% +rename from hw/mips/mips_fulong2e.c +rename to hw/mips/fuloong2e.c +index 6996f5e3d1..f583c44b79 100644 +--- a/hw/mips/mips_fulong2e.c ++++ b/hw/mips/fuloong2e.c +@@ -1,5 +1,5 @@ + /* +- * QEMU fulong 2e mini pc support ++ * QEMU fuloong 2e mini pc support + * + * Copyright (c) 2008 yajin (yajin@vm-kernel.org) + * Copyright (c) 2009 chenming (chenming@rdc.faw.com.cn) +@@ -11,8 +11,8 @@ + */ + + /* +- * Fulong 2e mini pc is based on ICT/ST Loongson 2e CPU (MIPS III like, 800MHz) +- * http://www.linux-mips.org/wiki/Fulong ++ * Fuloong 2e mini pc is based on ICT/ST Loongson 2e CPU (MIPS III like, 800MHz) ++ * https://www.linux-mips.org/wiki/Fuloong_2E + * + * Loongson 2e user manual: + * http://www.loongsondeveloper.com/doc/Loongson2EUserGuide.pdf +@@ -45,13 +45,13 @@ + #include "sysemu/reset.h" + #include "qemu/error-report.h" + +-#define DEBUG_FULONG2E_INIT ++#define DEBUG_FULOONG2E_INIT + + #define ENVP_ADDR 0x80002000l + #define ENVP_NB_ENTRIES 16 + #define ENVP_ENTRY_SIZE 256 + +-/* fulong 2e has a 512k flash: Winbond W39L040AP70Z */ ++/* Fuloong 2e has a 512k flash: Winbond W39L040AP70Z */ + #define BIOS_SIZE (512 * KiB) + #define MAX_IDE_BUS 2 + +@@ -68,12 +68,12 @@ + * 2, use "Bonito2edev" to replace "dir_corresponding_to_your_target_hardware" + * in the "Compile Guide". + */ +-#define FULONG_BIOSNAME "pmon_fulong2e.bin" ++#define FULOONG_BIOSNAME "pmon_2e.bin" + +-/* PCI SLOT in fulong 2e */ +-#define FULONG2E_VIA_SLOT 5 +-#define FULONG2E_ATI_SLOT 6 +-#define FULONG2E_RTL8139_SLOT 7 ++/* PCI SLOT in Fuloong 2e */ ++#define FULOONG2E_VIA_SLOT 5 ++#define FULOONG2E_ATI_SLOT 6 ++#define FULOONG2E_RTL8139_SLOT 7 + + static struct _loaderparams { + int ram_size; +@@ -278,7 +278,7 @@ static void network_init(PCIBus *pci_bus) + const char *default_devaddr = NULL; + + if (i == 0 && (!nd->model || strcmp(nd->model, "rtl8139") == 0)) { +- /* The fulong board has a RTL8139 card using PCI SLOT 7 */ ++ /* The Fuloong board has a RTL8139 card using PCI SLOT 7 */ + default_devaddr = "07"; + } + +@@ -286,7 +286,7 @@ static void network_init(PCIBus *pci_bus) + } + } + +-static void mips_fulong2e_init(MachineState *machine) ++static void mips_fuloong2e_init(MachineState *machine) + { + const char *kernel_filename = machine->kernel_filename; + const char *kernel_cmdline = machine->kernel_cmdline; +@@ -318,7 +318,7 @@ static void mips_fulong2e_init(MachineState *machine) + memory_region_add_subregion(address_space_mem, 0, machine->ram); + + /* Boot ROM */ +- memory_region_init_rom(bios, NULL, "fulong2e.bios", BIOS_SIZE, ++ memory_region_init_rom(bios, NULL, "fuloong2e.bios", BIOS_SIZE, + &error_fatal); + memory_region_add_subregion(address_space_mem, 0x1fc00000LL, bios); + +@@ -336,7 +336,7 @@ static void mips_fulong2e_init(MachineState *machine) + write_bootloader(env, memory_region_get_ram_ptr(bios), kernel_entry); + } else { + if (bios_name == NULL) { +- bios_name = FULONG_BIOSNAME; ++ bios_name = FULOONG_BIOSNAME; + } + filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); + if (filename) { +@@ -362,7 +362,7 @@ static void mips_fulong2e_init(MachineState *machine) + pci_bus = bonito_init((qemu_irq *)&(env->irq[2])); + + /* South bridge -> IP5 */ +- vt82c686b_southbridge_init(pci_bus, FULONG2E_VIA_SLOT, env->irq[5], ++ vt82c686b_southbridge_init(pci_bus, FULOONG2E_VIA_SLOT, env->irq[5], + &smbus, &isa_bus); + + /* GPU */ +@@ -383,14 +383,15 @@ static void mips_fulong2e_init(MachineState *machine) + network_init(pci_bus); + } + +-static void mips_fulong2e_machine_init(MachineClass *mc) ++static void mips_fuloong2e_machine_init(MachineClass *mc) + { +- mc->desc = "Fulong 2e mini pc"; +- mc->init = mips_fulong2e_init; ++ mc->desc = "Fuloong 2e mini pc"; ++ mc->alias = "fulong2e"; /* Incorrect name used up to QEMU 4.2 */ ++ mc->init = mips_fuloong2e_init; + mc->block_default_type = IF_IDE; + mc->default_cpu_type = MIPS_CPU_TYPE_NAME("Loongson-2E"); + mc->default_ram_size = 256 * MiB; +- mc->default_ram_id = "fulong2e.ram"; ++ mc->default_ram_id = "fuloong2e.ram"; + } + +-DEFINE_MACHINE("fulong2e", mips_fulong2e_machine_init) ++DEFINE_MACHINE("fuloong2e", mips_fuloong2e_machine_init) +diff --git a/hw/pci-host/bonito.c b/hw/pci-host/bonito.c +index d0201ce59e..f9697dcc43 100644 +--- a/hw/pci-host/bonito.c ++++ b/hw/pci-host/bonito.c +@@ -11,7 +11,7 @@ + */ + + /* +- * fulong 2e mini pc has a bonito north bridge. ++ * fuloong 2e mini pc has a bonito north bridge. + */ + + /* +@@ -573,11 +573,11 @@ static int pci_bonito_map_irq(PCIDevice *pci_dev, int irq_num) + slot = (pci_dev->devfn >> 3); + + switch (slot) { +- case 5: /* FULONG2E_VIA_SLOT, SouthBridge, IDE, USB, ACPI, AC97, MC97 */ ++ case 5: /* FULOONG2E_VIA_SLOT, SouthBridge, IDE, USB, ACPI, AC97, MC97 */ + return irq_num % 4 + BONITO_IRQ_BASE; +- case 6: /* FULONG2E_ATI_SLOT, VGA */ ++ case 6: /* FULOONG2E_ATI_SLOT, VGA */ + return 4 + BONITO_IRQ_BASE; +- case 7: /* FULONG2E_RTL_SLOT, RTL8139 */ ++ case 7: /* FULOONG2E_RTL_SLOT, RTL8139 */ + return 5 + BONITO_IRQ_BASE; + case 8 ... 12: /* PCI slot 1 to 4 */ + return (slot - 8 + irq_num) + 6 + BONITO_IRQ_BASE; +diff --git a/tests/qtest/endianness-test.c b/tests/qtest/endianness-test.c +index 2798802c63..cc088ac01a 100644 +--- a/tests/qtest/endianness-test.c ++++ b/tests/qtest/endianness-test.c +@@ -33,7 +33,7 @@ static const TestCase test_cases[] = { + { "mips64", "pica61", 0x90000000, .bswap = true }, + { "mips64", "mips", 0x14000000, .bswap = true }, + { "mips64", "malta", 0x10000000, .bswap = true }, +- { "mips64el", "fulong2e", 0x1fd00000 }, ++ { "mips64el", "fuloong2e", 0x1fd00000 }, + { "ppc", "g3beige", 0xfe000000, .bswap = true, .superio = "i82378" }, + { "ppc", "40p", 0x80000000, .bswap = true }, + { "ppc", "bamboo", 0xe8000000, .bswap = true, .superio = "i82378" }, +-- +2.23.0 + diff --git a/hw-mips-fuloong2e-Move-code-and-update-a-comment.patch b/hw-mips-fuloong2e-Move-code-and-update-a-comment.patch new file mode 100644 index 0000000000000000000000000000000000000000..a510f5281859d8d003d3bde6e67148778053c18f --- /dev/null +++ b/hw-mips-fuloong2e-Move-code-and-update-a-comment.patch @@ -0,0 +1,40 @@ +From 3e5fe8dd1fcb6aa3acd3e5b719bd0b9e69ddee6b Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Sun, 26 Apr 2020 12:19:16 +0200 +Subject: [PATCH 661/709] hw/mips/fuloong2e: Move code and update a comment +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Move the RAM-related call closer to the RAM creation block, +rename the ROM comment. + +Reviewed-by: Huacai Chen +Message-id: <20200510210128.18343-4-f4bug@amsat.org> +Signed-off-by: Philippe Mathieu-Daudé +--- + hw/mips/mips_fulong2e.c | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +diff --git a/hw/mips/mips_fulong2e.c b/hw/mips/mips_fulong2e.c +index 05b9efa516..6996f5e3d1 100644 +--- a/hw/mips/mips_fulong2e.c ++++ b/hw/mips/mips_fulong2e.c +@@ -315,12 +315,11 @@ static void mips_fulong2e_init(MachineState *machine) + error_report("Invalid RAM size, should be 256MB"); + exit(EXIT_FAILURE); + } ++ memory_region_add_subregion(address_space_mem, 0, machine->ram); + +- /* allocate RAM */ ++ /* Boot ROM */ + memory_region_init_rom(bios, NULL, "fulong2e.bios", BIOS_SIZE, + &error_fatal); +- +- memory_region_add_subregion(address_space_mem, 0, machine->ram); + memory_region_add_subregion(address_space_mem, 0x1fc00000LL, bios); + + /* +-- +2.23.0 + diff --git a/hw-mips-malta-Add-some-logging-for-bad-register-offs.patch b/hw-mips-malta-Add-some-logging-for-bad-register-offs.patch new file mode 100644 index 0000000000000000000000000000000000000000..9ca156e75e5e07c049d52bd5008c4329ac32ef3c --- /dev/null +++ b/hw-mips-malta-Add-some-logging-for-bad-register-offs.patch @@ -0,0 +1,57 @@ +From c707f06fb1d9b09e5d442e72f6f3dcd021671a90 Mon Sep 17 00:00:00 2001 +From: Aleksandar Markovic +Date: Mon, 18 May 2020 22:09:19 +0200 +Subject: [PATCH 664/709] hw/mips/malta: Add some logging for bad register + offset cases +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Log the cases where a guest attempts read or write using bad +register offset. + +Reviewed-by: Philippe Mathieu-Daudé +Tested-by: Philippe Mathieu-Daudé +Signed-off-by: Aleksandar Markovic +Message-id: <20200518200920.17344-21-aleksandar.qemu.devel@gmail.com> +[PMD: Replaced TARGET_FMT_lx by HWADDR_PRIX] +Signed-off-by: Philippe Mathieu-Daudé +--- + hw/mips/malta.c | 14 ++++++-------- + 1 file changed, 6 insertions(+), 8 deletions(-) + +diff --git a/hw/mips/malta.c b/hw/mips/malta.c +index e4c4de1b4e..b673a3a248 100644 +--- a/hw/mips/malta.c ++++ b/hw/mips/malta.c +@@ -427,10 +427,9 @@ static uint64_t malta_fpga_read(void *opaque, hwaddr addr, + break; + + default: +-#if 0 +- printf("malta_fpga_read: Bad register offset 0x" TARGET_FMT_lx "\n", +- addr); +-#endif ++ qemu_log_mask(LOG_GUEST_ERROR, ++ "malta_fpga_read: Bad register addr 0x%"HWADDR_PRIX"\n", ++ addr); + break; + } + return val; +@@ -515,10 +514,9 @@ static void malta_fpga_write(void *opaque, hwaddr addr, + break; + + default: +-#if 0 +- printf("malta_fpga_write: Bad register offset 0x" TARGET_FMT_lx "\n", +- addr); +-#endif ++ qemu_log_mask(LOG_GUEST_ERROR, ++ "malta_fpga_write: Bad register addr 0x%"HWADDR_PRIX"\n", ++ addr); + break; + } + } +-- +2.23.0 + diff --git a/hw-mips-mips_fulong2e-Remove-unused-audio-audio.h-in.patch b/hw-mips-mips_fulong2e-Remove-unused-audio-audio.h-in.patch new file mode 100644 index 0000000000000000000000000000000000000000..6102d57349783ff5e0ee70be098a06c620c90cb5 --- /dev/null +++ b/hw-mips-mips_fulong2e-Remove-unused-audio-audio.h-in.patch @@ -0,0 +1,34 @@ +From b3b8a1fea6ed5004bbad2f70833caee70402bf02 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Fri, 15 May 2020 10:42:09 +0200 +Subject: [PATCH 652/709] hw/mips/mips_fulong2e: Remove unused 'audio/audio.h' + include +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The Fuloong machine never had to use "audio/audio.h", remove it. + +Signed-off-by: Philippe Mathieu-Daudé +Reviewed-by: Huacai Chen +Message-id: 20200515084209.9419-1-f4bug@amsat.org +Signed-off-by: Gerd Hoffmann +--- + hw/mips/mips_fulong2e.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/hw/mips/mips_fulong2e.c b/hw/mips/mips_fulong2e.c +index ef02d54b33..05b9efa516 100644 +--- a/hw/mips/mips_fulong2e.c ++++ b/hw/mips/mips_fulong2e.c +@@ -33,7 +33,6 @@ + #include "hw/mips/mips.h" + #include "hw/mips/cpudevs.h" + #include "hw/pci/pci.h" +-#include "audio/audio.h" + #include "qemu/log.h" + #include "hw/loader.h" + #include "hw/ide/pci.h" +-- +2.23.0 + diff --git a/hw-mips-mips_int-De-duplicate-KVM-interrupt-delivery.patch b/hw-mips-mips_int-De-duplicate-KVM-interrupt-delivery.patch new file mode 100644 index 0000000000000000000000000000000000000000..be5505a2b663d845abfa17822df526d5722fd287 --- /dev/null +++ b/hw-mips-mips_int-De-duplicate-KVM-interrupt-delivery.patch @@ -0,0 +1,45 @@ +From 56b92eeeac8074501858e15b7658ec6099456f04 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Wed, 29 Apr 2020 10:21:05 +0200 +Subject: [PATCH 665/709] hw/mips/mips_int: De-duplicate KVM interrupt delivery +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Refactor duplicated code in a single place. + +Reviewed-by: Thomas Huth +Message-Id: <20200429082916.10669-2-f4bug@amsat.org> +Signed-off-by: Philippe Mathieu-Daudé +--- + hw/mips/mips_int.c | 11 +++-------- + 1 file changed, 3 insertions(+), 8 deletions(-) + +diff --git a/hw/mips/mips_int.c b/hw/mips/mips_int.c +index 796730b11d..4a1bf846da 100644 +--- a/hw/mips/mips_int.c ++++ b/hw/mips/mips_int.c +@@ -47,17 +47,12 @@ static void cpu_mips_irq_request(void *opaque, int irq, int level) + + if (level) { + env->CP0_Cause |= 1 << (irq + CP0Ca_IP); +- +- if (kvm_enabled() && irq == 2) { +- kvm_mips_set_interrupt(cpu, irq, level); +- } +- + } else { + env->CP0_Cause &= ~(1 << (irq + CP0Ca_IP)); ++ } + +- if (kvm_enabled() && irq == 2) { +- kvm_mips_set_interrupt(cpu, irq, level); +- } ++ if (kvm_enabled() && irq == 2) { ++ kvm_mips_set_interrupt(cpu, irq, level); + } + + if (env->CP0_Cause & CP0Ca_IP_mask) { +-- +2.23.0 + diff --git a/hw-misc-zynq_slcr-add-clock-generation-for-uarts.patch b/hw-misc-zynq_slcr-add-clock-generation-for-uarts.patch new file mode 100644 index 0000000000000000000000000000000000000000..865bcd16125baf9ee12aa93f8654125850a7297b --- /dev/null +++ b/hw-misc-zynq_slcr-add-clock-generation-for-uarts.patch @@ -0,0 +1,278 @@ +From 38867cb7ec90253289cab22c13282a3ef6530f69 Mon Sep 17 00:00:00 2001 +From: Damien Hedde +Date: Mon, 6 Apr 2020 15:52:48 +0200 +Subject: [PATCH 107/709] hw/misc/zynq_slcr: add clock generation for uarts + +Add some clocks to zynq_slcr ++ the main input clock (ps_clk) ++ the reference clock outputs for each uart (uart0 & 1) + +This commit also transitional the slcr to multi-phase reset as it is +required to initialize the clocks correctly. + +The clock frequencies are computed using the internal pll & uart configuration +registers and the input ps_clk frequency. + +Signed-off-by: Damien Hedde +Reviewed-by: Edgar E. Iglesias +Acked-by: Alistair Francis +Message-id: 20200406135251.157596-7-damien.hedde@greensocs.com +Signed-off-by: Peter Maydell +--- + hw/misc/zynq_slcr.c | 172 ++++++++++++++++++++++++++++++++++++++++++-- + 1 file changed, 168 insertions(+), 4 deletions(-) + +diff --git a/hw/misc/zynq_slcr.c b/hw/misc/zynq_slcr.c +index b9a38272d9..f7472d1f3c 100644 +--- a/hw/misc/zynq_slcr.c ++++ b/hw/misc/zynq_slcr.c +@@ -22,6 +22,7 @@ + #include "qemu/log.h" + #include "qemu/module.h" + #include "hw/registerfields.h" ++#include "hw/qdev-clock.h" + + #ifndef ZYNQ_SLCR_ERR_DEBUG + #define ZYNQ_SLCR_ERR_DEBUG 0 +@@ -45,6 +46,12 @@ REG32(LOCKSTA, 0x00c) + REG32(ARM_PLL_CTRL, 0x100) + REG32(DDR_PLL_CTRL, 0x104) + REG32(IO_PLL_CTRL, 0x108) ++/* fields for [ARM|DDR|IO]_PLL_CTRL registers */ ++ FIELD(xxx_PLL_CTRL, PLL_RESET, 0, 1) ++ FIELD(xxx_PLL_CTRL, PLL_PWRDWN, 1, 1) ++ FIELD(xxx_PLL_CTRL, PLL_BYPASS_QUAL, 3, 1) ++ FIELD(xxx_PLL_CTRL, PLL_BYPASS_FORCE, 4, 1) ++ FIELD(xxx_PLL_CTRL, PLL_FPDIV, 12, 7) + REG32(PLL_STATUS, 0x10c) + REG32(ARM_PLL_CFG, 0x110) + REG32(DDR_PLL_CFG, 0x114) +@@ -64,6 +71,10 @@ REG32(SMC_CLK_CTRL, 0x148) + REG32(LQSPI_CLK_CTRL, 0x14c) + REG32(SDIO_CLK_CTRL, 0x150) + REG32(UART_CLK_CTRL, 0x154) ++ FIELD(UART_CLK_CTRL, CLKACT0, 0, 1) ++ FIELD(UART_CLK_CTRL, CLKACT1, 1, 1) ++ FIELD(UART_CLK_CTRL, SRCSEL, 4, 2) ++ FIELD(UART_CLK_CTRL, DIVISOR, 8, 6) + REG32(SPI_CLK_CTRL, 0x158) + REG32(CAN_CLK_CTRL, 0x15c) + REG32(CAN_MIOCLK_CTRL, 0x160) +@@ -179,11 +190,127 @@ typedef struct ZynqSLCRState { + MemoryRegion iomem; + + uint32_t regs[ZYNQ_SLCR_NUM_REGS]; ++ ++ Clock *ps_clk; ++ Clock *uart0_ref_clk; ++ Clock *uart1_ref_clk; + } ZynqSLCRState; + +-static void zynq_slcr_reset(DeviceState *d) ++/* ++ * return the output frequency of ARM/DDR/IO pll ++ * using input frequency and PLL_CTRL register ++ */ ++static uint64_t zynq_slcr_compute_pll(uint64_t input, uint32_t ctrl_reg) ++{ ++ uint32_t mult = ((ctrl_reg & R_xxx_PLL_CTRL_PLL_FPDIV_MASK) >> ++ R_xxx_PLL_CTRL_PLL_FPDIV_SHIFT); ++ ++ /* first, check if pll is bypassed */ ++ if (ctrl_reg & R_xxx_PLL_CTRL_PLL_BYPASS_FORCE_MASK) { ++ return input; ++ } ++ ++ /* is pll disabled ? */ ++ if (ctrl_reg & (R_xxx_PLL_CTRL_PLL_RESET_MASK | ++ R_xxx_PLL_CTRL_PLL_PWRDWN_MASK)) { ++ return 0; ++ } ++ ++ /* frequency multiplier -> period division */ ++ return input / mult; ++} ++ ++/* ++ * return the output period of a clock given: ++ * + the periods in an array corresponding to input mux selector ++ * + the register xxx_CLK_CTRL value ++ * + enable bit index in ctrl register ++ * ++ * This function makes the assumption that the ctrl_reg value is organized as ++ * follows: ++ * + bits[13:8] clock frequency divisor ++ * + bits[5:4] clock mux selector (index in array) ++ * + bits[index] clock enable ++ */ ++static uint64_t zynq_slcr_compute_clock(const uint64_t periods[], ++ uint32_t ctrl_reg, ++ unsigned index) ++{ ++ uint32_t srcsel = extract32(ctrl_reg, 4, 2); /* bits [5:4] */ ++ uint32_t divisor = extract32(ctrl_reg, 8, 6); /* bits [13:8] */ ++ ++ /* first, check if clock is disabled */ ++ if (((ctrl_reg >> index) & 1u) == 0) { ++ return 0; ++ } ++ ++ /* ++ * according to the Zynq technical ref. manual UG585 v1.12.2 in ++ * Clocks chapter, section 25.10.1 page 705: ++ * "The 6-bit divider provides a divide range of 1 to 63" ++ * We follow here what is implemented in linux kernel and consider ++ * the 0 value as a bypass (no division). ++ */ ++ /* frequency divisor -> period multiplication */ ++ return periods[srcsel] * (divisor ? divisor : 1u); ++} ++ ++/* ++ * macro helper around zynq_slcr_compute_clock to avoid repeating ++ * the register name. ++ */ ++#define ZYNQ_COMPUTE_CLK(state, plls, reg, enable_field) \ ++ zynq_slcr_compute_clock((plls), (state)->regs[reg], \ ++ reg ## _ ## enable_field ## _SHIFT) ++ ++/** ++ * Compute and set the ouputs clocks periods. ++ * But do not propagate them further. Connected clocks ++ * will not receive any updates (See zynq_slcr_compute_clocks()) ++ */ ++static void zynq_slcr_compute_clocks(ZynqSLCRState *s) ++{ ++ uint64_t ps_clk = clock_get(s->ps_clk); ++ ++ /* consider outputs clocks are disabled while in reset */ ++ if (device_is_in_reset(DEVICE(s))) { ++ ps_clk = 0; ++ } ++ ++ uint64_t io_pll = zynq_slcr_compute_pll(ps_clk, s->regs[R_IO_PLL_CTRL]); ++ uint64_t arm_pll = zynq_slcr_compute_pll(ps_clk, s->regs[R_ARM_PLL_CTRL]); ++ uint64_t ddr_pll = zynq_slcr_compute_pll(ps_clk, s->regs[R_DDR_PLL_CTRL]); ++ ++ uint64_t uart_mux[4] = {io_pll, io_pll, arm_pll, ddr_pll}; ++ ++ /* compute uartX reference clocks */ ++ clock_set(s->uart0_ref_clk, ++ ZYNQ_COMPUTE_CLK(s, uart_mux, R_UART_CLK_CTRL, CLKACT0)); ++ clock_set(s->uart1_ref_clk, ++ ZYNQ_COMPUTE_CLK(s, uart_mux, R_UART_CLK_CTRL, CLKACT1)); ++} ++ ++/** ++ * Propagate the outputs clocks. ++ * zynq_slcr_compute_clocks() should have been called before ++ * to configure them. ++ */ ++static void zynq_slcr_propagate_clocks(ZynqSLCRState *s) + { +- ZynqSLCRState *s = ZYNQ_SLCR(d); ++ clock_propagate(s->uart0_ref_clk); ++ clock_propagate(s->uart1_ref_clk); ++} ++ ++static void zynq_slcr_ps_clk_callback(void *opaque) ++{ ++ ZynqSLCRState *s = (ZynqSLCRState *) opaque; ++ zynq_slcr_compute_clocks(s); ++ zynq_slcr_propagate_clocks(s); ++} ++ ++static void zynq_slcr_reset_init(Object *obj, ResetType type) ++{ ++ ZynqSLCRState *s = ZYNQ_SLCR(obj); + int i; + + DB_PRINT("RESET\n"); +@@ -277,6 +404,23 @@ static void zynq_slcr_reset(DeviceState *d) + s->regs[R_DDRIOB + 12] = 0x00000021; + } + ++static void zynq_slcr_reset_hold(Object *obj) ++{ ++ ZynqSLCRState *s = ZYNQ_SLCR(obj); ++ ++ /* will disable all output clocks */ ++ zynq_slcr_compute_clocks(s); ++ zynq_slcr_propagate_clocks(s); ++} ++ ++static void zynq_slcr_reset_exit(Object *obj) ++{ ++ ZynqSLCRState *s = ZYNQ_SLCR(obj); ++ ++ /* will compute output clocks according to ps_clk and registers */ ++ zynq_slcr_compute_clocks(s); ++ zynq_slcr_propagate_clocks(s); ++} + + static bool zynq_slcr_check_offset(hwaddr offset, bool rnw) + { +@@ -409,6 +553,13 @@ static void zynq_slcr_write(void *opaque, hwaddr offset, + qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET); + } + break; ++ case R_IO_PLL_CTRL: ++ case R_ARM_PLL_CTRL: ++ case R_DDR_PLL_CTRL: ++ case R_UART_CLK_CTRL: ++ zynq_slcr_compute_clocks(s); ++ zynq_slcr_propagate_clocks(s); ++ break; + } + } + +@@ -418,6 +569,13 @@ static const MemoryRegionOps slcr_ops = { + .endianness = DEVICE_NATIVE_ENDIAN, + }; + ++static const ClockPortInitArray zynq_slcr_clocks = { ++ QDEV_CLOCK_IN(ZynqSLCRState, ps_clk, zynq_slcr_ps_clk_callback), ++ QDEV_CLOCK_OUT(ZynqSLCRState, uart0_ref_clk), ++ QDEV_CLOCK_OUT(ZynqSLCRState, uart1_ref_clk), ++ QDEV_CLOCK_END ++}; ++ + static void zynq_slcr_init(Object *obj) + { + ZynqSLCRState *s = ZYNQ_SLCR(obj); +@@ -425,14 +583,17 @@ static void zynq_slcr_init(Object *obj) + memory_region_init_io(&s->iomem, obj, &slcr_ops, s, "slcr", + ZYNQ_SLCR_MMIO_SIZE); + sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->iomem); ++ ++ qdev_init_clocks(DEVICE(obj), zynq_slcr_clocks); + } + + static const VMStateDescription vmstate_zynq_slcr = { + .name = "zynq_slcr", +- .version_id = 2, ++ .version_id = 3, + .minimum_version_id = 2, + .fields = (VMStateField[]) { + VMSTATE_UINT32_ARRAY(regs, ZynqSLCRState, ZYNQ_SLCR_NUM_REGS), ++ VMSTATE_CLOCK_V(ps_clk, ZynqSLCRState, 3), + VMSTATE_END_OF_LIST() + } + }; +@@ -440,9 +601,12 @@ static const VMStateDescription vmstate_zynq_slcr = { + static void zynq_slcr_class_init(ObjectClass *klass, void *data) + { + DeviceClass *dc = DEVICE_CLASS(klass); ++ ResettableClass *rc = RESETTABLE_CLASS(klass); + + dc->vmsd = &vmstate_zynq_slcr; +- dc->reset = zynq_slcr_reset; ++ rc->phases.enter = zynq_slcr_reset_init; ++ rc->phases.hold = zynq_slcr_reset_hold; ++ rc->phases.exit = zynq_slcr_reset_exit; + } + + static const TypeInfo zynq_slcr_info = { +-- +2.23.0 + diff --git a/hw-net-Add-Smartfusion2-emac-block.patch b/hw-net-Add-Smartfusion2-emac-block.patch new file mode 100644 index 0000000000000000000000000000000000000000..889ddf780d05f9089af5a2d69657c28f76e1ea2b --- /dev/null +++ b/hw-net-Add-Smartfusion2-emac-block.patch @@ -0,0 +1,705 @@ +From 1c66437879654705bbf8099d9767594668c57ce8 Mon Sep 17 00:00:00 2001 +From: Subbaraya Sundeep +Date: Thu, 16 Apr 2020 20:24:49 +0530 +Subject: [PATCH 099/709] hw/net: Add Smartfusion2 emac block +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Modelled Ethernet MAC of Smartfusion2 SoC. +Micrel KSZ8051 PHY is present on Emcraft's +SOM kit hence same PHY is emulated. + +Signed-off-by: Subbaraya Sundeep +Reviewed-by: Philippe Mathieu-Daudé +Tested-by: Philippe Mathieu-Daudé +Message-id: 1587048891-30493-2-git-send-email-sundeep.lkml@gmail.com +Signed-off-by: Peter Maydell +--- + MAINTAINERS | 2 + + hw/net/Makefile.objs | 1 + + hw/net/msf2-emac.c | 589 +++++++++++++++++++++++++++++++++++++ + include/hw/net/msf2-emac.h | 53 ++++ + 4 files changed, 645 insertions(+) + create mode 100644 hw/net/msf2-emac.c + create mode 100644 include/hw/net/msf2-emac.h + +diff --git a/MAINTAINERS b/MAINTAINERS +index 8cbc1fac2b..cea57331fe 100644 +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -919,6 +919,8 @@ F: include/hw/arm/msf2-soc.h + F: include/hw/misc/msf2-sysreg.h + F: include/hw/timer/mss-timer.h + F: include/hw/ssi/mss-spi.h ++F: hw/net/msf2-emac.c ++F: include/hw/net/msf2-emac.h + + Emcraft M2S-FG484 + M: Subbaraya Sundeep +diff --git a/hw/net/Makefile.objs b/hw/net/Makefile.objs +index af4d194866..f2b73983ee 100644 +--- a/hw/net/Makefile.objs ++++ b/hw/net/Makefile.objs +@@ -55,3 +55,4 @@ common-obj-$(CONFIG_ROCKER) += rocker/rocker.o rocker/rocker_fp.o \ + obj-$(call lnot,$(CONFIG_ROCKER)) += rocker/qmp-norocker.o + + common-obj-$(CONFIG_CAN_BUS) += can/ ++common-obj-$(CONFIG_MSF2) += msf2-emac.o +diff --git a/hw/net/msf2-emac.c b/hw/net/msf2-emac.c +new file mode 100644 +index 0000000000..32ba9e8412 +--- /dev/null ++++ b/hw/net/msf2-emac.c +@@ -0,0 +1,589 @@ ++/* ++ * QEMU model of the Smartfusion2 Ethernet MAC. ++ * ++ * Copyright (c) 2020 Subbaraya Sundeep . ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a copy ++ * of this software and associated documentation files (the "Software"), to deal ++ * in the Software without restriction, including without limitation the rights ++ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ++ * copies of the Software, and to permit persons to whom the Software is ++ * furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ++ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ * 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. ++ * ++ * Refer to section Ethernet MAC in the document: ++ * UG0331: SmartFusion2 Microcontroller Subsystem User Guide ++ * Datasheet URL: ++ * https://www.microsemi.com/document-portal/cat_view/56661-internal-documents/ ++ * 56758-soc?lang=en&limit=20&limitstart=220 ++ */ ++ ++#include "qemu/osdep.h" ++#include "qemu-common.h" ++#include "qemu/log.h" ++#include "qapi/error.h" ++#include "exec/address-spaces.h" ++#include "hw/registerfields.h" ++#include "hw/net/msf2-emac.h" ++#include "hw/net/mii.h" ++#include "hw/irq.h" ++#include "hw/qdev-properties.h" ++#include "migration/vmstate.h" ++ ++REG32(CFG1, 0x0) ++ FIELD(CFG1, RESET, 31, 1) ++ FIELD(CFG1, RX_EN, 2, 1) ++ FIELD(CFG1, TX_EN, 0, 1) ++ FIELD(CFG1, LB_EN, 8, 1) ++REG32(CFG2, 0x4) ++REG32(IFG, 0x8) ++REG32(HALF_DUPLEX, 0xc) ++REG32(MAX_FRAME_LENGTH, 0x10) ++REG32(MII_CMD, 0x24) ++ FIELD(MII_CMD, READ, 0, 1) ++REG32(MII_ADDR, 0x28) ++ FIELD(MII_ADDR, REGADDR, 0, 5) ++ FIELD(MII_ADDR, PHYADDR, 8, 5) ++REG32(MII_CTL, 0x2c) ++REG32(MII_STS, 0x30) ++REG32(STA1, 0x40) ++REG32(STA2, 0x44) ++REG32(FIFO_CFG0, 0x48) ++REG32(FIFO_CFG4, 0x58) ++ FIELD(FIFO_CFG4, BCAST, 9, 1) ++ FIELD(FIFO_CFG4, MCAST, 8, 1) ++REG32(FIFO_CFG5, 0x5C) ++ FIELD(FIFO_CFG5, BCAST, 9, 1) ++ FIELD(FIFO_CFG5, MCAST, 8, 1) ++REG32(DMA_TX_CTL, 0x180) ++ FIELD(DMA_TX_CTL, EN, 0, 1) ++REG32(DMA_TX_DESC, 0x184) ++REG32(DMA_TX_STATUS, 0x188) ++ FIELD(DMA_TX_STATUS, PKTCNT, 16, 8) ++ FIELD(DMA_TX_STATUS, UNDERRUN, 1, 1) ++ FIELD(DMA_TX_STATUS, PKT_SENT, 0, 1) ++REG32(DMA_RX_CTL, 0x18c) ++ FIELD(DMA_RX_CTL, EN, 0, 1) ++REG32(DMA_RX_DESC, 0x190) ++REG32(DMA_RX_STATUS, 0x194) ++ FIELD(DMA_RX_STATUS, PKTCNT, 16, 8) ++ FIELD(DMA_RX_STATUS, OVERFLOW, 2, 1) ++ FIELD(DMA_RX_STATUS, PKT_RCVD, 0, 1) ++REG32(DMA_IRQ_MASK, 0x198) ++REG32(DMA_IRQ, 0x19c) ++ ++#define EMPTY_MASK (1 << 31) ++#define PKT_SIZE 0x7FF ++#define PHYADDR 0x1 ++#define MAX_PKT_SIZE 2048 ++ ++typedef struct { ++ uint32_t pktaddr; ++ uint32_t pktsize; ++ uint32_t next; ++} EmacDesc; ++ ++static uint32_t emac_get_isr(MSF2EmacState *s) ++{ ++ uint32_t ier = s->regs[R_DMA_IRQ_MASK]; ++ uint32_t tx = s->regs[R_DMA_TX_STATUS] & 0xF; ++ uint32_t rx = s->regs[R_DMA_RX_STATUS] & 0xF; ++ uint32_t isr = (rx << 4) | tx; ++ ++ s->regs[R_DMA_IRQ] = ier & isr; ++ return s->regs[R_DMA_IRQ]; ++} ++ ++static void emac_update_irq(MSF2EmacState *s) ++{ ++ bool intr = emac_get_isr(s); ++ ++ qemu_set_irq(s->irq, intr); ++} ++ ++static void emac_load_desc(MSF2EmacState *s, EmacDesc *d, hwaddr desc) ++{ ++ address_space_read(&s->dma_as, desc, MEMTXATTRS_UNSPECIFIED, d, sizeof *d); ++ /* Convert from LE into host endianness. */ ++ d->pktaddr = le32_to_cpu(d->pktaddr); ++ d->pktsize = le32_to_cpu(d->pktsize); ++ d->next = le32_to_cpu(d->next); ++} ++ ++static void emac_store_desc(MSF2EmacState *s, EmacDesc *d, hwaddr desc) ++{ ++ /* Convert from host endianness into LE. */ ++ d->pktaddr = cpu_to_le32(d->pktaddr); ++ d->pktsize = cpu_to_le32(d->pktsize); ++ d->next = cpu_to_le32(d->next); ++ ++ address_space_write(&s->dma_as, desc, MEMTXATTRS_UNSPECIFIED, d, sizeof *d); ++} ++ ++static void msf2_dma_tx(MSF2EmacState *s) ++{ ++ NetClientState *nc = qemu_get_queue(s->nic); ++ hwaddr desc = s->regs[R_DMA_TX_DESC]; ++ uint8_t buf[MAX_PKT_SIZE]; ++ EmacDesc d; ++ int size; ++ uint8_t pktcnt; ++ uint32_t status; ++ ++ if (!(s->regs[R_CFG1] & R_CFG1_TX_EN_MASK)) { ++ return; ++ } ++ ++ while (1) { ++ emac_load_desc(s, &d, desc); ++ if (d.pktsize & EMPTY_MASK) { ++ break; ++ } ++ size = d.pktsize & PKT_SIZE; ++ address_space_read(&s->dma_as, d.pktaddr, MEMTXATTRS_UNSPECIFIED, ++ buf, size); ++ /* ++ * This is very basic way to send packets. Ideally there should be ++ * a FIFO and packets should be sent out from FIFO only when ++ * R_CFG1 bit 0 is set. ++ */ ++ if (s->regs[R_CFG1] & R_CFG1_LB_EN_MASK) { ++ nc->info->receive(nc, buf, size); ++ } else { ++ qemu_send_packet(nc, buf, size); ++ } ++ d.pktsize |= EMPTY_MASK; ++ emac_store_desc(s, &d, desc); ++ /* update sent packets count */ ++ status = s->regs[R_DMA_TX_STATUS]; ++ pktcnt = FIELD_EX32(status, DMA_TX_STATUS, PKTCNT); ++ pktcnt++; ++ s->regs[R_DMA_TX_STATUS] = FIELD_DP32(status, DMA_TX_STATUS, ++ PKTCNT, pktcnt); ++ s->regs[R_DMA_TX_STATUS] |= R_DMA_TX_STATUS_PKT_SENT_MASK; ++ desc = d.next; ++ } ++ s->regs[R_DMA_TX_STATUS] |= R_DMA_TX_STATUS_UNDERRUN_MASK; ++ s->regs[R_DMA_TX_CTL] &= ~R_DMA_TX_CTL_EN_MASK; ++} ++ ++static void msf2_phy_update_link(MSF2EmacState *s) ++{ ++ /* Autonegotiation status mirrors link status. */ ++ if (qemu_get_queue(s->nic)->link_down) { ++ s->phy_regs[MII_BMSR] &= ~(MII_BMSR_AN_COMP | ++ MII_BMSR_LINK_ST); ++ } else { ++ s->phy_regs[MII_BMSR] |= (MII_BMSR_AN_COMP | ++ MII_BMSR_LINK_ST); ++ } ++} ++ ++static void msf2_phy_reset(MSF2EmacState *s) ++{ ++ memset(&s->phy_regs[0], 0, sizeof(s->phy_regs)); ++ s->phy_regs[MII_BMCR] = 0x1140; ++ s->phy_regs[MII_BMSR] = 0x7968; ++ s->phy_regs[MII_PHYID1] = 0x0022; ++ s->phy_regs[MII_PHYID2] = 0x1550; ++ s->phy_regs[MII_ANAR] = 0x01E1; ++ s->phy_regs[MII_ANLPAR] = 0xCDE1; ++ ++ msf2_phy_update_link(s); ++} ++ ++static void write_to_phy(MSF2EmacState *s) ++{ ++ uint8_t reg_addr = s->regs[R_MII_ADDR] & R_MII_ADDR_REGADDR_MASK; ++ uint8_t phy_addr = (s->regs[R_MII_ADDR] >> R_MII_ADDR_PHYADDR_SHIFT) & ++ R_MII_ADDR_REGADDR_MASK; ++ uint16_t data = s->regs[R_MII_CTL] & 0xFFFF; ++ ++ if (phy_addr != PHYADDR) { ++ return; ++ } ++ ++ switch (reg_addr) { ++ case MII_BMCR: ++ if (data & MII_BMCR_RESET) { ++ /* Phy reset */ ++ msf2_phy_reset(s); ++ data &= ~MII_BMCR_RESET; ++ } ++ if (data & MII_BMCR_AUTOEN) { ++ /* Complete autonegotiation immediately */ ++ data &= ~MII_BMCR_AUTOEN; ++ s->phy_regs[MII_BMSR] |= MII_BMSR_AN_COMP; ++ } ++ break; ++ } ++ ++ s->phy_regs[reg_addr] = data; ++} ++ ++static uint16_t read_from_phy(MSF2EmacState *s) ++{ ++ uint8_t reg_addr = s->regs[R_MII_ADDR] & R_MII_ADDR_REGADDR_MASK; ++ uint8_t phy_addr = (s->regs[R_MII_ADDR] >> R_MII_ADDR_PHYADDR_SHIFT) & ++ R_MII_ADDR_REGADDR_MASK; ++ ++ if (phy_addr == PHYADDR) { ++ return s->phy_regs[reg_addr]; ++ } else { ++ return 0xFFFF; ++ } ++} ++ ++static void msf2_emac_do_reset(MSF2EmacState *s) ++{ ++ memset(&s->regs[0], 0, sizeof(s->regs)); ++ s->regs[R_CFG1] = 0x80000000; ++ s->regs[R_CFG2] = 0x00007000; ++ s->regs[R_IFG] = 0x40605060; ++ s->regs[R_HALF_DUPLEX] = 0x00A1F037; ++ s->regs[R_MAX_FRAME_LENGTH] = 0x00000600; ++ s->regs[R_FIFO_CFG5] = 0X3FFFF; ++ ++ msf2_phy_reset(s); ++} ++ ++static uint64_t emac_read(void *opaque, hwaddr addr, unsigned int size) ++{ ++ MSF2EmacState *s = opaque; ++ uint32_t r = 0; ++ ++ addr >>= 2; ++ ++ switch (addr) { ++ case R_DMA_IRQ: ++ r = emac_get_isr(s); ++ break; ++ default: ++ if (addr >= ARRAY_SIZE(s->regs)) { ++ qemu_log_mask(LOG_GUEST_ERROR, ++ "%s: Bad offset 0x%" HWADDR_PRIx "\n", __func__, ++ addr * 4); ++ return r; ++ } ++ r = s->regs[addr]; ++ break; ++ } ++ return r; ++} ++ ++static void emac_write(void *opaque, hwaddr addr, uint64_t val64, ++ unsigned int size) ++{ ++ MSF2EmacState *s = opaque; ++ uint32_t value = val64; ++ uint32_t enreqbits; ++ uint8_t pktcnt; ++ ++ addr >>= 2; ++ switch (addr) { ++ case R_DMA_TX_CTL: ++ s->regs[addr] = value; ++ if (value & R_DMA_TX_CTL_EN_MASK) { ++ msf2_dma_tx(s); ++ } ++ break; ++ case R_DMA_RX_CTL: ++ s->regs[addr] = value; ++ if (value & R_DMA_RX_CTL_EN_MASK) { ++ s->rx_desc = s->regs[R_DMA_RX_DESC]; ++ qemu_flush_queued_packets(qemu_get_queue(s->nic)); ++ } ++ break; ++ case R_CFG1: ++ s->regs[addr] = value; ++ if (value & R_CFG1_RESET_MASK) { ++ msf2_emac_do_reset(s); ++ } ++ break; ++ case R_FIFO_CFG0: ++ /* ++ * For our implementation, turning on modules is instantaneous, ++ * so the states requested via the *ENREQ bits appear in the ++ * *ENRPLY bits immediately. Also the reset bits to reset PE-MCXMAC ++ * module are not emulated here since it deals with start of frames, ++ * inter-packet gap and control frames. ++ */ ++ enreqbits = extract32(value, 8, 5); ++ s->regs[addr] = deposit32(value, 16, 5, enreqbits); ++ break; ++ case R_DMA_TX_DESC: ++ if (value & 0x3) { ++ qemu_log_mask(LOG_GUEST_ERROR, "Tx Descriptor address should be" ++ " 32 bit aligned\n"); ++ } ++ /* Ignore [1:0] bits */ ++ s->regs[addr] = value & ~3; ++ break; ++ case R_DMA_RX_DESC: ++ if (value & 0x3) { ++ qemu_log_mask(LOG_GUEST_ERROR, "Rx Descriptor address should be" ++ " 32 bit aligned\n"); ++ } ++ /* Ignore [1:0] bits */ ++ s->regs[addr] = value & ~3; ++ break; ++ case R_DMA_TX_STATUS: ++ if (value & R_DMA_TX_STATUS_UNDERRUN_MASK) { ++ s->regs[addr] &= ~R_DMA_TX_STATUS_UNDERRUN_MASK; ++ } ++ if (value & R_DMA_TX_STATUS_PKT_SENT_MASK) { ++ pktcnt = FIELD_EX32(s->regs[addr], DMA_TX_STATUS, PKTCNT); ++ pktcnt--; ++ s->regs[addr] = FIELD_DP32(s->regs[addr], DMA_TX_STATUS, ++ PKTCNT, pktcnt); ++ if (pktcnt == 0) { ++ s->regs[addr] &= ~R_DMA_TX_STATUS_PKT_SENT_MASK; ++ } ++ } ++ break; ++ case R_DMA_RX_STATUS: ++ if (value & R_DMA_RX_STATUS_OVERFLOW_MASK) { ++ s->regs[addr] &= ~R_DMA_RX_STATUS_OVERFLOW_MASK; ++ } ++ if (value & R_DMA_RX_STATUS_PKT_RCVD_MASK) { ++ pktcnt = FIELD_EX32(s->regs[addr], DMA_RX_STATUS, PKTCNT); ++ pktcnt--; ++ s->regs[addr] = FIELD_DP32(s->regs[addr], DMA_RX_STATUS, ++ PKTCNT, pktcnt); ++ if (pktcnt == 0) { ++ s->regs[addr] &= ~R_DMA_RX_STATUS_PKT_RCVD_MASK; ++ } ++ } ++ break; ++ case R_DMA_IRQ: ++ break; ++ case R_MII_CMD: ++ if (value & R_MII_CMD_READ_MASK) { ++ s->regs[R_MII_STS] = read_from_phy(s); ++ } ++ break; ++ case R_MII_CTL: ++ s->regs[addr] = value; ++ write_to_phy(s); ++ break; ++ case R_STA1: ++ s->regs[addr] = value; ++ /* ++ * R_STA1 [31:24] : octet 1 of mac address ++ * R_STA1 [23:16] : octet 2 of mac address ++ * R_STA1 [15:8] : octet 3 of mac address ++ * R_STA1 [7:0] : octet 4 of mac address ++ */ ++ stl_be_p(s->mac_addr, value); ++ break; ++ case R_STA2: ++ s->regs[addr] = value; ++ /* ++ * R_STA2 [31:24] : octet 5 of mac address ++ * R_STA2 [23:16] : octet 6 of mac address ++ */ ++ stw_be_p(s->mac_addr + 4, value >> 16); ++ break; ++ default: ++ if (addr >= ARRAY_SIZE(s->regs)) { ++ qemu_log_mask(LOG_GUEST_ERROR, ++ "%s: Bad offset 0x%" HWADDR_PRIx "\n", __func__, ++ addr * 4); ++ return; ++ } ++ s->regs[addr] = value; ++ break; ++ } ++ emac_update_irq(s); ++} ++ ++static const MemoryRegionOps emac_ops = { ++ .read = emac_read, ++ .write = emac_write, ++ .endianness = DEVICE_NATIVE_ENDIAN, ++ .impl = { ++ .min_access_size = 4, ++ .max_access_size = 4 ++ } ++}; ++ ++static bool emac_can_rx(NetClientState *nc) ++{ ++ MSF2EmacState *s = qemu_get_nic_opaque(nc); ++ ++ return (s->regs[R_CFG1] & R_CFG1_RX_EN_MASK) && ++ (s->regs[R_DMA_RX_CTL] & R_DMA_RX_CTL_EN_MASK); ++} ++ ++static bool addr_filter_ok(MSF2EmacState *s, const uint8_t *buf) ++{ ++ /* The broadcast MAC address: FF:FF:FF:FF:FF:FF */ ++ const uint8_t broadcast_addr[] = { 0xFF, 0xFF, 0xFF, 0xFF, ++ 0xFF, 0xFF }; ++ bool bcast_en = true; ++ bool mcast_en = true; ++ ++ if (s->regs[R_FIFO_CFG5] & R_FIFO_CFG5_BCAST_MASK) { ++ bcast_en = true; /* Broadcast dont care for drop circuitry */ ++ } else if (s->regs[R_FIFO_CFG4] & R_FIFO_CFG4_BCAST_MASK) { ++ bcast_en = false; ++ } ++ ++ if (s->regs[R_FIFO_CFG5] & R_FIFO_CFG5_MCAST_MASK) { ++ mcast_en = true; /* Multicast dont care for drop circuitry */ ++ } else if (s->regs[R_FIFO_CFG4] & R_FIFO_CFG4_MCAST_MASK) { ++ mcast_en = false; ++ } ++ ++ if (!memcmp(buf, broadcast_addr, sizeof(broadcast_addr))) { ++ return bcast_en; ++ } ++ ++ if (buf[0] & 1) { ++ return mcast_en; ++ } ++ ++ return !memcmp(buf, s->mac_addr, sizeof(s->mac_addr)); ++} ++ ++static ssize_t emac_rx(NetClientState *nc, const uint8_t *buf, size_t size) ++{ ++ MSF2EmacState *s = qemu_get_nic_opaque(nc); ++ EmacDesc d; ++ uint8_t pktcnt; ++ uint32_t status; ++ ++ if (size > (s->regs[R_MAX_FRAME_LENGTH] & 0xFFFF)) { ++ return size; ++ } ++ if (!addr_filter_ok(s, buf)) { ++ return size; ++ } ++ ++ emac_load_desc(s, &d, s->rx_desc); ++ ++ if (d.pktsize & EMPTY_MASK) { ++ address_space_write(&s->dma_as, d.pktaddr, MEMTXATTRS_UNSPECIFIED, ++ buf, size & PKT_SIZE); ++ d.pktsize = size & PKT_SIZE; ++ emac_store_desc(s, &d, s->rx_desc); ++ /* update received packets count */ ++ status = s->regs[R_DMA_RX_STATUS]; ++ pktcnt = FIELD_EX32(status, DMA_RX_STATUS, PKTCNT); ++ pktcnt++; ++ s->regs[R_DMA_RX_STATUS] = FIELD_DP32(status, DMA_RX_STATUS, ++ PKTCNT, pktcnt); ++ s->regs[R_DMA_RX_STATUS] |= R_DMA_RX_STATUS_PKT_RCVD_MASK; ++ s->rx_desc = d.next; ++ } else { ++ s->regs[R_DMA_RX_CTL] &= ~R_DMA_RX_CTL_EN_MASK; ++ s->regs[R_DMA_RX_STATUS] |= R_DMA_RX_STATUS_OVERFLOW_MASK; ++ } ++ emac_update_irq(s); ++ return size; ++} ++ ++static void msf2_emac_reset(DeviceState *dev) ++{ ++ MSF2EmacState *s = MSS_EMAC(dev); ++ ++ msf2_emac_do_reset(s); ++} ++ ++static void emac_set_link(NetClientState *nc) ++{ ++ MSF2EmacState *s = qemu_get_nic_opaque(nc); ++ ++ msf2_phy_update_link(s); ++} ++ ++static NetClientInfo net_msf2_emac_info = { ++ .type = NET_CLIENT_DRIVER_NIC, ++ .size = sizeof(NICState), ++ .can_receive = emac_can_rx, ++ .receive = emac_rx, ++ .link_status_changed = emac_set_link, ++}; ++ ++static void msf2_emac_realize(DeviceState *dev, Error **errp) ++{ ++ MSF2EmacState *s = MSS_EMAC(dev); ++ ++ if (!s->dma_mr) { ++ error_setg(errp, "MSS_EMAC 'ahb-bus' link not set"); ++ return; ++ } ++ ++ address_space_init(&s->dma_as, s->dma_mr, "emac-ahb"); ++ ++ qemu_macaddr_default_if_unset(&s->conf.macaddr); ++ s->nic = qemu_new_nic(&net_msf2_emac_info, &s->conf, ++ object_get_typename(OBJECT(dev)), dev->id, s); ++ qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a); ++} ++ ++static void msf2_emac_init(Object *obj) ++{ ++ MSF2EmacState *s = MSS_EMAC(obj); ++ ++ sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->irq); ++ ++ memory_region_init_io(&s->mmio, obj, &emac_ops, s, ++ "msf2-emac", R_MAX * 4); ++ sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio); ++} ++ ++static Property msf2_emac_properties[] = { ++ DEFINE_PROP_LINK("ahb-bus", MSF2EmacState, dma_mr, ++ TYPE_MEMORY_REGION, MemoryRegion *), ++ DEFINE_NIC_PROPERTIES(MSF2EmacState, conf), ++ DEFINE_PROP_END_OF_LIST(), ++}; ++ ++static const VMStateDescription vmstate_msf2_emac = { ++ .name = TYPE_MSS_EMAC, ++ .version_id = 1, ++ .minimum_version_id = 1, ++ .fields = (VMStateField[]) { ++ VMSTATE_UINT8_ARRAY(mac_addr, MSF2EmacState, ETH_ALEN), ++ VMSTATE_UINT32(rx_desc, MSF2EmacState), ++ VMSTATE_UINT16_ARRAY(phy_regs, MSF2EmacState, PHY_MAX_REGS), ++ VMSTATE_UINT32_ARRAY(regs, MSF2EmacState, R_MAX), ++ VMSTATE_END_OF_LIST() ++ } ++}; ++ ++static void msf2_emac_class_init(ObjectClass *klass, void *data) ++{ ++ DeviceClass *dc = DEVICE_CLASS(klass); ++ ++ dc->realize = msf2_emac_realize; ++ dc->reset = msf2_emac_reset; ++ dc->vmsd = &vmstate_msf2_emac; ++ device_class_set_props(dc, msf2_emac_properties); ++} ++ ++static const TypeInfo msf2_emac_info = { ++ .name = TYPE_MSS_EMAC, ++ .parent = TYPE_SYS_BUS_DEVICE, ++ .instance_size = sizeof(MSF2EmacState), ++ .instance_init = msf2_emac_init, ++ .class_init = msf2_emac_class_init, ++}; ++ ++static void msf2_emac_register_types(void) ++{ ++ type_register_static(&msf2_emac_info); ++} ++ ++type_init(msf2_emac_register_types) +diff --git a/include/hw/net/msf2-emac.h b/include/hw/net/msf2-emac.h +new file mode 100644 +index 0000000000..37966d3a81 +--- /dev/null ++++ b/include/hw/net/msf2-emac.h +@@ -0,0 +1,53 @@ ++/* ++ * QEMU model of the Smartfusion2 Ethernet MAC. ++ * ++ * Copyright (c) 2020 Subbaraya Sundeep . ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a copy ++ * of this software and associated documentation files (the "Software"), to deal ++ * in the Software without restriction, including without limitation the rights ++ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ++ * copies of the Software, and to permit persons to whom the Software is ++ * furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ++ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ * 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. ++ */ ++ ++#include "hw/sysbus.h" ++#include "exec/memory.h" ++#include "net/net.h" ++#include "net/eth.h" ++ ++#define TYPE_MSS_EMAC "msf2-emac" ++#define MSS_EMAC(obj) \ ++ OBJECT_CHECK(MSF2EmacState, (obj), TYPE_MSS_EMAC) ++ ++#define R_MAX (0x1a0 / 4) ++#define PHY_MAX_REGS 32 ++ ++typedef struct MSF2EmacState { ++ SysBusDevice parent; ++ ++ MemoryRegion mmio; ++ MemoryRegion *dma_mr; ++ AddressSpace dma_as; ++ ++ qemu_irq irq; ++ NICState *nic; ++ NICConf conf; ++ ++ uint8_t mac_addr[ETH_ALEN]; ++ uint32_t rx_desc; ++ uint16_t phy_regs[PHY_MAX_REGS]; ++ ++ uint32_t regs[R_MAX]; ++} MSF2EmacState; +-- +2.23.0 + diff --git a/hw-net-xilinx_axienet-Auto-clear-PHY-Autoneg.patch b/hw-net-xilinx_axienet-Auto-clear-PHY-Autoneg.patch new file mode 100644 index 0000000000000000000000000000000000000000..9aa86d6b31d435a759e4ef15f2dcbe9da0fdb4d0 --- /dev/null +++ b/hw-net-xilinx_axienet-Auto-clear-PHY-Autoneg.patch @@ -0,0 +1,33 @@ +From 3e2a0cb99d26fd5fb34ab8c50f90d4292363245d Mon Sep 17 00:00:00 2001 +From: "Edgar E. Iglesias" +Date: Wed, 6 May 2020 10:25:05 +0200 +Subject: [PATCH 402/709] hw/net/xilinx_axienet: Auto-clear PHY Autoneg + +Auto-clear PHY CR Autoneg bits. This makes this model +work with recent Linux kernels. + +Reviewed-by: Francisco Iglesias +Signed-off-by: Edgar E. Iglesias +Message-Id: <20200506082513.18751-2-edgar.iglesias@gmail.com> +--- + hw/net/xilinx_axienet.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/hw/net/xilinx_axienet.c b/hw/net/xilinx_axienet.c +index 704788811a..0f97510d8a 100644 +--- a/hw/net/xilinx_axienet.c ++++ b/hw/net/xilinx_axienet.c +@@ -149,8 +149,8 @@ tdk_write(struct PHY *phy, unsigned int req, unsigned int data) + break; + } + +- /* Unconditionally clear regs[BMCR][BMCR_RESET] */ +- phy->regs[0] &= ~0x8000; ++ /* Unconditionally clear regs[BMCR][BMCR_RESET] and auto-neg */ ++ phy->regs[0] &= ~0x8200; + } + + static void +-- +2.23.0 + diff --git a/hw-net-xilinx_axienet-Cleanup-stream-push-assignment.patch b/hw-net-xilinx_axienet-Cleanup-stream-push-assignment.patch new file mode 100644 index 0000000000000000000000000000000000000000..1eb15b276544b766fdf2cbdea9f432940d70c193 --- /dev/null +++ b/hw-net-xilinx_axienet-Cleanup-stream-push-assignment.patch @@ -0,0 +1,70 @@ +From 0d9047c4d999add0be60b12f204ce4c14c457415 Mon Sep 17 00:00:00 2001 +From: "Edgar E. Iglesias" +Date: Wed, 6 May 2020 10:25:06 +0200 +Subject: [PATCH 403/709] hw/net/xilinx_axienet: Cleanup stream->push + assignment +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Split the shared stream_class_init function to assign +stream->push with better type-safety. + +Reviewed-by: Alistair Francis +Reviewed-by: Francisco Iglesias +Signed-off-by: Edgar E. Iglesias +Reviewed-by: Philippe Mathieu-Daudé +Message-Id: <20200506082513.18751-3-edgar.iglesias@gmail.com> +--- + hw/net/xilinx_axienet.c | 18 ++++++++++++------ + 1 file changed, 12 insertions(+), 6 deletions(-) + +diff --git a/hw/net/xilinx_axienet.c b/hw/net/xilinx_axienet.c +index 0f97510d8a..84073753d7 100644 +--- a/hw/net/xilinx_axienet.c ++++ b/hw/net/xilinx_axienet.c +@@ -1029,11 +1029,19 @@ static void xilinx_enet_class_init(ObjectClass *klass, void *data) + dc->reset = xilinx_axienet_reset; + } + +-static void xilinx_enet_stream_class_init(ObjectClass *klass, void *data) ++static void xilinx_enet_control_stream_class_init(ObjectClass *klass, ++ void *data) + { + StreamSlaveClass *ssc = STREAM_SLAVE_CLASS(klass); + +- ssc->push = data; ++ ssc->push = xilinx_axienet_control_stream_push; ++} ++ ++static void xilinx_enet_data_stream_class_init(ObjectClass *klass, void *data) ++{ ++ StreamSlaveClass *ssc = STREAM_SLAVE_CLASS(klass); ++ ++ ssc->push = xilinx_axienet_data_stream_push; + } + + static const TypeInfo xilinx_enet_info = { +@@ -1048,8 +1056,7 @@ static const TypeInfo xilinx_enet_data_stream_info = { + .name = TYPE_XILINX_AXI_ENET_DATA_STREAM, + .parent = TYPE_OBJECT, + .instance_size = sizeof(struct XilinxAXIEnetStreamSlave), +- .class_init = xilinx_enet_stream_class_init, +- .class_data = xilinx_axienet_data_stream_push, ++ .class_init = xilinx_enet_data_stream_class_init, + .interfaces = (InterfaceInfo[]) { + { TYPE_STREAM_SLAVE }, + { } +@@ -1060,8 +1067,7 @@ static const TypeInfo xilinx_enet_control_stream_info = { + .name = TYPE_XILINX_AXI_ENET_CONTROL_STREAM, + .parent = TYPE_OBJECT, + .instance_size = sizeof(struct XilinxAXIEnetStreamSlave), +- .class_init = xilinx_enet_stream_class_init, +- .class_data = xilinx_axienet_control_stream_push, ++ .class_init = xilinx_enet_control_stream_class_init, + .interfaces = (InterfaceInfo[]) { + { TYPE_STREAM_SLAVE }, + { } +-- +2.23.0 + diff --git a/hw-net-xilinx_axienet-Handle-fragmented-packets-from.patch b/hw-net-xilinx_axienet-Handle-fragmented-packets-from.patch new file mode 100644 index 0000000000000000000000000000000000000000..f25532760941d607b7b70b50e335b6af3fa5c5f7 --- /dev/null +++ b/hw-net-xilinx_axienet-Handle-fragmented-packets-from.patch @@ -0,0 +1,113 @@ +From 2a4f26350c53f9f48d0245254d7af0c55a1d22fe Mon Sep 17 00:00:00 2001 +From: "Edgar E. Iglesias" +Date: Wed, 6 May 2020 10:25:10 +0200 +Subject: [PATCH 407/709] hw/net/xilinx_axienet: Handle fragmented packets from + DMA + +Add support for fragmented packets from the DMA. + +Reviewed-by: Francisco Iglesias +Signed-off-by: Edgar E. Iglesias +Message-Id: <20200506082513.18751-7-edgar.iglesias@gmail.com> +--- + hw/net/xilinx_axienet.c | 38 +++++++++++++++++++++++++++++++------- + 1 file changed, 31 insertions(+), 7 deletions(-) + +diff --git a/hw/net/xilinx_axienet.c b/hw/net/xilinx_axienet.c +index bd48305577..498afe2f54 100644 +--- a/hw/net/xilinx_axienet.c ++++ b/hw/net/xilinx_axienet.c +@@ -402,6 +402,9 @@ struct XilinxAXIEnet { + + uint32_t hdr[CONTROL_PAYLOAD_WORDS]; + ++ uint8_t *txmem; ++ uint32_t txpos; ++ + uint8_t *rxmem; + uint32_t rxsize; + uint32_t rxpos; +@@ -421,6 +424,7 @@ static void axienet_rx_reset(XilinxAXIEnet *s) + static void axienet_tx_reset(XilinxAXIEnet *s) + { + s->tc = TC_JUM | TC_TX | TC_VLAN; ++ s->txpos = 0; + } + + static inline int axienet_rx_resetting(XilinxAXIEnet *s) +@@ -902,17 +906,35 @@ xilinx_axienet_data_stream_push(StreamSlave *obj, uint8_t *buf, size_t size, + XilinxAXIEnetStreamSlave *ds = XILINX_AXI_ENET_DATA_STREAM(obj); + XilinxAXIEnet *s = ds->enet; + +- /* We don't support fragmented packets yet. */ +- assert(eop); +- + /* TX enable ? */ + if (!(s->tc & TC_TX)) { + return size; + } + ++ if (s->txpos + size > s->c_txmem) { ++ qemu_log_mask(LOG_GUEST_ERROR, "%s: Packet larger than txmem\n", ++ TYPE_XILINX_AXI_ENET); ++ s->txpos = 0; ++ return size; ++ } ++ ++ if (s->txpos == 0 && eop) { ++ /* Fast path single fragment. */ ++ s->txpos = size; ++ } else { ++ memcpy(s->txmem + s->txpos, buf, size); ++ buf = s->txmem; ++ s->txpos += size; ++ ++ if (!eop) { ++ return size; ++ } ++ } ++ + /* Jumbo or vlan sizes ? */ + if (!(s->tc & TC_JUM)) { +- if (size > 1518 && size <= 1522 && !(s->tc & TC_VLAN)) { ++ if (s->txpos > 1518 && s->txpos <= 1522 && !(s->tc & TC_VLAN)) { ++ s->txpos = 0; + return size; + } + } +@@ -923,7 +945,7 @@ xilinx_axienet_data_stream_push(StreamSlave *obj, uint8_t *buf, size_t size, + uint32_t tmp_csum; + uint16_t csum; + +- tmp_csum = net_checksum_add(size - start_off, ++ tmp_csum = net_checksum_add(s->txpos - start_off, + buf + start_off); + /* Accumulate the seed. */ + tmp_csum += s->hdr[2] & 0xffff; +@@ -936,12 +958,13 @@ xilinx_axienet_data_stream_push(StreamSlave *obj, uint8_t *buf, size_t size, + buf[write_off + 1] = csum & 0xff; + } + +- qemu_send_packet(qemu_get_queue(s->nic), buf, size); ++ qemu_send_packet(qemu_get_queue(s->nic), buf, s->txpos); + +- s->stats.tx_bytes += size; ++ s->stats.tx_bytes += s->txpos; + s->regs[R_IS] |= IS_TX_COMPLETE; + enet_update_irq(s); + ++ s->txpos = 0; + return size; + } + +@@ -989,6 +1012,7 @@ static void xilinx_enet_realize(DeviceState *dev, Error **errp) + s->TEMAC.parent = s; + + s->rxmem = g_malloc(s->c_rxmem); ++ s->txmem = g_malloc(s->c_txmem); + return; + + xilinx_enet_realize_fail: +-- +2.23.0 + diff --git a/hw-net-xilinx_axienet-Remove-unncessary-cast.patch b/hw-net-xilinx_axienet-Remove-unncessary-cast.patch new file mode 100644 index 0000000000000000000000000000000000000000..62c32781beb30817dcac35e0045a523dbd65033f --- /dev/null +++ b/hw-net-xilinx_axienet-Remove-unncessary-cast.patch @@ -0,0 +1,36 @@ +From da59e178d743b8fdb44518f2e58590467ba5ec9e Mon Sep 17 00:00:00 2001 +From: "Edgar E. Iglesias" +Date: Wed, 6 May 2020 10:25:07 +0200 +Subject: [PATCH 404/709] hw/net/xilinx_axienet: Remove unncessary cast +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Remove unncessary cast, buf is already uint8_t *. +No functional change. + +Reviewed-by: Alistair Francis +Reviewed-by: Francisco Iglesias +Signed-off-by: Edgar E. Iglesias +Reviewed-by: Philippe Mathieu-Daudé +Message-Id: <20200506082513.18751-4-edgar.iglesias@gmail.com> +--- + hw/net/xilinx_axienet.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/hw/net/xilinx_axienet.c b/hw/net/xilinx_axienet.c +index 84073753d7..c8dfcda3ee 100644 +--- a/hw/net/xilinx_axienet.c ++++ b/hw/net/xilinx_axienet.c +@@ -918,7 +918,7 @@ xilinx_axienet_data_stream_push(StreamSlave *obj, uint8_t *buf, size_t size) + uint16_t csum; + + tmp_csum = net_checksum_add(size - start_off, +- (uint8_t *)buf + start_off); ++ buf + start_off); + /* Accumulate the seed. */ + tmp_csum += s->hdr[2] & 0xffff; + +-- +2.23.0 + diff --git a/hw-pci-host-Use-CONFIG_PCI_BONITO-to-select-the-Boni.patch b/hw-pci-host-Use-CONFIG_PCI_BONITO-to-select-the-Boni.patch new file mode 100644 index 0000000000000000000000000000000000000000..39ea6b428a8b759686006a13f6fa179a2995c404 --- /dev/null +++ b/hw-pci-host-Use-CONFIG_PCI_BONITO-to-select-the-Boni.patch @@ -0,0 +1,63 @@ +From abc82de356f636d70ac36e202c989a5e978dbae3 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Sun, 3 Feb 2019 22:37:26 +0100 +Subject: [PATCH 654/709] hw/pci-host: Use CONFIG_PCI_BONITO to select the + Bonito North Bridge +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Ease the kconfig selection by introducing CONFIG_PCI_BONITO to select +the Bonito North Bridge. + +Reviewed-by: Aleksandar Markovic +Signed-off-by: Philippe Mathieu-Daudé +Message-id: <20200510210128.18343-6-f4bug@amsat.org> +Reviewed-by: Huacai Chen +Signed-off-by: Philippe Mathieu-Daudé +--- + hw/mips/Kconfig | 1 + + hw/pci-host/Kconfig | 4 ++++ + hw/pci-host/Makefile.objs | 2 +- + 3 files changed, 6 insertions(+), 1 deletion(-) + +diff --git a/hw/mips/Kconfig b/hw/mips/Kconfig +index 2c2adbc42a..2240504dff 100644 +--- a/hw/mips/Kconfig ++++ b/hw/mips/Kconfig +@@ -43,6 +43,7 @@ config JAZZ + + config FULONG + bool ++ select PCI_BONITO + + config MIPS_CPS + bool +diff --git a/hw/pci-host/Kconfig b/hw/pci-host/Kconfig +index 9642c77e98..8db41edc7e 100644 +--- a/hw/pci-host/Kconfig ++++ b/hw/pci-host/Kconfig +@@ -55,3 +55,7 @@ config PCI_EXPRESS_DESIGNWARE + bool + select PCI_EXPRESS + select MSI_NONBROKEN ++ ++config PCI_BONITO ++ select PCI ++ bool +diff --git a/hw/pci-host/Makefile.objs b/hw/pci-host/Makefile.objs +index 8c87e8494d..e422e0aca0 100644 +--- a/hw/pci-host/Makefile.objs ++++ b/hw/pci-host/Makefile.objs +@@ -12,7 +12,7 @@ common-obj-$(CONFIG_PPCE500_PCI) += ppce500.o + common-obj-$(CONFIG_VERSATILE_PCI) += versatile.o + + common-obj-$(CONFIG_PCI_SABRE) += sabre.o +-common-obj-$(CONFIG_FULONG) += bonito.o ++common-obj-$(CONFIG_PCI_BONITO) += bonito.o + common-obj-$(CONFIG_PCI_I440FX) += i440fx.o + common-obj-$(CONFIG_XEN_IGD_PASSTHROUGH) += xen_igd_pt.o + common-obj-$(CONFIG_PCI_EXPRESS_Q35) += q35.o +-- +2.23.0 + diff --git a/hw-pci-host-bonito-Better-describe-the-I-O-CS-region.patch b/hw-pci-host-bonito-Better-describe-the-I-O-CS-region.patch new file mode 100644 index 0000000000000000000000000000000000000000..174d60e504a5b20a3a67ff78d75a782aeb4b7c99 --- /dev/null +++ b/hw-pci-host-bonito-Better-describe-the-I-O-CS-region.patch @@ -0,0 +1,54 @@ +From 7a296990af3ae3a63e5397c9c1a9f26981815c1c Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Sun, 10 May 2020 21:46:43 +0200 +Subject: [PATCH 659/709] hw/pci-host/bonito: Better describe the I/O CS + regions +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Better describe the I/O CS regions, add the ROMCS region. + +Reviewed-by: Aleksandar Markovic +Message-id: <20200510210128.18343-11-f4bug@amsat.org> +Signed-off-by: Philippe Mathieu-Daudé +--- + hw/pci-host/bonito.c | 13 +++++++++++-- + 1 file changed, 11 insertions(+), 2 deletions(-) + +diff --git a/hw/pci-host/bonito.c b/hw/pci-host/bonito.c +index 52015cc2a7..20f2797a73 100644 +--- a/hw/pci-host/bonito.c ++++ b/hw/pci-host/bonito.c +@@ -673,6 +673,8 @@ static void bonito_realize(PCIDevice *dev, Error **errp) + sysbus_init_mmio(sysbus, &s->iomem_cop); + sysbus_mmio_map(sysbus, 4, 0x1fe00300); + ++ create_unimplemented_device("ROMCS", BONITO_FLASH_BASE, 60 * MiB); ++ + /* Map PCI IO Space 0x1fd0 0000 - 0x1fd1 0000 */ + memory_region_init_alias(&s->bonito_pciio, OBJECT(s), "isa_mmio", + get_system_io(), 0, BONITO_PCIIO_SIZE); +@@ -680,10 +682,17 @@ static void bonito_realize(PCIDevice *dev, Error **errp) + sysbus_mmio_map(sysbus, 5, BONITO_PCIIO_BASE); + + /* add pci local io mapping */ +- memory_region_init_alias(&s->bonito_localio, OBJECT(s), "isa_mmio", +- get_system_io(), 0, BONITO_DEV_SIZE); ++ ++ memory_region_init_alias(&s->bonito_localio, OBJECT(s), "IOCS[0]", ++ get_system_io(), 0, 256 * KiB); + sysbus_init_mmio(sysbus, &s->bonito_localio); + sysbus_mmio_map(sysbus, 6, BONITO_DEV_BASE); ++ create_unimplemented_device("IOCS[1]", BONITO_DEV_BASE + 1 * 256 * KiB, ++ 256 * KiB); ++ create_unimplemented_device("IOCS[2]", BONITO_DEV_BASE + 2 * 256 * KiB, ++ 256 * KiB); ++ create_unimplemented_device("IOCS[3]", BONITO_DEV_BASE + 3 * 256 * KiB, ++ 256 * KiB); + + memory_region_init_alias(pcimem_alias, NULL, "pci.mem.alias", + &bs->pci_mem, 0, BONITO_PCIHI_SIZE); +-- +2.23.0 + diff --git a/hw-pci-host-bonito-Fix-DPRINTF-format-strings.patch b/hw-pci-host-bonito-Fix-DPRINTF-format-strings.patch new file mode 100644 index 0000000000000000000000000000000000000000..764f31c3975bd4e528c7ea44d8d843fb5d788b05 --- /dev/null +++ b/hw-pci-host-bonito-Fix-DPRINTF-format-strings.patch @@ -0,0 +1,49 @@ +From 3d14264cceb005e6b2131082bfa202c701e7ffb6 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Sun, 10 May 2020 21:34:11 +0200 +Subject: [PATCH 655/709] hw/pci-host/bonito: Fix DPRINTF() format strings +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Reviewed-by: Huacai Chen +Message-id: <20200510210128.18343-7-f4bug@amsat.org> +Signed-off-by: Philippe Mathieu-Daudé +--- + hw/pci-host/bonito.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/hw/pci-host/bonito.c b/hw/pci-host/bonito.c +index f212796044..b874468ea6 100644 +--- a/hw/pci-host/bonito.c ++++ b/hw/pci-host/bonito.c +@@ -239,7 +239,7 @@ static void bonito_writel(void *opaque, hwaddr addr, + + saddr = addr >> 2; + +- DPRINTF("bonito_writel "TARGET_FMT_plx" val %x saddr %x\n", ++ DPRINTF("bonito_writel "TARGET_FMT_plx" val %lx saddr %x\n", + addr, val, saddr); + switch (saddr) { + case BONITO_BONPONCFG: +@@ -327,7 +327,7 @@ static void bonito_pciconf_writel(void *opaque, hwaddr addr, + PCIBonitoState *s = opaque; + PCIDevice *d = PCI_DEVICE(s); + +- DPRINTF("bonito_pciconf_writel "TARGET_FMT_plx" val %x\n", addr, val); ++ DPRINTF("bonito_pciconf_writel "TARGET_FMT_plx" val %lx\n", addr, val); + d->config_write(d, addr, val, 4); + } + +@@ -474,7 +474,7 @@ static void bonito_spciconf_write(void *opaque, hwaddr addr, uint64_t val, + uint32_t pciaddr; + uint16_t status; + +- DPRINTF("bonito_spciconf_write "TARGET_FMT_plx" size %d val %x\n", ++ DPRINTF("bonito_spciconf_write "TARGET_FMT_plx" size %d val %lx\n", + addr, size, val); + + pciaddr = bonito_sbridge_pciaddr(s, addr); +-- +2.23.0 + diff --git a/hw-pci-host-bonito-Map-all-the-Bonito64-I-O-range.patch b/hw-pci-host-bonito-Map-all-the-Bonito64-I-O-range.patch new file mode 100644 index 0000000000000000000000000000000000000000..306ea358f06148f4f2ff47aedb306fa0868ede68 --- /dev/null +++ b/hw-pci-host-bonito-Map-all-the-Bonito64-I-O-range.patch @@ -0,0 +1,55 @@ +From 25cca0a9b789244f89b24ed628b0dd6b0a169acc Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Sun, 10 May 2020 19:26:36 +0200 +Subject: [PATCH 657/709] hw/pci-host/bonito: Map all the Bonito64 I/O range +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +To ease following guest accesses to the Bonito64 chipset, +map its I/O range as UnimplementedDevice. +We can now see the accesses to unimplemented peripheral +using the '-d unimp' command line option. + +Reviewed-by: Aleksandar Markovic +Message-id: <20200510210128.18343-9-f4bug@amsat.org> +Signed-off-by: Philippe Mathieu-Daudé +--- + hw/pci-host/Kconfig | 1 + + hw/pci-host/bonito.c | 3 +++ + 2 files changed, 4 insertions(+) + +diff --git a/hw/pci-host/Kconfig b/hw/pci-host/Kconfig +index 8db41edc7e..036a61877a 100644 +--- a/hw/pci-host/Kconfig ++++ b/hw/pci-host/Kconfig +@@ -58,4 +58,5 @@ config PCI_EXPRESS_DESIGNWARE + + config PCI_BONITO + select PCI ++ select UNIMP + bool +diff --git a/hw/pci-host/bonito.c b/hw/pci-host/bonito.c +index b90e5a636d..f09bb1c6a8 100644 +--- a/hw/pci-host/bonito.c ++++ b/hw/pci-host/bonito.c +@@ -48,6 +48,7 @@ + #include "sysemu/reset.h" + #include "sysemu/runstate.h" + #include "exec/address-spaces.h" ++#include "hw/misc/unimp.h" + + /* #define DEBUG_BONITO */ + +@@ -644,6 +645,8 @@ static void bonito_realize(PCIDevice *dev, Error **errp) + sysbus_init_mmio(sysbus, &phb->data_mem); + sysbus_mmio_map(sysbus, 2, BONITO_SPCICONFIG_BASE); + ++ create_unimplemented_device("bonito", BONITO_REG_BASE, BONITO_REG_SIZE); ++ + memory_region_init_io(&s->iomem_ldma, OBJECT(s), &bonito_ldma_ops, s, + "ldma", 0x100); + sysbus_init_mmio(sysbus, &s->iomem_ldma); +-- +2.23.0 + diff --git a/hw-pci-host-bonito-Map-peripheral-using-physical-add.patch b/hw-pci-host-bonito-Map-peripheral-using-physical-add.patch new file mode 100644 index 0000000000000000000000000000000000000000..5bfe84ff340316f201e68cb20e23c7db39b86131 --- /dev/null +++ b/hw-pci-host-bonito-Map-peripheral-using-physical-add.patch @@ -0,0 +1,41 @@ +From 86313bdc85a3ebc4817ffb29edd1c108c50afbe6 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Sun, 10 May 2020 19:25:18 +0200 +Subject: [PATCH 656/709] hw/pci-host/bonito: Map peripheral using physical + address +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Peripherals are mapped at physical address on busses. +Only CPU/IOMMU can use virtual addresses. + +Reviewed-by: Aleksandar Markovic +Message-id: <20200510210128.18343-8-f4bug@amsat.org> +Signed-off-by: Philippe Mathieu-Daudé +--- + hw/pci-host/bonito.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/hw/pci-host/bonito.c b/hw/pci-host/bonito.c +index b874468ea6..b90e5a636d 100644 +--- a/hw/pci-host/bonito.c ++++ b/hw/pci-host/bonito.c +@@ -647,12 +647,12 @@ static void bonito_realize(PCIDevice *dev, Error **errp) + memory_region_init_io(&s->iomem_ldma, OBJECT(s), &bonito_ldma_ops, s, + "ldma", 0x100); + sysbus_init_mmio(sysbus, &s->iomem_ldma); +- sysbus_mmio_map(sysbus, 3, 0xbfe00200); ++ sysbus_mmio_map(sysbus, 3, 0x1fe00200); + + memory_region_init_io(&s->iomem_cop, OBJECT(s), &bonito_cop_ops, s, + "cop", 0x100); + sysbus_init_mmio(sysbus, &s->iomem_cop); +- sysbus_mmio_map(sysbus, 4, 0xbfe00300); ++ sysbus_mmio_map(sysbus, 4, 0x1fe00300); + + /* Map PCI IO Space 0x1fd0 0000 - 0x1fd1 0000 */ + memory_region_init_alias(&s->bonito_pciio, OBJECT(s), "isa_mmio", +-- +2.23.0 + diff --git a/hw-pci-host-bonito-Map-the-different-PCI-ranges-more.patch b/hw-pci-host-bonito-Map-the-different-PCI-ranges-more.patch new file mode 100644 index 0000000000000000000000000000000000000000..e0d520d3451ff5689f47c9511a52c1a4d3765210 --- /dev/null +++ b/hw-pci-host-bonito-Map-the-different-PCI-ranges-more.patch @@ -0,0 +1,105 @@ +From a0b544c1c95df240629964636479fc113086d57b Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Sun, 10 May 2020 21:42:11 +0200 +Subject: [PATCH 658/709] hw/pci-host/bonito: Map the different PCI ranges more + detailed +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Better describe the Bonito64 MEM HI/LO and I/O PCI ranges, +add more PCI regions as unimplemented. + +Reviewed-by: Aleksandar Markovic +Message-id: <20200526104726.11273-7-f4bug@amsat.org> +Signed-off-by: Philippe Mathieu-Daudé +--- + hw/pci-host/bonito.c | 32 ++++++++++++++++++++++++++++---- + 1 file changed, 28 insertions(+), 4 deletions(-) + +diff --git a/hw/pci-host/bonito.c b/hw/pci-host/bonito.c +index f09bb1c6a8..52015cc2a7 100644 +--- a/hw/pci-host/bonito.c ++++ b/hw/pci-host/bonito.c +@@ -39,6 +39,7 @@ + */ + + #include "qemu/osdep.h" ++#include "qemu/units.h" + #include "qemu/error-report.h" + #include "hw/pci/pci.h" + #include "hw/irq.h" +@@ -82,7 +83,7 @@ + #define BONITO_PCILO1_BASE 0x14000000 + #define BONITO_PCILO2_BASE 0x18000000 + #define BONITO_PCIHI_BASE 0x20000000 +-#define BONITO_PCIHI_SIZE 0x20000000 ++#define BONITO_PCIHI_SIZE 0x60000000 + #define BONITO_PCIHI_TOP (BONITO_PCIHI_BASE + BONITO_PCIHI_SIZE - 1) + #define BONITO_PCIIO_BASE 0x1fd00000 + #define BONITO_PCIIO_BASE_VA 0xbfd00000 +@@ -605,14 +606,26 @@ static void bonito_pcihost_realize(DeviceState *dev, Error **errp) + { + PCIHostState *phb = PCI_HOST_BRIDGE(dev); + BonitoState *bs = BONITO_PCI_HOST_BRIDGE(dev); ++ MemoryRegion *pcimem_lo_alias = g_new(MemoryRegion, 3); + +- memory_region_init(&bs->pci_mem, OBJECT(dev), "pci.mem", BONITO_PCILO_SIZE); ++ memory_region_init(&bs->pci_mem, OBJECT(dev), "pci.mem", BONITO_PCIHI_SIZE); + phb->bus = pci_register_root_bus(dev, "pci", + pci_bonito_set_irq, pci_bonito_map_irq, + dev, &bs->pci_mem, get_system_io(), + 0x28, 32, TYPE_PCI_BUS); +- memory_region_add_subregion(get_system_memory(), BONITO_PCILO_BASE, +- &bs->pci_mem); ++ ++ for (size_t i = 0; i < 3; i++) { ++ char *name = g_strdup_printf("pci.lomem%zu", i); ++ ++ memory_region_init_alias(&pcimem_lo_alias[i], NULL, name, ++ &bs->pci_mem, i * 64 * MiB, 64 * MiB); ++ memory_region_add_subregion(get_system_memory(), ++ BONITO_PCILO_BASE + i * 64 * MiB, ++ &pcimem_lo_alias[i]); ++ g_free(name); ++ } ++ ++ create_unimplemented_device("pci.io", BONITO_PCIIO_BASE, 1 * MiB); + } + + static void bonito_realize(PCIDevice *dev, Error **errp) +@@ -620,6 +633,8 @@ static void bonito_realize(PCIDevice *dev, Error **errp) + PCIBonitoState *s = PCI_BONITO(dev); + SysBusDevice *sysbus = SYS_BUS_DEVICE(s->pcihost); + PCIHostState *phb = PCI_HOST_BRIDGE(s->pcihost); ++ BonitoState *bs = BONITO_PCI_HOST_BRIDGE(s->pcihost); ++ MemoryRegion *pcimem_alias = g_new(MemoryRegion, 1); + + /* + * Bonito North Bridge, built on FPGA, +@@ -652,6 +667,7 @@ static void bonito_realize(PCIDevice *dev, Error **errp) + sysbus_init_mmio(sysbus, &s->iomem_ldma); + sysbus_mmio_map(sysbus, 3, 0x1fe00200); + ++ /* PCI copier */ + memory_region_init_io(&s->iomem_cop, OBJECT(s), &bonito_cop_ops, s, + "cop", 0x100); + sysbus_init_mmio(sysbus, &s->iomem_cop); +@@ -669,6 +685,14 @@ static void bonito_realize(PCIDevice *dev, Error **errp) + sysbus_init_mmio(sysbus, &s->bonito_localio); + sysbus_mmio_map(sysbus, 6, BONITO_DEV_BASE); + ++ memory_region_init_alias(pcimem_alias, NULL, "pci.mem.alias", ++ &bs->pci_mem, 0, BONITO_PCIHI_SIZE); ++ memory_region_add_subregion(get_system_memory(), ++ BONITO_PCIHI_BASE, pcimem_alias); ++ create_unimplemented_device("PCI_2", ++ (hwaddr)BONITO_PCIHI_BASE + BONITO_PCIHI_SIZE, ++ 2 * GiB); ++ + /* set the default value of north bridge pci config */ + pci_set_word(dev->config + PCI_COMMAND, 0x0000); + pci_set_word(dev->config + PCI_STATUS, 0x0000); +-- +2.23.0 + diff --git a/hw-pci-host-bonito-Set-the-Config-register-reset-val.patch b/hw-pci-host-bonito-Set-the-Config-register-reset-val.patch new file mode 100644 index 0000000000000000000000000000000000000000..c63848ad83a51a8e4138fdf4f12a49a05fc8d64d --- /dev/null +++ b/hw-pci-host-bonito-Set-the-Config-register-reset-val.patch @@ -0,0 +1,75 @@ +From 1f8a6c8b3c3a9c6ea0b215a764a1c4f1d6141078 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Sun, 10 May 2020 21:36:37 +0200 +Subject: [PATCH 660/709] hw/pci-host/bonito: Set the Config register reset + value with FIELD_DP32 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Describe some bits of the Config registers fields with the +registerfields API. Use the FIELD_DP32() macro to set the +BONGENCFG register bits at reset. + +Reviewed-by: Aleksandar Markovic +Message-id: <20200510210128.18343-12-f4bug@amsat.org> +Signed-off-by: Philippe Mathieu-Daudé +--- + hw/pci-host/bonito.c | 21 ++++++++++++++++++++- + 1 file changed, 20 insertions(+), 1 deletion(-) + +diff --git a/hw/pci-host/bonito.c b/hw/pci-host/bonito.c +index 20f2797a73..d0201ce59e 100644 +--- a/hw/pci-host/bonito.c ++++ b/hw/pci-host/bonito.c +@@ -50,6 +50,7 @@ + #include "sysemu/runstate.h" + #include "exec/address-spaces.h" + #include "hw/misc/unimp.h" ++#include "hw/registerfields.h" + + /* #define DEBUG_BONITO */ + +@@ -112,8 +113,19 @@ + /* Power on register */ + + #define BONITO_BONPONCFG (0x00 >> 2) /* 0x100 */ ++ ++/* PCI configuration register */ + #define BONITO_BONGENCFG_OFFSET 0x4 + #define BONITO_BONGENCFG (BONITO_BONGENCFG_OFFSET >> 2) /*0x104 */ ++REG32(BONGENCFG, 0x104) ++FIELD(BONGENCFG, DEBUGMODE, 0, 1) ++FIELD(BONGENCFG, SNOOP, 1, 1) ++FIELD(BONGENCFG, CPUSELFRESET, 2, 1) ++FIELD(BONGENCFG, BYTESWAP, 6, 1) ++FIELD(BONGENCFG, UNCACHED, 7, 1) ++FIELD(BONGENCFG, PREFETCH, 8, 1) ++FIELD(BONGENCFG, WRITEBEHIND, 9, 1) ++FIELD(BONGENCFG, PCIQUEUE, 12, 1) + + /* 2. IO & IDE configuration */ + #define BONITO_IODEVCFG (0x08 >> 2) /* 0x108 */ +@@ -577,11 +589,18 @@ static int pci_bonito_map_irq(PCIDevice *pci_dev, int irq_num) + static void bonito_reset(void *opaque) + { + PCIBonitoState *s = opaque; ++ uint32_t val = 0; + + /* set the default value of north bridge registers */ + + s->regs[BONITO_BONPONCFG] = 0xc40; +- s->regs[BONITO_BONGENCFG] = 0x1384; ++ val = FIELD_DP32(val, BONGENCFG, PCIQUEUE, 1); ++ val = FIELD_DP32(val, BONGENCFG, WRITEBEHIND, 1); ++ val = FIELD_DP32(val, BONGENCFG, PREFETCH, 1); ++ val = FIELD_DP32(val, BONGENCFG, UNCACHED, 1); ++ val = FIELD_DP32(val, BONGENCFG, CPUSELFRESET, 1); ++ s->regs[BONITO_BONGENCFG] = val; ++ + s->regs[BONITO_IODEVCFG] = 0x2bff8010; + s->regs[BONITO_SDCFG] = 0x255e0091; + +-- +2.23.0 + diff --git a/hw-pci-pcie-Forbid-hot-plug-if-it-s-disabled-on-the-.patch b/hw-pci-pcie-Forbid-hot-plug-if-it-s-disabled-on-the-.patch new file mode 100644 index 0000000000000000000000000000000000000000..859989852a7697a431ab6db2cbcc46708573316b --- /dev/null +++ b/hw-pci-pcie-Forbid-hot-plug-if-it-s-disabled-on-the-.patch @@ -0,0 +1,67 @@ +From 0501e1aa1d32a6e02dd06a79bba97fbe9d557cb5 Mon Sep 17 00:00:00 2001 +From: Julia Suvorova +Date: Mon, 27 Apr 2020 20:24:39 +0200 +Subject: [PATCH 204/709] hw/pci/pcie: Forbid hot-plug if it's disabled on the + slot + +Raise an error when trying to hot-plug/unplug a device through QMP to a device +with disabled hot-plug capability. This makes the device behaviour more +consistent and provides an explanation of the failure in the case of +asynchronous unplug. + +Signed-off-by: Julia Suvorova +Message-Id: <20200427182440.92433-2-jusual@redhat.com> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +Reviewed-by: Marcel Apfelbaum +--- + hw/pci/pcie.c | 19 +++++++++++++++++++ + 1 file changed, 19 insertions(+) + +diff --git a/hw/pci/pcie.c b/hw/pci/pcie.c +index 0eb3a2a5d2..6b48d04d2c 100644 +--- a/hw/pci/pcie.c ++++ b/hw/pci/pcie.c +@@ -415,6 +415,7 @@ void pcie_cap_slot_plug_cb(HotplugHandler *hotplug_dev, DeviceState *dev, + { + PCIDevice *hotplug_pdev = PCI_DEVICE(hotplug_dev); + uint8_t *exp_cap = hotplug_pdev->config + hotplug_pdev->exp.exp_cap; ++ uint32_t sltcap = pci_get_word(exp_cap + PCI_EXP_SLTCAP); + PCIDevice *pci_dev = PCI_DEVICE(dev); + + /* Don't send event when device is enabled during qemu machine creation: +@@ -430,6 +431,13 @@ void pcie_cap_slot_plug_cb(HotplugHandler *hotplug_dev, DeviceState *dev, + return; + } + ++ /* Check if hot-plug is disabled on the slot */ ++ if ((sltcap & PCI_EXP_SLTCAP_HPC) == 0) { ++ error_setg(errp, "Hot-plug failed: unsupported by the port device '%s'", ++ DEVICE(hotplug_pdev)->id); ++ return; ++ } ++ + /* To enable multifunction hot-plug, we just ensure the function + * 0 added last. When function 0 is added, we set the sltsta and + * inform OS via event notification. +@@ -470,6 +478,17 @@ void pcie_cap_slot_unplug_request_cb(HotplugHandler *hotplug_dev, + Error *local_err = NULL; + PCIDevice *pci_dev = PCI_DEVICE(dev); + PCIBus *bus = pci_get_bus(pci_dev); ++ PCIDevice *hotplug_pdev = PCI_DEVICE(hotplug_dev); ++ uint8_t *exp_cap = hotplug_pdev->config + hotplug_pdev->exp.exp_cap; ++ uint32_t sltcap = pci_get_word(exp_cap + PCI_EXP_SLTCAP); ++ ++ /* Check if hot-unplug is disabled on the slot */ ++ if ((sltcap & PCI_EXP_SLTCAP_HPC) == 0) { ++ error_setg(errp, "Hot-unplug failed: " ++ "unsupported by the port device '%s'", ++ DEVICE(hotplug_pdev)->id); ++ return; ++ } + + pcie_cap_slot_plug_common(PCI_DEVICE(hotplug_dev), dev, &local_err); + if (local_err) { +-- +2.23.0 + diff --git a/hw-pci-pcie-Replace-PCI_DEVICE-casts-with-existing-v.patch b/hw-pci-pcie-Replace-PCI_DEVICE-casts-with-existing-v.patch new file mode 100644 index 0000000000000000000000000000000000000000..123b38b8a473516b9b32042a6ddc15626ef4e10a --- /dev/null +++ b/hw-pci-pcie-Replace-PCI_DEVICE-casts-with-existing-v.patch @@ -0,0 +1,51 @@ +From 6a1e073378353eb6ac0565e0dc649b3db76ed5dc Mon Sep 17 00:00:00 2001 +From: Julia Suvorova +Date: Mon, 27 Apr 2020 20:24:40 +0200 +Subject: [PATCH 205/709] hw/pci/pcie: Replace PCI_DEVICE() casts with existing + variable + +A little cleanup is possible because of hotplug_pdev introduction. + +Signed-off-by: Julia Suvorova +Message-Id: <20200427182440.92433-3-jusual@redhat.com> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +Reviewed-by: Marcel Apfelbaum +--- + hw/pci/pcie.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/hw/pci/pcie.c b/hw/pci/pcie.c +index 6b48d04d2c..abc99b6eff 100644 +--- a/hw/pci/pcie.c ++++ b/hw/pci/pcie.c +@@ -449,7 +449,7 @@ void pcie_cap_slot_plug_cb(HotplugHandler *hotplug_dev, DeviceState *dev, + pci_word_test_and_set_mask(exp_cap + PCI_EXP_LNKSTA, + PCI_EXP_LNKSTA_DLLLA); + } +- pcie_cap_slot_event(PCI_DEVICE(hotplug_dev), ++ pcie_cap_slot_event(hotplug_pdev, + PCI_EXP_HP_EV_PDC | PCI_EXP_HP_EV_ABP); + } + } +@@ -490,7 +490,7 @@ void pcie_cap_slot_unplug_request_cb(HotplugHandler *hotplug_dev, + return; + } + +- pcie_cap_slot_plug_common(PCI_DEVICE(hotplug_dev), dev, &local_err); ++ pcie_cap_slot_plug_common(hotplug_pdev, dev, &local_err); + if (local_err) { + error_propagate(errp, local_err); + return; +@@ -509,7 +509,7 @@ void pcie_cap_slot_unplug_request_cb(HotplugHandler *hotplug_dev, + return; + } + +- pcie_cap_slot_push_attention_button(PCI_DEVICE(hotplug_dev)); ++ pcie_cap_slot_push_attention_button(hotplug_pdev); + } + + /* pci express slot for pci express root/downstream port +-- +2.23.0 + diff --git a/hw-rdma-Destroy-list-mutex-when-list-is-destroyed.patch b/hw-rdma-Destroy-list-mutex-when-list-is-destroyed.patch new file mode 100644 index 0000000000000000000000000000000000000000..aaed578b0d9d4414831b7ed6bcd1c0b735dfd0d1 --- /dev/null +++ b/hw-rdma-Destroy-list-mutex-when-list-is-destroyed.patch @@ -0,0 +1,31 @@ +From a5cde048e865da81fdc9077f3af28a43bff78d35 Mon Sep 17 00:00:00 2001 +From: Yuval Shaia +Date: Mon, 13 Apr 2020 11:57:38 +0300 +Subject: [PATCH 145/709] hw/rdma: Destroy list mutex when list is destroyed + +List mutex should be destroyed when gs list gets destroyed. + +Reported-by: Peter Maydell +Signed-off-by: Yuval Shaia +Message-Id: <20200413085738.11145-1-yuval.shaia.ml@gmail.com> +Reviewed-by: Marcel Apfelbaum +Signed-off-by: Marcel Apfelbaum +--- + hw/rdma/rdma_utils.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/hw/rdma/rdma_utils.c b/hw/rdma/rdma_utils.c +index 73f279104c..698ed4716c 100644 +--- a/hw/rdma/rdma_utils.c ++++ b/hw/rdma/rdma_utils.c +@@ -100,6 +100,7 @@ void rdma_protected_gslist_destroy(RdmaProtectedGSList *list) + { + if (list->list) { + g_slist_free(list->list); ++ qemu_mutex_destroy(&list->lock); + list->list = NULL; + } + } +-- +2.23.0 + diff --git a/hw-riscv-Add-helpers-for-RISC-V-multi-socket-NUMA-ma.patch b/hw-riscv-Add-helpers-for-RISC-V-multi-socket-NUMA-ma.patch new file mode 100644 index 0000000000000000000000000000000000000000..063682c933087c70970304ec93e43a16f6888ba1 --- /dev/null +++ b/hw-riscv-Add-helpers-for-RISC-V-multi-socket-NUMA-ma.patch @@ -0,0 +1,342 @@ +From 0ebc9f8393f4314ddecf1a19db164f857aba850c Mon Sep 17 00:00:00 2001 +From: Anup Patel +Date: Fri, 29 May 2020 13:26:22 +0530 +Subject: [PATCH 692/709] hw/riscv: Add helpers for RISC-V multi-socket NUMA + machines + +We add common helper routines which can be shared by RISC-V +multi-socket NUMA machines. + +We have two types of helpers: +1. riscv_socket_xyz() - These helper assist managing multiple + sockets irrespective whether QEMU NUMA is enabled/disabled +2. riscv_numa_xyz() - These helpers assist in providing + necessary QEMU machine callbacks for QEMU NUMA emulation + +Signed-off-by: Anup Patel +--- + hw/riscv/Makefile.objs | 1 + + hw/riscv/numa.c | 242 ++++++++++++++++++++++++++++++++++++++++ + include/hw/riscv/numa.h | 51 +++++++++ + 3 files changed, 294 insertions(+) + create mode 100644 hw/riscv/numa.c + create mode 100644 include/hw/riscv/numa.h + +diff --git a/hw/riscv/Makefile.objs b/hw/riscv/Makefile.objs +index fc3c6dd7c8..4483e61879 100644 +--- a/hw/riscv/Makefile.objs ++++ b/hw/riscv/Makefile.objs +@@ -1,4 +1,5 @@ + obj-y += boot.o ++obj-y += numa.o + obj-$(CONFIG_SPIKE) += riscv_htif.o + obj-$(CONFIG_HART) += riscv_hart.o + obj-$(CONFIG_SIFIVE_E) += sifive_e.o +diff --git a/hw/riscv/numa.c b/hw/riscv/numa.c +new file mode 100644 +index 0000000000..4f92307102 +--- /dev/null ++++ b/hw/riscv/numa.c +@@ -0,0 +1,242 @@ ++/* ++ * QEMU RISC-V NUMA Helper ++ * ++ * Copyright (c) 2020 Western Digital Corporation or its affiliates. ++ * ++ * 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/units.h" ++#include "qemu/log.h" ++#include "qemu/error-report.h" ++#include "qapi/error.h" ++#include "hw/boards.h" ++#include "hw/qdev-properties.h" ++#include "hw/riscv/numa.h" ++#include "sysemu/device_tree.h" ++ ++static bool numa_enabled(const MachineState *ms) ++{ ++ return (ms->numa_state && ms->numa_state->num_nodes) ? true : false; ++} ++ ++int riscv_socket_count(const MachineState *ms) ++{ ++ return (numa_enabled(ms)) ? ms->numa_state->num_nodes : 1; ++} ++ ++int riscv_socket_first_hartid(const MachineState *ms, int socket_id) ++{ ++ int i, first_hartid = ms->smp.cpus; ++ ++ if (!numa_enabled(ms)) { ++ return (!socket_id) ? 0 : -1; ++ } ++ ++ for (i = 0; i < ms->smp.cpus; i++) { ++ if (ms->possible_cpus->cpus[i].props.node_id != socket_id) { ++ continue; ++ } ++ if (i < first_hartid) { ++ first_hartid = i; ++ } ++ } ++ ++ return (first_hartid < ms->smp.cpus) ? first_hartid : -1; ++} ++ ++int riscv_socket_last_hartid(const MachineState *ms, int socket_id) ++{ ++ int i, last_hartid = -1; ++ ++ if (!numa_enabled(ms)) { ++ return (!socket_id) ? ms->smp.cpus - 1 : -1; ++ } ++ ++ for (i = 0; i < ms->smp.cpus; i++) { ++ if (ms->possible_cpus->cpus[i].props.node_id != socket_id) { ++ continue; ++ } ++ if (i > last_hartid) { ++ last_hartid = i; ++ } ++ } ++ ++ return (last_hartid < ms->smp.cpus) ? last_hartid : -1; ++} ++ ++int riscv_socket_hart_count(const MachineState *ms, int socket_id) ++{ ++ int first_hartid, last_hartid; ++ ++ if (!numa_enabled(ms)) { ++ return (!socket_id) ? ms->smp.cpus : -1; ++ } ++ ++ first_hartid = riscv_socket_first_hartid(ms, socket_id); ++ if (first_hartid < 0) { ++ return -1; ++ } ++ ++ last_hartid = riscv_socket_last_hartid(ms, socket_id); ++ if (last_hartid < 0) { ++ return -1; ++ } ++ ++ if (first_hartid > last_hartid) { ++ return -1; ++ } ++ ++ return last_hartid - first_hartid + 1; ++} ++ ++bool riscv_socket_check_hartids(const MachineState *ms, int socket_id) ++{ ++ int i, first_hartid, last_hartid; ++ ++ if (!numa_enabled(ms)) { ++ return (!socket_id) ? true : false; ++ } ++ ++ first_hartid = riscv_socket_first_hartid(ms, socket_id); ++ if (first_hartid < 0) { ++ return false; ++ } ++ ++ last_hartid = riscv_socket_last_hartid(ms, socket_id); ++ if (last_hartid < 0) { ++ return false; ++ } ++ ++ for (i = first_hartid; i <= last_hartid; i++) { ++ if (ms->possible_cpus->cpus[i].props.node_id != socket_id) { ++ return false; ++ } ++ } ++ ++ return true; ++} ++ ++uint64_t riscv_socket_mem_offset(const MachineState *ms, int socket_id) ++{ ++ int i; ++ uint64_t mem_offset = 0; ++ ++ if (!numa_enabled(ms)) { ++ return 0; ++ } ++ ++ for (i = 0; i < ms->numa_state->num_nodes; i++) { ++ if (i == socket_id) { ++ break; ++ } ++ mem_offset += ms->numa_state->nodes[i].node_mem; ++ } ++ ++ return (i == socket_id) ? mem_offset : 0; ++} ++ ++uint64_t riscv_socket_mem_size(const MachineState *ms, int socket_id) ++{ ++ if (!numa_enabled(ms)) { ++ return (!socket_id) ? ms->ram_size : 0; ++ } ++ ++ return (socket_id < ms->numa_state->num_nodes) ? ++ ms->numa_state->nodes[socket_id].node_mem : 0; ++} ++ ++void riscv_socket_fdt_write_id(const MachineState *ms, void *fdt, ++ const char *node_name, int socket_id) ++{ ++ if (numa_enabled(ms)) { ++ qemu_fdt_setprop_cell(fdt, node_name, "numa-node-id", socket_id); ++ } ++} ++ ++void riscv_socket_fdt_write_distance_matrix(const MachineState *ms, void *fdt) ++{ ++ int i, j, idx; ++ uint32_t *dist_matrix, dist_matrix_size; ++ ++ if (numa_enabled(ms) && ms->numa_state->have_numa_distance) { ++ dist_matrix_size = riscv_socket_count(ms) * riscv_socket_count(ms); ++ dist_matrix_size *= (3 * sizeof(uint32_t)); ++ dist_matrix = g_malloc0(dist_matrix_size); ++ ++ for (i = 0; i < riscv_socket_count(ms); i++) { ++ for (j = 0; j < riscv_socket_count(ms); j++) { ++ idx = (i * riscv_socket_count(ms) + j) * 3; ++ dist_matrix[idx + 0] = cpu_to_be32(i); ++ dist_matrix[idx + 1] = cpu_to_be32(j); ++ dist_matrix[idx + 2] = ++ cpu_to_be32(ms->numa_state->nodes[i].distance[j]); ++ } ++ } ++ ++ qemu_fdt_add_subnode(fdt, "/distance-map"); ++ qemu_fdt_setprop_string(fdt, "/distance-map", "compatible", ++ "numa-distance-map-v1"); ++ qemu_fdt_setprop(fdt, "/distance-map", "distance-matrix", ++ dist_matrix, dist_matrix_size); ++ g_free(dist_matrix); ++ } ++} ++ ++CpuInstanceProperties ++riscv_numa_cpu_index_to_props(MachineState *ms, unsigned cpu_index) ++{ ++ MachineClass *mc = MACHINE_GET_CLASS(ms); ++ const CPUArchIdList *possible_cpus = mc->possible_cpu_arch_ids(ms); ++ ++ assert(cpu_index < possible_cpus->len); ++ return possible_cpus->cpus[cpu_index].props; ++} ++ ++int64_t riscv_numa_get_default_cpu_node_id(const MachineState *ms, int idx) ++{ ++ int64_t nidx = 0; ++ ++ if (ms->numa_state->num_nodes) { ++ nidx = idx / (ms->smp.cpus / ms->numa_state->num_nodes); ++ if (ms->numa_state->num_nodes <= nidx) { ++ nidx = ms->numa_state->num_nodes - 1; ++ } ++ } ++ ++ return nidx; ++} ++ ++const CPUArchIdList *riscv_numa_possible_cpu_arch_ids(MachineState *ms) ++{ ++ int n; ++ unsigned int max_cpus = ms->smp.max_cpus; ++ ++ if (ms->possible_cpus) { ++ assert(ms->possible_cpus->len == max_cpus); ++ return ms->possible_cpus; ++ } ++ ++ ms->possible_cpus = g_malloc0(sizeof(CPUArchIdList) + ++ sizeof(CPUArchId) * max_cpus); ++ ms->possible_cpus->len = max_cpus; ++ for (n = 0; n < ms->possible_cpus->len; n++) { ++ ms->possible_cpus->cpus[n].type = ms->cpu_type; ++ ms->possible_cpus->cpus[n].arch_id = n; ++ ms->possible_cpus->cpus[n].props.has_core_id = true; ++ ms->possible_cpus->cpus[n].props.core_id = n; ++ } ++ ++ return ms->possible_cpus; ++} +diff --git a/include/hw/riscv/numa.h b/include/hw/riscv/numa.h +new file mode 100644 +index 0000000000..fd9517a315 +--- /dev/null ++++ b/include/hw/riscv/numa.h +@@ -0,0 +1,51 @@ ++/* ++ * QEMU RISC-V NUMA Helper ++ * ++ * Copyright (c) 2020 Western Digital Corporation or its affiliates. ++ * ++ * 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_NUMA_H ++#define RISCV_NUMA_H ++ ++#include "hw/sysbus.h" ++#include "sysemu/numa.h" ++ ++int riscv_socket_count(const MachineState *ms); ++ ++int riscv_socket_first_hartid(const MachineState *ms, int socket_id); ++ ++int riscv_socket_last_hartid(const MachineState *ms, int socket_id); ++ ++int riscv_socket_hart_count(const MachineState *ms, int socket_id); ++ ++uint64_t riscv_socket_mem_offset(const MachineState *ms, int socket_id); ++ ++uint64_t riscv_socket_mem_size(const MachineState *ms, int socket_id); ++ ++bool riscv_socket_check_hartids(const MachineState *ms, int socket_id); ++ ++void riscv_socket_fdt_write_id(const MachineState *ms, void *fdt, ++ const char *node_name, int socket_id); ++ ++void riscv_socket_fdt_write_distance_matrix(const MachineState *ms, void *fdt); ++ ++CpuInstanceProperties ++riscv_numa_cpu_index_to_props(MachineState *ms, unsigned cpu_index); ++ ++int64_t riscv_numa_get_default_cpu_node_id(const MachineState *ms, int idx); ++ ++const CPUArchIdList *riscv_numa_possible_cpu_arch_ids(MachineState *ms); ++ ++#endif /* RISCV_NUMA_H */ +-- +2.23.0 + diff --git a/hw-riscv-Add-optional-symbol-callback-ptr-to-riscv_l.patch b/hw-riscv-Add-optional-symbol-callback-ptr-to-riscv_l.patch new file mode 100644 index 0000000000000000000000000000000000000000..7a125dd173744c7e6e94cd22aa03f66cebb7a119 --- /dev/null +++ b/hw-riscv-Add-optional-symbol-callback-ptr-to-riscv_l.patch @@ -0,0 +1,116 @@ +From 02777ac3036187077c98a05843d888b4be8c51b3 Mon Sep 17 00:00:00 2001 +From: Anup Patel +Date: Mon, 27 Apr 2020 13:36:42 +0530 +Subject: [PATCH 065/709] hw/riscv: Add optional symbol callback ptr to + riscv_load_firmware() + +This patch adds an optional function pointer, "sym_cb", to +riscv_load_firmware() which provides the possibility to access +the symbol table during kernel loading. + +The pointer is ignored, if supplied with flat (non-elf) firmware image. + +The Spike board requires it locate the HTIF symbols from firmware ELF +passed via "-bios" option. + +Signed-off-by: Anup Patel +Reviewed-by: Alistair Francis +Message-id: 20200427080644.168461-2-anup.patel@wdc.com +Message-Id: <20200427080644.168461-2-anup.patel@wdc.com> +Signed-off-by: Alistair Francis +--- + hw/riscv/boot.c | 13 ++++++++----- + hw/riscv/sifive_u.c | 2 +- + hw/riscv/virt.c | 2 +- + include/hw/riscv/boot.h | 6 ++++-- + 4 files changed, 14 insertions(+), 9 deletions(-) + +diff --git a/hw/riscv/boot.c b/hw/riscv/boot.c +index b8e765277d..726300a171 100644 +--- a/hw/riscv/boot.c ++++ b/hw/riscv/boot.c +@@ -36,7 +36,8 @@ + + void riscv_find_and_load_firmware(MachineState *machine, + const char *default_machine_firmware, +- hwaddr firmware_load_addr) ++ hwaddr firmware_load_addr, ++ symbol_fn_t sym_cb) + { + char *firmware_filename = NULL; + +@@ -76,7 +77,7 @@ void riscv_find_and_load_firmware(MachineState *machine, + + if (firmware_filename) { + /* If not "none" load the firmware */ +- riscv_load_firmware(firmware_filename, firmware_load_addr); ++ riscv_load_firmware(firmware_filename, firmware_load_addr, sym_cb); + g_free(firmware_filename); + } + } +@@ -96,12 +97,14 @@ char *riscv_find_firmware(const char *firmware_filename) + } + + target_ulong riscv_load_firmware(const char *firmware_filename, +- hwaddr firmware_load_addr) ++ hwaddr firmware_load_addr, ++ symbol_fn_t sym_cb) + { + uint64_t firmware_entry, firmware_start, firmware_end; + +- if (load_elf(firmware_filename, NULL, NULL, NULL, &firmware_entry, +- &firmware_start, &firmware_end, NULL, 0, EM_RISCV, 1, 0) > 0) { ++ if (load_elf_ram_sym(firmware_filename, NULL, NULL, NULL, ++ &firmware_entry, &firmware_start, &firmware_end, NULL, ++ 0, EM_RISCV, 1, 0, NULL, true, sym_cb) > 0) { + return firmware_entry; + } + +diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c +index e32355a691..bed10fcfa8 100644 +--- a/hw/riscv/sifive_u.c ++++ b/hw/riscv/sifive_u.c +@@ -352,7 +352,7 @@ static void sifive_u_machine_init(MachineState *machine) + create_fdt(s, memmap, machine->ram_size, machine->kernel_cmdline); + + riscv_find_and_load_firmware(machine, BIOS_FILENAME, +- memmap[SIFIVE_U_DRAM].base); ++ memmap[SIFIVE_U_DRAM].base, NULL); + + if (machine->kernel_filename) { + uint64_t kernel_entry = riscv_load_kernel(machine->kernel_filename, +diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c +index c621a970aa..daae3ebdbb 100644 +--- a/hw/riscv/virt.c ++++ b/hw/riscv/virt.c +@@ -511,7 +511,7 @@ static void riscv_virt_board_init(MachineState *machine) + mask_rom); + + riscv_find_and_load_firmware(machine, BIOS_FILENAME, +- memmap[VIRT_DRAM].base); ++ memmap[VIRT_DRAM].base, NULL); + + if (machine->kernel_filename) { + uint64_t kernel_entry = riscv_load_kernel(machine->kernel_filename, +diff --git a/include/hw/riscv/boot.h b/include/hw/riscv/boot.h +index df80051fbc..474a940ad5 100644 +--- a/include/hw/riscv/boot.h ++++ b/include/hw/riscv/boot.h +@@ -24,10 +24,12 @@ + + void riscv_find_and_load_firmware(MachineState *machine, + const char *default_machine_firmware, +- hwaddr firmware_load_addr); ++ hwaddr firmware_load_addr, ++ symbol_fn_t sym_cb); + char *riscv_find_firmware(const char *firmware_filename); + target_ulong riscv_load_firmware(const char *firmware_filename, +- hwaddr firmware_load_addr); ++ hwaddr firmware_load_addr, ++ symbol_fn_t sym_cb); + target_ulong riscv_load_kernel(const char *kernel_filename, + symbol_fn_t sym_cb); + hwaddr riscv_load_initrd(const char *filename, uint64_t mem_size, +-- +2.23.0 + diff --git a/hw-riscv-Allow-creating-multiple-instances-of-CLINT.patch b/hw-riscv-Allow-creating-multiple-instances-of-CLINT.patch new file mode 100644 index 0000000000000000000000000000000000000000..a7a38446eb0a1a6051c51d84a37b03e9c2896a92 --- /dev/null +++ b/hw-riscv-Allow-creating-multiple-instances-of-CLINT.patch @@ -0,0 +1,177 @@ +From bdbb77ba1757927c0791d8ad8ef18923c6f6abc6 Mon Sep 17 00:00:00 2001 +From: Anup Patel +Date: Thu, 14 May 2020 15:51:31 +0530 +Subject: [PATCH 690/709] hw/riscv: Allow creating multiple instances of CLINT + +We extend CLINT emulation to allow multiple instances of CLINT in +a QEMU RISC-V machine. To achieve this, we remove first HART id +zero assumption from CLINT emulation. + +Signed-off-by: Anup Patel +Reviewed-by: Alistair Francis +Reviewed-by: Palmer Dabbelt +--- + hw/riscv/sifive_clint.c | 20 ++++++++++++-------- + hw/riscv/sifive_e.c | 2 +- + hw/riscv/sifive_u.c | 2 +- + hw/riscv/spike.c | 2 +- + hw/riscv/virt.c | 2 +- + include/hw/riscv/sifive_clint.h | 7 ++++--- + 6 files changed, 20 insertions(+), 15 deletions(-) + +diff --git a/hw/riscv/sifive_clint.c b/hw/riscv/sifive_clint.c +index e933d35092..7d713fd743 100644 +--- a/hw/riscv/sifive_clint.c ++++ b/hw/riscv/sifive_clint.c +@@ -78,7 +78,7 @@ static uint64_t sifive_clint_read(void *opaque, hwaddr addr, unsigned size) + SiFiveCLINTState *clint = opaque; + if (addr >= clint->sip_base && + addr < clint->sip_base + (clint->num_harts << 2)) { +- size_t hartid = (addr - clint->sip_base) >> 2; ++ size_t hartid = clint->hartid_base + ((addr - clint->sip_base) >> 2); + CPUState *cpu = qemu_get_cpu(hartid); + CPURISCVState *env = cpu ? cpu->env_ptr : NULL; + if (!env) { +@@ -91,7 +91,8 @@ static uint64_t sifive_clint_read(void *opaque, hwaddr addr, unsigned size) + } + } else if (addr >= clint->timecmp_base && + addr < clint->timecmp_base + (clint->num_harts << 3)) { +- size_t hartid = (addr - clint->timecmp_base) >> 3; ++ size_t hartid = clint->hartid_base + ++ ((addr - clint->timecmp_base) >> 3); + CPUState *cpu = qemu_get_cpu(hartid); + CPURISCVState *env = cpu ? cpu->env_ptr : NULL; + if (!env) { +@@ -128,7 +129,7 @@ static void sifive_clint_write(void *opaque, hwaddr addr, uint64_t value, + + if (addr >= clint->sip_base && + addr < clint->sip_base + (clint->num_harts << 2)) { +- size_t hartid = (addr - clint->sip_base) >> 2; ++ size_t hartid = clint->hartid_base + ((addr - clint->sip_base) >> 2); + CPUState *cpu = qemu_get_cpu(hartid); + CPURISCVState *env = cpu ? cpu->env_ptr : NULL; + if (!env) { +@@ -141,7 +142,8 @@ static void sifive_clint_write(void *opaque, hwaddr addr, uint64_t value, + return; + } else if (addr >= clint->timecmp_base && + addr < clint->timecmp_base + (clint->num_harts << 3)) { +- size_t hartid = (addr - clint->timecmp_base) >> 3; ++ size_t hartid = clint->hartid_base + ++ ((addr - clint->timecmp_base) >> 3); + CPUState *cpu = qemu_get_cpu(hartid); + CPURISCVState *env = cpu ? cpu->env_ptr : NULL; + if (!env) { +@@ -185,6 +187,7 @@ static const MemoryRegionOps sifive_clint_ops = { + }; + + static Property sifive_clint_properties[] = { ++ DEFINE_PROP_UINT32("hartid-base", SiFiveCLINTState, hartid_base, 0), + DEFINE_PROP_UINT32("num-harts", SiFiveCLINTState, num_harts, 0), + DEFINE_PROP_UINT32("sip-base", SiFiveCLINTState, sip_base, 0), + DEFINE_PROP_UINT32("timecmp-base", SiFiveCLINTState, timecmp_base, 0), +@@ -226,13 +229,13 @@ type_init(sifive_clint_register_types) + /* + * Create CLINT device. + */ +-DeviceState *sifive_clint_create(hwaddr addr, hwaddr size, uint32_t num_harts, +- uint32_t sip_base, uint32_t timecmp_base, uint32_t time_base, +- bool provide_rdtime) ++DeviceState *sifive_clint_create(hwaddr addr, hwaddr size, ++ uint32_t hartid_base, uint32_t num_harts, uint32_t sip_base, ++ uint32_t timecmp_base, uint32_t time_base, bool provide_rdtime) + { + int i; + for (i = 0; i < num_harts; i++) { +- CPUState *cpu = qemu_get_cpu(i); ++ CPUState *cpu = qemu_get_cpu(hartid_base + i); + CPURISCVState *env = cpu ? cpu->env_ptr : NULL; + if (!env) { + continue; +@@ -246,6 +249,7 @@ DeviceState *sifive_clint_create(hwaddr addr, hwaddr size, uint32_t num_harts, + } + + DeviceState *dev = qdev_create(NULL, TYPE_SIFIVE_CLINT); ++ qdev_prop_set_uint32(dev, "hartid-base", hartid_base); + qdev_prop_set_uint32(dev, "num-harts", num_harts); + qdev_prop_set_uint32(dev, "sip-base", sip_base); + qdev_prop_set_uint32(dev, "timecmp-base", timecmp_base); +diff --git a/hw/riscv/sifive_e.c b/hw/riscv/sifive_e.c +index b53109521e..1c3b37d0ba 100644 +--- a/hw/riscv/sifive_e.c ++++ b/hw/riscv/sifive_e.c +@@ -163,7 +163,7 @@ static void riscv_sifive_e_soc_realize(DeviceState *dev, Error **errp) + SIFIVE_E_PLIC_CONTEXT_STRIDE, + memmap[SIFIVE_E_PLIC].size); + sifive_clint_create(memmap[SIFIVE_E_CLINT].base, +- memmap[SIFIVE_E_CLINT].size, ms->smp.cpus, ++ memmap[SIFIVE_E_CLINT].size, 0, ms->smp.cpus, + SIFIVE_SIP_BASE, SIFIVE_TIMECMP_BASE, SIFIVE_TIME_BASE, false); + create_unimplemented_device("riscv.sifive.e.aon", + memmap[SIFIVE_E_AON].base, memmap[SIFIVE_E_AON].size); +diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c +index 4299bdf480..c193761916 100644 +--- a/hw/riscv/sifive_u.c ++++ b/hw/riscv/sifive_u.c +@@ -602,7 +602,7 @@ static void riscv_sifive_u_soc_realize(DeviceState *dev, Error **errp) + sifive_uart_create(system_memory, memmap[SIFIVE_U_UART1].base, + serial_hd(1), qdev_get_gpio_in(DEVICE(s->plic), SIFIVE_U_UART1_IRQ)); + sifive_clint_create(memmap[SIFIVE_U_CLINT].base, +- memmap[SIFIVE_U_CLINT].size, ms->smp.cpus, ++ memmap[SIFIVE_U_CLINT].size, 0, ms->smp.cpus, + SIFIVE_SIP_BASE, SIFIVE_TIMECMP_BASE, SIFIVE_TIME_BASE, false); + + object_property_set_bool(OBJECT(&s->prci), true, "realized", &err); +diff --git a/hw/riscv/spike.c b/hw/riscv/spike.c +index 7bbbdb5036..a3db885ffa 100644 +--- a/hw/riscv/spike.c ++++ b/hw/riscv/spike.c +@@ -253,7 +253,7 @@ static void spike_board_init(MachineState *machine) + + /* Core Local Interruptor (timer and IPI) */ + sifive_clint_create(memmap[SPIKE_CLINT].base, memmap[SPIKE_CLINT].size, +- smp_cpus, SIFIVE_SIP_BASE, SIFIVE_TIMECMP_BASE, SIFIVE_TIME_BASE, ++ 0, smp_cpus, SIFIVE_SIP_BASE, SIFIVE_TIMECMP_BASE, SIFIVE_TIME_BASE, + false); + } + +diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c +index 7ce28895bc..041c400261 100644 +--- a/hw/riscv/virt.c ++++ b/hw/riscv/virt.c +@@ -595,7 +595,7 @@ static void riscv_virt_board_init(MachineState *machine) + VIRT_PLIC_CONTEXT_STRIDE, + memmap[VIRT_PLIC].size); + sifive_clint_create(memmap[VIRT_CLINT].base, +- memmap[VIRT_CLINT].size, smp_cpus, ++ memmap[VIRT_CLINT].size, 0, smp_cpus, + SIFIVE_SIP_BASE, SIFIVE_TIMECMP_BASE, SIFIVE_TIME_BASE, true); + sifive_test_create(memmap[VIRT_TEST].base); + +diff --git a/include/hw/riscv/sifive_clint.h b/include/hw/riscv/sifive_clint.h +index 4a720bfece..9f5fb3d31d 100644 +--- a/include/hw/riscv/sifive_clint.h ++++ b/include/hw/riscv/sifive_clint.h +@@ -33,6 +33,7 @@ typedef struct SiFiveCLINTState { + + /*< public >*/ + MemoryRegion mmio; ++ uint32_t hartid_base; + uint32_t num_harts; + uint32_t sip_base; + uint32_t timecmp_base; +@@ -40,9 +41,9 @@ typedef struct SiFiveCLINTState { + uint32_t aperture_size; + } SiFiveCLINTState; + +-DeviceState *sifive_clint_create(hwaddr addr, hwaddr size, uint32_t num_harts, +- uint32_t sip_base, uint32_t timecmp_base, uint32_t time_base, +- bool provide_rdtime); ++DeviceState *sifive_clint_create(hwaddr addr, hwaddr size, ++ uint32_t hartid_base, uint32_t num_harts, uint32_t sip_base, ++ uint32_t timecmp_base, uint32_t time_base, bool provide_rdtime); + + enum { + SIFIVE_SIP_BASE = 0x0, +-- +2.23.0 + diff --git a/hw-riscv-Allow-creating-multiple-instances-of-PLIC.patch b/hw-riscv-Allow-creating-multiple-instances-of-PLIC.patch new file mode 100644 index 0000000000000000000000000000000000000000..0e99d9e3064fb254484c9722ba18bc109406bce9 --- /dev/null +++ b/hw-riscv-Allow-creating-multiple-instances-of-PLIC.patch @@ -0,0 +1,168 @@ +From 80ef84b1216345f88596564956c7734a8bdb0156 Mon Sep 17 00:00:00 2001 +From: Anup Patel +Date: Fri, 15 May 2020 10:25:33 +0530 +Subject: [PATCH 691/709] hw/riscv: Allow creating multiple instances of PLIC + +We extend PLIC emulation to allow multiple instances of PLIC in +a QEMU RISC-V machine. To achieve this, we remove first HART id +zero assumption from PLIC emulation. + +Signed-off-by: Anup Patel +Reviewed-by: Palmer Dabbelt +Reviewed-by: Alistair Francis +--- + hw/riscv/sifive_e.c | 2 +- + hw/riscv/sifive_plic.c | 24 +++++++++++++----------- + hw/riscv/sifive_u.c | 2 +- + hw/riscv/virt.c | 2 +- + include/hw/riscv/sifive_plic.h | 12 +++++++----- + 5 files changed, 23 insertions(+), 19 deletions(-) + +diff --git a/hw/riscv/sifive_e.c b/hw/riscv/sifive_e.c +index 1c3b37d0ba..bd122e71ae 100644 +--- a/hw/riscv/sifive_e.c ++++ b/hw/riscv/sifive_e.c +@@ -152,7 +152,7 @@ static void riscv_sifive_e_soc_realize(DeviceState *dev, Error **errp) + + /* MMIO */ + s->plic = sifive_plic_create(memmap[SIFIVE_E_PLIC].base, +- (char *)SIFIVE_E_PLIC_HART_CONFIG, ++ (char *)SIFIVE_E_PLIC_HART_CONFIG, 0, + SIFIVE_E_PLIC_NUM_SOURCES, + SIFIVE_E_PLIC_NUM_PRIORITIES, + SIFIVE_E_PLIC_PRIORITY_BASE, +diff --git a/hw/riscv/sifive_plic.c b/hw/riscv/sifive_plic.c +index c1e04cbb98..f88bb48053 100644 +--- a/hw/riscv/sifive_plic.c ++++ b/hw/riscv/sifive_plic.c +@@ -352,6 +352,7 @@ static const MemoryRegionOps sifive_plic_ops = { + + static Property sifive_plic_properties[] = { + DEFINE_PROP_STRING("hart-config", SiFivePLICState, hart_config), ++ DEFINE_PROP_UINT32("hartid-base", SiFivePLICState, hartid_base, 0), + DEFINE_PROP_UINT32("num-sources", SiFivePLICState, num_sources, 0), + DEFINE_PROP_UINT32("num-priorities", SiFivePLICState, num_priorities, 0), + DEFINE_PROP_UINT32("priority-base", SiFivePLICState, priority_base, 0), +@@ -400,10 +401,12 @@ static void parse_hart_config(SiFivePLICState *plic) + } + hartid++; + +- /* store hart/mode combinations */ + plic->num_addrs = addrid; ++ plic->num_harts = hartid; ++ ++ /* store hart/mode combinations */ + plic->addr_config = g_new(PLICAddr, plic->num_addrs); +- addrid = 0, hartid = 0; ++ addrid = 0, hartid = plic->hartid_base; + p = plic->hart_config; + while ((c = *p++)) { + if (c == ',') { +@@ -429,8 +432,6 @@ static void sifive_plic_irq_request(void *opaque, int irq, int level) + + static void sifive_plic_realize(DeviceState *dev, Error **errp) + { +- MachineState *ms = MACHINE(qdev_get_machine()); +- unsigned int smp_cpus = ms->smp.cpus; + SiFivePLICState *plic = SIFIVE_PLIC(dev); + int i; + +@@ -451,8 +452,8 @@ static void sifive_plic_realize(DeviceState *dev, Error **errp) + * lost a interrupt in the case a PLIC is attached. The SEIP bit must be + * hardware controlled when a PLIC is attached. + */ +- for (i = 0; i < smp_cpus; i++) { +- RISCVCPU *cpu = RISCV_CPU(qemu_get_cpu(i)); ++ for (i = 0; i < plic->num_harts; i++) { ++ RISCVCPU *cpu = RISCV_CPU(qemu_get_cpu(plic->hartid_base + i)); + if (riscv_cpu_claim_interrupts(cpu, MIP_SEIP) < 0) { + error_report("SEIP already claimed"); + exit(1); +@@ -488,16 +489,17 @@ type_init(sifive_plic_register_types) + * Create PLIC device. + */ + DeviceState *sifive_plic_create(hwaddr addr, char *hart_config, +- uint32_t num_sources, uint32_t num_priorities, +- uint32_t priority_base, uint32_t pending_base, +- uint32_t enable_base, uint32_t enable_stride, +- uint32_t context_base, uint32_t context_stride, +- uint32_t aperture_size) ++ uint32_t hartid_base, uint32_t num_sources, ++ uint32_t num_priorities, uint32_t priority_base, ++ uint32_t pending_base, uint32_t enable_base, ++ uint32_t enable_stride, uint32_t context_base, ++ uint32_t context_stride, uint32_t aperture_size) + { + DeviceState *dev = qdev_create(NULL, TYPE_SIFIVE_PLIC); + assert(enable_stride == (enable_stride & -enable_stride)); + assert(context_stride == (context_stride & -context_stride)); + qdev_prop_set_string(dev, "hart-config", hart_config); ++ qdev_prop_set_uint32(dev, "hartid-base", hartid_base); + qdev_prop_set_uint32(dev, "num-sources", num_sources); + qdev_prop_set_uint32(dev, "num-priorities", num_priorities); + qdev_prop_set_uint32(dev, "priority-base", priority_base); +diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c +index c193761916..53e48e2ff5 100644 +--- a/hw/riscv/sifive_u.c ++++ b/hw/riscv/sifive_u.c +@@ -586,7 +586,7 @@ static void riscv_sifive_u_soc_realize(DeviceState *dev, Error **errp) + + /* MMIO */ + s->plic = sifive_plic_create(memmap[SIFIVE_U_PLIC].base, +- plic_hart_config, ++ plic_hart_config, 0, + SIFIVE_U_PLIC_NUM_SOURCES, + SIFIVE_U_PLIC_NUM_PRIORITIES, + SIFIVE_U_PLIC_PRIORITY_BASE, +diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c +index 041c400261..35dc43d620 100644 +--- a/hw/riscv/virt.c ++++ b/hw/riscv/virt.c +@@ -584,7 +584,7 @@ static void riscv_virt_board_init(MachineState *machine) + + /* MMIO */ + s->plic = sifive_plic_create(memmap[VIRT_PLIC].base, +- plic_hart_config, ++ plic_hart_config, 0, + VIRT_PLIC_NUM_SOURCES, + VIRT_PLIC_NUM_PRIORITIES, + VIRT_PLIC_PRIORITY_BASE, +diff --git a/include/hw/riscv/sifive_plic.h b/include/hw/riscv/sifive_plic.h +index 4421e81249..ace76d0f1b 100644 +--- a/include/hw/riscv/sifive_plic.h ++++ b/include/hw/riscv/sifive_plic.h +@@ -48,6 +48,7 @@ typedef struct SiFivePLICState { + /*< public >*/ + MemoryRegion mmio; + uint32_t num_addrs; ++ uint32_t num_harts; + uint32_t bitfield_words; + PLICAddr *addr_config; + uint32_t *source_priority; +@@ -58,6 +59,7 @@ typedef struct SiFivePLICState { + + /* config */ + char *hart_config; ++ uint32_t hartid_base; + uint32_t num_sources; + uint32_t num_priorities; + uint32_t priority_base; +@@ -70,10 +72,10 @@ typedef struct SiFivePLICState { + } SiFivePLICState; + + DeviceState *sifive_plic_create(hwaddr addr, char *hart_config, +- uint32_t num_sources, uint32_t num_priorities, +- uint32_t priority_base, uint32_t pending_base, +- uint32_t enable_base, uint32_t enable_stride, +- uint32_t context_base, uint32_t context_stride, +- uint32_t aperture_size); ++ uint32_t hartid_base, uint32_t num_sources, ++ uint32_t num_priorities, uint32_t priority_base, ++ uint32_t pending_base, uint32_t enable_base, ++ uint32_t enable_stride, uint32_t context_base, ++ uint32_t context_stride, uint32_t aperture_size); + + #endif +-- +2.23.0 + diff --git a/hw-riscv-Generate-correct-mmu-type-for-32-bit-machin.patch b/hw-riscv-Generate-correct-mmu-type-for-32-bit-machin.patch new file mode 100644 index 0000000000000000000000000000000000000000..0e6403d90c08ba2d49268e913bb3084175db729e --- /dev/null +++ b/hw-riscv-Generate-correct-mmu-type-for-32-bit-machin.patch @@ -0,0 +1,70 @@ +From e883e9927ae667a2473c4a4ec666df53af1b34d9 Mon Sep 17 00:00:00 2001 +From: Bin Meng +Date: Sat, 7 Mar 2020 04:48:39 -0800 +Subject: [PATCH 060/709] hw/riscv: Generate correct "mmu-type" for 32-bit + machines + +32-bit machine should have its CPU's "mmu-type" set to "riscv,sv32". + +Signed-off-by: Bin Meng +Reviewed-by: Alistair Francis +Message-id: 1583585319-26603-1-git-send-email-bmeng.cn@gmail.com +Message-Id: <1583585319-26603-1-git-send-email-bmeng.cn@gmail.com> +Signed-off-by: Alistair Francis +--- + hw/riscv/sifive_u.c | 4 ++++ + hw/riscv/spike.c | 4 ++++ + hw/riscv/virt.c | 4 ++++ + 3 files changed, 12 insertions(+) + +diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c +index 8d0ee8b9c4..e32355a691 100644 +--- a/hw/riscv/sifive_u.c ++++ b/hw/riscv/sifive_u.c +@@ -160,7 +160,11 @@ static void create_fdt(SiFiveUState *s, const struct MemmapEntry *memmap, + qemu_fdt_add_subnode(fdt, nodename); + /* cpu 0 is the management hart that does not have mmu */ + if (cpu != 0) { ++#if defined(TARGET_RISCV32) ++ qemu_fdt_setprop_string(fdt, nodename, "mmu-type", "riscv,sv32"); ++#else + qemu_fdt_setprop_string(fdt, nodename, "mmu-type", "riscv,sv48"); ++#endif + isa = riscv_isa_string(&s->soc.u_cpus.harts[cpu - 1]); + } else { + isa = riscv_isa_string(&s->soc.e_cpus.harts[0]); +diff --git a/hw/riscv/spike.c b/hw/riscv/spike.c +index 5053fe4590..98697a244e 100644 +--- a/hw/riscv/spike.c ++++ b/hw/riscv/spike.c +@@ -102,7 +102,11 @@ static void create_fdt(SpikeState *s, const struct MemmapEntry *memmap, + char *intc = g_strdup_printf("/cpus/cpu@%d/interrupt-controller", cpu); + char *isa = riscv_isa_string(&s->soc.harts[cpu]); + qemu_fdt_add_subnode(fdt, nodename); ++#if defined(TARGET_RISCV32) ++ qemu_fdt_setprop_string(fdt, nodename, "mmu-type", "riscv,sv32"); ++#else + qemu_fdt_setprop_string(fdt, nodename, "mmu-type", "riscv,sv48"); ++#endif + qemu_fdt_setprop_string(fdt, nodename, "riscv,isa", isa); + qemu_fdt_setprop_string(fdt, nodename, "compatible", "riscv"); + qemu_fdt_setprop_string(fdt, nodename, "status", "okay"); +diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c +index 85ec9e22aa..c621a970aa 100644 +--- a/hw/riscv/virt.c ++++ b/hw/riscv/virt.c +@@ -229,7 +229,11 @@ static void create_fdt(RISCVVirtState *s, const struct MemmapEntry *memmap, + char *intc = g_strdup_printf("/cpus/cpu@%d/interrupt-controller", cpu); + char *isa = riscv_isa_string(&s->soc.harts[cpu]); + qemu_fdt_add_subnode(fdt, nodename); ++#if defined(TARGET_RISCV32) ++ qemu_fdt_setprop_string(fdt, nodename, "mmu-type", "riscv,sv32"); ++#else + qemu_fdt_setprop_string(fdt, nodename, "mmu-type", "riscv,sv48"); ++#endif + qemu_fdt_setprop_string(fdt, nodename, "riscv,isa", isa); + qemu_fdt_setprop_string(fdt, nodename, "compatible", "riscv"); + qemu_fdt_setprop_string(fdt, nodename, "status", "okay"); +-- +2.23.0 + diff --git a/hw-riscv-PLIC-update-external-interrupt-by-KVM-when-.patch b/hw-riscv-PLIC-update-external-interrupt-by-KVM-when-.patch new file mode 100644 index 0000000000000000000000000000000000000000..8d3999b88dc090f30c299e533961e22bd8218d46 --- /dev/null +++ b/hw-riscv-PLIC-update-external-interrupt-by-KVM-when-.patch @@ -0,0 +1,107 @@ +From 801cfa825bbbfffbb6bc29118513abfa96db44cd Mon Sep 17 00:00:00 2001 +From: Yifei Jiang +Date: Mon, 24 Aug 2020 20:24:25 +0800 +Subject: [PATCH 701/709] hw/riscv: PLIC update external interrupt by KVM when + kvm enabled + +Only support supervisor external interrupt currently. + +Signed-off-by: Yifei Jiang +Signed-off-by: Yipeng Yin +--- + hw/riscv/sifive_plic.c | 31 ++++++++++++++++++++++--------- + target/riscv/kvm.c | 20 ++++++++++++++++++++ + target/riscv/kvm_riscv.h | 1 + + 3 files changed, 43 insertions(+), 9 deletions(-) + +diff --git a/hw/riscv/sifive_plic.c b/hw/riscv/sifive_plic.c +index f88bb48053..be2fb0706e 100644 +--- a/hw/riscv/sifive_plic.c ++++ b/hw/riscv/sifive_plic.c +@@ -29,6 +29,8 @@ + #include "target/riscv/cpu.h" + #include "sysemu/sysemu.h" + #include "hw/riscv/sifive_plic.h" ++#include "sysemu/kvm.h" ++#include "kvm_riscv.h" + + #define RISCV_DEBUG_PLIC 0 + +@@ -145,15 +147,26 @@ static void sifive_plic_update(SiFivePLICState *plic) + continue; + } + int level = sifive_plic_irqs_pending(plic, addrid); +- switch (mode) { +- case PLICMode_M: +- riscv_cpu_update_mip(RISCV_CPU(cpu), MIP_MEIP, BOOL_TO_MASK(level)); +- break; +- case PLICMode_S: +- riscv_cpu_update_mip(RISCV_CPU(cpu), MIP_SEIP, BOOL_TO_MASK(level)); +- break; +- default: +- break; ++ if (kvm_enabled()) { ++ if (mode == PLICMode_M) { ++ continue; ++ } ++#ifdef CONFIG_KVM ++ kvm_riscv_set_irq(RISCV_CPU(cpu), IRQ_S_EXT, level); ++#endif ++ } else { ++ switch (mode) { ++ case PLICMode_M: ++ riscv_cpu_update_mip(RISCV_CPU(cpu), ++ MIP_MEIP, BOOL_TO_MASK(level)); ++ break; ++ case PLICMode_S: ++ riscv_cpu_update_mip(RISCV_CPU(cpu), ++ MIP_SEIP, BOOL_TO_MASK(level)); ++ break; ++ default: ++ break; ++ } + } + } + +diff --git a/target/riscv/kvm.c b/target/riscv/kvm.c +index 8cc9daaba9..6460746b2d 100644 +--- a/target/riscv/kvm.c ++++ b/target/riscv/kvm.c +@@ -439,3 +439,23 @@ void kvm_riscv_reset_vcpu(RISCVCPU *cpu) + env->gpr[10] = kvm_arch_vcpu_id(CPU(cpu)); /* a0 */ + env->gpr[11] = cpu->env.fdt_start; /* a1 */ + } ++ ++void kvm_riscv_set_irq(RISCVCPU *cpu, int irq, int level) ++{ ++ int ret; ++ unsigned virq = level ? KVM_INTERRUPT_SET : KVM_INTERRUPT_UNSET; ++ ++ if (irq != IRQ_S_EXT) { ++ return; ++ } ++ ++ if (!kvm_enabled()) { ++ return; ++ } ++ ++ ret = kvm_vcpu_ioctl(CPU(cpu), KVM_INTERRUPT, &virq); ++ if (ret < 0) { ++ perror("Set irq failed"); ++ abort(); ++ } ++} +diff --git a/target/riscv/kvm_riscv.h b/target/riscv/kvm_riscv.h +index 80a4ee721a..b3ab2c3d96 100644 +--- a/target/riscv/kvm_riscv.h ++++ b/target/riscv/kvm_riscv.h +@@ -20,5 +20,6 @@ + #define QEMU_KVM_RISCV_H + + void kvm_riscv_reset_vcpu(RISCVCPU *cpu); ++void kvm_riscv_set_irq(RISCVCPU *cpu, int irq, int level); + + #endif +-- +2.23.0 + diff --git a/hw-riscv-spike-Allow-creating-multiple-NUMA-sockets.patch b/hw-riscv-spike-Allow-creating-multiple-NUMA-sockets.patch new file mode 100644 index 0000000000000000000000000000000000000000..7306f1adc2d3d882c9679d1b8f2d1aa59ffd95b9 --- /dev/null +++ b/hw-riscv-spike-Allow-creating-multiple-NUMA-sockets.patch @@ -0,0 +1,358 @@ +From faac6f8ca9006acb9e809524a3d586cee13378ac Mon Sep 17 00:00:00 2001 +From: Anup Patel +Date: Thu, 14 May 2020 16:39:43 +0530 +Subject: [PATCH 693/709] hw/riscv: spike: Allow creating multiple NUMA sockets + +We extend RISC-V spike machine to allow creating a multi-socket +machine. Each RISC-V spike machine socket is a NUMA node having +a set of HARTs, a memory instance, and a CLINT instance. Other +devices are shared between all sockets. We also update the +generated device tree accordingly. + +By default, NUMA multi-socket support is disabled for RISC-V spike +machine. To enable it, users can use "-numa" command-line options +of QEMU. + +Example1: For two NUMA nodes with 2 CPUs each, append following +to command-line options: "-smp 4 -numa node -numa node" + +Example2: For two NUMA nodes with 1 and 3 CPUs, append following +to command-line options: +"-smp 4 -numa node -numa node -numa cpu,node-id=0,core-id=0 \ +-numa cpu,node-id=1,core-id=1 -numa cpu,node-id=1,core-id=2 \ +-numa cpu,node-id=1,core-id=3" + +The maximum number of sockets in a RISC-V spike machine is 8 +but this limit can be changed in future. + +Signed-off-by: Anup Patel +--- + hw/riscv/spike.c | 237 ++++++++++++++++++++++++++------------- + include/hw/riscv/spike.h | 11 +- + 2 files changed, 169 insertions(+), 79 deletions(-) + +diff --git a/hw/riscv/spike.c b/hw/riscv/spike.c +index a3db885ffa..29e7270035 100644 +--- a/hw/riscv/spike.c ++++ b/hw/riscv/spike.c +@@ -36,6 +36,7 @@ + #include "hw/riscv/sifive_clint.h" + #include "hw/riscv/spike.h" + #include "hw/riscv/boot.h" ++#include "hw/riscv/numa.h" + #include "chardev/char.h" + #include "sysemu/arch_init.h" + #include "sysemu/device_tree.h" +@@ -64,9 +65,14 @@ static void create_fdt(SpikeState *s, const struct MemmapEntry *memmap, + uint64_t mem_size, const char *cmdline) + { + void *fdt; +- int cpu; +- uint32_t *cells; +- char *nodename; ++ uint64_t addr, size; ++ unsigned long clint_addr; ++ int cpu, socket; ++ MachineState *mc = MACHINE(s); ++ uint32_t *clint_cells; ++ uint32_t cpu_phandle, intc_phandle, phandle = 1; ++ char *name, *mem_name, *clint_name, *clust_name; ++ char *core_name, *cpu_name, *intc_name; + + fdt = s->fdt = create_device_tree(&s->fdt_size); + if (!fdt) { +@@ -88,68 +94,91 @@ static void create_fdt(SpikeState *s, const struct MemmapEntry *memmap, + qemu_fdt_setprop_cell(fdt, "/soc", "#size-cells", 0x2); + qemu_fdt_setprop_cell(fdt, "/soc", "#address-cells", 0x2); + +- nodename = g_strdup_printf("/memory@%lx", +- (long)memmap[SPIKE_DRAM].base); +- qemu_fdt_add_subnode(fdt, nodename); +- qemu_fdt_setprop_cells(fdt, nodename, "reg", +- memmap[SPIKE_DRAM].base >> 32, memmap[SPIKE_DRAM].base, +- mem_size >> 32, 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", "timebase-frequency", + SIFIVE_CLINT_TIMEBASE_FREQ); + qemu_fdt_setprop_cell(fdt, "/cpus", "#size-cells", 0x0); + qemu_fdt_setprop_cell(fdt, "/cpus", "#address-cells", 0x1); ++ qemu_fdt_add_subnode(fdt, "/cpus/cpu-map"); ++ ++ for (socket = (riscv_socket_count(mc) - 1); socket >= 0; socket--) { ++ clust_name = g_strdup_printf("/cpus/cpu-map/cluster%d", socket); ++ qemu_fdt_add_subnode(fdt, clust_name); ++ ++ clint_cells = g_new0(uint32_t, s->soc[socket].num_harts * 4); + +- for (cpu = s->soc.num_harts - 1; cpu >= 0; cpu--) { +- nodename = g_strdup_printf("/cpus/cpu@%d", cpu); +- char *intc = g_strdup_printf("/cpus/cpu@%d/interrupt-controller", cpu); +- char *isa = riscv_isa_string(&s->soc.harts[cpu]); +- qemu_fdt_add_subnode(fdt, nodename); ++ for (cpu = s->soc[socket].num_harts - 1; cpu >= 0; cpu--) { ++ cpu_phandle = phandle++; ++ ++ cpu_name = g_strdup_printf("/cpus/cpu@%d", ++ s->soc[socket].hartid_base + cpu); ++ qemu_fdt_add_subnode(fdt, cpu_name); + #if defined(TARGET_RISCV32) +- qemu_fdt_setprop_string(fdt, nodename, "mmu-type", "riscv,sv32"); ++ qemu_fdt_setprop_string(fdt, cpu_name, "mmu-type", "riscv,sv32"); + #else +- qemu_fdt_setprop_string(fdt, nodename, "mmu-type", "riscv,sv48"); ++ qemu_fdt_setprop_string(fdt, cpu_name, "mmu-type", "riscv,sv48"); + #endif +- qemu_fdt_setprop_string(fdt, nodename, "riscv,isa", isa); +- qemu_fdt_setprop_string(fdt, nodename, "compatible", "riscv"); +- qemu_fdt_setprop_string(fdt, nodename, "status", "okay"); +- qemu_fdt_setprop_cell(fdt, nodename, "reg", cpu); +- qemu_fdt_setprop_string(fdt, nodename, "device_type", "cpu"); +- qemu_fdt_add_subnode(fdt, intc); +- qemu_fdt_setprop_cell(fdt, intc, "phandle", 1); +- qemu_fdt_setprop_string(fdt, intc, "compatible", "riscv,cpu-intc"); +- qemu_fdt_setprop(fdt, intc, "interrupt-controller", NULL, 0); +- qemu_fdt_setprop_cell(fdt, intc, "#interrupt-cells", 1); +- g_free(isa); +- g_free(intc); +- g_free(nodename); +- } ++ name = riscv_isa_string(&s->soc[socket].harts[cpu]); ++ qemu_fdt_setprop_string(fdt, cpu_name, "riscv,isa", name); ++ g_free(name); ++ qemu_fdt_setprop_string(fdt, cpu_name, "compatible", "riscv"); ++ qemu_fdt_setprop_string(fdt, cpu_name, "status", "okay"); ++ qemu_fdt_setprop_cell(fdt, cpu_name, "reg", ++ s->soc[socket].hartid_base + cpu); ++ qemu_fdt_setprop_string(fdt, cpu_name, "device_type", "cpu"); ++ riscv_socket_fdt_write_id(mc, fdt, cpu_name, socket); ++ qemu_fdt_setprop_cell(fdt, cpu_name, "phandle", cpu_phandle); + +- cells = g_new0(uint32_t, s->soc.num_harts * 4); +- for (cpu = 0; cpu < s->soc.num_harts; cpu++) { +- nodename = +- g_strdup_printf("/cpus/cpu@%d/interrupt-controller", cpu); +- uint32_t intc_phandle = qemu_fdt_get_phandle(fdt, nodename); +- cells[cpu * 4 + 0] = cpu_to_be32(intc_phandle); +- cells[cpu * 4 + 1] = cpu_to_be32(IRQ_M_SOFT); +- cells[cpu * 4 + 2] = cpu_to_be32(intc_phandle); +- cells[cpu * 4 + 3] = cpu_to_be32(IRQ_M_TIMER); +- g_free(nodename); ++ intc_name = g_strdup_printf("%s/interrupt-controller", cpu_name); ++ qemu_fdt_add_subnode(fdt, intc_name); ++ intc_phandle = phandle++; ++ qemu_fdt_setprop_cell(fdt, intc_name, "phandle", intc_phandle); ++ qemu_fdt_setprop_string(fdt, intc_name, "compatible", ++ "riscv,cpu-intc"); ++ qemu_fdt_setprop(fdt, intc_name, "interrupt-controller", NULL, 0); ++ qemu_fdt_setprop_cell(fdt, intc_name, "#interrupt-cells", 1); ++ ++ clint_cells[cpu * 4 + 0] = cpu_to_be32(intc_phandle); ++ clint_cells[cpu * 4 + 1] = cpu_to_be32(IRQ_M_SOFT); ++ clint_cells[cpu * 4 + 2] = cpu_to_be32(intc_phandle); ++ clint_cells[cpu * 4 + 3] = cpu_to_be32(IRQ_M_TIMER); ++ ++ core_name = g_strdup_printf("%s/core%d", clust_name, cpu); ++ qemu_fdt_add_subnode(fdt, core_name); ++ qemu_fdt_setprop_cell(fdt, core_name, "cpu", cpu_phandle); ++ ++ g_free(core_name); ++ g_free(intc_name); ++ g_free(cpu_name); ++ } ++ ++ addr = memmap[SPIKE_DRAM].base + riscv_socket_mem_offset(mc, socket); ++ size = riscv_socket_mem_size(mc, socket); ++ mem_name = g_strdup_printf("/memory@%lx", (long)addr); ++ qemu_fdt_add_subnode(fdt, mem_name); ++ qemu_fdt_setprop_cells(fdt, mem_name, "reg", ++ addr >> 32, addr, size >> 32, size); ++ qemu_fdt_setprop_string(fdt, mem_name, "device_type", "memory"); ++ riscv_socket_fdt_write_id(mc, fdt, mem_name, socket); ++ g_free(mem_name); ++ ++ clint_addr = memmap[SPIKE_CLINT].base + ++ (memmap[SPIKE_CLINT].size * socket); ++ clint_name = g_strdup_printf("/soc/clint@%lx", clint_addr); ++ qemu_fdt_add_subnode(fdt, clint_name); ++ qemu_fdt_setprop_string(fdt, clint_name, "compatible", "riscv,clint0"); ++ qemu_fdt_setprop_cells(fdt, clint_name, "reg", ++ 0x0, clint_addr, 0x0, memmap[SPIKE_CLINT].size); ++ qemu_fdt_setprop(fdt, clint_name, "interrupts-extended", ++ clint_cells, s->soc[socket].num_harts * sizeof(uint32_t) * 4); ++ riscv_socket_fdt_write_id(mc, fdt, clint_name, socket); ++ ++ g_free(clint_name); ++ g_free(clint_cells); ++ g_free(clust_name); + } +- nodename = g_strdup_printf("/soc/clint@%lx", +- (long)memmap[SPIKE_CLINT].base); +- qemu_fdt_add_subnode(fdt, nodename); +- qemu_fdt_setprop_string(fdt, nodename, "compatible", "riscv,clint0"); +- qemu_fdt_setprop_cells(fdt, nodename, "reg", +- 0x0, memmap[SPIKE_CLINT].base, +- 0x0, memmap[SPIKE_CLINT].size); +- qemu_fdt_setprop(fdt, nodename, "interrupts-extended", +- cells, s->soc.num_harts * sizeof(uint32_t) * 4); +- g_free(cells); +- g_free(nodename); ++ ++ riscv_socket_fdt_write_distance_matrix(mc, fdt); + + if (cmdline) { + qemu_fdt_add_subnode(fdt, "/chosen"); +@@ -160,23 +189,58 @@ static void create_fdt(SpikeState *s, const struct MemmapEntry *memmap, + static void spike_board_init(MachineState *machine) + { + const struct MemmapEntry *memmap = spike_memmap; +- +- SpikeState *s = g_new0(SpikeState, 1); ++ SpikeState *s = SPIKE_MACHINE(machine); + MemoryRegion *system_memory = get_system_memory(); + MemoryRegion *main_mem = g_new(MemoryRegion, 1); + MemoryRegion *mask_rom = g_new(MemoryRegion, 1); +- int i; +- unsigned int smp_cpus = machine->smp.cpus; +- +- /* Initialize SOC */ +- object_initialize_child(OBJECT(machine), "soc", &s->soc, sizeof(s->soc), +- TYPE_RISCV_HART_ARRAY, &error_abort, NULL); +- object_property_set_str(OBJECT(&s->soc), machine->cpu_type, "cpu-type", +- &error_abort); +- object_property_set_int(OBJECT(&s->soc), smp_cpus, "num-harts", +- &error_abort); +- object_property_set_bool(OBJECT(&s->soc), true, "realized", +- &error_abort); ++ char *soc_name; ++ int i, base_hartid, hart_count; ++ ++ /* Check socket count limit */ ++ if (SPIKE_SOCKETS_MAX < riscv_socket_count(machine)) { ++ error_report("number of sockets/nodes should be less than %d", ++ SPIKE_SOCKETS_MAX); ++ exit(1); ++ } ++ ++ /* Initialize sockets */ ++ for (i = 0; i < riscv_socket_count(machine); i++) { ++ if (!riscv_socket_check_hartids(machine, i)) { ++ error_report("discontinuous hartids in socket%d", i); ++ exit(1); ++ } ++ ++ base_hartid = riscv_socket_first_hartid(machine, i); ++ if (base_hartid < 0) { ++ error_report("can't find hartid base for socket%d", i); ++ exit(1); ++ } ++ ++ hart_count = riscv_socket_hart_count(machine, i); ++ if (hart_count < 0) { ++ error_report("can't find hart count for socket%d", i); ++ exit(1); ++ } ++ ++ soc_name = g_strdup_printf("soc%d", i); ++ object_initialize_child(OBJECT(machine), soc_name, &s->soc[i], ++ sizeof(s->soc[i]), TYPE_RISCV_HART_ARRAY, &error_abort, NULL); ++ g_free(soc_name); ++ object_property_set_str(OBJECT(&s->soc[i]), ++ machine->cpu_type, "cpu-type", &error_abort); ++ object_property_set_int(OBJECT(&s->soc[i]), ++ base_hartid, "hartid-base", &error_abort); ++ object_property_set_int(OBJECT(&s->soc[i]), ++ hart_count, "num-harts", &error_abort); ++ object_property_set_bool(OBJECT(&s->soc[i]), ++ true, "realized", &error_abort); ++ ++ /* Core Local Interruptor (timer and IPI) for each socket */ ++ sifive_clint_create( ++ memmap[SPIKE_CLINT].base + i * memmap[SPIKE_CLINT].size, ++ memmap[SPIKE_CLINT].size, base_hartid, hart_count, ++ SIFIVE_SIP_BASE, SIFIVE_TIMECMP_BASE, SIFIVE_TIME_BASE, false); ++ } + + /* register system main memory (actual RAM) */ + memory_region_init_ram(main_mem, NULL, "riscv.spike.ram", +@@ -249,21 +313,40 @@ static void spike_board_init(MachineState *machine) + &address_space_memory); + + /* initialize HTIF using symbols found in load_kernel */ +- htif_mm_init(system_memory, mask_rom, &s->soc.harts[0].env, serial_hd(0)); ++ htif_mm_init(system_memory, mask_rom, ++ &s->soc[0].harts[0].env, serial_hd(0)); ++} + +- /* Core Local Interruptor (timer and IPI) */ +- sifive_clint_create(memmap[SPIKE_CLINT].base, memmap[SPIKE_CLINT].size, +- 0, smp_cpus, SIFIVE_SIP_BASE, SIFIVE_TIMECMP_BASE, SIFIVE_TIME_BASE, +- false); ++static void spike_machine_instance_init(Object *obj) ++{ + } + +-static void spike_machine_init(MachineClass *mc) ++static void spike_machine_class_init(ObjectClass *oc, void *data) + { +- mc->desc = "RISC-V Spike Board"; ++ MachineClass *mc = MACHINE_CLASS(oc); ++ ++ mc->desc = "RISC-V Spike board"; + mc->init = spike_board_init; +- mc->max_cpus = 8; ++ mc->max_cpus = SPIKE_CPUS_MAX; + mc->is_default = true; + mc->default_cpu_type = SPIKE_V1_10_0_CPU; ++ mc->possible_cpu_arch_ids = riscv_numa_possible_cpu_arch_ids; ++ mc->cpu_index_to_instance_props = riscv_numa_cpu_index_to_props; ++ mc->get_default_cpu_node_id = riscv_numa_get_default_cpu_node_id; ++ mc->numa_mem_supported = true; ++} ++ ++static const TypeInfo spike_machine_typeinfo = { ++ .name = MACHINE_TYPE_NAME("spike"), ++ .parent = TYPE_MACHINE, ++ .class_init = spike_machine_class_init, ++ .instance_init = spike_machine_instance_init, ++ .instance_size = sizeof(SpikeState), ++}; ++ ++static void spike_machine_init_register_types(void) ++{ ++ type_register_static(&spike_machine_typeinfo); + } + +-DEFINE_MACHINE("spike", spike_machine_init) ++type_init(spike_machine_init_register_types) +diff --git a/include/hw/riscv/spike.h b/include/hw/riscv/spike.h +index 1cd72b85d6..b0a18a9c94 100644 +--- a/include/hw/riscv/spike.h ++++ b/include/hw/riscv/spike.h +@@ -22,12 +22,19 @@ + #include "hw/riscv/riscv_hart.h" + #include "hw/sysbus.h" + ++#define SPIKE_CPUS_MAX 8 ++#define SPIKE_SOCKETS_MAX 8 ++ ++#define TYPE_SPIKE_MACHINE MACHINE_TYPE_NAME("spike") ++#define SPIKE_MACHINE(obj) \ ++ OBJECT_CHECK(SpikeState, (obj), TYPE_SPIKE_MACHINE) ++ + typedef struct { + /*< private >*/ +- SysBusDevice parent_obj; ++ MachineState parent; + + /*< public >*/ +- RISCVHartArrayState soc; ++ RISCVHartArrayState soc[SPIKE_SOCKETS_MAX]; + void *fdt; + int fdt_size; + } SpikeState; +-- +2.23.0 + diff --git a/hw-riscv-spike-Allow-loading-firmware-separately-usi.patch b/hw-riscv-spike-Allow-loading-firmware-separately-usi.patch new file mode 100644 index 0000000000000000000000000000000000000000..e81d31432d69cf4dd065c3cfe7dbdd37afead477 --- /dev/null +++ b/hw-riscv-spike-Allow-loading-firmware-separately-usi.patch @@ -0,0 +1,64 @@ +From 5b8a986350a9ee2d9d95a76c29017c3c603bb350 Mon Sep 17 00:00:00 2001 +From: Anup Patel +Date: Mon, 27 Apr 2020 13:36:43 +0530 +Subject: [PATCH 066/709] hw/riscv/spike: Allow loading firmware separately + using -bios option + +This patch extends Spike machine support to allow loading OpenSBI +firmware (fw_jump.elf) separately using -bios option. + +Signed-off-by: Anup Patel +Reviewed-by: Alistair Francis +Message-id: 20200427080644.168461-3-anup.patel@wdc.com +Message-Id: <20200427080644.168461-3-anup.patel@wdc.com> +Signed-off-by: Alistair Francis +--- + hw/riscv/spike.c | 24 +++++++++++++++++++++++- + 1 file changed, 23 insertions(+), 1 deletion(-) + +diff --git a/hw/riscv/spike.c b/hw/riscv/spike.c +index 98697a244e..e7908b88fe 100644 +--- a/hw/riscv/spike.c ++++ b/hw/riscv/spike.c +@@ -45,6 +45,12 @@ + + #include + ++#if defined(TARGET_RISCV32) ++# define BIOS_FILENAME "opensbi-riscv32-spike-fw_jump.elf" ++#else ++# define BIOS_FILENAME "opensbi-riscv64-spike-fw_jump.elf" ++#endif ++ + static const struct MemmapEntry { + hwaddr base; + hwaddr size; +@@ -187,8 +193,24 @@ static void spike_board_init(MachineState *machine) + memory_region_add_subregion(system_memory, memmap[SPIKE_MROM].base, + mask_rom); + ++ riscv_find_and_load_firmware(machine, BIOS_FILENAME, ++ memmap[SPIKE_DRAM].base, ++ htif_symbol_callback); ++ + if (machine->kernel_filename) { +- riscv_load_kernel(machine->kernel_filename, htif_symbol_callback); ++ uint64_t kernel_entry = riscv_load_kernel(machine->kernel_filename, ++ htif_symbol_callback); ++ ++ if (machine->initrd_filename) { ++ hwaddr start; ++ hwaddr end = riscv_load_initrd(machine->initrd_filename, ++ machine->ram_size, kernel_entry, ++ &start); ++ qemu_fdt_setprop_cell(s->fdt, "/chosen", ++ "linux,initrd-start", start); ++ qemu_fdt_setprop_cell(s->fdt, "/chosen", "linux,initrd-end", ++ end); ++ } + } + + /* reset vector */ +-- +2.23.0 + diff --git a/hw-riscv-spike-Allow-more-than-one-CPUs.patch b/hw-riscv-spike-Allow-more-than-one-CPUs.patch new file mode 100644 index 0000000000000000000000000000000000000000..af9777fc629734d44b8f34b2e4240ac4db295938 --- /dev/null +++ b/hw-riscv-spike-Allow-more-than-one-CPUs.patch @@ -0,0 +1,37 @@ +From 31e6d70485b1a719ca27e9a2d21f2a61ac497cdf Mon Sep 17 00:00:00 2001 +From: Anup Patel +Date: Mon, 27 Apr 2020 13:36:44 +0530 +Subject: [PATCH 067/709] hw/riscv/spike: Allow more than one CPUs + +Currently, the upstream Spike ISA simulator allows more than +one CPUs so we update QEMU Spike machine on similar lines to +allow more than one CPUs. + +The maximum number of CPUs for QEMU Spike machine is kept +same as QEMU Virt machine. + +Signed-off-by: Anup Patel +Reviewed-by: Alistair Francis +Message-id: 20200427080644.168461-4-anup.patel@wdc.com +Message-Id: <20200427080644.168461-4-anup.patel@wdc.com> +Signed-off-by: Alistair Francis +--- + hw/riscv/spike.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/hw/riscv/spike.c b/hw/riscv/spike.c +index e7908b88fe..d0c4843712 100644 +--- a/hw/riscv/spike.c ++++ b/hw/riscv/spike.c +@@ -476,7 +476,7 @@ static void spike_machine_init(MachineClass *mc) + { + mc->desc = "RISC-V Spike Board"; + mc->init = spike_board_init; +- mc->max_cpus = 1; ++ mc->max_cpus = 8; + mc->is_default = true; + mc->default_cpu_type = SPIKE_V1_10_0_CPU; + } +-- +2.23.0 + diff --git a/hw-riscv-spike-Remove-deprecated-ISA-specific-machin.patch b/hw-riscv-spike-Remove-deprecated-ISA-specific-machin.patch new file mode 100644 index 0000000000000000000000000000000000000000..8175b567a44ca60efb92e1194052b5ee05ada850 --- /dev/null +++ b/hw-riscv-spike-Remove-deprecated-ISA-specific-machin.patch @@ -0,0 +1,274 @@ +From b3273bae2b3fffb7e870bd4ea6cef220c6b2bb42 Mon Sep 17 00:00:00 2001 +From: Alistair Francis +Date: Tue, 5 May 2020 13:07:24 -0700 +Subject: [PATCH 667/709] hw/riscv: spike: Remove deprecated ISA specific + machines +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The ISA specific Spike machines have been deprecated in QEMU since 4.1, +let's finally remove them. + +Signed-off-by: Alistair Francis +Reviewed-by: Philippe Mathieu-Daudé +Reviewed-by: Bin Meng +--- + hw/riscv/spike.c | 217 --------------------------------------- + include/hw/riscv/spike.h | 6 +- + 2 files changed, 2 insertions(+), 221 deletions(-) + +diff --git a/hw/riscv/spike.c b/hw/riscv/spike.c +index d0c4843712..7bbbdb5036 100644 +--- a/hw/riscv/spike.c ++++ b/hw/riscv/spike.c +@@ -257,221 +257,6 @@ static void spike_board_init(MachineState *machine) + false); + } + +-static void spike_v1_10_0_board_init(MachineState *machine) +-{ +- const struct MemmapEntry *memmap = spike_memmap; +- +- SpikeState *s = g_new0(SpikeState, 1); +- MemoryRegion *system_memory = get_system_memory(); +- MemoryRegion *main_mem = g_new(MemoryRegion, 1); +- MemoryRegion *mask_rom = g_new(MemoryRegion, 1); +- int i; +- unsigned int smp_cpus = machine->smp.cpus; +- +- if (!qtest_enabled()) { +- info_report("The Spike v1.10.0 machine has been deprecated. " +- "Please use the generic spike machine and specify the ISA " +- "versions using -cpu."); +- } +- +- /* Initialize SOC */ +- object_initialize_child(OBJECT(machine), "soc", &s->soc, sizeof(s->soc), +- TYPE_RISCV_HART_ARRAY, &error_abort, NULL); +- object_property_set_str(OBJECT(&s->soc), SPIKE_V1_10_0_CPU, "cpu-type", +- &error_abort); +- object_property_set_int(OBJECT(&s->soc), smp_cpus, "num-harts", +- &error_abort); +- object_property_set_bool(OBJECT(&s->soc), true, "realized", +- &error_abort); +- +- /* register system main memory (actual RAM) */ +- memory_region_init_ram(main_mem, NULL, "riscv.spike.ram", +- machine->ram_size, &error_fatal); +- memory_region_add_subregion(system_memory, memmap[SPIKE_DRAM].base, +- main_mem); +- +- /* create device tree */ +- create_fdt(s, memmap, machine->ram_size, machine->kernel_cmdline); +- +- /* boot rom */ +- memory_region_init_rom(mask_rom, NULL, "riscv.spike.mrom", +- memmap[SPIKE_MROM].size, &error_fatal); +- memory_region_add_subregion(system_memory, memmap[SPIKE_MROM].base, +- mask_rom); +- +- if (machine->kernel_filename) { +- riscv_load_kernel(machine->kernel_filename, htif_symbol_callback); +- } +- +- /* reset vector */ +- uint32_t reset_vec[8] = { +- 0x00000297, /* 1: auipc t0, %pcrel_hi(dtb) */ +- 0x02028593, /* addi a1, t0, %pcrel_lo(1b) */ +- 0xf1402573, /* csrr a0, mhartid */ +-#if defined(TARGET_RISCV32) +- 0x0182a283, /* lw t0, 24(t0) */ +-#elif defined(TARGET_RISCV64) +- 0x0182b283, /* ld t0, 24(t0) */ +-#endif +- 0x00028067, /* jr t0 */ +- 0x00000000, +- memmap[SPIKE_DRAM].base, /* start: .dword DRAM_BASE */ +- 0x00000000, +- /* dtb: */ +- }; +- +- /* copy in the reset vector in little_endian byte order */ +- for (i = 0; i < sizeof(reset_vec) >> 2; i++) { +- reset_vec[i] = cpu_to_le32(reset_vec[i]); +- } +- rom_add_blob_fixed_as("mrom.reset", reset_vec, sizeof(reset_vec), +- memmap[SPIKE_MROM].base, &address_space_memory); +- +- /* copy in the device tree */ +- if (fdt_pack(s->fdt) || fdt_totalsize(s->fdt) > +- memmap[SPIKE_MROM].size - sizeof(reset_vec)) { +- error_report("not enough space to store device-tree"); +- exit(1); +- } +- qemu_fdt_dumpdtb(s->fdt, fdt_totalsize(s->fdt)); +- rom_add_blob_fixed_as("mrom.fdt", s->fdt, fdt_totalsize(s->fdt), +- memmap[SPIKE_MROM].base + sizeof(reset_vec), +- &address_space_memory); +- +- /* initialize HTIF using symbols found in load_kernel */ +- htif_mm_init(system_memory, mask_rom, &s->soc.harts[0].env, serial_hd(0)); +- +- /* Core Local Interruptor (timer and IPI) */ +- sifive_clint_create(memmap[SPIKE_CLINT].base, memmap[SPIKE_CLINT].size, +- smp_cpus, SIFIVE_SIP_BASE, SIFIVE_TIMECMP_BASE, SIFIVE_TIME_BASE, +- false); +-} +- +-static void spike_v1_09_1_board_init(MachineState *machine) +-{ +- const struct MemmapEntry *memmap = spike_memmap; +- +- SpikeState *s = g_new0(SpikeState, 1); +- MemoryRegion *system_memory = get_system_memory(); +- MemoryRegion *main_mem = g_new(MemoryRegion, 1); +- MemoryRegion *mask_rom = g_new(MemoryRegion, 1); +- int i; +- unsigned int smp_cpus = machine->smp.cpus; +- +- if (!qtest_enabled()) { +- info_report("The Spike v1.09.1 machine has been deprecated. " +- "Please use the generic spike machine and specify the ISA " +- "versions using -cpu."); +- } +- +- /* Initialize SOC */ +- object_initialize_child(OBJECT(machine), "soc", &s->soc, sizeof(s->soc), +- TYPE_RISCV_HART_ARRAY, &error_abort, NULL); +- object_property_set_str(OBJECT(&s->soc), SPIKE_V1_09_1_CPU, "cpu-type", +- &error_abort); +- object_property_set_int(OBJECT(&s->soc), smp_cpus, "num-harts", +- &error_abort); +- object_property_set_bool(OBJECT(&s->soc), true, "realized", +- &error_abort); +- +- /* register system main memory (actual RAM) */ +- memory_region_init_ram(main_mem, NULL, "riscv.spike.ram", +- machine->ram_size, &error_fatal); +- memory_region_add_subregion(system_memory, memmap[SPIKE_DRAM].base, +- main_mem); +- +- /* boot rom */ +- memory_region_init_rom(mask_rom, NULL, "riscv.spike.mrom", +- memmap[SPIKE_MROM].size, &error_fatal); +- memory_region_add_subregion(system_memory, memmap[SPIKE_MROM].base, +- mask_rom); +- +- if (machine->kernel_filename) { +- riscv_load_kernel(machine->kernel_filename, htif_symbol_callback); +- } +- +- /* reset vector */ +- uint32_t reset_vec[8] = { +- 0x297 + memmap[SPIKE_DRAM].base - memmap[SPIKE_MROM].base, /* lui */ +- 0x00028067, /* jump to DRAM_BASE */ +- 0x00000000, /* reserved */ +- memmap[SPIKE_MROM].base + sizeof(reset_vec), /* config string pointer */ +- 0, 0, 0, 0 /* trap vector */ +- }; +- +- /* part one of config string - before memory size specified */ +- const char *config_string_tmpl = +- "platform {\n" +- " vendor ucb;\n" +- " arch spike;\n" +- "};\n" +- "rtc {\n" +- " addr 0x%" PRIx64 "x;\n" +- "};\n" +- "ram {\n" +- " 0 {\n" +- " addr 0x%" PRIx64 "x;\n" +- " size 0x%" PRIx64 "x;\n" +- " };\n" +- "};\n" +- "core {\n" +- " 0" " {\n" +- " " "0 {\n" +- " isa %s;\n" +- " timecmp 0x%" PRIx64 "x;\n" +- " ipi 0x%" PRIx64 "x;\n" +- " };\n" +- " };\n" +- "};\n"; +- +- /* build config string with supplied memory size */ +- char *isa = riscv_isa_string(&s->soc.harts[0]); +- char *config_string = g_strdup_printf(config_string_tmpl, +- (uint64_t)memmap[SPIKE_CLINT].base + SIFIVE_TIME_BASE, +- (uint64_t)memmap[SPIKE_DRAM].base, +- (uint64_t)ram_size, isa, +- (uint64_t)memmap[SPIKE_CLINT].base + SIFIVE_TIMECMP_BASE, +- (uint64_t)memmap[SPIKE_CLINT].base + SIFIVE_SIP_BASE); +- g_free(isa); +- size_t config_string_len = strlen(config_string); +- +- /* copy in the reset vector in little_endian byte order */ +- for (i = 0; i < sizeof(reset_vec) >> 2; i++) { +- reset_vec[i] = cpu_to_le32(reset_vec[i]); +- } +- rom_add_blob_fixed_as("mrom.reset", reset_vec, sizeof(reset_vec), +- memmap[SPIKE_MROM].base, &address_space_memory); +- +- /* copy in the config string */ +- rom_add_blob_fixed_as("mrom.reset", config_string, config_string_len, +- memmap[SPIKE_MROM].base + sizeof(reset_vec), +- &address_space_memory); +- +- /* initialize HTIF using symbols found in load_kernel */ +- htif_mm_init(system_memory, mask_rom, &s->soc.harts[0].env, serial_hd(0)); +- +- /* Core Local Interruptor (timer and IPI) */ +- sifive_clint_create(memmap[SPIKE_CLINT].base, memmap[SPIKE_CLINT].size, +- smp_cpus, SIFIVE_SIP_BASE, SIFIVE_TIMECMP_BASE, SIFIVE_TIME_BASE, +- false); +- +- g_free(config_string); +-} +- +-static void spike_v1_09_1_machine_init(MachineClass *mc) +-{ +- mc->desc = "RISC-V Spike Board (Privileged ISA v1.9.1)"; +- mc->init = spike_v1_09_1_board_init; +- mc->max_cpus = 1; +-} +- +-static void spike_v1_10_0_machine_init(MachineClass *mc) +-{ +- mc->desc = "RISC-V Spike Board (Privileged ISA v1.10)"; +- mc->init = spike_v1_10_0_board_init; +- mc->max_cpus = 1; +-} +- + static void spike_machine_init(MachineClass *mc) + { + mc->desc = "RISC-V Spike Board"; +@@ -481,6 +266,4 @@ static void spike_machine_init(MachineClass *mc) + mc->default_cpu_type = SPIKE_V1_10_0_CPU; + } + +-DEFINE_MACHINE("spike_v1.9.1", spike_v1_09_1_machine_init) +-DEFINE_MACHINE("spike_v1.10", spike_v1_10_0_machine_init) + DEFINE_MACHINE("spike", spike_machine_init) +diff --git a/include/hw/riscv/spike.h b/include/hw/riscv/spike.h +index dc770421bc..1cd72b85d6 100644 +--- a/include/hw/riscv/spike.h ++++ b/include/hw/riscv/spike.h +@@ -39,11 +39,9 @@ enum { + }; + + #if defined(TARGET_RISCV32) +-#define SPIKE_V1_09_1_CPU TYPE_RISCV_CPU_RV32GCSU_V1_09_1 +-#define SPIKE_V1_10_0_CPU TYPE_RISCV_CPU_RV32GCSU_V1_10_0 ++#define SPIKE_V1_10_0_CPU TYPE_RISCV_CPU_BASE32 + #elif defined(TARGET_RISCV64) +-#define SPIKE_V1_09_1_CPU TYPE_RISCV_CPU_RV64GCSU_V1_09_1 +-#define SPIKE_V1_10_0_CPU TYPE_RISCV_CPU_RV64GCSU_V1_10_0 ++#define SPIKE_V1_10_0_CPU TYPE_RISCV_CPU_BASE64 + #endif + + #endif +-- +2.23.0 + diff --git a/hw-riscv-virt-Allow-creating-multiple-NUMA-sockets.patch b/hw-riscv-virt-Allow-creating-multiple-NUMA-sockets.patch new file mode 100644 index 0000000000000000000000000000000000000000..86a2d4e58dda25d560d8ba2216cc549bd62ac7dd --- /dev/null +++ b/hw-riscv-virt-Allow-creating-multiple-NUMA-sockets.patch @@ -0,0 +1,728 @@ +From df64c9ebe9bb5c333925d74975ae32c945c1d0f3 Mon Sep 17 00:00:00 2001 +From: Anup Patel +Date: Fri, 15 May 2020 14:58:50 +0530 +Subject: [PATCH 694/709] hw/riscv: virt: Allow creating multiple NUMA sockets + +We extend RISC-V virt machine to allow creating a multi-socket +machine. Each RISC-V virt machine socket is a NUMA node having +a set of HARTs, a memory instance, a CLINT instance, and a PLIC +instance. Other devices are shared between all sockets. We also +update the generated device tree accordingly. + +By default, NUMA multi-socket support is disabled for RISC-V virt +machine. To enable it, users can use "-numa" command-line options +of QEMU. + +Example1: For two NUMA nodes with 2 CPUs each, append following +to command-line options: "-smp 4 -numa node -numa node" + +Example2: For two NUMA nodes with 1 and 3 CPUs, append following +to command-line options: +"-smp 4 -numa node -numa node -numa cpu,node-id=0,core-id=0 \ +-numa cpu,node-id=1,core-id=1 -numa cpu,node-id=1,core-id=2 \ +-numa cpu,node-id=1,core-id=3" + +The maximum number of sockets in a RISC-V virt machine is 8 +but this limit can be changed in future. + +Signed-off-by: Anup Patel +--- + hw/riscv/virt.c | 530 +++++++++++++++++++++++----------------- + include/hw/riscv/virt.h | 9 +- + 2 files changed, 308 insertions(+), 231 deletions(-) + +diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c +index 35dc43d620..e01925ff3d 100644 +--- a/hw/riscv/virt.c ++++ b/hw/riscv/virt.c +@@ -35,6 +35,7 @@ + #include "hw/riscv/sifive_test.h" + #include "hw/riscv/virt.h" + #include "hw/riscv/boot.h" ++#include "hw/riscv/numa.h" + #include "chardev/char.h" + #include "sysemu/arch_init.h" + #include "sysemu/device_tree.h" +@@ -60,7 +61,7 @@ static const struct MemmapEntry { + [VIRT_TEST] = { 0x100000, 0x1000 }, + [VIRT_RTC] = { 0x101000, 0x1000 }, + [VIRT_CLINT] = { 0x2000000, 0x10000 }, +- [VIRT_PLIC] = { 0xc000000, 0x4000000 }, ++ [VIRT_PLIC] = { 0xc000000, VIRT_PLIC_SIZE(VIRT_CPUS_MAX * 2) }, + [VIRT_UART0] = { 0x10000000, 0x100 }, + [VIRT_VIRTIO] = { 0x10001000, 0x1000 }, + [VIRT_FLASH] = { 0x20000000, 0x4000000 }, +@@ -182,10 +183,17 @@ static void create_fdt(RISCVVirtState *s, const struct MemmapEntry *memmap, + uint64_t mem_size, const char *cmdline) + { + void *fdt; +- int cpu, i; +- uint32_t *cells; +- char *nodename; +- uint32_t plic_phandle, test_phandle, phandle = 1; ++ int i, cpu, socket; ++ MachineState *mc = MACHINE(s); ++ uint64_t addr, size; ++ uint32_t *clint_cells, *plic_cells; ++ unsigned long clint_addr, plic_addr; ++ uint32_t plic_phandle[MAX_NODES]; ++ uint32_t cpu_phandle, intc_phandle, test_phandle; ++ uint32_t phandle = 1, plic_mmio_phandle = 1; ++ uint32_t plic_pcie_phandle = 1, plic_virtio_phandle = 1; ++ char *mem_name, *cpu_name, *core_name, *intc_name; ++ char *name, *clint_name, *plic_name, *clust_name; + hwaddr flashsize = virt_memmap[VIRT_FLASH].size / 2; + hwaddr flashbase = virt_memmap[VIRT_FLASH].base; + +@@ -206,231 +214,238 @@ static void create_fdt(RISCVVirtState *s, const struct MemmapEntry *memmap, + qemu_fdt_setprop_cell(fdt, "/soc", "#size-cells", 0x2); + qemu_fdt_setprop_cell(fdt, "/soc", "#address-cells", 0x2); + +- nodename = g_strdup_printf("/memory@%lx", +- (long)memmap[VIRT_DRAM].base); +- qemu_fdt_add_subnode(fdt, nodename); +- qemu_fdt_setprop_cells(fdt, nodename, "reg", +- memmap[VIRT_DRAM].base >> 32, memmap[VIRT_DRAM].base, +- mem_size >> 32, 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", "timebase-frequency", + SIFIVE_CLINT_TIMEBASE_FREQ); + qemu_fdt_setprop_cell(fdt, "/cpus", "#size-cells", 0x0); + qemu_fdt_setprop_cell(fdt, "/cpus", "#address-cells", 0x1); ++ qemu_fdt_add_subnode(fdt, "/cpus/cpu-map"); ++ ++ for (socket = (riscv_socket_count(mc) - 1); socket >= 0; socket--) { ++ clust_name = g_strdup_printf("/cpus/cpu-map/cluster%d", socket); ++ qemu_fdt_add_subnode(fdt, clust_name); ++ ++ plic_cells = g_new0(uint32_t, s->soc[socket].num_harts * 4); ++ clint_cells = g_new0(uint32_t, s->soc[socket].num_harts * 4); ++ ++ for (cpu = s->soc[socket].num_harts - 1; cpu >= 0; cpu--) { ++ cpu_phandle = phandle++; + +- for (cpu = s->soc.num_harts - 1; cpu >= 0; cpu--) { +- int cpu_phandle = phandle++; +- int intc_phandle; +- nodename = g_strdup_printf("/cpus/cpu@%d", cpu); +- char *intc = g_strdup_printf("/cpus/cpu@%d/interrupt-controller", cpu); +- char *isa = riscv_isa_string(&s->soc.harts[cpu]); +- qemu_fdt_add_subnode(fdt, nodename); ++ cpu_name = g_strdup_printf("/cpus/cpu@%d", ++ s->soc[socket].hartid_base + cpu); ++ qemu_fdt_add_subnode(fdt, cpu_name); + #if defined(TARGET_RISCV32) +- qemu_fdt_setprop_string(fdt, nodename, "mmu-type", "riscv,sv32"); ++ qemu_fdt_setprop_string(fdt, cpu_name, "mmu-type", "riscv,sv32"); + #else +- qemu_fdt_setprop_string(fdt, nodename, "mmu-type", "riscv,sv48"); ++ qemu_fdt_setprop_string(fdt, cpu_name, "mmu-type", "riscv,sv48"); + #endif +- qemu_fdt_setprop_string(fdt, nodename, "riscv,isa", isa); +- qemu_fdt_setprop_string(fdt, nodename, "compatible", "riscv"); +- qemu_fdt_setprop_string(fdt, nodename, "status", "okay"); +- qemu_fdt_setprop_cell(fdt, nodename, "reg", cpu); +- qemu_fdt_setprop_string(fdt, nodename, "device_type", "cpu"); +- qemu_fdt_setprop_cell(fdt, nodename, "phandle", cpu_phandle); +- intc_phandle = phandle++; +- qemu_fdt_add_subnode(fdt, intc); +- qemu_fdt_setprop_cell(fdt, intc, "phandle", intc_phandle); +- qemu_fdt_setprop_string(fdt, intc, "compatible", "riscv,cpu-intc"); +- qemu_fdt_setprop(fdt, intc, "interrupt-controller", NULL, 0); +- qemu_fdt_setprop_cell(fdt, intc, "#interrupt-cells", 1); +- g_free(isa); +- g_free(intc); +- g_free(nodename); +- } ++ name = riscv_isa_string(&s->soc[socket].harts[cpu]); ++ qemu_fdt_setprop_string(fdt, cpu_name, "riscv,isa", name); ++ g_free(name); ++ qemu_fdt_setprop_string(fdt, cpu_name, "compatible", "riscv"); ++ qemu_fdt_setprop_string(fdt, cpu_name, "status", "okay"); ++ qemu_fdt_setprop_cell(fdt, cpu_name, "reg", ++ s->soc[socket].hartid_base + cpu); ++ qemu_fdt_setprop_string(fdt, cpu_name, "device_type", "cpu"); ++ riscv_socket_fdt_write_id(mc, fdt, cpu_name, socket); ++ qemu_fdt_setprop_cell(fdt, cpu_name, "phandle", cpu_phandle); ++ ++ intc_name = g_strdup_printf("%s/interrupt-controller", cpu_name); ++ qemu_fdt_add_subnode(fdt, intc_name); ++ intc_phandle = phandle++; ++ qemu_fdt_setprop_cell(fdt, intc_name, "phandle", intc_phandle); ++ qemu_fdt_setprop_string(fdt, intc_name, "compatible", ++ "riscv,cpu-intc"); ++ qemu_fdt_setprop(fdt, intc_name, "interrupt-controller", NULL, 0); ++ qemu_fdt_setprop_cell(fdt, intc_name, "#interrupt-cells", 1); ++ ++ clint_cells[cpu * 4 + 0] = cpu_to_be32(intc_phandle); ++ clint_cells[cpu * 4 + 1] = cpu_to_be32(IRQ_M_SOFT); ++ clint_cells[cpu * 4 + 2] = cpu_to_be32(intc_phandle); ++ clint_cells[cpu * 4 + 3] = cpu_to_be32(IRQ_M_TIMER); ++ ++ plic_cells[cpu * 4 + 0] = cpu_to_be32(intc_phandle); ++ plic_cells[cpu * 4 + 1] = cpu_to_be32(IRQ_M_EXT); ++ plic_cells[cpu * 4 + 2] = cpu_to_be32(intc_phandle); ++ plic_cells[cpu * 4 + 3] = cpu_to_be32(IRQ_S_EXT); ++ ++ core_name = g_strdup_printf("%s/core%d", clust_name, cpu); ++ qemu_fdt_add_subnode(fdt, core_name); ++ qemu_fdt_setprop_cell(fdt, core_name, "cpu", cpu_phandle); ++ ++ g_free(core_name); ++ g_free(intc_name); ++ g_free(cpu_name); ++ } + +- /* Add cpu-topology node */ +- qemu_fdt_add_subnode(fdt, "/cpus/cpu-map"); +- qemu_fdt_add_subnode(fdt, "/cpus/cpu-map/cluster0"); +- for (cpu = s->soc.num_harts - 1; cpu >= 0; cpu--) { +- char *core_nodename = g_strdup_printf("/cpus/cpu-map/cluster0/core%d", +- cpu); +- char *cpu_nodename = g_strdup_printf("/cpus/cpu@%d", cpu); +- uint32_t intc_phandle = qemu_fdt_get_phandle(fdt, cpu_nodename); +- qemu_fdt_add_subnode(fdt, core_nodename); +- qemu_fdt_setprop_cell(fdt, core_nodename, "cpu", intc_phandle); +- g_free(core_nodename); +- g_free(cpu_nodename); ++ addr = memmap[VIRT_DRAM].base + riscv_socket_mem_offset(mc, socket); ++ size = riscv_socket_mem_size(mc, socket); ++ mem_name = g_strdup_printf("/memory@%lx", (long)addr); ++ qemu_fdt_add_subnode(fdt, mem_name); ++ qemu_fdt_setprop_cells(fdt, mem_name, "reg", ++ addr >> 32, addr, size >> 32, size); ++ qemu_fdt_setprop_string(fdt, mem_name, "device_type", "memory"); ++ riscv_socket_fdt_write_id(mc, fdt, mem_name, socket); ++ g_free(mem_name); ++ ++ clint_addr = memmap[VIRT_CLINT].base + ++ (memmap[VIRT_CLINT].size * socket); ++ clint_name = g_strdup_printf("/soc/clint@%lx", clint_addr); ++ qemu_fdt_add_subnode(fdt, clint_name); ++ qemu_fdt_setprop_string(fdt, clint_name, "compatible", "riscv,clint0"); ++ qemu_fdt_setprop_cells(fdt, clint_name, "reg", ++ 0x0, clint_addr, 0x0, memmap[VIRT_CLINT].size); ++ qemu_fdt_setprop(fdt, clint_name, "interrupts-extended", ++ clint_cells, s->soc[socket].num_harts * sizeof(uint32_t) * 4); ++ riscv_socket_fdt_write_id(mc, fdt, clint_name, socket); ++ g_free(clint_name); ++ ++ plic_phandle[socket] = phandle++; ++ plic_addr = memmap[VIRT_PLIC].base + (memmap[VIRT_PLIC].size * socket); ++ plic_name = g_strdup_printf("/soc/plic@%lx", plic_addr); ++ qemu_fdt_add_subnode(fdt, plic_name); ++ qemu_fdt_setprop_cell(fdt, plic_name, ++ "#address-cells", FDT_PLIC_ADDR_CELLS); ++ qemu_fdt_setprop_cell(fdt, plic_name, ++ "#interrupt-cells", FDT_PLIC_INT_CELLS); ++ qemu_fdt_setprop_string(fdt, plic_name, "compatible", "riscv,plic0"); ++ qemu_fdt_setprop(fdt, plic_name, "interrupt-controller", NULL, 0); ++ qemu_fdt_setprop(fdt, plic_name, "interrupts-extended", ++ plic_cells, s->soc[socket].num_harts * sizeof(uint32_t) * 4); ++ qemu_fdt_setprop_cells(fdt, plic_name, "reg", ++ 0x0, plic_addr, 0x0, memmap[VIRT_PLIC].size); ++ qemu_fdt_setprop_cell(fdt, plic_name, "riscv,ndev", VIRTIO_NDEV); ++ riscv_socket_fdt_write_id(mc, fdt, plic_name, socket); ++ qemu_fdt_setprop_cell(fdt, plic_name, "phandle", plic_phandle[socket]); ++ g_free(plic_name); ++ ++ g_free(clint_cells); ++ g_free(plic_cells); ++ g_free(clust_name); + } + +- cells = g_new0(uint32_t, s->soc.num_harts * 4); +- for (cpu = 0; cpu < s->soc.num_harts; cpu++) { +- nodename = +- g_strdup_printf("/cpus/cpu@%d/interrupt-controller", cpu); +- uint32_t intc_phandle = qemu_fdt_get_phandle(fdt, nodename); +- cells[cpu * 4 + 0] = cpu_to_be32(intc_phandle); +- cells[cpu * 4 + 1] = cpu_to_be32(IRQ_M_SOFT); +- cells[cpu * 4 + 2] = cpu_to_be32(intc_phandle); +- cells[cpu * 4 + 3] = cpu_to_be32(IRQ_M_TIMER); +- g_free(nodename); +- } +- nodename = g_strdup_printf("/soc/clint@%lx", +- (long)memmap[VIRT_CLINT].base); +- qemu_fdt_add_subnode(fdt, nodename); +- qemu_fdt_setprop_string(fdt, nodename, "compatible", "riscv,clint0"); +- qemu_fdt_setprop_cells(fdt, nodename, "reg", +- 0x0, memmap[VIRT_CLINT].base, +- 0x0, memmap[VIRT_CLINT].size); +- qemu_fdt_setprop(fdt, nodename, "interrupts-extended", +- cells, s->soc.num_harts * sizeof(uint32_t) * 4); +- g_free(cells); +- g_free(nodename); +- +- plic_phandle = phandle++; +- cells = g_new0(uint32_t, s->soc.num_harts * 4); +- for (cpu = 0; cpu < s->soc.num_harts; cpu++) { +- nodename = +- g_strdup_printf("/cpus/cpu@%d/interrupt-controller", cpu); +- uint32_t intc_phandle = qemu_fdt_get_phandle(fdt, nodename); +- cells[cpu * 4 + 0] = cpu_to_be32(intc_phandle); +- cells[cpu * 4 + 1] = cpu_to_be32(IRQ_M_EXT); +- cells[cpu * 4 + 2] = cpu_to_be32(intc_phandle); +- cells[cpu * 4 + 3] = cpu_to_be32(IRQ_S_EXT); +- g_free(nodename); ++ for (socket = 0; socket < riscv_socket_count(mc); socket++) { ++ if (socket == 0) { ++ plic_mmio_phandle = plic_phandle[socket]; ++ plic_virtio_phandle = plic_phandle[socket]; ++ plic_pcie_phandle = plic_phandle[socket]; ++ } ++ if (socket == 1) { ++ plic_virtio_phandle = plic_phandle[socket]; ++ plic_pcie_phandle = plic_phandle[socket]; ++ } ++ if (socket == 2) { ++ plic_pcie_phandle = plic_phandle[socket]; ++ } + } +- nodename = g_strdup_printf("/soc/interrupt-controller@%lx", +- (long)memmap[VIRT_PLIC].base); +- qemu_fdt_add_subnode(fdt, nodename); +- qemu_fdt_setprop_cell(fdt, nodename, "#address-cells", +- FDT_PLIC_ADDR_CELLS); +- qemu_fdt_setprop_cell(fdt, nodename, "#interrupt-cells", +- FDT_PLIC_INT_CELLS); +- qemu_fdt_setprop_string(fdt, nodename, "compatible", "riscv,plic0"); +- qemu_fdt_setprop(fdt, nodename, "interrupt-controller", NULL, 0); +- qemu_fdt_setprop(fdt, nodename, "interrupts-extended", +- cells, s->soc.num_harts * sizeof(uint32_t) * 4); +- qemu_fdt_setprop_cells(fdt, nodename, "reg", +- 0x0, memmap[VIRT_PLIC].base, +- 0x0, memmap[VIRT_PLIC].size); +- qemu_fdt_setprop_cell(fdt, nodename, "riscv,ndev", VIRTIO_NDEV); +- qemu_fdt_setprop_cell(fdt, nodename, "phandle", plic_phandle); +- plic_phandle = qemu_fdt_get_phandle(fdt, nodename); +- g_free(cells); +- g_free(nodename); ++ ++ riscv_socket_fdt_write_distance_matrix(mc, fdt); + + for (i = 0; i < VIRTIO_COUNT; i++) { +- nodename = g_strdup_printf("/virtio_mmio@%lx", ++ name = g_strdup_printf("/soc/virtio_mmio@%lx", + (long)(memmap[VIRT_VIRTIO].base + i * memmap[VIRT_VIRTIO].size)); +- qemu_fdt_add_subnode(fdt, nodename); +- qemu_fdt_setprop_string(fdt, nodename, "compatible", "virtio,mmio"); +- qemu_fdt_setprop_cells(fdt, nodename, "reg", ++ qemu_fdt_add_subnode(fdt, name); ++ qemu_fdt_setprop_string(fdt, name, "compatible", "virtio,mmio"); ++ qemu_fdt_setprop_cells(fdt, name, "reg", + 0x0, memmap[VIRT_VIRTIO].base + i * memmap[VIRT_VIRTIO].size, + 0x0, memmap[VIRT_VIRTIO].size); +- qemu_fdt_setprop_cell(fdt, nodename, "interrupt-parent", plic_phandle); +- qemu_fdt_setprop_cell(fdt, nodename, "interrupts", VIRTIO_IRQ + i); +- g_free(nodename); ++ qemu_fdt_setprop_cell(fdt, name, "interrupt-parent", ++ plic_virtio_phandle); ++ qemu_fdt_setprop_cell(fdt, name, "interrupts", VIRTIO_IRQ + i); ++ g_free(name); + } + +- nodename = g_strdup_printf("/soc/pci@%lx", ++ name = g_strdup_printf("/soc/pci@%lx", + (long) memmap[VIRT_PCIE_ECAM].base); +- qemu_fdt_add_subnode(fdt, nodename); +- qemu_fdt_setprop_cell(fdt, nodename, "#address-cells", +- FDT_PCI_ADDR_CELLS); +- qemu_fdt_setprop_cell(fdt, nodename, "#interrupt-cells", +- FDT_PCI_INT_CELLS); +- qemu_fdt_setprop_cell(fdt, nodename, "#size-cells", 0x2); +- 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, +- memmap[VIRT_PCIE_ECAM].size / +- PCIE_MMCFG_SIZE_MIN - 1); +- qemu_fdt_setprop(fdt, nodename, "dma-coherent", NULL, 0); +- qemu_fdt_setprop_cells(fdt, nodename, "reg", 0, memmap[VIRT_PCIE_ECAM].base, +- 0, memmap[VIRT_PCIE_ECAM].size); +- qemu_fdt_setprop_sized_cells(fdt, nodename, "ranges", ++ qemu_fdt_add_subnode(fdt, name); ++ qemu_fdt_setprop_cell(fdt, name, "#address-cells", FDT_PCI_ADDR_CELLS); ++ qemu_fdt_setprop_cell(fdt, name, "#interrupt-cells", FDT_PCI_INT_CELLS); ++ qemu_fdt_setprop_cell(fdt, name, "#size-cells", 0x2); ++ qemu_fdt_setprop_string(fdt, name, "compatible", "pci-host-ecam-generic"); ++ qemu_fdt_setprop_string(fdt, name, "device_type", "pci"); ++ qemu_fdt_setprop_cell(fdt, name, "linux,pci-domain", 0); ++ qemu_fdt_setprop_cells(fdt, name, "bus-range", 0, ++ memmap[VIRT_PCIE_ECAM].size / PCIE_MMCFG_SIZE_MIN - 1); ++ qemu_fdt_setprop(fdt, name, "dma-coherent", NULL, 0); ++ qemu_fdt_setprop_cells(fdt, name, "reg", 0, ++ memmap[VIRT_PCIE_ECAM].base, 0, memmap[VIRT_PCIE_ECAM].size); ++ qemu_fdt_setprop_sized_cells(fdt, name, "ranges", + 1, FDT_PCI_RANGE_IOPORT, 2, 0, + 2, memmap[VIRT_PCIE_PIO].base, 2, memmap[VIRT_PCIE_PIO].size, + 1, FDT_PCI_RANGE_MMIO, + 2, memmap[VIRT_PCIE_MMIO].base, + 2, memmap[VIRT_PCIE_MMIO].base, 2, memmap[VIRT_PCIE_MMIO].size); +- create_pcie_irq_map(fdt, nodename, plic_phandle); +- g_free(nodename); ++ create_pcie_irq_map(fdt, name, plic_pcie_phandle); ++ g_free(name); + + test_phandle = phandle++; +- nodename = g_strdup_printf("/test@%lx", ++ name = g_strdup_printf("/soc/test@%lx", + (long)memmap[VIRT_TEST].base); +- qemu_fdt_add_subnode(fdt, nodename); ++ qemu_fdt_add_subnode(fdt, name); + { + const char compat[] = "sifive,test1\0sifive,test0\0syscon"; +- qemu_fdt_setprop(fdt, nodename, "compatible", compat, sizeof(compat)); ++ qemu_fdt_setprop(fdt, name, "compatible", compat, sizeof(compat)); + } +- qemu_fdt_setprop_cells(fdt, nodename, "reg", ++ qemu_fdt_setprop_cells(fdt, name, "reg", + 0x0, memmap[VIRT_TEST].base, + 0x0, memmap[VIRT_TEST].size); +- qemu_fdt_setprop_cell(fdt, nodename, "phandle", test_phandle); +- test_phandle = qemu_fdt_get_phandle(fdt, nodename); +- g_free(nodename); +- +- nodename = g_strdup_printf("/reboot"); +- qemu_fdt_add_subnode(fdt, nodename); +- qemu_fdt_setprop_string(fdt, nodename, "compatible", "syscon-reboot"); +- qemu_fdt_setprop_cell(fdt, nodename, "regmap", test_phandle); +- qemu_fdt_setprop_cell(fdt, nodename, "offset", 0x0); +- qemu_fdt_setprop_cell(fdt, nodename, "value", FINISHER_RESET); +- g_free(nodename); +- +- nodename = g_strdup_printf("/poweroff"); +- qemu_fdt_add_subnode(fdt, nodename); +- qemu_fdt_setprop_string(fdt, nodename, "compatible", "syscon-poweroff"); +- qemu_fdt_setprop_cell(fdt, nodename, "regmap", test_phandle); +- qemu_fdt_setprop_cell(fdt, nodename, "offset", 0x0); +- qemu_fdt_setprop_cell(fdt, nodename, "value", FINISHER_PASS); +- g_free(nodename); +- +- nodename = g_strdup_printf("/uart@%lx", +- (long)memmap[VIRT_UART0].base); +- qemu_fdt_add_subnode(fdt, nodename); +- qemu_fdt_setprop_string(fdt, nodename, "compatible", "ns16550a"); +- qemu_fdt_setprop_cells(fdt, nodename, "reg", ++ qemu_fdt_setprop_cell(fdt, name, "phandle", test_phandle); ++ test_phandle = qemu_fdt_get_phandle(fdt, name); ++ g_free(name); ++ ++ name = g_strdup_printf("/soc/reboot"); ++ qemu_fdt_add_subnode(fdt, name); ++ qemu_fdt_setprop_string(fdt, name, "compatible", "syscon-reboot"); ++ qemu_fdt_setprop_cell(fdt, name, "regmap", test_phandle); ++ qemu_fdt_setprop_cell(fdt, name, "offset", 0x0); ++ qemu_fdt_setprop_cell(fdt, name, "value", FINISHER_RESET); ++ g_free(name); ++ ++ name = g_strdup_printf("/soc/poweroff"); ++ qemu_fdt_add_subnode(fdt, name); ++ qemu_fdt_setprop_string(fdt, name, "compatible", "syscon-poweroff"); ++ qemu_fdt_setprop_cell(fdt, name, "regmap", test_phandle); ++ qemu_fdt_setprop_cell(fdt, name, "offset", 0x0); ++ qemu_fdt_setprop_cell(fdt, name, "value", FINISHER_PASS); ++ g_free(name); ++ ++ name = g_strdup_printf("/soc/uart@%lx", (long)memmap[VIRT_UART0].base); ++ qemu_fdt_add_subnode(fdt, name); ++ qemu_fdt_setprop_string(fdt, name, "compatible", "ns16550a"); ++ qemu_fdt_setprop_cells(fdt, name, "reg", + 0x0, memmap[VIRT_UART0].base, + 0x0, memmap[VIRT_UART0].size); +- qemu_fdt_setprop_cell(fdt, nodename, "clock-frequency", 3686400); +- qemu_fdt_setprop_cell(fdt, nodename, "interrupt-parent", plic_phandle); +- qemu_fdt_setprop_cell(fdt, nodename, "interrupts", UART0_IRQ); ++ qemu_fdt_setprop_cell(fdt, name, "clock-frequency", 3686400); ++ qemu_fdt_setprop_cell(fdt, name, "interrupt-parent", plic_mmio_phandle); ++ qemu_fdt_setprop_cell(fdt, name, "interrupts", UART0_IRQ); + + qemu_fdt_add_subnode(fdt, "/chosen"); +- qemu_fdt_setprop_string(fdt, "/chosen", "stdout-path", nodename); ++ qemu_fdt_setprop_string(fdt, "/chosen", "stdout-path", name); + if (cmdline) { + qemu_fdt_setprop_string(fdt, "/chosen", "bootargs", cmdline); + } +- g_free(nodename); +- +- nodename = g_strdup_printf("/rtc@%lx", +- (long)memmap[VIRT_RTC].base); +- qemu_fdt_add_subnode(fdt, nodename); +- qemu_fdt_setprop_string(fdt, nodename, "compatible", +- "google,goldfish-rtc"); +- qemu_fdt_setprop_cells(fdt, nodename, "reg", ++ g_free(name); ++ ++ name = g_strdup_printf("/soc/rtc@%lx", (long)memmap[VIRT_RTC].base); ++ qemu_fdt_add_subnode(fdt, name); ++ qemu_fdt_setprop_string(fdt, name, "compatible", "google,goldfish-rtc"); ++ qemu_fdt_setprop_cells(fdt, name, "reg", + 0x0, memmap[VIRT_RTC].base, + 0x0, memmap[VIRT_RTC].size); +- qemu_fdt_setprop_cell(fdt, nodename, "interrupt-parent", plic_phandle); +- qemu_fdt_setprop_cell(fdt, nodename, "interrupts", RTC_IRQ); +- g_free(nodename); +- +- nodename = g_strdup_printf("/flash@%" PRIx64, flashbase); +- qemu_fdt_add_subnode(s->fdt, nodename); +- qemu_fdt_setprop_string(s->fdt, nodename, "compatible", "cfi-flash"); +- qemu_fdt_setprop_sized_cells(s->fdt, nodename, "reg", ++ qemu_fdt_setprop_cell(fdt, name, "interrupt-parent", plic_mmio_phandle); ++ qemu_fdt_setprop_cell(fdt, name, "interrupts", RTC_IRQ); ++ g_free(name); ++ ++ name = g_strdup_printf("/soc/flash@%" PRIx64, flashbase); ++ qemu_fdt_add_subnode(s->fdt, name); ++ qemu_fdt_setprop_string(s->fdt, name, "compatible", "cfi-flash"); ++ qemu_fdt_setprop_sized_cells(s->fdt, name, "reg", + 2, flashbase, 2, flashsize, + 2, flashbase + flashsize, 2, flashsize); +- qemu_fdt_setprop_cell(s->fdt, nodename, "bank-width", 4); +- g_free(nodename); ++ qemu_fdt_setprop_cell(s->fdt, name, "bank-width", 4); ++ g_free(name); + } + +- + static inline DeviceState *gpex_pcie_init(MemoryRegion *sys_mem, + hwaddr ecam_base, hwaddr ecam_size, + hwaddr mmio_base, hwaddr mmio_size, +@@ -478,21 +493,100 @@ static void riscv_virt_board_init(MachineState *machine) + MemoryRegion *system_memory = get_system_memory(); + MemoryRegion *main_mem = g_new(MemoryRegion, 1); + MemoryRegion *mask_rom = g_new(MemoryRegion, 1); +- char *plic_hart_config; ++ char *plic_hart_config, *soc_name; + size_t plic_hart_config_len; + target_ulong start_addr = memmap[VIRT_DRAM].base; +- int i; +- unsigned int smp_cpus = machine->smp.cpus; +- +- /* Initialize SOC */ +- object_initialize_child(OBJECT(machine), "soc", &s->soc, sizeof(s->soc), +- TYPE_RISCV_HART_ARRAY, &error_abort, NULL); +- object_property_set_str(OBJECT(&s->soc), machine->cpu_type, "cpu-type", +- &error_abort); +- object_property_set_int(OBJECT(&s->soc), smp_cpus, "num-harts", +- &error_abort); +- object_property_set_bool(OBJECT(&s->soc), true, "realized", +- &error_abort); ++ DeviceState *mmio_plic, *virtio_plic, *pcie_plic; ++ int i, j, base_hartid, hart_count; ++ ++ /* Check socket count limit */ ++ if (VIRT_SOCKETS_MAX < riscv_socket_count(machine)) { ++ error_report("number of sockets/nodes should be less than %d", ++ VIRT_SOCKETS_MAX); ++ exit(1); ++ } ++ ++ /* Initialize sockets */ ++ mmio_plic = virtio_plic = pcie_plic = NULL; ++ for (i = 0; i < riscv_socket_count(machine); i++) { ++ if (!riscv_socket_check_hartids(machine, i)) { ++ error_report("discontinuous hartids in socket%d", i); ++ exit(1); ++ } ++ ++ base_hartid = riscv_socket_first_hartid(machine, i); ++ if (base_hartid < 0) { ++ error_report("can't find hartid base for socket%d", i); ++ exit(1); ++ } ++ ++ hart_count = riscv_socket_hart_count(machine, i); ++ if (hart_count < 0) { ++ error_report("can't find hart count for socket%d", i); ++ exit(1); ++ } ++ ++ soc_name = g_strdup_printf("soc%d", i); ++ object_initialize_child(OBJECT(machine), soc_name, &s->soc[i], ++ sizeof(s->soc[i]), TYPE_RISCV_HART_ARRAY, &error_abort, NULL); ++ g_free(soc_name); ++ object_property_set_str(OBJECT(&s->soc[i]), ++ machine->cpu_type, "cpu-type", &error_abort); ++ object_property_set_int(OBJECT(&s->soc[i]), ++ base_hartid, "hartid-base", &error_abort); ++ object_property_set_int(OBJECT(&s->soc[i]), ++ hart_count, "num-harts", &error_abort); ++ object_property_set_bool(OBJECT(&s->soc[i]), ++ true, "realized", &error_abort); ++ ++ /* Per-socket CLINT */ ++ sifive_clint_create( ++ memmap[VIRT_CLINT].base + i * memmap[VIRT_CLINT].size, ++ memmap[VIRT_CLINT].size, base_hartid, hart_count, ++ SIFIVE_SIP_BASE, SIFIVE_TIMECMP_BASE, SIFIVE_TIME_BASE, true); ++ ++ /* Per-socket PLIC hart topology configuration string */ ++ plic_hart_config_len = ++ (strlen(VIRT_PLIC_HART_CONFIG) + 1) * hart_count; ++ plic_hart_config = g_malloc0(plic_hart_config_len); ++ for (j = 0; j < hart_count; j++) { ++ if (j != 0) { ++ strncat(plic_hart_config, ",", plic_hart_config_len); ++ } ++ strncat(plic_hart_config, VIRT_PLIC_HART_CONFIG, ++ plic_hart_config_len); ++ plic_hart_config_len -= (strlen(VIRT_PLIC_HART_CONFIG) + 1); ++ } ++ ++ /* Per-socket PLIC */ ++ s->plic[i] = sifive_plic_create( ++ memmap[VIRT_PLIC].base + i * memmap[VIRT_PLIC].size, ++ plic_hart_config, base_hartid, ++ VIRT_PLIC_NUM_SOURCES, ++ VIRT_PLIC_NUM_PRIORITIES, ++ VIRT_PLIC_PRIORITY_BASE, ++ VIRT_PLIC_PENDING_BASE, ++ VIRT_PLIC_ENABLE_BASE, ++ VIRT_PLIC_ENABLE_STRIDE, ++ VIRT_PLIC_CONTEXT_BASE, ++ VIRT_PLIC_CONTEXT_STRIDE, ++ memmap[VIRT_PLIC].size); ++ g_free(plic_hart_config); ++ ++ /* Try to use different PLIC instance based device type */ ++ if (i == 0) { ++ mmio_plic = s->plic[i]; ++ virtio_plic = s->plic[i]; ++ pcie_plic = s->plic[i]; ++ } ++ if (i == 1) { ++ virtio_plic = s->plic[i]; ++ pcie_plic = s->plic[i]; ++ } ++ if (i == 2) { ++ pcie_plic = s->plic[i]; ++ } ++ } + + /* register system main memory (actual RAM) */ + memory_region_init_ram(main_mem, NULL, "riscv_virt_board.ram", +@@ -571,38 +665,14 @@ static void riscv_virt_board_init(MachineState *machine) + memmap[VIRT_MROM].base + sizeof(reset_vec), + &address_space_memory); + +- /* create PLIC hart topology configuration string */ +- plic_hart_config_len = (strlen(VIRT_PLIC_HART_CONFIG) + 1) * smp_cpus; +- plic_hart_config = g_malloc0(plic_hart_config_len); +- for (i = 0; i < smp_cpus; i++) { +- if (i != 0) { +- strncat(plic_hart_config, ",", plic_hart_config_len); +- } +- strncat(plic_hart_config, VIRT_PLIC_HART_CONFIG, plic_hart_config_len); +- plic_hart_config_len -= (strlen(VIRT_PLIC_HART_CONFIG) + 1); +- } +- +- /* MMIO */ +- s->plic = sifive_plic_create(memmap[VIRT_PLIC].base, +- plic_hart_config, 0, +- VIRT_PLIC_NUM_SOURCES, +- VIRT_PLIC_NUM_PRIORITIES, +- VIRT_PLIC_PRIORITY_BASE, +- VIRT_PLIC_PENDING_BASE, +- VIRT_PLIC_ENABLE_BASE, +- VIRT_PLIC_ENABLE_STRIDE, +- VIRT_PLIC_CONTEXT_BASE, +- VIRT_PLIC_CONTEXT_STRIDE, +- memmap[VIRT_PLIC].size); +- sifive_clint_create(memmap[VIRT_CLINT].base, +- memmap[VIRT_CLINT].size, 0, smp_cpus, +- SIFIVE_SIP_BASE, SIFIVE_TIMECMP_BASE, SIFIVE_TIME_BASE, true); ++ /* SiFive Test MMIO device */ + sifive_test_create(memmap[VIRT_TEST].base); + ++ /* VirtIO MMIO devices */ + for (i = 0; i < VIRTIO_COUNT; i++) { + sysbus_create_simple("virtio-mmio", + memmap[VIRT_VIRTIO].base + i * memmap[VIRT_VIRTIO].size, +- qdev_get_gpio_in(DEVICE(s->plic), VIRTIO_IRQ + i)); ++ qdev_get_gpio_in(DEVICE(virtio_plic), VIRTIO_IRQ + i)); + } + + gpex_pcie_init(system_memory, +@@ -611,14 +681,14 @@ static void riscv_virt_board_init(MachineState *machine) + memmap[VIRT_PCIE_MMIO].base, + memmap[VIRT_PCIE_MMIO].size, + memmap[VIRT_PCIE_PIO].base, +- DEVICE(s->plic), true); ++ DEVICE(pcie_plic), true); + + serial_mm_init(system_memory, memmap[VIRT_UART0].base, +- 0, qdev_get_gpio_in(DEVICE(s->plic), UART0_IRQ), 399193, ++ 0, qdev_get_gpio_in(DEVICE(mmio_plic), UART0_IRQ), 399193, + serial_hd(0), DEVICE_LITTLE_ENDIAN); + + sysbus_create_simple("goldfish_rtc", memmap[VIRT_RTC].base, +- qdev_get_gpio_in(DEVICE(s->plic), RTC_IRQ)); ++ qdev_get_gpio_in(DEVICE(mmio_plic), RTC_IRQ)); + + virt_flash_create(s); + +@@ -628,8 +698,6 @@ static void riscv_virt_board_init(MachineState *machine) + drive_get(IF_PFLASH, 0, i)); + } + virt_flash_map(s, system_memory); +- +- g_free(plic_hart_config); + } + + static void riscv_virt_machine_instance_init(Object *obj) +@@ -642,9 +710,13 @@ static void riscv_virt_machine_class_init(ObjectClass *oc, void *data) + + mc->desc = "RISC-V VirtIO board"; + mc->init = riscv_virt_board_init; +- mc->max_cpus = 8; ++ mc->max_cpus = VIRT_CPUS_MAX; + mc->default_cpu_type = VIRT_CPU; + mc->pci_allow_0_address = true; ++ mc->possible_cpu_arch_ids = riscv_numa_possible_cpu_arch_ids; ++ mc->cpu_index_to_instance_props = riscv_numa_cpu_index_to_props; ++ mc->get_default_cpu_node_id = riscv_numa_get_default_cpu_node_id; ++ mc->numa_mem_supported = true; + } + + static const TypeInfo riscv_virt_machine_typeinfo = { +diff --git a/include/hw/riscv/virt.h b/include/hw/riscv/virt.h +index e69355efaf..1beacd7666 100644 +--- a/include/hw/riscv/virt.h ++++ b/include/hw/riscv/virt.h +@@ -23,6 +23,9 @@ + #include "hw/sysbus.h" + #include "hw/block/flash.h" + ++#define VIRT_CPUS_MAX 8 ++#define VIRT_SOCKETS_MAX 8 ++ + #define TYPE_RISCV_VIRT_MACHINE MACHINE_TYPE_NAME("virt") + #define RISCV_VIRT_MACHINE(obj) \ + OBJECT_CHECK(RISCVVirtState, (obj), TYPE_RISCV_VIRT_MACHINE) +@@ -32,8 +35,8 @@ typedef struct { + MachineState parent; + + /*< public >*/ +- RISCVHartArrayState soc; +- DeviceState *plic; ++ RISCVHartArrayState soc[VIRT_SOCKETS_MAX]; ++ DeviceState *plic[VIRT_SOCKETS_MAX]; + PFlashCFI01 *flash[2]; + + void *fdt; +@@ -74,6 +77,8 @@ enum { + #define VIRT_PLIC_ENABLE_STRIDE 0x80 + #define VIRT_PLIC_CONTEXT_BASE 0x200000 + #define VIRT_PLIC_CONTEXT_STRIDE 0x1000 ++#define VIRT_PLIC_SIZE(__num_context) \ ++ (VIRT_PLIC_CONTEXT_BASE + (__num_context) * VIRT_PLIC_CONTEXT_STRIDE) + + #define FDT_PCI_ADDR_CELLS 3 + #define FDT_PCI_INT_CELLS 1 +-- +2.23.0 + diff --git a/hw-timer-exynos4210_mct-Replace-hw_error-by-qemu_log.patch b/hw-timer-exynos4210_mct-Replace-hw_error-by-qemu_log.patch new file mode 100644 index 0000000000000000000000000000000000000000..7d4e6df5954e83114ecbc8f5f053fc742e1fe7a6 --- /dev/null +++ b/hw-timer-exynos4210_mct-Replace-hw_error-by-qemu_log.patch @@ -0,0 +1,81 @@ +From a50fe66846d1d02065265f1e54c2b0007f8cb609 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Mon, 18 May 2020 16:03:09 +0200 +Subject: [PATCH 629/709] hw/timer/exynos4210_mct: Replace hw_error() by + qemu_log_mask() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +hw_error() calls exit(). This a bit overkill when we can log +the accesses as unimplemented or guest error. + +When fuzzing the devices, we don't want the whole process to +exit. Replace some hw_error() calls by qemu_log_mask(). + +Per the datasheet "Exynos 4412 RISC Microprocessor Rev 1.00" +Chapter 25 "Multi Core Timer (MCT)" figure 1 and table 4, +the default value on the APB bus is 0. + +Signed-off-by: Philippe Mathieu-Daudé +Reviewed-by: Alistair Francis +Message-id: 20200518140309.5220-5-f4bug@amsat.org +Signed-off-by: Peter Maydell +--- + hw/timer/exynos4210_mct.c | 12 +++++------- + 1 file changed, 5 insertions(+), 7 deletions(-) + +diff --git a/hw/timer/exynos4210_mct.c b/hw/timer/exynos4210_mct.c +index 570cf7075b..29a4b10676 100644 +--- a/hw/timer/exynos4210_mct.c ++++ b/hw/timer/exynos4210_mct.c +@@ -54,7 +54,6 @@ + + #include "qemu/osdep.h" + #include "qemu/log.h" +-#include "hw/hw.h" + #include "hw/sysbus.h" + #include "migration/vmstate.h" + #include "qemu/timer.h" +@@ -62,7 +61,6 @@ + #include "hw/ptimer.h" + + #include "hw/arm/exynos4210.h" +-#include "hw/hw.h" + #include "hw/irq.h" + + //#define DEBUG_MCT +@@ -1062,7 +1060,7 @@ static uint64_t exynos4210_mct_read(void *opaque, hwaddr offset, + int index; + int shift; + uint64_t count; +- uint32_t value; ++ uint32_t value = 0; + int lt_i; + + switch (offset) { +@@ -1158,8 +1156,8 @@ static uint64_t exynos4210_mct_read(void *opaque, hwaddr offset, + break; + + default: +- hw_error("exynos4210.mct: bad read offset " +- TARGET_FMT_plx "\n", offset); ++ qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIX "\n", ++ __func__, offset); + break; + } + return value; +@@ -1484,8 +1482,8 @@ static void exynos4210_mct_write(void *opaque, hwaddr offset, + break; + + default: +- hw_error("exynos4210.mct: bad write offset " +- TARGET_FMT_plx "\n", offset); ++ qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIX "\n", ++ __func__, offset); + break; + } + } +-- +2.23.0 + diff --git a/hw-timer-nrf51_timer-Add-trace-event-of-counter-valu.patch b/hw-timer-nrf51_timer-Add-trace-event-of-counter-valu.patch new file mode 100644 index 0000000000000000000000000000000000000000..208c281a8702ed2df51a3efce73cd4aeb641dd97 --- /dev/null +++ b/hw-timer-nrf51_timer-Add-trace-event-of-counter-valu.patch @@ -0,0 +1,47 @@ +From 602ab789363741aee29aeacc6b024af72161f3f7 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Mon, 4 May 2020 09:28:22 +0200 +Subject: [PATCH 364/709] hw/timer/nrf51_timer: Add trace event of counter + value update +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Add trace event to display timer's counter value updates. + +Signed-off-by: Philippe Mathieu-Daudé +Reviewed-by: Richard Henderson +Message-id: 20200504072822.18799-5-f4bug@amsat.org +Signed-off-by: Peter Maydell +--- + hw/timer/nrf51_timer.c | 1 + + hw/timer/trace-events | 1 + + 2 files changed, 2 insertions(+) + +diff --git a/hw/timer/nrf51_timer.c b/hw/timer/nrf51_timer.c +index 38cea0542e..42be79c736 100644 +--- a/hw/timer/nrf51_timer.c ++++ b/hw/timer/nrf51_timer.c +@@ -240,6 +240,7 @@ static void nrf51_timer_write(void *opaque, hwaddr offset, + + idx = (offset - NRF51_TIMER_TASK_CAPTURE_0) / 4; + s->cc[idx] = s->counter; ++ trace_nrf51_timer_set_count(s->id, idx, s->counter); + } + break; + case NRF51_TIMER_EVENT_COMPARE_0 ... NRF51_TIMER_EVENT_COMPARE_3: +diff --git a/hw/timer/trace-events b/hw/timer/trace-events +index 43b605cc75..80ea197594 100644 +--- a/hw/timer/trace-events ++++ b/hw/timer/trace-events +@@ -69,6 +69,7 @@ cmsdk_apb_dualtimer_reset(void) "CMSDK APB dualtimer: reset" + # nrf51_timer.c + nrf51_timer_read(uint8_t timer_id, uint64_t addr, uint32_t value, unsigned size) "timer %u read addr 0x%" PRIx64 " data 0x%" PRIx32 " size %u" + nrf51_timer_write(uint8_t timer_id, uint64_t addr, uint32_t value, unsigned size) "timer %u write addr 0x%" PRIx64 " data 0x%" PRIx32 " size %u" ++nrf51_timer_set_count(uint8_t timer_id, uint8_t counter_id, uint32_t value) "timer %u counter %u count 0x%" PRIx32 + + # bcm2835_systmr.c + bcm2835_systmr_irq(bool enable) "timer irq state %u" +-- +2.23.0 + diff --git a/hw-timer-nrf51_timer-Display-timer-ID-in-trace-event.patch b/hw-timer-nrf51_timer-Display-timer-ID-in-trace-event.patch new file mode 100644 index 0000000000000000000000000000000000000000..31c842c753fcbc85abff95751660a303dff84a66 --- /dev/null +++ b/hw-timer-nrf51_timer-Display-timer-ID-in-trace-event.patch @@ -0,0 +1,119 @@ +From 27d6dea3d702b4f9cefacfc8438a9478c03092e4 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Mon, 4 May 2020 09:28:21 +0200 +Subject: [PATCH 363/709] hw/timer/nrf51_timer: Display timer ID in trace + events +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The NRF51 series SoC have 3 timer peripherals, each having +4 counters. To help differentiate which peripheral is accessed, +display the timer ID in the trace events. + +Signed-off-by: Philippe Mathieu-Daudé +Reviewed-by: Richard Henderson +Message-id: 20200504072822.18799-4-f4bug@amsat.org +Signed-off-by: Peter Maydell +--- + hw/arm/nrf51_soc.c | 5 +++++ + hw/timer/nrf51_timer.c | 11 +++++++++-- + hw/timer/trace-events | 4 ++-- + include/hw/timer/nrf51_timer.h | 1 + + 4 files changed, 17 insertions(+), 4 deletions(-) + +diff --git a/hw/arm/nrf51_soc.c b/hw/arm/nrf51_soc.c +index e50473fd19..71309e53cc 100644 +--- a/hw/arm/nrf51_soc.c ++++ b/hw/arm/nrf51_soc.c +@@ -150,6 +150,11 @@ static void nrf51_soc_realize(DeviceState *dev_soc, Error **errp) + + /* TIMER */ + for (i = 0; i < NRF51_NUM_TIMERS; i++) { ++ object_property_set_uint(OBJECT(&s->timer[i]), i, "id", &err); ++ if (err) { ++ error_propagate(errp, err); ++ return; ++ } + object_property_set_bool(OBJECT(&s->timer[i]), true, "realized", &err); + if (err) { + error_propagate(errp, err); +diff --git a/hw/timer/nrf51_timer.c b/hw/timer/nrf51_timer.c +index bc82c85a6f..38cea0542e 100644 +--- a/hw/timer/nrf51_timer.c ++++ b/hw/timer/nrf51_timer.c +@@ -17,6 +17,7 @@ + #include "hw/arm/nrf51.h" + #include "hw/irq.h" + #include "hw/timer/nrf51_timer.h" ++#include "hw/qdev-properties.h" + #include "migration/vmstate.h" + #include "trace.h" + +@@ -185,7 +186,7 @@ static uint64_t nrf51_timer_read(void *opaque, hwaddr offset, unsigned int size) + __func__, offset); + } + +- trace_nrf51_timer_read(offset, r, size); ++ trace_nrf51_timer_read(s->id, offset, r, size); + + return r; + } +@@ -197,7 +198,7 @@ static void nrf51_timer_write(void *opaque, hwaddr offset, + uint64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); + size_t idx; + +- trace_nrf51_timer_write(offset, value, size); ++ trace_nrf51_timer_write(s->id, offset, value, size); + + switch (offset) { + case NRF51_TIMER_TASK_START: +@@ -372,12 +373,18 @@ static const VMStateDescription vmstate_nrf51_timer = { + } + }; + ++static Property nrf51_timer_properties[] = { ++ DEFINE_PROP_UINT8("id", NRF51TimerState, id, 0), ++ DEFINE_PROP_END_OF_LIST(), ++}; ++ + static void nrf51_timer_class_init(ObjectClass *klass, void *data) + { + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->reset = nrf51_timer_reset; + dc->vmsd = &vmstate_nrf51_timer; ++ device_class_set_props(dc, nrf51_timer_properties); + } + + static const TypeInfo nrf51_timer_info = { +diff --git a/hw/timer/trace-events b/hw/timer/trace-events +index 29fda7870e..43b605cc75 100644 +--- a/hw/timer/trace-events ++++ b/hw/timer/trace-events +@@ -67,8 +67,8 @@ cmsdk_apb_dualtimer_write(uint64_t offset, uint64_t data, unsigned size) "CMSDK + cmsdk_apb_dualtimer_reset(void) "CMSDK APB dualtimer: reset" + + # nrf51_timer.c +-nrf51_timer_read(uint64_t addr, uint32_t value, unsigned size) "read addr 0x%" PRIx64 " data 0x%" PRIx32 " size %u" +-nrf51_timer_write(uint64_t addr, uint32_t value, unsigned size) "write addr 0x%" PRIx64 " data 0x%" PRIx32 " size %u" ++nrf51_timer_read(uint8_t timer_id, uint64_t addr, uint32_t value, unsigned size) "timer %u read addr 0x%" PRIx64 " data 0x%" PRIx32 " size %u" ++nrf51_timer_write(uint8_t timer_id, uint64_t addr, uint32_t value, unsigned size) "timer %u write addr 0x%" PRIx64 " data 0x%" PRIx32 " size %u" + + # bcm2835_systmr.c + bcm2835_systmr_irq(bool enable) "timer irq state %u" +diff --git a/include/hw/timer/nrf51_timer.h b/include/hw/timer/nrf51_timer.h +index 85cad2300d..eb6815f21d 100644 +--- a/include/hw/timer/nrf51_timer.h ++++ b/include/hw/timer/nrf51_timer.h +@@ -59,6 +59,7 @@ typedef struct NRF51TimerState { + MemoryRegion iomem; + qemu_irq irq; + ++ uint8_t id; + QEMUTimer timer; + int64_t timer_start_ns; + int64_t update_counter_ns; +-- +2.23.0 + diff --git a/hw-timer-pxa2xx_timer-Add-assertion-to-silent-static.patch b/hw-timer-pxa2xx_timer-Add-assertion-to-silent-static.patch new file mode 100644 index 0000000000000000000000000000000000000000..05de9d6427f63a0820897d2eca3d42107e5746ee --- /dev/null +++ b/hw-timer-pxa2xx_timer-Add-assertion-to-silent-static.patch @@ -0,0 +1,64 @@ +From e702fba83108519618046a2a09235a62e3a81595 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Wed, 22 Apr 2020 15:31:52 +0200 +Subject: [PATCH 203/709] hw/timer/pxa2xx_timer: Add assertion to silent static + analyzer warning +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +pxa2xx_timer_tick4() takes an opaque pointer, then calls +pxa2xx_timer_update4(), so the static analyzer can not +verify that the 'n < 8': + + 425 static void pxa2xx_timer_tick4(void *opaque) + 426 { + 427 PXA2xxTimer4 *t = (PXA2xxTimer4 *) opaque; + 428 PXA2xxTimerInfo *i = (PXA2xxTimerInfo *) t->tm.info; + 429 + 430 pxa2xx_timer_tick(&t->tm); + 433 if (t->control & (1 << 6)) + 434 pxa2xx_timer_update4(i, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), t->tm.num - 4); + + 135 static void pxa2xx_timer_update4(void *opaque, uint64_t now_qemu, int n) + 136 { + 137 PXA2xxTimerInfo *s = (PXA2xxTimerInfo *) opaque; + 140 static const int counters[8] = { 0, 0, 0, 0, 4, 4, 6, 6 }; + 142 + 143 if (s->tm4[n].control & (1 << 7)) + 144 counter = n; + 145 else + 146 counter = counters[n]; + +Add an assert() to give the static analyzer a hint, this fixes a +warning reported by Clang static code analyzer: + + CC hw/timer/pxa2xx_timer.o + hw/timer/pxa2xx_timer.c:146:17: warning: Assigned value is garbage or undefined + counter = counters[n]; + ^ ~~~~~~~~~~~ + +Reported-by: Clang Static Analyzer +Reviewed-by: Alistair Francis +Signed-off-by: Philippe Mathieu-Daudé +Message-Id: <20200422133152.16770-10-philmd@redhat.com> +Signed-off-by: Laurent Vivier +--- + hw/timer/pxa2xx_timer.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/hw/timer/pxa2xx_timer.c b/hw/timer/pxa2xx_timer.c +index cd172cc1e9..944c165889 100644 +--- a/hw/timer/pxa2xx_timer.c ++++ b/hw/timer/pxa2xx_timer.c +@@ -140,6 +140,7 @@ static void pxa2xx_timer_update4(void *opaque, uint64_t now_qemu, int n) + static const int counters[8] = { 0, 0, 0, 0, 4, 4, 6, 6 }; + int counter; + ++ assert(n < ARRAY_SIZE(counters)); + if (s->tm4[n].control & (1 << 7)) + counter = n; + else +-- +2.23.0 + diff --git a/hw-timer-stm32f2xx_timer-Remove-dead-assignment.patch b/hw-timer-stm32f2xx_timer-Remove-dead-assignment.patch new file mode 100644 index 0000000000000000000000000000000000000000..e6ae570ba13da9ece21a298461064877a2876fcf --- /dev/null +++ b/hw-timer-stm32f2xx_timer-Remove-dead-assignment.patch @@ -0,0 +1,39 @@ +From dd1545a3f03f6e821a4ef588acbd99fb4328bcc2 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Wed, 22 Apr 2020 15:31:51 +0200 +Subject: [PATCH 202/709] hw/timer/stm32f2xx_timer: Remove dead assignment +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Fix warning reported by Clang static code analyzer: + + CC hw/timer/stm32f2xx_timer.o + hw/timer/stm32f2xx_timer.c:225:9: warning: Value stored to 'value' is never read + value = timer_val; + ^ ~~~~~~~~~ + +Reported-by: Clang Static Analyzer +Reviewed-by: Alistair Francis +Signed-off-by: Philippe Mathieu-Daudé +Message-Id: <20200422133152.16770-9-philmd@redhat.com> +Signed-off-by: Laurent Vivier +--- + hw/timer/stm32f2xx_timer.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/hw/timer/stm32f2xx_timer.c b/hw/timer/stm32f2xx_timer.c +index 06ec8a02c2..ba8694dcd3 100644 +--- a/hw/timer/stm32f2xx_timer.c ++++ b/hw/timer/stm32f2xx_timer.c +@@ -222,7 +222,6 @@ static void stm32f2xx_timer_write(void *opaque, hwaddr offset, + case TIM_PSC: + timer_val = stm32f2xx_ns_to_ticks(s, now) - s->tick_offset; + s->tim_psc = value & 0xFFFF; +- value = timer_val; + break; + case TIM_CNT: + timer_val = value; +-- +2.23.0 + diff --git a/hw-tpm-fix-usage-of-bool-in-tpm-tis.c.patch b/hw-tpm-fix-usage-of-bool-in-tpm-tis.c.patch new file mode 100644 index 0000000000000000000000000000000000000000..93171f35b5488d7eba9252d8a474a605248b8b5e --- /dev/null +++ b/hw-tpm-fix-usage-of-bool-in-tpm-tis.c.patch @@ -0,0 +1,44 @@ +From aadad398e7dc21fe177278498c1be31b8c7d5078 Mon Sep 17 00:00:00 2001 +From: Jafar Abdi +Date: Sat, 23 Mar 2019 17:26:37 +0300 +Subject: [PATCH 392/709] hw/tpm: fix usage of bool in tpm-tis.c + +Clean up wrong usage of FALSE and TRUE in places that use "bool" from stdbool.h. + +FALSE and TRUE (with capital letters) are the constants defined by glib for +being used with the "gboolean" type of glib. But some parts of the code also use +TRUE and FALSE for variables that are declared as "bool" (the type from ). + +Signed-off-by: Jafar Abdi +Reviewed-by: Thomas Huth +Reviewed-by: Stefan Berger +Signed-off-by: Stefan Berger +--- + hw/tpm/tpm_tis_common.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/hw/tpm/tpm_tis_common.c b/hw/tpm/tpm_tis_common.c +index 9ce64d4836..1af4bce139 100644 +--- a/hw/tpm/tpm_tis_common.c ++++ b/hw/tpm/tpm_tis_common.c +@@ -536,7 +536,7 @@ static void tpm_tis_mmio_write(void *opaque, hwaddr addr, + while ((TPM_TIS_IS_VALID_LOCTY(s->active_locty) && + locty > s->active_locty) || + !TPM_TIS_IS_VALID_LOCTY(s->active_locty)) { +- bool higher_seize = FALSE; ++ bool higher_seize = false; + + /* already a pending SEIZE ? */ + if ((s->loc[locty].access & TPM_TIS_ACCESS_SEIZE)) { +@@ -546,7 +546,7 @@ static void tpm_tis_mmio_write(void *opaque, hwaddr addr, + /* check for ongoing seize by a higher locality */ + for (l = locty + 1; l < TPM_TIS_NUM_LOCALITIES; l++) { + if ((s->loc[l].access & TPM_TIS_ACCESS_SEIZE)) { +- higher_seize = TRUE; ++ higher_seize = true; + break; + } + } +-- +2.23.0 + diff --git a/hw-watchdog-Implement-full-i.MX-watchdog-support.patch b/hw-watchdog-Implement-full-i.MX-watchdog-support.patch new file mode 100644 index 0000000000000000000000000000000000000000..f71dd59caa8598c2be36d11a9fe98fa102d727b0 --- /dev/null +++ b/hw-watchdog-Implement-full-i.MX-watchdog-support.patch @@ -0,0 +1,392 @@ +From daca13d495a11945c22d2aa68ad28dc5c8180911 Mon Sep 17 00:00:00 2001 +From: Guenter Roeck +Date: Sun, 17 May 2020 09:21:29 -0700 +Subject: [PATCH 618/709] hw/watchdog: Implement full i.MX watchdog support + +Implement full support for the watchdog in i.MX systems. +Pretimeout support is optional because the watchdog hardware +on i.MX31 does not support pretimeouts. + +Signed-off-by: Guenter Roeck +Message-id: 20200517162135.110364-3-linux@roeck-us.net +Signed-off-by: Peter Maydell +[PMM: added Property array terminator entry] +Reviewed-by: Peter Maydell +--- + hw/watchdog/wdt_imx2.c | 238 +++++++++++++++++++++++++++++++-- + include/hw/watchdog/wdt_imx2.h | 61 ++++++++- + 2 files changed, 285 insertions(+), 14 deletions(-) + +diff --git a/hw/watchdog/wdt_imx2.c b/hw/watchdog/wdt_imx2.c +index ad1ef02e9e..a5fb76308f 100644 +--- a/hw/watchdog/wdt_imx2.c ++++ b/hw/watchdog/wdt_imx2.c +@@ -13,24 +13,189 @@ + #include "qemu/bitops.h" + #include "qemu/module.h" + #include "sysemu/watchdog.h" ++#include "migration/vmstate.h" ++#include "hw/qdev-properties.h" + + #include "hw/watchdog/wdt_imx2.h" + +-#define IMX2_WDT_WCR_WDA BIT(5) /* -> External Reset WDOG_B */ +-#define IMX2_WDT_WCR_SRS BIT(4) /* -> Software Reset Signal */ ++static void imx2_wdt_interrupt(void *opaque) ++{ ++ IMX2WdtState *s = IMX2_WDT(opaque); ++ ++ s->wicr |= IMX2_WDT_WICR_WTIS; ++ qemu_set_irq(s->irq, 1); ++} ++ ++static void imx2_wdt_expired(void *opaque) ++{ ++ IMX2WdtState *s = IMX2_WDT(opaque); ++ ++ s->wrsr = IMX2_WDT_WRSR_TOUT; ++ ++ /* Perform watchdog action if watchdog is enabled */ ++ if (s->wcr & IMX2_WDT_WCR_WDE) { ++ s->wrsr = IMX2_WDT_WRSR_TOUT; ++ watchdog_perform_action(); ++ } ++} ++ ++static void imx2_wdt_reset(DeviceState *dev) ++{ ++ IMX2WdtState *s = IMX2_WDT(dev); ++ ++ ptimer_transaction_begin(s->timer); ++ ptimer_stop(s->timer); ++ ptimer_transaction_commit(s->timer); ++ ++ if (s->pretimeout_support) { ++ ptimer_transaction_begin(s->itimer); ++ ptimer_stop(s->itimer); ++ ptimer_transaction_commit(s->itimer); ++ } ++ ++ s->wicr_locked = false; ++ s->wcr_locked = false; ++ s->wcr_wde_locked = false; ++ ++ s->wcr = IMX2_WDT_WCR_WDA | IMX2_WDT_WCR_SRS; ++ s->wsr = 0; ++ s->wrsr &= ~(IMX2_WDT_WRSR_TOUT | IMX2_WDT_WRSR_SFTW); ++ s->wicr = IMX2_WDT_WICR_WICT_DEF; ++ s->wmcr = IMX2_WDT_WMCR_PDE; ++} + +-static uint64_t imx2_wdt_read(void *opaque, hwaddr addr, +- unsigned int size) ++static uint64_t imx2_wdt_read(void *opaque, hwaddr addr, unsigned int size) + { ++ IMX2WdtState *s = IMX2_WDT(opaque); ++ ++ switch (addr) { ++ case IMX2_WDT_WCR: ++ return s->wcr; ++ case IMX2_WDT_WSR: ++ return s->wsr; ++ case IMX2_WDT_WRSR: ++ return s->wrsr; ++ case IMX2_WDT_WICR: ++ return s->wicr; ++ case IMX2_WDT_WMCR: ++ return s->wmcr; ++ } + return 0; + } + ++static void imx_wdt2_update_itimer(IMX2WdtState *s, bool start) ++{ ++ bool running = (s->wcr & IMX2_WDT_WCR_WDE) && (s->wcr & IMX2_WDT_WCR_WT); ++ bool enabled = s->wicr & IMX2_WDT_WICR_WIE; ++ ++ ptimer_transaction_begin(s->itimer); ++ if (start || !enabled) { ++ ptimer_stop(s->itimer); ++ } ++ if (running && enabled) { ++ int count = ptimer_get_count(s->timer); ++ int pretimeout = s->wicr & IMX2_WDT_WICR_WICT; ++ ++ /* ++ * Only (re-)start pretimeout timer if its counter value is larger ++ * than 0. Otherwise it will fire right away and we'll get an ++ * interrupt loop. ++ */ ++ if (count > pretimeout) { ++ ptimer_set_count(s->itimer, count - pretimeout); ++ if (start) { ++ ptimer_run(s->itimer, 1); ++ } ++ } ++ } ++ ptimer_transaction_commit(s->itimer); ++} ++ ++static void imx_wdt2_update_timer(IMX2WdtState *s, bool start) ++{ ++ ptimer_transaction_begin(s->timer); ++ if (start) { ++ ptimer_stop(s->timer); ++ } ++ if ((s->wcr & IMX2_WDT_WCR_WDE) && (s->wcr & IMX2_WDT_WCR_WT)) { ++ int count = (s->wcr & IMX2_WDT_WCR_WT) >> 8; ++ ++ /* A value of 0 reflects one period (0.5s). */ ++ ptimer_set_count(s->timer, count + 1); ++ if (start) { ++ ptimer_run(s->timer, 1); ++ } ++ } ++ ptimer_transaction_commit(s->timer); ++ if (s->pretimeout_support) { ++ imx_wdt2_update_itimer(s, start); ++ } ++} ++ + static void imx2_wdt_write(void *opaque, hwaddr addr, + uint64_t value, unsigned int size) + { +- if (addr == IMX2_WDT_WCR && +- (~value & (IMX2_WDT_WCR_WDA | IMX2_WDT_WCR_SRS))) { +- watchdog_perform_action(); ++ IMX2WdtState *s = IMX2_WDT(opaque); ++ ++ switch (addr) { ++ case IMX2_WDT_WCR: ++ if (s->wcr_locked) { ++ value &= ~IMX2_WDT_WCR_LOCK_MASK; ++ value |= (s->wicr & IMX2_WDT_WCR_LOCK_MASK); ++ } ++ s->wcr_locked = true; ++ if (s->wcr_wde_locked) { ++ value &= ~IMX2_WDT_WCR_WDE; ++ value |= (s->wicr & ~IMX2_WDT_WCR_WDE); ++ } else if (value & IMX2_WDT_WCR_WDE) { ++ s->wcr_wde_locked = true; ++ } ++ if (s->wcr_wdt_locked) { ++ value &= ~IMX2_WDT_WCR_WDT; ++ value |= (s->wicr & ~IMX2_WDT_WCR_WDT); ++ } else if (value & IMX2_WDT_WCR_WDT) { ++ s->wcr_wdt_locked = true; ++ } ++ ++ s->wcr = value; ++ if (!(value & IMX2_WDT_WCR_SRS)) { ++ s->wrsr = IMX2_WDT_WRSR_SFTW; ++ } ++ if (!(value & (IMX2_WDT_WCR_WDA | IMX2_WDT_WCR_SRS)) || ++ (!(value & IMX2_WDT_WCR_WT) && (value & IMX2_WDT_WCR_WDE))) { ++ watchdog_perform_action(); ++ } ++ s->wcr |= IMX2_WDT_WCR_SRS; ++ imx_wdt2_update_timer(s, true); ++ break; ++ case IMX2_WDT_WSR: ++ if (s->wsr == IMX2_WDT_SEQ1 && value == IMX2_WDT_SEQ2) { ++ imx_wdt2_update_timer(s, false); ++ } ++ s->wsr = value; ++ break; ++ case IMX2_WDT_WRSR: ++ break; ++ case IMX2_WDT_WICR: ++ if (!s->pretimeout_support) { ++ return; ++ } ++ value &= IMX2_WDT_WICR_LOCK_MASK | IMX2_WDT_WICR_WTIS; ++ if (s->wicr_locked) { ++ value &= IMX2_WDT_WICR_WTIS; ++ value |= (s->wicr & IMX2_WDT_WICR_LOCK_MASK); ++ } ++ s->wicr = value | (s->wicr & IMX2_WDT_WICR_WTIS); ++ if (value & IMX2_WDT_WICR_WTIS) { ++ s->wicr &= ~IMX2_WDT_WICR_WTIS; ++ qemu_set_irq(s->irq, 0); ++ } ++ imx_wdt2_update_itimer(s, true); ++ s->wicr_locked = true; ++ break; ++ case IMX2_WDT_WMCR: ++ s->wmcr = value & IMX2_WDT_WMCR_PDE; ++ break; + } + } + +@@ -45,28 +210,77 @@ static const MemoryRegionOps imx2_wdt_ops = { + * real device but in practice there is no reason for a guest + * to access this device unaligned. + */ +- .min_access_size = 4, +- .max_access_size = 4, ++ .min_access_size = 2, ++ .max_access_size = 2, + .unaligned = false, + }, + }; + ++static const VMStateDescription vmstate_imx2_wdt = { ++ .name = "imx2.wdt", ++ .fields = (VMStateField[]) { ++ VMSTATE_PTIMER(timer, IMX2WdtState), ++ VMSTATE_PTIMER(itimer, IMX2WdtState), ++ VMSTATE_BOOL(wicr_locked, IMX2WdtState), ++ VMSTATE_BOOL(wcr_locked, IMX2WdtState), ++ VMSTATE_BOOL(wcr_wde_locked, IMX2WdtState), ++ VMSTATE_BOOL(wcr_wdt_locked, IMX2WdtState), ++ VMSTATE_UINT16(wcr, IMX2WdtState), ++ VMSTATE_UINT16(wsr, IMX2WdtState), ++ VMSTATE_UINT16(wrsr, IMX2WdtState), ++ VMSTATE_UINT16(wmcr, IMX2WdtState), ++ VMSTATE_UINT16(wicr, IMX2WdtState), ++ VMSTATE_END_OF_LIST() ++ } ++}; ++ + static void imx2_wdt_realize(DeviceState *dev, Error **errp) + { + IMX2WdtState *s = IMX2_WDT(dev); ++ SysBusDevice *sbd = SYS_BUS_DEVICE(dev); + + memory_region_init_io(&s->mmio, OBJECT(dev), + &imx2_wdt_ops, s, +- TYPE_IMX2_WDT".mmio", +- IMX2_WDT_REG_NUM * sizeof(uint16_t)); +- sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->mmio); ++ TYPE_IMX2_WDT, ++ IMX2_WDT_MMIO_SIZE); ++ sysbus_init_mmio(sbd, &s->mmio); ++ sysbus_init_irq(sbd, &s->irq); ++ ++ s->timer = ptimer_init(imx2_wdt_expired, s, ++ PTIMER_POLICY_NO_IMMEDIATE_TRIGGER | ++ PTIMER_POLICY_NO_IMMEDIATE_RELOAD | ++ PTIMER_POLICY_NO_COUNTER_ROUND_DOWN); ++ ptimer_transaction_begin(s->timer); ++ ptimer_set_freq(s->timer, 2); ++ ptimer_set_limit(s->timer, 0xff, 1); ++ ptimer_transaction_commit(s->timer); ++ if (s->pretimeout_support) { ++ s->itimer = ptimer_init(imx2_wdt_interrupt, s, ++ PTIMER_POLICY_NO_IMMEDIATE_TRIGGER | ++ PTIMER_POLICY_NO_IMMEDIATE_RELOAD | ++ PTIMER_POLICY_NO_COUNTER_ROUND_DOWN); ++ ptimer_transaction_begin(s->itimer); ++ ptimer_set_freq(s->itimer, 2); ++ ptimer_set_limit(s->itimer, 0xff, 1); ++ ptimer_transaction_commit(s->itimer); ++ } + } + ++static Property imx2_wdt_properties[] = { ++ DEFINE_PROP_BOOL("pretimeout-support", IMX2WdtState, pretimeout_support, ++ false), ++ DEFINE_PROP_END_OF_LIST() ++}; ++ + static void imx2_wdt_class_init(ObjectClass *klass, void *data) + { + DeviceClass *dc = DEVICE_CLASS(klass); + ++ device_class_set_props(dc, imx2_wdt_properties); + dc->realize = imx2_wdt_realize; ++ dc->reset = imx2_wdt_reset; ++ dc->vmsd = &vmstate_imx2_wdt; ++ dc->desc = "i.MX watchdog timer"; + set_bit(DEVICE_CATEGORY_MISC, dc->categories); + } + +diff --git a/include/hw/watchdog/wdt_imx2.h b/include/hw/watchdog/wdt_imx2.h +index b91b002528..f9af6be4b6 100644 +--- a/include/hw/watchdog/wdt_imx2.h ++++ b/include/hw/watchdog/wdt_imx2.h +@@ -12,22 +12,79 @@ + #ifndef IMX2_WDT_H + #define IMX2_WDT_H + ++#include "qemu/bitops.h" + #include "hw/sysbus.h" ++#include "hw/irq.h" ++#include "hw/ptimer.h" + + #define TYPE_IMX2_WDT "imx2.wdt" + #define IMX2_WDT(obj) OBJECT_CHECK(IMX2WdtState, (obj), TYPE_IMX2_WDT) + + enum IMX2WdtRegisters { +- IMX2_WDT_WCR = 0x0000, +- IMX2_WDT_REG_NUM = 0x0008 / sizeof(uint16_t) + 1, ++ IMX2_WDT_WCR = 0x0000, /* Control Register */ ++ IMX2_WDT_WSR = 0x0002, /* Service Register */ ++ IMX2_WDT_WRSR = 0x0004, /* Reset Status Register */ ++ IMX2_WDT_WICR = 0x0006, /* Interrupt Control Register */ ++ IMX2_WDT_WMCR = 0x0008, /* Misc Register */ + }; + ++#define IMX2_WDT_MMIO_SIZE 0x000a ++ ++/* Control Register definitions */ ++#define IMX2_WDT_WCR_WT (0xFF << 8) /* Watchdog Timeout Field */ ++#define IMX2_WDT_WCR_WDW BIT(7) /* WDOG Disable for Wait */ ++#define IMX2_WDT_WCR_WDA BIT(5) /* WDOG Assertion */ ++#define IMX2_WDT_WCR_SRS BIT(4) /* Software Reset Signal */ ++#define IMX2_WDT_WCR_WDT BIT(3) /* WDOG Timeout Assertion */ ++#define IMX2_WDT_WCR_WDE BIT(2) /* Watchdog Enable */ ++#define IMX2_WDT_WCR_WDBG BIT(1) /* Watchdog Debug Enable */ ++#define IMX2_WDT_WCR_WDZST BIT(0) /* Watchdog Timer Suspend */ ++ ++#define IMX2_WDT_WCR_LOCK_MASK (IMX2_WDT_WCR_WDZST | IMX2_WDT_WCR_WDBG \ ++ | IMX2_WDT_WCR_WDW) ++ ++/* Service Register definitions */ ++#define IMX2_WDT_SEQ1 0x5555 /* service sequence 1 */ ++#define IMX2_WDT_SEQ2 0xAAAA /* service sequence 2 */ ++ ++/* Reset Status Register definitions */ ++#define IMX2_WDT_WRSR_TOUT BIT(1) /* Reset due to Timeout */ ++#define IMX2_WDT_WRSR_SFTW BIT(0) /* Reset due to software reset */ ++ ++/* Interrupt Control Register definitions */ ++#define IMX2_WDT_WICR_WIE BIT(15) /* Interrupt Enable */ ++#define IMX2_WDT_WICR_WTIS BIT(14) /* Interrupt Status */ ++#define IMX2_WDT_WICR_WICT 0xff /* Interrupt Timeout */ ++#define IMX2_WDT_WICR_WICT_DEF 0x04 /* Default interrupt timeout (2s) */ ++ ++#define IMX2_WDT_WICR_LOCK_MASK (IMX2_WDT_WICR_WIE | IMX2_WDT_WICR_WICT) ++ ++/* Misc Control Register definitions */ ++#define IMX2_WDT_WMCR_PDE BIT(0) /* Power-Down Enable */ + + typedef struct IMX2WdtState { + /* */ + SysBusDevice parent_obj; + ++ /*< public >*/ + MemoryRegion mmio; ++ qemu_irq irq; ++ ++ struct ptimer_state *timer; ++ struct ptimer_state *itimer; ++ ++ bool pretimeout_support; ++ bool wicr_locked; ++ ++ uint16_t wcr; ++ uint16_t wsr; ++ uint16_t wrsr; ++ uint16_t wicr; ++ uint16_t wmcr; ++ ++ bool wcr_locked; /* affects WDZST, WDBG, and WDW */ ++ bool wcr_wde_locked; /* affects WDE */ ++ bool wcr_wdt_locked; /* affects WDT (never cleared) */ + } IMX2WdtState; + + #endif /* IMX2_WDT_H */ +-- +2.23.0 + diff --git a/i386-acpi-fix-gint-overflow-in-crs_range_compare.patch b/i386-acpi-fix-gint-overflow-in-crs_range_compare.patch deleted file mode 100644 index 5f5cbc47887b679dc22e628469a56fe678969de7..0000000000000000000000000000000000000000 --- a/i386-acpi-fix-gint-overflow-in-crs_range_compare.patch +++ /dev/null @@ -1,54 +0,0 @@ -From 21e2acd583126db94f6d881005cd58e835160582 Mon Sep 17 00:00:00 2001 -From: Evgeny Yakovlev -Date: Thu, 18 Jul 2019 19:14:23 +0300 -Subject: [PATCH] i386/acpi: fix gint overflow in crs_range_compare - -When very large regions (32GB sized in our case, PCI pass-through of GPUs) -are compared substraction result does not fit into gint. - -As a result crs_replace_with_free_ranges does not get sorted ranges and -incorrectly computes PCI64 free space regions. Which then makes linux -guest complain about device and PCI64 hole intersection and device -becomes unusable. - -Fix that by returning exactly fitting ranges. - -Also fix indentation of an entire crs_replace_with_free_ranges to make -checkpatch happy. - -Cc: qemu-stable@nongnu.org -Signed-off-by: Evgeny Yakovlev -Message-Id: <1563466463-26012-1-git-send-email-wrfsh@yandex-team.ru> -Signed-off-by: Evgeny Yakovlev -(cherry-picked from commit 21e2acd583126db94f6d881005cd58e835160582) ---- - hw/i386/acpi-build.c | 12 +++++++++--- - 1 file changed, 9 insertions(+), 3 deletions(-) - -diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c -index d281ffa89e..e7b756b51b 100644 ---- a/hw/i386/acpi-build.c -+++ b/hw/i386/acpi-build.c -@@ -755,10 +755,16 @@ static void crs_range_set_free(CrsRangeSet *range_set) - - static gint crs_range_compare(gconstpointer a, gconstpointer b) - { -- CrsRangeEntry *entry_a = *(CrsRangeEntry **)a; -- CrsRangeEntry *entry_b = *(CrsRangeEntry **)b; -+ CrsRangeEntry *entry_a = *(CrsRangeEntry **)a; -+ CrsRangeEntry *entry_b = *(CrsRangeEntry **)b; - -- return (int64_t)entry_a->base - (int64_t)entry_b->base; -+ if (entry_a->base < entry_b->base) { -+ return -1; -+ } else if (entry_a->base > entry_b->base) { -+ return 1; -+ } else { -+ return 0; -+ } - } - - /* --- -2.19.1 - diff --git a/i386-acpi-show-PCI-Express-bus-on-pxb-pcie-expanders.patch b/i386-acpi-show-PCI-Express-bus-on-pxb-pcie-expanders.patch deleted file mode 100644 index 640329867cb1750b83ccceb72a2c44c8a5577fa3..0000000000000000000000000000000000000000 --- a/i386-acpi-show-PCI-Express-bus-on-pxb-pcie-expanders.patch +++ /dev/null @@ -1,40 +0,0 @@ -From ee4b0c8686f781987879508d7c6dd605b5435bac Mon Sep 17 00:00:00 2001 -From: Evgeny Yakovlev -Date: Fri, 19 Jul 2019 11:54:29 +0300 -Subject: [PATCH] i386/acpi: show PCI Express bus on pxb-pcie expanders - -Show PCIe host bridge PNP id with PCI host bridge as a compatible id -when expanding a pcie bus. - -Cc: qemu-stable@nongnu.org -Signed-off-by: Evgeny Yakovlev -Message-Id: <1563526469-15588-1-git-send-email-wrfsh@yandex-team.ru> -Reviewed-by: Michael S. Tsirkin -Signed-off-by: Michael S. Tsirkin -(cherry-picked from commit ee4b0c8686f781987879508d7c6dd605b5435bac) ---- - hw/i386/acpi-build.c | 5 ++++- - 1 file changed, 4 insertions(+), 1 deletion(-) - -diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c -index e7b756b51b..f3fdfefcd5 100644 ---- a/hw/i386/acpi-build.c -+++ b/hw/i386/acpi-build.c -@@ -1914,10 +1914,13 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, - scope = aml_scope("\\_SB"); - dev = aml_device("PC%.02X", bus_num); - aml_append(dev, aml_name_decl("_UID", aml_int(bus_num))); -- aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0A03"))); - aml_append(dev, aml_name_decl("_BBN", aml_int(bus_num))); - if (pci_bus_is_express(bus)) { -+ aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0A08"))); -+ aml_append(dev, aml_name_decl("_CID", aml_eisaid("PNP0A03"))); - aml_append(dev, build_q35_osc_method()); -+ } else { -+ aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0A03"))); - } - - if (numa_node != NUMA_NODE_UNASSIGNED) { --- -2.19.1 - diff --git a/intc-arm_gic-Support-IRQ-injection-for-more-than-256.patch b/intc-arm_gic-Support-IRQ-injection-for-more-than-256.patch deleted file mode 100644 index d69dcc71825a8ed70e133ffb7d28af03a08485a1..0000000000000000000000000000000000000000 --- a/intc-arm_gic-Support-IRQ-injection-for-more-than-256.patch +++ /dev/null @@ -1,132 +0,0 @@ -From 15849387df5c25e8ebaef19e2a16e8d428675f5d Mon Sep 17 00:00:00 2001 -From: Eric Auger -Date: Thu, 3 Oct 2019 17:46:39 +0200 -Subject: [PATCH 2/3] intc/arm_gic: Support IRQ injection for more than 256 - vpus - -Host kernels that expose the KVM_CAP_ARM_IRQ_LINE_LAYOUT_2 capability -allow injection of interrupts along with vcpu ids larger than 255. -Let's encode the vpcu id on 12 bits according to the upgraded KVM_IRQ_LINE -ABI when needed. - -Given that we have two callsites that need to assemble -the value for kvm_set_irq(), a new helper routine, kvm_arm_set_irq -is introduced. - -Without that patch qemu exits with "kvm_set_irq: Invalid argument" -message. - -Signed-off-by: Eric Auger -Reported-by: Zenghui Yu -Reviewed-by: Richard Henderson -Reviewed-by: Andrew Jones -Acked-by: Marc Zyngier -Message-id: 20191003154640.22451-3-eric.auger@redhat.com -Signed-off-by: Peter Maydell -(cherry-picked from commit f6530926e2310147a7844a3e663230d47b3d7333) -Signed-off-by: Zenghui Yu ---- - hw/intc/arm_gic_kvm.c | 7 ++----- - target/arm/cpu.c | 10 ++++------ - target/arm/kvm.c | 12 ++++++++++++ - target/arm/kvm_arm.h | 1 + - 4 files changed, 19 insertions(+), 11 deletions(-) - -diff --git a/hw/intc/arm_gic_kvm.c b/hw/intc/arm_gic_kvm.c -index a611e8ee..7d600a61 100644 ---- a/hw/intc/arm_gic_kvm.c -+++ b/hw/intc/arm_gic_kvm.c -@@ -55,7 +55,7 @@ void kvm_arm_gic_set_irq(uint32_t num_irq, int irq, int level) - * has separate fields in the irq number for type, - * CPU number and interrupt number. - */ -- int kvm_irq, irqtype, cpu; -+ int irqtype, cpu; - - if (irq < (num_irq - GIC_INTERNAL)) { - /* External interrupt. The kernel numbers these like the GIC -@@ -72,10 +72,7 @@ void kvm_arm_gic_set_irq(uint32_t num_irq, int irq, int level) - cpu = irq / GIC_INTERNAL; - irq %= GIC_INTERNAL; - } -- kvm_irq = (irqtype << KVM_ARM_IRQ_TYPE_SHIFT) -- | (cpu << KVM_ARM_IRQ_VCPU_SHIFT) | irq; -- -- kvm_set_irq(kvm_state, kvm_irq, !!level); -+ kvm_arm_set_irq(cpu, irqtype, irq, !!level); - } - - static void kvm_arm_gicv2_set_irq(void *opaque, int irq, int level) -diff --git a/target/arm/cpu.c b/target/arm/cpu.c -index 41557821..0b4c8e27 100644 ---- a/target/arm/cpu.c -+++ b/target/arm/cpu.c -@@ -561,16 +561,16 @@ static void arm_cpu_kvm_set_irq(void *opaque, int irq, int level) - ARMCPU *cpu = opaque; - CPUARMState *env = &cpu->env; - CPUState *cs = CPU(cpu); -- int kvm_irq = KVM_ARM_IRQ_TYPE_CPU << KVM_ARM_IRQ_TYPE_SHIFT; - uint32_t linestate_bit; -+ int irq_id; - - switch (irq) { - case ARM_CPU_IRQ: -- kvm_irq |= KVM_ARM_IRQ_CPU_IRQ; -+ irq_id = KVM_ARM_IRQ_CPU_IRQ; - linestate_bit = CPU_INTERRUPT_HARD; - break; - case ARM_CPU_FIQ: -- kvm_irq |= KVM_ARM_IRQ_CPU_FIQ; -+ irq_id = KVM_ARM_IRQ_CPU_FIQ; - linestate_bit = CPU_INTERRUPT_FIQ; - break; - default: -@@ -582,9 +582,7 @@ static void arm_cpu_kvm_set_irq(void *opaque, int irq, int level) - } else { - env->irq_line_state &= ~linestate_bit; - } -- -- kvm_irq |= cs->cpu_index << KVM_ARM_IRQ_VCPU_SHIFT; -- kvm_set_irq(kvm_state, kvm_irq, level ? 1 : 0); -+ kvm_arm_set_irq(cs->cpu_index, KVM_ARM_IRQ_TYPE_CPU, irq_id, !!level); - #endif - } - -diff --git a/target/arm/kvm.c b/target/arm/kvm.c -index 79a79f01..f60185ad 100644 ---- a/target/arm/kvm.c -+++ b/target/arm/kvm.c -@@ -728,6 +728,18 @@ int kvm_arm_vgic_probe(void) - } - } - -+int kvm_arm_set_irq(int cpu, int irqtype, int irq, int level) -+{ -+ int kvm_irq = (irqtype << KVM_ARM_IRQ_TYPE_SHIFT) | irq; -+ int cpu_idx1 = cpu % 256; -+ int cpu_idx2 = cpu / 256; -+ -+ kvm_irq |= (cpu_idx1 << KVM_ARM_IRQ_VCPU_SHIFT) | -+ (cpu_idx2 << KVM_ARM_IRQ_VCPU2_SHIFT); -+ -+ return kvm_set_irq(kvm_state, kvm_irq, !!level); -+} -+ - int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route, - uint64_t address, uint32_t data, PCIDevice *dev) - { -diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h -index 2a07333c..a9f3ccab 100644 ---- a/target/arm/kvm_arm.h -+++ b/target/arm/kvm_arm.h -@@ -235,6 +235,7 @@ int kvm_arm_vgic_probe(void); - - void kvm_arm_pmu_set_irq(CPUState *cs, int irq); - void kvm_arm_pmu_init(CPUState *cs); -+int kvm_arm_set_irq(int cpu, int irqtype, int irq, int level); - - #else - --- -2.19.1 - diff --git a/io-Fix-qio_channel_socket_close-error-handling.patch b/io-Fix-qio_channel_socket_close-error-handling.patch new file mode 100644 index 0000000000000000000000000000000000000000..3aa2ebff82d52da016820a51f5e484cca202c41c --- /dev/null +++ b/io-Fix-qio_channel_socket_close-error-handling.patch @@ -0,0 +1,56 @@ +From fdceb4ab4d7ba920bb094ab477df4221261b291e Mon Sep 17 00:00:00 2001 +From: Markus Armbruster +Date: Wed, 22 Apr 2020 15:07:15 +0200 +Subject: [PATCH 023/709] io: Fix qio_channel_socket_close() error handling +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The Error ** argument must be NULL, &error_abort, &error_fatal, or a +pointer to a variable containing NULL. Passing an argument of the +latter kind twice without clearing it in between is wrong: if the +first call sets an error, it no longer points to NULL for the second +call. + +qio_channel_socket_close() passes @errp first to +socket_listen_cleanup(), and then, if closesocket() fails, to +error_setg_errno(). If socket_listen_cleanup() failed, this will trip +the assertion in error_setv(). + +Fix by ignoring a second error. + +Fixes: 73564c407caedf992a1c688b5fea776a8b56ba2a +Cc: Daniel P. Berrangé +Signed-off-by: Markus Armbruster +Reviewed-by: Daniel P. Berrangé +Message-Id: <20200422130719.28225-11-armbru@redhat.com> +--- + io/channel-socket.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/io/channel-socket.c b/io/channel-socket.c +index b74f5b92a0..e1b4667087 100644 +--- a/io/channel-socket.c ++++ b/io/channel-socket.c +@@ -704,6 +704,7 @@ qio_channel_socket_close(QIOChannel *ioc, + { + QIOChannelSocket *sioc = QIO_CHANNEL_SOCKET(ioc); + int rc = 0; ++ Error *err = NULL; + + if (sioc->fd != -1) { + #ifdef WIN32 +@@ -715,8 +716,8 @@ qio_channel_socket_close(QIOChannel *ioc, + + if (closesocket(sioc->fd) < 0) { + sioc->fd = -1; +- error_setg_errno(errp, errno, +- "Unable to close socket"); ++ error_setg_errno(&err, errno, "Unable to close socket"); ++ error_propagate(errp, err); + return -1; + } + sioc->fd = -1; +-- +2.23.0 + diff --git a/ioapic-kvm-Skip-route-updates-for-masked-pins.patch b/ioapic-kvm-Skip-route-updates-for-masked-pins.patch deleted file mode 100644 index 0a27bfdcc58b01cab2e95ea2589f19867226b600..0000000000000000000000000000000000000000 --- a/ioapic-kvm-Skip-route-updates-for-masked-pins.patch +++ /dev/null @@ -1,46 +0,0 @@ -From be1927c97e564346cbd409cb17fe611df74b84e5 Mon Sep 17 00:00:00 2001 -From: Jan Kiszka -Date: Sun, 2 Jun 2019 13:42:13 +0200 -Subject: [PATCH] ioapic: kvm: Skip route updates for masked pins - -Masked entries will not generate interrupt messages, thus do no need to -be routed by KVM. This is a cosmetic cleanup, just avoiding warnings of -the kind - -qemu-system-x86_64: vtd_irte_get: detected non-present IRTE (index=0, high=0xff00, low=0x100) - -if the masked entry happens to reference a non-present IRTE. - -Cc: qemu-stable@nongnu.org -Signed-off-by: Jan Kiszka -Message-Id: -Reviewed-by: Michael S. Tsirkin -Signed-off-by: Michael S. Tsirkin -Reviewed-by: Peter Xu -(cherry-picked from commit be1927c97e564346cbd409cb17fe611df74b84e5) ---- - hw/intc/ioapic.c | 8 +++++--- - 1 file changed, 5 insertions(+), 3 deletions(-) - -diff --git a/hw/intc/ioapic.c b/hw/intc/ioapic.c -index c408749876..e99c37cceb 100644 ---- a/hw/intc/ioapic.c -+++ b/hw/intc/ioapic.c -@@ -197,9 +197,11 @@ static void ioapic_update_kvm_routes(IOAPICCommonState *s) - MSIMessage msg; - struct ioapic_entry_info info; - ioapic_entry_parse(s->ioredtbl[i], &info); -- msg.address = info.addr; -- msg.data = info.data; -- kvm_irqchip_update_msi_route(kvm_state, i, msg, NULL); -+ if (!info.masked) { -+ msg.address = info.addr; -+ msg.data = info.data; -+ kvm_irqchip_update_msi_route(kvm_state, i, msg, NULL); -+ } - } - kvm_irqchip_commit_routes(kvm_state); - } --- -2.19.1 - diff --git a/iotest-258-use-script_main.patch b/iotest-258-use-script_main.patch new file mode 100644 index 0000000000000000000000000000000000000000..0ae642c6f4853416732d265bce6df04db5758cce --- /dev/null +++ b/iotest-258-use-script_main.patch @@ -0,0 +1,50 @@ +From 5e089feb93e1c0ce55a5900b00b03d772587c396 Mon Sep 17 00:00:00 2001 +From: John Snow +Date: Mon, 30 Mar 2020 20:00:12 -0400 +Subject: [PATCH 252/709] iotest 258: use script_main +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Since this one is nicely factored to use a single entry point, +use script_main to run the tests. + +Signed-off-by: John Snow +Reviewed-by: Philippe Mathieu-Daudé +Reviewed-by: Max Reitz +Message-Id: <20200331000014.11581-13-jsnow@redhat.com> +Reviewed-by: Kevin Wolf +Signed-off-by: Max Reitz +--- + tests/qemu-iotests/258 | 11 ++++------- + 1 file changed, 4 insertions(+), 7 deletions(-) + +diff --git a/tests/qemu-iotests/258 b/tests/qemu-iotests/258 +index a65151dda6..e305a1502f 100755 +--- a/tests/qemu-iotests/258 ++++ b/tests/qemu-iotests/258 +@@ -23,12 +23,6 @@ import iotests + from iotests import log, qemu_img, qemu_io_silent, \ + filter_qmp_testfiles, filter_qmp_imgfmt + +-# Need backing file and change-backing-file support +-iotests.script_initialize( +- supported_fmts=['qcow2', 'qed'], +- supported_platforms=['linux'], +-) +- + # Returns a node for blockdev-add + def node(node_name, path, backing=None, fmt=None, throttle=None): + if fmt is None: +@@ -161,4 +155,7 @@ def main(): + test_concurrent_finish(False) + + if __name__ == '__main__': +- main() ++ # Need backing file and change-backing-file support ++ iotests.script_main(main, ++ supported_fmts=['qcow2', 'qed'], ++ supported_platforms=['linux']) +-- +2.23.0 + diff --git a/iotests-030-Reduce-run-time-by-unthrottling-job-earl.patch b/iotests-030-Reduce-run-time-by-unthrottling-job-earl.patch new file mode 100644 index 0000000000000000000000000000000000000000..9ce7834af1694736ca47303058aee3d949ef8f98 --- /dev/null +++ b/iotests-030-Reduce-run-time-by-unthrottling-job-earl.patch @@ -0,0 +1,48 @@ +From b1b30ff4df942ef75abb3799889ab2f4c52155e9 Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Wed, 13 May 2020 12:00:25 +0200 +Subject: [PATCH 571/709] iotests/030: Reduce run time by unthrottling job + earlier + +test_overlapping_3() throttles its active commit job so it can be sure +the job is still busy when it checks that you can't start a conflicting +streaming job. + +However, it only sets the commit job back to full speed when it is +ready, which takes a few seconds while it's throttled. We can already +reset the limit after having checked that block-stream returns an error +and save these seconds. + +Signed-off-by: Kevin Wolf +Message-Id: <20200513100025.33543-1-kwolf@redhat.com> +Reviewed-by: Alberto Garcia +Signed-off-by: Kevin Wolf +--- + tests/qemu-iotests/030 | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/tests/qemu-iotests/030 b/tests/qemu-iotests/030 +index 104e3cee1b..1cdd7e2999 100755 +--- a/tests/qemu-iotests/030 ++++ b/tests/qemu-iotests/030 +@@ -354,14 +354,14 @@ class TestParallelOps(iotests.QMPTestCase): + self.assert_qmp(result, 'error/desc', + "Node 'node5' is busy: block device is in use by block job: commit") + ++ result = self.vm.qmp('block-job-set-speed', device='commit-drive0', speed=0) ++ self.assert_qmp(result, 'return', {}) ++ + event = self.vm.event_wait(name='BLOCK_JOB_READY') + self.assert_qmp(event, 'data/device', 'commit-drive0') + self.assert_qmp(event, 'data/type', 'commit') + self.assert_qmp_absent(event, 'data/error') + +- result = self.vm.qmp('block-job-set-speed', device='commit-drive0', speed=0) +- self.assert_qmp(result, 'return', {}) +- + result = self.vm.qmp('block-job-complete', device='commit-drive0') + self.assert_qmp(result, 'return', {}) + +-- +2.23.0 + diff --git a/iotests-041-Fix-NBD-socket-path.patch b/iotests-041-Fix-NBD-socket-path.patch new file mode 100644 index 0000000000000000000000000000000000000000..f23cb6b74ee958e8bf912a2f0784fc34aa1a0ada --- /dev/null +++ b/iotests-041-Fix-NBD-socket-path.patch @@ -0,0 +1,34 @@ +From e5ac52d8d405f46843465128410a8f1362458eb6 Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Fri, 24 Apr 2020 15:46:26 +0200 +Subject: [PATCH 238/709] iotests/041: Fix NBD socket path + +We should put all UNIX socket files into the sock_dir, not test_dir. + +Reported-by: Elena Ufimtseva +Signed-off-by: Max Reitz +Message-Id: <20200424134626.78945-1-mreitz@redhat.com> +Reviewed-by: Eric Blake +Fixes: a1da1878607a +Reviewed-by: Stefan Hajnoczi +Signed-off-by: Eric Blake +--- + tests/qemu-iotests/041 | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tests/qemu-iotests/041 b/tests/qemu-iotests/041 +index 5d67bf14bf..46bf1f6c81 100755 +--- a/tests/qemu-iotests/041 ++++ b/tests/qemu-iotests/041 +@@ -35,7 +35,7 @@ quorum_img3 = os.path.join(iotests.test_dir, 'quorum3.img') + quorum_repair_img = os.path.join(iotests.test_dir, 'quorum_repair.img') + quorum_snapshot_file = os.path.join(iotests.test_dir, 'quorum_snapshot.img') + +-nbd_sock_path = os.path.join(iotests.test_dir, 'nbd.sock') ++nbd_sock_path = os.path.join(iotests.sock_dir, 'nbd.sock') + + class TestSingleDrive(iotests.QMPTestCase): + image_len = 1 * 1024 * 1024 # MB +-- +2.23.0 + diff --git a/iotests-041-drop-self.assert_no_active_block_jobs.patch b/iotests-041-drop-self.assert_no_active_block_jobs.patch new file mode 100644 index 0000000000000000000000000000000000000000..30f91bb76af27ecaea14de073c28609ad0483c04 --- /dev/null +++ b/iotests-041-drop-self.assert_no_active_block_jobs.patch @@ -0,0 +1,58 @@ +From 4b4083d53f7b6da14a96eee2636fff2d1b197649 Mon Sep 17 00:00:00 2001 +From: Vladimir Sementsov-Ogievskiy +Date: Thu, 30 Apr 2020 15:47:09 +0300 +Subject: [PATCH 331/709] iotests/041: drop self.assert_no_active_block_jobs() + +Drop check for no block-jobs: it's obvious that there no jobs +immediately after vm.launch(). + +Signed-off-by: Vladimir Sementsov-Ogievskiy +Message-Id: <20200430124713.3067-5-vsementsov@virtuozzo.com> +Signed-off-by: Kevin Wolf +--- + tests/qemu-iotests/041 | 8 -------- + 1 file changed, 8 deletions(-) + +diff --git a/tests/qemu-iotests/041 b/tests/qemu-iotests/041 +index 46bf1f6c81..1812dd8479 100755 +--- a/tests/qemu-iotests/041 ++++ b/tests/qemu-iotests/041 +@@ -904,8 +904,6 @@ class TestRepairQuorum(iotests.QMPTestCase): + pass + + def test_complete(self): +- self.assert_no_active_block_jobs() +- + result = self.vm.qmp('drive-mirror', job_id='job0', device='quorum0', + sync='full', node_name="repair0", replaces="img1", + target=quorum_repair_img, format=iotests.imgfmt) +@@ -919,8 +917,6 @@ class TestRepairQuorum(iotests.QMPTestCase): + 'target image does not match source after mirroring') + + def test_cancel(self): +- self.assert_no_active_block_jobs() +- + result = self.vm.qmp('drive-mirror', job_id='job0', device='quorum0', + sync='full', node_name="repair0", replaces="img1", + target=quorum_repair_img, format=iotests.imgfmt) +@@ -932,8 +928,6 @@ class TestRepairQuorum(iotests.QMPTestCase): + self.assert_has_block_node(None, quorum_img3) + + def test_cancel_after_ready(self): +- self.assert_no_active_block_jobs() +- + result = self.vm.qmp('drive-mirror', job_id='job0', device='quorum0', + sync='full', node_name="repair0", replaces="img1", + target=quorum_repair_img, format=iotests.imgfmt) +@@ -948,8 +942,6 @@ class TestRepairQuorum(iotests.QMPTestCase): + 'target image does not match source after mirroring') + + def test_pause(self): +- self.assert_no_active_block_jobs() +- + result = self.vm.qmp('drive-mirror', job_id='job0', device='quorum0', + sync='full', node_name="repair0", replaces="img1", + target=quorum_repair_img, format=iotests.imgfmt) +-- +2.23.0 + diff --git a/iotests-055-Use-cache.no-flush-for-vmdk-target.patch b/iotests-055-Use-cache.no-flush-for-vmdk-target.patch new file mode 100644 index 0000000000000000000000000000000000000000..bfe2e217837647c557c686ea03b56d9bfabc768e --- /dev/null +++ b/iotests-055-Use-cache.no-flush-for-vmdk-target.patch @@ -0,0 +1,73 @@ +From 6a9d73bdd061d9eb7001d38147f73f4b6987f00b Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Tue, 5 May 2020 08:46:18 +0200 +Subject: [PATCH 347/709] iotests/055: Use cache.no-flush for vmdk target + +055 uses the backup block job to create a compressed backup of an +$IMGFMT image with both qcow2 and vmdk targets. However, cluster +allocation in vmdk is very slow because it flushes the image file after +each L2 update. + +There is no reason why we need this level of safety in this test, so +let's disable flushes for vmdk. For the blockdev-backup tests this is +achieved by simply adding the cache.no-flush=on to the drive_add() for +the target. For drive-backup, the caching flags are copied from the +source node, so we'll also add the flag to the source node, even though +it is not vmdk. + +This can make the test run significantly faster (though it doesn't make +a difference on tmpfs). In my usual setup it goes from ~45s to ~15s. + +Signed-off-by: Kevin Wolf +Message-Id: <20200505064618.16267-1-kwolf@redhat.com> +Reviewed-by: Eric Blake +Signed-off-by: Kevin Wolf +--- + tests/qemu-iotests/055 | 11 +++++++---- + 1 file changed, 7 insertions(+), 4 deletions(-) + +diff --git a/tests/qemu-iotests/055 b/tests/qemu-iotests/055 +index 7f8e630de3..4d3744b0d3 100755 +--- a/tests/qemu-iotests/055 ++++ b/tests/qemu-iotests/055 +@@ -489,7 +489,7 @@ class TestSingleTransaction(iotests.QMPTestCase): + + class TestCompressedToQcow2(iotests.QMPTestCase): + image_len = 64 * 1024 * 1024 # MB +- target_fmt = {'type': 'qcow2', 'args': ()} ++ target_fmt = {'type': 'qcow2', 'args': (), 'drive-opts': ''} + + def tearDown(self): + self.vm.shutdown() +@@ -500,14 +500,16 @@ class TestCompressedToQcow2(iotests.QMPTestCase): + pass + + def do_prepare_drives(self, attach_target): +- self.vm = iotests.VM().add_drive('blkdebug::' + test_img) ++ self.vm = iotests.VM().add_drive('blkdebug::' + test_img, ++ opts=self.target_fmt['drive-opts']) + + qemu_img('create', '-f', self.target_fmt['type'], blockdev_target_img, + str(self.image_len), *self.target_fmt['args']) + if attach_target: + self.vm.add_drive(blockdev_target_img, + img_format=self.target_fmt['type'], +- interface="none") ++ interface="none", ++ opts=self.target_fmt['drive-opts']) + + self.vm.launch() + +@@ -601,7 +603,8 @@ class TestCompressedToQcow2(iotests.QMPTestCase): + + + class TestCompressedToVmdk(TestCompressedToQcow2): +- target_fmt = {'type': 'vmdk', 'args': ('-o', 'subformat=streamOptimized')} ++ target_fmt = {'type': 'vmdk', 'args': ('-o', 'subformat=streamOptimized'), ++ 'drive-opts': 'cache.no-flush=on'} + + @iotests.skip_if_unsupported(['vmdk']) + def setUp(self): +-- +2.23.0 + diff --git a/iotests-055-refactor-compressed-backup-to-vmdk.patch b/iotests-055-refactor-compressed-backup-to-vmdk.patch new file mode 100644 index 0000000000000000000000000000000000000000..67c8f0e41aeca236769021b1f83422bced33ed25 --- /dev/null +++ b/iotests-055-refactor-compressed-backup-to-vmdk.patch @@ -0,0 +1,162 @@ +From 8e8372944e5e097e98844b4db10f867689065e16 Mon Sep 17 00:00:00 2001 +From: Vladimir Sementsov-Ogievskiy +Date: Thu, 30 Apr 2020 15:47:10 +0300 +Subject: [PATCH 332/709] iotests/055: refactor compressed backup to vmdk + +Instead of looping in each test, let's better refactor vmdk target case +as a subclass. + +Signed-off-by: Vladimir Sementsov-Ogievskiy +Message-Id: <20200430124713.3067-6-vsementsov@virtuozzo.com> +Signed-off-by: Kevin Wolf +--- + tests/qemu-iotests/055 | 70 ++++++++++++++++++++------------------ + tests/qemu-iotests/055.out | 4 +-- + 2 files changed, 39 insertions(+), 35 deletions(-) + +diff --git a/tests/qemu-iotests/055 b/tests/qemu-iotests/055 +index 4175fff5e4..d9e8985167 100755 +--- a/tests/qemu-iotests/055 ++++ b/tests/qemu-iotests/055 +@@ -450,10 +450,9 @@ class TestSingleTransaction(iotests.QMPTestCase): + self.assert_no_active_block_jobs() + + +-class TestDriveCompression(iotests.QMPTestCase): ++class TestCompressedToQcow2(iotests.QMPTestCase): + image_len = 64 * 1024 * 1024 # MB +- fmt_supports_compression = [{'type': 'qcow2', 'args': ()}, +- {'type': 'vmdk', 'args': ('-o', 'subformat=streamOptimized')}] ++ target_fmt = {'type': 'qcow2', 'args': ()} + + def tearDown(self): + self.vm.shutdown() +@@ -463,19 +462,20 @@ class TestDriveCompression(iotests.QMPTestCase): + except OSError: + pass + +- def do_prepare_drives(self, fmt, args, attach_target): ++ def do_prepare_drives(self, attach_target): + self.vm = iotests.VM().add_drive('blkdebug::' + test_img) + +- qemu_img('create', '-f', fmt, blockdev_target_img, +- str(TestDriveCompression.image_len), *args) ++ qemu_img('create', '-f', self.target_fmt['type'], blockdev_target_img, ++ str(self.image_len), *self.target_fmt['args']) + if attach_target: + self.vm.add_drive(blockdev_target_img, +- img_format=fmt, interface="none") ++ img_format=self.target_fmt['type'], ++ interface="none") + + self.vm.launch() + +- def do_test_compress_complete(self, cmd, format, attach_target, **args): +- self.do_prepare_drives(format['type'], format['args'], attach_target) ++ def do_test_compress_complete(self, cmd, attach_target, **args): ++ self.do_prepare_drives(attach_target) + + self.assert_no_active_block_jobs() + +@@ -486,21 +486,21 @@ class TestDriveCompression(iotests.QMPTestCase): + + self.vm.shutdown() + self.assertTrue(iotests.compare_images(test_img, blockdev_target_img, +- iotests.imgfmt, format['type']), ++ iotests.imgfmt, ++ self.target_fmt['type']), + 'target image does not match source after backup') + + def test_complete_compress_drive_backup(self): +- for format in TestDriveCompression.fmt_supports_compression: +- self.do_test_compress_complete('drive-backup', format, False, +- target=blockdev_target_img, mode='existing') ++ self.do_test_compress_complete('drive-backup', False, ++ target=blockdev_target_img, ++ mode='existing') + + def test_complete_compress_blockdev_backup(self): +- for format in TestDriveCompression.fmt_supports_compression: +- self.do_test_compress_complete('blockdev-backup', format, True, +- target='drive1') ++ self.do_test_compress_complete('blockdev-backup', ++ True, target='drive1') + +- def do_test_compress_cancel(self, cmd, format, attach_target, **args): +- self.do_prepare_drives(format['type'], format['args'], attach_target) ++ def do_test_compress_cancel(self, cmd, attach_target, **args): ++ self.do_prepare_drives(attach_target) + + self.assert_no_active_block_jobs() + +@@ -514,17 +514,16 @@ class TestDriveCompression(iotests.QMPTestCase): + self.vm.shutdown() + + def test_compress_cancel_drive_backup(self): +- for format in TestDriveCompression.fmt_supports_compression: +- self.do_test_compress_cancel('drive-backup', format, False, +- target=blockdev_target_img, mode='existing') ++ self.do_test_compress_cancel('drive-backup', False, ++ target=blockdev_target_img, ++ mode='existing') + + def test_compress_cancel_blockdev_backup(self): +- for format in TestDriveCompression.fmt_supports_compression: +- self.do_test_compress_cancel('blockdev-backup', format, True, +- target='drive1') ++ self.do_test_compress_cancel('blockdev-backup', True, ++ target='drive1') + +- def do_test_compress_pause(self, cmd, format, attach_target, **args): +- self.do_prepare_drives(format['type'], format['args'], attach_target) ++ def do_test_compress_pause(self, cmd, attach_target, **args): ++ self.do_prepare_drives(attach_target) + + self.assert_no_active_block_jobs() + +@@ -550,18 +549,23 @@ class TestDriveCompression(iotests.QMPTestCase): + + self.vm.shutdown() + self.assertTrue(iotests.compare_images(test_img, blockdev_target_img, +- iotests.imgfmt, format['type']), ++ iotests.imgfmt, ++ self.target_fmt['type']), + 'target image does not match source after backup') + + def test_compress_pause_drive_backup(self): +- for format in TestDriveCompression.fmt_supports_compression: +- self.do_test_compress_pause('drive-backup', format, False, +- target=blockdev_target_img, mode='existing') ++ self.do_test_compress_pause('drive-backup', False, ++ target=blockdev_target_img, ++ mode='existing') + + def test_compress_pause_blockdev_backup(self): +- for format in TestDriveCompression.fmt_supports_compression: +- self.do_test_compress_pause('blockdev-backup', format, True, +- target='drive1') ++ self.do_test_compress_pause('blockdev-backup', True, ++ target='drive1') ++ ++ ++class TestCompressedToVmdk(TestCompressedToQcow2): ++ target_fmt = {'type': 'vmdk', 'args': ('-o', 'subformat=streamOptimized')} ++ + + if __name__ == '__main__': + iotests.main(supported_fmts=['raw', 'qcow2'], +diff --git a/tests/qemu-iotests/055.out b/tests/qemu-iotests/055.out +index 5ce2f9a2ed..5c26d15c0d 100644 +--- a/tests/qemu-iotests/055.out ++++ b/tests/qemu-iotests/055.out +@@ -1,5 +1,5 @@ +-.............................. ++.................................... + ---------------------------------------------------------------------- +-Ran 30 tests ++Ran 36 tests + + OK +-- +2.23.0 + diff --git a/iotests-055-skip-vmdk-target-tests-if-vmdk-is-not-wh.patch b/iotests-055-skip-vmdk-target-tests-if-vmdk-is-not-wh.patch new file mode 100644 index 0000000000000000000000000000000000000000..fa506d0fc567f29cd22600dcce0311065581797a --- /dev/null +++ b/iotests-055-skip-vmdk-target-tests-if-vmdk-is-not-wh.patch @@ -0,0 +1,31 @@ +From 761cd2e791eae38c3d08ea5f83309ce58bb85ff7 Mon Sep 17 00:00:00 2001 +From: Vladimir Sementsov-Ogievskiy +Date: Thu, 30 Apr 2020 15:47:11 +0300 +Subject: [PATCH 333/709] iotests/055: skip vmdk target tests if vmdk is not + whitelisted + +Signed-off-by: Vladimir Sementsov-Ogievskiy +Message-Id: <20200430124713.3067-7-vsementsov@virtuozzo.com> +Signed-off-by: Kevin Wolf +--- + tests/qemu-iotests/055 | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/tests/qemu-iotests/055 b/tests/qemu-iotests/055 +index d9e8985167..e250f798f9 100755 +--- a/tests/qemu-iotests/055 ++++ b/tests/qemu-iotests/055 +@@ -566,6 +566,10 @@ class TestCompressedToQcow2(iotests.QMPTestCase): + class TestCompressedToVmdk(TestCompressedToQcow2): + target_fmt = {'type': 'vmdk', 'args': ('-o', 'subformat=streamOptimized')} + ++ @iotests.skip_if_unsupported(['vmdk']) ++ def setUp(self): ++ pass ++ + + if __name__ == '__main__': + iotests.main(supported_fmts=['raw', 'qcow2'], +-- +2.23.0 + diff --git a/iotests-082-require-bochs.patch b/iotests-082-require-bochs.patch new file mode 100644 index 0000000000000000000000000000000000000000..3465c92a74dff4fce4c3a52a9f79a327815b3938 --- /dev/null +++ b/iotests-082-require-bochs.patch @@ -0,0 +1,29 @@ +From f03a8c73354f9f52364c528c3bdb4c42f08082e4 Mon Sep 17 00:00:00 2001 +From: Vladimir Sementsov-Ogievskiy +Date: Thu, 30 Apr 2020 15:47:07 +0300 +Subject: [PATCH 329/709] iotests/082: require bochs + +Test fails if bochs not whitelisted, so, skip it in this case. + +Signed-off-by: Vladimir Sementsov-Ogievskiy +Message-Id: <20200430124713.3067-3-vsementsov@virtuozzo.com> +Signed-off-by: Kevin Wolf +--- + tests/qemu-iotests/082 | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/tests/qemu-iotests/082 b/tests/qemu-iotests/082 +index 3286c2c6db..1998965ed4 100755 +--- a/tests/qemu-iotests/082 ++++ b/tests/qemu-iotests/082 +@@ -38,6 +38,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 15 + + _supported_fmt qcow2 + _supported_proto file nfs ++_require_drivers bochs + + run_qemu_img() + { +-- +2.23.0 + diff --git a/iotests-109-Don-t-mirror-with-mismatched-size.patch b/iotests-109-Don-t-mirror-with-mismatched-size.patch new file mode 100644 index 0000000000000000000000000000000000000000..a75b42d4a69d52b3e345352bac76223f5bf3d785 --- /dev/null +++ b/iotests-109-Don-t-mirror-with-mismatched-size.patch @@ -0,0 +1,375 @@ +From ffa41a62d0b0e6d91f2071328befa046d56993e1 Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Mon, 11 May 2020 15:58:22 +0200 +Subject: [PATCH 521/709] iotests/109: Don't mirror with mismatched size + +This patch makes the raw image the same size as the file in a different +format that is mirrored as raw to it to avoid errors when mirror starts +to enforce that source and target are the same size. + +We check only that the first 512 bytes are zeroed (instead of 64k) +because some image formats create image files that are smaller than 64k, +so trying to read 64k would result in I/O errors. Apart from this, 512 +is more appropriate anyway because the raw format driver protects +specifically the first 512 bytes. + +Signed-off-by: Kevin Wolf +Message-Id: <20200511135825.219437-2-kwolf@redhat.com> +Reviewed-by: Max Reitz +Reviewed-by: Vladimir Sementsov-Ogievskiy +Signed-off-by: Kevin Wolf +--- + tests/qemu-iotests/109 | 10 ++--- + tests/qemu-iotests/109.out | 74 +++++++++++++------------------- + tests/qemu-iotests/common.filter | 5 +++ + 3 files changed, 41 insertions(+), 48 deletions(-) + +diff --git a/tests/qemu-iotests/109 b/tests/qemu-iotests/109 +index 5bc2e9b001..3ffeaf3c55 100755 +--- a/tests/qemu-iotests/109 ++++ b/tests/qemu-iotests/109 +@@ -77,14 +77,14 @@ for fmt in qcow qcow2 qed vdi vmdk vpc; do + echo "=== Writing a $fmt header into raw ===" + echo + +- _make_test_img 64M + TEST_IMG="$TEST_IMG.src" IMGFMT=$fmt _make_test_img 64M ++ _make_test_img $(du -b "$TEST_IMG.src" | cut -f1) | _filter_img_create_size + + # This first test should fail: The image format was probed, we may not + # write an image header at the start of the image + run_qemu "$TEST_IMG" "$TEST_IMG.src" "" "BLOCK_JOB_ERROR" | + _filter_block_job_len +- $QEMU_IO -c 'read -P 0 0 64k' "$TEST_IMG" | _filter_qemu_io ++ $QEMU_IO -c 'read -P 0 0 512' "$TEST_IMG" | _filter_qemu_io + + + # When raw was explicitly specified, the same must succeed +@@ -103,12 +103,12 @@ for sample_img in empty.bochs iotest-dirtylog-10G-4M.vhdx parallels-v1 \ + + # Can't use _use_sample_img because that isn't designed to be used multiple + # times and it overwrites $TEST_IMG (both breaks cleanup) +- _make_test_img 64M + bzcat "$SAMPLE_IMG_DIR/$sample_img.bz2" > "$TEST_IMG.src" ++ _make_test_img $(du -b "$TEST_IMG.src" | cut -f1) | _filter_img_create_size + + run_qemu "$TEST_IMG" "$TEST_IMG.src" "" "BLOCK_JOB_ERROR" | + _filter_block_job_offset | _filter_block_job_len +- $QEMU_IO -c 'read -P 0 0 64k' "$TEST_IMG" | _filter_qemu_io ++ $QEMU_IO -c 'read -P 0 0 512' "$TEST_IMG" | _filter_qemu_io + + run_qemu "$TEST_IMG" "$TEST_IMG.src" "'format': 'raw'," "BLOCK_JOB_READY" + $QEMU_IMG compare -f raw -F raw "$TEST_IMG" "$TEST_IMG.src" +@@ -119,8 +119,8 @@ echo "=== Write legitimate MBR into raw ===" + echo + + for sample_img in grub_mbr.raw; do +- _make_test_img 64M + bzcat "$SAMPLE_IMG_DIR/$sample_img.bz2" > "$TEST_IMG.src" ++ _make_test_img $(du -b "$TEST_IMG.src" | cut -f1) | _filter_img_create_size + + run_qemu "$TEST_IMG" "$TEST_IMG.src" "" "BLOCK_JOB_READY" + $QEMU_IMG compare -f raw -F raw "$TEST_IMG" "$TEST_IMG.src" +diff --git a/tests/qemu-iotests/109.out b/tests/qemu-iotests/109.out +index 884f65f18d..ad739df46c 100644 +--- a/tests/qemu-iotests/109.out ++++ b/tests/qemu-iotests/109.out +@@ -2,8 +2,8 @@ QA output created by 109 + + === Writing a qcow header into raw === + +-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 + Formatting 'TEST_DIR/t.raw.src', fmt=IMGFMT size=67108864 ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=SIZE + { 'execute': 'qmp_capabilities' } + {"return": {}} + {'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'mode': 'existing', 'sync': 'full'}} +@@ -23,8 +23,8 @@ WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed + {"execute":"quit"} + {"return": {}} + {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}} +-read 65536/65536 bytes at offset 0 +-64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++read 512/512 bytes at offset 0 ++512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + { 'execute': 'qmp_capabilities' } + {"return": {}} + {'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'format': 'IMGFMT', 'mode': 'existing', 'sync': 'full'}} +@@ -43,13 +43,12 @@ read 65536/65536 bytes at offset 0 + {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 1024, "offset": 1024, "speed": 0, "type": "mirror"}} + {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}} + {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}} +-Warning: Image size mismatch! + Images are identical. + + === Writing a qcow2 header into raw === + +-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 + Formatting 'TEST_DIR/t.raw.src', fmt=IMGFMT size=67108864 ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=SIZE + { 'execute': 'qmp_capabilities' } + {"return": {}} + {'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'mode': 'existing', 'sync': 'full'}} +@@ -69,8 +68,8 @@ WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed + {"execute":"quit"} + {"return": {}} + {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}} +-read 65536/65536 bytes at offset 0 +-64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++read 512/512 bytes at offset 0 ++512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + { 'execute': 'qmp_capabilities' } + {"return": {}} + {'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'format': 'IMGFMT', 'mode': 'existing', 'sync': 'full'}} +@@ -89,13 +88,12 @@ read 65536/65536 bytes at offset 0 + {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 197120, "offset": 197120, "speed": 0, "type": "mirror"}} + {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}} + {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}} +-Warning: Image size mismatch! + Images are identical. + + === Writing a qed header into raw === + +-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 + Formatting 'TEST_DIR/t.raw.src', fmt=IMGFMT size=67108864 ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=SIZE + { 'execute': 'qmp_capabilities' } + {"return": {}} + {'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'mode': 'existing', 'sync': 'full'}} +@@ -115,8 +113,8 @@ WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed + {"execute":"quit"} + {"return": {}} + {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}} +-read 65536/65536 bytes at offset 0 +-64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++read 512/512 bytes at offset 0 ++512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + { 'execute': 'qmp_capabilities' } + {"return": {}} + {'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'format': 'IMGFMT', 'mode': 'existing', 'sync': 'full'}} +@@ -135,13 +133,12 @@ read 65536/65536 bytes at offset 0 + {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 327680, "offset": 327680, "speed": 0, "type": "mirror"}} + {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}} + {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}} +-Warning: Image size mismatch! + Images are identical. + + === Writing a vdi header into raw === + +-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 + Formatting 'TEST_DIR/t.raw.src', fmt=IMGFMT size=67108864 ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=SIZE + { 'execute': 'qmp_capabilities' } + {"return": {}} + {'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'mode': 'existing', 'sync': 'full'}} +@@ -161,8 +158,8 @@ WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed + {"execute":"quit"} + {"return": {}} + {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}} +-read 65536/65536 bytes at offset 0 +-64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++read 512/512 bytes at offset 0 ++512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + { 'execute': 'qmp_capabilities' } + {"return": {}} + {'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'format': 'IMGFMT', 'mode': 'existing', 'sync': 'full'}} +@@ -181,13 +178,12 @@ read 65536/65536 bytes at offset 0 + {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 1024, "offset": 1024, "speed": 0, "type": "mirror"}} + {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}} + {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}} +-Warning: Image size mismatch! + Images are identical. + + === Writing a vmdk header into raw === + +-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 + Formatting 'TEST_DIR/t.raw.src', fmt=IMGFMT size=67108864 ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=SIZE + { 'execute': 'qmp_capabilities' } + {"return": {}} + {'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'mode': 'existing', 'sync': 'full'}} +@@ -207,8 +203,8 @@ WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed + {"execute":"quit"} + {"return": {}} + {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}} +-read 65536/65536 bytes at offset 0 +-64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++read 512/512 bytes at offset 0 ++512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + { 'execute': 'qmp_capabilities' } + {"return": {}} + {'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'format': 'IMGFMT', 'mode': 'existing', 'sync': 'full'}} +@@ -227,13 +223,12 @@ read 65536/65536 bytes at offset 0 + {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 65536, "offset": 65536, "speed": 0, "type": "mirror"}} + {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}} + {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}} +-Warning: Image size mismatch! + Images are identical. + + === Writing a vpc header into raw === + +-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 + Formatting 'TEST_DIR/t.raw.src', fmt=IMGFMT size=67108864 ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=SIZE + { 'execute': 'qmp_capabilities' } + {"return": {}} + {'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'mode': 'existing', 'sync': 'full'}} +@@ -253,8 +248,8 @@ WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed + {"execute":"quit"} + {"return": {}} + {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}} +-read 65536/65536 bytes at offset 0 +-64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++read 512/512 bytes at offset 0 ++512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + { 'execute': 'qmp_capabilities' } + {"return": {}} + {'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'format': 'IMGFMT', 'mode': 'existing', 'sync': 'full'}} +@@ -273,12 +268,11 @@ read 65536/65536 bytes at offset 0 + {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 2560, "offset": 2560, "speed": 0, "type": "mirror"}} + {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}} + {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}} +-Warning: Image size mismatch! + Images are identical. + + === Copying sample image empty.bochs into raw === + +-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=SIZE + { 'execute': 'qmp_capabilities' } + {"return": {}} + {'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'mode': 'existing', 'sync': 'full'}} +@@ -298,8 +292,8 @@ WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed + {"execute":"quit"} + {"return": {}} + {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}} +-read 65536/65536 bytes at offset 0 +-64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++read 512/512 bytes at offset 0 ++512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + { 'execute': 'qmp_capabilities' } + {"return": {}} + {'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'format': 'IMGFMT', 'mode': 'existing', 'sync': 'full'}} +@@ -318,12 +312,11 @@ read 65536/65536 bytes at offset 0 + {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 2560, "offset": 2560, "speed": 0, "type": "mirror"}} + {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}} + {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}} +-Warning: Image size mismatch! + Images are identical. + + === Copying sample image iotest-dirtylog-10G-4M.vhdx into raw === + +-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=SIZE + { 'execute': 'qmp_capabilities' } + {"return": {}} + {'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'mode': 'existing', 'sync': 'full'}} +@@ -343,8 +336,8 @@ WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed + {"execute":"quit"} + {"return": {}} + {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}} +-read 65536/65536 bytes at offset 0 +-64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++read 512/512 bytes at offset 0 ++512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + { 'execute': 'qmp_capabilities' } + {"return": {}} + {'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'format': 'IMGFMT', 'mode': 'existing', 'sync': 'full'}} +@@ -363,12 +356,11 @@ read 65536/65536 bytes at offset 0 + {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 31457280, "offset": 31457280, "speed": 0, "type": "mirror"}} + {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}} + {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}} +-Warning: Image size mismatch! + Images are identical. + + === Copying sample image parallels-v1 into raw === + +-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=SIZE + { 'execute': 'qmp_capabilities' } + {"return": {}} + {'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'mode': 'existing', 'sync': 'full'}} +@@ -388,8 +380,8 @@ WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed + {"execute":"quit"} + {"return": {}} + {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}} +-read 65536/65536 bytes at offset 0 +-64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++read 512/512 bytes at offset 0 ++512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + { 'execute': 'qmp_capabilities' } + {"return": {}} + {'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'format': 'IMGFMT', 'mode': 'existing', 'sync': 'full'}} +@@ -408,12 +400,11 @@ read 65536/65536 bytes at offset 0 + {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 327680, "offset": 327680, "speed": 0, "type": "mirror"}} + {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}} + {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}} +-Warning: Image size mismatch! + Images are identical. + + === Copying sample image simple-pattern.cloop into raw === + +-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=SIZE + { 'execute': 'qmp_capabilities' } + {"return": {}} + {'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'mode': 'existing', 'sync': 'full'}} +@@ -433,8 +424,8 @@ WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed + {"execute":"quit"} + {"return": {}} + {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}} +-read 65536/65536 bytes at offset 0 +-64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++read 512/512 bytes at offset 0 ++512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + { 'execute': 'qmp_capabilities' } + {"return": {}} + {'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'format': 'IMGFMT', 'mode': 'existing', 'sync': 'full'}} +@@ -453,12 +444,11 @@ read 65536/65536 bytes at offset 0 + {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 2048, "offset": 2048, "speed": 0, "type": "mirror"}} + {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}} + {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}} +-Warning: Image size mismatch! + Images are identical. + + === Write legitimate MBR into raw === + +-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=SIZE + { 'execute': 'qmp_capabilities' } + {"return": {}} + {'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'mode': 'existing', 'sync': 'full'}} +@@ -480,7 +470,6 @@ WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed + {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 512, "offset": 512, "speed": 0, "type": "mirror"}} + {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}} + {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}} +-Warning: Image size mismatch! + Images are identical. + { 'execute': 'qmp_capabilities' } + {"return": {}} +@@ -500,6 +489,5 @@ Images are identical. + {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 512, "offset": 512, "speed": 0, "type": "mirror"}} + {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}} + {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}} +-Warning: Image size mismatch! + Images are identical. + *** done +diff --git a/tests/qemu-iotests/common.filter b/tests/qemu-iotests/common.filter +index 279e0bbb0d..03e4f71808 100644 +--- a/tests/qemu-iotests/common.filter ++++ b/tests/qemu-iotests/common.filter +@@ -156,6 +156,11 @@ _filter_img_create() + -e "s# compression_type=[a-zA-Z0-9]\\+##g" + } + ++_filter_img_create_size() ++{ ++ $SED -e "s# size=[0-9]\\+# size=SIZE#g" ++} ++ + _filter_img_info() + { + if [[ "$1" == "--format-specific" ]]; then +-- +2.23.0 + diff --git a/iotests-109-mark-required-formats-as-required-to-sup.patch b/iotests-109-mark-required-formats-as-required-to-sup.patch new file mode 100644 index 0000000000000000000000000000000000000000..bb9957e41aba66acfe4e8436c400b6adaf51d62a --- /dev/null +++ b/iotests-109-mark-required-formats-as-required-to-sup.patch @@ -0,0 +1,28 @@ +From 503034efc8c443c9eee7d6c0d3850f9086d1dde4 Mon Sep 17 00:00:00 2001 +From: Vladimir Sementsov-Ogievskiy +Date: Thu, 30 Apr 2020 15:47:12 +0300 +Subject: [PATCH 334/709] iotests/109: mark required formats as required to + support whitelisting + +Signed-off-by: Vladimir Sementsov-Ogievskiy +Message-Id: <20200430124713.3067-8-vsementsov@virtuozzo.com> +Signed-off-by: Kevin Wolf +--- + tests/qemu-iotests/109 | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/tests/qemu-iotests/109 b/tests/qemu-iotests/109 +index a51dd84b3d..5bc2e9b001 100755 +--- a/tests/qemu-iotests/109 ++++ b/tests/qemu-iotests/109 +@@ -42,6 +42,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 15 + _supported_fmt raw + _supported_proto file + _supported_os Linux ++_require_drivers qcow qcow2 qed vdi vmdk vpc + + qemu_comm_method=qmp + +-- +2.23.0 + diff --git a/iotests-113-mark-bochs-as-required-to-support-whitel.patch b/iotests-113-mark-bochs-as-required-to-support-whitel.patch new file mode 100644 index 0000000000000000000000000000000000000000..76c2f2ae76792ac81fcb1c7035e5785e118061e8 --- /dev/null +++ b/iotests-113-mark-bochs-as-required-to-support-whitel.patch @@ -0,0 +1,31 @@ +From 5fc2b4f21811668c7cbbe907bdddab839fb50fe9 Mon Sep 17 00:00:00 2001 +From: Vladimir Sementsov-Ogievskiy +Date: Thu, 30 Apr 2020 15:47:13 +0300 +Subject: [PATCH 335/709] iotests/113: mark bochs as required to support + whitelisting + +Signed-off-by: Vladimir Sementsov-Ogievskiy +Message-Id: <20200430124713.3067-9-vsementsov@virtuozzo.com> +Signed-off-by: Kevin Wolf +--- + tests/qemu-iotests/113 | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/tests/qemu-iotests/113 b/tests/qemu-iotests/113 +index f2703a2c50..71a65de2e7 100755 +--- a/tests/qemu-iotests/113 ++++ b/tests/qemu-iotests/113 +@@ -37,8 +37,8 @@ trap "_cleanup; exit \$status" 0 1 2 3 15 + . ./common.rc + . ./common.filter + +-# Some of these test cases use bochs, but others do use raw, so this +-# is only half a lie. ++# Some of these test cases use bochs, but others do use raw ++_require_drivers bochs + _supported_fmt raw + _supported_proto file + _supported_os Linux +-- +2.23.0 + diff --git a/iotests-148-use-skip_if_unsupported.patch b/iotests-148-use-skip_if_unsupported.patch new file mode 100644 index 0000000000000000000000000000000000000000..0ba4e345ceb07abff3d1ff3970da6d9ed8897d65 --- /dev/null +++ b/iotests-148-use-skip_if_unsupported.patch @@ -0,0 +1,29 @@ +From 50bb041a3d0c611de38e1afbd8a6ac58e096da55 Mon Sep 17 00:00:00 2001 +From: Vladimir Sementsov-Ogievskiy +Date: Thu, 30 Apr 2020 15:47:08 +0300 +Subject: [PATCH 330/709] iotests/148: use skip_if_unsupported + +Skip test-case with quorum if quorum is not whitelisted. + +Signed-off-by: Vladimir Sementsov-Ogievskiy +Message-Id: <20200430124713.3067-4-vsementsov@virtuozzo.com> +Signed-off-by: Kevin Wolf +--- + tests/qemu-iotests/148 | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/tests/qemu-iotests/148 b/tests/qemu-iotests/148 +index 90931948e3..5e14a455b1 100755 +--- a/tests/qemu-iotests/148 ++++ b/tests/qemu-iotests/148 +@@ -47,6 +47,7 @@ sector = "%d" + ''' % bad_sector) + file.close() + ++ @iotests.skip_if_unsupported(['quorum']) + def setUp(self): + driveopts = ['driver=quorum', 'vote-threshold=2'] + driveopts.append('read-pattern=%s' % self.read_pattern) +-- +2.23.0 + diff --git a/iotests-229-Use-blkdebug-to-inject-an-error.patch b/iotests-229-Use-blkdebug-to-inject-an-error.patch new file mode 100644 index 0000000000000000000000000000000000000000..cc7bb42f4e8339a23725b7ae810951159dc8897f --- /dev/null +++ b/iotests-229-Use-blkdebug-to-inject-an-error.patch @@ -0,0 +1,108 @@ +From d89ac3cf305b28c024a76805a84d75c0ee1e786f Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Mon, 11 May 2020 15:58:23 +0200 +Subject: [PATCH 522/709] iotests/229: Use blkdebug to inject an error + +229 relies on the mirror running into an I/O error when the target is +smaller than the source. After changing mirror to catch this condition +while starting the job, this test case won't get a job that is paused +for an I/O error any more. Use blkdebug instead to inject an error. + +Signed-off-by: Kevin Wolf +Reviewed-by: Eric Blake +Message-Id: <20200511135825.219437-3-kwolf@redhat.com> +Reviewed-by: Max Reitz +Reviewed-by: Vladimir Sementsov-Ogievskiy +Signed-off-by: Kevin Wolf +--- + tests/qemu-iotests/229 | 18 +++++++++++++----- + tests/qemu-iotests/229.out | 6 +++--- + 2 files changed, 16 insertions(+), 8 deletions(-) + +diff --git a/tests/qemu-iotests/229 b/tests/qemu-iotests/229 +index 866168b236..99acb55ebb 100755 +--- a/tests/qemu-iotests/229 ++++ b/tests/qemu-iotests/229 +@@ -33,6 +33,7 @@ _cleanup() + _cleanup_test_img + _rm_test_img "$TEST_IMG" + _rm_test_img "$DEST_IMG" ++ rm -f "$TEST_DIR/blkdebug.conf" + } + trap "_cleanup; exit \$status" 0 1 2 3 15 + +@@ -49,11 +50,10 @@ _supported_os Linux + + DEST_IMG="$TEST_DIR/d.$IMGFMT" + TEST_IMG="$TEST_DIR/b.$IMGFMT" ++BLKDEBUG_CONF="$TEST_DIR/blkdebug.conf" + + _make_test_img 2M +- +-# destination for mirror will be too small, causing error +-TEST_IMG=$DEST_IMG _make_test_img 1M ++TEST_IMG=$DEST_IMG _make_test_img 2M + + $QEMU_IO -c 'write 0 2M' "$TEST_IMG" | _filter_qemu_io + +@@ -67,11 +67,18 @@ echo + echo '=== Starting drive-mirror, causing error & stop ===' + echo + ++cat > "$BLKDEBUG_CONF" < +Date: Thu, 30 Apr 2020 16:27:52 +0200 +Subject: [PATCH 343/709] iotests/283: Use consistent size for source and + target + +The test case forgot to specify the null-co size for the target node. +When adding a check to backup that both sizes match, this would fail +because of the size mismatch and not the behaviour that the test really +wanted to test. + +Fixes: a541fcc27c98b96da187c7d4573f3270f3ddd283 +Signed-off-by: Kevin Wolf +Message-Id: <20200430142755.315494-2-kwolf@redhat.com> +Reviewed-by: Vladimir Sementsov-Ogievskiy +Signed-off-by: Kevin Wolf +--- + tests/qemu-iotests/283 | 6 +++++- + tests/qemu-iotests/283.out | 2 +- + 2 files changed, 6 insertions(+), 2 deletions(-) + +diff --git a/tests/qemu-iotests/283 b/tests/qemu-iotests/283 +index e17b953333..383797ed62 100644 +--- a/tests/qemu-iotests/283 ++++ b/tests/qemu-iotests/283 +@@ -74,7 +74,11 @@ to check that crash is fixed :) + vm = iotests.VM() + vm.launch() + +-vm.qmp_log('blockdev-add', **{'node-name': 'target', 'driver': 'null-co'}) ++vm.qmp_log('blockdev-add', **{ ++ 'node-name': 'target', ++ 'driver': 'null-co', ++ 'size': size, ++}) + + vm.qmp_log('blockdev-add', **{ + 'node-name': 'source', +diff --git a/tests/qemu-iotests/283.out b/tests/qemu-iotests/283.out +index daaf5828c1..d8cff22cc1 100644 +--- a/tests/qemu-iotests/283.out ++++ b/tests/qemu-iotests/283.out +@@ -1,4 +1,4 @@ +-{"execute": "blockdev-add", "arguments": {"driver": "null-co", "node-name": "target"}} ++{"execute": "blockdev-add", "arguments": {"driver": "null-co", "node-name": "target", "size": 1048576}} + {"return": {}} + {"execute": "blockdev-add", "arguments": {"driver": "blkdebug", "image": {"driver": "null-co", "node-name": "base", "size": 1048576}, "node-name": "source"}} + {"return": {}} +-- +2.23.0 + diff --git a/iotests-287-add-qcow2-compression-type-test.patch b/iotests-287-add-qcow2-compression-type-test.patch new file mode 100644 index 0000000000000000000000000000000000000000..cd1db104984487c5fb33ad09a76c2cf9d358417a --- /dev/null +++ b/iotests-287-add-qcow2-compression-type-test.patch @@ -0,0 +1,268 @@ +From dd488fc1c000700741355426198d240c6f25ccb7 Mon Sep 17 00:00:00 2001 +From: Denis Plotnikov +Date: Thu, 7 May 2020 11:25:21 +0300 +Subject: [PATCH 396/709] iotests: 287: add qcow2 compression type test + +The test checks fulfilling qcow2 requirements for the compression +type feature and zstd compression type operability. + +Signed-off-by: Denis Plotnikov +Reviewed-by: Vladimir Sementsov-Ogievskiy +Tested-by: Vladimir Sementsov-Ogievskiy +Reviewed-by: Eric Blake +Message-Id: <20200507082521.29210-5-dplotnikov@virtuozzo.com> +Signed-off-by: Max Reitz +--- + tests/qemu-iotests/287 | 152 +++++++++++++++++++++++++++++++++++++ + tests/qemu-iotests/287.out | 67 ++++++++++++++++ + tests/qemu-iotests/group | 1 + + 3 files changed, 220 insertions(+) + create mode 100755 tests/qemu-iotests/287 + create mode 100644 tests/qemu-iotests/287.out + +diff --git a/tests/qemu-iotests/287 b/tests/qemu-iotests/287 +new file mode 100755 +index 0000000000..f98a4cadc1 +--- /dev/null ++++ b/tests/qemu-iotests/287 +@@ -0,0 +1,152 @@ ++#!/usr/bin/env bash ++# ++# Test case for an image using zstd compression ++# ++# Copyright (c) 2020 Virtuozzo International GmbH ++# ++# 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 . ++# ++ ++# creator ++owner=dplotnikov@virtuozzo.com ++ ++seq="$(basename $0)" ++echo "QA output created by $seq" ++ ++status=1 # failure is the default! ++ ++# standard environment ++. ./common.rc ++. ./common.filter ++ ++# This tests qocw2-specific low-level functionality ++_supported_fmt qcow2 ++_supported_proto file ++_supported_os Linux ++_unsupported_imgopts 'compat=0.10' data_file ++ ++COMPR_IMG="$TEST_IMG.compressed" ++RAND_FILE="$TEST_DIR/rand_data" ++ ++_cleanup() ++{ ++ _cleanup_test_img ++ _rm_test_img "$COMPR_IMG" ++ rm -f "$RAND_FILE" ++} ++trap "_cleanup; exit \$status" 0 1 2 3 15 ++ ++# for all the cases ++CLUSTER_SIZE=65536 ++ ++# Check if we can run this test. ++if IMGOPTS='compression_type=zstd' _make_test_img 64M | ++ grep "Invalid parameter 'zstd'"; then ++ _notrun "ZSTD is disabled" ++fi ++ ++echo ++echo "=== Testing compression type incompatible bit setting for zlib ===" ++echo ++_make_test_img -o compression_type=zlib 64M ++$PYTHON qcow2.py "$TEST_IMG" dump-header | grep incompatible_features ++ ++echo ++echo "=== Testing compression type incompatible bit setting for zstd ===" ++echo ++_make_test_img -o compression_type=zstd 64M ++$PYTHON qcow2.py "$TEST_IMG" dump-header | grep incompatible_features ++ ++echo ++echo "=== Testing zlib with incompatible bit set ===" ++echo ++_make_test_img -o compression_type=zlib 64M ++$PYTHON qcow2.py "$TEST_IMG" set-feature-bit incompatible 3 ++# to make sure the bit was actually set ++$PYTHON qcow2.py "$TEST_IMG" dump-header | grep incompatible_features ++ ++if $QEMU_IMG info "$TEST_IMG" >/dev/null 2>&1 ; then ++ echo "Error: The image opened successfully. The image must not be opened." ++fi ++ ++echo ++echo "=== Testing zstd with incompatible bit unset ===" ++echo ++_make_test_img -o compression_type=zstd 64M ++$PYTHON qcow2.py "$TEST_IMG" set-header incompatible_features 0 ++# to make sure the bit was actually unset ++$PYTHON qcow2.py "$TEST_IMG" dump-header | grep incompatible_features ++ ++if $QEMU_IMG info "$TEST_IMG" >/dev/null 2>&1 ; then ++ echo "Error: The image opened successfully. The image must not be opened." ++fi ++ ++echo ++echo "=== Testing compression type values ===" ++echo ++# zlib=0 ++_make_test_img -o compression_type=zlib 64M ++peek_file_be "$TEST_IMG" 104 1 ++echo ++ ++# zstd=1 ++_make_test_img -o compression_type=zstd 64M ++peek_file_be "$TEST_IMG" 104 1 ++echo ++ ++echo ++echo "=== Testing simple reading and writing with zstd ===" ++echo ++_make_test_img -o compression_type=zstd 64M ++$QEMU_IO -c "write -c -P 0xAC 64K 64K " "$TEST_IMG" | _filter_qemu_io ++$QEMU_IO -c "read -P 0xAC 64K 64K " "$TEST_IMG" | _filter_qemu_io ++# read on the cluster boundaries ++$QEMU_IO -c "read -v 131070 8 " "$TEST_IMG" | _filter_qemu_io ++$QEMU_IO -c "read -v 65534 8" "$TEST_IMG" | _filter_qemu_io ++ ++echo ++echo "=== Testing adjacent clusters reading and writing with zstd ===" ++echo ++_make_test_img -o compression_type=zstd 64M ++$QEMU_IO -c "write -c -P 0xAB 0 64K " "$TEST_IMG" | _filter_qemu_io ++$QEMU_IO -c "write -c -P 0xAC 64K 64K " "$TEST_IMG" | _filter_qemu_io ++$QEMU_IO -c "write -c -P 0xAD 128K 64K " "$TEST_IMG" | _filter_qemu_io ++ ++$QEMU_IO -c "read -P 0xAB 0 64k " "$TEST_IMG" | _filter_qemu_io ++$QEMU_IO -c "read -P 0xAC 64K 64k " "$TEST_IMG" | _filter_qemu_io ++$QEMU_IO -c "read -P 0xAD 128K 64k " "$TEST_IMG" | _filter_qemu_io ++ ++echo ++echo "=== Testing incompressible cluster processing with zstd ===" ++echo ++# create a 2M image and fill it with 1M likely incompressible data ++# and 1M compressible data ++dd if=/dev/urandom of="$RAND_FILE" bs=1M count=1 seek=1 ++QEMU_IO_OPTIONS="$QEMU_IO_OPTIONS_NO_FMT" \ ++$QEMU_IO -f raw -c "write -P 0xFA 0 1M" "$RAND_FILE" | _filter_qemu_io ++ ++$QEMU_IMG convert -f raw -O $IMGFMT -c \ ++-o "$(_optstr_add "$IMGOPTS" "compression_type=zlib")" "$RAND_FILE" \ ++"$TEST_IMG" | _filter_qemu_io ++ ++$QEMU_IMG convert -O $IMGFMT -c \ ++-o "$(_optstr_add "$IMGOPTS" "compression_type=zstd")" "$TEST_IMG" \ ++"$COMPR_IMG" | _filter_qemu_io ++ ++$QEMU_IMG compare "$TEST_IMG" "$COMPR_IMG" ++ ++# success, all done ++echo "*** done" ++rm -f $seq.full ++status=0 +diff --git a/tests/qemu-iotests/287.out b/tests/qemu-iotests/287.out +new file mode 100644 +index 0000000000..6b9dfb4af0 +--- /dev/null ++++ b/tests/qemu-iotests/287.out +@@ -0,0 +1,67 @@ ++QA output created by 287 ++ ++=== Testing compression type incompatible bit setting for zlib === ++ ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 ++incompatible_features [] ++ ++=== Testing compression type incompatible bit setting for zstd === ++ ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 ++incompatible_features [3] ++ ++=== Testing zlib with incompatible bit set === ++ ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 ++incompatible_features [3] ++ ++=== Testing zstd with incompatible bit unset === ++ ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 ++incompatible_features [] ++ ++=== Testing compression type values === ++ ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 ++ 0 ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 ++ 1 ++ ++=== Testing simple reading and writing with zstd === ++ ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 ++wrote 65536/65536 bytes at offset 65536 ++64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++read 65536/65536 bytes at offset 65536 ++64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++0001fffe: ac ac 00 00 00 00 00 00 ........ ++read 8/8 bytes at offset 131070 ++8 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++0000fffe: 00 00 ac ac ac ac ac ac ........ ++read 8/8 bytes at offset 65534 ++8 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++ ++=== Testing adjacent clusters reading and writing with zstd === ++ ++Formatting 'TEST_DIR/t.IMGFMT', 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 65536/65536 bytes at offset 65536 ++64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++wrote 65536/65536 bytes at offset 131072 ++64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++read 65536/65536 bytes at offset 0 ++64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++read 65536/65536 bytes at offset 65536 ++64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++read 65536/65536 bytes at offset 131072 ++64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++ ++=== Testing incompressible cluster processing with zstd === ++ ++1+0 records in ++1+0 records out ++wrote 1048576/1048576 bytes at offset 0 ++1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++Images are identical. ++*** done +diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group +index fe649c5b73..34175fd437 100644 +--- a/tests/qemu-iotests/group ++++ b/tests/qemu-iotests/group +@@ -295,6 +295,7 @@ + 283 auto quick + 284 rw + 286 rw quick ++287 auto quick + 288 quick + 289 rw quick + 290 rw auto quick +-- +2.23.0 + diff --git a/iotests-Backup-with-different-source-target-size.patch b/iotests-Backup-with-different-source-target-size.patch new file mode 100644 index 0000000000000000000000000000000000000000..3893e9c1f9f7d90bdcf2c975c9fff2278e778813 --- /dev/null +++ b/iotests-Backup-with-different-source-target-size.patch @@ -0,0 +1,92 @@ +From 0a82a9273062d05764e3df3637b3aa95ad8291c6 Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Thu, 30 Apr 2020 16:27:55 +0200 +Subject: [PATCH 346/709] iotests: Backup with different source/target size + +This tests that the backup job catches situations where the target node +has a different size than the source node. It must also forbid resize +operations when the job is already running. + +Signed-off-by: Kevin Wolf +Message-Id: <20200430142755.315494-5-kwolf@redhat.com> +Reviewed-by: Vladimir Sementsov-Ogievskiy +Signed-off-by: Kevin Wolf +--- + tests/qemu-iotests/055 | 41 ++++++++++++++++++++++++++++++++++++-- + tests/qemu-iotests/055.out | 4 ++-- + 2 files changed, 41 insertions(+), 4 deletions(-) + +diff --git a/tests/qemu-iotests/055 b/tests/qemu-iotests/055 +index e250f798f9..7f8e630de3 100755 +--- a/tests/qemu-iotests/055 ++++ b/tests/qemu-iotests/055 +@@ -48,8 +48,10 @@ class TestSingleDrive(iotests.QMPTestCase): + def setUp(self): + qemu_img('create', '-f', iotests.imgfmt, blockdev_target_img, str(image_len)) + +- self.vm = iotests.VM().add_drive('blkdebug::' + test_img) +- self.vm.add_drive(blockdev_target_img, interface="none") ++ self.vm = iotests.VM() ++ self.vm.add_drive('blkdebug::' + test_img, 'node-name=source') ++ self.vm.add_drive(blockdev_target_img, 'node-name=target', ++ interface="none") + if iotests.qemu_default_machine == 'pc': + self.vm.add_drive(None, 'media=cdrom', 'ide') + self.vm.launch() +@@ -112,6 +114,41 @@ class TestSingleDrive(iotests.QMPTestCase): + def test_pause_blockdev_backup(self): + self.do_test_pause('blockdev-backup', 'drive1', blockdev_target_img) + ++ def do_test_resize_blockdev_backup(self, device, node): ++ def pre_finalize(): ++ result = self.vm.qmp('block_resize', device=device, size=65536) ++ self.assert_qmp(result, 'error/class', 'GenericError') ++ ++ result = self.vm.qmp('block_resize', node_name=node, size=65536) ++ self.assert_qmp(result, 'error/class', 'GenericError') ++ ++ result = self.vm.qmp('blockdev-backup', job_id='job0', device='drive0', ++ target='drive1', sync='full', auto_finalize=False, ++ auto_dismiss=False) ++ self.assert_qmp(result, 'return', {}) ++ ++ self.vm.run_job('job0', auto_finalize=False, pre_finalize=pre_finalize) ++ ++ def test_source_resize_blockdev_backup(self): ++ self.do_test_resize_blockdev_backup('drive0', 'source') ++ ++ def test_target_resize_blockdev_backup(self): ++ self.do_test_resize_blockdev_backup('drive1', 'target') ++ ++ def do_test_target_size(self, size): ++ result = self.vm.qmp('block_resize', device='drive1', size=size) ++ self.assert_qmp(result, 'return', {}) ++ ++ result = self.vm.qmp('blockdev-backup', job_id='job0', device='drive0', ++ target='drive1', sync='full') ++ self.assert_qmp(result, 'error/class', 'GenericError') ++ ++ def test_small_target(self): ++ self.do_test_target_size(image_len // 2) ++ ++ def test_large_target(self): ++ self.do_test_target_size(image_len * 2) ++ + def test_medium_not_found(self): + if iotests.qemu_default_machine != 'pc': + return +diff --git a/tests/qemu-iotests/055.out b/tests/qemu-iotests/055.out +index 5c26d15c0d..0a5e9583a4 100644 +--- a/tests/qemu-iotests/055.out ++++ b/tests/qemu-iotests/055.out +@@ -1,5 +1,5 @@ +-.................................... ++........................................ + ---------------------------------------------------------------------- +-Ran 36 tests ++Ran 40 tests + + OK +-- +2.23.0 + diff --git a/iotests-Enhance-223-to-cover-qemu-img-map-improvemen.patch b/iotests-Enhance-223-to-cover-qemu-img-map-improvemen.patch new file mode 100644 index 0000000000000000000000000000000000000000..819a6ee3fb5210cd04f18aedf6835ddc8b39289f --- /dev/null +++ b/iotests-Enhance-223-to-cover-qemu-img-map-improvemen.patch @@ -0,0 +1,58 @@ +From d8154b0945f795177511ea0e2212bd5c749fe84c Mon Sep 17 00:00:00 2001 +From: Eric Blake +Date: Wed, 13 May 2020 12:58:34 -0500 +Subject: [PATCH 520/709] iotests: Enhance 223 to cover qemu-img map + improvements + +Since qemu-img map + x-dirty-bitmap remains the easiest way to read +persistent bitmaps at the moment, it makes a reasonable place to add +coverage to ensure we do not regress on the just-added parameters to +qemu-img map. + +Signed-off-by: Eric Blake +Message-Id: <20200513181455.295267-1-eblake@redhat.com> +--- + tests/qemu-iotests/223 | 6 ++++-- + tests/qemu-iotests/223.out | 3 ++- + 2 files changed, 6 insertions(+), 3 deletions(-) + +diff --git a/tests/qemu-iotests/223 b/tests/qemu-iotests/223 +index 56fbc5fb09..d68bc3cb6f 100755 +--- a/tests/qemu-iotests/223 ++++ b/tests/qemu-iotests/223 +@@ -2,7 +2,7 @@ + # + # Test reading dirty bitmap over NBD + # +-# Copyright (C) 2018-2019 Red Hat, Inc. ++# Copyright (C) 2018-2020 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 +@@ -206,7 +206,9 @@ $QEMU_IMG map --output=json --image-opts \ + + nbd_server_start_unix_socket -f $IMGFMT -B b2 "$TEST_IMG" + IMG="driver=nbd,server.type=unix,server.path=$nbd_unix_socket" +-$QEMU_IMG map --output=json --image-opts \ ++$QEMU_IMG map --output=json --image-opts --max-length=12345 \ ++ "$IMG,x-dirty-bitmap=qemu:dirty-bitmap:b2" | _filter_qemu_img_map ++$QEMU_IMG map --output=json --image-opts --start-offset=12345 \ + "$IMG,x-dirty-bitmap=qemu:dirty-bitmap:b2" | _filter_qemu_img_map + + # success, all done +diff --git a/tests/qemu-iotests/223.out b/tests/qemu-iotests/223.out +index 80c0cf6509..e1eaaedb55 100644 +--- a/tests/qemu-iotests/223.out ++++ b/tests/qemu-iotests/223.out +@@ -201,6 +201,7 @@ read 2097152/2097152 bytes at offset 2097152 + { "start": 2097152, "length": 2097152, "depth": 0, "zero": false, "data": false}] + [{ "start": 0, "length": 512, "depth": 0, "zero": false, "data": true, "offset": OFFSET}, + { "start": 512, "length": 512, "depth": 0, "zero": false, "data": false}, +-{ "start": 1024, "length": 2096128, "depth": 0, "zero": false, "data": true, "offset": OFFSET}, ++{ "start": 1024, "length": 11321, "depth": 0, "zero": false, "data": true, "offset": OFFSET}] ++[{ "start": 12345, "length": 2084807, "depth": 0, "zero": false, "data": true, "offset": OFFSET}, + { "start": 2097152, "length": 2097152, "depth": 0, "zero": false, "data": false}] + *** done +-- +2.23.0 + diff --git a/iotests-Filter-testfiles-out-in-filter_img_info.patch b/iotests-Filter-testfiles-out-in-filter_img_info.patch new file mode 100644 index 0000000000000000000000000000000000000000..c2b5e81b78d1e29b52748a1da706a5c01612c9de --- /dev/null +++ b/iotests-Filter-testfiles-out-in-filter_img_info.patch @@ -0,0 +1,40 @@ +From fd586ce8bee50d98773436214dc9e644ddda54aa Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Fri, 24 Apr 2020 14:54:46 +0200 +Subject: [PATCH 133/709] iotests: Filter testfiles out in filter_img_info() + +We want to keep TEST_IMG for the full path of the main test image, but +filter_testfiles() must be called for other test images before replacing +other things like the image format because the test directory path could +contain the format as a substring. + +Insert a filter_testfiles() call between both. + +Signed-off-by: Kevin Wolf +Reviewed-by: Max Reitz +Reviewed-by: Vladimir Sementsov-Ogievskiy +Message-Id: <20200424125448.63318-9-kwolf@redhat.com> +Signed-off-by: Kevin Wolf +--- + tests/qemu-iotests/iotests.py | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py +index 7bc4934cd2..5f8c263d59 100644 +--- a/tests/qemu-iotests/iotests.py ++++ b/tests/qemu-iotests/iotests.py +@@ -338,8 +338,9 @@ def filter_img_info(output, filename): + for line in output.split('\n'): + if 'disk size' in line or 'actual-size' in line: + continue +- line = line.replace(filename, 'TEST_IMG') \ +- .replace(imgfmt, 'IMGFMT') ++ line = line.replace(filename, 'TEST_IMG') ++ line = filter_testfiles(line) ++ line = line.replace(imgfmt, 'IMGFMT') + line = re.sub('iters: [0-9]+', 'iters: XXX', line) + line = re.sub('uuid: [-a-f0-9]+', 'uuid: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX', line) + line = re.sub('cid: [0-9]+', 'cid: XXXXXXXXXX', line) +-- +2.23.0 + diff --git a/iotests-Fix-incomplete-type-declarations.patch b/iotests-Fix-incomplete-type-declarations.patch new file mode 100644 index 0000000000000000000000000000000000000000..fc190dd9b720f7083c68e6e42198ee11e678a8c9 --- /dev/null +++ b/iotests-Fix-incomplete-type-declarations.patch @@ -0,0 +1,55 @@ +From cd8f5b75927afdd8ac2378f4360208e0aa8f58e2 Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Mon, 11 May 2020 18:35:28 +0200 +Subject: [PATCH 526/709] iotests: Fix incomplete type declarations + +We need to fix only a few places so that iotests.py can pass +mypy --disallow-incomplete-defs, which seems to be a desirable option to +have enabled in the long run. + +Signed-off-by: Kevin Wolf +Message-Id: <20200511163529.349329-2-kwolf@redhat.com> +Reviewed-by: Max Reitz +Reviewed-by: John Snow +Signed-off-by: Kevin Wolf +--- + tests/qemu-iotests/iotests.py | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py +index 6c0e781af7..1d7f6fd7cf 100644 +--- a/tests/qemu-iotests/iotests.py ++++ b/tests/qemu-iotests/iotests.py +@@ -1040,7 +1040,7 @@ def _verify_cache_mode(supported_cache_modes: Sequence[str] = ()) -> None: + if supported_cache_modes and (cachemode not in supported_cache_modes): + notrun('not suitable for this cache mode: %s' % cachemode) + +-def _verify_aio_mode(supported_aio_modes: Sequence[str] = ()): ++def _verify_aio_mode(supported_aio_modes: Sequence[str] = ()) -> None: + if supported_aio_modes and (aiomode not in supported_aio_modes): + notrun('not suitable for this aio mode: %s' % aiomode) + +@@ -1087,7 +1087,8 @@ def skip_if_unsupported(required_formats=(), read_only=False): + '''Skip Test Decorator + Runs the test if all the required formats are whitelisted''' + def skip_test_decorator(func): +- def func_wrapper(test_case: QMPTestCase, *args, **kwargs): ++ def func_wrapper(test_case: QMPTestCase, *args: List[Any], ++ **kwargs: Dict[str, Any]) -> None: + if callable(required_formats): + fmts = required_formats(test_case) + else: +@@ -1097,9 +1098,8 @@ def skip_if_unsupported(required_formats=(), read_only=False): + if usf_list: + msg = f'{test_case}: formats {usf_list} are not whitelisted' + test_case.case_skip(msg) +- return None + else: +- return func(test_case, *args, **kwargs) ++ func(test_case, *args, **kwargs) + return func_wrapper + return skip_test_decorator + +-- +2.23.0 + diff --git a/iotests-Mark-verify-functions-as-private.patch b/iotests-Mark-verify-functions-as-private.patch new file mode 100644 index 0000000000000000000000000000000000000000..4eb7355c5892c12ad625770ab4ed894ef6ad4058 --- /dev/null +++ b/iotests-Mark-verify-functions-as-private.patch @@ -0,0 +1,88 @@ +From 59c29869e0c5e8875edc50a0e3073eeaa8fe6143 Mon Sep 17 00:00:00 2001 +From: John Snow +Date: Mon, 30 Mar 2020 20:00:13 -0400 +Subject: [PATCH 253/709] iotests: Mark verify functions as private + +Mark the verify functions as "private" with a leading underscore, to +discourage their use. Update type signatures while we're here. + +(Also, make pending patches not yet using the new entry points fail in a +very obvious way.) + +Signed-off-by: John Snow +Message-Id: <20200331000014.11581-14-jsnow@redhat.com> +Reviewed-by: Max Reitz +Reviewed-by: Kevin Wolf +Signed-off-by: Max Reitz +--- + tests/qemu-iotests/iotests.py | 23 +++++++++++++---------- + 1 file changed, 13 insertions(+), 10 deletions(-) + +diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py +index 9f85e1fba3..35d8cae997 100644 +--- a/tests/qemu-iotests/iotests.py ++++ b/tests/qemu-iotests/iotests.py +@@ -1006,7 +1006,8 @@ def case_notrun(reason): + open('%s/%s.casenotrun' % (output_dir, seq), 'a').write( + ' [case not run] ' + reason + '\n') + +-def verify_image_format(supported_fmts=(), unsupported_fmts=()): ++def _verify_image_format(supported_fmts: Sequence[str] = (), ++ unsupported_fmts: Sequence[str] = ()) -> None: + assert not (supported_fmts and unsupported_fmts) + + if 'generic' in supported_fmts and \ +@@ -1020,7 +1021,8 @@ def verify_image_format(supported_fmts=(), unsupported_fmts=()): + if not_sup or (imgfmt in unsupported_fmts): + notrun('not suitable for this image format: %s' % imgfmt) + +-def verify_protocol(supported=(), unsupported=()): ++def _verify_protocol(supported: Sequence[str] = (), ++ unsupported: Sequence[str] = ()) -> None: + assert not (supported and unsupported) + + if 'generic' in supported: +@@ -1030,7 +1032,8 @@ def verify_protocol(supported=(), unsupported=()): + if not_sup or (imgproto in unsupported): + notrun('not suitable for this protocol: %s' % imgproto) + +-def verify_platform(supported=(), unsupported=()): ++def _verify_platform(supported: Sequence[str] = (), ++ unsupported: Sequence[str] = ()) -> None: + if any((sys.platform.startswith(x) for x in unsupported)): + notrun('not suitable for this OS: %s' % sys.platform) + +@@ -1038,11 +1041,11 @@ def verify_platform(supported=(), unsupported=()): + if not any((sys.platform.startswith(x) for x in supported)): + notrun('not suitable for this OS: %s' % sys.platform) + +-def verify_cache_mode(supported_cache_modes=()): ++def _verify_cache_mode(supported_cache_modes: Sequence[str] = ()) -> None: + if supported_cache_modes and (cachemode not in supported_cache_modes): + notrun('not suitable for this cache mode: %s' % cachemode) + +-def verify_aio_mode(supported_aio_modes=()): ++def _verify_aio_mode(supported_aio_modes: Sequence[str] = ()): + if supported_aio_modes and (aiomode not in supported_aio_modes): + notrun('not suitable for this aio mode: %s' % aiomode) + +@@ -1170,11 +1173,11 @@ def execute_setup_common(supported_fmts: Sequence[str] = (), + sys.stderr.write('Please run this test via the "check" script\n') + sys.exit(os.EX_USAGE) + +- verify_image_format(supported_fmts, unsupported_fmts) +- verify_protocol(supported_protocols, unsupported_protocols) +- verify_platform(supported=supported_platforms) +- verify_cache_mode(supported_cache_modes) +- verify_aio_mode(supported_aio_modes) ++ _verify_image_format(supported_fmts, unsupported_fmts) ++ _verify_protocol(supported_protocols, unsupported_protocols) ++ _verify_platform(supported=supported_platforms) ++ _verify_cache_mode(supported_cache_modes) ++ _verify_aio_mode(supported_aio_modes) + + debug = '-d' in sys.argv + if debug: +-- +2.23.0 + diff --git a/iotests-Mirror-with-different-source-target-size.patch b/iotests-Mirror-with-different-source-target-size.patch new file mode 100644 index 0000000000000000000000000000000000000000..656c3fc0d888ccb53b40433ca9b776bba4c7f4de --- /dev/null +++ b/iotests-Mirror-with-different-source-target-size.patch @@ -0,0 +1,98 @@ +From 16cea4ee1c8e5a69a058e76f426b2e17974d8d7d Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Mon, 11 May 2020 15:58:25 +0200 +Subject: [PATCH 524/709] iotests: Mirror with different source/target size + +This tests that the mirror job catches situations where the target node +has a different size than the source node. It must also forbid resize +operations when the job is already running. + +Signed-off-by: Kevin Wolf +Reviewed-by: Eric Blake +Message-Id: <20200511135825.219437-5-kwolf@redhat.com> +Reviewed-by: Max Reitz +Reviewed-by: Vladimir Sementsov-Ogievskiy +Signed-off-by: Kevin Wolf +--- + tests/qemu-iotests/041 | 45 ++++++++++++++++++++++++++++++++++++++ + tests/qemu-iotests/041.out | 4 ++-- + 2 files changed, 47 insertions(+), 2 deletions(-) + +diff --git a/tests/qemu-iotests/041 b/tests/qemu-iotests/041 +index 1812dd8479..601c756117 100755 +--- a/tests/qemu-iotests/041 ++++ b/tests/qemu-iotests/041 +@@ -240,6 +240,49 @@ class TestSingleBlockdev(TestSingleDrive): + target=self.qmp_target) + self.assert_qmp(result, 'error/class', 'GenericError') + ++ def do_test_resize(self, device, node): ++ def pre_finalize(): ++ if device: ++ result = self.vm.qmp('block_resize', device=device, size=65536) ++ self.assert_qmp(result, 'error/class', 'GenericError') ++ ++ result = self.vm.qmp('block_resize', node_name=node, size=65536) ++ self.assert_qmp(result, 'error/class', 'GenericError') ++ ++ result = self.vm.qmp(self.qmp_cmd, job_id='job0', device='drive0', ++ sync='full', target=self.qmp_target, ++ auto_finalize=False, auto_dismiss=False) ++ self.assert_qmp(result, 'return', {}) ++ ++ result = self.vm.run_job('job0', auto_finalize=False, ++ pre_finalize=pre_finalize) ++ self.assertEqual(result, None) ++ ++ def test_source_resize(self): ++ self.do_test_resize('drive0', 'top') ++ ++ def test_target_resize(self): ++ self.do_test_resize(None, self.qmp_target) ++ ++ def do_test_target_size(self, size): ++ result = self.vm.qmp('block_resize', node_name=self.qmp_target, ++ size=size) ++ self.assert_qmp(result, 'return', {}) ++ ++ result = self.vm.qmp(self.qmp_cmd, job_id='job0', ++ device='drive0', sync='full', auto_dismiss=False, ++ target=self.qmp_target) ++ self.assert_qmp(result, 'return', {}) ++ ++ result = self.vm.run_job('job0') ++ self.assertEqual(result, 'Source and target image have different sizes') ++ ++ def test_small_target(self): ++ self.do_test_target_size(self.image_len // 2) ++ ++ def test_large_target(self): ++ self.do_test_target_size(self.image_len * 2) ++ + test_large_cluster = None + test_image_not_found = None + test_small_buffer2 = None +@@ -251,6 +294,8 @@ class TestSingleDriveZeroLength(TestSingleDrive): + + class TestSingleBlockdevZeroLength(TestSingleBlockdev): + image_len = 0 ++ test_small_target = None ++ test_large_target = None + + class TestSingleDriveUnalignedLength(TestSingleDrive): + image_len = 1025 * 1024 +diff --git a/tests/qemu-iotests/041.out b/tests/qemu-iotests/041.out +index 877b76fd31..53abe11d73 100644 +--- a/tests/qemu-iotests/041.out ++++ b/tests/qemu-iotests/041.out +@@ -1,5 +1,5 @@ +-.............................................................................................. ++........................................................................................................ + ---------------------------------------------------------------------- +-Ran 94 tests ++Ran 104 tests + + OK +-- +2.23.0 + diff --git a/iotests-Run-pylint-and-mypy-in-a-testcase.patch b/iotests-Run-pylint-and-mypy-in-a-testcase.patch new file mode 100644 index 0000000000000000000000000000000000000000..8c3aaaea1386ba9fcb8e68fddc89fe2f73f8f380 --- /dev/null +++ b/iotests-Run-pylint-and-mypy-in-a-testcase.patch @@ -0,0 +1,97 @@ +From 19b7868eff865c01985a5d37f1c9c0c8691b0001 Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Mon, 11 May 2020 18:35:29 +0200 +Subject: [PATCH 527/709] iotests: Run pylint and mypy in a testcase + +We made sure that iotests.py passes pylint. It would be a shame if we +allowed new patches in that break this again, so let's just add a +meta-test case that runs pylint on it. + +While we don't pass mypy --strict yet, we can already run it with a few +options that would be part of --strict to make sure that we won't +regress on these aspects at least until we can enable the full thing. + +Signed-off-by: Kevin Wolf +Message-Id: <20200511163529.349329-3-kwolf@redhat.com> +Reviewed-by: Max Reitz +Reviewed-by: John Snow +Signed-off-by: Kevin Wolf +--- + tests/qemu-iotests/297 | 44 ++++++++++++++++++++++++++++++++++++++ + tests/qemu-iotests/297.out | 3 +++ + tests/qemu-iotests/group | 1 + + 3 files changed, 48 insertions(+) + create mode 100755 tests/qemu-iotests/297 + create mode 100644 tests/qemu-iotests/297.out + +diff --git a/tests/qemu-iotests/297 b/tests/qemu-iotests/297 +new file mode 100755 +index 0000000000..5c5420712b +--- /dev/null ++++ b/tests/qemu-iotests/297 +@@ -0,0 +1,44 @@ ++#!/usr/bin/env bash ++# ++# Copyright (C) 2020 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 . ++ ++seq=$(basename $0) ++echo "QA output created by $seq" ++ ++status=1 # failure is the default! ++ ++# get standard environment ++. ./common.rc ++ ++if ! type -p "pylint-3" > /dev/null; then ++ _notrun "pylint-3 not found" ++fi ++if ! type -p "mypy" > /dev/null; then ++ _notrun "mypy not found" ++fi ++ ++pylint-3 --score=n iotests.py ++ ++MYPYPATH=../../python/ mypy --warn-unused-configs --disallow-subclassing-any \ ++ --disallow-any-generics --disallow-incomplete-defs \ ++ --disallow-untyped-decorators --no-implicit-optional \ ++ --warn-redundant-casts --warn-unused-ignores \ ++ --no-implicit-reexport iotests.py ++ ++# success, all done ++echo "*** done" ++rm -f $seq.full ++status=0 +diff --git a/tests/qemu-iotests/297.out b/tests/qemu-iotests/297.out +new file mode 100644 +index 0000000000..6acc843649 +--- /dev/null ++++ b/tests/qemu-iotests/297.out +@@ -0,0 +1,3 @@ ++QA output created by 297 ++Success: no issues found in 1 source file ++*** done +diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group +index 34175fd437..445c26f8d2 100644 +--- a/tests/qemu-iotests/group ++++ b/tests/qemu-iotests/group +@@ -300,3 +300,4 @@ + 289 rw quick + 290 rw auto quick + 292 rw auto quick ++297 meta +-- +2.23.0 + diff --git a/iotests-Test-committing-to-short-backing-file.patch b/iotests-Test-committing-to-short-backing-file.patch new file mode 100644 index 0000000000000000000000000000000000000000..f29d7493094074241976eeeec03232eb9d9de43f --- /dev/null +++ b/iotests-Test-committing-to-short-backing-file.patch @@ -0,0 +1,468 @@ +From bf03dede475e29a16f9188ea85a4d77cd3dcf2b7 Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Fri, 24 Apr 2020 14:54:47 +0200 +Subject: [PATCH 134/709] iotests: Test committing to short backing file + +Signed-off-by: Kevin Wolf +Message-Id: <20200424125448.63318-10-kwolf@redhat.com> +Reviewed-by: Max Reitz +Reviewed-by: Vladimir Sementsov-Ogievskiy +Signed-off-by: Kevin Wolf +--- + tests/qemu-iotests/274 | 155 +++++++++++++++++++++ + tests/qemu-iotests/274.out | 268 +++++++++++++++++++++++++++++++++++++ + tests/qemu-iotests/group | 1 + + 3 files changed, 424 insertions(+) + create mode 100755 tests/qemu-iotests/274 + create mode 100644 tests/qemu-iotests/274.out + +diff --git a/tests/qemu-iotests/274 b/tests/qemu-iotests/274 +new file mode 100755 +index 0000000000..e951f723b8 +--- /dev/null ++++ b/tests/qemu-iotests/274 +@@ -0,0 +1,155 @@ ++#!/usr/bin/env python3 ++# ++# Copyright (C) 2019 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 . ++# ++# Creator/Owner: Kevin Wolf ++# ++# Some tests for short backing files and short overlays ++ ++import iotests ++ ++iotests.verify_image_format(supported_fmts=['qcow2']) ++iotests.verify_platform(['linux']) ++ ++size_short = 1 * 1024 * 1024 ++size_long = 2 * 1024 * 1024 ++size_diff = size_long - size_short ++ ++def create_chain() -> None: ++ iotests.qemu_img_log('create', '-f', iotests.imgfmt, base, ++ str(size_long)) ++ iotests.qemu_img_log('create', '-f', iotests.imgfmt, '-b', base, mid, ++ str(size_short)) ++ iotests.qemu_img_log('create', '-f', iotests.imgfmt, '-b', mid, top, ++ str(size_long)) ++ ++ iotests.qemu_io_log('-c', 'write -P 1 0 %d' % size_long, base) ++ ++def create_vm() -> iotests.VM: ++ vm = iotests.VM() ++ vm.add_blockdev('file,filename=%s,node-name=base-file' % base) ++ vm.add_blockdev('%s,file=base-file,node-name=base' % iotests.imgfmt) ++ vm.add_blockdev('file,filename=%s,node-name=mid-file' % mid) ++ vm.add_blockdev('%s,file=mid-file,node-name=mid,backing=base' ++ % iotests.imgfmt) ++ vm.add_drive(top, 'backing=mid,node-name=top') ++ return vm ++ ++with iotests.FilePath('base') as base, \ ++ iotests.FilePath('mid') as mid, \ ++ iotests.FilePath('top') as top: ++ ++ iotests.log('== Commit tests ==') ++ ++ create_chain() ++ ++ iotests.log('=== Check visible data ===') ++ ++ iotests.qemu_io_log('-c', 'read -P 1 0 %d' % size_short, top) ++ iotests.qemu_io_log('-c', 'read -P 0 %d %d' % (size_short, size_diff), top) ++ ++ iotests.log('=== Checking allocation status ===') ++ ++ iotests.qemu_io_log('-c', 'alloc 0 %d' % size_short, ++ '-c', 'alloc %d %d' % (size_short, size_diff), ++ base) ++ ++ iotests.qemu_io_log('-c', 'alloc 0 %d' % size_short, ++ '-c', 'alloc %d %d' % (size_short, size_diff), ++ mid) ++ ++ iotests.qemu_io_log('-c', 'alloc 0 %d' % size_short, ++ '-c', 'alloc %d %d' % (size_short, size_diff), ++ top) ++ ++ iotests.log('=== Checking map ===') ++ ++ iotests.qemu_img_log('map', '--output=json', base) ++ iotests.qemu_img_log('map', '--output=human', base) ++ iotests.qemu_img_log('map', '--output=json', mid) ++ iotests.qemu_img_log('map', '--output=human', mid) ++ iotests.qemu_img_log('map', '--output=json', top) ++ iotests.qemu_img_log('map', '--output=human', top) ++ ++ iotests.log('=== Testing qemu-img commit (top -> mid) ===') ++ ++ iotests.qemu_img_log('commit', top) ++ iotests.img_info_log(mid) ++ iotests.qemu_io_log('-c', 'read -P 1 0 %d' % size_short, mid) ++ iotests.qemu_io_log('-c', 'read -P 0 %d %d' % (size_short, size_diff), mid) ++ ++ iotests.log('=== Testing HMP commit (top -> mid) ===') ++ ++ create_chain() ++ with create_vm() as vm: ++ vm.launch() ++ vm.qmp_log('human-monitor-command', command_line='commit drive0') ++ ++ iotests.img_info_log(mid) ++ iotests.qemu_io_log('-c', 'read -P 1 0 %d' % size_short, mid) ++ iotests.qemu_io_log('-c', 'read -P 0 %d %d' % (size_short, size_diff), mid) ++ ++ iotests.log('=== Testing QMP active commit (top -> mid) ===') ++ ++ create_chain() ++ with create_vm() as vm: ++ vm.launch() ++ vm.qmp_log('block-commit', device='top', base_node='mid', ++ job_id='job0', auto_dismiss=False) ++ vm.run_job('job0', wait=5) ++ ++ iotests.img_info_log(mid) ++ iotests.qemu_io_log('-c', 'read -P 1 0 %d' % size_short, mid) ++ iotests.qemu_io_log('-c', 'read -P 0 %d %d' % (size_short, size_diff), mid) ++ ++ ++ iotests.log('== Resize tests ==') ++ ++ # Use different sizes for different allocation modes: ++ # ++ # We want to have at least one test where 32 bit truncation in the size of ++ # the overlapping area becomes visible. This is covered by the ++ # prealloc='off' case (1G to 6G is an overlap of 5G). ++ # ++ # However, we can only do this for modes that don't preallocate data ++ # because otherwise we might run out of space on the test host. ++ # ++ # We also want to test some unaligned combinations. ++ for (prealloc, base_size, top_size_old, top_size_new, off) in [ ++ ('off', '6G', '1G', '8G', '5G'), ++ ('metadata', '32G', '30G', '33G', '31G'), ++ ('falloc', '10M', '5M', '15M', '9M'), ++ ('full', '16M', '8M', '12M', '11M'), ++ ('off', '384k', '253k', '512k', '253k'), ++ ('off', '400k', '256k', '512k', '336k'), ++ ('off', '512k', '256k', '500k', '436k')]: ++ ++ iotests.log('=== preallocation=%s ===' % prealloc) ++ iotests.qemu_img_log('create', '-f', iotests.imgfmt, base, base_size) ++ iotests.qemu_img_log('create', '-f', iotests.imgfmt, '-b', base, top, ++ top_size_old) ++ iotests.qemu_io_log('-c', 'write -P 1 %s 64k' % off, base) ++ ++ # After this, top_size_old to base_size should be allocated/zeroed. ++ # ++ # In theory, leaving base_size to top_size_new unallocated would be ++ # correct, but in practice, if we zero out anything, we zero out ++ # everything up to top_size_new. ++ iotests.qemu_img_log('resize', '-f', iotests.imgfmt, ++ '--preallocation', prealloc, top, top_size_new) ++ iotests.qemu_io_log('-c', 'read -P 0 %s 64k' % off, top) ++ iotests.qemu_io_log('-c', 'map', top) ++ iotests.qemu_img_log('map', '--output=json', top) +diff --git a/tests/qemu-iotests/274.out b/tests/qemu-iotests/274.out +new file mode 100644 +index 0000000000..1a796fd07c +--- /dev/null ++++ b/tests/qemu-iotests/274.out +@@ -0,0 +1,268 @@ ++== Commit tests == ++Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=2097152 cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++ ++Formatting 'TEST_DIR/PID-mid', fmt=qcow2 size=1048576 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++ ++Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=2097152 backing_file=TEST_DIR/PID-mid cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++ ++wrote 2097152/2097152 bytes at offset 0 ++2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++ ++=== Check visible data === ++read 1048576/1048576 bytes at offset 0 ++1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++ ++read 1048576/1048576 bytes at offset 1048576 ++1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++ ++=== Checking allocation status === ++1048576/1048576 bytes allocated at offset 0 bytes ++1048576/1048576 bytes allocated at offset 1 MiB ++ ++0/1048576 bytes allocated at offset 0 bytes ++0/0 bytes allocated at offset 1 MiB ++ ++0/1048576 bytes allocated at offset 0 bytes ++0/1048576 bytes allocated at offset 1 MiB ++ ++=== Checking map === ++[{ "start": 0, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": 327680}] ++ ++Offset Length Mapped to File ++0 0x200000 0x50000 TEST_DIR/PID-base ++ ++[{ "start": 0, "length": 1048576, "depth": 1, "zero": false, "data": true, "offset": 327680}] ++ ++Offset Length Mapped to File ++0 0x100000 0x50000 TEST_DIR/PID-base ++ ++[{ "start": 0, "length": 1048576, "depth": 2, "zero": false, "data": true, "offset": 327680}, ++{ "start": 1048576, "length": 1048576, "depth": 0, "zero": true, "data": false}] ++ ++Offset Length Mapped to File ++0 0x100000 0x50000 TEST_DIR/PID-base ++ ++=== Testing qemu-img commit (top -> mid) === ++Image committed. ++ ++image: TEST_IMG ++file format: IMGFMT ++virtual size: 2 MiB (2097152 bytes) ++cluster_size: 65536 ++backing file: TEST_DIR/PID-base ++Format specific information: ++ compat: 1.1 ++ lazy refcounts: false ++ refcount bits: 16 ++ corrupt: false ++ ++read 1048576/1048576 bytes at offset 0 ++1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++ ++read 1048576/1048576 bytes at offset 1048576 ++1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++ ++=== Testing HMP commit (top -> mid) === ++Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=2097152 cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++ ++Formatting 'TEST_DIR/PID-mid', fmt=qcow2 size=1048576 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++ ++Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=2097152 backing_file=TEST_DIR/PID-mid cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++ ++wrote 2097152/2097152 bytes at offset 0 ++2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++ ++{"execute": "human-monitor-command", "arguments": {"command-line": "commit drive0"}} ++{"return": ""} ++image: TEST_IMG ++file format: IMGFMT ++virtual size: 2 MiB (2097152 bytes) ++cluster_size: 65536 ++backing file: TEST_DIR/PID-base ++Format specific information: ++ compat: 1.1 ++ lazy refcounts: false ++ refcount bits: 16 ++ corrupt: false ++ ++read 1048576/1048576 bytes at offset 0 ++1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++ ++read 1048576/1048576 bytes at offset 1048576 ++1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++ ++=== Testing QMP active commit (top -> mid) === ++Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=2097152 cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++ ++Formatting 'TEST_DIR/PID-mid', fmt=qcow2 size=1048576 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++ ++Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=2097152 backing_file=TEST_DIR/PID-mid cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++ ++wrote 2097152/2097152 bytes at offset 0 ++2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++ ++{"execute": "block-commit", "arguments": {"auto-dismiss": false, "base-node": "mid", "device": "top", "job-id": "job0"}} ++{"return": {}} ++{"execute": "job-complete", "arguments": {"id": "job0"}} ++{"return": {}} ++{"data": {"device": "job0", "len": 0, "offset": 0, "speed": 0, "type": "commit"}, "event": "BLOCK_JOB_READY", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"data": {"device": "job0", "len": 0, "offset": 0, "speed": 0, "type": "commit"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} ++image: TEST_IMG ++file format: IMGFMT ++virtual size: 2 MiB (2097152 bytes) ++cluster_size: 65536 ++backing file: TEST_DIR/PID-base ++Format specific information: ++ compat: 1.1 ++ lazy refcounts: false ++ refcount bits: 16 ++ corrupt: false ++ ++read 1048576/1048576 bytes at offset 0 ++1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++ ++read 1048576/1048576 bytes at offset 1048576 ++1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++ ++== Resize tests == ++=== preallocation=off === ++Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=6442450944 cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++ ++Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=1073741824 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++ ++wrote 65536/65536 bytes at offset 5368709120 ++64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++ ++Image resized. ++ ++read 65536/65536 bytes at offset 5368709120 ++64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++ ++1 GiB (0x40000000) bytes not allocated at offset 0 bytes (0x0) ++7 GiB (0x1c0000000) bytes allocated at offset 1 GiB (0x40000000) ++ ++[{ "start": 0, "length": 1073741824, "depth": 1, "zero": true, "data": false}, ++{ "start": 1073741824, "length": 7516192768, "depth": 0, "zero": true, "data": false}] ++ ++=== preallocation=metadata === ++Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=34359738368 cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++ ++Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=32212254720 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++ ++wrote 65536/65536 bytes at offset 33285996544 ++64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++ ++Image resized. ++ ++read 65536/65536 bytes at offset 33285996544 ++64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++ ++30 GiB (0x780000000) bytes not allocated at offset 0 bytes (0x0) ++3 GiB (0xc0000000) bytes allocated at offset 30 GiB (0x780000000) ++ ++[{ "start": 0, "length": 32212254720, "depth": 1, "zero": true, "data": false}, ++{ "start": 32212254720, "length": 536870912, "depth": 0, "zero": true, "data": false, "offset": 327680}, ++{ "start": 32749125632, "length": 536870912, "depth": 0, "zero": true, "data": false, "offset": 537264128}, ++{ "start": 33285996544, "length": 536870912, "depth": 0, "zero": true, "data": false, "offset": 1074200576}, ++{ "start": 33822867456, "length": 536870912, "depth": 0, "zero": true, "data": false, "offset": 1611137024}, ++{ "start": 34359738368, "length": 536870912, "depth": 0, "zero": true, "data": false, "offset": 2148139008}, ++{ "start": 34896609280, "length": 536870912, "depth": 0, "zero": true, "data": false, "offset": 2685075456}] ++ ++=== preallocation=falloc === ++Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=10485760 cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++ ++Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=5242880 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++ ++wrote 65536/65536 bytes at offset 9437184 ++64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++ ++Image resized. ++ ++read 65536/65536 bytes at offset 9437184 ++64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++ ++5 MiB (0x500000) bytes not allocated at offset 0 bytes (0x0) ++10 MiB (0xa00000) bytes allocated at offset 5 MiB (0x500000) ++ ++[{ "start": 0, "length": 5242880, "depth": 1, "zero": true, "data": false}, ++{ "start": 5242880, "length": 10485760, "depth": 0, "zero": true, "data": false, "offset": 327680}] ++ ++=== preallocation=full === ++Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=16777216 cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++ ++Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=8388608 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++ ++wrote 65536/65536 bytes at offset 11534336 ++64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++ ++Image resized. ++ ++read 65536/65536 bytes at offset 11534336 ++64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++ ++8 MiB (0x800000) bytes not allocated at offset 0 bytes (0x0) ++4 MiB (0x400000) bytes allocated at offset 8 MiB (0x800000) ++ ++[{ "start": 0, "length": 8388608, "depth": 1, "zero": true, "data": false}, ++{ "start": 8388608, "length": 4194304, "depth": 0, "zero": true, "data": false, "offset": 327680}] ++ ++=== preallocation=off === ++Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=393216 cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++ ++Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=259072 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++ ++wrote 65536/65536 bytes at offset 259072 ++64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++ ++Image resized. ++ ++read 65536/65536 bytes at offset 259072 ++64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++ ++192 KiB (0x30000) bytes not allocated at offset 0 bytes (0x0) ++320 KiB (0x50000) bytes allocated at offset 192 KiB (0x30000) ++ ++[{ "start": 0, "length": 196608, "depth": 1, "zero": true, "data": false}, ++{ "start": 196608, "length": 65536, "depth": 0, "zero": false, "data": true, "offset": 327680}, ++{ "start": 262144, "length": 262144, "depth": 0, "zero": true, "data": false}] ++ ++=== preallocation=off === ++Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=409600 cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++ ++Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=262144 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++ ++wrote 65536/65536 bytes at offset 344064 ++64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++ ++Image resized. ++ ++read 65536/65536 bytes at offset 344064 ++64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++ ++256 KiB (0x40000) bytes not allocated at offset 0 bytes (0x0) ++256 KiB (0x40000) bytes allocated at offset 256 KiB (0x40000) ++ ++[{ "start": 0, "length": 262144, "depth": 1, "zero": true, "data": false}, ++{ "start": 262144, "length": 262144, "depth": 0, "zero": true, "data": false}] ++ ++=== preallocation=off === ++Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=524288 cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++ ++Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=262144 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++ ++wrote 65536/65536 bytes at offset 446464 ++64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++ ++Image resized. ++ ++read 65536/65536 bytes at offset 446464 ++64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++ ++256 KiB (0x40000) bytes not allocated at offset 0 bytes (0x0) ++244 KiB (0x3d000) bytes allocated at offset 256 KiB (0x40000) ++ ++[{ "start": 0, "length": 262144, "depth": 1, "zero": true, "data": false}, ++{ "start": 262144, "length": 249856, "depth": 0, "zero": true, "data": false}] ++ +diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group +index 435dccd5af..1710470e70 100644 +--- a/tests/qemu-iotests/group ++++ b/tests/qemu-iotests/group +@@ -286,6 +286,7 @@ + 270 rw backing quick + 272 rw + 273 backing quick ++274 rw backing + 277 rw quick + 279 rw backing quick + 280 rw migration quick +-- +2.23.0 + diff --git a/iotests-add-hmp-helper-with-logging.patch b/iotests-add-hmp-helper-with-logging.patch new file mode 100644 index 0000000000000000000000000000000000000000..db857bcd741731ea43d418248b98e299f7a7b535 --- /dev/null +++ b/iotests-add-hmp-helper-with-logging.patch @@ -0,0 +1,98 @@ +From 239bbcc0ae6ba24733839150955bdf8402e9ec55 Mon Sep 17 00:00:00 2001 +From: John Snow +Date: Mon, 30 Mar 2020 20:00:10 -0400 +Subject: [PATCH 250/709] iotests: add hmp helper with logging + +Minor cleanup for HMP functions; helps with line length and consolidates +HMP helpers through one implementation function. + +Although we are adding a universal toggle to turn QMP logging on or off, +many existing callers to hmp functions don't expect that output to be +logged, which causes quite a few changes in the test output. + +For now, offer a use_log parameter. + +Typing notes: + +QMPResponse is just an alias for Dict[str, Any]. It holds no special +meanings and it is not a formal subtype of Dict[str, Any]. It is best +thought of as a lexical synonym. + +We may well wish to add stricter subtypes in the future for certain +shapes of data that are not formalized as Python objects, at which point +we can simply retire the alias and allow mypy to more strictly check +usages of the name. + +Signed-off-by: John Snow +Message-Id: <20200331000014.11581-11-jsnow@redhat.com> +Reviewed-by: Max Reitz +Reviewed-by: Kevin Wolf +Signed-off-by: Max Reitz +--- + tests/qemu-iotests/iotests.py | 39 +++++++++++++++++++++-------------- + 1 file changed, 24 insertions(+), 15 deletions(-) + +diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py +index 9f5da32dae..cf10c428b5 100644 +--- a/tests/qemu-iotests/iotests.py ++++ b/tests/qemu-iotests/iotests.py +@@ -37,6 +37,10 @@ from qemu import qtest + + assert sys.version_info >= (3, 6) + ++# Type Aliases ++QMPResponse = Dict[str, Any] ++ ++ + faulthandler.enable() + + # This will not work if arguments contain spaces but is necessary if we +@@ -541,25 +545,30 @@ class VM(qtest.QEMUQtestMachine): + self._args.append(addr) + return self + +- def pause_drive(self, drive, event=None): +- '''Pause drive r/w operations''' ++ def hmp(self, command_line: str, use_log: bool = False) -> QMPResponse: ++ cmd = 'human-monitor-command' ++ kwargs = {'command-line': command_line} ++ if use_log: ++ return self.qmp_log(cmd, **kwargs) ++ else: ++ return self.qmp(cmd, **kwargs) ++ ++ def pause_drive(self, drive: str, event: Optional[str] = None) -> None: ++ """Pause drive r/w operations""" + if not event: + self.pause_drive(drive, "read_aio") + self.pause_drive(drive, "write_aio") + return +- self.qmp('human-monitor-command', +- command_line='qemu-io %s "break %s bp_%s"' +- % (drive, event, drive)) +- +- def resume_drive(self, drive): +- self.qmp('human-monitor-command', +- command_line='qemu-io %s "remove_break bp_%s"' +- % (drive, drive)) +- +- def hmp_qemu_io(self, drive, cmd): +- '''Write to a given drive using an HMP command''' +- return self.qmp('human-monitor-command', +- command_line='qemu-io %s "%s"' % (drive, cmd)) ++ self.hmp(f'qemu-io {drive} "break {event} bp_{drive}"') ++ ++ def resume_drive(self, drive: str) -> None: ++ """Resume drive r/w operations""" ++ self.hmp(f'qemu-io {drive} "remove_break bp_{drive}"') ++ ++ def hmp_qemu_io(self, drive: str, cmd: str, ++ use_log: bool = False) -> QMPResponse: ++ """Write to a given drive using an HMP command""" ++ return self.hmp(f'qemu-io {drive} "{cmd}"', use_log=use_log) + + def flatten_qmp_object(self, obj, output=None, basestr=''): + if output is None: +-- +2.23.0 + diff --git a/iotests-add-pylintrc-file.patch b/iotests-add-pylintrc-file.patch new file mode 100644 index 0000000000000000000000000000000000000000..ca01ec28568e17a77c39a0a83d110ac54d3c22d0 --- /dev/null +++ b/iotests-add-pylintrc-file.patch @@ -0,0 +1,49 @@ +From 576dc22be11d3cd95eec0e75ec5603cde671a370 Mon Sep 17 00:00:00 2001 +From: John Snow +Date: Mon, 30 Mar 2020 20:00:05 -0400 +Subject: [PATCH 245/709] iotests: add pylintrc file + +This allows others to get repeatable results with pylint. If you run +`pylint iotests.py`, you should see a 100% pass. + +Signed-off-by: John Snow +Reviewed-by: Max Reitz +Message-Id: <20200331000014.11581-6-jsnow@redhat.com> +Reviewed-by: Kevin Wolf +Signed-off-by: Max Reitz +--- + tests/qemu-iotests/pylintrc | 22 ++++++++++++++++++++++ + 1 file changed, 22 insertions(+) + create mode 100644 tests/qemu-iotests/pylintrc + +diff --git a/tests/qemu-iotests/pylintrc b/tests/qemu-iotests/pylintrc +new file mode 100644 +index 0000000000..daec2c4942 +--- /dev/null ++++ b/tests/qemu-iotests/pylintrc +@@ -0,0 +1,22 @@ ++[MESSAGES CONTROL] ++ ++# Disable the message, report, category or checker with the given id(s). You ++# can either give multiple identifiers separated by comma (,) or put this ++# option multiple times (only on the command line, not in the configuration ++# file where it should appear only once). You can also use "--disable=all" to ++# disable everything first and then reenable specific checks. For example, if ++# you want to run only the similarities checker, you can use "--disable=all ++# --enable=similarities". If you want to run only the classes checker, but have ++# no Warning level messages displayed, use "--disable=all --enable=classes ++# --disable=W". ++disable=invalid-name, ++ no-else-return, ++ too-few-public-methods, ++ too-many-arguments, ++ too-many-branches, ++ too-many-lines, ++ too-many-locals, ++ too-many-public-methods, ++ # These are temporary, and should be removed: ++ line-too-long, ++ missing-docstring, +-- +2.23.0 + diff --git a/iotests-add-script_initialize.patch b/iotests-add-script_initialize.patch new file mode 100644 index 0000000000000000000000000000000000000000..2494f7bd35ddcf86475abcb49f702df5ec51bad6 --- /dev/null +++ b/iotests-add-script_initialize.patch @@ -0,0 +1,752 @@ +From 7d8140595f1e131935ba1c98a55af7d066660707 Mon Sep 17 00:00:00 2001 +From: John Snow +Date: Mon, 30 Mar 2020 20:00:11 -0400 +Subject: [PATCH 251/709] iotests: add script_initialize + +Like script_main, but doesn't require a single point of entry. +Replace all existing initialization sections with this drop-in replacement. + +This brings debug support to all existing script-style iotests. + +Signed-off-by: John Snow +Reviewed-by: Max Reitz +Message-Id: <20200331000014.11581-12-jsnow@redhat.com> +Reviewed-by: Kevin Wolf +[mreitz: Give 274 the same treatment] +Signed-off-by: Max Reitz +--- + tests/qemu-iotests/149 | 3 +- + tests/qemu-iotests/194 | 4 +- + tests/qemu-iotests/202 | 4 +- + tests/qemu-iotests/203 | 4 +- + tests/qemu-iotests/206 | 2 +- + tests/qemu-iotests/207 | 6 ++- + tests/qemu-iotests/208 | 2 +- + tests/qemu-iotests/209 | 2 +- + tests/qemu-iotests/210 | 6 ++- + tests/qemu-iotests/211 | 6 ++- + tests/qemu-iotests/212 | 6 ++- + tests/qemu-iotests/213 | 6 ++- + tests/qemu-iotests/216 | 4 +- + tests/qemu-iotests/218 | 2 +- + tests/qemu-iotests/219 | 2 +- + tests/qemu-iotests/222 | 7 ++-- + tests/qemu-iotests/224 | 4 +- + tests/qemu-iotests/228 | 6 ++- + tests/qemu-iotests/234 | 4 +- + tests/qemu-iotests/235 | 4 +- + tests/qemu-iotests/236 | 2 +- + tests/qemu-iotests/237 | 2 +- + tests/qemu-iotests/238 | 2 + + tests/qemu-iotests/242 | 2 +- + tests/qemu-iotests/246 | 2 +- + tests/qemu-iotests/248 | 2 +- + tests/qemu-iotests/254 | 2 +- + tests/qemu-iotests/255 | 2 +- + tests/qemu-iotests/256 | 2 +- + tests/qemu-iotests/258 | 7 ++-- + tests/qemu-iotests/260 | 4 +- + tests/qemu-iotests/262 | 4 +- + tests/qemu-iotests/264 | 4 +- + tests/qemu-iotests/274 | 4 +- + tests/qemu-iotests/277 | 2 + + tests/qemu-iotests/280 | 8 ++-- + tests/qemu-iotests/283 | 4 +- + tests/qemu-iotests/iotests.py | 76 +++++++++++++++++++++++------------ + 38 files changed, 132 insertions(+), 83 deletions(-) + +diff --git a/tests/qemu-iotests/149 b/tests/qemu-iotests/149 +index b4a21bf7b7..852768f80a 100755 +--- a/tests/qemu-iotests/149 ++++ b/tests/qemu-iotests/149 +@@ -382,8 +382,7 @@ def test_once(config, qemu_img=False): + + + # Obviously we only work with the luks image format +-iotests.verify_image_format(supported_fmts=['luks']) +-iotests.verify_platform() ++iotests.script_initialize(supported_fmts=['luks']) + + # We need sudo in order to run cryptsetup to create + # dm-crypt devices. This is safe to use on any +diff --git a/tests/qemu-iotests/194 b/tests/qemu-iotests/194 +index 9dc1bd3510..8b1f720af4 100755 +--- a/tests/qemu-iotests/194 ++++ b/tests/qemu-iotests/194 +@@ -21,8 +21,8 @@ + + import iotests + +-iotests.verify_image_format(supported_fmts=['qcow2', 'qed', 'raw']) +-iotests.verify_platform(['linux']) ++iotests.script_initialize(supported_fmts=['qcow2', 'qed', 'raw'], ++ supported_platforms=['linux']) + + with iotests.FilePath('source.img') as source_img_path, \ + iotests.FilePath('dest.img') as dest_img_path, \ +diff --git a/tests/qemu-iotests/202 b/tests/qemu-iotests/202 +index 920a8683ef..e3900a44d1 100755 +--- a/tests/qemu-iotests/202 ++++ b/tests/qemu-iotests/202 +@@ -24,8 +24,8 @@ + + import iotests + +-iotests.verify_image_format(supported_fmts=['qcow2']) +-iotests.verify_platform(['linux']) ++iotests.script_initialize(supported_fmts=['qcow2'], ++ supported_platforms=['linux']) + + with iotests.FilePath('disk0.img') as disk0_img_path, \ + iotests.FilePath('disk1.img') as disk1_img_path, \ +diff --git a/tests/qemu-iotests/203 b/tests/qemu-iotests/203 +index 49eff5d405..4b4bd3307d 100755 +--- a/tests/qemu-iotests/203 ++++ b/tests/qemu-iotests/203 +@@ -24,8 +24,8 @@ + + import iotests + +-iotests.verify_image_format(supported_fmts=['qcow2']) +-iotests.verify_platform(['linux']) ++iotests.script_initialize(supported_fmts=['qcow2'], ++ supported_platforms=['linux']) + + with iotests.FilePath('disk0.img') as disk0_img_path, \ + iotests.FilePath('disk1.img') as disk1_img_path, \ +diff --git a/tests/qemu-iotests/206 b/tests/qemu-iotests/206 +index e2b50ae24d..f42432a838 100755 +--- a/tests/qemu-iotests/206 ++++ b/tests/qemu-iotests/206 +@@ -23,7 +23,7 @@ + import iotests + from iotests import imgfmt + +-iotests.verify_image_format(supported_fmts=['qcow2']) ++iotests.script_initialize(supported_fmts=['qcow2']) + + with iotests.FilePath('t.qcow2') as disk_path, \ + iotests.FilePath('t.qcow2.base') as backing_path, \ +diff --git a/tests/qemu-iotests/207 b/tests/qemu-iotests/207 +index 3d9c1208ca..a6621410da 100755 +--- a/tests/qemu-iotests/207 ++++ b/tests/qemu-iotests/207 +@@ -24,8 +24,10 @@ import iotests + import subprocess + import re + +-iotests.verify_image_format(supported_fmts=['raw']) +-iotests.verify_protocol(supported=['ssh']) ++iotests.script_initialize( ++ supported_fmts=['raw'], ++ supported_protocols=['ssh'], ++) + + def filter_hash(qmsg): + def _filter(key, value): +diff --git a/tests/qemu-iotests/208 b/tests/qemu-iotests/208 +index 1c3fc8c7fd..6cb642f821 100755 +--- a/tests/qemu-iotests/208 ++++ b/tests/qemu-iotests/208 +@@ -22,7 +22,7 @@ + + import iotests + +-iotests.verify_image_format(supported_fmts=['generic']) ++iotests.script_initialize(supported_fmts=['generic']) + + with iotests.FilePath('disk.img') as disk_img_path, \ + iotests.FilePath('disk-snapshot.img') as disk_snapshot_img_path, \ +diff --git a/tests/qemu-iotests/209 b/tests/qemu-iotests/209 +index 65c1a1e70a..8c804f4a30 100755 +--- a/tests/qemu-iotests/209 ++++ b/tests/qemu-iotests/209 +@@ -22,7 +22,7 @@ import iotests + from iotests import qemu_img_create, qemu_io, qemu_img_verbose, qemu_nbd, \ + file_path + +-iotests.verify_image_format(supported_fmts=['qcow2']) ++iotests.script_initialize(supported_fmts=['qcow2']) + + disk = file_path('disk') + nbd_sock = file_path('nbd-sock', base_dir=iotests.sock_dir) +diff --git a/tests/qemu-iotests/210 b/tests/qemu-iotests/210 +index e49896e23d..7bf591f313 100755 +--- a/tests/qemu-iotests/210 ++++ b/tests/qemu-iotests/210 +@@ -23,8 +23,10 @@ + import iotests + from iotests import imgfmt + +-iotests.verify_image_format(supported_fmts=['luks']) +-iotests.verify_protocol(supported=['file']) ++iotests.script_initialize( ++ supported_fmts=['luks'], ++ supported_protocols=['file'], ++) + + with iotests.FilePath('t.luks') as disk_path, \ + iotests.VM() as vm: +diff --git a/tests/qemu-iotests/211 b/tests/qemu-iotests/211 +index 163994d559..4969edb00c 100755 +--- a/tests/qemu-iotests/211 ++++ b/tests/qemu-iotests/211 +@@ -23,8 +23,10 @@ + import iotests + from iotests import imgfmt + +-iotests.verify_image_format(supported_fmts=['vdi']) +-iotests.verify_protocol(supported=['file']) ++iotests.script_initialize( ++ supported_fmts=['vdi'], ++ supported_protocols=['file'], ++) + + def blockdev_create(vm, options): + error = vm.blockdev_create(options) +diff --git a/tests/qemu-iotests/212 b/tests/qemu-iotests/212 +index 800f92dd84..45d08842bb 100755 +--- a/tests/qemu-iotests/212 ++++ b/tests/qemu-iotests/212 +@@ -23,8 +23,10 @@ + import iotests + from iotests import imgfmt + +-iotests.verify_image_format(supported_fmts=['parallels']) +-iotests.verify_protocol(supported=['file']) ++iotests.script_initialize( ++ supported_fmts=['parallels'], ++ supported_protocols=['file'], ++) + + with iotests.FilePath('t.parallels') as disk_path, \ + iotests.VM() as vm: +diff --git a/tests/qemu-iotests/213 b/tests/qemu-iotests/213 +index 1eee45276a..cf638eb927 100755 +--- a/tests/qemu-iotests/213 ++++ b/tests/qemu-iotests/213 +@@ -23,8 +23,10 @@ + import iotests + from iotests import imgfmt + +-iotests.verify_image_format(supported_fmts=['vhdx']) +-iotests.verify_protocol(supported=['file']) ++iotests.script_initialize( ++ supported_fmts=['vhdx'], ++ supported_protocols=['file'], ++) + + with iotests.FilePath('t.vhdx') as disk_path, \ + iotests.VM() as vm: +diff --git a/tests/qemu-iotests/216 b/tests/qemu-iotests/216 +index 372f042d3e..de11d85b5d 100755 +--- a/tests/qemu-iotests/216 ++++ b/tests/qemu-iotests/216 +@@ -23,8 +23,8 @@ import iotests + from iotests import log, qemu_img, qemu_io_silent + + # Need backing file support +-iotests.verify_image_format(supported_fmts=['qcow2', 'qcow', 'qed', 'vmdk']) +-iotests.verify_platform(['linux']) ++iotests.script_initialize(supported_fmts=['qcow2', 'qcow', 'qed', 'vmdk'], ++ supported_platforms=['linux']) + + log('') + log('=== Copy-on-read across nodes ===') +diff --git a/tests/qemu-iotests/218 b/tests/qemu-iotests/218 +index 1325ba9eaa..5586870456 100755 +--- a/tests/qemu-iotests/218 ++++ b/tests/qemu-iotests/218 +@@ -29,7 +29,7 @@ + import iotests + from iotests import log, qemu_img, qemu_io_silent + +-iotests.verify_image_format(supported_fmts=['qcow2', 'raw']) ++iotests.script_initialize(supported_fmts=['qcow2', 'raw']) + + + # Launches the VM, adds two null-co nodes (source and target), and +diff --git a/tests/qemu-iotests/219 b/tests/qemu-iotests/219 +index b8774770c4..db272c5249 100755 +--- a/tests/qemu-iotests/219 ++++ b/tests/qemu-iotests/219 +@@ -21,7 +21,7 @@ + + import iotests + +-iotests.verify_image_format(supported_fmts=['qcow2']) ++iotests.script_initialize(supported_fmts=['qcow2']) + + img_size = 4 * 1024 * 1024 + +diff --git a/tests/qemu-iotests/222 b/tests/qemu-iotests/222 +index bf1718e179..6602f6b4ba 100755 +--- a/tests/qemu-iotests/222 ++++ b/tests/qemu-iotests/222 +@@ -24,9 +24,10 @@ + import iotests + from iotests import log, qemu_img, qemu_io, qemu_io_silent + +-iotests.verify_platform(['linux']) +-iotests.verify_image_format(supported_fmts=['qcow2', 'qcow', 'qed', 'vmdk', +- 'vhdx', 'raw']) ++iotests.script_initialize( ++ supported_fmts=['qcow2', 'qcow', 'qed', 'vmdk', 'vhdx', 'raw'], ++ supported_platforms=['linux'], ++) + + patterns = [("0x5d", "0", "64k"), + ("0xd5", "1M", "64k"), +diff --git a/tests/qemu-iotests/224 b/tests/qemu-iotests/224 +index e91fb26fd8..81ca1e4898 100755 +--- a/tests/qemu-iotests/224 ++++ b/tests/qemu-iotests/224 +@@ -26,8 +26,8 @@ from iotests import log, qemu_img, qemu_io_silent, filter_qmp_testfiles, \ + import json + + # Need backing file support (for arbitrary backing formats) +-iotests.verify_image_format(supported_fmts=['qcow2', 'qcow', 'qed']) +-iotests.verify_platform(['linux']) ++iotests.script_initialize(supported_fmts=['qcow2', 'qcow', 'qed'], ++ supported_platforms=['linux']) + + + # There are two variations of this test: +diff --git a/tests/qemu-iotests/228 b/tests/qemu-iotests/228 +index 64bc82ee23..da0900fb82 100755 +--- a/tests/qemu-iotests/228 ++++ b/tests/qemu-iotests/228 +@@ -25,8 +25,10 @@ from iotests import log, qemu_img, filter_testfiles, filter_imgfmt, \ + filter_qmp_testfiles, filter_qmp_imgfmt + + # Need backing file and change-backing-file support +-iotests.verify_image_format(supported_fmts=['qcow2', 'qed']) +-iotests.verify_platform(['linux']) ++iotests.script_initialize( ++ supported_fmts=['qcow2', 'qed'], ++ supported_platforms=['linux'], ++) + + + def log_node_info(node): +diff --git a/tests/qemu-iotests/234 b/tests/qemu-iotests/234 +index 324c1549fd..73c899ddae 100755 +--- a/tests/qemu-iotests/234 ++++ b/tests/qemu-iotests/234 +@@ -23,8 +23,8 @@ + import iotests + import os + +-iotests.verify_image_format(supported_fmts=['qcow2']) +-iotests.verify_platform(['linux']) ++iotests.script_initialize(supported_fmts=['qcow2'], ++ supported_platforms=['linux']) + + with iotests.FilePath('img') as img_path, \ + iotests.FilePath('backing') as backing_path, \ +diff --git a/tests/qemu-iotests/235 b/tests/qemu-iotests/235 +index 760826128e..d1b10ac36b 100755 +--- a/tests/qemu-iotests/235 ++++ b/tests/qemu-iotests/235 +@@ -27,6 +27,8 @@ sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', 'python')) + + from qemu.machine import QEMUMachine + ++iotests.script_initialize(supported_fmts=['qcow2']) ++ + # Note: + # This test was added to check that mirror dead-lock was fixed (see previous + # commit before this test addition). +@@ -40,8 +42,6 @@ from qemu.machine import QEMUMachine + + size = 1 * 1024 * 1024 * 1024 + +-iotests.verify_image_format(supported_fmts=['qcow2']) +- + disk = file_path('disk') + + # prepare source image +diff --git a/tests/qemu-iotests/236 b/tests/qemu-iotests/236 +index 8ce927a16c..6f5cee2444 100755 +--- a/tests/qemu-iotests/236 ++++ b/tests/qemu-iotests/236 +@@ -22,7 +22,7 @@ + import iotests + from iotests import log + +-iotests.verify_image_format(supported_fmts=['generic']) ++iotests.script_initialize(supported_fmts=['generic']) + size = 64 * 1024 * 1024 + granularity = 64 * 1024 + +diff --git a/tests/qemu-iotests/237 b/tests/qemu-iotests/237 +index 50ba364a3e..5b21ad3509 100755 +--- a/tests/qemu-iotests/237 ++++ b/tests/qemu-iotests/237 +@@ -24,7 +24,7 @@ import math + import iotests + from iotests import imgfmt + +-iotests.verify_image_format(supported_fmts=['vmdk']) ++iotests.script_initialize(supported_fmts=['vmdk']) + + with iotests.FilePath('t.vmdk') as disk_path, \ + iotests.FilePath('t.vmdk.1') as extent1_path, \ +diff --git a/tests/qemu-iotests/238 b/tests/qemu-iotests/238 +index d4e060228c..b8fcf15a1f 100755 +--- a/tests/qemu-iotests/238 ++++ b/tests/qemu-iotests/238 +@@ -23,6 +23,8 @@ import os + import iotests + from iotests import log + ++iotests.script_initialize() ++ + virtio_scsi_device = iotests.get_virtio_scsi_device() + + vm = iotests.VM() +diff --git a/tests/qemu-iotests/242 b/tests/qemu-iotests/242 +index 97617876bc..64f1bd95e4 100755 +--- a/tests/qemu-iotests/242 ++++ b/tests/qemu-iotests/242 +@@ -24,7 +24,7 @@ import struct + from iotests import qemu_img_create, qemu_io, qemu_img_pipe, \ + file_path, img_info_log, log, filter_qemu_io + +-iotests.verify_image_format(supported_fmts=['qcow2']) ++iotests.script_initialize(supported_fmts=['qcow2']) + + disk = file_path('disk') + chunk = 256 * 1024 +diff --git a/tests/qemu-iotests/246 b/tests/qemu-iotests/246 +index 59a216a839..58a479cc1f 100755 +--- a/tests/qemu-iotests/246 ++++ b/tests/qemu-iotests/246 +@@ -22,7 +22,7 @@ + import iotests + from iotests import log + +-iotests.verify_image_format(supported_fmts=['qcow2']) ++iotests.script_initialize(supported_fmts=['qcow2']) + size = 64 * 1024 * 1024 * 1024 + gran_small = 32 * 1024 + gran_large = 128 * 1024 +diff --git a/tests/qemu-iotests/248 b/tests/qemu-iotests/248 +index 68c374692e..18ba03467e 100755 +--- a/tests/qemu-iotests/248 ++++ b/tests/qemu-iotests/248 +@@ -21,7 +21,7 @@ + import iotests + from iotests import qemu_img_create, qemu_io, file_path, filter_qmp_testfiles + +-iotests.verify_image_format(supported_fmts=['qcow2']) ++iotests.script_initialize(supported_fmts=['qcow2']) + + source, target = file_path('source', 'target') + size = 5 * 1024 * 1024 +diff --git a/tests/qemu-iotests/254 b/tests/qemu-iotests/254 +index ee66c986db..150e58be8e 100755 +--- a/tests/qemu-iotests/254 ++++ b/tests/qemu-iotests/254 +@@ -21,7 +21,7 @@ + import iotests + from iotests import qemu_img_create, file_path, log + +-iotests.verify_image_format(supported_fmts=['qcow2']) ++iotests.script_initialize(supported_fmts=['qcow2']) + + disk, top = file_path('disk', 'top') + size = 1024 * 1024 +diff --git a/tests/qemu-iotests/255 b/tests/qemu-iotests/255 +index 4a4818bafb..8f08f741da 100755 +--- a/tests/qemu-iotests/255 ++++ b/tests/qemu-iotests/255 +@@ -23,7 +23,7 @@ + import iotests + from iotests import imgfmt + +-iotests.verify_image_format(supported_fmts=['qcow2']) ++iotests.script_initialize(supported_fmts=['qcow2']) + + iotests.log('Finishing a commit job with background reads') + iotests.log('============================================') +diff --git a/tests/qemu-iotests/256 b/tests/qemu-iotests/256 +index e34074c83e..db8d6f31cf 100755 +--- a/tests/qemu-iotests/256 ++++ b/tests/qemu-iotests/256 +@@ -23,7 +23,7 @@ import os + import iotests + from iotests import log + +-iotests.verify_image_format(supported_fmts=['qcow2']) ++iotests.script_initialize(supported_fmts=['qcow2']) + size = 64 * 1024 * 1024 + + with iotests.FilePath('img0') as img0_path, \ +diff --git a/tests/qemu-iotests/258 b/tests/qemu-iotests/258 +index 091755a45c..a65151dda6 100755 +--- a/tests/qemu-iotests/258 ++++ b/tests/qemu-iotests/258 +@@ -24,9 +24,10 @@ from iotests import log, qemu_img, qemu_io_silent, \ + filter_qmp_testfiles, filter_qmp_imgfmt + + # Need backing file and change-backing-file support +-iotests.verify_image_format(supported_fmts=['qcow2', 'qed']) +-iotests.verify_platform(['linux']) +- ++iotests.script_initialize( ++ supported_fmts=['qcow2', 'qed'], ++ supported_platforms=['linux'], ++) + + # Returns a node for blockdev-add + def node(node_name, path, backing=None, fmt=None, throttle=None): +diff --git a/tests/qemu-iotests/260 b/tests/qemu-iotests/260 +index 30c0de380d..804a7addb9 100755 +--- a/tests/qemu-iotests/260 ++++ b/tests/qemu-iotests/260 +@@ -21,7 +21,9 @@ + import iotests + from iotests import qemu_img_create, file_path, log, filter_qmp_event + +-iotests.verify_image_format(supported_fmts=['qcow2']) ++iotests.script_initialize( ++ supported_fmts=['qcow2'] ++) + + base, top = file_path('base', 'top') + size = 64 * 1024 * 3 +diff --git a/tests/qemu-iotests/262 b/tests/qemu-iotests/262 +index 8835dce7be..03af061f94 100755 +--- a/tests/qemu-iotests/262 ++++ b/tests/qemu-iotests/262 +@@ -23,8 +23,8 @@ + import iotests + import os + +-iotests.verify_image_format(supported_fmts=['qcow2']) +-iotests.verify_platform(['linux']) ++iotests.script_initialize(supported_fmts=['qcow2'], ++ supported_platforms=['linux']) + + with iotests.FilePath('img') as img_path, \ + iotests.FilePath('mig_fifo') as fifo, \ +diff --git a/tests/qemu-iotests/264 b/tests/qemu-iotests/264 +index 879123a343..304a7443d7 100755 +--- a/tests/qemu-iotests/264 ++++ b/tests/qemu-iotests/264 +@@ -24,7 +24,9 @@ import iotests + from iotests import qemu_img_create, qemu_io_silent_check, file_path, \ + qemu_nbd_popen, log + +-iotests.verify_image_format(supported_fmts=['qcow2']) ++iotests.script_initialize( ++ supported_fmts=['qcow2'], ++) + + disk_a, disk_b, nbd_sock = file_path('disk_a', 'disk_b', 'nbd-sock') + nbd_uri = 'nbd+unix:///?socket=' + nbd_sock +diff --git a/tests/qemu-iotests/274 b/tests/qemu-iotests/274 +index e951f723b8..5d1bf34dff 100755 +--- a/tests/qemu-iotests/274 ++++ b/tests/qemu-iotests/274 +@@ -21,8 +21,8 @@ + + import iotests + +-iotests.verify_image_format(supported_fmts=['qcow2']) +-iotests.verify_platform(['linux']) ++iotests.script_initialize(supported_fmts=['qcow2'], ++ supported_platforms=['linux']) + + size_short = 1 * 1024 * 1024 + size_long = 2 * 1024 * 1024 +diff --git a/tests/qemu-iotests/277 b/tests/qemu-iotests/277 +index 04aa15a3d5..d34f87021f 100755 +--- a/tests/qemu-iotests/277 ++++ b/tests/qemu-iotests/277 +@@ -23,6 +23,8 @@ import subprocess + import iotests + from iotests import file_path, log + ++iotests.script_initialize() ++ + + nbd_sock, conf_file = file_path('nbd-sock', 'nbd-fault-injector.conf') + +diff --git a/tests/qemu-iotests/280 b/tests/qemu-iotests/280 +index 69288fdd0e..f594bb9ed2 100755 +--- a/tests/qemu-iotests/280 ++++ b/tests/qemu-iotests/280 +@@ -22,9 +22,11 @@ + import iotests + import os + +-iotests.verify_image_format(supported_fmts=['qcow2']) +-iotests.verify_protocol(supported=['file']) +-iotests.verify_platform(['linux']) ++iotests.script_initialize( ++ supported_fmts=['qcow2'], ++ supported_protocols=['file'], ++ supported_platforms=['linux'], ++) + + with iotests.FilePath('base') as base_path , \ + iotests.FilePath('top') as top_path, \ +diff --git a/tests/qemu-iotests/283 b/tests/qemu-iotests/283 +index 55b7cff953..e17b953333 100644 +--- a/tests/qemu-iotests/283 ++++ b/tests/qemu-iotests/283 +@@ -21,7 +21,9 @@ + import iotests + + # The test is unrelated to formats, restrict it to qcow2 to avoid extra runs +-iotests.verify_image_format(supported_fmts=['qcow2']) ++iotests.script_initialize( ++ supported_fmts=['qcow2'], ++) + + size = 1024 * 1024 + +diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py +index cf10c428b5..9f85e1fba3 100644 +--- a/tests/qemu-iotests/iotests.py ++++ b/tests/qemu-iotests/iotests.py +@@ -28,7 +28,8 @@ import signal + import struct + import subprocess + import sys +-from typing import (Any, Callable, Dict, Iterable, List, Optional, TypeVar) ++from typing import (Any, Callable, Dict, Iterable, ++ List, Optional, Sequence, TypeVar) + import unittest + + # pylint: disable=import-error, wrong-import-position +@@ -1029,12 +1030,11 @@ def verify_protocol(supported=(), unsupported=()): + if not_sup or (imgproto in unsupported): + notrun('not suitable for this protocol: %s' % imgproto) + +-def verify_platform(supported=None, unsupported=None): +- if unsupported is not None: +- if any((sys.platform.startswith(x) for x in unsupported)): +- notrun('not suitable for this OS: %s' % sys.platform) ++def verify_platform(supported=(), unsupported=()): ++ if any((sys.platform.startswith(x) for x in unsupported)): ++ notrun('not suitable for this OS: %s' % sys.platform) + +- if supported is not None: ++ if supported: + if not any((sys.platform.startswith(x) for x in supported)): + notrun('not suitable for this OS: %s' % sys.platform) + +@@ -1116,7 +1116,18 @@ def skip_if_user_is_root(func): + return func(*args, **kwargs) + return func_wrapper + +-def execute_unittest(output, verbosity, debug): ++def execute_unittest(debug=False): ++ """Executes unittests within the calling module.""" ++ ++ verbosity = 2 if debug else 1 ++ ++ if debug: ++ output = sys.stdout ++ else: ++ # We need to filter out the time taken from the output so that ++ # qemu-iotest can reliably diff the results against master output. ++ output = io.StringIO() ++ + runner = unittest.TextTestRunner(stream=output, descriptions=True, + verbosity=verbosity) + try: +@@ -1124,6 +1135,8 @@ def execute_unittest(output, verbosity, debug): + # exception + unittest.main(testRunner=runner) + finally: ++ # We need to filter out the time taken from the output so that ++ # qemu-iotest can reliably diff the results against master output. + if not debug: + out = output.getvalue() + out = re.sub(r'Ran (\d+) tests? in [\d.]+s', r'Ran \1 tests', out) +@@ -1135,13 +1148,19 @@ def execute_unittest(output, verbosity, debug): + + sys.stderr.write(out) + +-def execute_test(test_function=None, +- supported_fmts=(), +- supported_platforms=None, +- supported_cache_modes=(), supported_aio_modes=(), +- unsupported_fmts=(), supported_protocols=(), +- unsupported_protocols=()): +- """Run either unittest or script-style tests.""" ++def execute_setup_common(supported_fmts: Sequence[str] = (), ++ supported_platforms: Sequence[str] = (), ++ supported_cache_modes: Sequence[str] = (), ++ supported_aio_modes: Sequence[str] = (), ++ unsupported_fmts: Sequence[str] = (), ++ supported_protocols: Sequence[str] = (), ++ unsupported_protocols: Sequence[str] = ()) -> bool: ++ """ ++ Perform necessary setup for either script-style or unittest-style tests. ++ ++ :return: Bool; Whether or not debug mode has been requested via the CLI. ++ """ ++ # Note: Python 3.6 and pylint do not like 'Collection' so use 'Sequence'. + + # We are using TEST_DIR and QEMU_DEFAULT_MACHINE as proxies to + # indicate that we're not being run via "check". There may be +@@ -1151,34 +1170,39 @@ def execute_test(test_function=None, + sys.stderr.write('Please run this test via the "check" script\n') + sys.exit(os.EX_USAGE) + +- debug = '-d' in sys.argv +- verbosity = 1 + verify_image_format(supported_fmts, unsupported_fmts) + verify_protocol(supported_protocols, unsupported_protocols) + verify_platform(supported=supported_platforms) + verify_cache_mode(supported_cache_modes) + verify_aio_mode(supported_aio_modes) + ++ debug = '-d' in sys.argv + if debug: +- output = sys.stdout +- verbosity = 2 + sys.argv.remove('-d') +- else: +- # We need to filter out the time taken from the output so that +- # qemu-iotest can reliably diff the results against master output. +- output = io.StringIO() +- + logging.basicConfig(level=(logging.DEBUG if debug else logging.WARN)) + ++ return debug ++ ++def execute_test(*args, test_function=None, **kwargs): ++ """Run either unittest or script-style tests.""" ++ ++ debug = execute_setup_common(*args, **kwargs) + if not test_function: +- execute_unittest(output, verbosity, debug) ++ execute_unittest(debug) + else: + test_function() + ++# This is called from script-style iotests without a single point of entry ++def script_initialize(*args, **kwargs): ++ """Initialize script-style tests without running any tests.""" ++ execute_setup_common(*args, **kwargs) ++ ++# This is called from script-style iotests with a single point of entry + def script_main(test_function, *args, **kwargs): + """Run script-style tests outside of the unittest framework""" +- execute_test(test_function, *args, **kwargs) ++ execute_test(*args, test_function=test_function, **kwargs) + ++# This is called from unittest style iotests + def main(*args, **kwargs): + """Run tests using the unittest framework""" +- execute_test(None, *args, **kwargs) ++ execute_test(*args, **kwargs) +-- +2.23.0 + diff --git a/iotests-alphabetize-standard-imports.patch b/iotests-alphabetize-standard-imports.patch new file mode 100644 index 0000000000000000000000000000000000000000..9dc80f9a871240ace16fb987882332230f9f1b24 --- /dev/null +++ b/iotests-alphabetize-standard-imports.patch @@ -0,0 +1,57 @@ +From b404b13bd519301c99e603ac660122158ea5b93b Mon Sep 17 00:00:00 2001 +From: John Snow +Date: Mon, 30 Mar 2020 20:00:06 -0400 +Subject: [PATCH 246/709] iotests: alphabetize standard imports +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +I had to fix a merge conflict, so do this tiny harmless thing while I'm +here. + +Signed-off-by: John Snow +Reviewed-by: Max Reitz +Message-Id: <20200331000014.11581-7-jsnow@redhat.com> +Reviewed-by: Philippe Mathieu-Daudé +Reviewed-by: Kevin Wolf +Signed-off-by: Max Reitz +--- + tests/qemu-iotests/iotests.py | 18 +++++++++--------- + 1 file changed, 9 insertions(+), 9 deletions(-) + +diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py +index d8dc60275b..dae124872e 100644 +--- a/tests/qemu-iotests/iotests.py ++++ b/tests/qemu-iotests/iotests.py +@@ -16,19 +16,19 @@ + # along with this program. If not, see . + # + ++import atexit ++from collections import OrderedDict ++import faulthandler ++import io ++import json ++import logging + import os + import re ++import signal ++import struct + import subprocess +-import unittest + import sys +-import struct +-import json +-import signal +-import logging +-import atexit +-import io +-from collections import OrderedDict +-import faulthandler ++import unittest + + # pylint: disable=import-error, wrong-import-position + sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', 'python')) +-- +2.23.0 + diff --git a/iotests-do-a-light-delinting.patch b/iotests-do-a-light-delinting.patch new file mode 100644 index 0000000000000000000000000000000000000000..ee9b8c49b1c9d3be51d6daa1df7a2f9863734d6c --- /dev/null +++ b/iotests-do-a-light-delinting.patch @@ -0,0 +1,301 @@ +From 6a96d87cf40ddcd7b0e7ff398e8d2cd03c9be58d Mon Sep 17 00:00:00 2001 +From: John Snow +Date: Mon, 30 Mar 2020 20:00:01 -0400 +Subject: [PATCH 241/709] iotests: do a light delinting +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This doesn't fix everything in here, but it does help clean up the +pylint report considerably. + +This should be 100% style changes only; the intent is to make pylint +more useful by working on establishing a baseline for iotests that we +can gate against in the future. + +Signed-off-by: John Snow +Reviewed-by: Philippe Mathieu-Daudé +Reviewed-by: Max Reitz +Message-Id: <20200331000014.11581-2-jsnow@redhat.com> +Reviewed-by: Kevin Wolf +Signed-off-by: Max Reitz +--- + tests/qemu-iotests/iotests.py | 83 ++++++++++++++++++----------------- + 1 file changed, 43 insertions(+), 40 deletions(-) + +diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py +index 5f8c263d59..6f6363f3ec 100644 +--- a/tests/qemu-iotests/iotests.py ++++ b/tests/qemu-iotests/iotests.py +@@ -16,11 +16,9 @@ + # along with this program. If not, see . + # + +-import errno + import os + import re + import subprocess +-import string + import unittest + import sys + import struct +@@ -35,7 +33,7 @@ import faulthandler + sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', 'python')) + from qemu import qtest + +-assert sys.version_info >= (3,6) ++assert sys.version_info >= (3, 6) + + faulthandler.enable() + +@@ -141,11 +139,11 @@ def qemu_img_log(*args): + return result + + def img_info_log(filename, filter_path=None, imgopts=False, extra_args=[]): +- args = [ 'info' ] ++ args = ['info'] + if imgopts: + args.append('--image-opts') + else: +- args += [ '-f', imgfmt ] ++ args += ['-f', imgfmt] + args += extra_args + args.append(filename) + +@@ -224,7 +222,7 @@ class QemuIoInteractive: + # quit command is in close(), '\n' is added automatically + assert '\n' not in cmd + cmd = cmd.strip() +- assert cmd != 'q' and cmd != 'quit' ++ assert cmd not in ('q', 'quit') + self._p.stdin.write(cmd + '\n') + self._p.stdin.flush() + return self._read_output() +@@ -246,10 +244,8 @@ def qemu_nbd_early_pipe(*args): + sys.stderr.write('qemu-nbd received signal %i: %s\n' % + (-exitcode, + ' '.join(qemu_nbd_args + ['--fork'] + list(args)))) +- if exitcode == 0: +- return exitcode, '' +- else: +- return exitcode, subp.communicate()[0] ++ ++ return exitcode, subp.communicate()[0] if exitcode else '' + + def qemu_nbd_popen(*args): + '''Run qemu-nbd in daemon mode and return the parent's exit code''' +@@ -313,7 +309,7 @@ def filter_qmp(qmsg, filter_fn): + items = qmsg.items() + + for k, v in items: +- if isinstance(v, list) or isinstance(v, dict): ++ if isinstance(v, (dict, list)): + qmsg[k] = filter_qmp(v, filter_fn) + else: + qmsg[k] = filter_fn(k, v) +@@ -324,7 +320,7 @@ def filter_testfiles(msg): + return msg.replace(prefix, 'TEST_DIR/PID-') + + def filter_qmp_testfiles(qmsg): +- def _filter(key, value): ++ def _filter(_key, value): + if is_str(value): + return filter_testfiles(value) + return value +@@ -351,7 +347,7 @@ def filter_imgfmt(msg): + return msg.replace(imgfmt, 'IMGFMT') + + def filter_qmp_imgfmt(qmsg): +- def _filter(key, value): ++ def _filter(_key, value): + if is_str(value): + return filter_imgfmt(value) + return value +@@ -362,7 +358,7 @@ def log(msg, filters=[], indent=None): + If indent is provided, JSON serializable messages are pretty-printed.''' + for flt in filters: + msg = flt(msg) +- if isinstance(msg, dict) or isinstance(msg, list): ++ if isinstance(msg, (dict, list)): + # Python < 3.4 needs to know not to add whitespace when pretty-printing: + separators = (', ', ': ') if indent is None else (',', ': ') + # Don't sort if it's already sorted +@@ -373,14 +369,14 @@ def log(msg, filters=[], indent=None): + print(msg) + + class Timeout: +- def __init__(self, seconds, errmsg = "Timeout"): ++ def __init__(self, seconds, errmsg="Timeout"): + self.seconds = seconds + self.errmsg = errmsg + def __enter__(self): + signal.signal(signal.SIGALRM, self.timeout) + signal.setitimer(signal.ITIMER_REAL, self.seconds) + return self +- def __exit__(self, type, value, traceback): ++ def __exit__(self, exc_type, value, traceback): + signal.setitimer(signal.ITIMER_REAL, 0) + return False + def timeout(self, signum, frame): +@@ -389,7 +385,7 @@ class Timeout: + def file_pattern(name): + return "{0}-{1}".format(os.getpid(), name) + +-class FilePaths(object): ++class FilePaths: + """ + FilePaths is an auto-generated filename that cleans itself up. + +@@ -536,11 +532,11 @@ class VM(qtest.QEMUQtestMachine): + self.pause_drive(drive, "write_aio") + return + self.qmp('human-monitor-command', +- command_line='qemu-io %s "break %s bp_%s"' % (drive, event, drive)) ++ command_line='qemu-io %s "break %s bp_%s"' % (drive, event, drive)) + + def resume_drive(self, drive): + self.qmp('human-monitor-command', +- command_line='qemu-io %s "remove_break bp_%s"' % (drive, drive)) ++ command_line='qemu-io %s "remove_break bp_%s"' % (drive, drive)) + + def hmp_qemu_io(self, drive, cmd): + '''Write to a given drive using an HMP command''' +@@ -551,8 +547,8 @@ class VM(qtest.QEMUQtestMachine): + if output is None: + output = dict() + if isinstance(obj, list): +- for i in range(len(obj)): +- self.flatten_qmp_object(obj[i], output, basestr + str(i) + '.') ++ for i, item in enumerate(obj): ++ self.flatten_qmp_object(item, output, basestr + str(i) + '.') + elif isinstance(obj, dict): + for key in obj: + self.flatten_qmp_object(obj[key], output, basestr + key + '.') +@@ -710,9 +706,7 @@ class VM(qtest.QEMUQtestMachine): + + for bitmap in bitmaps[node_name]: + if bitmap.get('name', '') == bitmap_name: +- if recording is None: +- return bitmap +- elif bitmap.get('recording') == recording: ++ if recording is None or bitmap.get('recording') == recording: + return bitmap + return None + +@@ -763,12 +757,13 @@ class VM(qtest.QEMUQtestMachine): + assert node is not None, 'Cannot follow path %s%s' % (root, path) + + try: +- node_id = next(edge['child'] for edge in graph['edges'] \ +- if edge['parent'] == node['id'] and +- edge['name'] == child_name) ++ node_id = next(edge['child'] for edge in graph['edges'] ++ if (edge['parent'] == node['id'] and ++ edge['name'] == child_name)) ++ ++ node = next(node for node in graph['nodes'] ++ if node['id'] == node_id) + +- node = next(node for node in graph['nodes'] \ +- if node['id'] == node_id) + except StopIteration: + node = None + +@@ -786,6 +781,12 @@ index_re = re.compile(r'([^\[]+)\[([^\]]+)\]') + class QMPTestCase(unittest.TestCase): + '''Abstract base class for QMP test cases''' + ++ def __init__(self, *args, **kwargs): ++ super().__init__(*args, **kwargs) ++ # Many users of this class set a VM property we rely on heavily ++ # in the methods below. ++ self.vm = None ++ + def dictpath(self, d, path): + '''Traverse a path in a nested dict''' + for component in path.split('/'): +@@ -831,7 +832,7 @@ class QMPTestCase(unittest.TestCase): + else: + self.assertEqual(result, value, + '"%s" is "%s", expected "%s"' +- % (path, str(result), str(value))) ++ % (path, str(result), str(value))) + + def assert_no_active_block_jobs(self): + result = self.vm.qmp('query-block-jobs') +@@ -841,15 +842,15 @@ class QMPTestCase(unittest.TestCase): + """Issue a query-named-block-nodes and assert node_name and/or + file_name is present in the result""" + def check_equal_or_none(a, b): +- return a == None or b == None or a == b ++ return a is None or b is None or a == b + assert node_name or file_name + result = self.vm.qmp('query-named-block-nodes') + for x in result["return"]: + if check_equal_or_none(x.get("node-name"), node_name) and \ + check_equal_or_none(x.get("file"), file_name): + return +- self.assertTrue(False, "Cannot find %s %s in result:\n%s" % \ +- (node_name, file_name, result)) ++ self.fail("Cannot find %s %s in result:\n%s" % ++ (node_name, file_name, result)) + + def assert_json_filename_equal(self, json_filename, reference): + '''Asserts that the given filename is a json: filename and that its +@@ -898,13 +899,13 @@ class QMPTestCase(unittest.TestCase): + self.assert_qmp(event, 'data/error', error) + self.assert_no_active_block_jobs() + return event +- elif event['event'] == 'JOB_STATUS_CHANGE': ++ if event['event'] == 'JOB_STATUS_CHANGE': + self.assert_qmp(event, 'data/id', drive) + + def wait_ready(self, drive='drive0'): +- '''Wait until a block job BLOCK_JOB_READY event''' +- f = {'data': {'type': 'mirror', 'device': drive } } +- event = self.vm.event_wait(name='BLOCK_JOB_READY', match=f) ++ """Wait until a BLOCK_JOB_READY event, and return the event.""" ++ f = {'data': {'type': 'mirror', 'device': drive}} ++ return self.vm.event_wait(name='BLOCK_JOB_READY', match=f) + + def wait_ready_and_cancel(self, drive='drive0'): + self.wait_ready(drive=drive) +@@ -933,7 +934,7 @@ class QMPTestCase(unittest.TestCase): + for job in result['return']: + if job['device'] == job_id: + found = True +- if job['paused'] == True and job['busy'] == False: ++ if job['paused'] and not job['busy']: + return job + break + assert found +@@ -1030,8 +1031,8 @@ def qemu_pipe(*args): + universal_newlines=True) + exitcode = subp.wait() + if exitcode < 0: +- sys.stderr.write('qemu received signal %i: %s\n' % (-exitcode, +- ' '.join(args))) ++ sys.stderr.write('qemu received signal %i: %s\n' % ++ (-exitcode, ' '.join(args))) + return subp.communicate()[0] + + def supported_formats(read_only=False): +@@ -1063,6 +1064,7 @@ def skip_if_unsupported(required_formats=[], read_only=False): + if usf_list: + test_case.case_skip('{}: formats {} are not whitelisted'.format( + test_case, usf_list)) ++ return None + else: + return func(test_case, *args, **kwargs) + return func_wrapper +@@ -1074,6 +1076,7 @@ def skip_if_user_is_root(func): + def func_wrapper(*args, **kwargs): + if os.getuid() == 0: + case_notrun('{}: cannot be run as root'.format(args[0])) ++ return None + else: + return func(*args, **kwargs) + return func_wrapper +-- +2.23.0 + diff --git a/iotests-don-t-use-format-for-drive_add.patch b/iotests-don-t-use-format-for-drive_add.patch new file mode 100644 index 0000000000000000000000000000000000000000..bca3d982bba965f7ab6cace1f26c92dfb1c4e421 --- /dev/null +++ b/iotests-don-t-use-format-for-drive_add.patch @@ -0,0 +1,68 @@ +From 1d3d4b630c6ea8b19420c097f0c448b6ded95072 Mon Sep 17 00:00:00 2001 +From: John Snow +Date: Mon, 30 Mar 2020 20:00:02 -0400 +Subject: [PATCH 242/709] iotests: don't use 'format' for drive_add +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +It shadows (with a different type) the built-in format. +Use something else. + +Signed-off-by: John Snow +Reviewed-by: Philippe Mathieu-Daudé +Reviewed-by: Max Reitz +Message-Id: <20200331000014.11581-3-jsnow@redhat.com> +Reviewed-by: Kevin Wolf +Signed-off-by: Max Reitz +--- + tests/qemu-iotests/055 | 3 ++- + tests/qemu-iotests/iotests.py | 6 +++--- + 2 files changed, 5 insertions(+), 4 deletions(-) + +diff --git a/tests/qemu-iotests/055 b/tests/qemu-iotests/055 +index 82b9f5f47d..4175fff5e4 100755 +--- a/tests/qemu-iotests/055 ++++ b/tests/qemu-iotests/055 +@@ -469,7 +469,8 @@ class TestDriveCompression(iotests.QMPTestCase): + qemu_img('create', '-f', fmt, blockdev_target_img, + str(TestDriveCompression.image_len), *args) + if attach_target: +- self.vm.add_drive(blockdev_target_img, format=fmt, interface="none") ++ self.vm.add_drive(blockdev_target_img, ++ img_format=fmt, interface="none") + + self.vm.launch() + +diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py +index 6f6363f3ec..aca7d50524 100644 +--- a/tests/qemu-iotests/iotests.py ++++ b/tests/qemu-iotests/iotests.py +@@ -486,21 +486,21 @@ class VM(qtest.QEMUQtestMachine): + self._args.append(opts) + return self + +- def add_drive(self, path, opts='', interface='virtio', format=imgfmt): ++ def add_drive(self, path, opts='', interface='virtio', img_format=imgfmt): + '''Add a virtio-blk drive to the VM''' + options = ['if=%s' % interface, + 'id=drive%d' % self._num_drives] + + if path is not None: + options.append('file=%s' % path) +- options.append('format=%s' % format) ++ options.append('format=%s' % img_format) + options.append('cache=%s' % cachemode) + options.append('aio=%s' % aiomode) + + if opts: + options.append(opts) + +- if format == 'luks' and 'key-secret' not in opts: ++ if img_format == 'luks' and 'key-secret' not in opts: + # default luks support + if luks_default_secret_object not in self._args: + self.add_object(luks_default_secret_object) +-- +2.23.0 + diff --git a/iotests-drop-pre-Python-3.4-compatibility-code.patch b/iotests-drop-pre-Python-3.4-compatibility-code.patch new file mode 100644 index 0000000000000000000000000000000000000000..59c7c9391d694330cbded85092953391b7970b2e --- /dev/null +++ b/iotests-drop-pre-Python-3.4-compatibility-code.patch @@ -0,0 +1,38 @@ +From 229fc0742a727c1733dd4d0c405c4c590f8dc627 Mon Sep 17 00:00:00 2001 +From: John Snow +Date: Mon, 30 Mar 2020 20:00:07 -0400 +Subject: [PATCH 247/709] iotests: drop pre-Python 3.4 compatibility code + +We no longer need to accommodate <3.4, drop this code. +(The lines were > 79 chars and it stood out.) + +Signed-off-by: John Snow +Reviewed-by: Max Reitz +Message-Id: <20200331000014.11581-8-jsnow@redhat.com> +Reviewed-by: Kevin Wolf +Signed-off-by: Max Reitz +--- + tests/qemu-iotests/iotests.py | 5 +---- + 1 file changed, 1 insertion(+), 4 deletions(-) + +diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py +index dae124872e..374a8f6077 100644 +--- a/tests/qemu-iotests/iotests.py ++++ b/tests/qemu-iotests/iotests.py +@@ -360,12 +360,9 @@ def log(msg, filters=(), indent=None): + for flt in filters: + msg = flt(msg) + if isinstance(msg, (dict, list)): +- # Python < 3.4 needs to know not to add whitespace when pretty-printing: +- separators = (', ', ': ') if indent is None else (',', ': ') + # Don't sort if it's already sorted + do_sort = not isinstance(msg, OrderedDict) +- print(json.dumps(msg, sort_keys=do_sort, +- indent=indent, separators=separators)) ++ print(json.dumps(msg, sort_keys=do_sort, indent=indent)) + else: + print(msg) + +-- +2.23.0 + diff --git a/iotests-handle-tmpfs.patch b/iotests-handle-tmpfs.patch new file mode 100644 index 0000000000000000000000000000000000000000..f97832505afc255c4002b23b68787453aded6374 --- /dev/null +++ b/iotests-handle-tmpfs.patch @@ -0,0 +1,90 @@ +From cfdca2b9f9d4ca26bb2b2dfe8de3149092e39170 Mon Sep 17 00:00:00 2001 +From: Vladimir Sementsov-Ogievskiy +Date: Thu, 30 Apr 2020 15:47:06 +0300 +Subject: [PATCH 328/709] iotests: handle tmpfs + +Some tests requires O_DIRECT, or want it by default. Introduce smarter +O_DIRECT handling: + +- Check O_DIRECT in common.rc, if it is requested by selected +cache-mode. + +- Support second fall-through argument in _default_cache_mode + +Inspired-by: Max's 23e1d054112cec1e +Signed-off-by: Vladimir Sementsov-Ogievskiy +Message-Id: <20200430124713.3067-2-vsementsov@virtuozzo.com> +Signed-off-by: Kevin Wolf +--- + tests/qemu-iotests/091 | 2 +- + tests/qemu-iotests/common.rc | 37 ++++++++++++++++++++++++++++++++++-- + 2 files changed, 36 insertions(+), 3 deletions(-) + +diff --git a/tests/qemu-iotests/091 b/tests/qemu-iotests/091 +index d2a2aca347..68fbfd777b 100755 +--- a/tests/qemu-iotests/091 ++++ b/tests/qemu-iotests/091 +@@ -46,8 +46,8 @@ trap "_cleanup; exit \$status" 0 1 2 3 15 + _supported_fmt qcow2 + _supported_proto file + _supported_os Linux +-_default_cache_mode none + _supported_cache_modes writethrough none writeback ++_default_cache_mode none writeback + + size=1G + +diff --git a/tests/qemu-iotests/common.rc b/tests/qemu-iotests/common.rc +index bf3b9fdea0..ba912555ca 100644 +--- a/tests/qemu-iotests/common.rc ++++ b/tests/qemu-iotests/common.rc +@@ -673,11 +673,44 @@ _supported_cache_modes() + _notrun "not suitable for cache mode: $CACHEMODE" + } + ++# Check whether the filesystem supports O_DIRECT ++_check_o_direct() ++{ ++ $QEMU_IMG create -f raw "$TEST_IMG".test_o_direct 1M > /dev/null ++ out=$($QEMU_IO -f raw -t none -c quit "$TEST_IMG".test_o_direct 2>&1) ++ rm -f "$TEST_IMG".test_o_direct ++ ++ [[ "$out" != *"O_DIRECT"* ]] ++} ++ ++_require_o_direct() ++{ ++ if ! _check_o_direct; then ++ _notrun "file system on $TEST_DIR does not support O_DIRECT" ++ fi ++} ++ ++_check_cache_mode() ++{ ++ if [ $CACHEMODE == "none" ] || [ $CACHEMODE == "directsync" ]; then ++ _require_o_direct ++ fi ++} ++ ++_check_cache_mode ++ ++# $1 - cache mode to use by default ++# $2 - (optional) cache mode to use by default if O_DIRECT is not supported + _default_cache_mode() + { + if $CACHEMODE_IS_DEFAULT; then +- CACHEMODE="$1" +- QEMU_IO="$QEMU_IO --cache $1" ++ if [ -z "$2" ] || _check_o_direct; then ++ CACHEMODE="$1" ++ else ++ CACHEMODE="$2" ++ fi ++ QEMU_IO="$QEMU_IO --cache $CACHEMODE" ++ _check_cache_mode + return + fi + } +-- +2.23.0 + diff --git a/iotests-ignore-import-warnings-from-pylint.patch b/iotests-ignore-import-warnings-from-pylint.patch new file mode 100644 index 0000000000000000000000000000000000000000..7ce41cc453ba973a91edc45ac2be64a6091963e1 --- /dev/null +++ b/iotests-ignore-import-warnings-from-pylint.patch @@ -0,0 +1,39 @@ +From 368e06200320fd1c046788832531c0148ccbdf11 Mon Sep 17 00:00:00 2001 +From: John Snow +Date: Mon, 30 Mar 2020 20:00:03 -0400 +Subject: [PATCH 243/709] iotests: ignore import warnings from pylint +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The right way to solve this is to come up with a virtual environment +infrastructure that sets all the paths correctly, and/or to create +installable python modules that can be imported normally. + +That's hard, so just silence this error for now. + +Reviewed-by: Philippe Mathieu-Daudé +Reviewed-by: Max Reitz +Signed-off-by: John Snow +Message-Id: <20200331000014.11581-4-jsnow@redhat.com> +Reviewed-by: Kevin Wolf +Signed-off-by: Max Reitz +--- + tests/qemu-iotests/iotests.py | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py +index aca7d50524..37a32c7461 100644 +--- a/tests/qemu-iotests/iotests.py ++++ b/tests/qemu-iotests/iotests.py +@@ -30,6 +30,7 @@ import io + from collections import OrderedDict + import faulthandler + ++# pylint: disable=import-error, wrong-import-position + sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', 'python')) + from qemu import qtest + +-- +2.23.0 + diff --git a/iotests-limit-line-length-to-79-chars.patch b/iotests-limit-line-length-to-79-chars.patch new file mode 100644 index 0000000000000000000000000000000000000000..cb108a6e8251dc09ac8cf6ea0561b9f7e5590fca --- /dev/null +++ b/iotests-limit-line-length-to-79-chars.patch @@ -0,0 +1,202 @@ +From b031e9a5a65ceef722ba506bc5ee69ec785dc5c5 Mon Sep 17 00:00:00 2001 +From: John Snow +Date: Mon, 30 Mar 2020 20:00:09 -0400 +Subject: [PATCH 249/709] iotests: limit line length to 79 chars + +79 is the PEP8 recommendation. This recommendation works well for +reading patch diffs in TUI email clients. + +Signed-off-by: John Snow +Reviewed-by: Max Reitz +Message-Id: <20200331000014.11581-10-jsnow@redhat.com> +Reviewed-by: Kevin Wolf +Signed-off-by: Max Reitz +--- + tests/qemu-iotests/iotests.py | 64 +++++++++++++++++++++++------------ + tests/qemu-iotests/pylintrc | 6 +++- + 2 files changed, 47 insertions(+), 23 deletions(-) + +diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py +index 69f24223d2..9f5da32dae 100644 +--- a/tests/qemu-iotests/iotests.py ++++ b/tests/qemu-iotests/iotests.py +@@ -80,9 +80,11 @@ luks_default_key_secret_opt = 'key-secret=keysec0' + def qemu_img(*args): + '''Run qemu-img and return the exit code''' + devnull = open('/dev/null', 'r+') +- exitcode = subprocess.call(qemu_img_args + list(args), stdin=devnull, stdout=devnull) ++ exitcode = subprocess.call(qemu_img_args + list(args), ++ stdin=devnull, stdout=devnull) + if exitcode < 0: +- sys.stderr.write('qemu-img received signal %i: %s\n' % (-exitcode, ' '.join(qemu_img_args + list(args)))) ++ sys.stderr.write('qemu-img received signal %i: %s\n' ++ % (-exitcode, ' '.join(qemu_img_args + list(args)))) + return exitcode + + def ordered_qmp(qmsg, conv_keys=True): +@@ -121,7 +123,8 @@ def qemu_img_verbose(*args): + '''Run qemu-img without suppressing its output and return the exit code''' + exitcode = subprocess.call(qemu_img_args + list(args)) + if exitcode < 0: +- sys.stderr.write('qemu-img received signal %i: %s\n' % (-exitcode, ' '.join(qemu_img_args + list(args)))) ++ sys.stderr.write('qemu-img received signal %i: %s\n' ++ % (-exitcode, ' '.join(qemu_img_args + list(args)))) + return exitcode + + def qemu_img_pipe(*args): +@@ -132,7 +135,8 @@ def qemu_img_pipe(*args): + universal_newlines=True) + exitcode = subp.wait() + if exitcode < 0: +- sys.stderr.write('qemu-img received signal %i: %s\n' % (-exitcode, ' '.join(qemu_img_args + list(args)))) ++ sys.stderr.write('qemu-img received signal %i: %s\n' ++ % (-exitcode, ' '.join(qemu_img_args + list(args)))) + return subp.communicate()[0] + + def qemu_img_log(*args): +@@ -162,7 +166,8 @@ def qemu_io(*args): + universal_newlines=True) + exitcode = subp.wait() + if exitcode < 0: +- sys.stderr.write('qemu-io received signal %i: %s\n' % (-exitcode, ' '.join(args))) ++ sys.stderr.write('qemu-io received signal %i: %s\n' ++ % (-exitcode, ' '.join(args))) + return subp.communicate()[0] + + def qemu_io_log(*args): +@@ -284,10 +289,13 @@ win32_re = re.compile(r"\r") + def filter_win32(msg): + return win32_re.sub("", msg) + +-qemu_io_re = re.compile(r"[0-9]* ops; [0-9\/:. sec]* \([0-9\/.inf]* [EPTGMKiBbytes]*\/sec and [0-9\/.inf]* ops\/sec\)") ++qemu_io_re = re.compile(r"[0-9]* ops; [0-9\/:. sec]* " ++ r"\([0-9\/.inf]* [EPTGMKiBbytes]*\/sec " ++ r"and [0-9\/.inf]* ops\/sec\)") + def filter_qemu_io(msg): + msg = filter_win32(msg) +- return qemu_io_re.sub("X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)", msg) ++ return qemu_io_re.sub("X ops; XX:XX:XX.X " ++ "(XXX YYY/sec and XXX ops/sec)", msg) + + chown_re = re.compile(r"chown [0-9]+:[0-9]+") + def filter_chown(msg): +@@ -340,7 +348,9 @@ def filter_img_info(output, filename): + line = filter_testfiles(line) + line = line.replace(imgfmt, 'IMGFMT') + line = re.sub('iters: [0-9]+', 'iters: XXX', line) +- line = re.sub('uuid: [-a-f0-9]+', 'uuid: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX', line) ++ line = re.sub('uuid: [-a-f0-9]+', ++ 'uuid: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX', ++ line) + line = re.sub('cid: [0-9]+', 'cid: XXXXXXXXXX', line) + lines.append(line) + return '\n'.join(lines) +@@ -538,11 +548,13 @@ class VM(qtest.QEMUQtestMachine): + self.pause_drive(drive, "write_aio") + return + self.qmp('human-monitor-command', +- command_line='qemu-io %s "break %s bp_%s"' % (drive, event, drive)) ++ command_line='qemu-io %s "break %s bp_%s"' ++ % (drive, event, drive)) + + def resume_drive(self, drive): + self.qmp('human-monitor-command', +- command_line='qemu-io %s "remove_break bp_%s"' % (drive, drive)) ++ command_line='qemu-io %s "remove_break bp_%s"' ++ % (drive, drive)) + + def hmp_qemu_io(self, drive, cmd): + '''Write to a given drive using an HMP command''' +@@ -802,16 +814,18 @@ class QMPTestCase(unittest.TestCase): + idx = int(idx) + + if not isinstance(d, dict) or component not in d: +- self.fail('failed path traversal for "%s" in "%s"' % (path, str(d))) ++ self.fail(f'failed path traversal for "{path}" in "{d}"') + d = d[component] + + if m: + if not isinstance(d, list): +- self.fail('path component "%s" in "%s" is not a list in "%s"' % (component, path, str(d))) ++ self.fail(f'path component "{component}" in "{path}" ' ++ f'is not a list in "{d}"') + try: + d = d[idx] + except IndexError: +- self.fail('invalid index "%s" in path "%s" in "%s"' % (idx, path, str(d))) ++ self.fail(f'invalid index "{idx}" in path "{path}" ' ++ f'in "{d}"') + return d + + def assert_qmp_absent(self, d, path): +@@ -862,10 +876,13 @@ class QMPTestCase(unittest.TestCase): + '''Asserts that the given filename is a json: filename and that its + content is equal to the given reference object''' + self.assertEqual(json_filename[:5], 'json:') +- self.assertEqual(self.vm.flatten_qmp_object(json.loads(json_filename[5:])), +- self.vm.flatten_qmp_object(reference)) ++ self.assertEqual( ++ self.vm.flatten_qmp_object(json.loads(json_filename[5:])), ++ self.vm.flatten_qmp_object(reference) ++ ) + +- def cancel_and_wait(self, drive='drive0', force=False, resume=False, wait=60.0): ++ def cancel_and_wait(self, drive='drive0', force=False, ++ resume=False, wait=60.0): + '''Cancel a block job and wait for it to finish, returning the event''' + result = self.vm.qmp('block-job-cancel', device=drive, force=force) + self.assert_qmp(result, 'return', {}) +@@ -889,8 +906,8 @@ class QMPTestCase(unittest.TestCase): + self.assert_no_active_block_jobs() + return result + +- def wait_until_completed(self, drive='drive0', check_offset=True, wait=60.0, +- error=None): ++ def wait_until_completed(self, drive='drive0', check_offset=True, ++ wait=60.0, error=None): + '''Wait for a block job to finish, returning the event''' + while True: + for event in self.vm.get_qmp_events(wait=wait): +@@ -1029,8 +1046,11 @@ def verify_quorum(): + notrun('quorum support missing') + + def qemu_pipe(*args): +- '''Run qemu with an option to print something and exit (e.g. a help option), +- and return its output''' ++ """ ++ Run qemu with an option to print something and exit (e.g. a help option). ++ ++ :return: QEMU's stdout output. ++ """ + args = [qemu_prog] + qemu_opts + list(args) + subp = subprocess.Popen(args, stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, +@@ -1068,8 +1088,8 @@ def skip_if_unsupported(required_formats=(), read_only=False): + + usf_list = list(set(fmts) - set(supported_formats(read_only))) + if usf_list: +- test_case.case_skip('{}: formats {} are not whitelisted'.format( +- test_case, usf_list)) ++ msg = f'{test_case}: formats {usf_list} are not whitelisted' ++ test_case.case_skip(msg) + return None + else: + return func(test_case, *args, **kwargs) +diff --git a/tests/qemu-iotests/pylintrc b/tests/qemu-iotests/pylintrc +index daec2c4942..5481afe528 100644 +--- a/tests/qemu-iotests/pylintrc ++++ b/tests/qemu-iotests/pylintrc +@@ -18,5 +18,9 @@ disable=invalid-name, + too-many-locals, + too-many-public-methods, + # These are temporary, and should be removed: +- line-too-long, + missing-docstring, ++ ++[FORMAT] ++ ++# Maximum number of characters on a single line. ++max-line-length=79 +-- +2.23.0 + diff --git a/iotests-log-messages-from-notrun.patch b/iotests-log-messages-from-notrun.patch new file mode 100644 index 0000000000000000000000000000000000000000..f38f9e36b202e3e5cdb4a1029fff60160c951ee0 --- /dev/null +++ b/iotests-log-messages-from-notrun.patch @@ -0,0 +1,49 @@ +From 44a46a9cd9f088e1a9655f2af8cb72ec36dfc731 Mon Sep 17 00:00:00 2001 +From: John Snow +Date: Thu, 14 May 2020 16:16:12 -0400 +Subject: [PATCH 569/709] iotests: log messages from notrun() + +Shift the logging initialization up to occur prior to validation checks, +so that notrun() messages still get printed to console. + +(Also, remove the "debugging messages active" message, because we don't +need to see that hundreds of times per iotest suite run.) + +Signed-off-by: John Snow +Message-Id: <20200514201614.19941-2-jsnow@redhat.com> +Signed-off-by: Kevin Wolf +--- + tests/qemu-iotests/iotests.py | 11 +++++------ + 1 file changed, 5 insertions(+), 6 deletions(-) + +diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py +index 1d7f6fd7cf..f20d90f969 100644 +--- a/tests/qemu-iotests/iotests.py ++++ b/tests/qemu-iotests/iotests.py +@@ -1168,18 +1168,17 @@ def execute_setup_common(supported_fmts: Sequence[str] = (), + sys.stderr.write('Please run this test via the "check" script\n') + sys.exit(os.EX_USAGE) + ++ debug = '-d' in sys.argv ++ if debug: ++ sys.argv.remove('-d') ++ logging.basicConfig(level=(logging.DEBUG if debug else logging.WARN)) ++ + _verify_image_format(supported_fmts, unsupported_fmts) + _verify_protocol(supported_protocols, unsupported_protocols) + _verify_platform(supported=supported_platforms) + _verify_cache_mode(supported_cache_modes) + _verify_aio_mode(supported_aio_modes) + +- debug = '-d' in sys.argv +- if debug: +- sys.argv.remove('-d') +- logging.basicConfig(level=(logging.DEBUG if debug else logging.WARN)) +- logger.debug("iotests debugging messages active") +- + return debug + + def execute_test(*args, test_function=None, **kwargs): +-- +2.23.0 + diff --git a/iotests-replace-mutable-list-default-args.patch b/iotests-replace-mutable-list-default-args.patch new file mode 100644 index 0000000000000000000000000000000000000000..88e2a07e581ee26a282fa25cbd5bcca951772265 --- /dev/null +++ b/iotests-replace-mutable-list-default-args.patch @@ -0,0 +1,115 @@ +From 4eabe0515ad7947da566fa52f9bd29e6fc1e6dcc Mon Sep 17 00:00:00 2001 +From: John Snow +Date: Mon, 30 Mar 2020 20:00:04 -0400 +Subject: [PATCH 244/709] iotests: replace mutable list default args +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +It's bad hygiene: if we modify this list, it will be modified across all +invocations. + +(Remaining bad usages are fixed in a subsequent patch which changes the +function signature anyway.) + +Signed-off-by: John Snow +Reviewed-by: Philippe Mathieu-Daudé +Reviewed-by: Max Reitz +Message-Id: <20200331000014.11581-5-jsnow@redhat.com> +Reviewed-by: Kevin Wolf +Signed-off-by: Max Reitz +--- + tests/qemu-iotests/iotests.py | 24 ++++++++++++------------ + 1 file changed, 12 insertions(+), 12 deletions(-) + +diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py +index 37a32c7461..d8dc60275b 100644 +--- a/tests/qemu-iotests/iotests.py ++++ b/tests/qemu-iotests/iotests.py +@@ -139,7 +139,7 @@ def qemu_img_log(*args): + log(result, filters=[filter_testfiles]) + return result + +-def img_info_log(filename, filter_path=None, imgopts=False, extra_args=[]): ++def img_info_log(filename, filter_path=None, imgopts=False, extra_args=()): + args = ['info'] + if imgopts: + args.append('--image-opts') +@@ -354,7 +354,7 @@ def filter_qmp_imgfmt(qmsg): + return value + return filter_qmp(qmsg, _filter) + +-def log(msg, filters=[], indent=None): ++def log(msg, filters=(), indent=None): + '''Logs either a string message or a JSON serializable message (like QMP). + If indent is provided, JSON serializable messages are pretty-printed.''' + for flt in filters: +@@ -570,7 +570,7 @@ class VM(qtest.QEMUQtestMachine): + result.append(filter_qmp_event(ev)) + return result + +- def qmp_log(self, cmd, filters=[], indent=None, **kwargs): ++ def qmp_log(self, cmd, filters=(), indent=None, **kwargs): + full_cmd = OrderedDict(( + ("execute", cmd), + ("arguments", ordered_qmp(kwargs)) +@@ -974,7 +974,7 @@ def case_notrun(reason): + open('%s/%s.casenotrun' % (output_dir, seq), 'a').write( + ' [case not run] ' + reason + '\n') + +-def verify_image_format(supported_fmts=[], unsupported_fmts=[]): ++def verify_image_format(supported_fmts=(), unsupported_fmts=()): + assert not (supported_fmts and unsupported_fmts) + + if 'generic' in supported_fmts and \ +@@ -988,7 +988,7 @@ def verify_image_format(supported_fmts=[], unsupported_fmts=[]): + if not_sup or (imgfmt in unsupported_fmts): + notrun('not suitable for this image format: %s' % imgfmt) + +-def verify_protocol(supported=[], unsupported=[]): ++def verify_protocol(supported=(), unsupported=()): + assert not (supported and unsupported) + + if 'generic' in supported: +@@ -1007,11 +1007,11 @@ def verify_platform(supported=None, unsupported=None): + if not any((sys.platform.startswith(x) for x in supported)): + notrun('not suitable for this OS: %s' % sys.platform) + +-def verify_cache_mode(supported_cache_modes=[]): ++def verify_cache_mode(supported_cache_modes=()): + if supported_cache_modes and (cachemode not in supported_cache_modes): + notrun('not suitable for this cache mode: %s' % cachemode) + +-def verify_aio_mode(supported_aio_modes=[]): ++def verify_aio_mode(supported_aio_modes=()): + if supported_aio_modes and (aiomode not in supported_aio_modes): + notrun('not suitable for this aio mode: %s' % aiomode) + +@@ -1051,7 +1051,7 @@ def supported_formats(read_only=False): + + return supported_formats.formats[read_only] + +-def skip_if_unsupported(required_formats=[], read_only=False): ++def skip_if_unsupported(required_formats=(), read_only=False): + '''Skip Test Decorator + Runs the test if all the required formats are whitelisted''' + def skip_test_decorator(func): +@@ -1102,11 +1102,11 @@ def execute_unittest(output, verbosity, debug): + sys.stderr.write(out) + + def execute_test(test_function=None, +- supported_fmts=[], ++ supported_fmts=(), + supported_platforms=None, +- supported_cache_modes=[], supported_aio_modes={}, +- unsupported_fmts=[], supported_protocols=[], +- unsupported_protocols=[]): ++ supported_cache_modes=(), supported_aio_modes=(), ++ unsupported_fmts=(), supported_protocols=(), ++ unsupported_protocols=()): + """Run either unittest or script-style tests.""" + + # We are using TEST_DIR and QEMU_DEFAULT_MACHINE as proxies to +-- +2.23.0 + diff --git a/iotests-touch-up-log-function-signature.patch b/iotests-touch-up-log-function-signature.patch new file mode 100644 index 0000000000000000000000000000000000000000..f8e79307bdabb44892af3d3e4d9d0ae27b99b96b --- /dev/null +++ b/iotests-touch-up-log-function-signature.patch @@ -0,0 +1,65 @@ +From 1cd0dbfc12019fcd5f0529094a939a1557dfc2df Mon Sep 17 00:00:00 2001 +From: John Snow +Date: Mon, 30 Mar 2020 20:00:08 -0400 +Subject: [PATCH 248/709] iotests: touch up log function signature + +Representing nested, recursive data structures in mypy is notoriously +difficult; the best we can reliably do right now is denote the leaf +types as "Any" while describing the general shape of the data. + +Regardless, this fully annotates the log() function. + +Typing notes: + +TypeVar is a Type variable that can optionally be constrained by a +sequence of possible types. This variable is bound to a specific type +per-invocation, like a Generic. + +log() behaves as log() now, where the incoming type informs the +signature it expects for any filter arguments passed in. If Msg is a +str, then filter should take and return a str. + +Signed-off-by: John Snow +Reviewed-by: Max Reitz +Message-Id: <20200331000014.11581-9-jsnow@redhat.com> +Reviewed-by: Kevin Wolf +Signed-off-by: Max Reitz +--- + tests/qemu-iotests/iotests.py | 14 +++++++++++--- + 1 file changed, 11 insertions(+), 3 deletions(-) + +diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py +index 374a8f6077..69f24223d2 100644 +--- a/tests/qemu-iotests/iotests.py ++++ b/tests/qemu-iotests/iotests.py +@@ -28,6 +28,7 @@ import signal + import struct + import subprocess + import sys ++from typing import (Any, Callable, Dict, Iterable, List, Optional, TypeVar) + import unittest + + # pylint: disable=import-error, wrong-import-position +@@ -354,9 +355,16 @@ def filter_qmp_imgfmt(qmsg): + return value + return filter_qmp(qmsg, _filter) + +-def log(msg, filters=(), indent=None): +- '''Logs either a string message or a JSON serializable message (like QMP). +- If indent is provided, JSON serializable messages are pretty-printed.''' ++ ++Msg = TypeVar('Msg', Dict[str, Any], List[Any], str) ++ ++def log(msg: Msg, ++ filters: Iterable[Callable[[Msg], Msg]] = (), ++ indent: Optional[int] = None) -> None: ++ """ ++ Logs either a string message or a JSON serializable message (like QMP). ++ If indent is provided, JSON serializable messages are pretty-printed. ++ """ + for flt in filters: + msg = flt(msg) + if isinstance(msg, (dict, list)): +-- +2.23.0 + diff --git a/iotests-use-python-logging-for-iotests.log.patch b/iotests-use-python-logging-for-iotests.log.patch new file mode 100644 index 0000000000000000000000000000000000000000..6b7528ab7b29086a5956a952c496ae348faf1f99 --- /dev/null +++ b/iotests-use-python-logging-for-iotests.log.patch @@ -0,0 +1,254 @@ +From 52ea799e9631ff00c230f1fed50986246149d8f2 Mon Sep 17 00:00:00 2001 +From: John Snow +Date: Mon, 30 Mar 2020 20:00:14 -0400 +Subject: [PATCH 254/709] iotests: use python logging for iotests.log() + +We can turn logging on/off globally instead of per-function. + +Remove use_log from run_job, and use python logging to turn on +diffable output when we run through a script entry point. + +iotest 245 changes output order due to buffering reasons. + +An extended note on python logging: + +A NullHandler is added to `qemu.iotests` to stop output from being +generated if this code is used as a library without configuring logging. +A NullHandler is only needed at the root, so a duplicate handler is not +needed for `qemu.iotests.diff_io`. + +When logging is not configured, messages at the 'WARNING' levels or +above are printed with default settings. The NullHandler stops this from +occurring, which is considered good hygiene for code used as a library. + +See https://docs.python.org/3/howto/logging.html#library-config + +When logging is actually enabled (always at the behest of an explicit +call by a client script), a root logger is implicitly created at the +root, which allows messages to propagate upwards and be handled/emitted +from the root logger with default settings. + +When we want iotest logging, we attach a handler to the +qemu.iotests.diff_io logger and disable propagation to avoid possible +double-printing. + +For more information on python logging infrastructure, I highly +recommend downloading the pip package `logging_tree`, which provides +convenient visualizations of the hierarchical logging configuration +under different circumstances. + +See https://pypi.org/project/logging_tree/ for more information. + +Signed-off-by: John Snow +Reviewed-by: Max Reitz +Message-Id: <20200331000014.11581-15-jsnow@redhat.com> +Reviewed-by: Kevin Wolf +Signed-off-by: Max Reitz +--- + tests/qemu-iotests/030 | 4 +-- + tests/qemu-iotests/155 | 2 +- + tests/qemu-iotests/245 | 1 + + tests/qemu-iotests/245.out | 10 +++---- + tests/qemu-iotests/iotests.py | 53 ++++++++++++++++++++--------------- + 5 files changed, 39 insertions(+), 31 deletions(-) + +diff --git a/tests/qemu-iotests/030 b/tests/qemu-iotests/030 +index aa911d266a..104e3cee1b 100755 +--- a/tests/qemu-iotests/030 ++++ b/tests/qemu-iotests/030 +@@ -411,8 +411,8 @@ class TestParallelOps(iotests.QMPTestCase): + result = self.vm.qmp('block-job-set-speed', device='drive0', speed=0) + self.assert_qmp(result, 'return', {}) + +- self.vm.run_job(job='drive0', auto_dismiss=True, use_log=False) +- self.vm.run_job(job='node4', auto_dismiss=True, use_log=False) ++ self.vm.run_job(job='drive0', auto_dismiss=True) ++ self.vm.run_job(job='node4', auto_dismiss=True) + self.assert_no_active_block_jobs() + + # Test a block-stream and a block-commit job in parallel +diff --git a/tests/qemu-iotests/155 b/tests/qemu-iotests/155 +index 571bce9de4..cb371d4649 100755 +--- a/tests/qemu-iotests/155 ++++ b/tests/qemu-iotests/155 +@@ -188,7 +188,7 @@ class MirrorBaseClass(BaseClass): + + self.assert_qmp(result, 'return', {}) + +- self.vm.run_job('mirror-job', use_log=False, auto_finalize=False, ++ self.vm.run_job('mirror-job', auto_finalize=False, + pre_finalize=self.openBacking, auto_dismiss=True) + + def testFull(self): +diff --git a/tests/qemu-iotests/245 b/tests/qemu-iotests/245 +index 1001275a44..4f5f0bb901 100755 +--- a/tests/qemu-iotests/245 ++++ b/tests/qemu-iotests/245 +@@ -1027,5 +1027,6 @@ class TestBlockdevReopen(iotests.QMPTestCase): + self.run_test_iothreads(None, 'iothread0') + + if __name__ == '__main__': ++ iotests.activate_logging() + iotests.main(supported_fmts=["qcow2"], + supported_protocols=["file"]) +diff --git a/tests/qemu-iotests/245.out b/tests/qemu-iotests/245.out +index 682b93394d..4b33dcaf5c 100644 +--- a/tests/qemu-iotests/245.out ++++ b/tests/qemu-iotests/245.out +@@ -1,8 +1,3 @@ +-..................... +----------------------------------------------------------------------- +-Ran 21 tests +- +-OK + {"execute": "job-finalize", "arguments": {"id": "commit0"}} + {"return": {}} + {"data": {"id": "commit0", "type": "commit"}, "event": "BLOCK_JOB_PENDING", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} +@@ -15,3 +10,8 @@ OK + {"return": {}} + {"data": {"id": "stream0", "type": "stream"}, "event": "BLOCK_JOB_PENDING", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} + {"data": {"device": "stream0", "len": 3145728, "offset": 3145728, "speed": 0, "type": "stream"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++..................... ++---------------------------------------------------------------------- ++Ran 21 tests ++ ++OK +diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py +index 35d8cae997..6c0e781af7 100644 +--- a/tests/qemu-iotests/iotests.py ++++ b/tests/qemu-iotests/iotests.py +@@ -42,6 +42,14 @@ assert sys.version_info >= (3, 6) + QMPResponse = Dict[str, Any] + + ++# Use this logger for logging messages directly from the iotests module ++logger = logging.getLogger('qemu.iotests') ++logger.addHandler(logging.NullHandler()) ++ ++# Use this logger for messages that ought to be used for diff output. ++test_logger = logging.getLogger('qemu.iotests.diff_io') ++ ++ + faulthandler.enable() + + # This will not work if arguments contain spaces but is necessary if we +@@ -385,9 +393,9 @@ def log(msg: Msg, + if isinstance(msg, (dict, list)): + # Don't sort if it's already sorted + do_sort = not isinstance(msg, OrderedDict) +- print(json.dumps(msg, sort_keys=do_sort, indent=indent)) ++ test_logger.info(json.dumps(msg, sort_keys=do_sort, indent=indent)) + else: +- print(msg) ++ test_logger.info(msg) + + class Timeout: + def __init__(self, seconds, errmsg="Timeout"): +@@ -609,7 +617,7 @@ class VM(qtest.QEMUQtestMachine): + + # Returns None on success, and an error string on failure + def run_job(self, job, auto_finalize=True, auto_dismiss=False, +- pre_finalize=None, cancel=False, use_log=True, wait=60.0): ++ pre_finalize=None, cancel=False, wait=60.0): + """ + run_job moves a job from creation through to dismissal. + +@@ -622,7 +630,6 @@ class VM(qtest.QEMUQtestMachine): + invoked prior to issuing job-finalize, if any. + :param cancel: Bool. When true, cancels the job after the pre_finalize + callback. +- :param use_log: Bool. When false, does not log QMP messages. + :param wait: Float. Timeout value specifying how long to wait for any + event, in seconds. Defaults to 60.0. + """ +@@ -640,8 +647,7 @@ class VM(qtest.QEMUQtestMachine): + while True: + ev = filter_qmp_event(self.events_wait(events, timeout=wait)) + if ev['event'] != 'JOB_STATUS_CHANGE': +- if use_log: +- log(ev) ++ log(ev) + continue + status = ev['data']['status'] + if status == 'aborting': +@@ -649,29 +655,18 @@ class VM(qtest.QEMUQtestMachine): + for j in result['return']: + if j['id'] == job: + error = j['error'] +- if use_log: +- log('Job failed: %s' % (j['error'])) ++ log('Job failed: %s' % (j['error'])) + elif status == 'ready': +- if use_log: +- self.qmp_log('job-complete', id=job) +- else: +- self.qmp('job-complete', id=job) ++ self.qmp_log('job-complete', id=job) + elif status == 'pending' and not auto_finalize: + if pre_finalize: + pre_finalize() +- if cancel and use_log: ++ if cancel: + self.qmp_log('job-cancel', id=job) +- elif cancel: +- self.qmp('job-cancel', id=job) +- elif use_log: +- self.qmp_log('job-finalize', id=job) + else: +- self.qmp('job-finalize', id=job) ++ self.qmp_log('job-finalize', id=job) + elif status == 'concluded' and not auto_dismiss: +- if use_log: +- self.qmp_log('job-dismiss', id=job) +- else: +- self.qmp('job-dismiss', id=job) ++ self.qmp_log('job-dismiss', id=job) + elif status == 'null': + return error + +@@ -991,7 +986,7 @@ def notrun(reason): + seq = os.path.basename(sys.argv[0]) + + open('%s/%s.notrun' % (output_dir, seq), 'w').write(reason + '\n') +- print('%s not run: %s' % (seq, reason)) ++ logger.warning("%s not run: %s", seq, reason) + sys.exit(0) + + def case_notrun(reason): +@@ -1183,6 +1178,7 @@ def execute_setup_common(supported_fmts: Sequence[str] = (), + if debug: + sys.argv.remove('-d') + logging.basicConfig(level=(logging.DEBUG if debug else logging.WARN)) ++ logger.debug("iotests debugging messages active") + + return debug + +@@ -1195,14 +1191,25 @@ def execute_test(*args, test_function=None, **kwargs): + else: + test_function() + ++def activate_logging(): ++ """Activate iotests.log() output to stdout for script-style tests.""" ++ handler = logging.StreamHandler(stream=sys.stdout) ++ formatter = logging.Formatter('%(message)s') ++ handler.setFormatter(formatter) ++ test_logger.addHandler(handler) ++ test_logger.setLevel(logging.INFO) ++ test_logger.propagate = False ++ + # This is called from script-style iotests without a single point of entry + def script_initialize(*args, **kwargs): + """Initialize script-style tests without running any tests.""" ++ activate_logging() + execute_setup_common(*args, **kwargs) + + # This is called from script-style iotests with a single point of entry + def script_main(test_function, *args, **kwargs): + """Run script-style tests outside of the unittest framework""" ++ activate_logging() + execute_test(*args, test_function=test_function, **kwargs) + + # This is called from unittest style iotests +-- +2.23.0 + diff --git a/iotests-vmdk-Enable-zeroed_grained-on-by-default.patch b/iotests-vmdk-Enable-zeroed_grained-on-by-default.patch new file mode 100644 index 0000000000000000000000000000000000000000..daa7f8a20567707287013009d7dfc483a3772695 --- /dev/null +++ b/iotests-vmdk-Enable-zeroed_grained-on-by-default.patch @@ -0,0 +1,55 @@ +From c1eafd27b136b6717f8271e842372565d9b8c178 Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Thu, 30 Apr 2020 15:30:07 +0200 +Subject: [PATCH 342/709] iotests: vmdk: Enable zeroed_grained=on by default + +In order to avoid bitrot in the zero cluster code in VMDK, enable +zeroed_grain=on by default for the tests. + +059 now unsets the default options because zeroed_grain=on works only +with some subformats and the test case tests many different subformats, +including those for which it doesn't work. + +Signed-off-by: Kevin Wolf +Message-Id: <20200430133007.170335-7-kwolf@redhat.com> +Reviewed-by: Eric Blake +Signed-off-by: Kevin Wolf +--- + tests/qemu-iotests/059 | 6 +++--- + tests/qemu-iotests/check | 3 +++ + 2 files changed, 6 insertions(+), 3 deletions(-) + +diff --git a/tests/qemu-iotests/059 b/tests/qemu-iotests/059 +index 5438025285..4c90fc0363 100755 +--- a/tests/qemu-iotests/059 ++++ b/tests/qemu-iotests/059 +@@ -41,9 +41,9 @@ trap "_cleanup; exit \$status" 0 1 2 3 15 + _supported_fmt vmdk + _supported_proto file + _supported_os Linux +-_unsupported_imgopts "subformat=monolithicFlat" \ +- "subformat=twoGbMaxExtentFlat" \ +- "subformat=twoGbMaxExtentSparse" ++ ++# We test all kinds of VMDK options here, so ignore user-specified options ++IMGOPTS="" + + capacity_offset=16 + granularity_offset=20 +diff --git a/tests/qemu-iotests/check b/tests/qemu-iotests/check +index f7a2d3d6c3..9c461cf76d 100755 +--- a/tests/qemu-iotests/check ++++ b/tests/qemu-iotests/check +@@ -546,6 +546,9 @@ fi + if [ "$IMGFMT" == "luks" ] && ! (echo "$IMGOPTS" | grep "iter-time=" > /dev/null); then + IMGOPTS=$(_optstr_add "$IMGOPTS" "iter-time=10") + fi ++if [ "$IMGFMT" == "vmdk" ] && ! (echo "$IMGOPTS" | grep "zeroed_grain=" > /dev/null); then ++ IMGOPTS=$(_optstr_add "$IMGOPTS" "zeroed_grain=on") ++fi + + if [ -z "$SAMPLE_IMG_DIR" ]; then + SAMPLE_IMG_DIR="$source_iotests/sample_images" +-- +2.23.0 + diff --git a/kbd-state-fix-autorepeat-handling.patch b/kbd-state-fix-autorepeat-handling.patch deleted file mode 100644 index aa1bef302866dd7202eca95b74e0a3b61820f020..0000000000000000000000000000000000000000 --- a/kbd-state-fix-autorepeat-handling.patch +++ /dev/null @@ -1,40 +0,0 @@ -From 5fff13f245cddd3bc260dfe6ebe1b1f05b72116f Mon Sep 17 00:00:00 2001 -From: Gerd Hoffmann -Date: Tue, 14 May 2019 06:24:43 +0200 -Subject: [PATCH] kbd-state: fix autorepeat handling - -When allowing multiple down-events in a row (key autorepeat) we can't -use change_bit() any more to update the state, because autorepeat events -don't change the key state. We have to explicitly use set_bit() and -clear_bit() instead. - -Cc: qemu-stable@nongnu.org -Fixes: 35921860156e kbd-state: don't block auto-repeat events -Buglink: https://bugs.launchpad.net/qemu/+bug/1828272 -Signed-off-by: Gerd Hoffmann -Message-id: 20190514042443.10735-1-kraxel@redhat.com -(cherry-picked from commit 5fff13f245cddd3bc260dfe6ebe1b1f05b72116f) ---- - ui/kbd-state.c | 6 +++++- - 1 file changed, 5 insertions(+), 1 deletion(-) - -diff --git a/ui/kbd-state.c b/ui/kbd-state.c -index f3ab2d7a66..1668d17dda 100644 ---- a/ui/kbd-state.c -+++ b/ui/kbd-state.c -@@ -59,7 +59,11 @@ void qkbd_state_key_event(QKbdState *kbd, QKeyCode qcode, bool down) - } - - /* update key and modifier state */ -- change_bit(qcode, kbd->keys); -+ if (down) { -+ set_bit(qcode, kbd->keys); -+ } else { -+ clear_bit(qcode, kbd->keys); -+ } - switch (qcode) { - case Q_KEY_CODE_SHIFT: - case Q_KEY_CODE_SHIFT_R: --- -2.19.1 - diff --git a/libqos-Give-get_machine_allocator-internal-linkage.patch b/libqos-Give-get_machine_allocator-internal-linkage.patch new file mode 100644 index 0000000000000000000000000000000000000000..8a20a8034a579c6e0a41f81d5f98cdb3aeb24759 --- /dev/null +++ b/libqos-Give-get_machine_allocator-internal-linkage.patch @@ -0,0 +1,52 @@ +From f6528054f2ef7aab5c70664419b982b50142c25a Mon Sep 17 00:00:00 2001 +From: Markus Armbruster +Date: Fri, 24 Apr 2020 09:11:42 +0200 +Subject: [PATCH 034/709] libqos: Give get_machine_allocator() internal linkage +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Markus Armbruster +Message-Id: <20200424071142.3525-4-armbru@redhat.com> +Reviewed-by: Philippe Mathieu-Daudé +--- + tests/qtest/libqos/qos_external.c | 2 +- + tests/qtest/libqos/qos_external.h | 2 -- + 2 files changed, 1 insertion(+), 3 deletions(-) + +diff --git a/tests/qtest/libqos/qos_external.c b/tests/qtest/libqos/qos_external.c +index c707dac3b9..9f5180e18d 100644 +--- a/tests/qtest/libqos/qos_external.c ++++ b/tests/qtest/libqos/qos_external.c +@@ -66,7 +66,7 @@ void types_apply_to_node(ObjectTypeInfoList *type_info) + } + } + +-QGuestAllocator *get_machine_allocator(QOSGraphObject *obj) ++static QGuestAllocator *get_machine_allocator(QOSGraphObject *obj) + { + return obj->get_driver(obj, "memory"); + } +diff --git a/tests/qtest/libqos/qos_external.h b/tests/qtest/libqos/qos_external.h +index f63388cb30..72d7f91707 100644 +--- a/tests/qtest/libqos/qos_external.h ++++ b/tests/qtest/libqos/qos_external.h +@@ -18,7 +18,6 @@ + + #ifndef QOS_EXTERNAL_H + #define QOS_EXTERNAL_H +-#include "libqos/qgraph.h" + + #include "libqos/malloc.h" + #include "qapi/qapi-types-machine.h" +@@ -26,7 +25,6 @@ + + void machines_apply_to_node(MachineInfoList *mach_info); + void types_apply_to_node(ObjectTypeInfoList *type_info); +-QGuestAllocator *get_machine_allocator(QOSGraphObject *obj); + void *allocate_objects(QTestState *qts, char **path, QGuestAllocator **p_alloc); + + #endif +-- +2.23.0 + diff --git a/linux-header-Update-linux-kvm.h.patch b/linux-header-Update-linux-kvm.h.patch new file mode 100644 index 0000000000000000000000000000000000000000..fce546db62691547c2982f610ee13cd24dd1b5d1 --- /dev/null +++ b/linux-header-Update-linux-kvm.h.patch @@ -0,0 +1,43 @@ +From eddbf7e249875f60db7c22abebcaa67d8a24f20d Mon Sep 17 00:00:00 2001 +From: Yifei Jiang +Date: Mon, 24 Aug 2020 20:09:16 +0800 +Subject: [PATCH 695/709] linux-header: Update linux/kvm.h + +Update linux/kvm.h on https://gitee.com/openeuler/kernel/tree/kernel-5.5/ +Only use this header file, so do not update all linux headers. + +Signed-off-by: Yifei Jiang +Signed-off-by: Yipeng Yin +--- + linux-headers/linux/kvm.h | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h +index 9804495a46..ff6fb2ff53 100644 +--- a/linux-headers/linux/kvm.h ++++ b/linux-headers/linux/kvm.h +@@ -236,6 +236,7 @@ struct kvm_hyperv_exit { + #define KVM_EXIT_IOAPIC_EOI 26 + #define KVM_EXIT_HYPERV 27 + #define KVM_EXIT_ARM_NISV 28 ++#define KVM_EXIT_RISCV_SBI 28 + + /* For KVM_EXIT_INTERNAL_ERROR */ + /* Emulate instruction failed. */ +@@ -400,6 +401,13 @@ struct kvm_run { + __u64 esr_iss; + __u64 fault_ipa; + } arm_nisv; ++ /* KVM_EXIT_RISCV_SBI */ ++ struct { ++ unsigned long extension_id; ++ unsigned long function_id; ++ unsigned long args[6]; ++ unsigned long ret[2]; ++ } riscv_sbi; + /* Fix the size of the union. */ + char padding[256]; + }; +-- +2.23.0 + diff --git a/linux-headers-update-against-KVM-ARM-Fix-256-vcpus.patch b/linux-headers-update-against-KVM-ARM-Fix-256-vcpus.patch deleted file mode 100644 index 3d4e4ad5bb7e833e97c2d51f9ab2cf5ae555e823..0000000000000000000000000000000000000000 --- a/linux-headers-update-against-KVM-ARM-Fix-256-vcpus.patch +++ /dev/null @@ -1,62 +0,0 @@ -From 896b9892d4df316b85836daa973e442c0c64cec6 Mon Sep 17 00:00:00 2001 -From: Zenghui Yu -Date: Fri, 3 Jan 2020 17:16:55 +0800 -Subject: [PATCH 1/3] linux headers: update against "KVM/ARM: Fix >256 vcpus" - -This is part of upstream commit f363d039e883 ("linux headers: update -against v5.4-rc1"), authored by Eric Auger . - -Signed-off-by: Zenghui Yu ---- - linux-headers/asm-arm/kvm.h | 4 +++- - linux-headers/asm-arm64/kvm.h | 4 +++- - linux-headers/linux/kvm.h | 1 + - 3 files changed, 7 insertions(+), 2 deletions(-) - -diff --git a/linux-headers/asm-arm/kvm.h b/linux-headers/asm-arm/kvm.h -index e1f8b745..137a2730 100644 ---- a/linux-headers/asm-arm/kvm.h -+++ b/linux-headers/asm-arm/kvm.h -@@ -254,8 +254,10 @@ struct kvm_vcpu_events { - #define KVM_DEV_ARM_ITS_CTRL_RESET 4 - - /* KVM_IRQ_LINE irq field index values */ -+#define KVM_ARM_IRQ_VCPU2_SHIFT 28 -+#define KVM_ARM_IRQ_VCPU2_MASK 0xf - #define KVM_ARM_IRQ_TYPE_SHIFT 24 --#define KVM_ARM_IRQ_TYPE_MASK 0xff -+#define KVM_ARM_IRQ_TYPE_MASK 0xf - #define KVM_ARM_IRQ_VCPU_SHIFT 16 - #define KVM_ARM_IRQ_VCPU_MASK 0xff - #define KVM_ARM_IRQ_NUM_SHIFT 0 -diff --git a/linux-headers/asm-arm64/kvm.h b/linux-headers/asm-arm64/kvm.h -index e6a98c14..dfd3a028 100644 ---- a/linux-headers/asm-arm64/kvm.h -+++ b/linux-headers/asm-arm64/kvm.h -@@ -265,8 +265,10 @@ struct kvm_vcpu_events { - #define KVM_ARM_VCPU_TIMER_IRQ_PTIMER 1 - - /* KVM_IRQ_LINE irq field index values */ -+#define KVM_ARM_IRQ_VCPU2_SHIFT 28 -+#define KVM_ARM_IRQ_VCPU2_MASK 0xf - #define KVM_ARM_IRQ_TYPE_SHIFT 24 --#define KVM_ARM_IRQ_TYPE_MASK 0xff -+#define KVM_ARM_IRQ_TYPE_MASK 0xf - #define KVM_ARM_IRQ_VCPU_SHIFT 16 - #define KVM_ARM_IRQ_VCPU_MASK 0xff - #define KVM_ARM_IRQ_NUM_SHIFT 0 -diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h -index b53ee597..086cea4d 100644 ---- a/linux-headers/linux/kvm.h -+++ b/linux-headers/linux/kvm.h -@@ -988,6 +988,7 @@ struct kvm_ppc_resize_hpt { - #define KVM_CAP_ARM_VM_IPA_SIZE 165 - #define KVM_CAP_MANUAL_DIRTY_LOG_PROTECT 166 - #define KVM_CAP_HYPERV_CPUID 167 -+#define KVM_CAP_ARM_IRQ_LINE_LAYOUT_2 174 - - #ifdef KVM_CAP_IRQ_ROUTING - --- -2.19.1 - diff --git a/linux-headers-update-against-Linux-5.7-rc3.patch b/linux-headers-update-against-Linux-5.7-rc3.patch new file mode 100644 index 0000000000000000000000000000000000000000..169513881bda5651d01d20a7802d05ea0bf2c420 --- /dev/null +++ b/linux-headers-update-against-Linux-5.7-rc3.patch @@ -0,0 +1,660 @@ +From dc6f8d458a4ccc360723993f31d310d06469f55f Mon Sep 17 00:00:00 2001 +From: Cornelia Huck +Date: Mon, 27 Apr 2020 12:24:14 +0200 +Subject: [PATCH 002/709] linux-headers: update against Linux 5.7-rc3 + +commit 6a8b55ed4056ea5559ebe4f6a4b247f627870d4c + +Reviewed-by: Michael S. Tsirkin # virtio/vhost parts +Signed-off-by: Cornelia Huck +Message-Id: <20200427102415.10915-3-cohuck@redhat.com> +--- + include/standard-headers/linux/ethtool.h | 10 +- + .../linux/input-event-codes.h | 5 +- + include/standard-headers/linux/pci_regs.h | 2 + + include/standard-headers/linux/vhost_types.h | 8 ++ + .../standard-headers/linux/virtio_balloon.h | 12 ++- + include/standard-headers/linux/virtio_ids.h | 1 + + include/standard-headers/linux/virtio_net.h | 102 +++++++++++++++++- + linux-headers/COPYING | 2 + + linux-headers/asm-x86/kvm.h | 1 + + linux-headers/asm-x86/unistd_32.h | 1 + + linux-headers/asm-x86/unistd_64.h | 1 + + linux-headers/asm-x86/unistd_x32.h | 1 + + linux-headers/linux/kvm.h | 47 +++++++- + linux-headers/linux/mman.h | 5 +- + linux-headers/linux/userfaultfd.h | 40 +++++-- + linux-headers/linux/vfio.h | 37 +++++++ + linux-headers/linux/vhost.h | 24 +++++ + 17 files changed, 280 insertions(+), 19 deletions(-) + +diff --git a/include/standard-headers/linux/ethtool.h b/include/standard-headers/linux/ethtool.h +index 8adf3b018b..1200890c86 100644 +--- a/include/standard-headers/linux/ethtool.h ++++ b/include/standard-headers/linux/ethtool.h +@@ -596,6 +596,9 @@ struct ethtool_pauseparam { + * @ETH_SS_LINK_MODES: link mode names + * @ETH_SS_MSG_CLASSES: debug message class names + * @ETH_SS_WOL_MODES: wake-on-lan modes ++ * @ETH_SS_SOF_TIMESTAMPING: SOF_TIMESTAMPING_* flags ++ * @ETH_SS_TS_TX_TYPES: timestamping Tx types ++ * @ETH_SS_TS_RX_FILTERS: timestamping Rx filters + */ + enum ethtool_stringset { + ETH_SS_TEST = 0, +@@ -610,6 +613,9 @@ enum ethtool_stringset { + ETH_SS_LINK_MODES, + ETH_SS_MSG_CLASSES, + ETH_SS_WOL_MODES, ++ ETH_SS_SOF_TIMESTAMPING, ++ ETH_SS_TS_TX_TYPES, ++ ETH_SS_TS_RX_FILTERS, + + /* add new constants above here */ + ETH_SS_COUNT +@@ -1330,6 +1336,7 @@ enum ethtool_fec_config_bits { + ETHTOOL_FEC_OFF_BIT, + ETHTOOL_FEC_RS_BIT, + ETHTOOL_FEC_BASER_BIT, ++ ETHTOOL_FEC_LLRS_BIT, + }; + + #define ETHTOOL_FEC_NONE (1 << ETHTOOL_FEC_NONE_BIT) +@@ -1337,6 +1344,7 @@ enum ethtool_fec_config_bits { + #define ETHTOOL_FEC_OFF (1 << ETHTOOL_FEC_OFF_BIT) + #define ETHTOOL_FEC_RS (1 << ETHTOOL_FEC_RS_BIT) + #define ETHTOOL_FEC_BASER (1 << ETHTOOL_FEC_BASER_BIT) ++#define ETHTOOL_FEC_LLRS (1 << ETHTOOL_FEC_LLRS_BIT) + + /* CMDs currently supported */ + #define ETHTOOL_GSET 0x00000001 /* DEPRECATED, Get settings. +@@ -1521,7 +1529,7 @@ enum ethtool_link_mode_bit_indices { + ETHTOOL_LINK_MODE_400000baseLR8_ER8_FR8_Full_BIT = 71, + ETHTOOL_LINK_MODE_400000baseDR8_Full_BIT = 72, + ETHTOOL_LINK_MODE_400000baseCR8_Full_BIT = 73, +- ++ ETHTOOL_LINK_MODE_FEC_LLRS_BIT = 74, + /* must be last entry */ + __ETHTOOL_LINK_MODE_MASK_NBITS + }; +diff --git a/include/standard-headers/linux/input-event-codes.h b/include/standard-headers/linux/input-event-codes.h +index b484c25289..ebf72c1031 100644 +--- a/include/standard-headers/linux/input-event-codes.h ++++ b/include/standard-headers/linux/input-event-codes.h +@@ -1,4 +1,4 @@ +-/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ ++/* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */ + /* + * Input event codes + * +@@ -652,6 +652,9 @@ + /* Electronic privacy screen control */ + #define KEY_PRIVACY_SCREEN_TOGGLE 0x279 + ++/* Select an area of screen to be copied */ ++#define KEY_SELECTIVE_SCREENSHOT 0x27a ++ + /* + * Some keyboards have keys which do not have a defined meaning, these keys + * are intended to be programmed / bound to macros by the user. For most +diff --git a/include/standard-headers/linux/pci_regs.h b/include/standard-headers/linux/pci_regs.h +index 5437690483..f9701410d3 100644 +--- a/include/standard-headers/linux/pci_regs.h ++++ b/include/standard-headers/linux/pci_regs.h +@@ -605,6 +605,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_IBPD_DISABLE 0x4000 /* In-band PD disable */ + #define PCI_EXP_SLTSTA 26 /* Slot Status */ + #define PCI_EXP_SLTSTA_ABP 0x0001 /* Attention Button Pressed */ + #define PCI_EXP_SLTSTA_PFD 0x0002 /* Power Fault Detected */ +@@ -680,6 +681,7 @@ + #define PCI_EXP_LNKSTA2 50 /* Link Status 2 */ + #define PCI_CAP_EXP_ENDPOINT_SIZEOF_V2 52 /* v2 endpoints with link end here */ + #define PCI_EXP_SLTCAP2 52 /* Slot Capabilities 2 */ ++#define PCI_EXP_SLTCAP2_IBPD 0x00000001 /* In-band PD Disable Supported */ + #define PCI_EXP_SLTCTL2 56 /* Slot Control 2 */ + #define PCI_EXP_SLTSTA2 58 /* Slot Status 2 */ + +diff --git a/include/standard-headers/linux/vhost_types.h b/include/standard-headers/linux/vhost_types.h +index 5351fe172d..a678d8fbaa 100644 +--- a/include/standard-headers/linux/vhost_types.h ++++ b/include/standard-headers/linux/vhost_types.h +@@ -119,6 +119,14 @@ struct vhost_scsi_target { + unsigned short reserved; + }; + ++/* VHOST_VDPA specific definitions */ ++ ++struct vhost_vdpa_config { ++ uint32_t off; ++ uint32_t len; ++ uint8_t buf[0]; ++}; ++ + /* Feature bits */ + /* Log all write descriptors. Can be changed while device is active. */ + #define VHOST_F_LOG_ALL 26 +diff --git a/include/standard-headers/linux/virtio_balloon.h b/include/standard-headers/linux/virtio_balloon.h +index 9375ca2a70..f343bfefd8 100644 +--- a/include/standard-headers/linux/virtio_balloon.h ++++ b/include/standard-headers/linux/virtio_balloon.h +@@ -36,6 +36,7 @@ + #define VIRTIO_BALLOON_F_DEFLATE_ON_OOM 2 /* Deflate balloon on OOM */ + #define VIRTIO_BALLOON_F_FREE_PAGE_HINT 3 /* VQ to report free pages */ + #define VIRTIO_BALLOON_F_PAGE_POISON 4 /* Guest is using page poisoning */ ++#define VIRTIO_BALLOON_F_REPORTING 5 /* Page reporting virtqueue */ + + /* Size of a PFN in the balloon interface. */ + #define VIRTIO_BALLOON_PFN_SHIFT 12 +@@ -47,8 +48,15 @@ struct virtio_balloon_config { + uint32_t num_pages; + /* Number of pages we've actually got in balloon. */ + uint32_t actual; +- /* Free page report command id, readonly by guest */ +- uint32_t free_page_report_cmd_id; ++ /* ++ * Free page hint command id, readonly by guest. ++ * Was previously named free_page_report_cmd_id so we ++ * need to carry that name for legacy support. ++ */ ++ union { ++ uint32_t free_page_hint_cmd_id; ++ uint32_t free_page_report_cmd_id; /* deprecated */ ++ }; + /* Stores PAGE_POISON if page poisoning is in use */ + uint32_t poison_val; + }; +diff --git a/include/standard-headers/linux/virtio_ids.h b/include/standard-headers/linux/virtio_ids.h +index 585e07b273..ecc27a1740 100644 +--- a/include/standard-headers/linux/virtio_ids.h ++++ b/include/standard-headers/linux/virtio_ids.h +@@ -46,5 +46,6 @@ + #define VIRTIO_ID_IOMMU 23 /* virtio IOMMU */ + #define VIRTIO_ID_FS 26 /* virtio filesystem */ + #define VIRTIO_ID_PMEM 27 /* virtio pmem */ ++#define VIRTIO_ID_MAC80211_HWSIM 29 /* virtio mac80211-hwsim */ + + #endif /* _LINUX_VIRTIO_IDS_H */ +diff --git a/include/standard-headers/linux/virtio_net.h b/include/standard-headers/linux/virtio_net.h +index 260c3681d7..a90f79e1b1 100644 +--- a/include/standard-headers/linux/virtio_net.h ++++ b/include/standard-headers/linux/virtio_net.h +@@ -57,6 +57,9 @@ + * Steering */ + #define VIRTIO_NET_F_CTRL_MAC_ADDR 23 /* Set MAC address */ + ++#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 */ + #define VIRTIO_NET_F_STANDBY 62 /* Act as standby for another device + * with the same MAC. + */ +@@ -69,6 +72,17 @@ + #define VIRTIO_NET_S_LINK_UP 1 /* Link is up */ + #define VIRTIO_NET_S_ANNOUNCE 2 /* Announcement is needed */ + ++/* supported/enabled hash types */ ++#define VIRTIO_NET_RSS_HASH_TYPE_IPv4 (1 << 0) ++#define VIRTIO_NET_RSS_HASH_TYPE_TCPv4 (1 << 1) ++#define VIRTIO_NET_RSS_HASH_TYPE_UDPv4 (1 << 2) ++#define VIRTIO_NET_RSS_HASH_TYPE_IPv6 (1 << 3) ++#define VIRTIO_NET_RSS_HASH_TYPE_TCPv6 (1 << 4) ++#define VIRTIO_NET_RSS_HASH_TYPE_UDPv6 (1 << 5) ++#define VIRTIO_NET_RSS_HASH_TYPE_IP_EX (1 << 6) ++#define VIRTIO_NET_RSS_HASH_TYPE_TCP_EX (1 << 7) ++#define VIRTIO_NET_RSS_HASH_TYPE_UDP_EX (1 << 8) ++ + struct virtio_net_config { + /* The config defining mac address (if VIRTIO_NET_F_MAC) */ + uint8_t mac[ETH_ALEN]; +@@ -92,6 +106,12 @@ struct virtio_net_config { + * Any other value stands for unknown. + */ + uint8_t duplex; ++ /* maximum size of RSS key */ ++ uint8_t rss_max_key_size; ++ /* maximum number of indirection table entries */ ++ uint16_t rss_max_indirection_table_length; ++ /* bitmask of supported VIRTIO_NET_RSS_HASH_ types */ ++ uint32_t supported_hash_types; + } QEMU_PACKED; + + /* +@@ -104,6 +124,7 @@ struct virtio_net_config { + struct virtio_net_hdr_v1 { + #define VIRTIO_NET_HDR_F_NEEDS_CSUM 1 /* Use csum_start, csum_offset */ + #define VIRTIO_NET_HDR_F_DATA_VALID 2 /* Csum is valid */ ++#define VIRTIO_NET_HDR_F_RSC_INFO 4 /* rsc info in csum_ fields */ + uint8_t flags; + #define VIRTIO_NET_HDR_GSO_NONE 0 /* Not a GSO frame */ + #define VIRTIO_NET_HDR_GSO_TCPV4 1 /* GSO frame, IPv4 TCP (TSO) */ +@@ -113,11 +134,46 @@ struct virtio_net_hdr_v1 { + uint8_t gso_type; + __virtio16 hdr_len; /* Ethernet + IP + tcp/udp hdrs */ + __virtio16 gso_size; /* Bytes to append to hdr_len per frame */ +- __virtio16 csum_start; /* Position to start checksumming from */ +- __virtio16 csum_offset; /* Offset after that to place checksum */ ++ union { ++ struct { ++ __virtio16 csum_start; ++ __virtio16 csum_offset; ++ }; ++ /* Checksum calculation */ ++ struct { ++ /* Position to start checksumming from */ ++ __virtio16 start; ++ /* Offset after that to place checksum */ ++ __virtio16 offset; ++ } csum; ++ /* Receive Segment Coalescing */ ++ struct { ++ /* Number of coalesced segments */ ++ uint16_t segments; ++ /* Number of duplicated acks */ ++ uint16_t dup_acks; ++ } rsc; ++ }; + __virtio16 num_buffers; /* Number of merged rx buffers */ + }; + ++struct virtio_net_hdr_v1_hash { ++ struct virtio_net_hdr_v1 hdr; ++ uint32_t hash_value; ++#define VIRTIO_NET_HASH_REPORT_NONE 0 ++#define VIRTIO_NET_HASH_REPORT_IPv4 1 ++#define VIRTIO_NET_HASH_REPORT_TCPv4 2 ++#define VIRTIO_NET_HASH_REPORT_UDPv4 3 ++#define VIRTIO_NET_HASH_REPORT_IPv6 4 ++#define VIRTIO_NET_HASH_REPORT_TCPv6 5 ++#define VIRTIO_NET_HASH_REPORT_UDPv6 6 ++#define VIRTIO_NET_HASH_REPORT_IPv6_EX 7 ++#define VIRTIO_NET_HASH_REPORT_TCPv6_EX 8 ++#define VIRTIO_NET_HASH_REPORT_UDPv6_EX 9 ++ uint16_t hash_report; ++ uint16_t padding; ++}; ++ + #ifndef VIRTIO_NET_NO_LEGACY + /* This header comes first in the scatter-gather list. + * For legacy virtio, if VIRTIO_F_ANY_LAYOUT is not negotiated, it must +@@ -228,7 +284,9 @@ struct virtio_net_ctrl_mac { + + /* + * Control Receive Flow Steering +- * ++ */ ++#define VIRTIO_NET_CTRL_MQ 4 ++/* + * The command VIRTIO_NET_CTRL_MQ_VQ_PAIRS_SET + * enables Receive Flow Steering, specifying the number of the transmit and + * receive queues that will be used. After the command is consumed and acked by +@@ -241,11 +299,47 @@ struct virtio_net_ctrl_mq { + __virtio16 virtqueue_pairs; + }; + +-#define VIRTIO_NET_CTRL_MQ 4 + #define VIRTIO_NET_CTRL_MQ_VQ_PAIRS_SET 0 + #define VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MIN 1 + #define VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MAX 0x8000 + ++/* ++ * The command VIRTIO_NET_CTRL_MQ_RSS_CONFIG has the same effect as ++ * VIRTIO_NET_CTRL_MQ_VQ_PAIRS_SET does and additionally configures ++ * the receive steering to use a hash calculated for incoming packet ++ * to decide on receive virtqueue to place the packet. The command ++ * also provides parameters to calculate a hash and receive virtqueue. ++ */ ++struct virtio_net_rss_config { ++ uint32_t hash_types; ++ uint16_t indirection_table_mask; ++ uint16_t unclassified_queue; ++ uint16_t indirection_table[1/* + indirection_table_mask */]; ++ uint16_t max_tx_vq; ++ uint8_t hash_key_length; ++ uint8_t hash_key_data[/* hash_key_length */]; ++}; ++ ++ #define VIRTIO_NET_CTRL_MQ_RSS_CONFIG 1 ++ ++/* ++ * The command VIRTIO_NET_CTRL_MQ_HASH_CONFIG requests the device ++ * to include in the virtio header of the packet the value of the ++ * calculated hash and the report type of hash. It also provides ++ * parameters for hash calculation. The command requires feature ++ * VIRTIO_NET_F_HASH_REPORT to be negotiated to extend the ++ * layout of virtio header as defined in virtio_net_hdr_v1_hash. ++ */ ++struct virtio_net_hash_config { ++ uint32_t hash_types; ++ /* for compatibility with virtio_net_rss_config */ ++ uint16_t reserved[4]; ++ uint8_t hash_key_length; ++ uint8_t hash_key_data[/* hash_key_length */]; ++}; ++ ++ #define VIRTIO_NET_CTRL_MQ_HASH_CONFIG 2 ++ + /* + * Control network offloads + * +diff --git a/linux-headers/COPYING b/linux-headers/COPYING +index da4cb28feb..a635a38ef9 100644 +--- a/linux-headers/COPYING ++++ b/linux-headers/COPYING +@@ -16,3 +16,5 @@ In addition, other licenses may also apply. Please see: + Documentation/process/license-rules.rst + + for more details. ++ ++All contributions to the Linux Kernel are subject to this COPYING file. +diff --git a/linux-headers/asm-x86/kvm.h b/linux-headers/asm-x86/kvm.h +index 503d3f42da..3f3f780c8c 100644 +--- a/linux-headers/asm-x86/kvm.h ++++ b/linux-headers/asm-x86/kvm.h +@@ -390,6 +390,7 @@ struct kvm_sync_regs { + #define KVM_STATE_NESTED_GUEST_MODE 0x00000001 + #define KVM_STATE_NESTED_RUN_PENDING 0x00000002 + #define KVM_STATE_NESTED_EVMCS 0x00000004 ++#define KVM_STATE_NESTED_MTF_PENDING 0x00000008 + + #define KVM_STATE_NESTED_SMM_GUEST_MODE 0x00000001 + #define KVM_STATE_NESTED_SMM_VMXON 0x00000002 +diff --git a/linux-headers/asm-x86/unistd_32.h b/linux-headers/asm-x86/unistd_32.h +index f6e06fcfbd..1e6c1a5867 100644 +--- a/linux-headers/asm-x86/unistd_32.h ++++ b/linux-headers/asm-x86/unistd_32.h +@@ -429,4 +429,5 @@ + #define __NR_openat2 437 + #define __NR_pidfd_getfd 438 + ++ + #endif /* _ASM_X86_UNISTD_32_H */ +diff --git a/linux-headers/asm-x86/unistd_64.h b/linux-headers/asm-x86/unistd_64.h +index 924f826d2d..6daf0aecb2 100644 +--- a/linux-headers/asm-x86/unistd_64.h ++++ b/linux-headers/asm-x86/unistd_64.h +@@ -351,4 +351,5 @@ + #define __NR_openat2 437 + #define __NR_pidfd_getfd 438 + ++ + #endif /* _ASM_X86_UNISTD_64_H */ +diff --git a/linux-headers/asm-x86/unistd_x32.h b/linux-headers/asm-x86/unistd_x32.h +index 010307757b..e3f17ef370 100644 +--- a/linux-headers/asm-x86/unistd_x32.h ++++ b/linux-headers/asm-x86/unistd_x32.h +@@ -340,4 +340,5 @@ + #define __NR_preadv2 (__X32_SYSCALL_BIT + 546) + #define __NR_pwritev2 (__X32_SYSCALL_BIT + 547) + ++ + #endif /* _ASM_X86_UNISTD_X32_H */ +diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h +index 265099100e..9804495a46 100644 +--- a/linux-headers/linux/kvm.h ++++ b/linux-headers/linux/kvm.h +@@ -474,12 +474,17 @@ struct kvm_s390_mem_op { + __u32 size; /* amount of bytes */ + __u32 op; /* type of operation */ + __u64 buf; /* buffer in userspace */ +- __u8 ar; /* the access register number */ +- __u8 reserved[31]; /* should be set to 0 */ ++ union { ++ __u8 ar; /* the access register number */ ++ __u32 sida_offset; /* offset into the sida */ ++ __u8 reserved[32]; /* should be set to 0 */ ++ }; + }; + /* types for kvm_s390_mem_op->op */ + #define KVM_S390_MEMOP_LOGICAL_READ 0 + #define KVM_S390_MEMOP_LOGICAL_WRITE 1 ++#define KVM_S390_MEMOP_SIDA_READ 2 ++#define KVM_S390_MEMOP_SIDA_WRITE 3 + /* flags for kvm_s390_mem_op->flags */ + #define KVM_S390_MEMOP_F_CHECK_ONLY (1ULL << 0) + #define KVM_S390_MEMOP_F_INJECT_EXCEPTION (1ULL << 1) +@@ -1010,6 +1015,8 @@ struct kvm_ppc_resize_hpt { + #define KVM_CAP_ARM_NISV_TO_USER 177 + #define KVM_CAP_ARM_INJECT_EXT_DABT 178 + #define KVM_CAP_S390_VCPU_RESETS 179 ++#define KVM_CAP_S390_PROTECTED 180 ++#define KVM_CAP_PPC_SECURE_GUEST 181 + + #ifdef KVM_CAP_IRQ_ROUTING + +@@ -1478,6 +1485,39 @@ struct kvm_enc_region { + #define KVM_S390_NORMAL_RESET _IO(KVMIO, 0xc3) + #define KVM_S390_CLEAR_RESET _IO(KVMIO, 0xc4) + ++struct kvm_s390_pv_sec_parm { ++ __u64 origin; ++ __u64 length; ++}; ++ ++struct kvm_s390_pv_unp { ++ __u64 addr; ++ __u64 size; ++ __u64 tweak; ++}; ++ ++enum pv_cmd_id { ++ KVM_PV_ENABLE, ++ KVM_PV_DISABLE, ++ KVM_PV_SET_SEC_PARMS, ++ KVM_PV_UNPACK, ++ KVM_PV_VERIFY, ++ KVM_PV_PREP_RESET, ++ KVM_PV_UNSHARE_ALL, ++}; ++ ++struct kvm_pv_cmd { ++ __u32 cmd; /* Command to be executed */ ++ __u16 rc; /* Ultravisor return code */ ++ __u16 rrc; /* Ultravisor return reason code */ ++ __u64 data; /* Data or address */ ++ __u32 flags; /* flags for future extensions. Must be 0 for now */ ++ __u32 reserved[3]; ++}; ++ ++/* Available with KVM_CAP_S390_PROTECTED */ ++#define KVM_S390_PV_COMMAND _IOWR(KVMIO, 0xc5, struct kvm_pv_cmd) ++ + /* Secure Encrypted Virtualization command */ + enum sev_cmd_id { + /* Guest initialization commands */ +@@ -1628,4 +1668,7 @@ struct kvm_hyperv_eventfd { + #define KVM_HYPERV_CONN_ID_MASK 0x00ffffff + #define KVM_HYPERV_EVENTFD_DEASSIGN (1 << 0) + ++#define KVM_DIRTY_LOG_MANUAL_PROTECT_ENABLE (1 << 0) ++#define KVM_DIRTY_LOG_INITIALLY_SET (1 << 1) ++ + #endif /* __LINUX_KVM_H */ +diff --git a/linux-headers/linux/mman.h b/linux-headers/linux/mman.h +index 1f6e2cd89c..51ea363759 100644 +--- a/linux-headers/linux/mman.h ++++ b/linux-headers/linux/mman.h +@@ -5,8 +5,9 @@ + #include + #include + +-#define MREMAP_MAYMOVE 1 +-#define MREMAP_FIXED 2 ++#define MREMAP_MAYMOVE 1 ++#define MREMAP_FIXED 2 ++#define MREMAP_DONTUNMAP 4 + + #define OVERCOMMIT_GUESS 0 + #define OVERCOMMIT_ALWAYS 1 +diff --git a/linux-headers/linux/userfaultfd.h b/linux-headers/linux/userfaultfd.h +index ce78878d12..8d3996eb82 100644 +--- a/linux-headers/linux/userfaultfd.h ++++ b/linux-headers/linux/userfaultfd.h +@@ -19,7 +19,8 @@ + * means the userland is reading). + */ + #define UFFD_API ((__u64)0xAA) +-#define UFFD_API_FEATURES (UFFD_FEATURE_EVENT_FORK | \ ++#define UFFD_API_FEATURES (UFFD_FEATURE_PAGEFAULT_FLAG_WP | \ ++ UFFD_FEATURE_EVENT_FORK | \ + UFFD_FEATURE_EVENT_REMAP | \ + UFFD_FEATURE_EVENT_REMOVE | \ + UFFD_FEATURE_EVENT_UNMAP | \ +@@ -34,7 +35,8 @@ + #define UFFD_API_RANGE_IOCTLS \ + ((__u64)1 << _UFFDIO_WAKE | \ + (__u64)1 << _UFFDIO_COPY | \ +- (__u64)1 << _UFFDIO_ZEROPAGE) ++ (__u64)1 << _UFFDIO_ZEROPAGE | \ ++ (__u64)1 << _UFFDIO_WRITEPROTECT) + #define UFFD_API_RANGE_IOCTLS_BASIC \ + ((__u64)1 << _UFFDIO_WAKE | \ + (__u64)1 << _UFFDIO_COPY) +@@ -52,6 +54,7 @@ + #define _UFFDIO_WAKE (0x02) + #define _UFFDIO_COPY (0x03) + #define _UFFDIO_ZEROPAGE (0x04) ++#define _UFFDIO_WRITEPROTECT (0x06) + #define _UFFDIO_API (0x3F) + + /* userfaultfd ioctl ids */ +@@ -68,6 +71,8 @@ + struct uffdio_copy) + #define UFFDIO_ZEROPAGE _IOWR(UFFDIO, _UFFDIO_ZEROPAGE, \ + struct uffdio_zeropage) ++#define UFFDIO_WRITEPROTECT _IOWR(UFFDIO, _UFFDIO_WRITEPROTECT, \ ++ struct uffdio_writeprotect) + + /* read() structure */ + struct uffd_msg { +@@ -203,13 +208,14 @@ struct uffdio_copy { + __u64 dst; + __u64 src; + __u64 len; ++#define UFFDIO_COPY_MODE_DONTWAKE ((__u64)1<<0) + /* +- * There will be a wrprotection flag later that allows to map +- * pages wrprotected on the fly. And such a flag will be +- * available if the wrprotection ioctl are implemented for the +- * range according to the uffdio_register.ioctls. ++ * UFFDIO_COPY_MODE_WP will map the page write protected on ++ * the fly. UFFDIO_COPY_MODE_WP is available only if the ++ * write protected ioctl is implemented for the range ++ * according to the uffdio_register.ioctls. + */ +-#define UFFDIO_COPY_MODE_DONTWAKE ((__u64)1<<0) ++#define UFFDIO_COPY_MODE_WP ((__u64)1<<1) + __u64 mode; + + /* +@@ -231,4 +237,24 @@ struct uffdio_zeropage { + __s64 zeropage; + }; + ++struct uffdio_writeprotect { ++ struct uffdio_range range; ++/* ++ * UFFDIO_WRITEPROTECT_MODE_WP: set the flag to write protect a range, ++ * unset the flag to undo protection of a range which was previously ++ * write protected. ++ * ++ * UFFDIO_WRITEPROTECT_MODE_DONTWAKE: set the flag to avoid waking up ++ * any wait thread after the operation succeeds. ++ * ++ * NOTE: Write protecting a region (WP=1) is unrelated to page faults, ++ * therefore DONTWAKE flag is meaningless with WP=1. Removing write ++ * protection (WP=0) in response to a page fault wakes the faulting ++ * task unless DONTWAKE is set. ++ */ ++#define UFFDIO_WRITEPROTECT_MODE_WP ((__u64)1<<0) ++#define UFFDIO_WRITEPROTECT_MODE_DONTWAKE ((__u64)1<<1) ++ __u64 mode; ++}; ++ + #endif /* _LINUX_USERFAULTFD_H */ +diff --git a/linux-headers/linux/vfio.h b/linux-headers/linux/vfio.h +index fb10370d29..a41c452865 100644 +--- a/linux-headers/linux/vfio.h ++++ b/linux-headers/linux/vfio.h +@@ -707,6 +707,43 @@ struct vfio_device_ioeventfd { + + #define VFIO_DEVICE_IOEVENTFD _IO(VFIO_TYPE, VFIO_BASE + 16) + ++/** ++ * VFIO_DEVICE_FEATURE - _IORW(VFIO_TYPE, VFIO_BASE + 17, ++ * struct vfio_device_feature) ++ * ++ * Get, set, or probe feature data of the device. The feature is selected ++ * using the FEATURE_MASK portion of the flags field. Support for a feature ++ * can be probed by setting both the FEATURE_MASK and PROBE bits. A probe ++ * may optionally include the GET and/or SET bits to determine read vs write ++ * access of the feature respectively. Probing a feature will return success ++ * if the feature is supported and all of the optionally indicated GET/SET ++ * methods are supported. The format of the data portion of the structure is ++ * specific to the given feature. The data portion is not required for ++ * probing. GET and SET are mutually exclusive, except for use with PROBE. ++ * ++ * Return 0 on success, -errno on failure. ++ */ ++struct vfio_device_feature { ++ __u32 argsz; ++ __u32 flags; ++#define VFIO_DEVICE_FEATURE_MASK (0xffff) /* 16-bit feature index */ ++#define VFIO_DEVICE_FEATURE_GET (1 << 16) /* Get feature into data[] */ ++#define VFIO_DEVICE_FEATURE_SET (1 << 17) /* Set feature from data[] */ ++#define VFIO_DEVICE_FEATURE_PROBE (1 << 18) /* Probe feature support */ ++ __u8 data[]; ++}; ++ ++#define VFIO_DEVICE_FEATURE _IO(VFIO_TYPE, VFIO_BASE + 17) ++ ++/* ++ * Provide support for setting a PCI VF Token, which is used as a shared ++ * secret between PF and VF drivers. This feature may only be set on a ++ * PCI SR-IOV PF when SR-IOV is enabled on the PF and there are no existing ++ * open VFs. Data provided when setting this feature is a 16-byte array ++ * (__u8 b[16]), representing a UUID. ++ */ ++#define VFIO_DEVICE_FEATURE_PCI_VF_TOKEN (0) ++ + /* -------- API for Type1 VFIO IOMMU -------- */ + + /** +diff --git a/linux-headers/linux/vhost.h b/linux-headers/linux/vhost.h +index 40d028eed6..9fe72e4b13 100644 +--- a/linux-headers/linux/vhost.h ++++ b/linux-headers/linux/vhost.h +@@ -116,4 +116,28 @@ + #define VHOST_VSOCK_SET_GUEST_CID _IOW(VHOST_VIRTIO, 0x60, __u64) + #define VHOST_VSOCK_SET_RUNNING _IOW(VHOST_VIRTIO, 0x61, int) + ++/* VHOST_VDPA specific defines */ ++ ++/* Get the device id. The device ids follow the same definition of ++ * the device id defined in virtio-spec. ++ */ ++#define VHOST_VDPA_GET_DEVICE_ID _IOR(VHOST_VIRTIO, 0x70, __u32) ++/* Get and set the status. The status bits follow the same definition ++ * of the device status defined in virtio-spec. ++ */ ++#define VHOST_VDPA_GET_STATUS _IOR(VHOST_VIRTIO, 0x71, __u8) ++#define VHOST_VDPA_SET_STATUS _IOW(VHOST_VIRTIO, 0x72, __u8) ++/* Get and set the device config. The device config follows the same ++ * definition of the device config defined in virtio-spec. ++ */ ++#define VHOST_VDPA_GET_CONFIG _IOR(VHOST_VIRTIO, 0x73, \ ++ struct vhost_vdpa_config) ++#define VHOST_VDPA_SET_CONFIG _IOW(VHOST_VIRTIO, 0x74, \ ++ struct vhost_vdpa_config) ++/* Enable/disable the ring. */ ++#define VHOST_VDPA_SET_VRING_ENABLE _IOW(VHOST_VIRTIO, 0x75, \ ++ struct vhost_vring_state) ++/* Get the max ring size. */ ++#define VHOST_VDPA_GET_VRING_NUM _IOR(VHOST_VIRTIO, 0x76, __u16) ++ + #endif +-- +2.23.0 + diff --git a/linux-user-arm-BKPT-should-cause-SIGTRAP-not-be-a-sy.patch b/linux-user-arm-BKPT-should-cause-SIGTRAP-not-be-a-sy.patch new file mode 100644 index 0000000000000000000000000000000000000000..ec483c657ccc387c8d9e3ab0b7ba12f444bf22b1 --- /dev/null +++ b/linux-user-arm-BKPT-should-cause-SIGTRAP-not-be-a-sy.patch @@ -0,0 +1,91 @@ +From 13a0c21e64bddf1a3659d30b2b6e95529f9047ed Mon Sep 17 00:00:00 2001 +From: Peter Maydell +Date: Mon, 20 Apr 2020 22:22:03 +0100 +Subject: [PATCH 612/709] linux-user/arm: BKPT should cause SIGTRAP, not be a + syscall +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +In linux-user/arm/cpu-loop.c we incorrectly treat EXCP_BKPT similarly +to EXCP_SWI, which means that if the guest executes a BKPT insn then +QEMU will perform a syscall for it (which syscall depends on what +value happens to be in r7...). The correct behaviour is that the +guest process should take a SIGTRAP. + +This code has been like this (more or less) since commit +06c949e62a098f in 2006 which added BKPT in the first place. This is +probably because at the time the same code path was used to handle +both Linux syscalls and semihosting calls, and (on M profile) BKPT +with a suitable magic number is used for semihosting calls. But +these days we've moved handling of semihosting out to an entirely +different codepath, so we can fix this bug by simply removing this +handling of EXCP_BKPT and instead making it deliver a SIGTRAP like +EXCP_DEBUG (as we do already on aarch64). + +Reported-by: +Reviewed-by: Edgar E. Iglesias +Reviewed-by: Philippe Mathieu-Daudé +Signed-off-by: Peter Maydell +Message-id: 20200420212206.12776-2-peter.maydell@linaro.org +Fixes: https://bugs.launchpad.net/qemu/+bug/1873898 +Signed-off-by: Peter Maydell +--- + linux-user/arm/cpu_loop.c | 30 ++++++++---------------------- + 1 file changed, 8 insertions(+), 22 deletions(-) + +diff --git a/linux-user/arm/cpu_loop.c b/linux-user/arm/cpu_loop.c +index cf618daa1c..82d0dd3c31 100644 +--- a/linux-user/arm/cpu_loop.c ++++ b/linux-user/arm/cpu_loop.c +@@ -295,32 +295,17 @@ void cpu_loop(CPUARMState *env) + } + break; + case EXCP_SWI: +- case EXCP_BKPT: + { + env->eabi = 1; + /* system call */ +- if (trapnr == EXCP_BKPT) { +- if (env->thumb) { +- /* FIXME - what to do if get_user() fails? */ +- get_user_code_u16(insn, env->regs[15], env); +- n = insn & 0xff; +- env->regs[15] += 2; +- } else { +- /* FIXME - what to do if get_user() fails? */ +- get_user_code_u32(insn, env->regs[15], env); +- n = (insn & 0xf) | ((insn >> 4) & 0xff0); +- env->regs[15] += 4; +- } ++ if (env->thumb) { ++ /* FIXME - what to do if get_user() fails? */ ++ get_user_code_u16(insn, env->regs[15] - 2, env); ++ n = insn & 0xff; + } else { +- if (env->thumb) { +- /* FIXME - what to do if get_user() fails? */ +- get_user_code_u16(insn, env->regs[15] - 2, env); +- n = insn & 0xff; +- } else { +- /* FIXME - what to do if get_user() fails? */ +- get_user_code_u32(insn, env->regs[15] - 4, env); +- n = insn & 0xffffff; +- } ++ /* FIXME - what to do if get_user() fails? */ ++ get_user_code_u32(insn, env->regs[15] - 4, env); ++ n = insn & 0xffffff; + } + + if (n == ARM_NR_cacheflush) { +@@ -396,6 +381,7 @@ void cpu_loop(CPUARMState *env) + } + break; + case EXCP_DEBUG: ++ case EXCP_BKPT: + excp_debug: + info.si_signo = TARGET_SIGTRAP; + info.si_errno = 0; +-- +2.23.0 + diff --git a/linux-user-arm-Fix-identification-of-syscall-numbers.patch b/linux-user-arm-Fix-identification-of-syscall-numbers.patch new file mode 100644 index 0000000000000000000000000000000000000000..8d9fa0df0c0fe754524a4652a4bb8b68517fbfb5 --- /dev/null +++ b/linux-user-arm-Fix-identification-of-syscall-numbers.patch @@ -0,0 +1,200 @@ +From 3986a1721e10aebe0dc2c17f262ebf067e7414df Mon Sep 17 00:00:00 2001 +From: Peter Maydell +Date: Mon, 20 Apr 2020 22:22:06 +0100 +Subject: [PATCH 615/709] linux-user/arm: Fix identification of syscall numbers + +Our code to identify syscall numbers has some issues: + * for Thumb mode, we never need the immediate value from the insn, + but we always read it anyway + * bad immediate values in the svc insn should cause a SIGILL, but we + were abort()ing instead (via "goto error") + +We can fix both these things by refactoring the code that identifies +the syscall number to more closely follow the kernel COMPAT_OABI code: + * for Thumb it is always r7 + * for Arm, if the immediate value is 0, then this is an EABI call + with the syscall number in r7 + * otherwise, we XOR the immediate value with 0x900000 + (ARM_SYSCALL_BASE for QEMU; __NR_OABI_SYSCALL_BASE in the kernel), + which converts valid syscall immediates into the desired value, + and puts all invalid immediates in the range 0x100000 or above + * then we can just let the existing "value too large, deliver + SIGILL" case handle invalid numbers, and drop the 'goto error' + +Signed-off-by: Peter Maydell +Reviewed-by: Edgar E. Iglesias +Message-id: 20200420212206.12776-5-peter.maydell@linaro.org +--- + linux-user/arm/cpu_loop.c | 143 ++++++++++++++++++++------------------ + 1 file changed, 77 insertions(+), 66 deletions(-) + +diff --git a/linux-user/arm/cpu_loop.c b/linux-user/arm/cpu_loop.c +index df8b7b3fa9..13629ee1f6 100644 +--- a/linux-user/arm/cpu_loop.c ++++ b/linux-user/arm/cpu_loop.c +@@ -299,85 +299,96 @@ void cpu_loop(CPUARMState *env) + env->eabi = 1; + /* system call */ + if (env->thumb) { +- /* FIXME - what to do if get_user() fails? */ +- get_user_code_u16(insn, env->regs[15] - 2, env); +- n = insn & 0xff; ++ /* Thumb is always EABI style with syscall number in r7 */ ++ n = env->regs[7]; + } else { ++ /* ++ * Equivalent of kernel CONFIG_OABI_COMPAT: read the ++ * Arm SVC insn to extract the immediate, which is the ++ * syscall number in OABI. ++ */ + /* FIXME - what to do if get_user() fails? */ + get_user_code_u32(insn, env->regs[15] - 4, env); + n = insn & 0xffffff; +- } +- +- if (n == 0 || n >= ARM_SYSCALL_BASE || env->thumb) { +- /* linux syscall */ +- if (env->thumb || n == 0) { ++ if (n == 0) { ++ /* zero immediate: EABI, syscall number in r7 */ + n = env->regs[7]; + } else { +- n -= ARM_SYSCALL_BASE; ++ /* ++ * This XOR matches the kernel code: an immediate ++ * in the valid range (0x900000 .. 0x9fffff) is ++ * converted into the correct EABI-style syscall ++ * number; invalid immediates end up as values ++ * > 0xfffff and are handled below as out-of-range. ++ */ ++ n ^= ARM_SYSCALL_BASE; + env->eabi = 0; + } +- if ( n > ARM_NR_BASE) { +- switch (n) { +- case ARM_NR_cacheflush: +- /* nop */ +- break; +- case ARM_NR_set_tls: +- cpu_set_tls(env, env->regs[0]); +- env->regs[0] = 0; +- break; +- case ARM_NR_breakpoint: +- env->regs[15] -= env->thumb ? 2 : 4; +- goto excp_debug; +- case ARM_NR_get_tls: +- env->regs[0] = cpu_get_tls(env); +- break; +- default: +- if (n < 0xf0800) { +- /* +- * Syscalls 0xf0000..0xf07ff (or 0x9f0000.. +- * 0x9f07ff in OABI numbering) are defined +- * to return -ENOSYS rather than raising +- * SIGILL. Note that we have already +- * removed the 0x900000 prefix. +- */ +- qemu_log_mask(LOG_UNIMP, +- "qemu: Unsupported ARM syscall: 0x%x\n", +- n); +- env->regs[0] = -TARGET_ENOSYS; ++ } ++ ++ if (n > ARM_NR_BASE) { ++ switch (n) { ++ case ARM_NR_cacheflush: ++ /* nop */ ++ break; ++ case ARM_NR_set_tls: ++ cpu_set_tls(env, env->regs[0]); ++ env->regs[0] = 0; ++ break; ++ case ARM_NR_breakpoint: ++ env->regs[15] -= env->thumb ? 2 : 4; ++ goto excp_debug; ++ case ARM_NR_get_tls: ++ env->regs[0] = cpu_get_tls(env); ++ break; ++ default: ++ if (n < 0xf0800) { ++ /* ++ * Syscalls 0xf0000..0xf07ff (or 0x9f0000.. ++ * 0x9f07ff in OABI numbering) are defined ++ * to return -ENOSYS rather than raising ++ * SIGILL. Note that we have already ++ * removed the 0x900000 prefix. ++ */ ++ qemu_log_mask(LOG_UNIMP, ++ "qemu: Unsupported ARM syscall: 0x%x\n", ++ n); ++ env->regs[0] = -TARGET_ENOSYS; ++ } else { ++ /* ++ * Otherwise SIGILL. This includes any SWI with ++ * immediate not originally 0x9fxxxx, because ++ * of the earlier XOR. ++ */ ++ info.si_signo = TARGET_SIGILL; ++ info.si_errno = 0; ++ info.si_code = TARGET_ILL_ILLTRP; ++ info._sifields._sigfault._addr = env->regs[15]; ++ if (env->thumb) { ++ info._sifields._sigfault._addr -= 2; + } else { +- /* Otherwise SIGILL */ +- info.si_signo = TARGET_SIGILL; +- info.si_errno = 0; +- info.si_code = TARGET_ILL_ILLTRP; +- info._sifields._sigfault._addr = env->regs[15]; +- if (env->thumb) { +- info._sifields._sigfault._addr -= 2; +- } else { +- info._sifields._sigfault._addr -= 4; +- } +- queue_signal(env, info.si_signo, +- QEMU_SI_FAULT, &info); ++ info._sifields._sigfault._addr -= 4; + } +- break; +- } +- } else { +- ret = do_syscall(env, +- n, +- env->regs[0], +- env->regs[1], +- env->regs[2], +- env->regs[3], +- env->regs[4], +- env->regs[5], +- 0, 0); +- if (ret == -TARGET_ERESTARTSYS) { +- env->regs[15] -= env->thumb ? 2 : 4; +- } else if (ret != -TARGET_QEMU_ESIGRETURN) { +- env->regs[0] = ret; ++ queue_signal(env, info.si_signo, ++ QEMU_SI_FAULT, &info); + } ++ break; + } + } else { +- goto error; ++ ret = do_syscall(env, ++ n, ++ env->regs[0], ++ env->regs[1], ++ env->regs[2], ++ env->regs[3], ++ env->regs[4], ++ env->regs[5], ++ 0, 0); ++ if (ret == -TARGET_ERESTARTSYS) { ++ env->regs[15] -= env->thumb ? 2 : 4; ++ } else if (ret != -TARGET_QEMU_ESIGRETURN) { ++ env->regs[0] = ret; ++ } + } + } + break; +-- +2.23.0 + diff --git a/linux-user-arm-Handle-invalid-arm-specific-syscalls-.patch b/linux-user-arm-Handle-invalid-arm-specific-syscalls-.patch new file mode 100644 index 0000000000000000000000000000000000000000..b7703cb6a9bc94560f4b05aa1da52b5ea6c516ab --- /dev/null +++ b/linux-user-arm-Handle-invalid-arm-specific-syscalls-.patch @@ -0,0 +1,71 @@ +From ab546bd23856866411ff1b2ffaedabdc360e69df Mon Sep 17 00:00:00 2001 +From: Peter Maydell +Date: Mon, 20 Apr 2020 22:22:05 +0100 +Subject: [PATCH 614/709] linux-user/arm: Handle invalid arm-specific syscalls + correctly +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The kernel has different handling for syscalls with invalid +numbers that are in the "arm-specific" range 0x9f0000 and up: + * 0x9f0000..0x9f07ff return -ENOSYS if not implemented + * other out of range syscalls cause a SIGILL +(see the kernel's arch/arm/kernel/traps.c:arm_syscall()) + +Implement this distinction. (Note that our code doesn't look +quite like the kernel's, because we have removed the +0x900000 prefix by this point, whereas the kernel retains +it in arm_syscall().) + +Signed-off-by: Peter Maydell +Reviewed-by: Philippe Mathieu-Daudé +Message-id: 20200420212206.12776-4-peter.maydell@linaro.org +--- + linux-user/arm/cpu_loop.c | 30 ++++++++++++++++++++++++++---- + 1 file changed, 26 insertions(+), 4 deletions(-) + +diff --git a/linux-user/arm/cpu_loop.c b/linux-user/arm/cpu_loop.c +index 025887d6b8..df8b7b3fa9 100644 +--- a/linux-user/arm/cpu_loop.c ++++ b/linux-user/arm/cpu_loop.c +@@ -332,10 +332,32 @@ void cpu_loop(CPUARMState *env) + env->regs[0] = cpu_get_tls(env); + break; + default: +- qemu_log_mask(LOG_UNIMP, +- "qemu: Unsupported ARM syscall: 0x%x\n", +- n); +- env->regs[0] = -TARGET_ENOSYS; ++ if (n < 0xf0800) { ++ /* ++ * Syscalls 0xf0000..0xf07ff (or 0x9f0000.. ++ * 0x9f07ff in OABI numbering) are defined ++ * to return -ENOSYS rather than raising ++ * SIGILL. Note that we have already ++ * removed the 0x900000 prefix. ++ */ ++ qemu_log_mask(LOG_UNIMP, ++ "qemu: Unsupported ARM syscall: 0x%x\n", ++ n); ++ env->regs[0] = -TARGET_ENOSYS; ++ } else { ++ /* Otherwise SIGILL */ ++ info.si_signo = TARGET_SIGILL; ++ info.si_errno = 0; ++ info.si_code = TARGET_ILL_ILLTRP; ++ info._sifields._sigfault._addr = env->regs[15]; ++ if (env->thumb) { ++ info._sifields._sigfault._addr -= 2; ++ } else { ++ info._sifields._sigfault._addr -= 4; ++ } ++ queue_signal(env, info.si_signo, ++ QEMU_SI_FAULT, &info); ++ } + break; + } + } else { +-- +2.23.0 + diff --git a/linux-user-arm-Remove-bogus-SVC-0xf0002-handling.patch b/linux-user-arm-Remove-bogus-SVC-0xf0002-handling.patch new file mode 100644 index 0000000000000000000000000000000000000000..1a8c0f89ccc2057ae5099b4421d59dce1ec0e3e4 --- /dev/null +++ b/linux-user-arm-Remove-bogus-SVC-0xf0002-handling.patch @@ -0,0 +1,52 @@ +From 62f141a426d27c15555714a2c2967045b43d9a4a Mon Sep 17 00:00:00 2001 +From: Peter Maydell +Date: Mon, 20 Apr 2020 22:22:04 +0100 +Subject: [PATCH 613/709] linux-user/arm: Remove bogus SVC 0xf0002 handling +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +We incorrectly treat SVC 0xf0002 as a cacheflush request (which is a +NOP for QEMU). This is the wrong syscall number, because in the +svc-immediate OABI syscall numbers are all offset by the +ARM_SYSCALL_BASE value and so the correct insn is SVC 0x9f0002. +(This is handled further down in the code with the other Arm-specific +syscalls like NR_breakpoint.) + +When this code was initially added in commit 6f1f31c069b20611 in +2004, ARM_NR_cacheflush was defined as (ARM_SYSCALL_BASE + 0xf0000 + 2) +so the value in the comparison took account of the extra 0x900000 +offset. In commit fbb4a2e371f2fa7 in 2008, the ARM_SYSCALL_BASE +was removed from the definition of ARM_NR_cacheflush and handling +for this group of syscalls was added below the point where we subtract +ARM_SYSCALL_BASE from the SVC immediate value. However that commit +forgot to remove the now-obsolete earlier handling code. + +Remove the spurious ARM_NR_cacheflush condition. + +Signed-off-by: Peter Maydell +Reviewed-by: Philippe Mathieu-Daudé +Reviewed-by: Edgar E. Iglesias +Message-id: 20200420212206.12776-3-peter.maydell@linaro.org +--- + linux-user/arm/cpu_loop.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +diff --git a/linux-user/arm/cpu_loop.c b/linux-user/arm/cpu_loop.c +index 82d0dd3c31..025887d6b8 100644 +--- a/linux-user/arm/cpu_loop.c ++++ b/linux-user/arm/cpu_loop.c +@@ -308,9 +308,7 @@ void cpu_loop(CPUARMState *env) + n = insn & 0xffffff; + } + +- if (n == ARM_NR_cacheflush) { +- /* nop */ +- } else if (n == 0 || n >= ARM_SYSCALL_BASE || env->thumb) { ++ if (n == 0 || n >= ARM_SYSCALL_BASE || env->thumb) { + /* linux syscall */ + if (env->thumb || n == 0) { + n = env->regs[7]; +-- +2.23.0 + diff --git a/linux-user-arm-Reset-CPSR_E-when-entering-a-signal-h.patch b/linux-user-arm-Reset-CPSR_E-when-entering-a-signal-h.patch new file mode 100644 index 0000000000000000000000000000000000000000..a88a004c1eb38f2c677f0cf26dfcdeebae00534f --- /dev/null +++ b/linux-user-arm-Reset-CPSR_E-when-entering-a-signal-h.patch @@ -0,0 +1,46 @@ +From 45e2813964b135a11e0fb6371d2c5f48d901929e Mon Sep 17 00:00:00 2001 +From: Amanieu d'Antras +Date: Mon, 11 May 2020 14:11:17 +0100 +Subject: [PATCH 634/709] linux-user/arm: Reset CPSR_E when entering a signal + handler + +This fixes signal handlers running with the wrong endianness if the +interrupted code used SETEND to dynamically switch endianness. + +Signed-off-by: Amanieu d'Antras +Reviewed-by: Peter Maydell +Message-id: 20200511131117.2486486-1-amanieu@gmail.com +Signed-off-by: Peter Maydell +--- + linux-user/arm/signal.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/linux-user/arm/signal.c b/linux-user/arm/signal.c +index 8020c80acb..698985a647 100644 +--- a/linux-user/arm/signal.c ++++ b/linux-user/arm/signal.c +@@ -244,6 +244,11 @@ setup_return(CPUARMState *env, struct target_sigaction *ka, + } else { + cpsr &= ~CPSR_T; + } ++ if (env->cp15.sctlr_el[1] & SCTLR_E0E) { ++ cpsr |= CPSR_E; ++ } else { ++ cpsr &= ~CPSR_E; ++ } + + if (ka->sa_flags & TARGET_SA_RESTORER) { + if (is_fdpic) { +@@ -287,7 +292,8 @@ setup_return(CPUARMState *env, struct target_sigaction *ka, + env->regs[13] = frame_addr; + env->regs[14] = retcode; + env->regs[15] = handler & (thumb ? ~1 : ~3); +- cpsr_write(env, cpsr, CPSR_IT | CPSR_T, CPSRWriteByInstr); ++ cpsr_write(env, cpsr, CPSR_IT | CPSR_T | CPSR_E, CPSRWriteByInstr); ++ arm_rebuild_hflags(env); + + return 0; + } +-- +2.23.0 + diff --git a/linux-user-arm-signal.c-Drop-TARGET_CONFIG_CPU_32.patch b/linux-user-arm-signal.c-Drop-TARGET_CONFIG_CPU_32.patch new file mode 100644 index 0000000000000000000000000000000000000000..4fbd8bbd973d12f5456489da40d3662e397c22d5 --- /dev/null +++ b/linux-user-arm-signal.c-Drop-TARGET_CONFIG_CPU_32.patch @@ -0,0 +1,62 @@ +From fafe7229272f39500c14845bc7ea60a8504a5a20 Mon Sep 17 00:00:00 2001 +From: Peter Maydell +Date: Mon, 18 May 2020 15:30:14 +0100 +Subject: [PATCH 635/709] linux-user/arm/signal.c: Drop TARGET_CONFIG_CPU_32 + +The Arm signal-handling code has some parts ifdeffed with a +TARGET_CONFIG_CPU_32, which is always defined. This is a leftover +from when this code's structure was based on the Linux kernel +signal handling code, where it was intended to support 26-bit +Arm CPUs. The kernel dropped its CONFIG_CPU_32 in kernel commit +4da8b8208eded0ba21e3 in 2009. + +QEMU has never had 26-bit CPU support and is unlikely to ever +add it; we certainly aren't going to support 26-bit Linux +binaries via linux-user mode. The ifdef is just unhelpful +noise, so remove it entirely. + +Signed-off-by: Peter Maydell +Reviewed-by: Richard Henderson +Message-id: 20200518143014.20689-1-peter.maydell@linaro.org +--- + linux-user/arm/signal.c | 6 ------ + 1 file changed, 6 deletions(-) + +diff --git a/linux-user/arm/signal.c b/linux-user/arm/signal.c +index 698985a647..f21d1535e4 100644 +--- a/linux-user/arm/signal.c ++++ b/linux-user/arm/signal.c +@@ -126,8 +126,6 @@ struct rt_sigframe_v2 + abi_ulong retcode[4]; + }; + +-#define TARGET_CONFIG_CPU_32 1 +- + /* + * For ARM syscalls, we encode the syscall number into the instruction. + */ +@@ -187,9 +185,7 @@ setup_sigcontext(struct target_sigcontext *sc, /*struct _fpstate *fpstate,*/ + __put_user(env->regs[13], &sc->arm_sp); + __put_user(env->regs[14], &sc->arm_lr); + __put_user(env->regs[15], &sc->arm_pc); +-#ifdef TARGET_CONFIG_CPU_32 + __put_user(cpsr_read(env), &sc->arm_cpsr); +-#endif + + __put_user(/* current->thread.trap_no */ 0, &sc->trap_no); + __put_user(/* current->thread.error_code */ 0, &sc->error_code); +@@ -549,11 +545,9 @@ restore_sigcontext(CPUARMState *env, struct target_sigcontext *sc) + __get_user(env->regs[13], &sc->arm_sp); + __get_user(env->regs[14], &sc->arm_lr); + __get_user(env->regs[15], &sc->arm_pc); +-#ifdef TARGET_CONFIG_CPU_32 + __get_user(cpsr, &sc->arm_cpsr); + cpsr_write(env, cpsr, CPSR_USER | CPSR_EXEC, CPSRWriteByInstr); + arm_rebuild_hflags(env); +-#endif + + err |= !valid_user_regs(env); + +-- +2.23.0 + diff --git a/linux-user-completely-re-write-init_guest_space.patch b/linux-user-completely-re-write-init_guest_space.patch new file mode 100644 index 0000000000000000000000000000000000000000..b147491831884572751a51d28b66708702cc280c --- /dev/null +++ b/linux-user-completely-re-write-init_guest_space.patch @@ -0,0 +1,720 @@ +From ee94743034bfb443cf246eda4971bdc15d8ee066 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Alex=20Benn=C3=A9e?= +Date: Wed, 13 May 2020 18:51:28 +0100 +Subject: [PATCH 492/709] linux-user: completely re-write init_guest_space +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +First we ensure all guest space initialisation logic comes through +probe_guest_base once we understand the nature of the binary we are +loading. The convoluted init_guest_space routine is removed and +replaced with a number of pgb_* helpers which are called depending on +what requirements we have when loading the binary. + +We first try to do what is requested by the host. Failing that we try +and satisfy the guest requested base address. If all those options +fail we fall back to finding a space in the memory map using our +recently written read_self_maps() helper. + +There are some additional complications we try and take into account +when looking for holes in the address space. We try not to go directly +after the system brk() space so there is space for a little growth. We +also don't want to have to use negative offsets which would result in +slightly less efficient code on x86 when it's unable to use the +segment offset register. + +Less mind-binding gotos and hopefully clearer logic throughout. + +Signed-off-by: Alex Bennée +Acked-by: Laurent Vivier + +Message-Id: <20200513175134.19619-5-alex.bennee@linaro.org> +--- + linux-user/elfload.c | 503 +++++++++++++++++++++--------------------- + linux-user/flatload.c | 6 + + linux-user/main.c | 23 +- + linux-user/qemu.h | 31 ++- + 4 files changed, 277 insertions(+), 286 deletions(-) + +diff --git a/linux-user/elfload.c b/linux-user/elfload.c +index 619c054cc4..01a9323a63 100644 +--- a/linux-user/elfload.c ++++ b/linux-user/elfload.c +@@ -11,6 +11,7 @@ + #include "qemu/queue.h" + #include "qemu/guest-random.h" + #include "qemu/units.h" ++#include "qemu/selfmap.h" + + #ifdef _ARCH_PPC64 + #undef ARCH_DLINFO +@@ -382,68 +383,30 @@ enum { + + /* The commpage only exists for 32 bit kernels */ + +-/* Return 1 if the proposed guest space is suitable for the guest. +- * Return 0 if the proposed guest space isn't suitable, but another +- * address space should be tried. +- * Return -1 if there is no way the proposed guest space can be +- * valid regardless of the base. +- * The guest code may leave a page mapped and populate it if the +- * address is suitable. +- */ +-static int init_guest_commpage(unsigned long guest_base, +- unsigned long guest_size) +-{ +- unsigned long real_start, test_page_addr; +- +- /* We need to check that we can force a fault on access to the +- * commpage at 0xffff0fxx +- */ +- test_page_addr = guest_base + (0xffff0f00 & qemu_host_page_mask); +- +- /* If the commpage lies within the already allocated guest space, +- * then there is no way we can allocate it. +- * +- * You may be thinking that that this check is redundant because +- * we already validated the guest size against MAX_RESERVED_VA; +- * but if qemu_host_page_mask is unusually large, then +- * test_page_addr may be lower. +- */ +- if (test_page_addr >= guest_base +- && test_page_addr < (guest_base + guest_size)) { +- return -1; +- } ++#define ARM_COMMPAGE (intptr_t)0xffff0f00u + +- /* Note it needs to be writeable to let us initialise it */ +- real_start = (unsigned long) +- mmap((void *)test_page_addr, qemu_host_page_size, +- PROT_READ | PROT_WRITE, +- MAP_ANONYMOUS | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); ++static bool init_guest_commpage(void) ++{ ++ void *want = g2h(ARM_COMMPAGE & -qemu_host_page_size); ++ void *addr = mmap(want, qemu_host_page_size, PROT_READ | PROT_WRITE, ++ MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); + +- /* If we can't map it then try another address */ +- if (real_start == -1ul) { +- return 0; ++ if (addr == MAP_FAILED) { ++ perror("Allocating guest commpage"); ++ exit(EXIT_FAILURE); + } +- +- if (real_start != test_page_addr) { +- /* OS didn't put the page where we asked - unmap and reject */ +- munmap((void *)real_start, qemu_host_page_size); +- return 0; ++ if (addr != want) { ++ return false; + } + +- /* Leave the page mapped +- * Populate it (mmap should have left it all 0'd) +- */ +- +- /* Kernel helper versions */ +- __put_user(5, (uint32_t *)g2h(0xffff0ffcul)); ++ /* Set kernel helper versions; rest of page is 0. */ ++ __put_user(5, (uint32_t *)g2h(0xffff0ffcu)); + +- /* Now it's populated make it RO */ +- if (mprotect((void *)test_page_addr, qemu_host_page_size, PROT_READ)) { ++ if (mprotect(addr, qemu_host_page_size, PROT_READ)) { + perror("Protecting guest commpage"); +- exit(-1); ++ exit(EXIT_FAILURE); + } +- +- return 1; /* All good */ ++ return true; + } + + #define ELF_HWCAP get_elf_hwcap() +@@ -2075,239 +2038,267 @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc, + return sp; + } + +-unsigned long init_guest_space(unsigned long host_start, +- unsigned long host_size, +- unsigned long guest_start, +- bool fixed) +-{ +- /* In order to use host shmat, we must be able to honor SHMLBA. */ +- unsigned long align = MAX(SHMLBA, qemu_host_page_size); +- unsigned long current_start, aligned_start; +- int flags; +- +- assert(host_start || host_size); +- +- /* If just a starting address is given, then just verify that +- * address. */ +- if (host_start && !host_size) { +-#if defined(TARGET_ARM) && !defined(TARGET_AARCH64) +- if (init_guest_commpage(host_start, host_size) != 1) { +- return (unsigned long)-1; +- } ++#ifndef ARM_COMMPAGE ++#define ARM_COMMPAGE 0 ++#define init_guest_commpage() true + #endif +- return host_start; +- } + +- /* Setup the initial flags and start address. */ +- current_start = host_start & -align; +- flags = MAP_ANONYMOUS | MAP_PRIVATE | MAP_NORESERVE; +- if (fixed) { +- flags |= MAP_FIXED; +- } ++static void pgb_fail_in_use(const char *image_name) ++{ ++ error_report("%s: requires virtual address space that is in use " ++ "(omit the -B option or choose a different value)", ++ image_name); ++ exit(EXIT_FAILURE); ++} + +- /* Otherwise, a non-zero size region of memory needs to be mapped +- * and validated. */ ++static void pgb_have_guest_base(const char *image_name, abi_ulong guest_loaddr, ++ abi_ulong guest_hiaddr, long align) ++{ ++ const int flags = MAP_ANONYMOUS | MAP_PRIVATE | MAP_NORESERVE; ++ void *addr, *test; + +-#if defined(TARGET_ARM) && !defined(TARGET_AARCH64) +- /* On 32-bit ARM, we need to map not just the usable memory, but +- * also the commpage. Try to find a suitable place by allocating +- * a big chunk for all of it. If host_start, then the naive +- * strategy probably does good enough. +- */ +- if (!host_start) { +- unsigned long guest_full_size, host_full_size, real_start; +- +- guest_full_size = +- (0xffff0f00 & qemu_host_page_mask) + qemu_host_page_size; +- host_full_size = guest_full_size - guest_start; +- real_start = (unsigned long) +- mmap(NULL, host_full_size, PROT_NONE, flags, -1, 0); +- if (real_start == (unsigned long)-1) { +- if (host_size < host_full_size - qemu_host_page_size) { +- /* We failed to map a continous segment, but we're +- * allowed to have a gap between the usable memory and +- * the commpage where other things can be mapped. +- * This sparseness gives us more flexibility to find +- * an address range. +- */ +- goto naive; +- } +- return (unsigned long)-1; ++ if (!QEMU_IS_ALIGNED(guest_base, align)) { ++ fprintf(stderr, "Requested guest base 0x%lx does not satisfy " ++ "host minimum alignment (0x%lx)\n", ++ guest_base, align); ++ exit(EXIT_FAILURE); ++ } ++ ++ /* Sanity check the guest binary. */ ++ if (reserved_va) { ++ if (guest_hiaddr > reserved_va) { ++ error_report("%s: requires more than reserved virtual " ++ "address space (0x%" PRIx64 " > 0x%lx)", ++ image_name, (uint64_t)guest_hiaddr, reserved_va); ++ exit(EXIT_FAILURE); + } +- munmap((void *)real_start, host_full_size); +- if (real_start & (align - 1)) { +- /* The same thing again, but with extra +- * so that we can shift around alignment. +- */ +- unsigned long real_size = host_full_size + qemu_host_page_size; +- real_start = (unsigned long) +- mmap(NULL, real_size, PROT_NONE, flags, -1, 0); +- if (real_start == (unsigned long)-1) { +- if (host_size < host_full_size - qemu_host_page_size) { +- goto naive; +- } +- return (unsigned long)-1; +- } +- munmap((void *)real_start, real_size); +- real_start = ROUND_UP(real_start, align); ++ } else { ++ if ((guest_hiaddr - guest_base) > ~(uintptr_t)0) { ++ error_report("%s: requires more virtual address space " ++ "than the host can provide (0x%" PRIx64 ")", ++ image_name, (uint64_t)guest_hiaddr - guest_base); ++ exit(EXIT_FAILURE); + } +- current_start = real_start; + } +- naive: +-#endif + +- while (1) { +- unsigned long real_start, real_size, aligned_size; +- aligned_size = real_size = host_size; ++ /* ++ * Expand the allocation to the entire reserved_va. ++ * Exclude the mmap_min_addr hole. ++ */ ++ if (reserved_va) { ++ guest_loaddr = (guest_base >= mmap_min_addr ? 0 ++ : mmap_min_addr - guest_base); ++ guest_hiaddr = reserved_va; ++ } + +- /* Do not use mmap_find_vma here because that is limited to the +- * guest address space. We are going to make the +- * guest address space fit whatever we're given. +- */ +- real_start = (unsigned long) +- mmap((void *)current_start, host_size, PROT_NONE, flags, -1, 0); +- if (real_start == (unsigned long)-1) { +- return (unsigned long)-1; +- } ++ /* Reserve the address space for the binary, or reserved_va. */ ++ test = g2h(guest_loaddr); ++ addr = mmap(test, guest_hiaddr - guest_loaddr, PROT_NONE, flags, -1, 0); ++ if (test != addr) { ++ pgb_fail_in_use(image_name); ++ } ++} + +- /* Check to see if the address is valid. */ +- if (host_start && real_start != current_start) { +- qemu_log_mask(CPU_LOG_PAGE, "invalid %lx && %lx != %lx\n", +- host_start, real_start, current_start); +- goto try_again; ++/* Return value for guest_base, or -1 if no hole found. */ ++static uintptr_t pgb_find_hole(uintptr_t guest_loaddr, uintptr_t guest_size, ++ long align) ++{ ++ GSList *maps, *iter; ++ uintptr_t this_start, this_end, next_start, brk; ++ intptr_t ret = -1; ++ ++ assert(QEMU_IS_ALIGNED(guest_loaddr, align)); ++ ++ maps = read_self_maps(); ++ ++ /* Read brk after we've read the maps, which will malloc. */ ++ brk = (uintptr_t)sbrk(0); ++ ++ /* The first hole is before the first map entry. */ ++ this_start = mmap_min_addr; ++ ++ for (iter = maps; iter; ++ this_start = next_start, iter = g_slist_next(iter)) { ++ uintptr_t align_start, hole_size; ++ ++ this_end = ((MapInfo *)iter->data)->start; ++ next_start = ((MapInfo *)iter->data)->end; ++ align_start = ROUND_UP(this_start, align); ++ ++ /* Skip holes that are too small. */ ++ if (align_start >= this_end) { ++ continue; ++ } ++ hole_size = this_end - align_start; ++ if (hole_size < guest_size) { ++ continue; + } + +- /* Ensure the address is properly aligned. */ +- if (real_start & (align - 1)) { +- /* Ideally, we adjust like +- * +- * pages: [ ][ ][ ][ ][ ] +- * old: [ real ] +- * [ aligned ] +- * new: [ real ] +- * [ aligned ] +- * +- * But if there is something else mapped right after it, +- * then obviously it won't have room to grow, and the +- * kernel will put the new larger real someplace else with +- * unknown alignment (if we made it to here, then +- * fixed=false). Which is why we grow real by a full page +- * size, instead of by part of one; so that even if we get +- * moved, we can still guarantee alignment. But this does +- * mean that there is a padding of < 1 page both before +- * and after the aligned range; the "after" could could +- * cause problems for ARM emulation where it could butt in +- * to where we need to put the commpage. +- */ +- munmap((void *)real_start, host_size); +- real_size = aligned_size + align; +- real_start = (unsigned long) +- mmap((void *)real_start, real_size, PROT_NONE, flags, -1, 0); +- if (real_start == (unsigned long)-1) { +- return (unsigned long)-1; ++ /* If this hole contains brk, give ourselves some room to grow. */ ++ if (this_start <= brk && brk < this_end) { ++ hole_size -= guest_size; ++ if (sizeof(uintptr_t) == 8 && hole_size >= 1 * GiB) { ++ align_start += 1 * GiB; ++ } else if (hole_size >= 16 * MiB) { ++ align_start += 16 * MiB; ++ } else { ++ align_start = (this_end - guest_size) & -align; ++ if (align_start < this_start) { ++ continue; ++ } + } +- aligned_start = ROUND_UP(real_start, align); +- } else { +- aligned_start = real_start; + } + +-#if defined(TARGET_ARM) && !defined(TARGET_AARCH64) +- /* On 32-bit ARM, we need to also be able to map the commpage. */ +- int valid = init_guest_commpage(aligned_start - guest_start, +- aligned_size + guest_start); +- if (valid == -1) { +- munmap((void *)real_start, real_size); +- return (unsigned long)-1; +- } else if (valid == 0) { +- goto try_again; ++ /* Record the lowest successful match. */ ++ if (ret < 0) { ++ ret = align_start - guest_loaddr; + } +-#endif +- +- /* If nothing has said `return -1` or `goto try_again` yet, +- * then the address we have is good. +- */ +- break; +- +- try_again: +- /* That address didn't work. Unmap and try a different one. +- * The address the host picked because is typically right at +- * the top of the host address space and leaves the guest with +- * no usable address space. Resort to a linear search. We +- * already compensated for mmap_min_addr, so this should not +- * happen often. Probably means we got unlucky and host +- * address space randomization put a shared library somewhere +- * inconvenient. +- * +- * This is probably a good strategy if host_start, but is +- * probably a bad strategy if not, which means we got here +- * because of trouble with ARM commpage setup. +- */ +- if (munmap((void *)real_start, real_size) != 0) { +- error_report("%s: failed to unmap %lx:%lx (%s)", __func__, +- real_start, real_size, strerror(errno)); +- abort(); ++ /* If this hole contains the identity map, select it. */ ++ if (align_start <= guest_loaddr && ++ guest_loaddr + guest_size <= this_end) { ++ ret = 0; + } +- current_start += align; +- if (host_start == current_start) { +- /* Theoretically possible if host doesn't have any suitably +- * aligned areas. Normally the first mmap will fail. +- */ +- return (unsigned long)-1; ++ /* If this hole ends above the identity map, stop looking. */ ++ if (this_end >= guest_loaddr) { ++ break; + } + } ++ free_self_maps(maps); + +- qemu_log_mask(CPU_LOG_PAGE, "Reserved 0x%lx bytes of guest address space\n", host_size); +- +- return aligned_start; ++ return ret; + } + +-static void probe_guest_base(const char *image_name, +- abi_ulong loaddr, abi_ulong hiaddr) ++static void pgb_static(const char *image_name, abi_ulong orig_loaddr, ++ abi_ulong orig_hiaddr, long align) + { +- /* Probe for a suitable guest base address, if the user has not set +- * it explicitly, and set guest_base appropriately. +- * In case of error we will print a suitable message and exit. +- */ +- const char *errmsg; +- if (!have_guest_base && !reserved_va) { +- unsigned long host_start, real_start, host_size; ++ uintptr_t loaddr = orig_loaddr; ++ uintptr_t hiaddr = orig_hiaddr; ++ uintptr_t addr; + +- /* Round addresses to page boundaries. */ +- loaddr &= qemu_host_page_mask; +- hiaddr = HOST_PAGE_ALIGN(hiaddr); ++ if (hiaddr != orig_hiaddr) { ++ error_report("%s: requires virtual address space that the " ++ "host cannot provide (0x%" PRIx64 ")", ++ image_name, (uint64_t)orig_hiaddr); ++ exit(EXIT_FAILURE); ++ } + +- if (loaddr < mmap_min_addr) { +- host_start = HOST_PAGE_ALIGN(mmap_min_addr); ++ loaddr &= -align; ++ if (ARM_COMMPAGE) { ++ /* ++ * Extend the allocation to include the commpage. ++ * For a 64-bit host, this is just 4GiB; for a 32-bit host, ++ * the address arithmetic will wrap around, but the difference ++ * will produce the correct allocation size. ++ */ ++ if (sizeof(uintptr_t) == 8 || loaddr >= 0x80000000u) { ++ hiaddr = (uintptr_t)4 << 30; + } else { +- host_start = loaddr; +- if (host_start != loaddr) { +- errmsg = "Address overflow loading ELF binary"; +- goto exit_errmsg; +- } ++ loaddr = ARM_COMMPAGE & -align; + } +- host_size = hiaddr - loaddr; ++ } + +- /* Setup the initial guest memory space with ranges gleaned from +- * the ELF image that is being loaded. ++ addr = pgb_find_hole(loaddr, hiaddr - loaddr, align); ++ if (addr == -1) { ++ /* ++ * If ARM_COMMPAGE, there *might* be a non-consecutive allocation ++ * that can satisfy both. But as the normal arm32 link base address ++ * is ~32k, and we extend down to include the commpage, making the ++ * overhead only ~96k, this is unlikely. + */ +- real_start = init_guest_space(host_start, host_size, loaddr, false); +- if (real_start == (unsigned long)-1) { +- errmsg = "Unable to find space for application"; +- goto exit_errmsg; +- } +- guest_base = real_start - loaddr; ++ error_report("%s: Unable to allocate %#zx bytes of " ++ "virtual address space", image_name, ++ (size_t)(hiaddr - loaddr)); ++ exit(EXIT_FAILURE); ++ } ++ ++ guest_base = addr; ++} ++ ++static void pgb_dynamic(const char *image_name, long align) ++{ ++ /* ++ * The executable is dynamic and does not require a fixed address. ++ * All we need is a commpage that satisfies align. ++ * If we do not need a commpage, leave guest_base == 0. ++ */ ++ if (ARM_COMMPAGE) { ++ uintptr_t addr, commpage; + +- qemu_log_mask(CPU_LOG_PAGE, "Relocating guest address space from 0x" +- TARGET_ABI_FMT_lx " to 0x%lx\n", +- loaddr, real_start); ++ /* 64-bit hosts should have used reserved_va. */ ++ assert(sizeof(uintptr_t) == 4); ++ ++ /* ++ * By putting the commpage at the first hole, that puts guest_base ++ * just above that, and maximises the positive guest addresses. ++ */ ++ commpage = ARM_COMMPAGE & -align; ++ addr = pgb_find_hole(commpage, -commpage, align); ++ assert(addr != -1); ++ guest_base = addr; + } +- return; ++} + +-exit_errmsg: +- fprintf(stderr, "%s: %s\n", image_name, errmsg); +- exit(-1); ++static void pgb_reserved_va(const char *image_name, abi_ulong guest_loaddr, ++ abi_ulong guest_hiaddr, long align) ++{ ++ const int flags = MAP_ANONYMOUS | MAP_PRIVATE | MAP_NORESERVE; ++ void *addr, *test; ++ ++ if (guest_hiaddr > reserved_va) { ++ error_report("%s: requires more than reserved virtual " ++ "address space (0x%" PRIx64 " > 0x%lx)", ++ image_name, (uint64_t)guest_hiaddr, reserved_va); ++ exit(EXIT_FAILURE); ++ } ++ ++ /* Widen the "image" to the entire reserved address space. */ ++ pgb_static(image_name, 0, reserved_va, align); ++ ++ /* Reserve the memory on the host. */ ++ assert(guest_base != 0); ++ test = g2h(0); ++ addr = mmap(test, reserved_va, PROT_NONE, flags, -1, 0); ++ if (addr == MAP_FAILED) { ++ error_report("Unable to reserve 0x%lx bytes of virtual address " ++ "space for use as guest address space (check your " ++ "virtual memory ulimit setting or reserve less " ++ "using -R option)", reserved_va); ++ exit(EXIT_FAILURE); ++ } ++ assert(addr == test); + } + ++void probe_guest_base(const char *image_name, abi_ulong guest_loaddr, ++ abi_ulong guest_hiaddr) ++{ ++ /* In order to use host shmat, we must be able to honor SHMLBA. */ ++ uintptr_t align = MAX(SHMLBA, qemu_host_page_size); ++ ++ if (have_guest_base) { ++ pgb_have_guest_base(image_name, guest_loaddr, guest_hiaddr, align); ++ } else if (reserved_va) { ++ pgb_reserved_va(image_name, guest_loaddr, guest_hiaddr, align); ++ } else if (guest_loaddr) { ++ pgb_static(image_name, guest_loaddr, guest_hiaddr, align); ++ } else { ++ pgb_dynamic(image_name, align); ++ } ++ ++ /* Reserve and initialize the commpage. */ ++ if (!init_guest_commpage()) { ++ /* ++ * With have_guest_base, the user has selected the address and ++ * we are trying to work with that. Otherwise, we have selected ++ * free space and init_guest_commpage must succeeded. ++ */ ++ assert(have_guest_base); ++ pgb_fail_in_use(image_name); ++ } ++ ++ assert(QEMU_IS_ALIGNED(guest_base, align)); ++ qemu_log_mask(CPU_LOG_PAGE, "Locating guest address space " ++ "@ 0x%" PRIx64 "\n", (uint64_t)guest_base); ++} + + /* Load an ELF image into the address space. + +@@ -2399,6 +2390,12 @@ static void load_elf_image(const char *image_name, int image_fd, + * MMAP_MIN_ADDR or the QEMU application itself. + */ + probe_guest_base(image_name, loaddr, hiaddr); ++ } else { ++ /* ++ * The binary is dynamic, but we still need to ++ * select guest_base. In this case we pass a size. ++ */ ++ probe_guest_base(image_name, 0, hiaddr - loaddr); + } + } + +diff --git a/linux-user/flatload.c b/linux-user/flatload.c +index 66901f39cc..8fb448f0bf 100644 +--- a/linux-user/flatload.c ++++ b/linux-user/flatload.c +@@ -441,6 +441,12 @@ static int load_flat_file(struct linux_binprm * bprm, + indx_len = MAX_SHARED_LIBS * sizeof(abi_ulong); + indx_len = (indx_len + 15) & ~(abi_ulong)15; + ++ /* ++ * Alloate the address space. ++ */ ++ probe_guest_base(bprm->filename, 0, ++ text_len + data_len + extra + indx_len); ++ + /* + * there are a couple of cases here, the separate code/data + * case, and then the fully copied to RAM case which lumps +diff --git a/linux-user/main.c b/linux-user/main.c +index 2cd443237d..e18c1fb952 100644 +--- a/linux-user/main.c ++++ b/linux-user/main.c +@@ -24,6 +24,7 @@ + #include "qemu-version.h" + #include + #include ++#include + + #include "qapi/error.h" + #include "qemu.h" +@@ -747,28 +748,6 @@ int main(int argc, char **argv, char **envp) + target_environ = envlist_to_environ(envlist, NULL); + envlist_free(envlist); + +- /* +- * Now that page sizes are configured in tcg_exec_init() we can do +- * proper page alignment for guest_base. +- */ +- guest_base = HOST_PAGE_ALIGN(guest_base); +- +- if (reserved_va || have_guest_base) { +- guest_base = init_guest_space(guest_base, reserved_va, 0, +- have_guest_base); +- if (guest_base == (unsigned long)-1) { +- fprintf(stderr, "Unable to reserve 0x%lx bytes of virtual address " +- "space for use as guest address space (check your virtual " +- "memory ulimit setting or reserve less using -R option)\n", +- reserved_va); +- exit(EXIT_FAILURE); +- } +- +- if (reserved_va) { +- mmap_next_start = reserved_va; +- } +- } +- + /* + * Read in mmap_min_addr kernel parameter. This value is used + * When loading the ELF image to determine whether guest_base +diff --git a/linux-user/qemu.h b/linux-user/qemu.h +index 792c74290f..ce902f5132 100644 +--- a/linux-user/qemu.h ++++ b/linux-user/qemu.h +@@ -219,18 +219,27 @@ void init_qemu_uname_release(void); + void fork_start(void); + void fork_end(int child); + +-/* Creates the initial guest address space in the host memory space using +- * the given host start address hint and size. The guest_start parameter +- * specifies the start address of the guest space. guest_base will be the +- * difference between the host start address computed by this function and +- * guest_start. If fixed is specified, then the mapped address space must +- * start at host_start. The real start address of the mapped memory space is +- * returned or -1 if there was an error. ++/** ++ * probe_guest_base: ++ * @image_name: the executable being loaded ++ * @loaddr: the lowest fixed address in the executable ++ * @hiaddr: the highest fixed address in the executable ++ * ++ * Creates the initial guest address space in the host memory space. ++ * ++ * If @loaddr == 0, then no address in the executable is fixed, ++ * i.e. it is fully relocatable. In that case @hiaddr is the size ++ * of the executable. ++ * ++ * This function will not return if a valid value for guest_base ++ * cannot be chosen. On return, the executable loader can expect ++ * ++ * target_mmap(loaddr, hiaddr - loaddr, ...) ++ * ++ * to succeed. + */ +-unsigned long init_guest_space(unsigned long host_start, +- unsigned long host_size, +- unsigned long guest_start, +- bool fixed); ++void probe_guest_base(const char *image_name, ++ abi_ulong loaddr, abi_ulong hiaddr); + + #include "qemu/log.h" + +-- +2.23.0 + diff --git a/linux-user-riscv-fix-up-struct-target_ucontext-defin.patch b/linux-user-riscv-fix-up-struct-target_ucontext-defin.patch new file mode 100644 index 0000000000000000000000000000000000000000..1bdaf912b6fcc63cdb4714a2647fcecfa6bf9041 --- /dev/null +++ b/linux-user-riscv-fix-up-struct-target_ucontext-defin.patch @@ -0,0 +1,36 @@ +From 64ce00a6c7c00c0b120270e1644009e5d521e277 Mon Sep 17 00:00:00 2001 +From: LIU Zhiwei +Date: Sun, 12 Apr 2020 10:08:30 +0800 +Subject: [PATCH 063/709] linux-user/riscv: fix up struct target_ucontext + definition + +As struct target_ucontext will be transfered to signal handler, it +must keep pace with struct ucontext_t defined in Linux kernel. + +Signed-off-by: LIU Zhiwei +Reviewed-by: Alistair Francis +Message-id: 20200412020830.607-1-zhiwei_liu@c-sky.com +Message-Id: <20200412020830.607-1-zhiwei_liu@c-sky.com> +Signed-off-by: Alistair Francis +--- + linux-user/riscv/signal.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/linux-user/riscv/signal.c b/linux-user/riscv/signal.c +index 83ecc6f799..67a95dbc7b 100644 +--- a/linux-user/riscv/signal.c ++++ b/linux-user/riscv/signal.c +@@ -40,8 +40,9 @@ struct target_ucontext { + unsigned long uc_flags; + struct target_ucontext *uc_link; + target_stack_t uc_stack; +- struct target_sigcontext uc_mcontext; + target_sigset_t uc_sigmask; ++ uint8_t __unused[1024 / 8 - sizeof(target_sigset_t)]; ++ struct target_sigcontext uc_mcontext QEMU_ALIGNED(16); + }; + + struct target_rt_sigframe { +-- +2.23.0 + diff --git a/lockable-Replace-locks-with-lock-guard-macros.patch b/lockable-Replace-locks-with-lock-guard-macros.patch new file mode 100644 index 0000000000000000000000000000000000000000..8ae66e22628230c95abdc15dd03c783ba1aa516d --- /dev/null +++ b/lockable-Replace-locks-with-lock-guard-macros.patch @@ -0,0 +1,177 @@ +From 08b689aa6b521964b8275dd7a2564aefa5d68129 Mon Sep 17 00:00:00 2001 +From: Simran Singhal +Date: Thu, 2 Apr 2020 12:20:35 +0530 +Subject: [PATCH 236/709] lockable: Replace locks with lock guard macros + +Replace manual lock()/unlock() calls with lock guard macros +(QEMU_LOCK_GUARD/WITH_QEMU_LOCK_GUARD). + +Signed-off-by: Simran Singhal +Reviewed-by: Yuval Shaia +Reviewed-by: Marcel Apfelbaum +Tested-by: Yuval Shaia +Message-id: 20200402065035.GA15477@simran-Inspiron-5558 +Signed-off-by: Stefan Hajnoczi +--- + hw/hyperv/hyperv.c | 15 ++++++------- + hw/rdma/rdma_backend.c | 50 +++++++++++++++++++++--------------------- + hw/rdma/rdma_rm.c | 3 +-- + 3 files changed, 33 insertions(+), 35 deletions(-) + +diff --git a/hw/hyperv/hyperv.c b/hw/hyperv/hyperv.c +index 8ca3706f5b..4ddafe1de1 100644 +--- a/hw/hyperv/hyperv.c ++++ b/hw/hyperv/hyperv.c +@@ -15,6 +15,7 @@ + #include "sysemu/kvm.h" + #include "qemu/bitops.h" + #include "qemu/error-report.h" ++#include "qemu/lockable.h" + #include "qemu/queue.h" + #include "qemu/rcu.h" + #include "qemu/rcu_queue.h" +@@ -491,7 +492,7 @@ int hyperv_set_msg_handler(uint32_t conn_id, HvMsgHandler handler, void *data) + int ret; + MsgHandler *mh; + +- qemu_mutex_lock(&handlers_mutex); ++ QEMU_LOCK_GUARD(&handlers_mutex); + QLIST_FOREACH(mh, &msg_handlers, link) { + if (mh->conn_id == conn_id) { + if (handler) { +@@ -501,7 +502,7 @@ int hyperv_set_msg_handler(uint32_t conn_id, HvMsgHandler handler, void *data) + g_free_rcu(mh, rcu); + ret = 0; + } +- goto unlock; ++ return ret; + } + } + +@@ -515,8 +516,7 @@ int hyperv_set_msg_handler(uint32_t conn_id, HvMsgHandler handler, void *data) + } else { + ret = -ENOENT; + } +-unlock: +- qemu_mutex_unlock(&handlers_mutex); ++ + return ret; + } + +@@ -565,7 +565,7 @@ static int set_event_flag_handler(uint32_t conn_id, EventNotifier *notifier) + int ret; + EventFlagHandler *handler; + +- qemu_mutex_lock(&handlers_mutex); ++ QEMU_LOCK_GUARD(&handlers_mutex); + QLIST_FOREACH(handler, &event_flag_handlers, link) { + if (handler->conn_id == conn_id) { + if (notifier) { +@@ -575,7 +575,7 @@ static int set_event_flag_handler(uint32_t conn_id, EventNotifier *notifier) + g_free_rcu(handler, rcu); + ret = 0; + } +- goto unlock; ++ return ret; + } + } + +@@ -588,8 +588,7 @@ static int set_event_flag_handler(uint32_t conn_id, EventNotifier *notifier) + } else { + ret = -ENOENT; + } +-unlock: +- qemu_mutex_unlock(&handlers_mutex); ++ + return ret; + } + +diff --git a/hw/rdma/rdma_backend.c b/hw/rdma/rdma_backend.c +index 3dd39fe1a7..db7e5c8be5 100644 +--- a/hw/rdma/rdma_backend.c ++++ b/hw/rdma/rdma_backend.c +@@ -95,36 +95,36 @@ static int rdma_poll_cq(RdmaDeviceResources *rdma_dev_res, struct ibv_cq *ibcq) + struct ibv_wc wc[2]; + RdmaProtectedGSList *cqe_ctx_list; + +- qemu_mutex_lock(&rdma_dev_res->lock); +- do { +- ne = ibv_poll_cq(ibcq, ARRAY_SIZE(wc), wc); ++ WITH_QEMU_LOCK_GUARD(&rdma_dev_res->lock) { ++ do { ++ ne = ibv_poll_cq(ibcq, ARRAY_SIZE(wc), wc); + +- trace_rdma_poll_cq(ne, ibcq); ++ trace_rdma_poll_cq(ne, ibcq); + +- for (i = 0; i < ne; i++) { +- bctx = rdma_rm_get_cqe_ctx(rdma_dev_res, wc[i].wr_id); +- if (unlikely(!bctx)) { +- rdma_error_report("No matching ctx for req %"PRId64, +- wc[i].wr_id); +- continue; +- } ++ for (i = 0; i < ne; i++) { ++ bctx = rdma_rm_get_cqe_ctx(rdma_dev_res, wc[i].wr_id); ++ if (unlikely(!bctx)) { ++ rdma_error_report("No matching ctx for req %"PRId64, ++ wc[i].wr_id); ++ continue; ++ } + +- comp_handler(bctx->up_ctx, &wc[i]); ++ comp_handler(bctx->up_ctx, &wc[i]); + +- if (bctx->backend_qp) { +- cqe_ctx_list = &bctx->backend_qp->cqe_ctx_list; +- } else { +- cqe_ctx_list = &bctx->backend_srq->cqe_ctx_list; +- } ++ if (bctx->backend_qp) { ++ cqe_ctx_list = &bctx->backend_qp->cqe_ctx_list; ++ } else { ++ cqe_ctx_list = &bctx->backend_srq->cqe_ctx_list; ++ } + +- rdma_protected_gslist_remove_int32(cqe_ctx_list, wc[i].wr_id); +- rdma_rm_dealloc_cqe_ctx(rdma_dev_res, wc[i].wr_id); +- g_free(bctx); +- } +- total_ne += ne; +- } while (ne > 0); +- atomic_sub(&rdma_dev_res->stats.missing_cqe, total_ne); +- qemu_mutex_unlock(&rdma_dev_res->lock); ++ rdma_protected_gslist_remove_int32(cqe_ctx_list, wc[i].wr_id); ++ rdma_rm_dealloc_cqe_ctx(rdma_dev_res, wc[i].wr_id); ++ g_free(bctx); ++ } ++ total_ne += ne; ++ } while (ne > 0); ++ atomic_sub(&rdma_dev_res->stats.missing_cqe, total_ne); ++ } + + if (ne < 0) { + rdma_error_report("ibv_poll_cq fail, rc=%d, errno=%d", ne, errno); +diff --git a/hw/rdma/rdma_rm.c b/hw/rdma/rdma_rm.c +index 7e9ea283c9..60957f88db 100644 +--- a/hw/rdma/rdma_rm.c ++++ b/hw/rdma/rdma_rm.c +@@ -147,14 +147,13 @@ static inline void rdma_res_tbl_dealloc(RdmaRmResTbl *tbl, uint32_t handle) + { + trace_rdma_res_tbl_dealloc(tbl->name, handle); + +- qemu_mutex_lock(&tbl->lock); ++ QEMU_LOCK_GUARD(&tbl->lock); + + if (handle < tbl->tbl_sz) { + clear_bit(handle, tbl->bitmap); + tbl->used--; + } + +- qemu_mutex_unlock(&tbl->lock); + } + + int rdma_rm_alloc_pd(RdmaDeviceResources *dev_res, RdmaBackendDev *backend_dev, +-- +2.23.0 + diff --git a/lockable-fix-__COUNTER__-macro-to-be-referenced-prop.patch b/lockable-fix-__COUNTER__-macro-to-be-referenced-prop.patch new file mode 100644 index 0000000000000000000000000000000000000000..6a84b97f89829b0c7dd58368ff833c7067df0214 --- /dev/null +++ b/lockable-fix-__COUNTER__-macro-to-be-referenced-prop.patch @@ -0,0 +1,60 @@ +From 56f21718b8767a1b523f2a14107d6307336ca51d Mon Sep 17 00:00:00 2001 +From: Daniel Brodsky +Date: Fri, 3 Apr 2020 21:21:07 -0700 +Subject: [PATCH 234/709] lockable: fix __COUNTER__ macro to be referenced + properly + +- __COUNTER__ doesn't work with ## concat +- replaced ## with glue() macro so __COUNTER__ is evaluated + +Fixes: 3284c3ddc4 + +Signed-off-by: Daniel Brodsky +Message-id: 20200404042108.389635-2-dnbrdsky@gmail.com +Signed-off-by: Stefan Hajnoczi +--- + include/qemu/lockable.h | 7 ++++--- + include/qemu/rcu.h | 2 +- + 2 files changed, 5 insertions(+), 4 deletions(-) + +diff --git a/include/qemu/lockable.h b/include/qemu/lockable.h +index 1aeb2cb1a6..b620023141 100644 +--- a/include/qemu/lockable.h ++++ b/include/qemu/lockable.h +@@ -152,7 +152,7 @@ G_DEFINE_AUTOPTR_CLEANUP_FUNC(QemuLockable, qemu_lockable_auto_unlock) + * } + */ + #define WITH_QEMU_LOCK_GUARD(x) \ +- WITH_QEMU_LOCK_GUARD_((x), qemu_lockable_auto##__COUNTER__) ++ WITH_QEMU_LOCK_GUARD_((x), glue(qemu_lockable_auto, __COUNTER__)) + + /** + * QEMU_LOCK_GUARD - Lock an object until the end of the scope +@@ -169,8 +169,9 @@ G_DEFINE_AUTOPTR_CLEANUP_FUNC(QemuLockable, qemu_lockable_auto_unlock) + * return; <-- mutex is automatically unlocked + * } + */ +-#define QEMU_LOCK_GUARD(x) \ +- g_autoptr(QemuLockable) qemu_lockable_auto##__COUNTER__ = \ ++#define QEMU_LOCK_GUARD(x) \ ++ g_autoptr(QemuLockable) \ ++ glue(qemu_lockable_auto, __COUNTER__) G_GNUC_UNUSED = \ + qemu_lockable_auto_lock(QEMU_MAKE_LOCKABLE((x))) + + #endif +diff --git a/include/qemu/rcu.h b/include/qemu/rcu.h +index 9c82683e37..570aa603eb 100644 +--- a/include/qemu/rcu.h ++++ b/include/qemu/rcu.h +@@ -170,7 +170,7 @@ static inline void rcu_read_auto_unlock(RCUReadAuto *r) + G_DEFINE_AUTOPTR_CLEANUP_FUNC(RCUReadAuto, rcu_read_auto_unlock) + + #define WITH_RCU_READ_LOCK_GUARD() \ +- WITH_RCU_READ_LOCK_GUARD_(_rcu_read_auto##__COUNTER__) ++ WITH_RCU_READ_LOCK_GUARD_(glue(_rcu_read_auto, __COUNTER__)) + + #define WITH_RCU_READ_LOCK_GUARD_(var) \ + for (g_autoptr(RCUReadAuto) var = rcu_read_auto_lock(); \ +-- +2.23.0 + diff --git a/lockable-replaced-locks-with-lock-guard-macros-where.patch b/lockable-replaced-locks-with-lock-guard-macros-where.patch new file mode 100644 index 0000000000000000000000000000000000000000..2cefc396ff451c83d176a15881c2206c2df47175 --- /dev/null +++ b/lockable-replaced-locks-with-lock-guard-macros-where.patch @@ -0,0 +1,626 @@ +From 6e8a355de6c4d32e9df336cdafb009cd78262836 Mon Sep 17 00:00:00 2001 +From: Daniel Brodsky +Date: Fri, 3 Apr 2020 21:21:08 -0700 +Subject: [PATCH 235/709] lockable: replaced locks with lock guard macros where + appropriate + +- ran regexp "qemu_mutex_lock\(.*\).*\n.*if" to find targets +- replaced result with QEMU_LOCK_GUARD if all unlocks at function end +- replaced result with WITH_QEMU_LOCK_GUARD if unlock not at end + +Signed-off-by: Daniel Brodsky +Reviewed-by: Juan Quintela +Message-id: 20200404042108.389635-3-dnbrdsky@gmail.com +Signed-off-by: Stefan Hajnoczi +--- + block/iscsi.c | 7 ++---- + block/nfs.c | 51 ++++++++++++++++++++----------------------- + cpus-common.c | 14 +++++------- + hw/display/qxl.c | 43 +++++++++++++++++------------------- + hw/vfio/platform.c | 5 ++--- + migration/migration.c | 3 +-- + migration/multifd.c | 8 +++---- + migration/ram.c | 3 +-- + monitor/misc.c | 4 +--- + ui/spice-display.c | 14 ++++++------ + util/log.c | 4 ++-- + util/qemu-timer.c | 17 +++++++-------- + util/rcu.c | 8 +++---- + util/thread-pool.c | 3 +-- + util/vfio-helpers.c | 5 ++--- + 15 files changed, 83 insertions(+), 106 deletions(-) + +diff --git a/block/iscsi.c b/block/iscsi.c +index 914a1de9fb..a8b76979d8 100644 +--- a/block/iscsi.c ++++ b/block/iscsi.c +@@ -1394,20 +1394,17 @@ static void iscsi_nop_timed_event(void *opaque) + { + IscsiLun *iscsilun = opaque; + +- qemu_mutex_lock(&iscsilun->mutex); ++ QEMU_LOCK_GUARD(&iscsilun->mutex); + if (iscsi_get_nops_in_flight(iscsilun->iscsi) >= MAX_NOP_FAILURES) { + error_report("iSCSI: NOP timeout. Reconnecting..."); + iscsilun->request_timed_out = true; + } else if (iscsi_nop_out_async(iscsilun->iscsi, NULL, NULL, 0, NULL) != 0) { + error_report("iSCSI: failed to sent NOP-Out. Disabling NOP messages."); +- goto out; ++ return; + } + + timer_mod(iscsilun->nop_timer, qemu_clock_get_ms(QEMU_CLOCK_REALTIME) + NOP_INTERVAL); + iscsi_set_events(iscsilun); +- +-out: +- qemu_mutex_unlock(&iscsilun->mutex); + } + + static void iscsi_readcapacity_sync(IscsiLun *iscsilun, Error **errp) +diff --git a/block/nfs.c b/block/nfs.c +index 2393fbfe6b..b86ba5bfa1 100644 +--- a/block/nfs.c ++++ b/block/nfs.c +@@ -273,15 +273,14 @@ static int coroutine_fn nfs_co_preadv(BlockDriverState *bs, uint64_t offset, + nfs_co_init_task(bs, &task); + task.iov = iov; + +- qemu_mutex_lock(&client->mutex); +- if (nfs_pread_async(client->context, client->fh, +- offset, bytes, nfs_co_generic_cb, &task) != 0) { +- qemu_mutex_unlock(&client->mutex); +- return -ENOMEM; +- } ++ WITH_QEMU_LOCK_GUARD(&client->mutex) { ++ if (nfs_pread_async(client->context, client->fh, ++ offset, bytes, nfs_co_generic_cb, &task) != 0) { ++ return -ENOMEM; ++ } + +- nfs_set_events(client); +- qemu_mutex_unlock(&client->mutex); ++ nfs_set_events(client); ++ } + while (!task.complete) { + qemu_coroutine_yield(); + } +@@ -320,19 +319,18 @@ static int coroutine_fn nfs_co_pwritev(BlockDriverState *bs, uint64_t offset, + buf = iov->iov[0].iov_base; + } + +- qemu_mutex_lock(&client->mutex); +- if (nfs_pwrite_async(client->context, client->fh, +- offset, bytes, buf, +- nfs_co_generic_cb, &task) != 0) { +- qemu_mutex_unlock(&client->mutex); +- if (my_buffer) { +- g_free(buf); ++ WITH_QEMU_LOCK_GUARD(&client->mutex) { ++ if (nfs_pwrite_async(client->context, client->fh, ++ offset, bytes, buf, ++ nfs_co_generic_cb, &task) != 0) { ++ if (my_buffer) { ++ g_free(buf); ++ } ++ return -ENOMEM; + } +- return -ENOMEM; +- } + +- nfs_set_events(client); +- qemu_mutex_unlock(&client->mutex); ++ nfs_set_events(client); ++ } + while (!task.complete) { + qemu_coroutine_yield(); + } +@@ -355,15 +353,14 @@ static int coroutine_fn nfs_co_flush(BlockDriverState *bs) + + nfs_co_init_task(bs, &task); + +- qemu_mutex_lock(&client->mutex); +- if (nfs_fsync_async(client->context, client->fh, nfs_co_generic_cb, +- &task) != 0) { +- qemu_mutex_unlock(&client->mutex); +- return -ENOMEM; +- } ++ WITH_QEMU_LOCK_GUARD(&client->mutex) { ++ if (nfs_fsync_async(client->context, client->fh, nfs_co_generic_cb, ++ &task) != 0) { ++ return -ENOMEM; ++ } + +- nfs_set_events(client); +- qemu_mutex_unlock(&client->mutex); ++ nfs_set_events(client); ++ } + while (!task.complete) { + qemu_coroutine_yield(); + } +diff --git a/cpus-common.c b/cpus-common.c +index eaf590cb38..55d5df8923 100644 +--- a/cpus-common.c ++++ b/cpus-common.c +@@ -22,6 +22,7 @@ + #include "exec/cpu-common.h" + #include "hw/core/cpu.h" + #include "sysemu/cpus.h" ++#include "qemu/lockable.h" + + static QemuMutex qemu_cpu_list_lock; + static QemuCond exclusive_cond; +@@ -71,7 +72,7 @@ static int cpu_get_free_index(void) + + void cpu_list_add(CPUState *cpu) + { +- qemu_mutex_lock(&qemu_cpu_list_lock); ++ QEMU_LOCK_GUARD(&qemu_cpu_list_lock); + if (cpu->cpu_index == UNASSIGNED_CPU_INDEX) { + cpu->cpu_index = cpu_get_free_index(); + assert(cpu->cpu_index != UNASSIGNED_CPU_INDEX); +@@ -79,15 +80,13 @@ void cpu_list_add(CPUState *cpu) + assert(!cpu_index_auto_assigned); + } + QTAILQ_INSERT_TAIL_RCU(&cpus, cpu, node); +- qemu_mutex_unlock(&qemu_cpu_list_lock); + } + + void cpu_list_remove(CPUState *cpu) + { +- qemu_mutex_lock(&qemu_cpu_list_lock); ++ QEMU_LOCK_GUARD(&qemu_cpu_list_lock); + if (!QTAILQ_IN_USE(cpu, node)) { + /* there is nothing to undo since cpu_exec_init() hasn't been called */ +- qemu_mutex_unlock(&qemu_cpu_list_lock); + return; + } + +@@ -95,7 +94,6 @@ void cpu_list_remove(CPUState *cpu) + + QTAILQ_REMOVE_RCU(&cpus, cpu, node); + cpu->cpu_index = UNASSIGNED_CPU_INDEX; +- qemu_mutex_unlock(&qemu_cpu_list_lock); + } + + struct qemu_work_item { +@@ -237,7 +235,7 @@ void cpu_exec_start(CPUState *cpu) + * see cpu->running == true, and it will kick the CPU. + */ + if (unlikely(atomic_read(&pending_cpus))) { +- qemu_mutex_lock(&qemu_cpu_list_lock); ++ QEMU_LOCK_GUARD(&qemu_cpu_list_lock); + if (!cpu->has_waiter) { + /* Not counted in pending_cpus, let the exclusive item + * run. Since we have the lock, just set cpu->running to true +@@ -252,7 +250,6 @@ void cpu_exec_start(CPUState *cpu) + * waiter at cpu_exec_end. + */ + } +- qemu_mutex_unlock(&qemu_cpu_list_lock); + } + } + +@@ -280,7 +277,7 @@ void cpu_exec_end(CPUState *cpu) + * next cpu_exec_start. + */ + if (unlikely(atomic_read(&pending_cpus))) { +- qemu_mutex_lock(&qemu_cpu_list_lock); ++ QEMU_LOCK_GUARD(&qemu_cpu_list_lock); + if (cpu->has_waiter) { + cpu->has_waiter = false; + atomic_set(&pending_cpus, pending_cpus - 1); +@@ -288,7 +285,6 @@ void cpu_exec_end(CPUState *cpu) + qemu_cond_signal(&exclusive_cond); + } + } +- qemu_mutex_unlock(&qemu_cpu_list_lock); + } + } + +diff --git a/hw/display/qxl.c b/hw/display/qxl.c +index 227da69a50..d5627119ec 100644 +--- a/hw/display/qxl.c ++++ b/hw/display/qxl.c +@@ -478,18 +478,19 @@ static int qxl_track_command(PCIQXLDevice *qxl, struct QXLCommandExt *ext) + cmd->u.surface_create.stride); + return 1; + } +- qemu_mutex_lock(&qxl->track_lock); +- if (cmd->type == QXL_SURFACE_CMD_CREATE) { +- qxl->guest_surfaces.cmds[id] = ext->cmd.data; +- qxl->guest_surfaces.count++; +- if (qxl->guest_surfaces.max < qxl->guest_surfaces.count) +- qxl->guest_surfaces.max = qxl->guest_surfaces.count; +- } +- if (cmd->type == QXL_SURFACE_CMD_DESTROY) { +- qxl->guest_surfaces.cmds[id] = 0; +- qxl->guest_surfaces.count--; ++ WITH_QEMU_LOCK_GUARD(&qxl->track_lock) { ++ if (cmd->type == QXL_SURFACE_CMD_CREATE) { ++ qxl->guest_surfaces.cmds[id] = ext->cmd.data; ++ qxl->guest_surfaces.count++; ++ if (qxl->guest_surfaces.max < qxl->guest_surfaces.count) { ++ qxl->guest_surfaces.max = qxl->guest_surfaces.count; ++ } ++ } ++ if (cmd->type == QXL_SURFACE_CMD_DESTROY) { ++ qxl->guest_surfaces.cmds[id] = 0; ++ qxl->guest_surfaces.count--; ++ } + } +- qemu_mutex_unlock(&qxl->track_lock); + break; + } + case QXL_CMD_CURSOR: +@@ -958,10 +959,9 @@ static void interface_update_area_complete(QXLInstance *sin, + int i; + int qxl_i; + +- qemu_mutex_lock(&qxl->ssd.lock); ++ QEMU_LOCK_GUARD(&qxl->ssd.lock); + if (surface_id != 0 || !num_updated_rects || + !qxl->render_update_cookie_num) { +- qemu_mutex_unlock(&qxl->ssd.lock); + return; + } + trace_qxl_interface_update_area_complete(qxl->id, surface_id, dirty->left, +@@ -980,7 +980,6 @@ static void interface_update_area_complete(QXLInstance *sin, + * Don't bother copying or scheduling the bh since we will flip + * the whole area anyway on completion of the update_area async call + */ +- qemu_mutex_unlock(&qxl->ssd.lock); + return; + } + qxl_i = qxl->num_dirty_rects; +@@ -991,7 +990,6 @@ static void interface_update_area_complete(QXLInstance *sin, + trace_qxl_interface_update_area_complete_schedule_bh(qxl->id, + qxl->num_dirty_rects); + qemu_bh_schedule(qxl->update_area_bh); +- qemu_mutex_unlock(&qxl->ssd.lock); + } + + /* called from spice server thread context only */ +@@ -1694,15 +1692,14 @@ static void ioport_write(void *opaque, hwaddr addr, + case QXL_IO_MONITORS_CONFIG_ASYNC: + async_common: + async = QXL_ASYNC; +- qemu_mutex_lock(&d->async_lock); +- if (d->current_async != QXL_UNDEFINED_IO) { +- qxl_set_guest_bug(d, "%d async started before last (%d) complete", +- io_port, d->current_async); +- qemu_mutex_unlock(&d->async_lock); +- return; ++ WITH_QEMU_LOCK_GUARD(&d->async_lock) { ++ if (d->current_async != QXL_UNDEFINED_IO) { ++ qxl_set_guest_bug(d, "%d async started before last (%d) complete", ++ io_port, d->current_async); ++ return; ++ } ++ d->current_async = orig_io_port; + } +- d->current_async = orig_io_port; +- qemu_mutex_unlock(&d->async_lock); + break; + default: + break; +diff --git a/hw/vfio/platform.c b/hw/vfio/platform.c +index 6b2952c034..ac2cefc9b1 100644 +--- a/hw/vfio/platform.c ++++ b/hw/vfio/platform.c +@@ -22,6 +22,7 @@ + #include "hw/vfio/vfio-platform.h" + #include "migration/vmstate.h" + #include "qemu/error-report.h" ++#include "qemu/lockable.h" + #include "qemu/main-loop.h" + #include "qemu/module.h" + #include "qemu/range.h" +@@ -216,7 +217,7 @@ static void vfio_intp_interrupt(VFIOINTp *intp) + VFIOPlatformDevice *vdev = intp->vdev; + bool delay_handling = false; + +- qemu_mutex_lock(&vdev->intp_mutex); ++ QEMU_LOCK_GUARD(&vdev->intp_mutex); + if (intp->state == VFIO_IRQ_INACTIVE) { + QLIST_FOREACH(tmp, &vdev->intp_list, next) { + if (tmp->state == VFIO_IRQ_ACTIVE || +@@ -236,7 +237,6 @@ static void vfio_intp_interrupt(VFIOINTp *intp) + QSIMPLEQ_INSERT_TAIL(&vdev->pending_intp_queue, + intp, pqnext); + ret = event_notifier_test_and_clear(intp->interrupt); +- qemu_mutex_unlock(&vdev->intp_mutex); + return; + } + +@@ -266,7 +266,6 @@ static void vfio_intp_interrupt(VFIOINTp *intp) + qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + + vdev->mmap_timeout); + } +- qemu_mutex_unlock(&vdev->intp_mutex); + } + + /** +diff --git a/migration/migration.c b/migration/migration.c +index 187ac0410c..177cce9e95 100644 +--- a/migration/migration.c ++++ b/migration/migration.c +@@ -1653,11 +1653,10 @@ static void migrate_fd_cleanup_bh(void *opaque) + + void migrate_set_error(MigrationState *s, const Error *error) + { +- qemu_mutex_lock(&s->error_mutex); ++ QEMU_LOCK_GUARD(&s->error_mutex); + if (!s->error) { + s->error = error_copy(error); + } +- qemu_mutex_unlock(&s->error_mutex); + } + + void migrate_fd_error(MigrationState *s, const Error *error) +diff --git a/migration/multifd.c b/migration/multifd.c +index cb6a4a3ab8..9123c111a3 100644 +--- a/migration/multifd.c ++++ b/migration/multifd.c +@@ -894,11 +894,11 @@ void multifd_recv_sync_main(void) + for (i = 0; i < migrate_multifd_channels(); i++) { + MultiFDRecvParams *p = &multifd_recv_state->params[i]; + +- qemu_mutex_lock(&p->mutex); +- if (multifd_recv_state->packet_num < p->packet_num) { +- multifd_recv_state->packet_num = p->packet_num; ++ WITH_QEMU_LOCK_GUARD(&p->mutex) { ++ if (multifd_recv_state->packet_num < p->packet_num) { ++ multifd_recv_state->packet_num = p->packet_num; ++ } + } +- qemu_mutex_unlock(&p->mutex); + trace_multifd_recv_sync_main_signal(p->id); + qemu_sem_post(&p->sem_sync); + } +diff --git a/migration/ram.c b/migration/ram.c +index 04f13feb2e..580ec24522 100644 +--- a/migration/ram.c ++++ b/migration/ram.c +@@ -1369,7 +1369,7 @@ static RAMBlock *unqueue_page(RAMState *rs, ram_addr_t *offset) + return NULL; + } + +- qemu_mutex_lock(&rs->src_page_req_mutex); ++ QEMU_LOCK_GUARD(&rs->src_page_req_mutex); + if (!QSIMPLEQ_EMPTY(&rs->src_page_requests)) { + struct RAMSrcPageRequest *entry = + QSIMPLEQ_FIRST(&rs->src_page_requests); +@@ -1386,7 +1386,6 @@ static RAMBlock *unqueue_page(RAMState *rs, ram_addr_t *offset) + migration_consume_urgent_request(); + } + } +- qemu_mutex_unlock(&rs->src_page_req_mutex); + + return block; + } +diff --git a/monitor/misc.c b/monitor/misc.c +index 6c45fa490f..9723b466cd 100644 +--- a/monitor/misc.c ++++ b/monitor/misc.c +@@ -1473,7 +1473,7 @@ AddfdInfo *monitor_fdset_add_fd(int fd, bool has_fdset_id, int64_t fdset_id, + MonFdsetFd *mon_fdset_fd; + AddfdInfo *fdinfo; + +- qemu_mutex_lock(&mon_fdsets_lock); ++ QEMU_LOCK_GUARD(&mon_fdsets_lock); + if (has_fdset_id) { + QLIST_FOREACH(mon_fdset, &mon_fdsets, next) { + /* Break if match found or match impossible due to ordering by ID */ +@@ -1494,7 +1494,6 @@ AddfdInfo *monitor_fdset_add_fd(int fd, bool has_fdset_id, int64_t fdset_id, + if (fdset_id < 0) { + error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "fdset-id", + "a non-negative value"); +- qemu_mutex_unlock(&mon_fdsets_lock); + return NULL; + } + /* Use specified fdset ID */ +@@ -1545,7 +1544,6 @@ AddfdInfo *monitor_fdset_add_fd(int fd, bool has_fdset_id, int64_t fdset_id, + fdinfo->fdset_id = mon_fdset->id; + fdinfo->fd = mon_fdset_fd->fd; + +- qemu_mutex_unlock(&mon_fdsets_lock); + return fdinfo; + } + +diff --git a/ui/spice-display.c b/ui/spice-display.c +index 6babe24909..19632fdf6c 100644 +--- a/ui/spice-display.c ++++ b/ui/spice-display.c +@@ -18,6 +18,7 @@ + #include "qemu/osdep.h" + #include "ui/qemu-spice.h" + #include "qemu/timer.h" ++#include "qemu/lockable.h" + #include "qemu/main-loop.h" + #include "qemu/option.h" + #include "qemu/queue.h" +@@ -483,12 +484,12 @@ void qemu_spice_display_refresh(SimpleSpiceDisplay *ssd) + { + graphic_hw_update(ssd->dcl.con); + +- qemu_mutex_lock(&ssd->lock); +- if (QTAILQ_EMPTY(&ssd->updates) && ssd->ds) { +- qemu_spice_create_update(ssd); +- ssd->notify++; ++ WITH_QEMU_LOCK_GUARD(&ssd->lock) { ++ if (QTAILQ_EMPTY(&ssd->updates) && ssd->ds) { ++ qemu_spice_create_update(ssd); ++ ssd->notify++; ++ } + } +- qemu_mutex_unlock(&ssd->lock); + + trace_qemu_spice_display_refresh(ssd->qxl.id, ssd->notify); + if (ssd->notify) { +@@ -580,7 +581,7 @@ static int interface_get_cursor_command(QXLInstance *sin, QXLCommandExt *ext) + SimpleSpiceDisplay *ssd = container_of(sin, SimpleSpiceDisplay, qxl); + int ret; + +- qemu_mutex_lock(&ssd->lock); ++ QEMU_LOCK_GUARD(&ssd->lock); + if (ssd->ptr_define) { + *ext = ssd->ptr_define->ext; + ssd->ptr_define = NULL; +@@ -592,7 +593,6 @@ static int interface_get_cursor_command(QXLInstance *sin, QXLCommandExt *ext) + } else { + ret = false; + } +- qemu_mutex_unlock(&ssd->lock); + return ret; + } + +diff --git a/util/log.c b/util/log.c +index 2da6cb31dc..bdb3d712e8 100644 +--- a/util/log.c ++++ b/util/log.c +@@ -25,6 +25,7 @@ + #include "qemu/cutils.h" + #include "trace/control.h" + #include "qemu/thread.h" ++#include "qemu/lockable.h" + + static char *logfilename; + static QemuMutex qemu_logfile_mutex; +@@ -94,7 +95,7 @@ void qemu_set_log(int log_flags) + if (qemu_loglevel && (!is_daemonized() || logfilename)) { + need_to_open_file = true; + } +- qemu_mutex_lock(&qemu_logfile_mutex); ++ QEMU_LOCK_GUARD(&qemu_logfile_mutex); + if (qemu_logfile && !need_to_open_file) { + logfile = qemu_logfile; + atomic_rcu_set(&qemu_logfile, NULL); +@@ -136,7 +137,6 @@ void qemu_set_log(int log_flags) + } + atomic_rcu_set(&qemu_logfile, logfile); + } +- qemu_mutex_unlock(&qemu_logfile_mutex); + } + + void qemu_log_needs_buffers(void) +diff --git a/util/qemu-timer.c b/util/qemu-timer.c +index d548d3c1ad..b6575a2cd5 100644 +--- a/util/qemu-timer.c ++++ b/util/qemu-timer.c +@@ -459,17 +459,16 @@ void timer_mod_anticipate_ns(QEMUTimer *ts, int64_t expire_time) + QEMUTimerList *timer_list = ts->timer_list; + bool rearm; + +- qemu_mutex_lock(&timer_list->active_timers_lock); +- if (ts->expire_time == -1 || ts->expire_time > expire_time) { +- if (ts->expire_time != -1) { +- timer_del_locked(timer_list, ts); ++ WITH_QEMU_LOCK_GUARD(&timer_list->active_timers_lock) { ++ if (ts->expire_time == -1 || ts->expire_time > expire_time) { ++ if (ts->expire_time != -1) { ++ timer_del_locked(timer_list, ts); ++ } ++ rearm = timer_mod_ns_locked(timer_list, ts, expire_time); ++ } else { ++ rearm = false; + } +- rearm = timer_mod_ns_locked(timer_list, ts, expire_time); +- } else { +- rearm = false; + } +- qemu_mutex_unlock(&timer_list->active_timers_lock); +- + if (rearm) { + timerlist_rearm(timer_list); + } +diff --git a/util/rcu.c b/util/rcu.c +index 177a675619..60a37f72c3 100644 +--- a/util/rcu.c ++++ b/util/rcu.c +@@ -31,6 +31,7 @@ + #include "qemu/atomic.h" + #include "qemu/thread.h" + #include "qemu/main-loop.h" ++#include "qemu/lockable.h" + #if defined(CONFIG_MALLOC_TRIM) + #include + #endif +@@ -141,14 +142,14 @@ static void wait_for_readers(void) + + void synchronize_rcu(void) + { +- qemu_mutex_lock(&rcu_sync_lock); ++ QEMU_LOCK_GUARD(&rcu_sync_lock); + + /* Write RCU-protected pointers before reading p_rcu_reader->ctr. + * Pairs with smp_mb_placeholder() in rcu_read_lock(). + */ + smp_mb_global(); + +- qemu_mutex_lock(&rcu_registry_lock); ++ QEMU_LOCK_GUARD(&rcu_registry_lock); + if (!QLIST_EMPTY(®istry)) { + /* In either case, the atomic_mb_set below blocks stores that free + * old RCU-protected pointers. +@@ -169,9 +170,6 @@ void synchronize_rcu(void) + + wait_for_readers(); + } +- +- qemu_mutex_unlock(&rcu_registry_lock); +- qemu_mutex_unlock(&rcu_sync_lock); + } + + +diff --git a/util/thread-pool.c b/util/thread-pool.c +index 4ed9b89ab2..d763cea505 100644 +--- a/util/thread-pool.c ++++ b/util/thread-pool.c +@@ -210,7 +210,7 @@ static void thread_pool_cancel(BlockAIOCB *acb) + + trace_thread_pool_cancel(elem, elem->common.opaque); + +- qemu_mutex_lock(&pool->lock); ++ QEMU_LOCK_GUARD(&pool->lock); + if (elem->state == THREAD_QUEUED && + /* No thread has yet started working on elem. we can try to "steal" + * the item from the worker if we can get a signal from the +@@ -225,7 +225,6 @@ static void thread_pool_cancel(BlockAIOCB *acb) + elem->ret = -ECANCELED; + } + +- qemu_mutex_unlock(&pool->lock); + } + + static AioContext *thread_pool_get_aio_context(BlockAIOCB *acb) +diff --git a/util/vfio-helpers.c b/util/vfio-helpers.c +index ddd9a96e76..e399e330e2 100644 +--- a/util/vfio-helpers.c ++++ b/util/vfio-helpers.c +@@ -21,6 +21,7 @@ + #include "standard-headers/linux/pci_regs.h" + #include "qemu/event_notifier.h" + #include "qemu/vfio-helpers.h" ++#include "qemu/lockable.h" + #include "trace.h" + + #define QEMU_VFIO_DEBUG 0 +@@ -667,14 +668,12 @@ int qemu_vfio_dma_reset_temporary(QEMUVFIOState *s) + .size = QEMU_VFIO_IOVA_MAX - s->high_water_mark, + }; + trace_qemu_vfio_dma_reset_temporary(s); +- qemu_mutex_lock(&s->lock); ++ QEMU_LOCK_GUARD(&s->lock); + if (ioctl(s->container, VFIO_IOMMU_UNMAP_DMA, &unmap)) { + error_report("VFIO_UNMAP_DMA failed: %s", strerror(errno)); +- qemu_mutex_unlock(&s->lock); + return -errno; + } + s->high_water_mark = QEMU_VFIO_IOVA_MAX; +- qemu_mutex_unlock(&s->lock); + return 0; + } + +-- +2.23.0 + diff --git a/megasas-fix-mapped-frame-size.patch b/megasas-fix-mapped-frame-size.patch deleted file mode 100644 index 46cc8d30f9506545dec3a307a3bdc777678cbce9..0000000000000000000000000000000000000000 --- a/megasas-fix-mapped-frame-size.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 2e56fbc87f6ec3cd56c37b01d313abd502b80d61 Mon Sep 17 00:00:00 2001 -From: Peter Lieven -Date: Thu, 4 Apr 2019 14:10:15 +0200 -Subject: [PATCH] megasas: fix mapped frame size - -the current value of 1024 bytes (16 * MFI_FRAME_SIZE) we map is not enough to hold -the maximum number of scatter gather elements we advertise. We actually need a -maximum of 2048 bytes. This is 128 max sg elements * 16 bytes (sizeof (union mfi_sgl)). - -Cc: qemu-stable@nongnu.org -Signed-off-by: Peter Lieven -Message-Id: <20190404121015.28634-1-pl@kamp.de> -Reviewed-by: Hannes Reinecke -Signed-off-by: Paolo Bonzini -(cherry-picked from commit 2e56fbc87f6ec3cd56c37b01d313abd502b80d61) ---- - hw/scsi/megasas.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/hw/scsi/megasas.c b/hw/scsi/megasas.c -index a56317e026..5ad762de23 100644 ---- a/hw/scsi/megasas.c -+++ b/hw/scsi/megasas.c -@@ -477,7 +477,7 @@ static MegasasCmd *megasas_enqueue_frame(MegasasState *s, - { - PCIDevice *pcid = PCI_DEVICE(s); - MegasasCmd *cmd = NULL; -- int frame_size = MFI_FRAME_SIZE * 16; -+ int frame_size = MEGASAS_MAX_SGE * sizeof(union mfi_sgl); - hwaddr frame_size_p = frame_size; - unsigned long index; - --- -2.19.1 - diff --git a/memory-unref-the-memory-region-in-simplify-flatview.patch b/memory-unref-the-memory-region-in-simplify-flatview.patch deleted file mode 100644 index eb199646181ccf95dcfef2208a6b5592ff20b6d8..0000000000000000000000000000000000000000 --- a/memory-unref-the-memory-region-in-simplify-flatview.patch +++ /dev/null @@ -1,85 +0,0 @@ -From b9f43f0cca03586a31b53e47ade72e77db01cb4c Mon Sep 17 00:00:00 2001 -From: King Wang -Date: Fri, 12 Jul 2019 14:52:41 +0800 -Subject: [PATCH 2/5] memory: unref the memory region in simplify flatview - -The memory region reference is increased when insert a range -into flatview range array, then decreased by destroy flatview. -If some flat range merged by flatview_simplify, the memory region -reference can not be decreased by destroy flatview any more. - -In this case, start virtual machine by the command line: -qemu-system-x86_64 --name guest=ubuntu,debug-threads=on --machine pc,accel=kvm,usb=off,dump-guest-core=off --cpu host --m 16384 --realtime mlock=off --smp 8,sockets=2,cores=4,threads=1 --object memory-backend-file,id=ram-node0,prealloc=yes,mem-path=/dev/hugepages,share=yes,size=8589934592 --numa node,nodeid=0,cpus=0-3,memdev=ram-node0 --object memory-backend-file,id=ram-node1,prealloc=yes,mem-path=/dev/hugepages,share=yes,size=8589934592 --numa node,nodeid=1,cpus=4-7,memdev=ram-node1 --no-user-config --nodefaults --rtc base=utc --no-shutdown --boot strict=on --device piix3-usb-uhci,id=usb,bus=pci.0,addr=0x1.0x2 --device virtio-scsi-pci,id=scsi0,bus=pci.0,addr=0x2 --device virtio-serial-pci,id=virtio-serial0,bus=pci.0,addr=0x3 --drive file=ubuntu.qcow2,format=qcow2,if=none,id=drive-virtio-disk0,cache=none,aio=native --device virtio-blk-pci,scsi=off,bus=pci.0,addr=0x4,drive=drive-virtio-disk0,id=virtio-disk0,bootindex=1 --chardev pty,id=charserial0 --device isa-serial,chardev=charserial0,id=serial0 --device usb-tablet,id=input0,bus=usb.0,port=1 --vnc 0.0.0.0:0 --device VGA,id=video0,vgamem_mb=16,bus=pci.0,addr=0x5 --device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x6 --msg timestamp=on - -And run the script in guest OS: -while true -do - setpci -s 00:06.0 04.b=03 - setpci -s 00:06.0 04.b=07 -done - -I found the reference of node0 HostMemoryBackendFile is a big one. -(gdb) p numa_info[0]->node_memdev->parent.ref -$6 = 1636278 -(gdb) - -Signed-off-by: King Wang -Message-Id: <20190712065241.11784-1-king.wang@huawei.com> -Signed-off-by: Paolo Bonzini ---- - memory.c | 5 ++++- - 1 file changed, 4 insertions(+), 1 deletion(-) - -diff --git a/memory.c b/memory.c -index 9fbca52..0b49281 100644 ---- a/memory.c -+++ b/memory.c -@@ -320,7 +320,7 @@ static bool can_merge(FlatRange *r1, FlatRange *r2) - /* Attempt to simplify a view by merging adjacent ranges */ - static void flatview_simplify(FlatView *view) - { -- unsigned i, j; -+ unsigned i, j, k; - - i = 0; - while (i < view->nr) { -@@ -331,6 +331,9 @@ static void flatview_simplify(FlatView *view) - ++j; - } - ++i; -+ for (k = i; k < j; k++) { -+ memory_region_unref(view->ranges[k].mr); -+ } - memmove(&view->ranges[i], &view->ranges[j], - (view->nr - j) * sizeof(view->ranges[j])); - view->nr -= j - i; --- -1.8.3.1 - diff --git a/migration-Fix-use-after-free-during-process-exit.patch b/migration-Fix-use-after-free-during-process-exit.patch deleted file mode 100644 index e64034241b749db9b6f078815f806fbfca15bf3d..0000000000000000000000000000000000000000 --- a/migration-Fix-use-after-free-during-process-exit.patch +++ /dev/null @@ -1,205 +0,0 @@ -From 35d6458d6a100b2f15a7e079558a4570742c6e5a Mon Sep 17 00:00:00 2001 -From: Yury Kotov -Date: Mon, 8 Apr 2019 14:33:43 +0300 -Subject: [PATCH] migration: Fix use-after-free during process exit - -It fixes heap-use-after-free which was found by clang's ASAN. - -Control flow of this use-after-free: -main_thread: - * Got SIGTERM and completes main loop - * Calls migration_shutdown - - migrate_fd_cancel (so, migration_thread begins to complete) - - object_unref(OBJECT(current_migration)); - -migration_thread: - * migration_iteration_finish -> schedule cleanup bh - * object_unref(OBJECT(s)); (Now, current_migration is freed) - * exits - -main_thread: - * Calls vm_shutdown -> drain bdrvs -> main loop - -> cleanup_bh -> use after free - -If you want to reproduce, these couple of sleeps will help: -vl.c:4613: - migration_shutdown(); -+ sleep(2); -migration.c:3269: -+ sleep(1); - trace_migration_thread_after_loop(); - migration_iteration_finish(s); - -Original output: -qemu-system-x86_64: terminating on signal 15 from pid 31980 () -================================================================= -==31958==ERROR: AddressSanitizer: heap-use-after-free on address 0x61900001d210 - at pc 0x555558a535ca bp 0x7fffffffb190 sp 0x7fffffffb188 -READ of size 8 at 0x61900001d210 thread T0 (qemu-vm-0) - #0 0x555558a535c9 in migrate_fd_cleanup migration/migration.c:1502:23 - #1 0x5555594fde0a in aio_bh_call util/async.c:90:5 - #2 0x5555594fe522 in aio_bh_poll util/async.c:118:13 - #3 0x555559524783 in aio_poll util/aio-posix.c:725:17 - #4 0x555559504fb3 in aio_wait_bh_oneshot util/aio-wait.c:71:5 - #5 0x5555573bddf6 in virtio_blk_data_plane_stop - hw/block/dataplane/virtio-blk.c:282:5 - #6 0x5555589d5c09 in virtio_bus_stop_ioeventfd hw/virtio/virtio-bus.c:246:9 - #7 0x5555589e9917 in virtio_pci_stop_ioeventfd hw/virtio/virtio-pci.c:287:5 - #8 0x5555589e22bf in virtio_pci_vmstate_change hw/virtio/virtio-pci.c:1072:9 - #9 0x555557628931 in virtio_vmstate_change hw/virtio/virtio.c:2257:9 - #10 0x555557c36713 in vm_state_notify vl.c:1605:9 - #11 0x55555716ef53 in do_vm_stop cpus.c:1074:9 - #12 0x55555716eeff in vm_shutdown cpus.c:1092:12 - #13 0x555557c4283e in main vl.c:4617:5 - #14 0x7fffdfdb482f in __libc_start_main - (/lib/x86_64-linux-gnu/libc.so.6+0x2082f) - #15 0x555556ecb118 in _start (x86_64-softmmu/qemu-system-x86_64+0x1977118) - -0x61900001d210 is located 144 bytes inside of 952-byte region - [0x61900001d180,0x61900001d538) -freed by thread T6 (live_migration) here: - #0 0x555556f76782 in __interceptor_free - /tmp/final/llvm.src/projects/compiler-rt/lib/asan/asan_malloc_linux.cc:124:3 - #1 0x555558d5fa94 in object_finalize qom/object.c:618:9 - #2 0x555558d57651 in object_unref qom/object.c:1068:9 - #3 0x555558a55588 in migration_thread migration/migration.c:3272:5 - #4 0x5555595393f2 in qemu_thread_start util/qemu-thread-posix.c:502:9 - #5 0x7fffe057f6b9 in start_thread (/lib/x86_64-linux-gnu/libpthread.so.0+0x76b9) - -previously allocated by thread T0 (qemu-vm-0) here: - #0 0x555556f76b03 in __interceptor_malloc - /tmp/final/llvm.src/projects/compiler-rt/lib/asan/asan_malloc_linux.cc:146:3 - #1 0x7ffff6ee37b8 in g_malloc (/lib/x86_64-linux-gnu/libglib-2.0.so.0+0x4f7b8) - #2 0x555558d58031 in object_new qom/object.c:640:12 - #3 0x555558a31f21 in migration_object_init migration/migration.c:139:25 - #4 0x555557c41398 in main vl.c:4320:5 - #5 0x7fffdfdb482f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f) - -Thread T6 (live_migration) created by T0 (qemu-vm-0) here: - #0 0x555556f5f0dd in pthread_create - /tmp/final/llvm.src/projects/compiler-rt/lib/asan/asan_interceptors.cc:210:3 - #1 0x555559538cf9 in qemu_thread_create util/qemu-thread-posix.c:539:11 - #2 0x555558a53304 in migrate_fd_connect migration/migration.c:3332:5 - #3 0x555558a72bd8 in migration_channel_connect migration/channel.c:92:5 - #4 0x555558a6ef87 in exec_start_outgoing_migration migration/exec.c:42:5 - #5 0x555558a4f3c2 in qmp_migrate migration/migration.c:1922:9 - #6 0x555558bb4f6a in qmp_marshal_migrate qapi/qapi-commands-migration.c:607:5 - #7 0x555559363738 in do_qmp_dispatch qapi/qmp-dispatch.c:131:5 - #8 0x555559362a15 in qmp_dispatch qapi/qmp-dispatch.c:174:11 - #9 0x5555571bac15 in monitor_qmp_dispatch monitor.c:4124:11 - #10 0x55555719a22d in monitor_qmp_bh_dispatcher monitor.c:4207:9 - #11 0x5555594fde0a in aio_bh_call util/async.c:90:5 - #12 0x5555594fe522 in aio_bh_poll util/async.c:118:13 - #13 0x5555595201e0 in aio_dispatch util/aio-posix.c:460:5 - #14 0x555559503553 in aio_ctx_dispatch util/async.c:261:5 - #15 0x7ffff6ede196 in g_main_context_dispatch - (/lib/x86_64-linux-gnu/libglib-2.0.so.0+0x4a196) - -SUMMARY: AddressSanitizer: heap-use-after-free migration/migration.c:1502:23 - in migrate_fd_cleanup -Shadow bytes around the buggy address: - 0x0c327fffb9f0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa - 0x0c327fffba00: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa - 0x0c327fffba10: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa - 0x0c327fffba20: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa - 0x0c327fffba30: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd -=>0x0c327fffba40: fd fd[fd]fd fd fd fd fd fd fd fd fd fd fd fd fd - 0x0c327fffba50: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd - 0x0c327fffba60: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd - 0x0c327fffba70: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd - 0x0c327fffba80: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd - 0x0c327fffba90: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd -Shadow byte legend (one shadow byte represents 8 application bytes): - Addressable: 00 - Partially addressable: 01 02 03 04 05 06 07 - Heap left redzone: fa - Freed heap region: fd - Stack left redzone: f1 - Stack mid redzone: f2 - Stack right redzone: f3 - Stack after return: f5 - Stack use after scope: f8 - Global redzone: f9 - Global init order: f6 - Poisoned by user: f7 - Container overflow: fc - Array cookie: ac - Intra object redzone: bb - ASan internal: fe - Left alloca redzone: ca - Right alloca redzone: cb - Shadow gap: cc -==31958==ABORTING - -Signed-off-by: Yury Kotov -Message-Id: <20190408113343.2370-1-yury-kotov@yandex-team.ru> -Reviewed-by: Dr. David Alan Gilbert -Signed-off-by: Dr. David Alan Gilbert - Fixed up comment formatting -(cherry picked from commit fd392cfa8e6fb0dc34bd0327fc356dfbf6edf1fd) -Signed-off-by: Michael Roth ---- - migration/migration.c | 25 ++++++++++++++++++++----- - 1 file changed, 20 insertions(+), 5 deletions(-) - -diff --git a/migration/migration.c b/migration/migration.c -index 609e0df5d0..2f617b9dba 100644 ---- a/migration/migration.c -+++ b/migration/migration.c -@@ -1495,10 +1495,8 @@ static void block_cleanup_parameters(MigrationState *s) - } - } - --static void migrate_fd_cleanup(void *opaque) -+static void migrate_fd_cleanup(MigrationState *s) - { -- MigrationState *s = opaque; -- - qemu_bh_delete(s->cleanup_bh); - s->cleanup_bh = NULL; - -@@ -1543,6 +1541,23 @@ static void migrate_fd_cleanup(void *opaque) - block_cleanup_parameters(s); - } - -+static void migrate_fd_cleanup_schedule(MigrationState *s) -+{ -+ /* -+ * Ref the state for bh, because it may be called when -+ * there're already no other refs -+ */ -+ object_ref(OBJECT(s)); -+ qemu_bh_schedule(s->cleanup_bh); -+} -+ -+static void migrate_fd_cleanup_bh(void *opaque) -+{ -+ MigrationState *s = opaque; -+ migrate_fd_cleanup(s); -+ object_unref(OBJECT(s)); -+} -+ - void migrate_set_error(MigrationState *s, const Error *error) - { - qemu_mutex_lock(&s->error_mutex); -@@ -3144,7 +3159,7 @@ static void migration_iteration_finish(MigrationState *s) - error_report("%s: Unknown ending state %d", __func__, s->state); - break; - } -- qemu_bh_schedule(s->cleanup_bh); -+ migrate_fd_cleanup_schedule(s); - qemu_mutex_unlock_iothread(); - } - -@@ -3279,7 +3294,7 @@ void migrate_fd_connect(MigrationState *s, Error *error_in) - bool resume = s->state == MIGRATION_STATUS_POSTCOPY_PAUSED; - - s->expected_downtime = s->parameters.downtime_limit; -- s->cleanup_bh = qemu_bh_new(migrate_fd_cleanup, s); -+ s->cleanup_bh = qemu_bh_new(migrate_fd_cleanup_bh, s); - if (error_in) { - migrate_fd_error(s, error_in); - migrate_fd_cleanup(s); --- -2.19.1 - diff --git a/migration-colo-Add-missing-error-propagation-code.patch b/migration-colo-Add-missing-error-propagation-code.patch new file mode 100644 index 0000000000000000000000000000000000000000..1d5c5ca2a84e8adf4180447e620862a704148eb3 --- /dev/null +++ b/migration-colo-Add-missing-error-propagation-code.patch @@ -0,0 +1,44 @@ +From 58602676dfd00f519248d4936b0711b7967cbf62 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Mon, 13 Apr 2020 22:52:49 +0200 +Subject: [PATCH 321/709] migration/colo: Add missing error-propagation code +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Running the coccinelle script produced: + + $ spatch \ + --macro-file scripts/cocci-macro-file.h --include-headers \ + --sp-file scripts/coccinelle/find-missing-error_propagate.cocci \ + --keep-comments --smpl-spacing --dir . + HANDLING: ./migration/colo.c + [[manual check required: error_propagate() might be missing in migrate_set_block_enabled() ./migration/colo.c:439:4]] + +Add the missing error_propagate() after review. + +Reviewed-by: Juan Quintela +Signed-off-by: Philippe Mathieu-Daudé +Message-Id: <20200413205250.687-1-f4bug@amsat.org> +Signed-off-by: Dr. David Alan Gilbert +--- + migration/colo.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/migration/colo.c b/migration/colo.c +index 1b3493729b..d015d4f84e 100644 +--- a/migration/colo.c ++++ b/migration/colo.c +@@ -443,6 +443,9 @@ static int colo_do_checkpoint_transaction(MigrationState *s, + + /* Disable block migration */ + migrate_set_block_enabled(false, &local_err); ++ if (local_err) { ++ goto out; ++ } + qemu_mutex_lock_iothread(); + + #ifdef CONFIG_REPLICATION +-- +2.23.0 + diff --git a/migration-colo-Fix-qmp_xen_colo_do_checkpoint-error-.patch b/migration-colo-Fix-qmp_xen_colo_do_checkpoint-error-.patch new file mode 100644 index 0000000000000000000000000000000000000000..6580d60f9b757ec4389a8fbeaf3a16ef51d83e5f --- /dev/null +++ b/migration-colo-Fix-qmp_xen_colo_do_checkpoint-error-.patch @@ -0,0 +1,58 @@ +From 735527e17907cca330ec369a13566fab2ef9adf6 Mon Sep 17 00:00:00 2001 +From: Markus Armbruster +Date: Wed, 22 Apr 2020 15:07:16 +0200 +Subject: [PATCH 024/709] migration/colo: Fix qmp_xen_colo_do_checkpoint() + error handling +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The Error ** argument must be NULL, &error_abort, &error_fatal, or a +pointer to a variable containing NULL. Passing an argument of the +latter kind twice without clearing it in between is wrong: if the +first call sets an error, it no longer points to NULL for the second +call. + +qmp_xen_colo_do_checkpoint() passes @errp first to +replication_do_checkpoint_all(), and then to +colo_notify_filters_event(). If both fail, this will trip the +assertion in error_setv(). + +Similar code in secondary_vm_do_failover() calls +colo_notify_filters_event() only after replication_do_checkpoint_all() +succeeded. Do the same here. + +Fixes: 0e8818f023616677416840d6ddc880db8de3c967 +Cc: Zhang Chen +Cc: zhanghailiang +Signed-off-by: Markus Armbruster +Reviewed-by: zhanghailiang +Reviewed-by: Philippe Mathieu-Daudé +Reviewed-by: Zhang Chen +Message-Id: <20200422130719.28225-12-armbru@redhat.com> +--- + migration/colo.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/migration/colo.c b/migration/colo.c +index a54ac84f41..1b3493729b 100644 +--- a/migration/colo.c ++++ b/migration/colo.c +@@ -263,7 +263,13 @@ ReplicationStatus *qmp_query_xen_replication_status(Error **errp) + + void qmp_xen_colo_do_checkpoint(Error **errp) + { +- replication_do_checkpoint_all(errp); ++ Error *err = NULL; ++ ++ replication_do_checkpoint_all(&err); ++ if (err) { ++ error_propagate(errp, err); ++ return; ++ } + /* Notify all filters of all NIC to do checkpoint */ + colo_notify_filters_event(COLO_EVENT_CHECKPOINT, errp); + } +-- +2.23.0 + diff --git a/migration-dirty-bitmaps-change-bitmap-enumeration-method.patch b/migration-dirty-bitmaps-change-bitmap-enumeration-method.patch deleted file mode 100644 index c720cc1e6942f5b2bbb2812aae583ca9fd4c6b18..0000000000000000000000000000000000000000 --- a/migration-dirty-bitmaps-change-bitmap-enumeration-method.patch +++ /dev/null @@ -1,83 +0,0 @@ -From 3a87d07722d4be717a97b59cfbc7b2ba27ca30b0 Mon Sep 17 00:00:00 2001 -From: John Snow -Date: Tue, 28 May 2019 19:33:31 -0400 -Subject: [PATCH] migration/dirty-bitmaps: change bitmap enumeration method -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Shift from looking at every root BDS to *every* BDS. This will migrate -bitmaps that are attached to blockdev created nodes instead of just ones -attached to emulated storage devices. - -Note that this will not migrate anonymous or internal-use bitmaps, as -those are defined as having no name. - -This will also fix the Coverity issues Peter Maydell has been asking -about for the past several releases, as well as fixing a real bug. - -Reported-by: Peter Maydell -Reported-by: Coverity 😅 -Reported-by: aihua liang -Reviewed-by: Vladimir Sementsov-Ogievskiy -Signed-off-by: John Snow -Message-id: 20190514201926.10407-1-jsnow@redhat.com -Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1652490 -Fixes: Coverity CID 1390625 -CC: Stefan Hajnoczi -Signed-off-by: John Snow -(cherry picked from commit 592203e7cfbd1ad261178431fcf390adfe8b16df) -Signed-off-by: Michael Roth ---- - migration/block-dirty-bitmap.c | 14 ++++---------- - 1 file changed, 4 insertions(+), 10 deletions(-) - -diff --git a/migration/block-dirty-bitmap.c b/migration/block-dirty-bitmap.c -index d1bb863cb6..4a896a09eb 100644 ---- a/migration/block-dirty-bitmap.c -+++ b/migration/block-dirty-bitmap.c -@@ -273,7 +273,6 @@ static int init_dirty_bitmap_migration(void) - BlockDriverState *bs; - BdrvDirtyBitmap *bitmap; - DirtyBitmapMigBitmapState *dbms; -- BdrvNextIterator it; - Error *local_err = NULL; - - dirty_bitmap_mig_state.bulk_completed = false; -@@ -281,13 +280,8 @@ static int init_dirty_bitmap_migration(void) - dirty_bitmap_mig_state.prev_bitmap = NULL; - dirty_bitmap_mig_state.no_bitmaps = false; - -- for (bs = bdrv_first(&it); bs; bs = bdrv_next(&it)) { -- const char *drive_name = bdrv_get_device_or_node_name(bs); -- -- /* skip automatically inserted nodes */ -- while (bs && bs->drv && bs->implicit) { -- bs = backing_bs(bs); -- } -+ for (bs = bdrv_next_all_states(NULL); bs; bs = bdrv_next_all_states(bs)) { -+ const char *name = bdrv_get_device_or_node_name(bs); - - for (bitmap = bdrv_dirty_bitmap_next(bs, NULL); bitmap; - bitmap = bdrv_dirty_bitmap_next(bs, bitmap)) -@@ -296,7 +290,7 @@ static int init_dirty_bitmap_migration(void) - continue; - } - -- if (drive_name == NULL) { -+ if (!name || strcmp(name, "") == 0) { - error_report("Found bitmap '%s' in unnamed node %p. It can't " - "be migrated", bdrv_dirty_bitmap_name(bitmap), bs); - goto fail; -@@ -313,7 +307,7 @@ static int init_dirty_bitmap_migration(void) - - dbms = g_new0(DirtyBitmapMigBitmapState, 1); - dbms->bs = bs; -- dbms->node_name = drive_name; -+ dbms->node_name = name; - dbms->bitmap = bitmap; - dbms->total_sectors = bdrv_nb_sectors(bs); - dbms->sectors_per_chunk = CHUNK_SIZE * 8 * --- -2.19.1 - diff --git a/migration-fix-bad-indentation-in-error_report.patch b/migration-fix-bad-indentation-in-error_report.patch new file mode 100644 index 0000000000000000000000000000000000000000..7d1f98248b64fe38c3be8af8e0dad4ccf77b3ef3 --- /dev/null +++ b/migration-fix-bad-indentation-in-error_report.patch @@ -0,0 +1,54 @@ +From ed8b2828ccc9f94b2ea846a2adb6790edab393c3 Mon Sep 17 00:00:00 2001 +From: Mao Zhongyi +Date: Sat, 28 Mar 2020 01:19:08 +0800 +Subject: [PATCH 316/709] migration: fix bad indentation in error_report() + +bad indentation conflicts with CODING_STYLE doc. + +Signed-off-by: Mao Zhongyi +Message-Id: <09f7529c665cac0c6a5e032ac6fdb6ca701f7e37.1585329482.git.maozhongyi@cmss.chinamobile.com> +Reviewed-by: Dr. David Alan Gilbert +Reviewed-by: Juan Quintela +Signed-off-by: Dr. David Alan Gilbert +--- + migration/migration.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/migration/migration.c b/migration/migration.c +index 177cce9e95..8f27174ff6 100644 +--- a/migration/migration.c ++++ b/migration/migration.c +@@ -2494,7 +2494,7 @@ retry: + if (header_type >= MIG_RP_MSG_MAX || + header_type == MIG_RP_MSG_INVALID) { + error_report("RP: Received invalid message 0x%04x length 0x%04x", +- header_type, header_len); ++ header_type, header_len); + mark_source_rp_bad(ms); + goto out; + } +@@ -2503,9 +2503,9 @@ retry: + header_len != rp_cmd_args[header_type].len) || + header_len > sizeof(buf)) { + error_report("RP: Received '%s' message (0x%04x) with" +- "incorrect length %d expecting %zu", +- rp_cmd_args[header_type].name, header_type, header_len, +- (size_t)rp_cmd_args[header_type].len); ++ "incorrect length %d expecting %zu", ++ rp_cmd_args[header_type].name, header_type, header_len, ++ (size_t)rp_cmd_args[header_type].len); + mark_source_rp_bad(ms); + goto out; + } +@@ -2560,7 +2560,7 @@ retry: + } + if (header_len != expected_len) { + error_report("RP: Req_Page_id with length %d expecting %zd", +- header_len, expected_len); ++ header_len, expected_len); + mark_source_rp_bad(ms); + goto out; + } +-- +2.23.0 + diff --git a/migration-migration-improve-error-reporting-for-migr.patch b/migration-migration-improve-error-reporting-for-migr.patch new file mode 100644 index 0000000000000000000000000000000000000000..dd0c6af454b99c51fe42f7d7e3bffbccc7289bc8 --- /dev/null +++ b/migration-migration-improve-error-reporting-for-migr.patch @@ -0,0 +1,63 @@ +From 2ee30cf078006f60bb59af8090a238e98dc7cfe5 Mon Sep 17 00:00:00 2001 +From: Mao Zhongyi +Date: Tue, 31 Mar 2020 16:22:05 +0800 +Subject: [PATCH 317/709] migration/migration: improve error reporting for + migrate parameters + +use QERR_INVALID_PARAMETER_VALUE instead of +"Parameter '%s' expects" for consistency. + +Signed-off-by: Mao Zhongyi +Message-Id: <4ce71da4a5f98ad6ead0806ec71043473dcb4c07.1585641083.git.maozhongyi@cmss.chinamobile.com> +Reviewed-by: Juan Quintela +Signed-off-by: Dr. David Alan Gilbert +--- + migration/migration.c | 20 ++++++++++++-------- + 1 file changed, 12 insertions(+), 8 deletions(-) + +diff --git a/migration/migration.c b/migration/migration.c +index 8f27174ff6..6e079efdcc 100644 +--- a/migration/migration.c ++++ b/migration/migration.c +@@ -1202,16 +1202,19 @@ static bool migrate_params_check(MigrationParameters *params, Error **errp) + } + + if (params->has_max_bandwidth && (params->max_bandwidth > SIZE_MAX)) { +- error_setg(errp, "Parameter 'max_bandwidth' expects an integer in the" +- " range of 0 to %zu bytes/second", SIZE_MAX); ++ error_setg(errp, QERR_INVALID_PARAMETER_VALUE, ++ "max_bandwidth", ++ "an integer in the range of 0 to "stringify(SIZE_MAX) ++ " bytes/second"); + return false; + } + + if (params->has_downtime_limit && + (params->downtime_limit > MAX_MIGRATE_DOWNTIME)) { +- error_setg(errp, "Parameter 'downtime_limit' expects an integer in " +- "the range of 0 to %d milliseconds", +- MAX_MIGRATE_DOWNTIME); ++ error_setg(errp, QERR_INVALID_PARAMETER_VALUE, ++ "downtime_limit", ++ "an integer in the range of 0 to " ++ stringify(MAX_MIGRATE_DOWNTIME)" milliseconds"); + return false; + } + +@@ -2107,9 +2110,10 @@ void qmp_migrate_set_speed(int64_t value, Error **errp) + void qmp_migrate_set_downtime(double value, Error **errp) + { + if (value < 0 || value > MAX_MIGRATE_DOWNTIME_SECONDS) { +- error_setg(errp, "Parameter 'downtime_limit' expects an integer in " +- "the range of 0 to %d seconds", +- MAX_MIGRATE_DOWNTIME_SECONDS); ++ error_setg(errp, QERR_INVALID_PARAMETER_VALUE, ++ "downtime_limit", ++ "an integer in the range of 0 to " ++ stringify(MAX_MIGRATE_DOWNTIME_SECONDS)" seconds"); + return; + } + +-- +2.23.0 + diff --git a/migration-move-the-units-of-migrate-parameters-from-.patch b/migration-move-the-units-of-migrate-parameters-from-.patch new file mode 100644 index 0000000000000000000000000000000000000000..ae4d427598daeb8b2c82796c8ca4cbc5d418d2e5 --- /dev/null +++ b/migration-move-the-units-of-migrate-parameters-from-.patch @@ -0,0 +1,59 @@ +From 7ac5529afba7b4e9c4d9d1cbeb2b607208af97c1 Mon Sep 17 00:00:00 2001 +From: Mao Zhongyi +Date: Tue, 31 Mar 2020 16:22:07 +0800 +Subject: [PATCH 319/709] migration: move the units of migrate parameters from + milliseconds to ms + +Signed-off-by: Mao Zhongyi +Reviewed-by: Juan Quintela +Message-Id: <474bb6cf67defb8be9de5035c11aee57a680557a.1585641083.git.maozhongyi@cmss.chinamobile.com> +Reviewed-by: Stefano Garzarella +Signed-off-by: Dr. David Alan Gilbert +--- + migration/migration.c | 2 +- + monitor/hmp-cmds.c | 8 ++++---- + 2 files changed, 5 insertions(+), 5 deletions(-) + +diff --git a/migration/migration.c b/migration/migration.c +index 6e079efdcc..79f16f6625 100644 +--- a/migration/migration.c ++++ b/migration/migration.c +@@ -1214,7 +1214,7 @@ static bool migrate_params_check(MigrationParameters *params, Error **errp) + error_setg(errp, QERR_INVALID_PARAMETER_VALUE, + "downtime_limit", + "an integer in the range of 0 to " +- stringify(MAX_MIGRATE_DOWNTIME)" milliseconds"); ++ stringify(MAX_MIGRATE_DOWNTIME)" ms"); + return false; + } + +diff --git a/monitor/hmp-cmds.c b/monitor/hmp-cmds.c +index 9bb6946fbf..1552dee489 100644 +--- a/monitor/hmp-cmds.c ++++ b/monitor/hmp-cmds.c +@@ -231,18 +231,18 @@ void hmp_info_migrate(Monitor *mon, const QDict *qdict) + monitor_printf(mon, "\n"); + } + +- monitor_printf(mon, "total time: %" PRIu64 " milliseconds\n", ++ monitor_printf(mon, "total time: %" PRIu64 " ms\n", + info->total_time); + if (info->has_expected_downtime) { +- monitor_printf(mon, "expected downtime: %" PRIu64 " milliseconds\n", ++ monitor_printf(mon, "expected downtime: %" PRIu64 " ms\n", + info->expected_downtime); + } + if (info->has_downtime) { +- monitor_printf(mon, "downtime: %" PRIu64 " milliseconds\n", ++ monitor_printf(mon, "downtime: %" PRIu64 " ms\n", + info->downtime); + } + if (info->has_setup_time) { +- monitor_printf(mon, "setup: %" PRIu64 " milliseconds\n", ++ monitor_printf(mon, "setup: %" PRIu64 " ms\n", + info->setup_time); + } + } +-- +2.23.0 + diff --git a/migration-multifd-Do-error_free-after-migrate_set_er.patch b/migration-multifd-Do-error_free-after-migrate_set_er.patch new file mode 100644 index 0000000000000000000000000000000000000000..1f4b2292deba39b466a4ef40c5aed5b3c97e7b7d --- /dev/null +++ b/migration-multifd-Do-error_free-after-migrate_set_er.patch @@ -0,0 +1,83 @@ +From 13f2cb21e5fb33e9f8d7db8eee48edc1c67b812f Mon Sep 17 00:00:00 2001 +From: Pan Nengyuan +Date: Wed, 6 May 2020 05:54:16 -0400 +Subject: [PATCH 327/709] migration/multifd: Do error_free after + migrate_set_error to avoid memleaks + +When error happen in multifd_send_thread, it use error_copy to set migrate error in +multifd_send_terminate_threads(). We should call error_free after it. + +Similarly, fix another two places in multifd_recv_thread/multifd_save_cleanup. + +The leak stack: +Direct leak of 48 byte(s) in 1 object(s) allocated from: + #0 0x7f781af07cf0 in calloc (/lib64/libasan.so.5+0xefcf0) + #1 0x7f781a2ce22d in g_malloc0 (/lib64/libglib-2.0.so.0+0x5322d) + #2 0x55ee1d075c17 in error_setv /mnt/sdb/backup/qemu/util/error.c:61 + #3 0x55ee1d076464 in error_setg_errno_internal /mnt/sdb/backup/qemu/util/error.c:109 + #4 0x55ee1cef066e in qio_channel_socket_writev /mnt/sdb/backup/qemu/io/channel-socket.c:569 + #5 0x55ee1cee806b in qio_channel_writev /mnt/sdb/backup/qemu/io/channel.c:207 + #6 0x55ee1cee806b in qio_channel_writev_all /mnt/sdb/backup/qemu/io/channel.c:171 + #7 0x55ee1cee8248 in qio_channel_write_all /mnt/sdb/backup/qemu/io/channel.c:257 + #8 0x55ee1ca12c9a in multifd_send_thread /mnt/sdb/backup/qemu/migration/multifd.c:657 + #9 0x55ee1d0607fc in qemu_thread_start /mnt/sdb/backup/qemu/util/qemu-thread-posix.c:519 + #10 0x7f78159ae2dd in start_thread (/lib64/libpthread.so.0+0x82dd) + #11 0x7f78156df4b2 in __GI___clone (/lib64/libc.so.6+0xfc4b2) + +Indirect leak of 52 byte(s) in 1 object(s) allocated from: + #0 0x7f781af07f28 in __interceptor_realloc (/lib64/libasan.so.5+0xeff28) + #1 0x7f78156f07d9 in __GI___vasprintf_chk (/lib64/libc.so.6+0x10d7d9) + #2 0x7f781a30ea6c in g_vasprintf (/lib64/libglib-2.0.so.0+0x93a6c) + #3 0x7f781a2e7cd0 in g_strdup_vprintf (/lib64/libglib-2.0.so.0+0x6ccd0) + #4 0x7f781a2e7d8c in g_strdup_printf (/lib64/libglib-2.0.so.0+0x6cd8c) + #5 0x55ee1d075c86 in error_setv /mnt/sdb/backup/qemu/util/error.c:65 + #6 0x55ee1d076464 in error_setg_errno_internal /mnt/sdb/backup/qemu/util/error.c:109 + #7 0x55ee1cef066e in qio_channel_socket_writev /mnt/sdb/backup/qemu/io/channel-socket.c:569 + #8 0x55ee1cee806b in qio_channel_writev /mnt/sdb/backup/qemu/io/channel.c:207 + #9 0x55ee1cee806b in qio_channel_writev_all /mnt/sdb/backup/qemu/io/channel.c:171 + #10 0x55ee1cee8248 in qio_channel_write_all /mnt/sdb/backup/qemu/io/channel.c:257 + #11 0x55ee1ca12c9a in multifd_send_thread /mnt/sdb/backup/qemu/migration/multifd.c:657 + #12 0x55ee1d0607fc in qemu_thread_start /mnt/sdb/backup/qemu/util/qemu-thread-posix.c:519 + #13 0x7f78159ae2dd in start_thread (/lib64/libpthread.so.0+0x82dd) + #14 0x7f78156df4b2 in __GI___clone (/lib64/libc.so.6+0xfc4b2) + +Reported-by: Euler Robot +Signed-off-by: Pan Nengyuan +Message-Id: <20200506095416.26099-3-pannengyuan@huawei.com> +Reviewed-by: Juan Quintela +Signed-off-by: Dr. David Alan Gilbert +--- + migration/multifd.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/migration/multifd.c b/migration/multifd.c +index e3efd33a0d..5a3e4d0d46 100644 +--- a/migration/multifd.c ++++ b/migration/multifd.c +@@ -550,6 +550,7 @@ void multifd_save_cleanup(void) + multifd_send_state->ops->send_cleanup(p, &local_err); + if (local_err) { + migrate_set_error(migrate_get_current(), local_err); ++ error_free(local_err); + } + } + qemu_sem_destroy(&multifd_send_state->channels_ready); +@@ -688,6 +689,7 @@ out: + if (local_err) { + trace_multifd_send_error(p->id); + multifd_send_terminate_threads(local_err); ++ error_free(local_err); + } + + /* +@@ -965,6 +967,7 @@ static void *multifd_recv_thread(void *opaque) + + if (local_err) { + multifd_recv_terminate_threads(local_err); ++ error_free(local_err); + } + qemu_mutex_lock(&p->mutex); + p->running = false; +-- +2.23.0 + diff --git a/migration-multifd-fix-memleaks-in-multifd_new_send_c.patch b/migration-multifd-fix-memleaks-in-multifd_new_send_c.patch new file mode 100644 index 0000000000000000000000000000000000000000..3946068103a91a9380a4565fcf78e1475ba276de --- /dev/null +++ b/migration-multifd-fix-memleaks-in-multifd_new_send_c.patch @@ -0,0 +1,72 @@ +From ad31b8af73b8c5df62bd5c82fb543e44aa856cd4 Mon Sep 17 00:00:00 2001 +From: Pan Nengyuan +Date: Wed, 6 May 2020 05:54:15 -0400 +Subject: [PATCH 326/709] migration/multifd: fix memleaks in + multifd_new_send_channel_async + +When error happen in multifd_new_send_channel_async, 'sioc' will not be used +to create the multifd_send_thread. Let's free it to avoid a memleak. And also +do error_free after migrate_set_error() to avoid another leak in the same place. + +The leak stack: +Direct leak of 2880 byte(s) in 8 object(s) allocated from: + #0 0x7f20b5118ae8 in __interceptor_malloc (/lib64/libasan.so.5+0xefae8) + #1 0x7f20b44df1d5 in g_malloc (/lib64/libglib-2.0.so.0+0x531d5) + #2 0x564133bce18b in object_new_with_type /mnt/sdb/backup/qemu/qom/object.c:683 + #3 0x564133eea950 in qio_channel_socket_new /mnt/sdb/backup/qemu/io/channel-socket.c:56 + #4 0x5641339cfe4f in socket_send_channel_create /mnt/sdb/backup/qemu/migration/socket.c:37 + #5 0x564133a10328 in multifd_save_setup /mnt/sdb/backup/qemu/migration/multifd.c:772 + #6 0x5641339cebed in migrate_fd_connect /mnt/sdb/backup/qemu/migration/migration.c:3530 + #7 0x5641339d15e4 in migration_channel_connect /mnt/sdb/backup/qemu/migration/channel.c:92 + #8 0x5641339cf5b7 in socket_outgoing_migration /mnt/sdb/backup/qemu/migration/socket.c:108 + +Direct leak of 384 byte(s) in 8 object(s) allocated from: + #0 0x7f20b5118cf0 in calloc (/lib64/libasan.so.5+0xefcf0) + #1 0x7f20b44df22d in g_malloc0 (/lib64/libglib-2.0.so.0+0x5322d) + #2 0x56413406fc17 in error_setv /mnt/sdb/backup/qemu/util/error.c:61 + #3 0x564134070464 in error_setg_errno_internal /mnt/sdb/backup/qemu/util/error.c:109 + #4 0x5641340851be in inet_connect_addr /mnt/sdb/backup/qemu/util/qemu-sockets.c:379 + #5 0x5641340851be in inet_connect_saddr /mnt/sdb/backup/qemu/util/qemu-sockets.c:458 + #6 0x5641340870ab in socket_connect /mnt/sdb/backup/qemu/util/qemu-sockets.c:1105 + #7 0x564133eeaabf in qio_channel_socket_connect_sync /mnt/sdb/backup/qemu/io/channel-socket.c:145 + #8 0x564133eeabf5 in qio_channel_socket_connect_worker /mnt/sdb/backup/qemu/io/channel-socket.c:168 + +Indirect leak of 360 byte(s) in 8 object(s) allocated from: + #0 0x7f20b5118ae8 in __interceptor_malloc (/lib64/libasan.so.5+0xefae8) + #1 0x7f20af901817 in __GI___vasprintf_chk (/lib64/libc.so.6+0x10d817) + #2 0x7f20b451fa6c in g_vasprintf (/lib64/libglib-2.0.so.0+0x93a6c) + #3 0x7f20b44f8cd0 in g_strdup_vprintf (/lib64/libglib-2.0.so.0+0x6ccd0) + #4 0x7f20b44f8d8c in g_strdup_printf (/lib64/libglib-2.0.so.0+0x6cd8c) + #5 0x56413406fc86 in error_setv /mnt/sdb/backup/qemu/util/error.c:65 + #6 0x564134070464 in error_setg_errno_internal /mnt/sdb/backup/qemu/util/error.c:109 + #7 0x5641340851be in inet_connect_addr /mnt/sdb/backup/qemu/util/qemu-sockets.c:379 + #8 0x5641340851be in inet_connect_saddr /mnt/sdb/backup/qemu/util/qemu-sockets.c:458 + #9 0x5641340870ab in socket_connect /mnt/sdb/backup/qemu/util/qemu-sockets.c:1105 + #10 0x564133eeaabf in qio_channel_socket_connect_sync /mnt/sdb/backup/qemu/io/channel-socket.c:145 + #11 0x564133eeabf5 in qio_channel_socket_connect_worker /mnt/sdb/backup/qemu/io/channel-socket.c:168 + +Reported-by: Euler Robot +Signed-off-by: Pan Nengyuan +Message-Id: <20200506095416.26099-2-pannengyuan@huawei.com> +Reviewed-by: Juan Quintela +Signed-off-by: Dr. David Alan Gilbert +--- + migration/multifd.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/migration/multifd.c b/migration/multifd.c +index 9123c111a3..e3efd33a0d 100644 +--- a/migration/multifd.c ++++ b/migration/multifd.c +@@ -727,6 +727,8 @@ static void multifd_new_send_channel_async(QIOTask *task, gpointer opaque) + * its status. + */ + p->quit = true; ++ object_unref(OBJECT(sioc)); ++ error_free(local_err); + } else { + p->c = QIO_CHANNEL(sioc); + qio_channel_set_delay(p->c, false); +-- +2.23.0 + diff --git a/migration-ram-Consolidate-variable-reset-after-place.patch b/migration-ram-Consolidate-variable-reset-after-place.patch new file mode 100644 index 0000000000000000000000000000000000000000..0d111a5021fcab6f30acada122e99e96419da628 --- /dev/null +++ b/migration-ram-Consolidate-variable-reset-after-place.patch @@ -0,0 +1,73 @@ +From ddf35bdf0ab4282dfc6c326da98b54d84f140a68 Mon Sep 17 00:00:00 2001 +From: David Hildenbrand +Date: Tue, 21 Apr 2020 10:52:56 +0200 +Subject: [PATCH 323/709] migration/ram: Consolidate variable reset after + placement in ram_load_postcopy() + +Let's consolidate resetting the variables. + +Cc: "Dr. David Alan Gilbert" +Cc: Juan Quintela +Cc: Peter Xu +Signed-off-by: David Hildenbrand +Message-Id: <20200421085300.7734-10-david@redhat.com> +Reviewed-by: Dr. David Alan Gilbert +Signed-off-by: Dr. David Alan Gilbert + Fixup for context conflicts with 91ba442 +--- + migration/ram.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/migration/ram.c b/migration/ram.c +index 52fc032b83..08eb382f53 100644 +--- a/migration/ram.c ++++ b/migration/ram.c +@@ -3147,7 +3147,7 @@ static int ram_load_postcopy(QEMUFile *f) + /* Temporary page that is later 'placed' */ + void *postcopy_host_page = mis->postcopy_tmp_page; + void *this_host = NULL; +- bool all_zero = false; ++ bool all_zero = true; + int target_pages = 0; + + while (!ret && !(flags & RAM_SAVE_FLAG_EOS)) { +@@ -3174,7 +3174,6 @@ static int ram_load_postcopy(QEMUFile *f) + addr &= TARGET_PAGE_MASK; + + trace_ram_load_postcopy_loop((uint64_t)addr, flags); +- place_needed = false; + if (flags & (RAM_SAVE_FLAG_ZERO | RAM_SAVE_FLAG_PAGE | + RAM_SAVE_FLAG_COMPRESS_PAGE)) { + block = ram_block_from_stream(f, flags); +@@ -3199,9 +3198,7 @@ static int ram_load_postcopy(QEMUFile *f) + */ + page_buffer = postcopy_host_page + + ((uintptr_t)host & (block->page_size - 1)); +- /* If all TP are zero then we can optimise the place */ + if (target_pages == 1) { +- all_zero = true; + this_host = (void *)QEMU_ALIGN_DOWN((uintptr_t)host, + block->page_size); + } else { +@@ -3221,7 +3218,6 @@ static int ram_load_postcopy(QEMUFile *f) + */ + if (target_pages == (block->page_size / TARGET_PAGE_SIZE)) { + place_needed = true; +- target_pages = 0; + } + place_source = postcopy_host_page; + } +@@ -3303,6 +3299,10 @@ static int ram_load_postcopy(QEMUFile *f) + ret = postcopy_place_page(mis, place_dest, + place_source, block); + } ++ place_needed = false; ++ target_pages = 0; ++ /* Assume we have a zero page until we detect something different */ ++ all_zero = true; + } + } + +-- +2.23.0 + diff --git a/migration-rdma-fix-a-memleak-on-error-path-in-rdma_s.patch b/migration-rdma-fix-a-memleak-on-error-path-in-rdma_s.patch new file mode 100644 index 0000000000000000000000000000000000000000..6b23120c2d7c1faf5f79bd23d570ee19a411175b --- /dev/null +++ b/migration-rdma-fix-a-memleak-on-error-path-in-rdma_s.patch @@ -0,0 +1,46 @@ +From 59c59c67ee6b0327ae932deb303caa47919aeb1e Mon Sep 17 00:00:00 2001 +From: Pan Nengyuan +Date: Mon, 20 Apr 2020 06:27:27 -0400 +Subject: [PATCH 324/709] migration/rdma: fix a memleak on error path in + rdma_start_incoming_migration + +'rdma->host' is malloced in qemu_rdma_data_init, but forgot to free on the error +path in rdma_start_incoming_migration(), this patch fix that. + +The leak stack: +Direct leak of 2 byte(s) in 1 object(s) allocated from: + #0 0x7fb7add18ae8 in __interceptor_malloc (/lib64/libasan.so.5+0xefae8) + #1 0x7fb7ad0df1d5 in g_malloc (/lib64/libglib-2.0.so.0+0x531d5) + #2 0x7fb7ad0f8b32 in g_strdup (/lib64/libglib-2.0.so.0+0x6cb32) + #3 0x55a0464a0f6f in qemu_rdma_data_init /mnt/sdb/qemu/migration/rdma.c:2647 + #4 0x55a0464b0e76 in rdma_start_incoming_migration /mnt/sdb/qemu/migration/rdma.c:4020 + #5 0x55a0463f898a in qemu_start_incoming_migration /mnt/sdb/qemu/migration/migration.c:365 + #6 0x55a0458c75d3 in qemu_init /mnt/sdb/qemu/softmmu/vl.c:4438 + #7 0x55a046a3d811 in main /mnt/sdb/qemu/softmmu/main.c:48 + #8 0x7fb7a8417872 in __libc_start_main (/lib64/libc.so.6+0x23872) + #9 0x55a04536b26d in _start (/mnt/sdb/qemu/build/x86_64-softmmu/qemu-system-x86_64+0x286926d) + +Reported-by: Euler Robot +Signed-off-by: Pan Nengyuan +Message-Id: <20200420102727.17339-1-pannengyuan@huawei.com> +Reviewed-by: Dr. David Alan Gilbert +Signed-off-by: Dr. David Alan Gilbert +--- + migration/rdma.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/migration/rdma.c b/migration/rdma.c +index f61587891b..967fda5b0c 100644 +--- a/migration/rdma.c ++++ b/migration/rdma.c +@@ -4056,6 +4056,7 @@ void rdma_start_incoming_migration(const char *host_port, Error **errp) + return; + err: + error_propagate(errp, local_err); ++ g_free(rdma->host); + g_free(rdma); + g_free(rdma_return_path); + } +-- +2.23.0 + diff --git a/migration-throttle-Add-cpu-throttle-tailslow-migrati.patch b/migration-throttle-Add-cpu-throttle-tailslow-migrati.patch new file mode 100644 index 0000000000000000000000000000000000000000..ef621a81aa81bacf37ab91d9ac1dda912025df15 --- /dev/null +++ b/migration-throttle-Add-cpu-throttle-tailslow-migrati.patch @@ -0,0 +1,259 @@ +From cbbf818224faf5ede75c876e4900c9f8e6b6c0db Mon Sep 17 00:00:00 2001 +From: Keqian Zhu +Date: Mon, 13 Apr 2020 18:15:08 +0800 +Subject: [PATCH 322/709] migration/throttle: Add cpu-throttle-tailslow + migration parameter + +At the tail stage of throttling, the Guest is very sensitive to +CPU percentage while the @cpu-throttle-increment is excessive +usually at tail stage. + +If this parameter is true, we will compute the ideal CPU percentage +used by the Guest, which may exactly make the dirty rate match the +dirty rate threshold. Then we will choose a smaller throttle increment +between the one specified by @cpu-throttle-increment and the one +generated by ideal CPU percentage. + +Therefore, it is compatible to traditional throttling, meanwhile +the throttle increment won't be excessive at tail stage. This may +make migration time longer, and is disabled by default. + +Signed-off-by: Keqian Zhu +Message-Id: <20200413101508.54793-1-zhukeqian1@huawei.com> +Reviewed-by: Dr. David Alan Gilbert +Signed-off-by: Dr. David Alan Gilbert +--- + migration/migration.c | 13 ++++++++++++ + migration/ram.c | 25 +++++++++++++++++----- + monitor/hmp-cmds.c | 8 ++++++++ + qapi/migration.json | 48 +++++++++++++++++++++++++++++++++++++++++++ + 4 files changed, 89 insertions(+), 5 deletions(-) + +diff --git a/migration/migration.c b/migration/migration.c +index 79f16f6625..f5dbffc442 100644 +--- a/migration/migration.c ++++ b/migration/migration.c +@@ -785,6 +785,8 @@ MigrationParameters *qmp_query_migrate_parameters(Error **errp) + params->cpu_throttle_initial = s->parameters.cpu_throttle_initial; + params->has_cpu_throttle_increment = true; + params->cpu_throttle_increment = s->parameters.cpu_throttle_increment; ++ params->has_cpu_throttle_tailslow = true; ++ params->cpu_throttle_tailslow = s->parameters.cpu_throttle_tailslow; + params->has_tls_creds = true; + params->tls_creds = g_strdup(s->parameters.tls_creds); + params->has_tls_hostname = true; +@@ -1327,6 +1329,10 @@ static void migrate_params_test_apply(MigrateSetParameters *params, + dest->cpu_throttle_increment = params->cpu_throttle_increment; + } + ++ if (params->has_cpu_throttle_tailslow) { ++ dest->cpu_throttle_tailslow = params->cpu_throttle_tailslow; ++ } ++ + if (params->has_tls_creds) { + assert(params->tls_creds->type == QTYPE_QSTRING); + dest->tls_creds = g_strdup(params->tls_creds->u.s); +@@ -1415,6 +1421,10 @@ static void migrate_params_apply(MigrateSetParameters *params, Error **errp) + s->parameters.cpu_throttle_increment = params->cpu_throttle_increment; + } + ++ if (params->has_cpu_throttle_tailslow) { ++ s->parameters.cpu_throttle_tailslow = params->cpu_throttle_tailslow; ++ } ++ + if (params->has_tls_creds) { + g_free(s->parameters.tls_creds); + assert(params->tls_creds->type == QTYPE_QSTRING); +@@ -3597,6 +3607,8 @@ static Property migration_properties[] = { + DEFINE_PROP_UINT8("x-cpu-throttle-increment", MigrationState, + parameters.cpu_throttle_increment, + DEFAULT_MIGRATE_CPU_THROTTLE_INCREMENT), ++ DEFINE_PROP_BOOL("x-cpu-throttle-tailslow", MigrationState, ++ parameters.cpu_throttle_tailslow, false), + DEFINE_PROP_SIZE("x-max-bandwidth", MigrationState, + parameters.max_bandwidth, MAX_THROTTLE), + DEFINE_PROP_UINT64("x-downtime-limit", MigrationState, +@@ -3703,6 +3715,7 @@ static void migration_instance_init(Object *obj) + params->has_throttle_trigger_threshold = true; + params->has_cpu_throttle_initial = true; + params->has_cpu_throttle_increment = true; ++ params->has_cpu_throttle_tailslow = true; + params->has_max_bandwidth = true; + params->has_downtime_limit = true; + params->has_x_checkpoint_delay = true; +diff --git a/migration/ram.c b/migration/ram.c +index 53166fc279..52fc032b83 100644 +--- a/migration/ram.c ++++ b/migration/ram.c +@@ -616,20 +616,34 @@ static size_t save_page_header(RAMState *rs, QEMUFile *f, RAMBlock *block, + * able to complete migration. Some workloads dirty memory way too + * fast and will not effectively converge, even with auto-converge. + */ +-static void mig_throttle_guest_down(void) ++static void mig_throttle_guest_down(uint64_t bytes_dirty_period, ++ uint64_t bytes_dirty_threshold) + { + MigrationState *s = migrate_get_current(); + uint64_t pct_initial = s->parameters.cpu_throttle_initial; +- uint64_t pct_icrement = s->parameters.cpu_throttle_increment; ++ uint64_t pct_increment = s->parameters.cpu_throttle_increment; ++ bool pct_tailslow = s->parameters.cpu_throttle_tailslow; + int pct_max = s->parameters.max_cpu_throttle; + ++ uint64_t throttle_now = cpu_throttle_get_percentage(); ++ uint64_t cpu_now, cpu_ideal, throttle_inc; ++ + /* We have not started throttling yet. Let's start it. */ + if (!cpu_throttle_active()) { + cpu_throttle_set(pct_initial); + } else { + /* Throttling already on, just increase the rate */ +- cpu_throttle_set(MIN(cpu_throttle_get_percentage() + pct_icrement, +- pct_max)); ++ if (!pct_tailslow) { ++ throttle_inc = pct_increment; ++ } else { ++ /* Compute the ideal CPU percentage used by Guest, which may ++ * make the dirty rate match the dirty rate threshold. */ ++ cpu_now = 100 - throttle_now; ++ cpu_ideal = cpu_now * (bytes_dirty_threshold * 1.0 / ++ bytes_dirty_period); ++ throttle_inc = MIN(cpu_now - cpu_ideal, pct_increment); ++ } ++ cpu_throttle_set(MIN(throttle_now + throttle_inc, pct_max)); + } + } + +@@ -919,7 +933,8 @@ static void migration_trigger_throttle(RAMState *rs) + (++rs->dirty_rate_high_cnt >= 2)) { + trace_migration_throttle(); + rs->dirty_rate_high_cnt = 0; +- mig_throttle_guest_down(); ++ mig_throttle_guest_down(bytes_dirty_period, ++ bytes_dirty_threshold); + } + } + } +diff --git a/monitor/hmp-cmds.c b/monitor/hmp-cmds.c +index 1552dee489..ade1f85e0c 100644 +--- a/monitor/hmp-cmds.c ++++ b/monitor/hmp-cmds.c +@@ -420,6 +420,10 @@ void hmp_info_migrate_parameters(Monitor *mon, const QDict *qdict) + monitor_printf(mon, "%s: %u\n", + MigrationParameter_str(MIGRATION_PARAMETER_CPU_THROTTLE_INCREMENT), + params->cpu_throttle_increment); ++ assert(params->has_cpu_throttle_tailslow); ++ monitor_printf(mon, "%s: %s\n", ++ MigrationParameter_str(MIGRATION_PARAMETER_CPU_THROTTLE_TAILSLOW), ++ params->cpu_throttle_tailslow ? "on" : "off"); + assert(params->has_max_cpu_throttle); + monitor_printf(mon, "%s: %u\n", + MigrationParameter_str(MIGRATION_PARAMETER_MAX_CPU_THROTTLE), +@@ -1275,6 +1279,10 @@ void hmp_migrate_set_parameter(Monitor *mon, const QDict *qdict) + p->has_cpu_throttle_increment = true; + visit_type_int(v, param, &p->cpu_throttle_increment, &err); + break; ++ case MIGRATION_PARAMETER_CPU_THROTTLE_TAILSLOW: ++ p->has_cpu_throttle_tailslow = true; ++ visit_type_bool(v, param, &p->cpu_throttle_tailslow, &err); ++ break; + case MIGRATION_PARAMETER_MAX_CPU_THROTTLE: + p->has_max_cpu_throttle = true; + visit_type_int(v, param, &p->max_cpu_throttle, &err); +diff --git a/qapi/migration.json b/qapi/migration.json +index eca2981d0a..ee6c5a0cae 100644 +--- a/qapi/migration.json ++++ b/qapi/migration.json +@@ -552,6 +552,21 @@ + # auto-converge detects that migration is not making + # progress. The default value is 10. (Since 2.7) + # ++# @cpu-throttle-tailslow: Make CPU throttling slower at tail stage ++# At the tail stage of throttling, the Guest is very ++# sensitive to CPU percentage while the @cpu-throttle ++# -increment is excessive usually at tail stage. ++# If this parameter is true, we will compute the ideal ++# CPU percentage used by the Guest, which may exactly make ++# the dirty rate match the dirty rate threshold. Then we ++# will choose a smaller throttle increment between the ++# one specified by @cpu-throttle-increment and the one ++# generated by ideal CPU percentage. ++# Therefore, it is compatible to traditional throttling, ++# meanwhile the throttle increment won't be excessive ++# at tail stage. ++# The default value is false. (Since 5.1) ++# + # @tls-creds: ID of the 'tls-creds' object that provides credentials for + # establishing a TLS connection over the migration data channel. + # On the outgoing side of the migration, the credentials must +@@ -631,6 +646,7 @@ + 'compress-level', 'compress-threads', 'decompress-threads', + 'compress-wait-thread', 'throttle-trigger-threshold', + 'cpu-throttle-initial', 'cpu-throttle-increment', ++ 'cpu-throttle-tailslow', + 'tls-creds', 'tls-hostname', 'tls-authz', 'max-bandwidth', + 'downtime-limit', 'x-checkpoint-delay', 'block-incremental', + 'multifd-channels', +@@ -676,6 +692,21 @@ + # auto-converge detects that migration is not making + # progress. The default value is 10. (Since 2.7) + # ++# @cpu-throttle-tailslow: Make CPU throttling slower at tail stage ++# At the tail stage of throttling, the Guest is very ++# sensitive to CPU percentage while the @cpu-throttle ++# -increment is excessive usually at tail stage. ++# If this parameter is true, we will compute the ideal ++# CPU percentage used by the Guest, which may exactly make ++# the dirty rate match the dirty rate threshold. Then we ++# will choose a smaller throttle increment between the ++# one specified by @cpu-throttle-increment and the one ++# generated by ideal CPU percentage. ++# Therefore, it is compatible to traditional throttling, ++# meanwhile the throttle increment won't be excessive ++# at tail stage. ++# The default value is false. (Since 5.1) ++# + # @tls-creds: ID of the 'tls-creds' object that provides credentials + # for establishing a TLS connection over the migration data + # channel. On the outgoing side of the migration, the credentials +@@ -763,6 +794,7 @@ + '*throttle-trigger-threshold': 'int', + '*cpu-throttle-initial': 'int', + '*cpu-throttle-increment': 'int', ++ '*cpu-throttle-tailslow': 'bool', + '*tls-creds': 'StrOrNull', + '*tls-hostname': 'StrOrNull', + '*tls-authz': 'StrOrNull', +@@ -834,6 +866,21 @@ + # auto-converge detects that migration is not making + # progress. (Since 2.7) + # ++# @cpu-throttle-tailslow: Make CPU throttling slower at tail stage ++# At the tail stage of throttling, the Guest is very ++# sensitive to CPU percentage while the @cpu-throttle ++# -increment is excessive usually at tail stage. ++# If this parameter is true, we will compute the ideal ++# CPU percentage used by the Guest, which may exactly make ++# the dirty rate match the dirty rate threshold. Then we ++# will choose a smaller throttle increment between the ++# one specified by @cpu-throttle-increment and the one ++# generated by ideal CPU percentage. ++# Therefore, it is compatible to traditional throttling, ++# meanwhile the throttle increment won't be excessive ++# at tail stage. ++# The default value is false. (Since 5.1) ++# + # @tls-creds: ID of the 'tls-creds' object that provides credentials + # for establishing a TLS connection over the migration data + # channel. On the outgoing side of the migration, the credentials +@@ -921,6 +968,7 @@ + '*throttle-trigger-threshold': 'uint8', + '*cpu-throttle-initial': 'uint8', + '*cpu-throttle-increment': 'uint8', ++ '*cpu-throttle-tailslow': 'bool', + '*tls-creds': 'str', + '*tls-hostname': 'str', + '*tls-authz': 'str', +-- +2.23.0 + diff --git a/migration-xbzrle-add-encoding-rate.patch b/migration-xbzrle-add-encoding-rate.patch new file mode 100644 index 0000000000000000000000000000000000000000..f8ab2b3e941da7307652108c0cdf17421797f9e1 --- /dev/null +++ b/migration-xbzrle-add-encoding-rate.patch @@ -0,0 +1,160 @@ +From e460a4b1a4c0e0aeea2c56bfc2407a9a1d1a3ae2 Mon Sep 17 00:00:00 2001 +From: Wei Wang +Date: Thu, 30 Apr 2020 08:59:35 +0800 +Subject: [PATCH 325/709] migration/xbzrle: add encoding rate + +Users may need to check the xbzrle encoding rate to know if the guest +memory is xbzrle encoding-friendly, and dynamically turn off the +encoding if the encoding rate is low. + +Signed-off-by: Yi Sun +Signed-off-by: Wei Wang +Message-Id: <1588208375-19556-1-git-send-email-wei.w.wang@intel.com> +Reviewed-by: Dr. David Alan Gilbert +Signed-off-by: Dr. David Alan Gilbert +--- + migration/migration.c | 1 + + migration/ram.c | 39 +++++++++++++++++++++++++++++++++++++-- + monitor/hmp-cmds.c | 2 ++ + qapi/migration.json | 5 ++++- + 4 files changed, 44 insertions(+), 3 deletions(-) + +diff --git a/migration/migration.c b/migration/migration.c +index f5dbffc442..0bb042a0f7 100644 +--- a/migration/migration.c ++++ b/migration/migration.c +@@ -932,6 +932,7 @@ static void populate_ram_info(MigrationInfo *info, MigrationState *s) + info->xbzrle_cache->pages = xbzrle_counters.pages; + info->xbzrle_cache->cache_miss = xbzrle_counters.cache_miss; + info->xbzrle_cache->cache_miss_rate = xbzrle_counters.cache_miss_rate; ++ info->xbzrle_cache->encoding_rate = xbzrle_counters.encoding_rate; + info->xbzrle_cache->overflow = xbzrle_counters.overflow; + } + +diff --git a/migration/ram.c b/migration/ram.c +index 08eb382f53..859f835f1a 100644 +--- a/migration/ram.c ++++ b/migration/ram.c +@@ -327,6 +327,10 @@ struct RAMState { + uint64_t num_dirty_pages_period; + /* xbzrle misses since the beginning of the period */ + uint64_t xbzrle_cache_miss_prev; ++ /* Amount of xbzrle pages since the beginning of the period */ ++ uint64_t xbzrle_pages_prev; ++ /* Amount of xbzrle encoded bytes since the beginning of the period */ ++ uint64_t xbzrle_bytes_prev; + + /* compression statistics since the beginning of the period */ + /* amount of count that no free thread to compress data */ +@@ -710,6 +714,18 @@ static int save_xbzrle_page(RAMState *rs, uint8_t **current_data, + return -1; + } + ++ /* ++ * Reaching here means the page has hit the xbzrle cache, no matter what ++ * encoding result it is (normal encoding, overflow or skipping the page), ++ * count the page as encoded. This is used to caculate the encoding rate. ++ * ++ * Example: 2 pages (8KB) being encoded, first page encoding generates 2KB, ++ * 2nd page turns out to be skipped (i.e. no new bytes written to the ++ * page), the overall encoding rate will be 8KB / 2KB = 4, which has the ++ * skipped page included. In this way, the encoding rate can tell if the ++ * guest page is good for xbzrle encoding. ++ */ ++ xbzrle_counters.pages++; + prev_cached_page = get_cached_data(XBZRLE.cache, current_addr); + + /* save current buffer into memory */ +@@ -740,6 +756,7 @@ static int save_xbzrle_page(RAMState *rs, uint8_t **current_data, + } else if (encoded_len == -1) { + trace_save_xbzrle_page_overflow(); + xbzrle_counters.overflow++; ++ xbzrle_counters.bytes += TARGET_PAGE_SIZE; + return -1; + } + +@@ -750,8 +767,12 @@ static int save_xbzrle_page(RAMState *rs, uint8_t **current_data, + qemu_put_be16(rs->f, encoded_len); + qemu_put_buffer(rs->f, XBZRLE.encoded_buf, encoded_len); + bytes_xbzrle += encoded_len + 1 + 2; +- xbzrle_counters.pages++; +- xbzrle_counters.bytes += bytes_xbzrle; ++ /* ++ * Like compressed_size (please see update_compress_thread_counts), ++ * the xbzrle encoded bytes don't count the 8 byte header with ++ * RAM_SAVE_FLAG_CONTINUE. ++ */ ++ xbzrle_counters.bytes += bytes_xbzrle - 8; + ram_counters.transferred += bytes_xbzrle; + + return 1; +@@ -884,9 +905,23 @@ static void migration_update_rates(RAMState *rs, int64_t end_time) + } + + if (migrate_use_xbzrle()) { ++ double encoded_size, unencoded_size; ++ + xbzrle_counters.cache_miss_rate = (double)(xbzrle_counters.cache_miss - + rs->xbzrle_cache_miss_prev) / page_count; + rs->xbzrle_cache_miss_prev = xbzrle_counters.cache_miss; ++ unencoded_size = (xbzrle_counters.pages - rs->xbzrle_pages_prev) * ++ TARGET_PAGE_SIZE; ++ encoded_size = xbzrle_counters.bytes - rs->xbzrle_bytes_prev; ++ if (xbzrle_counters.pages == rs->xbzrle_pages_prev) { ++ xbzrle_counters.encoding_rate = 0; ++ } else if (!encoded_size) { ++ xbzrle_counters.encoding_rate = UINT64_MAX; ++ } else { ++ xbzrle_counters.encoding_rate = unencoded_size / encoded_size; ++ } ++ rs->xbzrle_pages_prev = xbzrle_counters.pages; ++ rs->xbzrle_bytes_prev = xbzrle_counters.bytes; + } + + if (migrate_use_compression()) { +diff --git a/monitor/hmp-cmds.c b/monitor/hmp-cmds.c +index ade1f85e0c..9c61e769ca 100644 +--- a/monitor/hmp-cmds.c ++++ b/monitor/hmp-cmds.c +@@ -303,6 +303,8 @@ void hmp_info_migrate(Monitor *mon, const QDict *qdict) + info->xbzrle_cache->cache_miss); + monitor_printf(mon, "xbzrle cache miss rate: %0.2f\n", + info->xbzrle_cache->cache_miss_rate); ++ monitor_printf(mon, "xbzrle encoding rate: %0.2f\n", ++ info->xbzrle_cache->encoding_rate); + monitor_printf(mon, "xbzrle overflow: %" PRIu64 "\n", + info->xbzrle_cache->overflow); + } +diff --git a/qapi/migration.json b/qapi/migration.json +index ee6c5a0cae..d5000558c6 100644 +--- a/qapi/migration.json ++++ b/qapi/migration.json +@@ -70,6 +70,8 @@ + # + # @cache-miss-rate: rate of cache miss (since 2.1) + # ++# @encoding-rate: rate of encoded bytes (since 5.1) ++# + # @overflow: number of overflows + # + # Since: 1.2 +@@ -77,7 +79,7 @@ + { 'struct': 'XBZRLECacheStats', + 'data': {'cache-size': 'int', 'bytes': 'int', 'pages': 'int', + 'cache-miss': 'int', 'cache-miss-rate': 'number', +- 'overflow': 'int' } } ++ 'encoding-rate': 'number', 'overflow': 'int' } } + + ## + # @CompressionStats: +@@ -337,6 +339,7 @@ + # "pages":2444343, + # "cache-miss":2244, + # "cache-miss-rate":0.123, ++# "encoding-rate":80.1, + # "overflow":34434 + # } + # } +-- +2.23.0 + diff --git a/mirror-Make-sure-that-source-and-target-size-match.patch b/mirror-Make-sure-that-source-and-target-size-match.patch new file mode 100644 index 0000000000000000000000000000000000000000..a76f856c3bf1496f2f0f1b09fc18540c964e7122 --- /dev/null +++ b/mirror-Make-sure-that-source-and-target-size-match.patch @@ -0,0 +1,77 @@ +From e83dd6808c6e0975970f37b49b27cc37bb54eea8 Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Mon, 11 May 2020 15:58:24 +0200 +Subject: [PATCH 523/709] mirror: Make sure that source and target size match + +If the target is shorter than the source, mirror would copy data until +it reaches the end of the target and then fail with an I/O error when +trying to write past the end. + +If the target is longer than the source, the mirror job would complete +successfully, but the target wouldn't actually be an accurate copy of +the source image (it would contain some additional garbage at the end). + +Fix this by checking that both images have the same size when the job +starts. + +Signed-off-by: Kevin Wolf +Reviewed-by: Eric Blake +Message-Id: <20200511135825.219437-4-kwolf@redhat.com> +Reviewed-by: Max Reitz +Reviewed-by: Vladimir Sementsov-Ogievskiy +Signed-off-by: Kevin Wolf +--- + block/mirror.c | 21 ++++++++++++--------- + 1 file changed, 12 insertions(+), 9 deletions(-) + +diff --git a/block/mirror.c b/block/mirror.c +index aca95c9bc9..201ffa26f9 100644 +--- a/block/mirror.c ++++ b/block/mirror.c +@@ -872,6 +872,7 @@ static int coroutine_fn mirror_run(Job *job, Error **errp) + BlockDriverState *target_bs = blk_bs(s->target); + bool need_drain = true; + int64_t length; ++ int64_t target_length; + BlockDriverInfo bdi; + char backing_filename[2]; /* we only need 2 characters because we are only + checking for a NULL string */ +@@ -887,24 +888,26 @@ static int coroutine_fn mirror_run(Job *job, Error **errp) + goto immediate_exit; + } + ++ target_length = blk_getlength(s->target); ++ if (target_length < 0) { ++ ret = target_length; ++ goto immediate_exit; ++ } ++ + /* Active commit must resize the base image if its size differs from the + * active layer. */ + if (s->base == blk_bs(s->target)) { +- int64_t base_length; +- +- base_length = blk_getlength(s->target); +- if (base_length < 0) { +- ret = base_length; +- goto immediate_exit; +- } +- +- if (s->bdev_length > base_length) { ++ if (s->bdev_length > target_length) { + ret = blk_truncate(s->target, s->bdev_length, false, + PREALLOC_MODE_OFF, 0, NULL); + if (ret < 0) { + goto immediate_exit; + } + } ++ } else if (s->bdev_length != target_length) { ++ error_setg(errp, "Source and target image have different sizes"); ++ ret = -EINVAL; ++ goto immediate_exit; + } + + if (s->bdev_length == 0) { +-- +2.23.0 + diff --git a/mirror-Only-mirror-granularity-aligned-chunks.patch b/mirror-Only-mirror-granularity-aligned-chunks.patch deleted file mode 100644 index 17a87ee2a9a4c29f6b451b2b216b14413e3876e9..0000000000000000000000000000000000000000 --- a/mirror-Only-mirror-granularity-aligned-chunks.patch +++ /dev/null @@ -1,84 +0,0 @@ -From d65d02614b6b0f6bcc64cd2a737b5204c0fc5304 Mon Sep 17 00:00:00 2001 -From: Max Reitz -Date: Mon, 5 Aug 2019 17:33:08 +0200 -Subject: [PATCH] mirror: Only mirror granularity-aligned chunks - -In write-blocking mode, all writes to the top node directly go to the -target. We must only mirror chunks of data that are aligned to the -job's granularity, because that is how the dirty bitmap works. -Therefore, the request alignment for writes must be the job's -granularity (in write-blocking mode). - -Unfortunately, this forces all reads and writes to have the same -granularity (we only need this alignment for writes to the target, not -the source), but that is something to be fixed another time. - -Cc: qemu-stable@nongnu.org -Signed-off-by: Max Reitz -Message-id: 20190805153308.2657-1-mreitz@redhat.com -Reviewed-by: Vladimir Sementsov-Ogievskiy -Fixes: d06107ade0ce74dc39739bac80de84b51ec18546 -Signed-off-by: Max Reitz -(cherry picked from commit 9adc1cb49af8d4e54f57980b1eed5c0a4b2dafa6) -Signed-off-by: Michael Roth ---- - block/mirror.c | 29 +++++++++++++++++++++++++++++ - 1 file changed, 29 insertions(+) - -diff --git a/block/mirror.c b/block/mirror.c -index ff15cfb197..062dc42867 100644 ---- a/block/mirror.c -+++ b/block/mirror.c -@@ -1477,6 +1477,15 @@ static void bdrv_mirror_top_child_perm(BlockDriverState *bs, BdrvChild *c, - *nshared = BLK_PERM_ALL; - } - -+static void bdrv_mirror_top_refresh_limits(BlockDriverState *bs, Error **errp) -+{ -+ MirrorBDSOpaque *s = bs->opaque; -+ -+ if (s && s->job && s->job->copy_mode == MIRROR_COPY_MODE_WRITE_BLOCKING) { -+ bs->bl.request_alignment = s->job->granularity; -+ } -+} -+ - /* Dummy node that provides consistent read to its users without requiring it - * from its backing file and that allows writes on the backing file chain. */ - static BlockDriver bdrv_mirror_top = { -@@ -1489,6 +1498,7 @@ static BlockDriver bdrv_mirror_top = { - .bdrv_co_block_status = bdrv_co_block_status_from_backing, - .bdrv_refresh_filename = bdrv_mirror_top_refresh_filename, - .bdrv_child_perm = bdrv_mirror_top_child_perm, -+ .bdrv_refresh_limits = bdrv_mirror_top_refresh_limits, - }; - - static void mirror_start_job(const char *job_id, BlockDriverState *bs, -@@ -1627,6 +1637,25 @@ static void mirror_start_job(const char *job_id, BlockDriverState *bs, - s->should_complete = true; - } - -+ /* -+ * Must be called before we start tracking writes, but after -+ * -+ * ((MirrorBlockJob *) -+ * ((MirrorBDSOpaque *) -+ * mirror_top_bs->opaque -+ * )->job -+ * )->copy_mode -+ * -+ * has the correct value. -+ * (We start tracking writes as of the following -+ * bdrv_create_dirty_bitmap() call.) -+ */ -+ bdrv_refresh_limits(mirror_top_bs, &local_err); -+ if (local_err) { -+ error_propagate(errp, local_err); -+ goto fail; -+ } -+ - s->dirty_bitmap = bdrv_create_dirty_bitmap(bs, granularity, NULL, errp); - if (!s->dirty_bitmap) { - goto fail; --- -2.19.1 - diff --git a/monitor-hmp-cmds-add-hmp_handle_error-for-hmp_migrat.patch b/monitor-hmp-cmds-add-hmp_handle_error-for-hmp_migrat.patch new file mode 100644 index 0000000000000000000000000000000000000000..2763d062ed790ce8911f4747fd976ce9119b4305 --- /dev/null +++ b/monitor-hmp-cmds-add-hmp_handle_error-for-hmp_migrat.patch @@ -0,0 +1,34 @@ +From f96c6a8736517af2a2d9e1fae3c1368d5b9adc4a Mon Sep 17 00:00:00 2001 +From: Mao Zhongyi +Date: Tue, 31 Mar 2020 16:22:06 +0800 +Subject: [PATCH 318/709] monitor/hmp-cmds: add hmp_handle_error() for + hmp_migrate_set_speed() + +Signed-off-by: Mao Zhongyi +Reviewed-by: Juan Quintela +Message-Id: <305323f835436023c53d759f5ab18af3ec874183.1585641083.git.maozhongyi@cmss.chinamobile.com> +Signed-off-by: Dr. David Alan Gilbert +--- + monitor/hmp-cmds.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/monitor/hmp-cmds.c b/monitor/hmp-cmds.c +index 7f6e982dc8..9bb6946fbf 100644 +--- a/monitor/hmp-cmds.c ++++ b/monitor/hmp-cmds.c +@@ -1198,8 +1198,11 @@ void hmp_migrate_set_cache_size(Monitor *mon, const QDict *qdict) + /* Kept for backwards compatibility */ + void hmp_migrate_set_speed(Monitor *mon, const QDict *qdict) + { ++ Error *err = NULL; ++ + int64_t value = qdict_get_int(qdict, "value"); +- qmp_migrate_set_speed(value, NULL); ++ qmp_migrate_set_speed(value, &err); ++ hmp_handle_error(mon, err); + } + + void hmp_migrate_set_capability(Monitor *mon, const QDict *qdict) +-- +2.23.0 + diff --git a/move-typedef-Aml-to-qemu-types.h.patch b/move-typedef-Aml-to-qemu-types.h.patch new file mode 100644 index 0000000000000000000000000000000000000000..10dcde6de660f1a0df9f5cae4159da4c18abc3f1 --- /dev/null +++ b/move-typedef-Aml-to-qemu-types.h.patch @@ -0,0 +1,46 @@ +From 0f8d656b3b8ef31ebfbd4a24003d9a58d987a605 Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann +Date: Wed, 29 Apr 2020 15:59:49 +0200 +Subject: [PATCH 206/709] move 'typedef Aml' to qemu/types.h +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Gerd Hoffmann +Reviewed-by: Igor Mammedov +Message-Id: <20200429140003.7336-2-kraxel@redhat.com> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +Reviewed-by: Philippe Mathieu-Daudé +--- + include/hw/acpi/aml-build.h | 1 - + include/qemu/typedefs.h | 1 + + 2 files changed, 1 insertion(+), 1 deletion(-) + +diff --git a/include/hw/acpi/aml-build.h b/include/hw/acpi/aml-build.h +index 0f4ed53d7f..1539fe0667 100644 +--- a/include/hw/acpi/aml-build.h ++++ b/include/hw/acpi/aml-build.h +@@ -33,7 +33,6 @@ struct Aml { + uint8_t op; + AmlBlockFlags block_flags; + }; +-typedef struct Aml Aml; + + typedef enum { + AML_COMPATIBILITY = 0, +diff --git a/include/qemu/typedefs.h b/include/qemu/typedefs.h +index 375770a80f..ecf3cde26c 100644 +--- a/include/qemu/typedefs.h ++++ b/include/qemu/typedefs.h +@@ -24,6 +24,7 @@ + typedef struct AdapterInfo AdapterInfo; + typedef struct AddressSpace AddressSpace; + typedef struct AioContext AioContext; ++typedef struct Aml Aml; + typedef struct AnnounceTimer AnnounceTimer; + typedef struct BdrvDirtyBitmap BdrvDirtyBitmap; + typedef struct BdrvDirtyBitmapIter BdrvDirtyBitmapIter; +-- +2.23.0 + diff --git a/msf2-Add-EMAC-block-to-SmartFusion2-SoC.patch b/msf2-Add-EMAC-block-to-SmartFusion2-SoC.patch new file mode 100644 index 0000000000000000000000000000000000000000..c779bd116c7bf6ad656419a25fefa0f6ace1f192 --- /dev/null +++ b/msf2-Add-EMAC-block-to-SmartFusion2-SoC.patch @@ -0,0 +1,114 @@ +From 05b7374a58cd18aa3516e33513808896d0ac9b7b Mon Sep 17 00:00:00 2001 +From: Subbaraya Sundeep +Date: Thu, 16 Apr 2020 20:24:50 +0530 +Subject: [PATCH 100/709] msf2: Add EMAC block to SmartFusion2 SoC +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +With SmartFusion2 Ethernet MAC model in +place this patch adds the same to SoC. + +Signed-off-by: Subbaraya Sundeep +Reviewed-by: Philippe Mathieu-Daudé +Tested-by: Philippe Mathieu-Daudé +Message-id: 1587048891-30493-3-git-send-email-sundeep.lkml@gmail.com +Signed-off-by: Peter Maydell +--- + hw/arm/msf2-soc.c | 26 ++++++++++++++++++++++++-- + include/hw/arm/msf2-soc.h | 2 ++ + 2 files changed, 26 insertions(+), 2 deletions(-) + +diff --git a/hw/arm/msf2-soc.c b/hw/arm/msf2-soc.c +index 588d643b8d..a455b8831f 100644 +--- a/hw/arm/msf2-soc.c ++++ b/hw/arm/msf2-soc.c +@@ -1,7 +1,7 @@ + /* + * SmartFusion2 SoC emulation. + * +- * Copyright (c) 2017 Subbaraya Sundeep ++ * Copyright (c) 2017-2020 Subbaraya Sundeep + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal +@@ -35,11 +35,14 @@ + + #define MSF2_TIMER_BASE 0x40004000 + #define MSF2_SYSREG_BASE 0x40038000 ++#define MSF2_EMAC_BASE 0x40041000 + + #define ENVM_BASE_ADDRESS 0x60000000 + + #define SRAM_BASE_ADDRESS 0x20000000 + ++#define MSF2_EMAC_IRQ 12 ++ + #define MSF2_ENVM_MAX_SIZE (512 * KiB) + + /* +@@ -81,6 +84,13 @@ static void m2sxxx_soc_initfn(Object *obj) + sysbus_init_child_obj(obj, "spi[*]", &s->spi[i], sizeof(s->spi[i]), + TYPE_MSS_SPI); + } ++ ++ sysbus_init_child_obj(obj, "emac", &s->emac, sizeof(s->emac), ++ TYPE_MSS_EMAC); ++ if (nd_table[0].used) { ++ qemu_check_nic_model(&nd_table[0], TYPE_MSS_EMAC); ++ qdev_set_nic_properties(DEVICE(&s->emac), &nd_table[0]); ++ } + } + + static void m2sxxx_soc_realize(DeviceState *dev_soc, Error **errp) +@@ -192,6 +202,19 @@ static void m2sxxx_soc_realize(DeviceState *dev_soc, Error **errp) + g_free(bus_name); + } + ++ dev = DEVICE(&s->emac); ++ object_property_set_link(OBJECT(&s->emac), OBJECT(get_system_memory()), ++ "ahb-bus", &error_abort); ++ object_property_set_bool(OBJECT(&s->emac), true, "realized", &err); ++ if (err != NULL) { ++ error_propagate(errp, err); ++ return; ++ } ++ busdev = SYS_BUS_DEVICE(dev); ++ sysbus_mmio_map(busdev, 0, MSF2_EMAC_BASE); ++ sysbus_connect_irq(busdev, 0, ++ qdev_get_gpio_in(armv7m, MSF2_EMAC_IRQ)); ++ + /* Below devices are not modelled yet. */ + create_unimplemented_device("i2c_0", 0x40002000, 0x1000); + create_unimplemented_device("dma", 0x40003000, 0x1000); +@@ -202,7 +225,6 @@ static void m2sxxx_soc_realize(DeviceState *dev_soc, Error **errp) + create_unimplemented_device("can", 0x40015000, 0x1000); + create_unimplemented_device("rtc", 0x40017000, 0x1000); + create_unimplemented_device("apb_config", 0x40020000, 0x10000); +- create_unimplemented_device("emac", 0x40041000, 0x1000); + create_unimplemented_device("usb", 0x40043000, 0x1000); + } + +diff --git a/include/hw/arm/msf2-soc.h b/include/hw/arm/msf2-soc.h +index 3cfe5c76ee..c9cb214aa6 100644 +--- a/include/hw/arm/msf2-soc.h ++++ b/include/hw/arm/msf2-soc.h +@@ -29,6 +29,7 @@ + #include "hw/timer/mss-timer.h" + #include "hw/misc/msf2-sysreg.h" + #include "hw/ssi/mss-spi.h" ++#include "hw/net/msf2-emac.h" + + #define TYPE_MSF2_SOC "msf2-soc" + #define MSF2_SOC(obj) OBJECT_CHECK(MSF2State, (obj), TYPE_MSF2_SOC) +@@ -62,6 +63,7 @@ typedef struct MSF2State { + MSF2SysregState sysreg; + MSSTimerState timer; + MSSSpiState spi[MSF2_NUM_SPIS]; ++ MSF2EmacState emac; + } MSF2State; + + #endif +-- +2.23.0 + diff --git a/nbd-fix-uninitialized-variable-warning.patch b/nbd-fix-uninitialized-variable-warning.patch deleted file mode 100644 index be69252807d1a7fbd5be7e8e6d187862527c439d..0000000000000000000000000000000000000000 --- a/nbd-fix-uninitialized-variable-warning.patch +++ /dev/null @@ -1,46 +0,0 @@ -From eb5abb631196b97879a868ec75e7f70400695f7f Mon Sep 17 00:00:00 2001 -From: Pan Nengyuan -Date: Mon, 13 Jan 2020 17:03:08 +0800 -Subject: [PATCH] nbd: fix uninitialized variable warning - -Fixes: -/mnt/sdb/qemu/nbd/server.c: In function 'nbd_handle_request': -/mnt/sdb/qemu/nbd/server.c:2313:9: error: 'ret' may be used uninitialized in this function [-Werror=maybe-uninitialized] - int ret; - -Reported-by: Euler Robot -Signed-off-by: Pan Nengyuan ---- - nbd/server.c | 10 +--------- - 1 file changed, 1 insertion(+), 9 deletions(-) - -diff --git a/nbd/server.c b/nbd/server.c -index e21bd501..aefb07d9 100644 ---- a/nbd/server.c -+++ b/nbd/server.c -@@ -2304,20 +2304,12 @@ static coroutine_fn int nbd_handle_request(NBDClient *client, - !client->export_meta.bitmap, - NBD_META_ID_BASE_ALLOCATION, - errp); -- if (ret < 0) { -- return ret; -- } -- } -- -- if (client->export_meta.bitmap) { -+ } else { /* client->export_meta.bitmap */ - ret = nbd_co_send_bitmap(client, request->handle, - client->exp->export_bitmap, - request->from, request->len, - dont_fragment, - true, NBD_META_ID_DIRTY_BITMAP, errp); -- if (ret < 0) { -- return ret; -- } - } - - return ret; --- -2.18.1 - - diff --git a/net-cadence_gem-clear-RX-control-descriptor.patch b/net-cadence_gem-clear-RX-control-descriptor.patch new file mode 100644 index 0000000000000000000000000000000000000000..3742b7a2367694c98e660937a588fa4343e4c0b0 --- /dev/null +++ b/net-cadence_gem-clear-RX-control-descriptor.patch @@ -0,0 +1,52 @@ +From 59ab136a9e24f989cb7922d9cf7d1774fc497a78 Mon Sep 17 00:00:00 2001 +From: Ramon Fried +Date: Sat, 18 Apr 2020 11:51:45 +0300 +Subject: [PATCH 113/709] net: cadence_gem: clear RX control descriptor +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The RX ring descriptors control field is used for setting +SOF and EOF (start of frame and end of frame). +The SOF and EOF weren't cleared from the previous descriptors, +causing inconsistencies in ring buffer. +Fix that by clearing the control field of every descriptors we're +processing. + +Signed-off-by: Ramon Fried +Reviewed-by: Philippe Mathieu-Daudé +Reviewed-by: Edgar E. Iglesias +Message-id: 20200418085145.489726-1-rfried.dev@gmail.com +Signed-off-by: Peter Maydell +--- + hw/net/cadence_gem.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/hw/net/cadence_gem.c b/hw/net/cadence_gem.c +index b7b7985bf2..22a0b1b1f9 100644 +--- a/hw/net/cadence_gem.c ++++ b/hw/net/cadence_gem.c +@@ -411,6 +411,11 @@ static inline void rx_desc_set_sof(uint32_t *desc) + desc[1] |= DESC_1_RX_SOF; + } + ++static inline void rx_desc_clear_control(uint32_t *desc) ++{ ++ desc[1] = 0; ++} ++ + static inline void rx_desc_set_eof(uint32_t *desc) + { + desc[1] |= DESC_1_RX_EOF; +@@ -999,6 +1004,8 @@ static ssize_t gem_receive(NetClientState *nc, const uint8_t *buf, size_t size) + rxbuf_ptr += MIN(bytes_to_copy, rxbufsize); + bytes_to_copy -= MIN(bytes_to_copy, rxbufsize); + ++ rx_desc_clear_control(s->rx_desc[q]); ++ + /* Update the descriptor. */ + if (first_desc) { + rx_desc_set_sof(s->rx_desc[q]); +-- +2.23.0 + diff --git a/nfs-Support-BDRV_REQ_ZERO_WRITE-for-truncate.patch b/nfs-Support-BDRV_REQ_ZERO_WRITE-for-truncate.patch new file mode 100644 index 0000000000000000000000000000000000000000..a025cb180197609c888f672b3af97666592628d7 --- /dev/null +++ b/nfs-Support-BDRV_REQ_ZERO_WRITE-for-truncate.patch @@ -0,0 +1,34 @@ +From 8f23aaf5d6a5458e251c5d5d0555d9e515355e35 Mon Sep 17 00:00:00 2001 +From: Eric Blake +Date: Tue, 28 Apr 2020 15:28:59 -0500 +Subject: [PATCH 351/709] nfs: Support BDRV_REQ_ZERO_WRITE for truncate + +Our .bdrv_has_zero_init_truncate returns 1 if we detect that the OS +always 0-fills; we can use that same knowledge to implement +BDRV_REQ_ZERO_WRITE by ignoring it when the OS gives it to us for +free. + +Signed-off-by: Eric Blake +Message-Id: <20200428202905.770727-4-eblake@redhat.com> +Signed-off-by: Kevin Wolf +--- + block/nfs.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/block/nfs.c b/block/nfs.c +index 385d756e1d..76daa7c9f6 100644 +--- a/block/nfs.c ++++ b/block/nfs.c +@@ -620,6 +620,9 @@ static int nfs_file_open(BlockDriverState *bs, QDict *options, int flags, + } + + bs->total_sectors = ret; ++ if (client->has_zero_init) { ++ bs->supported_truncate_flags = BDRV_REQ_ZERO_WRITE; ++ } + return 0; + } + +-- +2.23.0 + diff --git a/nrf51-Fix-last-GPIO-CNF-address.patch b/nrf51-Fix-last-GPIO-CNF-address.patch new file mode 100644 index 0000000000000000000000000000000000000000..e7fa469457a74c6330882d5fc51a1e0de6e1d60e --- /dev/null +++ b/nrf51-Fix-last-GPIO-CNF-address.patch @@ -0,0 +1,52 @@ +From c8aeef3aed6beef14175f9c6744b2ea30fc309d9 Mon Sep 17 00:00:00 2001 +From: Cameron Esfahani +Date: Tue, 14 Apr 2020 21:37:17 -0700 +Subject: [PATCH 096/709] nrf51: Fix last GPIO CNF address +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +NRF51_GPIO_REG_CNF_END doesn't actually refer to the start of the last +valid CNF register: it's referring to the last byte of the last valid +CNF register. + +This hasn't been a problem up to now, as current implementation in +memory.c turns an unaligned 4-byte read from 0x77f to a single byte read +and the qtest only looks at the least-significant byte of the register. + +But when running with patches which fix unaligned accesses in memory.c, +the qtest breaks. + +Considering NRF51 doesn't support unaligned accesses, the simplest fix +is to actually set NRF51_GPIO_REG_CNF_END to the start of the last valid +CNF register: 0x77c. + +Now, qtests work with or without the unaligned access patches. + +Reviewed-by: Cédric Le Goater +Tested-by: Cédric Le Goater +Reviewed-by: Joel Stanley +Signed-off-by: Cameron Esfahani +Message-id: 51b427f06838622da783d38ba56e3630d6d85c60.1586925392.git.dirty@apple.com +Reviewed-by: Peter Maydell +Signed-off-by: Peter Maydell +--- + include/hw/gpio/nrf51_gpio.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/include/hw/gpio/nrf51_gpio.h b/include/hw/gpio/nrf51_gpio.h +index 337ee534bb..1d62bbc928 100644 +--- a/include/hw/gpio/nrf51_gpio.h ++++ b/include/hw/gpio/nrf51_gpio.h +@@ -42,7 +42,7 @@ + #define NRF51_GPIO_REG_DIRSET 0x518 + #define NRF51_GPIO_REG_DIRCLR 0x51C + #define NRF51_GPIO_REG_CNF_START 0x700 +-#define NRF51_GPIO_REG_CNF_END 0x77F ++#define NRF51_GPIO_REG_CNF_END 0x77C + + #define NRF51_GPIO_PULLDOWN 1 + #define NRF51_GPIO_PULLUP 3 +-- +2.23.0 + diff --git a/nvdimm-Use-configurable-ACPI-IO-base-and-size.patch b/nvdimm-Use-configurable-ACPI-IO-base-and-size.patch new file mode 100644 index 0000000000000000000000000000000000000000..f7705fabb613903fd12de9d74717ca6988ae8d86 --- /dev/null +++ b/nvdimm-Use-configurable-ACPI-IO-base-and-size.patch @@ -0,0 +1,229 @@ +From 5c94b82662a815d8430b81090200178b5377a62e Mon Sep 17 00:00:00 2001 +From: Kwangwoo Lee +Date: Tue, 21 Apr 2020 13:59:29 +0100 +Subject: [PATCH 219/709] nvdimm: Use configurable ACPI IO base and size + +This patch makes IO base and size configurable to create NPIO AML for +ACPI NFIT. Since a different architecture like AArch64 does not use +port-mapped IO, a configurable IO base is required to create correct +mapping of ACPI IO address and size. + +Signed-off-by: Kwangwoo Lee +Signed-off-by: Eric Auger +Signed-off-by: Shameer Kolothum +Reviewed-by: Igor Mammedov +Message-Id: <20200421125934.14952-3-shameerali.kolothum.thodi@huawei.com> +Acked-by: Peter Maydell +Tested-by: Eric Auger +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +--- + hw/acpi/nvdimm.c | 32 ++++++++++++++++++++++---------- + hw/i386/acpi-build.c | 6 ++++++ + hw/i386/acpi-build.h | 3 +++ + hw/i386/pc_piix.c | 2 ++ + hw/i386/pc_q35.c | 2 ++ + include/hw/mem/nvdimm.h | 3 +++ + 6 files changed, 38 insertions(+), 10 deletions(-) + +diff --git a/hw/acpi/nvdimm.c b/hw/acpi/nvdimm.c +index df0790719a..fa7bf8b507 100644 +--- a/hw/acpi/nvdimm.c ++++ b/hw/acpi/nvdimm.c +@@ -900,11 +900,13 @@ void nvdimm_acpi_plug_cb(HotplugHandler *hotplug_dev, DeviceState *dev) + } + + void nvdimm_init_acpi_state(NVDIMMState *state, MemoryRegion *io, ++ struct AcpiGenericAddress dsm_io, + FWCfgState *fw_cfg, Object *owner) + { ++ state->dsm_io = dsm_io; + memory_region_init_io(&state->io_mr, owner, &nvdimm_dsm_ops, state, +- "nvdimm-acpi-io", NVDIMM_ACPI_IO_LEN); +- memory_region_add_subregion(io, NVDIMM_ACPI_IO_BASE, &state->io_mr); ++ "nvdimm-acpi-io", dsm_io.bit_width >> 3); ++ memory_region_add_subregion(io, dsm_io.address, &state->io_mr); + + state->dsm_mem = g_array_new(false, true /* clear */, 1); + acpi_data_push(state->dsm_mem, sizeof(NvdimmDsmIn)); +@@ -933,13 +935,15 @@ void nvdimm_init_acpi_state(NVDIMMState *state, MemoryRegion *io, + + #define NVDIMM_QEMU_RSVD_UUID "648B9CF2-CDA1-4312-8AD9-49C4AF32BD62" + +-static void nvdimm_build_common_dsm(Aml *dev) ++static void nvdimm_build_common_dsm(Aml *dev, ++ NVDIMMState *nvdimm_state) + { + Aml *method, *ifctx, *function, *handle, *uuid, *dsm_mem, *elsectx2; + Aml *elsectx, *unsupport, *unpatched, *expected_uuid, *uuid_invalid; + Aml *pckg, *pckg_index, *pckg_buf, *field, *dsm_out_buf, *dsm_out_buf_size; + Aml *whilectx, *offset; + uint8_t byte_list[1]; ++ AmlRegionSpace rs; + + method = aml_method(NVDIMM_COMMON_DSM, 5, AML_SERIALIZED); + uuid = aml_arg(0); +@@ -950,9 +954,16 @@ static void nvdimm_build_common_dsm(Aml *dev) + + aml_append(method, aml_store(aml_name(NVDIMM_ACPI_MEM_ADDR), dsm_mem)); + ++ if (nvdimm_state->dsm_io.space_id == AML_AS_SYSTEM_IO) { ++ rs = AML_SYSTEM_IO; ++ } else { ++ rs = AML_SYSTEM_MEMORY; ++ } ++ + /* map DSM memory and IO into ACPI namespace. */ +- aml_append(method, aml_operation_region(NVDIMM_DSM_IOPORT, AML_SYSTEM_IO, +- aml_int(NVDIMM_ACPI_IO_BASE), NVDIMM_ACPI_IO_LEN)); ++ aml_append(method, aml_operation_region(NVDIMM_DSM_IOPORT, rs, ++ aml_int(nvdimm_state->dsm_io.address), ++ nvdimm_state->dsm_io.bit_width >> 3)); + aml_append(method, aml_operation_region(NVDIMM_DSM_MEMORY, + AML_SYSTEM_MEMORY, dsm_mem, sizeof(NvdimmDsmIn))); + +@@ -967,7 +978,7 @@ static void nvdimm_build_common_dsm(Aml *dev) + field = aml_field(NVDIMM_DSM_IOPORT, AML_DWORD_ACC, AML_NOLOCK, + AML_PRESERVE); + aml_append(field, aml_named_field(NVDIMM_DSM_NOTIFY, +- NVDIMM_ACPI_IO_LEN * BITS_PER_BYTE)); ++ nvdimm_state->dsm_io.bit_width)); + aml_append(method, field); + + /* +@@ -1268,7 +1279,8 @@ static void nvdimm_build_nvdimm_devices(Aml *root_dev, uint32_t ram_slots) + } + + static void nvdimm_build_ssdt(GArray *table_offsets, GArray *table_data, +- BIOSLinker *linker, GArray *dsm_dma_area, ++ BIOSLinker *linker, ++ NVDIMMState *nvdimm_state, + uint32_t ram_slots) + { + Aml *ssdt, *sb_scope, *dev; +@@ -1296,7 +1308,7 @@ static void nvdimm_build_ssdt(GArray *table_offsets, GArray *table_data, + */ + aml_append(dev, aml_name_decl("_HID", aml_string("ACPI0012"))); + +- nvdimm_build_common_dsm(dev); ++ nvdimm_build_common_dsm(dev, nvdimm_state); + + /* 0 is reserved for root device. */ + nvdimm_build_device_dsm(dev, 0); +@@ -1315,7 +1327,7 @@ static void nvdimm_build_ssdt(GArray *table_offsets, GArray *table_data, + NVDIMM_ACPI_MEM_ADDR); + + bios_linker_loader_alloc(linker, +- NVDIMM_DSM_MEM_FILE, dsm_dma_area, ++ NVDIMM_DSM_MEM_FILE, nvdimm_state->dsm_mem, + sizeof(NvdimmDsmIn), false /* high memory */); + bios_linker_loader_add_pointer(linker, + ACPI_BUILD_TABLE_FILE, mem_addr_offset, sizeof(uint32_t), +@@ -1337,7 +1349,7 @@ void nvdimm_build_acpi(GArray *table_offsets, GArray *table_data, + return; + } + +- nvdimm_build_ssdt(table_offsets, table_data, linker, state->dsm_mem, ++ nvdimm_build_ssdt(table_offsets, table_data, linker, state, + ram_slots); + + device_list = nvdimm_get_device_list(); +diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c +index 97f3c75cd9..7d880bec4a 100644 +--- a/hw/i386/acpi-build.c ++++ b/hw/i386/acpi-build.c +@@ -128,6 +128,12 @@ typedef struct FwCfgTPMConfig { + + static bool acpi_get_mcfg(AcpiMcfgInfo *mcfg); + ++const struct AcpiGenericAddress x86_nvdimm_acpi_dsmio = { ++ .space_id = AML_AS_SYSTEM_IO, ++ .address = NVDIMM_ACPI_IO_BASE, ++ .bit_width = NVDIMM_ACPI_IO_LEN << 3 ++}; ++ + static void init_common_fadt_data(MachineState *ms, Object *o, + AcpiFadtData *data) + { +diff --git a/hw/i386/acpi-build.h b/hw/i386/acpi-build.h +index 007332e51c..74df5fc612 100644 +--- a/hw/i386/acpi-build.h ++++ b/hw/i386/acpi-build.h +@@ -1,6 +1,9 @@ + + #ifndef HW_I386_ACPI_BUILD_H + #define HW_I386_ACPI_BUILD_H ++#include "hw/acpi/acpi-defs.h" ++ ++extern const struct AcpiGenericAddress x86_nvdimm_acpi_dsmio; + + void acpi_setup(void); + +diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c +index 22dee0e76c..b75087d71b 100644 +--- a/hw/i386/pc_piix.c ++++ b/hw/i386/pc_piix.c +@@ -61,6 +61,7 @@ + #include "migration/misc.h" + #include "sysemu/numa.h" + #include "hw/mem/nvdimm.h" ++#include "hw/i386/acpi-build.h" + + #define MAX_IDE_BUS 2 + +@@ -297,6 +298,7 @@ static void pc_init1(MachineState *machine, + + if (machine->nvdimms_state->is_enabled) { + nvdimm_init_acpi_state(machine->nvdimms_state, system_io, ++ x86_nvdimm_acpi_dsmio, + x86ms->fw_cfg, OBJECT(pcms)); + } + } +diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c +index d37c425e22..d2806c1b29 100644 +--- a/hw/i386/pc_q35.c ++++ b/hw/i386/pc_q35.c +@@ -54,6 +54,7 @@ + #include "qemu/error-report.h" + #include "sysemu/numa.h" + #include "hw/mem/nvdimm.h" ++#include "hw/i386/acpi-build.h" + + /* ICH9 AHCI has 6 ports */ + #define MAX_SATA_PORTS 6 +@@ -315,6 +316,7 @@ static void pc_q35_init(MachineState *machine) + + if (machine->nvdimms_state->is_enabled) { + nvdimm_init_acpi_state(machine->nvdimms_state, system_io, ++ x86_nvdimm_acpi_dsmio, + x86ms->fw_cfg, OBJECT(pcms)); + } + } +diff --git a/include/hw/mem/nvdimm.h b/include/hw/mem/nvdimm.h +index 4807ca615b..a3c08955e8 100644 +--- a/include/hw/mem/nvdimm.h ++++ b/include/hw/mem/nvdimm.h +@@ -26,6 +26,7 @@ + #include "hw/mem/pc-dimm.h" + #include "hw/acpi/bios-linker-loader.h" + #include "qemu/uuid.h" ++#include "hw/acpi/aml-build.h" + + #define NVDIMM_DEBUG 0 + #define nvdimm_debug(fmt, ...) \ +@@ -147,10 +148,12 @@ struct NVDIMMState { + */ + int32_t persistence; + char *persistence_string; ++ struct AcpiGenericAddress dsm_io; + }; + typedef struct NVDIMMState NVDIMMState; + + void nvdimm_init_acpi_state(NVDIMMState *state, MemoryRegion *io, ++ struct AcpiGenericAddress dsm_io, + FWCfgState *fw_cfg, Object *owner); + void nvdimm_build_acpi(GArray *table_offsets, GArray *table_data, + BIOSLinker *linker, NVDIMMState *state, +-- +2.23.0 + diff --git a/nvme-introduce-PMR-support-from-NVMe-1.4-spec.patch b/nvme-introduce-PMR-support-from-NVMe-1.4-spec.patch new file mode 100644 index 0000000000000000000000000000000000000000..4e36b2ce672539383bb1672b0518cb3221f2f3eb --- /dev/null +++ b/nvme-introduce-PMR-support-from-NVMe-1.4-spec.patch @@ -0,0 +1,457 @@ +From 6cf94132293adb5c76d336ab7ff5924afe2cb147 Mon Sep 17 00:00:00 2001 +From: Andrzej Jakowski +Date: Mon, 30 Mar 2020 09:46:56 -0700 +Subject: [PATCH 136/709] nvme: introduce PMR support from NVMe 1.4 spec + +This patch introduces support for PMR that has been defined as part of NVMe 1.4 +spec. User can now specify a pmrdev option that should point to HostMemoryBackend. +pmrdev memory region will subsequently be exposed as PCI BAR 2 in emulated NVMe +device. Guest OS can perform mmio read and writes to the PMR region that will stay +persistent across system reboot. + +Signed-off-by: Andrzej Jakowski +Reviewed-by: Klaus Jensen +Reviewed-by: Stefan Hajnoczi +Message-Id: <20200330164656.9348-1-andrzej.jakowski@linux.intel.com> +Reviewed-by: Keith Busch +Signed-off-by: Kevin Wolf +--- + hw/block/Makefile.objs | 2 +- + hw/block/nvme.c | 109 ++++++++++++++++++++++++++ + hw/block/nvme.h | 2 + + hw/block/trace-events | 4 + + include/block/nvme.h | 172 +++++++++++++++++++++++++++++++++++++++++ + 5 files changed, 288 insertions(+), 1 deletion(-) + +diff --git a/hw/block/Makefile.objs b/hw/block/Makefile.objs +index 4b4a2b338d..47960b5f0d 100644 +--- a/hw/block/Makefile.objs ++++ b/hw/block/Makefile.objs +@@ -7,12 +7,12 @@ common-obj-$(CONFIG_PFLASH_CFI02) += pflash_cfi02.o + common-obj-$(CONFIG_XEN) += xen-block.o + common-obj-$(CONFIG_ECC) += ecc.o + common-obj-$(CONFIG_ONENAND) += onenand.o +-common-obj-$(CONFIG_NVME_PCI) += nvme.o + common-obj-$(CONFIG_SWIM) += swim.o + + common-obj-$(CONFIG_SH4) += tc58128.o + + obj-$(CONFIG_VIRTIO_BLK) += virtio-blk.o + obj-$(CONFIG_VHOST_USER_BLK) += vhost-user-blk.o ++obj-$(CONFIG_NVME_PCI) += nvme.o + + obj-y += dataplane/ +diff --git a/hw/block/nvme.c b/hw/block/nvme.c +index d28335cbf3..9b453423cf 100644 +--- a/hw/block/nvme.c ++++ b/hw/block/nvme.c +@@ -19,10 +19,19 @@ + * -drive file=,if=none,id= + * -device nvme,drive=,serial=,id=, \ + * cmb_size_mb=, \ ++ * [pmrdev=,] \ + * num_queues= + * + * Note cmb_size_mb denotes size of CMB in MB. CMB is assumed to be at + * offset 0 in BAR2 and supports only WDS, RDS and SQS for now. ++ * ++ * cmb_size_mb= and pmrdev= options are mutually exclusive due to limitation ++ * in available BAR's. cmb_size_mb= will take precedence over pmrdev= when ++ * both provided. ++ * Enabling pmr emulation can be achieved by pointing to memory-backend-file. ++ * For example: ++ * -object memory-backend-file,id=,share=on,mem-path=, \ ++ * size= .... -device nvme,...,pmrdev= + */ + + #include "qemu/osdep.h" +@@ -35,7 +44,9 @@ + #include "sysemu/sysemu.h" + #include "qapi/error.h" + #include "qapi/visitor.h" ++#include "sysemu/hostmem.h" + #include "sysemu/block-backend.h" ++#include "exec/ram_addr.h" + + #include "qemu/log.h" + #include "qemu/module.h" +@@ -1141,6 +1152,26 @@ static void nvme_write_bar(NvmeCtrl *n, hwaddr offset, uint64_t data, + NVME_GUEST_ERR(nvme_ub_mmiowr_cmbsz_readonly, + "invalid write to read only CMBSZ, ignored"); + return; ++ case 0xE00: /* PMRCAP */ ++ NVME_GUEST_ERR(nvme_ub_mmiowr_pmrcap_readonly, ++ "invalid write to PMRCAP register, ignored"); ++ return; ++ case 0xE04: /* TODO PMRCTL */ ++ break; ++ case 0xE08: /* PMRSTS */ ++ NVME_GUEST_ERR(nvme_ub_mmiowr_pmrsts_readonly, ++ "invalid write to PMRSTS register, ignored"); ++ return; ++ case 0xE0C: /* PMREBS */ ++ NVME_GUEST_ERR(nvme_ub_mmiowr_pmrebs_readonly, ++ "invalid write to PMREBS register, ignored"); ++ return; ++ case 0xE10: /* PMRSWTP */ ++ NVME_GUEST_ERR(nvme_ub_mmiowr_pmrswtp_readonly, ++ "invalid write to PMRSWTP register, ignored"); ++ return; ++ case 0xE14: /* TODO PMRMSC */ ++ break; + default: + NVME_GUEST_ERR(nvme_ub_mmiowr_invalid, + "invalid MMIO write," +@@ -1169,6 +1200,16 @@ static uint64_t nvme_mmio_read(void *opaque, hwaddr addr, unsigned size) + } + + if (addr < sizeof(n->bar)) { ++ /* ++ * When PMRWBM bit 1 is set then read from ++ * from PMRSTS should ensure prior writes ++ * made it to persistent media ++ */ ++ if (addr == 0xE08 && ++ (NVME_PMRCAP_PMRWBM(n->bar.pmrcap) & 0x02)) { ++ qemu_ram_writeback(n->pmrdev->mr.ram_block, ++ 0, n->pmrdev->size); ++ } + memcpy(&val, ptr + addr, size); + } else { + NVME_GUEST_ERR(nvme_ub_mmiord_invalid_ofs, +@@ -1332,6 +1373,23 @@ static void nvme_realize(PCIDevice *pci_dev, Error **errp) + error_setg(errp, "serial property not set"); + return; + } ++ ++ if (!n->cmb_size_mb && n->pmrdev) { ++ if (host_memory_backend_is_mapped(n->pmrdev)) { ++ char *path = object_get_canonical_path_component(OBJECT(n->pmrdev)); ++ error_setg(errp, "can't use already busy memdev: %s", path); ++ g_free(path); ++ return; ++ } ++ ++ if (!is_power_of_2(n->pmrdev->size)) { ++ error_setg(errp, "pmr backend size needs to be power of 2 in size"); ++ return; ++ } ++ ++ host_memory_backend_set_mapped(n->pmrdev, true); ++ } ++ + blkconf_blocksizes(&n->conf); + if (!blkconf_apply_backend_options(&n->conf, blk_is_read_only(n->conf.blk), + false, errp)) { +@@ -1415,6 +1473,51 @@ static void nvme_realize(PCIDevice *pci_dev, Error **errp) + PCI_BASE_ADDRESS_SPACE_MEMORY | PCI_BASE_ADDRESS_MEM_TYPE_64 | + PCI_BASE_ADDRESS_MEM_PREFETCH, &n->ctrl_mem); + ++ } else if (n->pmrdev) { ++ /* Controller Capabilities register */ ++ NVME_CAP_SET_PMRS(n->bar.cap, 1); ++ ++ /* PMR Capabities register */ ++ n->bar.pmrcap = 0; ++ NVME_PMRCAP_SET_RDS(n->bar.pmrcap, 0); ++ NVME_PMRCAP_SET_WDS(n->bar.pmrcap, 0); ++ NVME_PMRCAP_SET_BIR(n->bar.pmrcap, 2); ++ NVME_PMRCAP_SET_PMRTU(n->bar.pmrcap, 0); ++ /* Turn on bit 1 support */ ++ NVME_PMRCAP_SET_PMRWBM(n->bar.pmrcap, 0x02); ++ NVME_PMRCAP_SET_PMRTO(n->bar.pmrcap, 0); ++ NVME_PMRCAP_SET_CMSS(n->bar.pmrcap, 0); ++ ++ /* PMR Control register */ ++ n->bar.pmrctl = 0; ++ NVME_PMRCTL_SET_EN(n->bar.pmrctl, 0); ++ ++ /* PMR Status register */ ++ n->bar.pmrsts = 0; ++ NVME_PMRSTS_SET_ERR(n->bar.pmrsts, 0); ++ NVME_PMRSTS_SET_NRDY(n->bar.pmrsts, 0); ++ NVME_PMRSTS_SET_HSTS(n->bar.pmrsts, 0); ++ NVME_PMRSTS_SET_CBAI(n->bar.pmrsts, 0); ++ ++ /* PMR Elasticity Buffer Size register */ ++ n->bar.pmrebs = 0; ++ NVME_PMREBS_SET_PMRSZU(n->bar.pmrebs, 0); ++ NVME_PMREBS_SET_RBB(n->bar.pmrebs, 0); ++ NVME_PMREBS_SET_PMRWBZ(n->bar.pmrebs, 0); ++ ++ /* PMR Sustained Write Throughput register */ ++ n->bar.pmrswtp = 0; ++ NVME_PMRSWTP_SET_PMRSWTU(n->bar.pmrswtp, 0); ++ NVME_PMRSWTP_SET_PMRSWTV(n->bar.pmrswtp, 0); ++ ++ /* PMR Memory Space Control register */ ++ n->bar.pmrmsc = 0; ++ NVME_PMRMSC_SET_CMSE(n->bar.pmrmsc, 0); ++ NVME_PMRMSC_SET_CBA(n->bar.pmrmsc, 0); ++ ++ pci_register_bar(pci_dev, NVME_PMRCAP_BIR(n->bar.pmrcap), ++ PCI_BASE_ADDRESS_SPACE_MEMORY | PCI_BASE_ADDRESS_MEM_TYPE_64 | ++ PCI_BASE_ADDRESS_MEM_PREFETCH, &n->pmrdev->mr); + } + + for (i = 0; i < n->num_namespaces; i++) { +@@ -1445,11 +1548,17 @@ static void nvme_exit(PCIDevice *pci_dev) + if (n->cmb_size_mb) { + g_free(n->cmbuf); + } ++ ++ if (n->pmrdev) { ++ host_memory_backend_set_mapped(n->pmrdev, false); ++ } + msix_uninit_exclusive_bar(pci_dev); + } + + static Property nvme_props[] = { + DEFINE_BLOCK_PROPERTIES(NvmeCtrl, conf), ++ DEFINE_PROP_LINK("pmrdev", NvmeCtrl, pmrdev, TYPE_MEMORY_BACKEND, ++ HostMemoryBackend *), + DEFINE_PROP_STRING("serial", NvmeCtrl, serial), + DEFINE_PROP_UINT32("cmb_size_mb", NvmeCtrl, cmb_size_mb, 0), + DEFINE_PROP_UINT32("num_queues", NvmeCtrl, num_queues, 64), +diff --git a/hw/block/nvme.h b/hw/block/nvme.h +index 557194ee19..6520a9f0be 100644 +--- a/hw/block/nvme.h ++++ b/hw/block/nvme.h +@@ -83,6 +83,8 @@ typedef struct NvmeCtrl { + uint64_t timestamp_set_qemu_clock_ms; /* QEMU clock time */ + + char *serial; ++ HostMemoryBackend *pmrdev; ++ + NvmeNamespace *namespaces; + NvmeSQueue **sq; + NvmeCQueue **cq; +diff --git a/hw/block/trace-events b/hw/block/trace-events +index bf6d11b58b..aca54bda14 100644 +--- a/hw/block/trace-events ++++ b/hw/block/trace-events +@@ -110,6 +110,10 @@ nvme_ub_mmiowr_ssreset_w1c_unsupported(void) "attempted to W1C CSTS.NSSRO but CA + nvme_ub_mmiowr_ssreset_unsupported(void) "attempted NVM subsystem reset but CAP.NSSRS is zero (not supported)" + nvme_ub_mmiowr_cmbloc_reserved(void) "invalid write to reserved CMBLOC when CMBSZ is zero, ignored" + nvme_ub_mmiowr_cmbsz_readonly(void) "invalid write to read only CMBSZ, ignored" ++nvme_ub_mmiowr_pmrcap_readonly(void) "invalid write to read only PMRCAP, ignored" ++nvme_ub_mmiowr_pmrsts_readonly(void) "invalid write to read only PMRSTS, ignored" ++nvme_ub_mmiowr_pmrebs_readonly(void) "invalid write to read only PMREBS, ignored" ++nvme_ub_mmiowr_pmrswtp_readonly(void) "invalid write to read only PMRSWTP, ignored" + nvme_ub_mmiowr_invalid(uint64_t offset, uint64_t data) "invalid MMIO write, offset=0x%"PRIx64", data=0x%"PRIx64"" + nvme_ub_mmiord_misaligned32(uint64_t offset) "MMIO read not 32-bit aligned, offset=0x%"PRIx64"" + nvme_ub_mmiord_toosmall(uint64_t offset) "MMIO read smaller than 32-bits, offset=0x%"PRIx64"" +diff --git a/include/block/nvme.h b/include/block/nvme.h +index 8fb941c653..5525c8e343 100644 +--- a/include/block/nvme.h ++++ b/include/block/nvme.h +@@ -15,6 +15,13 @@ typedef struct NvmeBar { + uint64_t acq; + uint32_t cmbloc; + uint32_t cmbsz; ++ uint8_t padding[3520]; /* not used by QEMU */ ++ uint32_t pmrcap; ++ uint32_t pmrctl; ++ uint32_t pmrsts; ++ uint32_t pmrebs; ++ uint32_t pmrswtp; ++ uint32_t pmrmsc; + } NvmeBar; + + enum NvmeCapShift { +@@ -27,6 +34,7 @@ enum NvmeCapShift { + CAP_CSS_SHIFT = 37, + CAP_MPSMIN_SHIFT = 48, + CAP_MPSMAX_SHIFT = 52, ++ CAP_PMR_SHIFT = 56, + }; + + enum NvmeCapMask { +@@ -39,6 +47,7 @@ enum NvmeCapMask { + CAP_CSS_MASK = 0xff, + CAP_MPSMIN_MASK = 0xf, + CAP_MPSMAX_MASK = 0xf, ++ CAP_PMR_MASK = 0x1, + }; + + #define NVME_CAP_MQES(cap) (((cap) >> CAP_MQES_SHIFT) & CAP_MQES_MASK) +@@ -69,6 +78,8 @@ enum NvmeCapMask { + << CAP_MPSMIN_SHIFT) + #define NVME_CAP_SET_MPSMAX(cap, val) (cap |= (uint64_t)(val & CAP_MPSMAX_MASK)\ + << CAP_MPSMAX_SHIFT) ++#define NVME_CAP_SET_PMRS(cap, val) (cap |= (uint64_t)(val & CAP_PMR_MASK)\ ++ << CAP_PMR_SHIFT) + + enum NvmeCcShift { + CC_EN_SHIFT = 0, +@@ -205,6 +216,167 @@ enum NvmeCmbszMask { + #define NVME_CMBSZ_GETSIZE(cmbsz) \ + (NVME_CMBSZ_SZ(cmbsz) * (1 << (12 + 4 * NVME_CMBSZ_SZU(cmbsz)))) + ++enum NvmePmrcapShift { ++ PMRCAP_RDS_SHIFT = 3, ++ PMRCAP_WDS_SHIFT = 4, ++ PMRCAP_BIR_SHIFT = 5, ++ PMRCAP_PMRTU_SHIFT = 8, ++ PMRCAP_PMRWBM_SHIFT = 10, ++ PMRCAP_PMRTO_SHIFT = 16, ++ PMRCAP_CMSS_SHIFT = 24, ++}; ++ ++enum NvmePmrcapMask { ++ PMRCAP_RDS_MASK = 0x1, ++ PMRCAP_WDS_MASK = 0x1, ++ PMRCAP_BIR_MASK = 0x7, ++ PMRCAP_PMRTU_MASK = 0x3, ++ PMRCAP_PMRWBM_MASK = 0xf, ++ PMRCAP_PMRTO_MASK = 0xff, ++ PMRCAP_CMSS_MASK = 0x1, ++}; ++ ++#define NVME_PMRCAP_RDS(pmrcap) \ ++ ((pmrcap >> PMRCAP_RDS_SHIFT) & PMRCAP_RDS_MASK) ++#define NVME_PMRCAP_WDS(pmrcap) \ ++ ((pmrcap >> PMRCAP_WDS_SHIFT) & PMRCAP_WDS_MASK) ++#define NVME_PMRCAP_BIR(pmrcap) \ ++ ((pmrcap >> PMRCAP_BIR_SHIFT) & PMRCAP_BIR_MASK) ++#define NVME_PMRCAP_PMRTU(pmrcap) \ ++ ((pmrcap >> PMRCAP_PMRTU_SHIFT) & PMRCAP_PMRTU_MASK) ++#define NVME_PMRCAP_PMRWBM(pmrcap) \ ++ ((pmrcap >> PMRCAP_PMRWBM_SHIFT) & PMRCAP_PMRWBM_MASK) ++#define NVME_PMRCAP_PMRTO(pmrcap) \ ++ ((pmrcap >> PMRCAP_PMRTO_SHIFT) & PMRCAP_PMRTO_MASK) ++#define NVME_PMRCAP_CMSS(pmrcap) \ ++ ((pmrcap >> PMRCAP_CMSS_SHIFT) & PMRCAP_CMSS_MASK) ++ ++#define NVME_PMRCAP_SET_RDS(pmrcap, val) \ ++ (pmrcap |= (uint64_t)(val & PMRCAP_RDS_MASK) << PMRCAP_RDS_SHIFT) ++#define NVME_PMRCAP_SET_WDS(pmrcap, val) \ ++ (pmrcap |= (uint64_t)(val & PMRCAP_WDS_MASK) << PMRCAP_WDS_SHIFT) ++#define NVME_PMRCAP_SET_BIR(pmrcap, val) \ ++ (pmrcap |= (uint64_t)(val & PMRCAP_BIR_MASK) << PMRCAP_BIR_SHIFT) ++#define NVME_PMRCAP_SET_PMRTU(pmrcap, val) \ ++ (pmrcap |= (uint64_t)(val & PMRCAP_PMRTU_MASK) << PMRCAP_PMRTU_SHIFT) ++#define NVME_PMRCAP_SET_PMRWBM(pmrcap, val) \ ++ (pmrcap |= (uint64_t)(val & PMRCAP_PMRWBM_MASK) << PMRCAP_PMRWBM_SHIFT) ++#define NVME_PMRCAP_SET_PMRTO(pmrcap, val) \ ++ (pmrcap |= (uint64_t)(val & PMRCAP_PMRTO_MASK) << PMRCAP_PMRTO_SHIFT) ++#define NVME_PMRCAP_SET_CMSS(pmrcap, val) \ ++ (pmrcap |= (uint64_t)(val & PMRCAP_CMSS_MASK) << PMRCAP_CMSS_SHIFT) ++ ++enum NvmePmrctlShift { ++ PMRCTL_EN_SHIFT = 0, ++}; ++ ++enum NvmePmrctlMask { ++ PMRCTL_EN_MASK = 0x1, ++}; ++ ++#define NVME_PMRCTL_EN(pmrctl) ((pmrctl >> PMRCTL_EN_SHIFT) & PMRCTL_EN_MASK) ++ ++#define NVME_PMRCTL_SET_EN(pmrctl, val) \ ++ (pmrctl |= (uint64_t)(val & PMRCTL_EN_MASK) << PMRCTL_EN_SHIFT) ++ ++enum NvmePmrstsShift { ++ PMRSTS_ERR_SHIFT = 0, ++ PMRSTS_NRDY_SHIFT = 8, ++ PMRSTS_HSTS_SHIFT = 9, ++ PMRSTS_CBAI_SHIFT = 12, ++}; ++ ++enum NvmePmrstsMask { ++ PMRSTS_ERR_MASK = 0xff, ++ PMRSTS_NRDY_MASK = 0x1, ++ PMRSTS_HSTS_MASK = 0x7, ++ PMRSTS_CBAI_MASK = 0x1, ++}; ++ ++#define NVME_PMRSTS_ERR(pmrsts) \ ++ ((pmrsts >> PMRSTS_ERR_SHIFT) & PMRSTS_ERR_MASK) ++#define NVME_PMRSTS_NRDY(pmrsts) \ ++ ((pmrsts >> PMRSTS_NRDY_SHIFT) & PMRSTS_NRDY_MASK) ++#define NVME_PMRSTS_HSTS(pmrsts) \ ++ ((pmrsts >> PMRSTS_HSTS_SHIFT) & PMRSTS_HSTS_MASK) ++#define NVME_PMRSTS_CBAI(pmrsts) \ ++ ((pmrsts >> PMRSTS_CBAI_SHIFT) & PMRSTS_CBAI_MASK) ++ ++#define NVME_PMRSTS_SET_ERR(pmrsts, val) \ ++ (pmrsts |= (uint64_t)(val & PMRSTS_ERR_MASK) << PMRSTS_ERR_SHIFT) ++#define NVME_PMRSTS_SET_NRDY(pmrsts, val) \ ++ (pmrsts |= (uint64_t)(val & PMRSTS_NRDY_MASK) << PMRSTS_NRDY_SHIFT) ++#define NVME_PMRSTS_SET_HSTS(pmrsts, val) \ ++ (pmrsts |= (uint64_t)(val & PMRSTS_HSTS_MASK) << PMRSTS_HSTS_SHIFT) ++#define NVME_PMRSTS_SET_CBAI(pmrsts, val) \ ++ (pmrsts |= (uint64_t)(val & PMRSTS_CBAI_MASK) << PMRSTS_CBAI_SHIFT) ++ ++enum NvmePmrebsShift { ++ PMREBS_PMRSZU_SHIFT = 0, ++ PMREBS_RBB_SHIFT = 4, ++ PMREBS_PMRWBZ_SHIFT = 8, ++}; ++ ++enum NvmePmrebsMask { ++ PMREBS_PMRSZU_MASK = 0xf, ++ PMREBS_RBB_MASK = 0x1, ++ PMREBS_PMRWBZ_MASK = 0xffffff, ++}; ++ ++#define NVME_PMREBS_PMRSZU(pmrebs) \ ++ ((pmrebs >> PMREBS_PMRSZU_SHIFT) & PMREBS_PMRSZU_MASK) ++#define NVME_PMREBS_RBB(pmrebs) \ ++ ((pmrebs >> PMREBS_RBB_SHIFT) & PMREBS_RBB_MASK) ++#define NVME_PMREBS_PMRWBZ(pmrebs) \ ++ ((pmrebs >> PMREBS_PMRWBZ_SHIFT) & PMREBS_PMRWBZ_MASK) ++ ++#define NVME_PMREBS_SET_PMRSZU(pmrebs, val) \ ++ (pmrebs |= (uint64_t)(val & PMREBS_PMRSZU_MASK) << PMREBS_PMRSZU_SHIFT) ++#define NVME_PMREBS_SET_RBB(pmrebs, val) \ ++ (pmrebs |= (uint64_t)(val & PMREBS_RBB_MASK) << PMREBS_RBB_SHIFT) ++#define NVME_PMREBS_SET_PMRWBZ(pmrebs, val) \ ++ (pmrebs |= (uint64_t)(val & PMREBS_PMRWBZ_MASK) << PMREBS_PMRWBZ_SHIFT) ++ ++enum NvmePmrswtpShift { ++ PMRSWTP_PMRSWTU_SHIFT = 0, ++ PMRSWTP_PMRSWTV_SHIFT = 8, ++}; ++ ++enum NvmePmrswtpMask { ++ PMRSWTP_PMRSWTU_MASK = 0xf, ++ PMRSWTP_PMRSWTV_MASK = 0xffffff, ++}; ++ ++#define NVME_PMRSWTP_PMRSWTU(pmrswtp) \ ++ ((pmrswtp >> PMRSWTP_PMRSWTU_SHIFT) & PMRSWTP_PMRSWTU_MASK) ++#define NVME_PMRSWTP_PMRSWTV(pmrswtp) \ ++ ((pmrswtp >> PMRSWTP_PMRSWTV_SHIFT) & PMRSWTP_PMRSWTV_MASK) ++ ++#define NVME_PMRSWTP_SET_PMRSWTU(pmrswtp, val) \ ++ (pmrswtp |= (uint64_t)(val & PMRSWTP_PMRSWTU_MASK) << PMRSWTP_PMRSWTU_SHIFT) ++#define NVME_PMRSWTP_SET_PMRSWTV(pmrswtp, val) \ ++ (pmrswtp |= (uint64_t)(val & PMRSWTP_PMRSWTV_MASK) << PMRSWTP_PMRSWTV_SHIFT) ++ ++enum NvmePmrmscShift { ++ PMRMSC_CMSE_SHIFT = 1, ++ PMRMSC_CBA_SHIFT = 12, ++}; ++ ++enum NvmePmrmscMask { ++ PMRMSC_CMSE_MASK = 0x1, ++ PMRMSC_CBA_MASK = 0xfffffffffffff, ++}; ++ ++#define NVME_PMRMSC_CMSE(pmrmsc) \ ++ ((pmrmsc >> PMRMSC_CMSE_SHIFT) & PMRMSC_CMSE_MASK) ++#define NVME_PMRMSC_CBA(pmrmsc) \ ++ ((pmrmsc >> PMRMSC_CBA_SHIFT) & PMRMSC_CBA_MASK) ++ ++#define NVME_PMRMSC_SET_CMSE(pmrmsc, val) \ ++ (pmrmsc |= (uint64_t)(val & PMRMSC_CMSE_MASK) << PMRMSC_CMSE_SHIFT) ++#define NVME_PMRMSC_SET_CBA(pmrmsc, val) \ ++ (pmrmsc |= (uint64_t)(val & PMRMSC_CBA_MASK) << PMRMSC_CBA_SHIFT) ++ + typedef struct NvmeCmd { + uint8_t opcode; + uint8_t fuse; +-- +2.23.0 + diff --git a/parallels-Rework-truncation-logic.patch b/parallels-Rework-truncation-logic.patch new file mode 100644 index 0000000000000000000000000000000000000000..b84ab6c8f1a33e819404ad5df87c33b05c8fd4f3 --- /dev/null +++ b/parallels-Rework-truncation-logic.patch @@ -0,0 +1,83 @@ +From bda4cdcbb997d34762e2af27e1f475357a9b4453 Mon Sep 17 00:00:00 2001 +From: Eric Blake +Date: Tue, 28 Apr 2020 15:29:03 -0500 +Subject: [PATCH 355/709] parallels: Rework truncation logic + +The parallels driver tries to use truncation for image growth, but can +only do so when reads are guaranteed as zero. Now that we have a way +to request zero contents from truncation, we can defer the decision to +actual allocation attempts rather than up front, reducing the number +of places that still use bdrv_has_zero_init_truncate. + +Signed-off-by: Eric Blake +Message-Id: <20200428202905.770727-8-eblake@redhat.com> +Reviewed-by: Denis V. Lunev +Signed-off-by: Kevin Wolf +--- + block/parallels.c | 25 ++++++++++++++++--------- + 1 file changed, 16 insertions(+), 9 deletions(-) + +diff --git a/block/parallels.c b/block/parallels.c +index 8db64a55e3..e7717c508e 100644 +--- a/block/parallels.c ++++ b/block/parallels.c +@@ -166,7 +166,7 @@ static int64_t block_status(BDRVParallelsState *s, int64_t sector_num, + static int64_t allocate_clusters(BlockDriverState *bs, int64_t sector_num, + int nb_sectors, int *pnum) + { +- int ret; ++ int ret = 0; + BDRVParallelsState *s = bs->opaque; + int64_t pos, space, idx, to_allocate, i, len; + +@@ -196,14 +196,24 @@ static int64_t allocate_clusters(BlockDriverState *bs, int64_t sector_num, + } + if (s->data_end + space > (len >> BDRV_SECTOR_BITS)) { + space += s->prealloc_size; ++ /* ++ * We require the expanded size to read back as zero. If the ++ * user permitted truncation, we try that; but if it fails, we ++ * force the safer-but-slower fallocate. ++ */ ++ if (s->prealloc_mode == PRL_PREALLOC_MODE_TRUNCATE) { ++ ret = bdrv_truncate(bs->file, ++ (s->data_end + space) << BDRV_SECTOR_BITS, ++ false, PREALLOC_MODE_OFF, BDRV_REQ_ZERO_WRITE, ++ NULL); ++ if (ret == -ENOTSUP) { ++ s->prealloc_mode = PRL_PREALLOC_MODE_FALLOCATE; ++ } ++ } + if (s->prealloc_mode == PRL_PREALLOC_MODE_FALLOCATE) { + ret = bdrv_pwrite_zeroes(bs->file, + s->data_end << BDRV_SECTOR_BITS, + space << BDRV_SECTOR_BITS, 0); +- } else { +- ret = bdrv_truncate(bs->file, +- (s->data_end + space) << BDRV_SECTOR_BITS, +- false, PREALLOC_MODE_OFF, 0, NULL); + } + if (ret < 0) { + return ret; +@@ -828,6 +838,7 @@ static int parallels_open(BlockDriverState *bs, QDict *options, int flags, + qemu_opt_get_size_del(opts, PARALLELS_OPT_PREALLOC_SIZE, 0); + s->prealloc_size = MAX(s->tracks, s->prealloc_size >> BDRV_SECTOR_BITS); + buf = qemu_opt_get_del(opts, PARALLELS_OPT_PREALLOC_MODE); ++ /* prealloc_mode can be downgraded later during allocate_clusters */ + s->prealloc_mode = qapi_enum_parse(&prealloc_mode_lookup, buf, + PRL_PREALLOC_MODE_FALLOCATE, + &local_err); +@@ -836,10 +847,6 @@ static int parallels_open(BlockDriverState *bs, QDict *options, int flags, + goto fail_options; + } + +- if (!bdrv_has_zero_init_truncate(bs->file->bs)) { +- s->prealloc_mode = PRL_PREALLOC_MODE_FALLOCATE; +- } +- + if ((flags & BDRV_O_RDWR) && !(flags & BDRV_O_INACTIVE)) { + s->header->inuse = cpu_to_le32(HEADER_INUSE_MAGIC); + ret = parallels_update_header(bs); +-- +2.23.0 + diff --git a/pcie-disable-the-PCI_EXP_LINKSTA_DLLA-cap.patch b/pcie-disable-the-PCI_EXP_LINKSTA_DLLA-cap.patch deleted file mode 100644 index dc31a503345e1599abe5cf879b8edfeff4ee22e9..0000000000000000000000000000000000000000 --- a/pcie-disable-the-PCI_EXP_LINKSTA_DLLA-cap.patch +++ /dev/null @@ -1,99 +0,0 @@ -From 7381599d4222f9b5cff6935a66e8b311af77f620 Mon Sep 17 00:00:00 2001 -From: Li Mingwang -Date: Thu, 17 Oct 2019 16:57:52 +0800 -Subject: [PATCH] Subject: [PATCH] pcie: disable the PCI_EXP_LINKSTA_DLLA cap - for pcie-root-port by default - -If the PCI_EXP_LNKSTA_DLLLA capability is set by default, linux -kernel will send PDC event to detect whether there is a device in -pcie slot. If a device is pluged in the pcie-root-port at the same -time, hot-plug device will send ABP + PDC events to the kernel. The -VM kernel will wrongly unplug the device if two PDC events get too -close. Thus we'd better set the PCI_EXP_LNKSTA_DLLLA capability only -in hotplug scenario - -Signed-off-by: Li Mingwang ---- - hw/core/machine.c | 1 + - hw/pci-bridge/gen_pcie_root_port.c | 1 + - hw/pci/pcie.c | 18 ++++++++++++++---- - include/hw/pci/pcie_port.h | 2 ++ - 4 files changed, 18 insertions(+), 4 deletions(-) - -diff --git a/hw/core/machine.c b/hw/core/machine.c -index 5d046a43..29a708da 100644 ---- a/hw/core/machine.c -+++ b/hw/core/machine.c -@@ -30,6 +30,7 @@ const size_t hw_compat_4_0_len = G_N_ELEMENTS(hw_compat_4_0); - GlobalProperty hw_compat_3_1[] = { - { "pcie-root-port", "x-speed", "2_5" }, - { "pcie-root-port", "x-width", "1" }, -+ { "pcie-root-port", "fast-plug", "0" }, - { "memory-backend-file", "x-use-canonical-path-for-ramblock-id", "true" }, - { "memory-backend-memfd", "x-use-canonical-path-for-ramblock-id", "true" }, - { "tpm-crb", "ppi", "false" }, -diff --git a/hw/pci-bridge/gen_pcie_root_port.c b/hw/pci-bridge/gen_pcie_root_port.c -index 26bda73e..3179c4ea 100644 ---- a/hw/pci-bridge/gen_pcie_root_port.c -+++ b/hw/pci-bridge/gen_pcie_root_port.c -@@ -131,6 +131,7 @@ static Property gen_rp_props[] = { - speed, PCIE_LINK_SPEED_16), - DEFINE_PROP_PCIE_LINK_WIDTH("x-width", PCIESlot, - width, PCIE_LINK_WIDTH_32), -+ DEFINE_PROP_UINT8("fast-plug", PCIESlot, disable_lnksta_dllla, 0), - DEFINE_PROP_END_OF_LIST() - }; - -diff --git a/hw/pci/pcie.c b/hw/pci/pcie.c -index cf1ca30f..c0d6ff13 100644 ---- a/hw/pci/pcie.c -+++ b/hw/pci/pcie.c -@@ -50,6 +50,7 @@ pcie_cap_v1_fill(PCIDevice *dev, uint8_t port, uint8_t type, uint8_t version) - { - uint8_t *exp_cap = dev->config + dev->exp.exp_cap; - uint8_t *cmask = dev->cmask + dev->exp.exp_cap; -+ PCIESlot *s = (PCIESlot *)object_dynamic_cast(OBJECT(dev), TYPE_PCIE_SLOT); - - /* capability register - interrupt message number defaults to 0 */ -@@ -76,11 +77,20 @@ pcie_cap_v1_fill(PCIDevice *dev, uint8_t port, uint8_t type, uint8_t version) - QEMU_PCI_EXP_LNKSTA_NLW(QEMU_PCI_EXP_LNK_X1) | - QEMU_PCI_EXP_LNKSTA_CLS(QEMU_PCI_EXP_LNK_2_5GT)); - -- if (dev->cap_present & QEMU_PCIE_LNKSTA_DLLLA) { -- pci_word_test_and_set_mask(exp_cap + PCI_EXP_LNKSTA, -- PCI_EXP_LNKSTA_DLLLA); -+ /* If a device is plugged in the pcie-root-port when VM kernel -+ * is just booting, the kernel will wrongly disable the device. -+ * This bug was brought in two patches of the linux kernel, i.e. -+ * https://patchwork.kernel.org/patch/10575355/ and -+ * https://patchwork.kernel.org/patch/10766219/. -+ * To fix this up, let's enable the PCI_EXP_LNKSTA_DLLLA -+ * only if it is a PCIESlot device. -+ */ -+ if (s == NULL || s->disable_lnksta_dllla == 0) { -+ if (dev->cap_present & QEMU_PCIE_LNKSTA_DLLLA) { -+ pci_word_test_and_set_mask(exp_cap + PCI_EXP_LNKSTA, -+ PCI_EXP_LNKSTA_DLLLA); -+ } - } -- - /* We changed link status bits over time, and changing them across - * migrations is generally fine as hardware changes them too. - * Let's not bother checking. -diff --git a/include/hw/pci/pcie_port.h b/include/hw/pci/pcie_port.h -index 09586f46..c3969921 100644 ---- a/include/hw/pci/pcie_port.h -+++ b/include/hw/pci/pcie_port.h -@@ -50,6 +50,8 @@ struct PCIESlot { - uint8_t chassis; - uint16_t slot; - -+ uint8_t disable_lnksta_dllla; -+ - PCIExpLinkSpeed speed; - PCIExpLinkWidth width; - --- -2.19.1 - diff --git a/pl011-reset-read-FIFO-when-UARTTIMSC-0-UARTICR-0xfff.patch b/pl011-reset-read-FIFO-when-UARTTIMSC-0-UARTICR-0xfff.patch deleted file mode 100644 index b375c20f10426f4328d288d1be037609c06842de..0000000000000000000000000000000000000000 --- a/pl011-reset-read-FIFO-when-UARTTIMSC-0-UARTICR-0xfff.patch +++ /dev/null @@ -1,41 +0,0 @@ -From f995e8b5e5c14f83a16433f192440ec5c82c87fa Mon Sep 17 00:00:00 2001 -From: Ying Fang -Date: Mon, 29 Jul 2019 16:16:35 +0800 -Subject: [PATCH] pl011: reset read FIFO when UARTTIMSC=0 & UARTICR=0xffff - -We can enable ACPI when AArch64 Linux is booted with QEMU and UEFI (AAVMF). -When VM is booting and the SBSA driver has not initialized, writting data -that exceds 32 bytes will cause the read FIFO full and proceeding data will -be lost. The searil port appears to be stuck in this abnormal situation. - -A hack to reset read FIFO when UARTTIMSC=0 & UARTICR=0xffff appears to -resolve the issue. - -The question is fully discussed at -https://www.spinics.net/lists/linux-serial/msg23163.html - -Signed-off-by: Haibin Wang -Reviewed-by: Shannon Zhao -Reviewed-by: Ying Fang ---- - hw/char/pl011.c | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/hw/char/pl011.c b/hw/char/pl011.c -index e5dd448f..899745ef 100644 ---- a/hw/char/pl011.c -+++ b/hw/char/pl011.c -@@ -223,6 +223,10 @@ static void pl011_write(void *opaque, hwaddr offset, - case 17: /* UARTICR */ - s->int_level &= ~value; - pl011_update(s); -+ if (!s->int_enabled && !s->int_level) { -+ s->read_count = 0; -+ s->read_pos = 0; -+ } - break; - case 18: /* UARTDMACR */ - s->dmacr = value; --- -2.19.1 - diff --git a/pl031-support-rtc-timer-property-for-pl031.patch b/pl031-support-rtc-timer-property-for-pl031.patch deleted file mode 100644 index 7bd977af364da6871f7b0b7f8cb62af2f23ab26c..0000000000000000000000000000000000000000 --- a/pl031-support-rtc-timer-property-for-pl031.patch +++ /dev/null @@ -1,49 +0,0 @@ -From 68d4653b5ffde629e9b05d5de13b6adcde9d153b Mon Sep 17 00:00:00 2001 -From: Ying Fang -Date: Mon, 29 Jul 2019 16:20:51 +0800 -Subject: [PATCH] pl031: support rtc-timer property for pl031 - -This patch adds the rtc-timer property for pl031, we can get the -rtc time (UTC) through qmp command "qom-get date" with this property. - -Signed-off-by: Haibin Wang -Reviewed-by: Shannon Zhao -Reviewed-by: Ying Fang ---- - hw/timer/pl031.c | 13 +++++++++++++ - 1 file changed, 13 insertions(+) - -diff --git a/hw/timer/pl031.c b/hw/timer/pl031.c -index 274ad47a..04331472 100644 ---- a/hw/timer/pl031.c -+++ b/hw/timer/pl031.c -@@ -57,6 +57,15 @@ static uint32_t pl031_get_count(PL031State *s) - return s->tick_offset + now / NANOSECONDS_PER_SECOND; - } - -+static void pl031_get_date(Object *obj, struct tm *current_tm, Error **errp) -+{ -+ PL031State *s = PL031(obj); -+ time_t ti = pl031_get_count(s); -+ -+ /* Changed to UTC time */ -+ gmtime_r(&ti, current_tm); -+} -+ - static void pl031_set_alarm(PL031State *s) - { - uint32_t ticks; -@@ -191,6 +200,10 @@ static void pl031_init(Object *obj) - qemu_clock_get_ns(rtc_clock) / NANOSECONDS_PER_SECOND; - - s->timer = timer_new_ns(rtc_clock, pl031_interrupt, s); -+ -+ object_property_add_tm(OBJECT(s), "date", pl031_get_date, NULL); -+ object_property_add_alias(qdev_get_machine(), "rtc-time", -+ OBJECT(s), "date", NULL); - } - - static int pl031_pre_save(void *opaque) --- -2.19.1 - diff --git a/ppc-pnv-Add-support-for-NMI-interface.patch b/ppc-pnv-Add-support-for-NMI-interface.patch new file mode 100644 index 0000000000000000000000000000000000000000..d10ccc9cf8b314163f42b844ce7467ec7189ad4d --- /dev/null +++ b/ppc-pnv-Add-support-for-NMI-interface.patch @@ -0,0 +1,95 @@ +From 01b552b05b0f21f8ff57a508f7ad26f7abbcd123 Mon Sep 17 00:00:00 2001 +From: Nicholas Piggin +Date: Thu, 26 Mar 2020 00:41:44 +1000 +Subject: [PATCH 296/709] ppc/pnv: Add support for NMI interface +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This implements the NMI interface for the PNV machine, similarly to +commit 3431648272d ("spapr: Add support for new NMI interface") for +SPAPR. + +Signed-off-by: Nicholas Piggin +Message-Id: <20200325144147.221875-3-npiggin@gmail.com> +Reviewed-by: Cédric Le Goater +Signed-off-by: David Gibson +--- + hw/ppc/pnv.c | 29 +++++++++++++++++++++++++++++ + 1 file changed, 29 insertions(+) + +diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c +index c9cb6fa357..a3b7a8d0ff 100644 +--- a/hw/ppc/pnv.c ++++ b/hw/ppc/pnv.c +@@ -27,6 +27,7 @@ + #include "sysemu/runstate.h" + #include "sysemu/cpus.h" + #include "sysemu/device_tree.h" ++#include "sysemu/hw_accel.h" + #include "target/ppc/cpu.h" + #include "qemu/log.h" + #include "hw/ppc/fdt.h" +@@ -34,6 +35,7 @@ + #include "hw/ppc/pnv.h" + #include "hw/ppc/pnv_core.h" + #include "hw/loader.h" ++#include "hw/nmi.h" + #include "exec/address-spaces.h" + #include "qapi/visitor.h" + #include "monitor/monitor.h" +@@ -1977,10 +1979,35 @@ static void pnv_machine_set_hb(Object *obj, bool value, Error **errp) + } + } + ++static void pnv_cpu_do_nmi_on_cpu(CPUState *cs, run_on_cpu_data arg) ++{ ++ PowerPCCPU *cpu = POWERPC_CPU(cs); ++ CPUPPCState *env = &cpu->env; ++ ++ cpu_synchronize_state(cs); ++ ppc_cpu_do_system_reset(cs); ++ /* ++ * SRR1[42:45] is set to 0100 which the ISA defines as implementation ++ * dependent. POWER processors use this for xscom triggered interrupts, ++ * which come from the BMC or NMI IPIs. ++ */ ++ env->spr[SPR_SRR1] |= PPC_BIT(43); ++} ++ ++static void pnv_nmi(NMIState *n, int cpu_index, Error **errp) ++{ ++ CPUState *cs; ++ ++ CPU_FOREACH(cs) { ++ async_run_on_cpu(cs, pnv_cpu_do_nmi_on_cpu, RUN_ON_CPU_NULL); ++ } ++} ++ + static void pnv_machine_class_init(ObjectClass *oc, void *data) + { + MachineClass *mc = MACHINE_CLASS(oc); + InterruptStatsProviderClass *ispc = INTERRUPT_STATS_PROVIDER_CLASS(oc); ++ NMIClass *nc = NMI_CLASS(oc); + + mc->desc = "IBM PowerNV (Non-Virtualized)"; + mc->init = pnv_init; +@@ -1997,6 +2024,7 @@ static void pnv_machine_class_init(ObjectClass *oc, void *data) + mc->default_ram_size = INITRD_LOAD_ADDR + INITRD_MAX_SIZE; + mc->default_ram_id = "pnv.ram"; + ispc->print_info = pnv_pic_print_info; ++ nc->nmi_monitor_handler = pnv_nmi; + + object_class_property_add_bool(oc, "hb-mode", + pnv_machine_get_hb, pnv_machine_set_hb, +@@ -2060,6 +2088,7 @@ static const TypeInfo types[] = { + .class_size = sizeof(PnvMachineClass), + .interfaces = (InterfaceInfo[]) { + { TYPE_INTERRUPT_STATS_PROVIDER }, ++ { TYPE_NMI }, + { }, + }, + }, +-- +2.23.0 + diff --git a/ppc-spapr-tweak-change-system-reset-helper.patch b/ppc-spapr-tweak-change-system-reset-helper.patch new file mode 100644 index 0000000000000000000000000000000000000000..ea62f1f96b834c5279e7969f363d0d688b211800 --- /dev/null +++ b/ppc-spapr-tweak-change-system-reset-helper.patch @@ -0,0 +1,92 @@ +From b5b7f391817558f645034ea2e26bbed1e75eb731 Mon Sep 17 00:00:00 2001 +From: Nicholas Piggin +Date: Thu, 26 Mar 2020 00:41:43 +1000 +Subject: [PATCH 295/709] ppc/spapr: tweak change system reset helper +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Rather than have the helper take an optional vector address +override, instead have its caller modify env->nip itself. +This is more consistent when adding pnv nmi support, and also +with mce injection added later. + +Signed-off-by: Nicholas Piggin +Message-Id: <20200325144147.221875-2-npiggin@gmail.com> +Reviewed-by: Cédric Le Goater +Signed-off-by: David Gibson +--- + hw/ppc/spapr.c | 9 ++++++--- + target/ppc/cpu.h | 2 +- + target/ppc/excp_helper.c | 5 +---- + 3 files changed, 8 insertions(+), 8 deletions(-) + +diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c +index 9a2bd501aa..785c41d205 100644 +--- a/hw/ppc/spapr.c ++++ b/hw/ppc/spapr.c +@@ -3385,13 +3385,13 @@ static void spapr_machine_finalizefn(Object *obj) + void spapr_do_system_reset_on_cpu(CPUState *cs, run_on_cpu_data arg) + { + SpaprMachineState *spapr = SPAPR_MACHINE(qdev_get_machine()); ++ PowerPCCPU *cpu = POWERPC_CPU(cs); ++ CPUPPCState *env = &cpu->env; + + cpu_synchronize_state(cs); + /* If FWNMI is inactive, addr will be -1, which will deliver to 0x100 */ + if (spapr->fwnmi_system_reset_addr != -1) { + uint64_t rtas_addr, addr; +- PowerPCCPU *cpu = POWERPC_CPU(cs); +- CPUPPCState *env = &cpu->env; + + /* get rtas addr from fdt */ + rtas_addr = spapr_get_rtas_addr(); +@@ -3405,7 +3405,10 @@ void spapr_do_system_reset_on_cpu(CPUState *cs, run_on_cpu_data arg) + stq_be_phys(&address_space_memory, addr + sizeof(uint64_t), 0); + env->gpr[3] = addr; + } +- ppc_cpu_do_system_reset(cs, spapr->fwnmi_system_reset_addr); ++ ppc_cpu_do_system_reset(cs); ++ if (spapr->fwnmi_system_reset_addr != -1) { ++ env->nip = spapr->fwnmi_system_reset_addr; ++ } + } + + static void spapr_nmi(NMIState *n, int cpu_index, Error **errp) +diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h +index 88d9449555..f4a5304d43 100644 +--- a/target/ppc/cpu.h ++++ b/target/ppc/cpu.h +@@ -1220,7 +1220,7 @@ int ppc64_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs, + int ppc32_cpu_write_elf32_note(WriteCoreDumpFunction f, CPUState *cs, + int cpuid, void *opaque); + #ifndef CONFIG_USER_ONLY +-void ppc_cpu_do_system_reset(CPUState *cs, target_ulong vector); ++void ppc_cpu_do_system_reset(CPUState *cs); + void ppc_cpu_do_fwnmi_machine_check(CPUState *cs, target_ulong vector); + extern const VMStateDescription vmstate_ppc_cpu; + #endif +diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c +index 81ee19ebae..1acc3786de 100644 +--- a/target/ppc/excp_helper.c ++++ b/target/ppc/excp_helper.c +@@ -983,15 +983,12 @@ static void ppc_hw_interrupt(CPUPPCState *env) + } + } + +-void ppc_cpu_do_system_reset(CPUState *cs, target_ulong vector) ++void ppc_cpu_do_system_reset(CPUState *cs) + { + PowerPCCPU *cpu = POWERPC_CPU(cs); + CPUPPCState *env = &cpu->env; + + powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_RESET); +- if (vector != -1) { +- env->nip = vector; +- } + } + + void ppc_cpu_do_fwnmi_machine_check(CPUState *cs, target_ulong vector) +-- +2.23.0 + diff --git a/pr-manager-Fix-invalid-g_free-crash-bug.patch b/pr-manager-Fix-invalid-g_free-crash-bug.patch deleted file mode 100644 index 7e0fc7ee4f5dfa4f445b32c1c21bf17348faad7e..0000000000000000000000000000000000000000 --- a/pr-manager-Fix-invalid-g_free-crash-bug.patch +++ /dev/null @@ -1,40 +0,0 @@ -From 83f9b84c8bcb24265e25cd7f22e971e81cacebc6 Mon Sep 17 00:00:00 2001 -From: Markus Armbruster -Date: Thu, 22 Aug 2019 15:38:46 +0200 -Subject: [PATCH] pr-manager: Fix invalid g_free() crash bug -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -pr_manager_worker() passes its @opaque argument to g_free(). Wrong; -it points to pr_manager_worker()'s automatic @data. Broken when -commit 2f3a7ab39be converted @data from heap- to stack-allocated. Fix -by deleting the g_free(). - -Fixes: 2f3a7ab39bec4ba8022dc4d42ea641165b004e3e -Cc: qemu-stable@nongnu.org -Signed-off-by: Markus Armbruster -Reviewed-by: Philippe Mathieu-Daudé -Acked-by: Paolo Bonzini -Signed-off-by: Kevin Wolf -(cherry picked from commit 6b9d62c2a9e83bbad73fb61406f0ff69b46ff6f3) -Signed-off-by: Michael Roth ---- - scsi/pr-manager.c | 1 - - 1 file changed, 1 deletion(-) - -diff --git a/scsi/pr-manager.c b/scsi/pr-manager.c -index d9f4e8c3ad..227bdfaad2 100644 ---- a/scsi/pr-manager.c -+++ b/scsi/pr-manager.c -@@ -38,7 +38,6 @@ static int pr_manager_worker(void *opaque) - int fd = data->fd; - int r; - -- g_free(data); - trace_pr_manager_run(fd, hdr->cmdp[0], hdr->cmdp[1]); - - /* The reference was taken in pr_manager_execute. */ --- -2.19.1 - diff --git a/q35-Revert-to-kernel-irqchip.patch b/q35-Revert-to-kernel-irqchip.patch deleted file mode 100644 index 084217a233b199617c195386aa603eda757b7248..0000000000000000000000000000000000000000 --- a/q35-Revert-to-kernel-irqchip.patch +++ /dev/null @@ -1,132 +0,0 @@ -From c87759ce876a7a0b17c2bf4f0b964bd51f0ee871 Mon Sep 17 00:00:00 2001 -From: Alex Williamson -Date: Tue, 14 May 2019 14:14:41 -0600 -Subject: [PATCH] q35: Revert to kernel irqchip - -Commit b2fc91db8447 ("q35: set split kernel irqchip as default") changed -the default for the pc-q35-4.0 machine type to use split irqchip, which -turned out to have disasterous effects on vfio-pci INTx support. KVM -resampling irqfds are registered for handling these interrupts, but -these are non-functional in split irqchip mode. We can't simply test -for split irqchip in QEMU as userspace handling of this interrupt is a -significant performance regression versus KVM handling (GeForce GPUs -assigned to Windows VMs are non-functional without forcing MSI mode or -re-enabling kernel irqchip). - -The resolution is to revert the change in default irqchip mode in the -pc-q35-4.1 machine and create a pc-q35-4.0.1 machine for the 4.0-stable -branch. The qemu-q35-4.0 machine type should not be used in vfio-pci -configurations for devices requiring legacy INTx support without -explicitly modifying the VM configuration to use kernel irqchip. - -Link: https://bugs.launchpad.net/qemu/+bug/1826422 -Fixes: b2fc91db8447 ("q35: set split kernel irqchip as default") -Signed-off-by: Alex Williamson -Reviewed-by: Peter Xu -Message-Id: <155786484688.13873.6037015630912983760.stgit@gimli.home> -Signed-off-by: Paolo Bonzini -(cherry-picked from commit c87759ce876a7a0b17c2bf4f0b964bd51f0ee871) ---- - hw/core/machine.c | 3 +++ - hw/i386/pc.c | 3 +++ - hw/i386/pc_q35.c | 16 ++++++++++++++-- - include/hw/boards.h | 3 +++ - include/hw/i386/pc.h | 3 +++ - 5 files changed, 26 insertions(+), 2 deletions(-) - -diff --git a/hw/core/machine.c b/hw/core/machine.c -index 16ba667434..f1a0f45f9c 100644 ---- a/hw/core/machine.c -+++ b/hw/core/machine.c -@@ -24,6 +24,9 @@ - #include "hw/pci/pci.h" - #include "hw/mem/nvdimm.h" - -+GlobalProperty hw_compat_4_0_1[] = {}; -+const size_t hw_compat_4_0_1_len = G_N_ELEMENTS(hw_compat_4_0_1); -+ - GlobalProperty hw_compat_4_0[] = {}; - const size_t hw_compat_4_0_len = G_N_ELEMENTS(hw_compat_4_0); - -diff --git a/hw/i386/pc.c b/hw/i386/pc.c -index 2632b73f80..edc240bcbf 100644 ---- a/hw/i386/pc.c -+++ b/hw/i386/pc.c -@@ -110,6 +110,9 @@ struct hpet_fw_config hpet_cfg = {.count = UINT8_MAX}; - /* Physical Address of PVH entry point read from kernel ELF NOTE */ - static size_t pvh_start_addr; - -+GlobalProperty pc_compat_4_0_1[] = {}; -+const size_t pc_compat_4_0_1_len = G_N_ELEMENTS(pc_compat_4_0_1); -+ - GlobalProperty pc_compat_4_0[] = {}; - const size_t pc_compat_4_0_len = G_N_ELEMENTS(pc_compat_4_0); - -diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c -index 37dd350511..dcddc64662 100644 ---- a/hw/i386/pc_q35.c -+++ b/hw/i386/pc_q35.c -@@ -357,7 +357,7 @@ static void pc_q35_machine_options(MachineClass *m) - m->units_per_default_bus = 1; - m->default_machine_opts = "firmware=bios-256k.bin"; - m->default_display = "std"; -- m->default_kernel_irqchip_split = true; -+ m->default_kernel_irqchip_split = false; - m->no_floppy = 1; - machine_class_allow_dynamic_sysbus_dev(m, TYPE_AMD_IOMMU_DEVICE); - machine_class_allow_dynamic_sysbus_dev(m, TYPE_INTEL_IOMMU_DEVICE); -@@ -374,10 +374,22 @@ static void pc_q35_4_1_machine_options(MachineClass *m) - DEFINE_Q35_MACHINE(v4_1, "pc-q35-4.1", NULL, - pc_q35_4_1_machine_options); - --static void pc_q35_4_0_machine_options(MachineClass *m) -+static void pc_q35_4_0_1_machine_options(MachineClass *m) - { - pc_q35_4_1_machine_options(m); - m->alias = NULL; -+ compat_props_add(m->compat_props, hw_compat_4_0_1, hw_compat_4_0_1_len); -+ compat_props_add(m->compat_props, pc_compat_4_0_1, pc_compat_4_0_1_len); -+} -+ -+DEFINE_Q35_MACHINE(v4_0_1, "pc-q35-4.0.1", NULL, -+ pc_q35_4_0_1_machine_options); -+ -+static void pc_q35_4_0_machine_options(MachineClass *m) -+{ -+ pc_q35_4_0_1_machine_options(m); -+ m->default_kernel_irqchip_split = true; -+ m->alias = NULL; - compat_props_add(m->compat_props, hw_compat_4_0, hw_compat_4_0_len); - compat_props_add(m->compat_props, pc_compat_4_0, pc_compat_4_0_len); - } -diff --git a/include/hw/boards.h b/include/hw/boards.h -index 6f7916f88f..6ff02bf3e4 100644 ---- a/include/hw/boards.h -+++ b/include/hw/boards.h -@@ -292,6 +292,9 @@ struct MachineState { - } \ - type_init(machine_initfn##_register_types) - -+extern GlobalProperty hw_compat_4_0_1[]; -+extern const size_t hw_compat_4_0_1_len; -+ - extern GlobalProperty hw_compat_4_0[]; - extern const size_t hw_compat_4_0_len; - -diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h -index 43df7230a2..5d5636241e 100644 ---- a/include/hw/i386/pc.h -+++ b/include/hw/i386/pc.h -@@ -293,6 +293,9 @@ int e820_add_entry(uint64_t, uint64_t, uint32_t); - int e820_get_num_entries(void); - bool e820_get_entry(int, uint32_t, uint64_t *, uint64_t *); - -+extern GlobalProperty pc_compat_4_0_1[]; -+extern const size_t pc_compat_4_0_1_len; -+ - extern GlobalProperty pc_compat_4_0[]; - extern const size_t pc_compat_4_0_len; - --- -2.19.1 - diff --git a/qapi-Assert-incomplete-object-occurs-only-in-dealloc.patch b/qapi-Assert-incomplete-object-occurs-only-in-dealloc.patch new file mode 100644 index 0000000000000000000000000000000000000000..18026bb61ce30f00232c34e40321a424460ab9dd --- /dev/null +++ b/qapi-Assert-incomplete-object-occurs-only-in-dealloc.patch @@ -0,0 +1,86 @@ +From 8e08bf4ea24c3e6e07fab2c1b5bdcc7b104012c4 Mon Sep 17 00:00:00 2001 +From: Markus Armbruster +Date: Fri, 24 Apr 2020 10:43:29 +0200 +Subject: [PATCH 078/709] qapi: Assert incomplete object occurs only in dealloc + visitor + +Signed-off-by: Markus Armbruster +Reviewed-by: Eric Blake +Message-Id: <20200424084338.26803-7-armbru@redhat.com> +--- + docs/devel/qapi-code-gen.txt | 2 ++ + include/qapi/visitor.h | 5 +++++ + qapi/qapi-visit-core.c | 5 +++++ + scripts/qapi/visit.py | 4 ++++ + 4 files changed, 16 insertions(+) + +diff --git a/docs/devel/qapi-code-gen.txt b/docs/devel/qapi-code-gen.txt +index 1967adfa92..c6dd1891c3 100644 +--- a/docs/devel/qapi-code-gen.txt ++++ b/docs/devel/qapi-code-gen.txt +@@ -1446,6 +1446,8 @@ Example: + goto out; + } + if (!*obj) { ++ /* incomplete */ ++ assert(visit_is_dealloc(v)); + goto out_obj; + } + visit_type_UserDefOne_members(v, *obj, &err); +diff --git a/include/qapi/visitor.h b/include/qapi/visitor.h +index a425ea514c..2d40d2fe0f 100644 +--- a/include/qapi/visitor.h ++++ b/include/qapi/visitor.h +@@ -479,6 +479,11 @@ void visit_type_enum(Visitor *v, const char *name, int *obj, + */ + bool visit_is_input(Visitor *v); + ++/* ++ * Check if visitor is a dealloc visitor. ++ */ ++bool visit_is_dealloc(Visitor *v); ++ + /*** Visiting built-in types ***/ + + /* +diff --git a/qapi/qapi-visit-core.c b/qapi/qapi-visit-core.c +index 5365561b07..d4aac206cf 100644 +--- a/qapi/qapi-visit-core.c ++++ b/qapi/qapi-visit-core.c +@@ -142,6 +142,11 @@ bool visit_is_input(Visitor *v) + return v->type == VISITOR_INPUT; + } + ++bool visit_is_dealloc(Visitor *v) ++{ ++ return v->type == VISITOR_DEALLOC; ++} ++ + void visit_type_int(Visitor *v, const char *name, int64_t *obj, Error **errp) + { + assert(obj); +diff --git a/scripts/qapi/visit.py b/scripts/qapi/visit.py +index 23d9194aa4..e3467b770b 100644 +--- a/scripts/qapi/visit.py ++++ b/scripts/qapi/visit.py +@@ -189,6 +189,8 @@ void visit_type_%(c_name)s(Visitor *v, const char *name, %(c_name)s **obj, Error + goto out; + } + if (!*obj) { ++ /* incomplete */ ++ assert(visit_is_dealloc(v)); + goto out_obj; + } + switch ((*obj)->type) { +@@ -260,6 +262,8 @@ void visit_type_%(c_name)s(Visitor *v, const char *name, %(c_name)s **obj, Error + goto out; + } + if (!*obj) { ++ /* incomplete */ ++ assert(visit_is_dealloc(v)); + goto out_obj; + } + visit_type_%(c_name)s_members(v, *obj, &err); +-- +2.23.0 + diff --git a/qapi-Assert-non-input-visitors-see-only-valid-altern.patch b/qapi-Assert-non-input-visitors-see-only-valid-altern.patch new file mode 100644 index 0000000000000000000000000000000000000000..12453f0222c25d9ec3fd6bca287b634bf188ff16 --- /dev/null +++ b/qapi-Assert-non-input-visitors-see-only-valid-altern.patch @@ -0,0 +1,39 @@ +From 7111a86e1ba23ff8d59886df03d8a1cd6c5aab43 Mon Sep 17 00:00:00 2001 +From: Markus Armbruster +Date: Fri, 24 Apr 2020 10:43:34 +0200 +Subject: [PATCH 083/709] qapi: Assert non-input visitors see only valid + alternate tags + +An alternate type's visit_type_FOO() fails when it runs into an +invalid ->type. + +This is appropriate with an input visitor: visit_start_alternate() +sets ->type according to the input, and bad input can lead to bad +->type. + +It should never happen with an output, clone or dealloc visitor: if it +did, the alternate being output, cloned or deallocated would be messed +up beyond repair. Assert that. + +Signed-off-by: Markus Armbruster +Reviewed-by: Eric Blake +Message-Id: <20200424084338.26803-12-armbru@redhat.com> +--- + scripts/qapi/visit.py | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/scripts/qapi/visit.py b/scripts/qapi/visit.py +index 678109dfb5..d5d7a1031f 100644 +--- a/scripts/qapi/visit.py ++++ b/scripts/qapi/visit.py +@@ -232,6 +232,7 @@ void visit_type_%(c_name)s(Visitor *v, const char *name, %(c_name)s **obj, Error + case QTYPE_NONE: + abort(); + default: ++ assert(visit_is_input(v)); + error_setg(&err, QERR_INVALID_PARAMETER_TYPE, name ? name : "null", + "%(name)s"); + /* Avoid passing invalid *obj to qapi_free_%(c_name)s() */ +-- +2.23.0 + diff --git a/qapi-Assert-non-input-visitors-see-only-valid-narrow.patch b/qapi-Assert-non-input-visitors-see-only-valid-narrow.patch new file mode 100644 index 0000000000000000000000000000000000000000..4623abc8478bd856516895444384f07e9d115f11 --- /dev/null +++ b/qapi-Assert-non-input-visitors-see-only-valid-narrow.patch @@ -0,0 +1,57 @@ +From faad584adb48737aa3b39984786442a1a9c42aa4 Mon Sep 17 00:00:00 2001 +From: Markus Armbruster +Date: Fri, 24 Apr 2020 10:43:32 +0200 +Subject: [PATCH 081/709] qapi: Assert non-input visitors see only valid narrow + integers + +visit_type_intN() and visit_type_uintN() fail when the value is out of +bounds. + +This is appropriate with an input visitor: the value comes from input, +and input may be bad. + +It should never happen with the other visitors: the value comes from +the caller, and callers must keep it within bounds. Assert that. + +Signed-off-by: Markus Armbruster +Reviewed-by: Eric Blake +Message-Id: <20200424084338.26803-10-armbru@redhat.com> +--- + qapi/qapi-visit-core.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/qapi/qapi-visit-core.c b/qapi/qapi-visit-core.c +index 80ca83bcb9..74aa9c04bd 100644 +--- a/qapi/qapi-visit-core.c ++++ b/qapi/qapi-visit-core.c +@@ -160,10 +160,13 @@ static void visit_type_uintN(Visitor *v, uint64_t *obj, const char *name, + Error *err = NULL; + uint64_t value = *obj; + ++ assert(v->type == VISITOR_INPUT || value <= max); ++ + v->type_uint64(v, name, &value, &err); + if (err) { + error_propagate(errp, err); + } else if (value > max) { ++ assert(v->type == VISITOR_INPUT); + error_setg(errp, QERR_INVALID_PARAMETER_VALUE, + name ? name : "null", type); + } else { +@@ -219,10 +222,13 @@ static void visit_type_intN(Visitor *v, int64_t *obj, const char *name, + Error *err = NULL; + int64_t value = *obj; + ++ assert(v->type == VISITOR_INPUT || (value >= min && value <= max)); ++ + v->type_int64(v, name, &value, &err); + if (err) { + error_propagate(errp, err); + } else if (value < min || value > max) { ++ assert(v->type == VISITOR_INPUT); + error_setg(errp, QERR_INVALID_PARAMETER_VALUE, + name ? name : "null", type); + } else { +-- +2.23.0 + diff --git a/qapi-Assert-output-visitors-see-only-valid-enum-valu.patch b/qapi-Assert-output-visitors-see-only-valid-enum-valu.patch new file mode 100644 index 0000000000000000000000000000000000000000..061e6bab39314aa3f386781b02c23d928000ba45 --- /dev/null +++ b/qapi-Assert-output-visitors-see-only-valid-enum-valu.patch @@ -0,0 +1,148 @@ +From 777d20cfa5735de298f378e9b90f0cd1caafdc2d Mon Sep 17 00:00:00 2001 +From: Markus Armbruster +Date: Fri, 24 Apr 2020 10:43:31 +0200 +Subject: [PATCH 080/709] qapi: Assert output visitors see only valid enum + values + +output_type_enum() fails when *obj is not a valid value of the enum +type. Should not happen. Drop the check, along with its unit tests. +This unmasks qapi_enum_lookup()'s assertion. + +Signed-off-by: Markus Armbruster +Reviewed-by: Eric Blake +Message-Id: <20200424084338.26803-9-armbru@redhat.com> +[Commit message tweaked] +--- + qapi/qapi-visit-core.c | 9 ------- + tests/test-qobject-output-visitor.c | 39 ----------------------------- + tests/test-string-output-visitor.c | 19 -------------- + 3 files changed, 67 deletions(-) + +diff --git a/qapi/qapi-visit-core.c b/qapi/qapi-visit-core.c +index d4aac206cf..80ca83bcb9 100644 +--- a/qapi/qapi-visit-core.c ++++ b/qapi/qapi-visit-core.c +@@ -341,15 +341,6 @@ static void output_type_enum(Visitor *v, const char *name, int *obj, + int value = *obj; + char *enum_str; + +- /* +- * TODO why is this an error, not an assertion? If assertion: +- * delete, and rely on qapi_enum_lookup() +- */ +- if (value < 0 || value >= lookup->size) { +- error_setg(errp, QERR_INVALID_PARAMETER, name ? name : "null"); +- return; +- } +- + enum_str = (char *)qapi_enum_lookup(lookup, value); + visit_type_str(v, name, &enum_str, errp); + } +diff --git a/tests/test-qobject-output-visitor.c b/tests/test-qobject-output-visitor.c +index d7761ebf84..1c856d9bd2 100644 +--- a/tests/test-qobject-output-visitor.c ++++ b/tests/test-qobject-output-visitor.c +@@ -141,21 +141,6 @@ static void test_visitor_out_enum(TestOutputVisitorData *data, + } + } + +-static void test_visitor_out_enum_errors(TestOutputVisitorData *data, +- const void *unused) +-{ +- EnumOne i, bad_values[] = { ENUM_ONE__MAX, -1 }; +- +- for (i = 0; i < ARRAY_SIZE(bad_values) ; i++) { +- Error *err = NULL; +- +- visit_type_EnumOne(data->ov, "unused", &bad_values[i], &err); +- error_free_or_abort(&err); +- visitor_reset(data); +- } +-} +- +- + static void test_visitor_out_struct(TestOutputVisitorData *data, + const void *unused) + { +@@ -234,26 +219,6 @@ static void test_visitor_out_struct_nested(TestOutputVisitorData *data, + qapi_free_UserDefTwo(ud2); + } + +-static void test_visitor_out_struct_errors(TestOutputVisitorData *data, +- const void *unused) +-{ +- EnumOne bad_values[] = { ENUM_ONE__MAX, -1 }; +- UserDefOne u = {0}; +- UserDefOne *pu = &u; +- int i; +- +- for (i = 0; i < ARRAY_SIZE(bad_values) ; i++) { +- Error *err = NULL; +- +- u.has_enum1 = true; +- u.enum1 = bad_values[i]; +- visit_type_UserDefOne(data->ov, "unused", &pu, &err); +- error_free_or_abort(&err); +- visitor_reset(data); +- } +-} +- +- + static void test_visitor_out_list(TestOutputVisitorData *data, + const void *unused) + { +@@ -821,14 +786,10 @@ int main(int argc, char **argv) + &out_visitor_data, test_visitor_out_no_string); + output_visitor_test_add("/visitor/output/enum", + &out_visitor_data, test_visitor_out_enum); +- output_visitor_test_add("/visitor/output/enum-errors", +- &out_visitor_data, test_visitor_out_enum_errors); + output_visitor_test_add("/visitor/output/struct", + &out_visitor_data, test_visitor_out_struct); + output_visitor_test_add("/visitor/output/struct-nested", + &out_visitor_data, test_visitor_out_struct_nested); +- output_visitor_test_add("/visitor/output/struct-errors", +- &out_visitor_data, test_visitor_out_struct_errors); + output_visitor_test_add("/visitor/output/list", + &out_visitor_data, test_visitor_out_list); + output_visitor_test_add("/visitor/output/any", +diff --git a/tests/test-string-output-visitor.c b/tests/test-string-output-visitor.c +index 1be1540767..3bd732222c 100644 +--- a/tests/test-string-output-visitor.c ++++ b/tests/test-string-output-visitor.c +@@ -203,19 +203,6 @@ static void test_visitor_out_enum(TestOutputVisitorData *data, + } + } + +-static void test_visitor_out_enum_errors(TestOutputVisitorData *data, +- const void *unused) +-{ +- EnumOne i, bad_values[] = { ENUM_ONE__MAX, -1 }; +- +- for (i = 0; i < ARRAY_SIZE(bad_values) ; i++) { +- Error *err = NULL; +- +- visit_type_EnumOne(data->ov, "unused", &bad_values[i], &err); +- error_free_or_abort(&err); +- } +-} +- + static void + output_visitor_test_add(const char *testpath, + TestOutputVisitorData *data, +@@ -260,12 +247,6 @@ int main(int argc, char **argv) + &out_visitor_data, test_visitor_out_enum, false); + output_visitor_test_add("/string-visitor/output/enum-human", + &out_visitor_data, test_visitor_out_enum, true); +- output_visitor_test_add("/string-visitor/output/enum-errors", +- &out_visitor_data, test_visitor_out_enum_errors, +- false); +- output_visitor_test_add("/string-visitor/output/enum-errors-human", +- &out_visitor_data, test_visitor_out_enum_errors, +- true); + output_visitor_test_add("/string-visitor/output/intList", + &out_visitor_data, test_visitor_out_intList, false); + output_visitor_test_add("/string-visitor/output/intList-human", +-- +2.23.0 + diff --git a/qapi-Belatedly-update-visitor.h-s-big-comment-for-QA.patch b/qapi-Belatedly-update-visitor.h-s-big-comment-for-QA.patch new file mode 100644 index 0000000000000000000000000000000000000000..8f43bab6a5683f19c134153fdf86e416d847ccce --- /dev/null +++ b/qapi-Belatedly-update-visitor.h-s-big-comment-for-QA.patch @@ -0,0 +1,50 @@ +From 3777d36e674ca3b75b63413b4fb506b108309144 Mon Sep 17 00:00:00 2001 +From: Markus Armbruster +Date: Fri, 24 Apr 2020 10:43:24 +0200 +Subject: [PATCH 073/709] qapi: Belatedly update visitor.h's big comment for + QAPI modules + +Signed-off-by: Markus Armbruster +Reviewed-by: Eric Blake +Message-Id: <20200424084338.26803-2-armbru@redhat.com> +--- + include/qapi/visitor.h | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/include/qapi/visitor.h b/include/qapi/visitor.h +index c5b23851a1..f8a0fc1ea9 100644 +--- a/include/qapi/visitor.h ++++ b/include/qapi/visitor.h +@@ -58,7 +58,7 @@ + * + * where T is FOO for scalar types, and FOO * otherwise. The scalar + * visitors are declared here; the remaining visitors are generated in +- * qapi-visit.h. ++ * qapi-visit-MODULE.h. + * + * The @name parameter of visit_type_FOO() describes the relation + * between this QAPI value and its parent container. When visiting +@@ -86,16 +86,16 @@ + * by manual construction. + * + * For the QAPI object types (structs, unions, and alternates), there +- * is an additional generated function in qapi-visit.h compatible +- * with: ++ * is an additional generated function in qapi-visit-MODULE.h ++ * compatible with: + * + * void visit_type_FOO_members(Visitor *v, FOO *obj, Error **errp); + * + * for visiting the members of a type without also allocating the QAPI + * struct. + * +- * Additionally, in qapi-types.h, all QAPI pointer types (structs, +- * unions, alternates, and lists) have a generated function compatible ++ * Additionally, QAPI pointer types (structs, unions, alternates, and ++ * lists) have a generated function in qapi-types-MODULE.h compatible + * with: + * + * void qapi_free_FOO(FOO *obj); +-- +2.23.0 + diff --git a/qapi-Clean-up-visitor-s-recovery-from-input-with-inv.patch b/qapi-Clean-up-visitor-s-recovery-from-input-with-inv.patch new file mode 100644 index 0000000000000000000000000000000000000000..4ef95aa7526e7db88aaf164d10dad4ff4264e1bc --- /dev/null +++ b/qapi-Clean-up-visitor-s-recovery-from-input-with-inv.patch @@ -0,0 +1,42 @@ +From c978bd5226f1ed73456ac468a7ed50af3d24dc84 Mon Sep 17 00:00:00 2001 +From: Markus Armbruster +Date: Fri, 24 Apr 2020 10:43:33 +0200 +Subject: [PATCH 082/709] qapi: Clean up visitor's recovery from input with + invalid type + +An alternate type's visit_type_FOO() fails when it runs into an +invalid ->type. If it's an input visit, we then need to free the the +object we got from visit_start_alternate(). We do that with +qapi_free_FOO(), which uses the dealloc visitor. + +Trouble is that object is in a bad state: its ->type is invalid. So +the dealloc visitor will run into the same error again, and the error +recovery skips deallocating the alternate's (invalid) alternative. +Works, because qapi_free_FOO() ignores the error. + +Avoid it instead: free the messed up object with by g_free(). + +Signed-off-by: Markus Armbruster +Message-Id: <20200424084338.26803-11-armbru@redhat.com> +Reviewed-by: Eric Blake +--- + scripts/qapi/visit.py | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/scripts/qapi/visit.py b/scripts/qapi/visit.py +index e3467b770b..678109dfb5 100644 +--- a/scripts/qapi/visit.py ++++ b/scripts/qapi/visit.py +@@ -234,6 +234,9 @@ void visit_type_%(c_name)s(Visitor *v, const char *name, %(c_name)s **obj, Error + default: + error_setg(&err, QERR_INVALID_PARAMETER_TYPE, name ? name : "null", + "%(name)s"); ++ /* Avoid passing invalid *obj to qapi_free_%(c_name)s() */ ++ g_free(*obj); ++ *obj = NULL; + } + out_obj: + visit_end_alternate(v, (void **)obj); +-- +2.23.0 + diff --git a/qapi-Disallow-qmp_marshal_FOO-NULL.patch b/qapi-Disallow-qmp_marshal_FOO-NULL.patch new file mode 100644 index 0000000000000000000000000000000000000000..6cd39f4e0a97f518ca9513404a59581cdeff0761 --- /dev/null +++ b/qapi-Disallow-qmp_marshal_FOO-NULL.patch @@ -0,0 +1,126 @@ +From 2061487bdba7fb9077efc09210224b42fad7d18f Mon Sep 17 00:00:00 2001 +From: Markus Armbruster +Date: Fri, 24 Apr 2020 10:43:37 +0200 +Subject: [PATCH 086/709] qapi: Disallow qmp_marshal_FOO(NULL, ...) + +For QMP commands without arguments, gen_marshal() laboriously +generates a qmp_marshal_FOO() that copes with null @args. Turns +there's just one caller that passes null instead of an empty QDict. +Adjust that caller, and simplify gen_marshal(). + +Signed-off-by: Markus Armbruster +Message-Id: <20200424084338.26803-15-armbru@redhat.com> +Reviewed-by: Eric Blake +--- + docs/devel/qapi-code-gen.txt | 2 +- + monitor/qmp.c | 5 ++++- + scripts/qapi/commands.py | 26 ++------------------------ + 3 files changed, 7 insertions(+), 26 deletions(-) + +diff --git a/docs/devel/qapi-code-gen.txt b/docs/devel/qapi-code-gen.txt +index c6dd1891c3..a7794ef658 100644 +--- a/docs/devel/qapi-code-gen.txt ++++ b/docs/devel/qapi-code-gen.txt +@@ -1579,8 +1579,8 @@ Example: + void qmp_marshal_my_command(QDict *args, QObject **ret, Error **errp) + { + Error *err = NULL; +- UserDefOne *retval; + Visitor *v; ++ UserDefOne *retval; + q_obj_my_command_arg arg = {0}; + + v = qobject_input_visitor_new(QOBJECT(args)); +diff --git a/monitor/qmp.c b/monitor/qmp.c +index f89e7daf27..d433ceae5b 100644 +--- a/monitor/qmp.c ++++ b/monitor/qmp.c +@@ -322,9 +322,12 @@ static QDict *qmp_greeting(MonitorQMP *mon) + { + QList *cap_list = qlist_new(); + QObject *ver = NULL; ++ QDict *args; + QMPCapability cap; + +- qmp_marshal_query_version(NULL, &ver, NULL); ++ args = qdict_new(); ++ qmp_marshal_query_version(args, &ver, NULL); ++ qobject_unref(args); + + for (cap = 0; cap < QMP_CAPABILITY__MAX; cap++) { + if (mon->capab_offered[cap]) { +diff --git a/scripts/qapi/commands.py b/scripts/qapi/commands.py +index bc30876c88..f545903567 100644 +--- a/scripts/qapi/commands.py ++++ b/scripts/qapi/commands.py +@@ -104,6 +104,7 @@ def gen_marshal(name, arg_type, boxed, ret_type): + %(proto)s + { + Error *err = NULL; ++ Visitor *v; + ''', + proto=build_marshal_proto(name)) + +@@ -117,21 +118,14 @@ def gen_marshal(name, arg_type, boxed, ret_type): + visit_members = ('visit_type_%s_members(v, &arg, &err);' + % arg_type.c_name()) + ret += mcgen(''' +- Visitor *v; + %(c_name)s arg = {0}; +- + ''', + c_name=arg_type.c_name()) + else: + visit_members = '' +- ret += mcgen(''' +- Visitor *v = NULL; +- +- if (args) { +-''') +- push_indent() + + ret += mcgen(''' ++ + v = qobject_input_visitor_new(QOBJECT(args)); + visit_start_struct(v, NULL, NULL, 0, &err); + if (err) { +@@ -148,12 +142,6 @@ def gen_marshal(name, arg_type, boxed, ret_type): + ''', + visit_members=visit_members) + +- if not have_args: +- pop_indent() +- ret += mcgen(''' +- } +-''') +- + ret += gen_call(name, arg_type, boxed, ret_type) + + ret += mcgen(''' +@@ -168,10 +156,6 @@ out: + % arg_type.c_name()) + else: + visit_members = '' +- ret += mcgen(''' +- if (args) { +-''') +- push_indent() + + ret += mcgen(''' + v = qapi_dealloc_visitor_new(); +@@ -182,12 +166,6 @@ out: + ''', + visit_members=visit_members) + +- if not have_args: +- pop_indent() +- ret += mcgen(''' +- } +-''') +- + ret += mcgen(''' + } + ''') +-- +2.23.0 + diff --git a/qapi-Document-errp-usage-more-thoroughly-in-visitor..patch b/qapi-Document-errp-usage-more-thoroughly-in-visitor..patch new file mode 100644 index 0000000000000000000000000000000000000000..e5154e9abe7096c2894e0fcdd3f424d32b7e3f52 --- /dev/null +++ b/qapi-Document-errp-usage-more-thoroughly-in-visitor..patch @@ -0,0 +1,141 @@ +From c5460d5e19b4c531e86f8be0e00ab463fae7548b Mon Sep 17 00:00:00 2001 +From: Markus Armbruster +Date: Fri, 24 Apr 2020 10:43:27 +0200 +Subject: [PATCH 076/709] qapi: Document @errp usage more thoroughly in + visitor.h + +Signed-off-by: Markus Armbruster +Reviewed-by: Eric Blake +Message-Id: <20200424084338.26803-5-armbru@redhat.com> +--- + include/qapi/visitor.h | 37 +++++++++++++++++++++++-------------- + 1 file changed, 23 insertions(+), 14 deletions(-) + +diff --git a/include/qapi/visitor.h b/include/qapi/visitor.h +index c5d0ce9184..09df7099c6 100644 +--- a/include/qapi/visitor.h ++++ b/include/qapi/visitor.h +@@ -284,9 +284,7 @@ void visit_free(Visitor *v); + * into *@obj. @obj may also be NULL for a virtual walk, in which + * case @size is ignored. + * +- * @errp obeys typical error usage, and reports failures such as a +- * member @name is not present, or present but not an object. On +- * error, input visitors set *@obj to NULL. ++ * On failure, set *@obj to NULL and store an error through @errp. + * + * After visit_start_struct() succeeds, the caller may visit its + * members one after the other, passing the member's name and address +@@ -303,8 +301,7 @@ void visit_start_struct(Visitor *v, const char *name, void **obj, + /* + * Prepare for completing an object visit. + * +- * @errp obeys typical error usage, and reports failures such as +- * unparsed keys remaining in the input stream. ++ * On failure, store an error through @errp. + * + * Should be called prior to visit_end_struct() if all other + * intermediate visit steps were successful, to allow the visitor one +@@ -340,9 +337,7 @@ void visit_end_struct(Visitor *v, void **obj); + * allow @list to be NULL for a virtual walk, in which case @size is + * ignored. + * +- * @errp obeys typical error usage, and reports failures such as a +- * member @name is not present, or present but not a list. On error, +- * input visitors set *@list to NULL. ++ * On failure, set *@list to NULL and store an error through @errp. + * + * After visit_start_list() succeeds, the caller may visit its members + * one after the other. A real visit (where @list is non-NULL) uses +@@ -376,8 +371,7 @@ GenericList *visit_next_list(Visitor *v, GenericList *tail, size_t size); + /* + * Prepare for completing a list visit. + * +- * @errp obeys typical error usage, and reports failures such as +- * unvisited list tail remaining in the input stream. ++ * On failure, store an error through @errp. + * + * Should be called prior to visit_end_list() if all other + * intermediate visit steps were successful, to allow the visitor one +@@ -409,8 +403,10 @@ void visit_end_list(Visitor *v, void **list); + * + * @obj must not be NULL. Input and clone visitors use @size to + * determine how much memory to allocate into *@obj, then determine +- * the qtype of the next thing to be visited, stored in (*@obj)->type. +- * Other visitors will leave @obj unchanged. ++ * the qtype of the next thing to be visited, and store it in ++ * (*@obj)->type. Other visitors leave @obj unchanged. ++ * ++ * On failure, set *@obj to NULL and store an error through @errp. + * + * If successful, this must be paired with visit_end_alternate() with + * the same @obj to clean up, even if visiting the contents of the +@@ -463,8 +459,9 @@ bool visit_optional(Visitor *v, const char *name, bool *present); + * + * Currently, all input visitors parse text input, and all output + * visitors produce text output. The mapping between enumeration +- * values and strings is done by the visitor core, using @strings; it +- * should be the ENUM_lookup array from visit-types.h. ++ * values and strings is done by the visitor core, using @lookup. ++ * ++ * On failure, store an error through @errp. + * + * May call visit_type_str() under the hood, and the enum visit may + * fail even if the corresponding string visit succeeded; this implies +@@ -488,6 +485,8 @@ bool visit_is_input(Visitor *v); + * + * @obj must be non-NULL. Input visitors set *@obj to the value; + * other visitors will leave *@obj unchanged. ++ * ++ * On failure, store an error through @errp. + */ + void visit_type_int(Visitor *v, const char *name, int64_t *obj, Error **errp); + +@@ -564,6 +563,8 @@ void visit_type_size(Visitor *v, const char *name, uint64_t *obj, + * + * @obj must be non-NULL. Input visitors set *@obj to the value; + * other visitors will leave *@obj unchanged. ++ * ++ * On failure, store an error through @errp. + */ + void visit_type_bool(Visitor *v, const char *name, bool *obj, Error **errp); + +@@ -581,6 +582,8 @@ void visit_type_bool(Visitor *v, const char *name, bool *obj, Error **errp); + * It is safe to cast away const when preparing a (const char *) value + * into @obj for use by an output visitor. + * ++ * On failure, set *@obj to NULL and store an error through @errp. ++ * + * FIXME: Callers that try to output NULL *obj should not be allowed. + */ + void visit_type_str(Visitor *v, const char *name, char **obj, Error **errp); +@@ -594,6 +597,8 @@ void visit_type_str(Visitor *v, const char *name, char **obj, Error **errp); + * @obj must be non-NULL. Input visitors set *@obj to the value; + * other visitors will leave *@obj unchanged. Visitors should + * document if infinity or NaN are not permitted. ++ * ++ * On failure, store an error through @errp. + */ + void visit_type_number(Visitor *v, const char *name, double *obj, + Error **errp); +@@ -608,6 +613,8 @@ void visit_type_number(Visitor *v, const char *name, double *obj, + * other visitors will leave *@obj unchanged. *@obj must be non-NULL + * for output visitors. + * ++ * On failure, set *@obj to NULL and store an error through @errp. ++ * + * Note that some kinds of input can't express arbitrary QObject. + * E.g. the visitor returned by qobject_input_visitor_new_keyval() + * can't create numbers or booleans, only strings. +@@ -622,6 +629,8 @@ void visit_type_any(Visitor *v, const char *name, QObject **obj, Error **errp); + * + * @obj must be non-NULL. Input visitors set *@obj to the value; + * other visitors ignore *@obj. ++ * ++ * On failure, set *@obj to NULL and store an error through @errp. + */ + void visit_type_null(Visitor *v, const char *name, QNull **obj, + Error **errp); +-- +2.23.0 + diff --git a/qapi-Fix-Visitor-contract-for-start_alternate.patch b/qapi-Fix-Visitor-contract-for-start_alternate.patch new file mode 100644 index 0000000000000000000000000000000000000000..8728c057fa40ce8c91863d70e7f199b8aeb75524 --- /dev/null +++ b/qapi-Fix-Visitor-contract-for-start_alternate.patch @@ -0,0 +1,66 @@ +From 8b7ce95b46815f274aed52857260cb180f6fade3 Mon Sep 17 00:00:00 2001 +From: Markus Armbruster +Date: Fri, 24 Apr 2020 10:43:30 +0200 +Subject: [PATCH 079/709] qapi: Fix Visitor contract for start_alternate() + +The contract demands v->start_alternate() for input and dealloc +visitors, but visit_start_alternate() actually requires it for input +and clone visitors. Fix the contract, and delete superfluous +qapi_dealloc_start_alternate(). + +Signed-off-by: Markus Armbruster +Reviewed-by: Eric Blake +Message-Id: <20200424084338.26803-8-armbru@redhat.com> +--- + include/qapi/visitor-impl.h | 5 ++--- + qapi/qapi-dealloc-visitor.c | 7 ------- + 2 files changed, 2 insertions(+), 10 deletions(-) + +diff --git a/include/qapi/visitor-impl.h b/include/qapi/visitor-impl.h +index 8ccb3b6c20..252206dc0d 100644 +--- a/include/qapi/visitor-impl.h ++++ b/include/qapi/visitor-impl.h +@@ -67,13 +67,12 @@ struct Visitor + /* Must be set */ + void (*end_list)(Visitor *v, void **list); + +- /* Must be set by input and dealloc visitors to visit alternates; +- * optional for output visitors. */ ++ /* Must be set by input and clone visitors to visit alternates */ + void (*start_alternate)(Visitor *v, const char *name, + GenericAlternate **obj, size_t size, + Error **errp); + +- /* Optional, needed for dealloc visitor */ ++ /* Optional */ + void (*end_alternate)(Visitor *v, void **obj); + + /* Must be set */ +diff --git a/qapi/qapi-dealloc-visitor.c b/qapi/qapi-dealloc-visitor.c +index d192724b13..2239fc6417 100644 +--- a/qapi/qapi-dealloc-visitor.c ++++ b/qapi/qapi-dealloc-visitor.c +@@ -34,12 +34,6 @@ static void qapi_dealloc_end_struct(Visitor *v, void **obj) + } + } + +-static void qapi_dealloc_start_alternate(Visitor *v, const char *name, +- GenericAlternate **obj, size_t size, +- Error **errp) +-{ +-} +- + static void qapi_dealloc_end_alternate(Visitor *v, void **obj) + { + if (obj) { +@@ -123,7 +117,6 @@ Visitor *qapi_dealloc_visitor_new(void) + v->visitor.type = VISITOR_DEALLOC; + v->visitor.start_struct = qapi_dealloc_start_struct; + v->visitor.end_struct = qapi_dealloc_end_struct; +- v->visitor.start_alternate = qapi_dealloc_start_alternate; + v->visitor.end_alternate = qapi_dealloc_end_alternate; + v->visitor.start_list = qapi_dealloc_start_list; + v->visitor.next_list = qapi_dealloc_next_list; +-- +2.23.0 + diff --git a/qapi-Fix-the-virtual-walk-example-in-visitor.h-s-big.patch b/qapi-Fix-the-virtual-walk-example-in-visitor.h-s-big.patch new file mode 100644 index 0000000000000000000000000000000000000000..aba02bdda6f2bad76da186ab55127b3f9bf13284 --- /dev/null +++ b/qapi-Fix-the-virtual-walk-example-in-visitor.h-s-big.patch @@ -0,0 +1,43 @@ +From 294c90662ac9daae2c3bbf608296cf037925bd95 Mon Sep 17 00:00:00 2001 +From: Markus Armbruster +Date: Fri, 24 Apr 2020 10:43:25 +0200 +Subject: [PATCH 074/709] qapi: Fix the virtual walk example in visitor.h's big + comment + +Call visit_check_list(). Missed in commit a4a1c70dc7 "qapi: Make +input visitors detect unvisited list tails". + +Drop an irrelevant error_propagate() while there. + +Signed-off-by: Markus Armbruster +Reviewed-by: Eric Blake +Message-Id: <20200424084338.26803-3-armbru@redhat.com> +--- + include/qapi/visitor.h | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/include/qapi/visitor.h b/include/qapi/visitor.h +index f8a0fc1ea9..7f63e4c381 100644 +--- a/include/qapi/visitor.h ++++ b/include/qapi/visitor.h +@@ -215,6 +215,9 @@ + * goto outlist; + * } + * outlist: ++ * if (!err) { ++ * visit_check_list(v, &err); ++ * } + * visit_end_list(v, NULL); + * if (!err) { + * visit_check_struct(v, &err); +@@ -222,7 +225,6 @@ + * outobj: + * visit_end_struct(v, NULL); + * out: +- * error_propagate(errp, err); + * visit_free(v); + * + */ +-- +2.23.0 + diff --git a/qapi-Fix-typo-in-visit_start_list-s-contract.patch b/qapi-Fix-typo-in-visit_start_list-s-contract.patch new file mode 100644 index 0000000000000000000000000000000000000000..93efe0376daca71369e5e77d6304424c6bab33d7 --- /dev/null +++ b/qapi-Fix-typo-in-visit_start_list-s-contract.patch @@ -0,0 +1,31 @@ +From 782586c77103d297f38e78950dfbe2a31a3b2924 Mon Sep 17 00:00:00 2001 +From: Markus Armbruster +Date: Fri, 24 Apr 2020 10:43:26 +0200 +Subject: [PATCH 075/709] qapi: Fix typo in visit_start_list()'s contract + +Signed-off-by: Markus Armbruster +Reviewed-by: Eric Blake +Message-Id: <20200424084338.26803-4-armbru@redhat.com> +--- + include/qapi/visitor.h | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/include/qapi/visitor.h b/include/qapi/visitor.h +index 7f63e4c381..c5d0ce9184 100644 +--- a/include/qapi/visitor.h ++++ b/include/qapi/visitor.h +@@ -345,9 +345,9 @@ void visit_end_struct(Visitor *v, void **obj); + * input visitors set *@list to NULL. + * + * After visit_start_list() succeeds, the caller may visit its members +- * one after the other. A real visit (where @obj is non-NULL) uses ++ * one after the other. A real visit (where @list is non-NULL) uses + * visit_next_list() for traversing the linked list, while a virtual +- * visit (where @obj is NULL) uses other means. For each list ++ * visit (where @list is NULL) uses other means. For each list + * element, call the appropriate visit_type_FOO() with name set to + * NULL and obj set to the address of the value member of the list + * element. Finally, visit_end_list() needs to be called with the +-- +2.23.0 + diff --git a/qapi-Generate-simpler-marshalling-code-when-no-argum.patch b/qapi-Generate-simpler-marshalling-code-when-no-argum.patch new file mode 100644 index 0000000000000000000000000000000000000000..104488f26c2806e9d560d6207edfdb9d4ccee37e --- /dev/null +++ b/qapi-Generate-simpler-marshalling-code-when-no-argum.patch @@ -0,0 +1,114 @@ +From 89bf68f933393a1bc0de4d07b59ffa8920da130f Mon Sep 17 00:00:00 2001 +From: Markus Armbruster +Date: Fri, 24 Apr 2020 10:43:38 +0200 +Subject: [PATCH 087/709] qapi: Generate simpler marshalling code when no + arguments + +When command FOO has no arguments, its generated qmp_marshal_FOO() is +a bit confusing. Make it simpler: + + visit_start_struct(v, NULL, NULL, 0, &err); + if (err) { + goto out; + } +- +- if (!err) { +- visit_check_struct(v, &err); +- } ++ visit_check_struct(v, &err); + visit_end_struct(v, NULL); + if (err) { + goto out; + } + +Signed-off-by: Markus Armbruster +Message-Id: <20200424084338.26803-16-armbru@redhat.com> +Reviewed-by: Eric Blake +--- + scripts/qapi/commands.py | 40 ++++++++++++++++++++++++---------------- + 1 file changed, 24 insertions(+), 16 deletions(-) + +diff --git a/scripts/qapi/commands.py b/scripts/qapi/commands.py +index f545903567..6809b0fb6e 100644 +--- a/scripts/qapi/commands.py ++++ b/scripts/qapi/commands.py +@@ -115,14 +115,10 @@ def gen_marshal(name, arg_type, boxed, ret_type): + c_type=ret_type.c_type()) + + if have_args: +- visit_members = ('visit_type_%s_members(v, &arg, &err);' +- % arg_type.c_name()) + ret += mcgen(''' + %(c_name)s arg = {0}; + ''', + c_name=arg_type.c_name()) +- else: +- visit_members = '' + + ret += mcgen(''' + +@@ -131,16 +127,27 @@ def gen_marshal(name, arg_type, boxed, ret_type): + if (err) { + goto out; + } +- %(visit_members)s ++''') ++ ++ if have_args: ++ ret += mcgen(''' ++ visit_type_%(c_arg_type)s_members(v, &arg, &err); + if (!err) { + visit_check_struct(v, &err); + } ++''', ++ c_arg_type=arg_type.c_name()) ++ else: ++ ret += mcgen(''' ++ visit_check_struct(v, &err); ++''') ++ ++ ret += mcgen(''' + visit_end_struct(v, NULL); + if (err) { + goto out; + } +-''', +- visit_members=visit_members) ++''') + + ret += gen_call(name, arg_type, boxed, ret_type) + +@@ -151,20 +158,21 @@ out: + visit_free(v); + ''') + +- if have_args: +- visit_members = ('visit_type_%s_members(v, &arg, NULL);' +- % arg_type.c_name()) +- else: +- visit_members = '' +- + ret += mcgen(''' + v = qapi_dealloc_visitor_new(); + visit_start_struct(v, NULL, NULL, 0, NULL); +- %(visit_members)s ++''') ++ ++ if have_args: ++ ret += mcgen(''' ++ visit_type_%(c_arg_type)s_members(v, &arg, NULL); ++''', ++ c_arg_type=arg_type.c_name()) ++ ++ ret += mcgen(''' + visit_end_struct(v, NULL); + visit_free(v); +-''', +- visit_members=visit_members) ++''') + + ret += mcgen(''' + } +-- +2.23.0 + diff --git a/qapi-Only-input-visitors-can-actually-fail.patch b/qapi-Only-input-visitors-can-actually-fail.patch new file mode 100644 index 0000000000000000000000000000000000000000..537190e5aadbb765d7bce576f30d848da4ee5616 --- /dev/null +++ b/qapi-Only-input-visitors-can-actually-fail.patch @@ -0,0 +1,318 @@ +From 1f5842487ad5b3d59ea32742e30dc7441f413e6c Mon Sep 17 00:00:00 2001 +From: Markus Armbruster +Date: Fri, 24 Apr 2020 10:43:35 +0200 +Subject: [PATCH 084/709] qapi: Only input visitors can actually fail + +The previous few commits have made this more obvious, and removed the +one exception. Time to clarify the documentation, and drop dead error +checking. + +Signed-off-by: Markus Armbruster +Reviewed-by: Eric Blake +Message-Id: <20200424084338.26803-13-armbru@redhat.com> +--- + block.c | 9 +-------- + block/sheepdog.c | 9 +-------- + blockdev.c | 16 ++------------- + hw/core/machine-hmp-cmds.c | 2 +- + include/qapi/visitor-impl.h | 4 ++++ + include/qapi/visitor.h | 40 ++++++++++++++++++++++--------------- + monitor/hmp-cmds.c | 3 ++- + 7 files changed, 35 insertions(+), 48 deletions(-) + +diff --git a/block.c b/block.c +index 2e3905c99e..c11385ae05 100644 +--- a/block.c ++++ b/block.c +@@ -2982,7 +2982,6 @@ BdrvChild *bdrv_open_child(const char *filename, + BlockDriverState *bdrv_open_blockdev_ref(BlockdevRef *ref, Error **errp) + { + BlockDriverState *bs = NULL; +- Error *local_err = NULL; + QObject *obj = NULL; + QDict *qdict = NULL; + const char *reference = NULL; +@@ -2995,11 +2994,7 @@ BlockDriverState *bdrv_open_blockdev_ref(BlockdevRef *ref, Error **errp) + assert(ref->type == QTYPE_QDICT); + + v = qobject_output_visitor_new(&obj); +- visit_type_BlockdevOptions(v, NULL, &options, &local_err); +- if (local_err) { +- error_propagate(errp, local_err); +- goto fail; +- } ++ visit_type_BlockdevOptions(v, NULL, &options, &error_abort); + visit_complete(v, &obj); + + qdict = qobject_to(QDict, obj); +@@ -3017,8 +3012,6 @@ BlockDriverState *bdrv_open_blockdev_ref(BlockdevRef *ref, Error **errp) + + bs = bdrv_open_inherit(NULL, reference, qdict, 0, NULL, NULL, errp); + obj = NULL; +- +-fail: + qobject_unref(obj); + visit_free(v); + return bs; +diff --git a/block/sheepdog.c b/block/sheepdog.c +index 59f7ebb171..5f3aead038 100644 +--- a/block/sheepdog.c ++++ b/block/sheepdog.c +@@ -1854,19 +1854,12 @@ static int sd_create_prealloc(BlockdevOptionsSheepdog *location, int64_t size, + Visitor *v; + QObject *obj = NULL; + QDict *qdict; +- Error *local_err = NULL; + int ret; + + v = qobject_output_visitor_new(&obj); +- visit_type_BlockdevOptionsSheepdog(v, NULL, &location, &local_err); ++ visit_type_BlockdevOptionsSheepdog(v, NULL, &location, &error_abort); + visit_free(v); + +- if (local_err) { +- error_propagate(errp, local_err); +- qobject_unref(obj); +- return -EINVAL; +- } +- + qdict = qobject_to(QDict, obj); + qdict_flatten(qdict); + +diff --git a/blockdev.c b/blockdev.c +index 5faddaa705..9da960b1e7 100644 +--- a/blockdev.c ++++ b/blockdev.c +@@ -3725,14 +3725,8 @@ void qmp_blockdev_add(BlockdevOptions *options, Error **errp) + QObject *obj; + Visitor *v = qobject_output_visitor_new(&obj); + QDict *qdict; +- Error *local_err = NULL; +- +- visit_type_BlockdevOptions(v, NULL, &options, &local_err); +- if (local_err) { +- error_propagate(errp, local_err); +- goto fail; +- } + ++ visit_type_BlockdevOptions(v, NULL, &options, &error_abort); + visit_complete(v, &obj); + qdict = qobject_to(QDict, obj); + +@@ -3760,7 +3754,6 @@ void qmp_x_blockdev_reopen(BlockdevOptions *options, Error **errp) + AioContext *ctx; + QObject *obj; + Visitor *v = qobject_output_visitor_new(&obj); +- Error *local_err = NULL; + BlockReopenQueue *queue; + QDict *qdict; + +@@ -3777,12 +3770,7 @@ void qmp_x_blockdev_reopen(BlockdevOptions *options, Error **errp) + } + + /* Put all options in a QDict and flatten it */ +- visit_type_BlockdevOptions(v, NULL, &options, &local_err); +- if (local_err) { +- error_propagate(errp, local_err); +- goto fail; +- } +- ++ visit_type_BlockdevOptions(v, NULL, &options, &error_abort); + visit_complete(v, &obj); + qdict = qobject_to(QDict, obj); + +diff --git a/hw/core/machine-hmp-cmds.c b/hw/core/machine-hmp-cmds.c +index b76f7223af..39999c47c5 100644 +--- a/hw/core/machine-hmp-cmds.c ++++ b/hw/core/machine-hmp-cmds.c +@@ -113,7 +113,7 @@ void hmp_info_memdev(Monitor *mon, const QDict *qdict) + + while (m) { + v = string_output_visitor_new(false, &str); +- visit_type_uint16List(v, NULL, &m->value->host_nodes, NULL); ++ visit_type_uint16List(v, NULL, &m->value->host_nodes, &error_abort); + monitor_printf(mon, "memory backend: %s\n", m->value->id); + monitor_printf(mon, " size: %" PRId64 "\n", m->value->size); + monitor_printf(mon, " merge: %s\n", +diff --git a/include/qapi/visitor-impl.h b/include/qapi/visitor-impl.h +index 252206dc0d..98dc533d39 100644 +--- a/include/qapi/visitor-impl.h ++++ b/include/qapi/visitor-impl.h +@@ -43,6 +43,10 @@ typedef enum VisitorType { + + struct Visitor + { ++ /* ++ * Only input visitors may fail! ++ */ ++ + /* Must be set to visit structs */ + void (*start_struct)(Visitor *v, const char *name, void **obj, + size_t size, Error **errp); +diff --git a/include/qapi/visitor.h b/include/qapi/visitor.h +index 2d40d2fe0f..5573906966 100644 +--- a/include/qapi/visitor.h ++++ b/include/qapi/visitor.h +@@ -82,7 +82,7 @@ + * Each function also takes the customary @errp argument (see + * qapi/error.h for details), for reporting any errors (such as if a + * member @name is not present, or is present but not the specified +- * type). ++ * type). Only input visitors can fail. + * + * If an error is detected during visit_type_FOO() with an input + * visitor, then *@obj will be set to NULL for pointer types, and left +@@ -164,19 +164,14 @@ + * + * + * Foo *f = ...obtain populated object... +- * Error *err = NULL; + * Visitor *v; + * Type *result; + * + * v = FOO_visitor_new(..., &result); +- * visit_type_Foo(v, NULL, &f, &err); +- * if (err) { +- * ...handle error... +- * } else { +- * visit_complete(v, &result); +- * ...use result... +- * } ++ * visit_type_Foo(v, NULL, &f, &error_abort); ++ * visit_complete(v, &result); + * visit_free(v); ++ * ...use result... + * + * + * It is also possible to use the visitors to do a virtual walk, where +@@ -289,6 +284,7 @@ void visit_free(Visitor *v); + * case @size is ignored. + * + * On failure, set *@obj to NULL and store an error through @errp. ++ * Can happen only when @v is an input visitor. + * + * After visit_start_struct() succeeds, the caller may visit its + * members one after the other, passing the member's name and address +@@ -305,7 +301,8 @@ void visit_start_struct(Visitor *v, const char *name, void **obj, + /* + * Prepare for completing an object visit. + * +- * On failure, store an error through @errp. ++ * On failure, store an error through @errp. Can happen only when @v ++ * is an input visitor. + * + * Should be called prior to visit_end_struct() if all other + * intermediate visit steps were successful, to allow the visitor one +@@ -342,6 +339,7 @@ void visit_end_struct(Visitor *v, void **obj); + * ignored. + * + * On failure, set *@list to NULL and store an error through @errp. ++ * Can happen only when @v is an input visitor. + * + * After visit_start_list() succeeds, the caller may visit its members + * one after the other. A real visit (where @list is non-NULL) uses +@@ -375,7 +373,8 @@ GenericList *visit_next_list(Visitor *v, GenericList *tail, size_t size); + /* + * Prepare for completing a list visit. + * +- * On failure, store an error through @errp. ++ * On failure, store an error through @errp. Can happen only when @v ++ * is an input visitor. + * + * Should be called prior to visit_end_list() if all other + * intermediate visit steps were successful, to allow the visitor one +@@ -411,6 +410,7 @@ void visit_end_list(Visitor *v, void **list); + * (*@obj)->type. Other visitors leave @obj unchanged. + * + * On failure, set *@obj to NULL and store an error through @errp. ++ * Can happen only when @v is an input visitor. + * + * If successful, this must be paired with visit_end_alternate() with + * the same @obj to clean up, even if visiting the contents of the +@@ -465,11 +465,13 @@ bool visit_optional(Visitor *v, const char *name, bool *present); + * visitors produce text output. The mapping between enumeration + * values and strings is done by the visitor core, using @lookup. + * +- * On failure, store an error through @errp. ++ * On failure, store an error through @errp. Can happen only when @v ++ * is an input visitor. + * + * May call visit_type_str() under the hood, and the enum visit may + * fail even if the corresponding string visit succeeded; this implies +- * that visit_type_str() must have no unwelcome side effects. ++ * that an input visitor's visit_type_str() must have no unwelcome ++ * side effects. + */ + void visit_type_enum(Visitor *v, const char *name, int *obj, + const QEnumLookup *lookup, Error **errp); +@@ -495,7 +497,8 @@ bool visit_is_dealloc(Visitor *v); + * @obj must be non-NULL. Input visitors set *@obj to the value; + * other visitors will leave *@obj unchanged. + * +- * On failure, store an error through @errp. ++ * On failure, store an error through @errp. Can happen only when @v ++ * is an input visitor. + */ + void visit_type_int(Visitor *v, const char *name, int64_t *obj, Error **errp); + +@@ -573,7 +576,8 @@ void visit_type_size(Visitor *v, const char *name, uint64_t *obj, + * @obj must be non-NULL. Input visitors set *@obj to the value; + * other visitors will leave *@obj unchanged. + * +- * On failure, store an error through @errp. ++ * On failure, store an error through @errp. Can happen only when @v ++ * is an input visitor. + */ + void visit_type_bool(Visitor *v, const char *name, bool *obj, Error **errp); + +@@ -592,6 +596,7 @@ void visit_type_bool(Visitor *v, const char *name, bool *obj, Error **errp); + * into @obj for use by an output visitor. + * + * On failure, set *@obj to NULL and store an error through @errp. ++ * Can happen only when @v is an input visitor. + * + * FIXME: Callers that try to output NULL *obj should not be allowed. + */ +@@ -607,7 +612,8 @@ void visit_type_str(Visitor *v, const char *name, char **obj, Error **errp); + * other visitors will leave *@obj unchanged. Visitors should + * document if infinity or NaN are not permitted. + * +- * On failure, store an error through @errp. ++ * On failure, store an error through @errp. Can happen only when @v ++ * is an input visitor. + */ + void visit_type_number(Visitor *v, const char *name, double *obj, + Error **errp); +@@ -623,6 +629,7 @@ void visit_type_number(Visitor *v, const char *name, double *obj, + * for output visitors. + * + * On failure, set *@obj to NULL and store an error through @errp. ++ * Can happen only when @v is an input visitor. + * + * Note that some kinds of input can't express arbitrary QObject. + * E.g. the visitor returned by qobject_input_visitor_new_keyval() +@@ -640,6 +647,7 @@ void visit_type_any(Visitor *v, const char *name, QObject **obj, Error **errp); + * other visitors ignore *@obj. + * + * On failure, set *@obj to NULL and store an error through @errp. ++ * Can happen only when @v is an input visitor. + */ + void visit_type_null(Visitor *v, const char *name, QNull **obj, + Error **errp); +diff --git a/monitor/hmp-cmds.c b/monitor/hmp-cmds.c +index 9b94e67879..7f6e982dc8 100644 +--- a/monitor/hmp-cmds.c ++++ b/monitor/hmp-cmds.c +@@ -334,7 +334,8 @@ void hmp_info_migrate(Monitor *mon, const QDict *qdict) + Visitor *v; + char *str; + v = string_output_visitor_new(false, &str); +- visit_type_uint32List(v, NULL, &info->postcopy_vcpu_blocktime, NULL); ++ visit_type_uint32List(v, NULL, &info->postcopy_vcpu_blocktime, ++ &error_abort); + visit_complete(v, &str); + monitor_printf(mon, "postcopy vcpu blocktime: %s\n", str); + g_free(str); +-- +2.23.0 + diff --git a/qapi-Polish-prose-in-visitor.h.patch b/qapi-Polish-prose-in-visitor.h.patch new file mode 100644 index 0000000000000000000000000000000000000000..7961dd7c5afab237bafb08e61908b7c854ad6c4d --- /dev/null +++ b/qapi-Polish-prose-in-visitor.h.patch @@ -0,0 +1,185 @@ +From 554d6586ae96216771fe701c9d3a321e2adb057b Mon Sep 17 00:00:00 2001 +From: Markus Armbruster +Date: Fri, 24 Apr 2020 10:43:28 +0200 +Subject: [PATCH 077/709] qapi: Polish prose in visitor.h + +Signed-off-by: Markus Armbruster +Reviewed-by: Eric Blake +Message-Id: <20200424084338.26803-6-armbru@redhat.com> +--- + include/qapi/visitor.h | 104 +++++++++++++++++++++-------------------- + 1 file changed, 54 insertions(+), 50 deletions(-) + +diff --git a/include/qapi/visitor.h b/include/qapi/visitor.h +index 09df7099c6..a425ea514c 100644 +--- a/include/qapi/visitor.h ++++ b/include/qapi/visitor.h +@@ -25,19 +25,21 @@ + * for doing work at each node of a QAPI graph; it can also be used + * for a virtual walk, where there is no actual QAPI C struct. + * +- * There are four kinds of visitor classes: input visitors (QObject, +- * string, and QemuOpts) parse an external representation and build +- * the corresponding QAPI graph, output visitors (QObject and string) take +- * a completed QAPI graph and generate an external representation, the +- * dealloc visitor can take a QAPI graph (possibly partially +- * constructed) and recursively free its resources, and the clone +- * visitor performs a deep clone of one QAPI object to another. While +- * the dealloc and QObject input/output visitors are general, the string, +- * QemuOpts, and clone visitors have some implementation limitations; +- * see the documentation for each visitor for more details on what it +- * supports. Also, see visitor-impl.h for the callback contracts +- * implemented by each visitor, and docs/devel/qapi-code-gen.txt for more +- * about the QAPI code generator. ++ * There are four kinds of visitors: input visitors (QObject, string, ++ * and QemuOpts) parse an external representation and build the ++ * corresponding QAPI object, output visitors (QObject and string) ++ * take a QAPI object and generate an external representation, the ++ * dealloc visitor takes a QAPI object (possibly partially ++ * constructed) and recursively frees it, and the clone visitor ++ * performs a deep clone of a QAPI object. ++ * ++ * While the dealloc and QObject input/output visitors are general, ++ * the string, QemuOpts, and clone visitors have some implementation ++ * limitations; see the documentation for each visitor for more ++ * details on what it supports. Also, see visitor-impl.h for the ++ * callback contracts implemented by each visitor, and ++ * docs/devel/qapi-code-gen.txt for more about the QAPI code ++ * generator. + * + * All of the visitors are created via: + * +@@ -45,11 +47,15 @@ + * + * A visitor should be used for exactly one top-level visit_type_FOO() + * or virtual walk; if that is successful, the caller can optionally +- * call visit_complete() (for now, useful only for output visits, but +- * safe to call on all visits). Then, regardless of success or +- * failure, the user should call visit_free() to clean up resources. +- * It is okay to free the visitor without completing the visit, if +- * some other error is detected in the meantime. ++ * call visit_complete() (useful only for output visits, but safe to ++ * call on all visits). Then, regardless of success or failure, the ++ * user should call visit_free() to clean up resources. It is okay to ++ * free the visitor without completing the visit, if some other error ++ * is detected in the meantime. ++ * ++ * The clone and dealloc visitor should not be used directly outside ++ * of QAPI code. Use the qapi_free_FOO() and QAPI_CLONE() instead, ++ * described below. + * + * All QAPI types have a corresponding function with a signature + * roughly compatible with this: +@@ -68,22 +74,26 @@ + * alternate, @name should equal the name used for visiting the + * alternate. + * +- * The visit_type_FOO() functions expect a non-null @obj argument; +- * they allocate *@obj during input visits, leave it unchanged on +- * output visits, and recursively free any resources during a dealloc +- * visit. Each function also takes the customary @errp argument (see ++ * The visit_type_FOO() functions take a non-null @obj argument; they ++ * allocate *@obj during input visits, leave it unchanged during ++ * output and clone visits, and free it (recursively) during a dealloc ++ * visit. ++ * ++ * Each function also takes the customary @errp argument (see + * qapi/error.h for details), for reporting any errors (such as if a + * member @name is not present, or is present but not the specified + * type). + * + * If an error is detected during visit_type_FOO() with an input +- * visitor, then *@obj will be NULL for pointer types, and left +- * unchanged for scalar types. Using an output or clone visitor with +- * an incomplete object has undefined behavior (other than a special +- * case for visit_type_str() treating NULL like ""), while the dealloc +- * visitor safely handles incomplete objects. Since input visitors +- * never produce an incomplete object, such an object is possible only +- * by manual construction. ++ * visitor, then *@obj will be set to NULL for pointer types, and left ++ * unchanged for scalar types. ++ * ++ * Using an output or clone visitor with an incomplete object has ++ * undefined behavior (other than a special case for visit_type_str() ++ * treating NULL like ""), while the dealloc visitor safely handles ++ * incomplete objects. Since input visitors never produce an ++ * incomplete object, such an object is possible only by manual ++ * construction. + * + * For the QAPI object types (structs, unions, and alternates), there + * is an additional generated function in qapi-visit-MODULE.h +@@ -100,23 +110,20 @@ + * + * void qapi_free_FOO(FOO *obj); + * +- * where behaves like free() in that @obj may be NULL. Such objects +- * may also be used with the following macro, provided alongside the +- * clone visitor: ++ * Does nothing when @obj is NULL. ++ * ++ * Such objects may also be used with macro + * + * Type *QAPI_CLONE(Type, src); + * +- * in order to perform a deep clone of @src. Because of the generated +- * qapi_free functions and the QAPI_CLONE() macro, the clone and +- * dealloc visitor should not be used directly outside of QAPI code. ++ * in order to perform a deep clone of @src. + * +- * QAPI types can also inherit from a base class; when this happens, a +- * function is generated for easily going from the derived type to the +- * base type: ++ * For QAPI types can that inherit from a base type, a function is ++ * generated for going from the derived type to the base type: + * + * BASE *qapi_CHILD_base(CHILD *obj); + * +- * For a real QAPI struct, typical input usage involves: ++ * Typical input visitor usage involves: + * + * + * Foo *f; +@@ -153,7 +160,7 @@ + * qapi_free_FooList(l); + * + * +- * Similarly, typical output usage is: ++ * Typical output visitor usage: + * + * + * Foo *f = ...obtain populated object... +@@ -172,17 +179,8 @@ + * visit_free(v); + * + * +- * When visiting a real QAPI struct, this file provides several +- * helpers that rely on in-tree information to control the walk: +- * visit_optional() for the 'has_member' field associated with +- * optional 'member' in the C struct; and visit_next_list() for +- * advancing through a FooList linked list. Similarly, the +- * visit_is_input() helper makes it possible to write code that is +- * visitor-agnostic everywhere except for cleanup. Only the generated +- * visit_type functions need to use these helpers. +- * + * It is also possible to use the visitors to do a virtual walk, where +- * no actual QAPI struct is present. In this situation, decisions ++ * no actual QAPI object is present. In this situation, decisions + * about what needs to be walked are made by the calling code, and + * structured visits are split between pairs of start and end methods + * (where the end method must be called if the start function +@@ -227,6 +225,12 @@ + * out: + * visit_free(v); + * ++ * ++ * This file provides helpers for use by the generated ++ * visit_type_FOO(): visit_optional() for the 'has_member' field ++ * associated with optional 'member' in the C struct, ++ * visit_next_list() for advancing through a FooList linked list, and ++ * visit_is_input() for cleaning up on failure. + */ + + /*** Useful types ***/ +-- +2.23.0 + diff --git a/qcow2-Add-errp-to-preallocate_co.patch b/qcow2-Add-errp-to-preallocate_co.patch deleted file mode 100644 index 0b3dc7172270f7d9038c9ac5ea6ca4ae93a2d30d..0000000000000000000000000000000000000000 --- a/qcow2-Add-errp-to-preallocate_co.patch +++ /dev/null @@ -1,79 +0,0 @@ -From 360bd07471dfd1830246e8403ffdc9ba9d82f9d4 Mon Sep 17 00:00:00 2001 -From: Kevin Wolf -Date: Mon, 15 Apr 2019 16:56:07 +0200 -Subject: [PATCH] qcow2: Add errp to preallocate_co() - -We'll add a bdrv_co_truncate() call in the next patch which can return -an Error that we don't want to discard. So add an errp parameter to -preallocate_co(). - -Cc: qemu-stable@nongnu.org -Signed-off-by: Kevin Wolf -Reviewed-by: Eric Blake -(cherry-picked from commit 360bd07471dfd1830246e8403ffdc9ba9d82f9d4) ---- - block/qcow2.c | 11 ++++++----- - 1 file changed, 6 insertions(+), 5 deletions(-) - -diff --git a/block/qcow2.c b/block/qcow2.c -index dfac74c264..b4f9f5a240 100644 ---- a/block/qcow2.c -+++ b/block/qcow2.c -@@ -2721,7 +2721,7 @@ static int qcow2_set_up_encryption(BlockDriverState *bs, - * Returns: 0 on success, -errno on failure. - */ - static int coroutine_fn preallocate_co(BlockDriverState *bs, uint64_t offset, -- uint64_t new_length) -+ uint64_t new_length, Error **errp) - { - BDRVQcow2State *s = bs->opaque; - uint64_t bytes; -@@ -2738,6 +2738,7 @@ static int coroutine_fn preallocate_co(BlockDriverState *bs, uint64_t offset, - ret = qcow2_alloc_cluster_offset(bs, offset, &cur_bytes, - &host_offset, &meta); - if (ret < 0) { -+ error_setg_errno(errp, -ret, "Allocating clusters failed"); - return ret; - } - -@@ -2746,6 +2747,7 @@ static int coroutine_fn preallocate_co(BlockDriverState *bs, uint64_t offset, - - ret = qcow2_alloc_cluster_link_l2(bs, meta); - if (ret < 0) { -+ error_setg_errno(errp, -ret, "Mapping clusters failed"); - qcow2_free_any_clusters(bs, meta->alloc_offset, - meta->nb_clusters, QCOW2_DISCARD_NEVER); - return ret; -@@ -2775,6 +2777,7 @@ static int coroutine_fn preallocate_co(BlockDriverState *bs, uint64_t offset, - ret = bdrv_pwrite(s->data_file, (host_offset + cur_bytes) - 1, - &data, 1); - if (ret < 0) { -+ error_setg_errno(errp, -ret, "Writing to EOF failed"); - return ret; - } - } -@@ -3748,9 +3751,8 @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset, - break; - - case PREALLOC_MODE_METADATA: -- ret = preallocate_co(bs, old_length, offset); -+ ret = preallocate_co(bs, old_length, offset, errp); - if (ret < 0) { -- error_setg_errno(errp, -ret, "Preallocation failed"); - goto fail; - } - break; -@@ -3766,9 +3768,8 @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset, - /* With a data file, preallocation means just allocating the metadata - * and forwarding the truncate request to the data file */ - if (has_data_file(bs)) { -- ret = preallocate_co(bs, old_length, offset); -+ ret = preallocate_co(bs, old_length, offset, errp); - if (ret < 0) { -- error_setg_errno(errp, -ret, "Preallocation failed"); - goto fail; - } - break; --- -2.19.1 - diff --git a/qcow2-Add-incompatibility-note-between-backing-files.patch b/qcow2-Add-incompatibility-note-between-backing-files.patch new file mode 100644 index 0000000000000000000000000000000000000000..79fcdc1859c58605346007d61dec6e29456410c1 --- /dev/null +++ b/qcow2-Add-incompatibility-note-between-backing-files.patch @@ -0,0 +1,37 @@ +From a50c1f57e491ba17c0fcb7d285dfe04770be0a70 Mon Sep 17 00:00:00 2001 +From: Alberto Garcia +Date: Fri, 10 Apr 2020 14:18:15 +0200 +Subject: [PATCH 124/709] qcow2: Add incompatibility note between backing files + and raw external data files + +Backing files and raw external data files are mutually exclusive. +The documentation of the raw external data bit (in autoclear_features) +already indicates that, but we should also mention it on the other +side. + +Suggested-by: Eric Blake +Signed-off-by: Alberto Garcia +Message-Id: <20200410121816.8334-1-berto@igalia.com> +Reviewed-by: Eric Blake +Signed-off-by: Kevin Wolf +--- + docs/interop/qcow2.txt | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/docs/interop/qcow2.txt b/docs/interop/qcow2.txt +index 640e0eca40..298a031310 100644 +--- a/docs/interop/qcow2.txt ++++ b/docs/interop/qcow2.txt +@@ -25,6 +25,9 @@ The first cluster of a qcow2 image contains the file header: + is stored (NB: The string is not null terminated). 0 if the + image doesn't have a backing file. + ++ Note: backing files are incompatible with raw external data ++ files (auto-clear feature bit 1). ++ + 16 - 19: backing_file_size + Length of the backing file name in bytes. Must not be + longer than 1023 bytes. Undefined if the image doesn't have +-- +2.23.0 + diff --git a/qcow2-Allow-resize-of-images-with-internal-snapshots.patch b/qcow2-Allow-resize-of-images-with-internal-snapshots.patch new file mode 100644 index 0000000000000000000000000000000000000000..8140cecf762d871bea11ec9e6d56d060b5980b1f --- /dev/null +++ b/qcow2-Allow-resize-of-images-with-internal-snapshots.patch @@ -0,0 +1,223 @@ +From 7fa140abf69675b7b83af32de07fa8075c1da298 Mon Sep 17 00:00:00 2001 +From: Eric Blake +Date: Tue, 28 Apr 2020 14:26:47 -0500 +Subject: [PATCH 256/709] qcow2: Allow resize of images with internal snapshots + +We originally refused to allow resize of images with internal +snapshots because the v2 image format did not require the tracking of +snapshot size, making it impossible to safely revert to a snapshot +with a different size than the current view of the image. But the +snapshot size tracking was rectified in v3, and our recent fixes to +qemu-img amend (see 0a85af35) guarantee that we always have a valid +snapshot size. Thus, we no longer need to artificially limit image +resizes, but it does become one more thing that would prevent a +downgrade back to v2. And now that we support different-sized +snapshots, it's also easy to fix reverting to a snapshot to apply the +new size. + +Upgrade iotest 61 to cover this (we previously had NO coverage of +refusal to resize while snapshots exist). Note that the amend process +can fail but still have effects: in particular, since we break things +into upgrade, resize, downgrade, a failure during resize does not roll +back changes made during upgrade, nor does failure in downgrade roll +back a resize. But this situation is pre-existing even without this +patch; and without journaling, the best we could do is minimize the +chance of partial failure by collecting all changes prior to doing any +writes - which adds a lot of complexity but could still fail with EIO. +On the other hand, we are careful that even if we have partial +modification but then fail, the image is left viable (that is, we are +careful to sequence things so that after each successful cluster +write, there may be transient leaked clusters but no corrupt +metadata). And complicating the code to make it more transaction-like +is not worth the effort: a user can always request multiple 'qemu-img +amend' changing one thing each, if they need finer-grained control +over detecting the first failure than what they get by letting qemu +decide how to sequence multiple changes. + +Signed-off-by: Eric Blake +Reviewed-by: Max Reitz +Message-Id: <20200428192648.749066-3-eblake@redhat.com> +Signed-off-by: Max Reitz +--- + block/qcow2-snapshot.c | 20 ++++++++++++++++---- + block/qcow2.c | 25 ++++++++++++++++++++++--- + tests/qemu-iotests/061 | 35 +++++++++++++++++++++++++++++++++++ + tests/qemu-iotests/061.out | 28 ++++++++++++++++++++++++++++ + 4 files changed, 101 insertions(+), 7 deletions(-) + +diff --git a/block/qcow2-snapshot.c b/block/qcow2-snapshot.c +index 82c32d4c9b..2756b37d24 100644 +--- a/block/qcow2-snapshot.c ++++ b/block/qcow2-snapshot.c +@@ -23,6 +23,7 @@ + */ + + #include "qemu/osdep.h" ++#include "sysemu/block-backend.h" + #include "qapi/error.h" + #include "qcow2.h" + #include "qemu/bswap.h" +@@ -775,10 +776,21 @@ int qcow2_snapshot_goto(BlockDriverState *bs, const char *snapshot_id) + } + + if (sn->disk_size != bs->total_sectors * BDRV_SECTOR_SIZE) { +- error_report("qcow2: Loading snapshots with different disk " +- "size is not implemented"); +- ret = -ENOTSUP; +- goto fail; ++ BlockBackend *blk = blk_new_with_bs(bs, BLK_PERM_RESIZE, BLK_PERM_ALL, ++ &local_err); ++ if (!blk) { ++ error_report_err(local_err); ++ ret = -ENOTSUP; ++ goto fail; ++ } ++ ++ ret = blk_truncate(blk, sn->disk_size, true, PREALLOC_MODE_OFF, 0, ++ &local_err); ++ blk_unref(blk); ++ if (ret < 0) { ++ error_report_err(local_err); ++ goto fail; ++ } + } + + /* +diff --git a/block/qcow2.c b/block/qcow2.c +index 0edc7f4643..3e8b3d022b 100644 +--- a/block/qcow2.c ++++ b/block/qcow2.c +@@ -3989,9 +3989,12 @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset, + + qemu_co_mutex_lock(&s->lock); + +- /* cannot proceed if image has snapshots */ +- if (s->nb_snapshots) { +- error_setg(errp, "Can't resize an image which has snapshots"); ++ /* ++ * Even though we store snapshot size for all images, it was not ++ * required until v3, so it is not safe to proceed for v2. ++ */ ++ if (s->nb_snapshots && s->qcow_version < 3) { ++ error_setg(errp, "Can't resize a v2 image which has snapshots"); + ret = -ENOTSUP; + goto fail; + } +@@ -5005,6 +5008,7 @@ static int qcow2_downgrade(BlockDriverState *bs, int target_version, + BDRVQcow2State *s = bs->opaque; + int current_version = s->qcow_version; + int ret; ++ int i; + + /* This is qcow2_downgrade(), not qcow2_upgrade() */ + assert(target_version < current_version); +@@ -5022,6 +5026,21 @@ static int qcow2_downgrade(BlockDriverState *bs, int target_version, + return -ENOTSUP; + } + ++ /* ++ * If any internal snapshot has a different size than the current ++ * image size, or VM state size that exceeds 32 bits, downgrading ++ * is unsafe. Even though we would still use v3-compliant output ++ * to preserve that data, other v2 programs might not realize ++ * those optional fields are important. ++ */ ++ for (i = 0; i < s->nb_snapshots; i++) { ++ if (s->snapshots[i].vm_state_size > UINT32_MAX || ++ s->snapshots[i].disk_size != bs->total_sectors * BDRV_SECTOR_SIZE) { ++ error_setg(errp, "Internal snapshots prevent downgrade of image"); ++ return -ENOTSUP; ++ } ++ } ++ + /* clear incompatible features */ + if (s->incompatible_features & QCOW2_INCOMPAT_DIRTY) { + ret = qcow2_mark_clean(bs); +diff --git a/tests/qemu-iotests/061 b/tests/qemu-iotests/061 +index ce285d3084..10eb243164 100755 +--- a/tests/qemu-iotests/061 ++++ b/tests/qemu-iotests/061 +@@ -111,6 +111,41 @@ $PYTHON qcow2.py "$TEST_IMG" dump-header + $QEMU_IO -c "read -P 0x2a 42M 64k" "$TEST_IMG" | _filter_qemu_io + _check_test_img + ++echo ++echo "=== Testing resize with snapshots ===" ++echo ++_make_test_img -o "compat=0.10" 32M ++$QEMU_IO -c "write -P 0x2a 24M 64k" "$TEST_IMG" | _filter_qemu_io ++$QEMU_IMG snapshot -c foo "$TEST_IMG" ++$QEMU_IMG resize "$TEST_IMG" 64M && ++ echo "unexpected pass" ++$PYTHON qcow2.py "$TEST_IMG" dump-header | grep '^\(version\|size\|nb_snap\)' ++ ++$QEMU_IMG amend -o "compat=1.1,size=128M" "$TEST_IMG" || ++ echo "unexpected fail" ++$PYTHON qcow2.py "$TEST_IMG" dump-header | grep '^\(version\|size\|nb_snap\)' ++ ++$QEMU_IMG snapshot -c bar "$TEST_IMG" ++$QEMU_IMG resize --shrink "$TEST_IMG" 64M || ++ echo "unexpected fail" ++$PYTHON qcow2.py "$TEST_IMG" dump-header | grep '^\(version\|size\|nb_snap\)' ++ ++$QEMU_IMG amend -o "compat=0.10,size=32M" "$TEST_IMG" && ++ echo "unexpected pass" ++$PYTHON qcow2.py "$TEST_IMG" dump-header | grep '^\(version\|size\|nb_snap\)' ++ ++$QEMU_IMG snapshot -a bar "$TEST_IMG" || ++ echo "unexpected fail" ++$PYTHON qcow2.py "$TEST_IMG" dump-header | grep '^\(version\|size\|nb_snap\)' ++ ++$QEMU_IMG snapshot -d bar "$TEST_IMG" ++$QEMU_IMG amend -o "compat=0.10,size=32M" "$TEST_IMG" || ++ echo "unexpected fail" ++$PYTHON qcow2.py "$TEST_IMG" dump-header | grep '^\(version\|size\|nb_snap\)' ++ ++_check_test_img ++ ++ + echo + echo "=== Testing dirty lazy_refcounts=off ===" + echo +diff --git a/tests/qemu-iotests/061.out b/tests/qemu-iotests/061.out +index 413cc4e0f4..5a8d36d005 100644 +--- a/tests/qemu-iotests/061.out ++++ b/tests/qemu-iotests/061.out +@@ -271,6 +271,34 @@ read 65536/65536 bytes at offset 44040192 + 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + No errors were found on the image. + ++=== Testing resize with snapshots === ++ ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=33554432 ++wrote 65536/65536 bytes at offset 25165824 ++64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++qemu-img: Can't resize a v2 image which has snapshots ++version 2 ++size 33554432 ++nb_snapshots 1 ++version 3 ++size 134217728 ++nb_snapshots 1 ++Image resized. ++version 3 ++size 67108864 ++nb_snapshots 2 ++qemu-img: Internal snapshots prevent downgrade of image ++version 3 ++size 33554432 ++nb_snapshots 2 ++version 3 ++size 134217728 ++nb_snapshots 2 ++version 2 ++size 33554432 ++nb_snapshots 1 ++No errors were found on the image. ++ + === Testing dirty lazy_refcounts=off === + + Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +-- +2.23.0 + diff --git a/qcow2-Avoid-COW-during-metadata-preallocation.patch b/qcow2-Avoid-COW-during-metadata-preallocation.patch deleted file mode 100644 index 483d1199045004c8cbdabf467db08f664fa09bb0..0000000000000000000000000000000000000000 --- a/qcow2-Avoid-COW-during-metadata-preallocation.patch +++ /dev/null @@ -1,38 +0,0 @@ -From f29fbf7c6b1c9a84f6931c1c222716fbe073e6e4 Mon Sep 17 00:00:00 2001 -From: Kevin Wolf -Date: Mon, 15 Apr 2019 16:25:01 +0200 -Subject: [PATCH] qcow2: Avoid COW during metadata preallocation - -Limiting the allocation to INT_MAX bytes isn't particularly clever -because it means that the final cluster will be a partial cluster which -will be completed through a COW operation. This results in unnecessary -data read and write requests which lead to an unwanted non-sparse -filesystem block for metadata preallocation. - -Align the maximum allocation size down to the cluster size to avoid this -situation. - -Cc: qemu-stable@nongnu.org -Signed-off-by: Kevin Wolf -Reviewed-by: Eric Blake -(cherry-picked from commit f29fbf7c6b1c9a84f6931c1c222716fbe073e6e4) ---- - block/qcow2.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/block/qcow2.c b/block/qcow2.c -index 3ace3b2209..dfac74c264 100644 ---- a/block/qcow2.c -+++ b/block/qcow2.c -@@ -2734,7 +2734,7 @@ static int coroutine_fn preallocate_co(BlockDriverState *bs, uint64_t offset, - bytes = new_length - offset; - - while (bytes) { -- cur_bytes = MIN(bytes, INT_MAX); -+ cur_bytes = MIN(bytes, QEMU_ALIGN_DOWN(INT_MAX, s->cluster_size)); - ret = qcow2_alloc_cluster_offset(bs, offset, &cur_bytes, - &host_offset, &meta); - if (ret < 0) { --- -2.19.1 - diff --git a/qcow2-Avoid-integer-wraparound-in-qcow2_co_truncate.patch b/qcow2-Avoid-integer-wraparound-in-qcow2_co_truncate.patch new file mode 100644 index 0000000000000000000000000000000000000000..cae2cf5a030b90ff88c815ed530d4525519e57bf --- /dev/null +++ b/qcow2-Avoid-integer-wraparound-in-qcow2_co_truncate.patch @@ -0,0 +1,182 @@ +From e4d7019e1a81c61de6a925c3ac5bb6e62ea21b29 Mon Sep 17 00:00:00 2001 +From: Alberto Garcia +Date: Mon, 4 May 2020 17:52:17 +0200 +Subject: [PATCH 336/709] qcow2: Avoid integer wraparound in + qcow2_co_truncate() + +After commit f01643fb8b47e8a70c04bbf45e0f12a9e5bc54de when an image is +extended and BDRV_REQ_ZERO_WRITE is set then the new clusters are +zeroized. + +The code however does not detect correctly situations when the old and +the new end of the image are within the same cluster. The problem can +be reproduced with these steps: + + qemu-img create -f qcow2 backing.qcow2 1M + qemu-img create -f qcow2 -F qcow2 -b backing.qcow2 top.qcow2 + qemu-img resize --shrink top.qcow2 520k + qemu-img resize top.qcow2 567k + +In the last step offset - zero_start causes an integer wraparound. + +Signed-off-by: Alberto Garcia +Message-Id: <20200504155217.10325-1-berto@igalia.com> +Reviewed-by: Eric Blake +Signed-off-by: Kevin Wolf +--- + block/qcow2.c | 12 ++++--- + tests/qemu-iotests/292 | 73 ++++++++++++++++++++++++++++++++++++++ + tests/qemu-iotests/292.out | 24 +++++++++++++ + tests/qemu-iotests/group | 1 + + 4 files changed, 105 insertions(+), 5 deletions(-) + create mode 100755 tests/qemu-iotests/292 + create mode 100644 tests/qemu-iotests/292.out + +diff --git a/block/qcow2.c b/block/qcow2.c +index ad934109a8..fc7d4b185e 100644 +--- a/block/qcow2.c ++++ b/block/qcow2.c +@@ -4242,15 +4242,17 @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset, + * requires a cluster-aligned start. The end may be unaligned if it is + * at the end of the image (which it is here). + */ +- ret = qcow2_cluster_zeroize(bs, zero_start, offset - zero_start, 0); +- if (ret < 0) { +- error_setg_errno(errp, -ret, "Failed to zero out new clusters"); +- goto fail; ++ if (offset > zero_start) { ++ ret = qcow2_cluster_zeroize(bs, zero_start, offset - zero_start, 0); ++ if (ret < 0) { ++ error_setg_errno(errp, -ret, "Failed to zero out new clusters"); ++ goto fail; ++ } + } + + /* Write explicit zeros for the unaligned head */ + if (zero_start > old_length) { +- uint64_t len = zero_start - old_length; ++ uint64_t len = MIN(zero_start, offset) - old_length; + uint8_t *buf = qemu_blockalign0(bs, len); + QEMUIOVector qiov; + qemu_iovec_init_buf(&qiov, buf, len); +diff --git a/tests/qemu-iotests/292 b/tests/qemu-iotests/292 +new file mode 100755 +index 0000000000..a2de27cca4 +--- /dev/null ++++ b/tests/qemu-iotests/292 +@@ -0,0 +1,73 @@ ++#!/usr/bin/env bash ++# ++# Test resizing a qcow2 image with a backing file ++# ++# Copyright (C) 2020 Igalia, S.L. ++# Author: Alberto Garcia ++# ++# 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 . ++# ++ ++# creator ++owner=berto@igalia.com ++ ++seq=`basename $0` ++echo "QA output created by $seq" ++ ++status=1 # failure is the default! ++ ++_cleanup() ++{ ++ _cleanup_test_img ++} ++trap "_cleanup; exit \$status" 0 1 2 3 15 ++ ++# get standard environment, filters and checks ++. ./common.rc ++. ./common.filter ++ ++_supported_fmt qcow2 ++_supported_proto file ++_supported_os Linux ++ ++echo '### Create the backing image' ++BACKING_IMG="$TEST_IMG.base" ++TEST_IMG="$BACKING_IMG" _make_test_img 1M ++ ++echo '### Fill the backing image with data (0x11)' ++$QEMU_IO -c 'write -P 0x11 0 1M' "$BACKING_IMG" | _filter_qemu_io ++ ++echo '### Create the top image' ++_make_test_img -F "$IMGFMT" -b "$BACKING_IMG" ++ ++echo '### Fill the top image with data (0x22)' ++$QEMU_IO -c 'write -P 0x22 0 1M' "$TEST_IMG" | _filter_qemu_io ++ ++# Both offsets are part of the same cluster. ++echo '### Shrink the image to 520k' ++$QEMU_IMG resize --shrink "$TEST_IMG" 520k ++echo '### Grow the image to 567k' ++$QEMU_IMG resize "$TEST_IMG" 567k ++ ++echo '### Check that the tail of the image reads as zeroes' ++$QEMU_IO -c 'read -P 0x22 0 520k' "$TEST_IMG" | _filter_qemu_io ++$QEMU_IO -c 'read -P 0x00 520k 47k' "$TEST_IMG" | _filter_qemu_io ++ ++echo '### Show output of qemu-img map' ++$QEMU_IMG map "$TEST_IMG" | _filter_testdir ++ ++# success, all done ++echo "*** done" ++rm -f $seq.full ++status=0 +diff --git a/tests/qemu-iotests/292.out b/tests/qemu-iotests/292.out +new file mode 100644 +index 0000000000..807e0530c3 +--- /dev/null ++++ b/tests/qemu-iotests/292.out +@@ -0,0 +1,24 @@ ++QA output created by 292 ++### Create the backing image ++Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=1048576 ++### Fill the backing image with data (0x11) ++wrote 1048576/1048576 bytes at offset 0 ++1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++### Create the top image ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=IMGFMT ++### Fill the top image with data (0x22) ++wrote 1048576/1048576 bytes at offset 0 ++1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++### Shrink the image to 520k ++Image resized. ++### Grow the image to 567k ++Image resized. ++### Check that the tail of the image reads as zeroes ++read 532480/532480 bytes at offset 0 ++520 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++read 48128/48128 bytes at offset 532480 ++47 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++### Show output of qemu-img map ++Offset Length Mapped to File ++0 0x8dc00 0x50000 TEST_DIR/t.qcow2 ++*** done +diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group +index 1710470e70..fe649c5b73 100644 +--- a/tests/qemu-iotests/group ++++ b/tests/qemu-iotests/group +@@ -298,3 +298,4 @@ + 288 quick + 289 rw quick + 290 rw auto quick ++292 rw auto quick +-- +2.23.0 + diff --git a/qcow2-Fix-full-preallocation-with-external-data-file.patch b/qcow2-Fix-full-preallocation-with-external-data-file.patch deleted file mode 100644 index 12ad5215de829a101f03c7996b5c9078c5d3c606..0000000000000000000000000000000000000000 --- a/qcow2-Fix-full-preallocation-with-external-data-file.patch +++ /dev/null @@ -1,116 +0,0 @@ -From 718c0fce2f56755a8d8f737607779a98aa6e7cc4 Mon Sep 17 00:00:00 2001 -From: Kevin Wolf -Date: Mon, 15 Apr 2019 16:34:30 +0200 -Subject: [PATCH] qcow2: Fix full preallocation with external data file - -preallocate_co() already gave the data file the full size without -forwarding the requested preallocation mode to the protocol. When -bdrv_co_truncate() was called later with the preallocation mode, the -file didn't actually grow any more, so the data file stayed unallocated -even if full preallocation was requested. - -Pass the right preallocation mode to preallocate_co() and remove the -second bdrv_co_truncate() to fix this. As a side effect, the ugly -one-byte write in preallocate_co() is replaced with a truncate call, -now leaving the last block unallocated on the protocol level as it -should be. - -Cc: qemu-stable@nongnu.org -Signed-off-by: Kevin Wolf -Reviewed-by: Eric Blake -(cherry-picked from commit 718c0fce2f56755a8d8f737607779a98aa6e7cc4) ---- - block/qcow2.c | 41 +++++++++++++++++++++++------------------ - 1 file changed, 23 insertions(+), 18 deletions(-) - -diff --git a/block/qcow2.c b/block/qcow2.c -index b4f9f5a240..7fbef97aab 100644 ---- a/block/qcow2.c -+++ b/block/qcow2.c -@@ -2721,11 +2721,13 @@ static int qcow2_set_up_encryption(BlockDriverState *bs, - * Returns: 0 on success, -errno on failure. - */ - static int coroutine_fn preallocate_co(BlockDriverState *bs, uint64_t offset, -- uint64_t new_length, Error **errp) -+ uint64_t new_length, PreallocMode mode, -+ Error **errp) - { - BDRVQcow2State *s = bs->opaque; - uint64_t bytes; - uint64_t host_offset = 0; -+ int64_t file_length; - unsigned int cur_bytes; - int ret; - QCowL2Meta *meta; -@@ -2772,12 +2774,19 @@ static int coroutine_fn preallocate_co(BlockDriverState *bs, uint64_t offset, - * all of the allocated clusters (otherwise we get failing reads after - * EOF). Extend the image to the last allocated sector. - */ -- if (host_offset != 0) { -- uint8_t data = 0; -- ret = bdrv_pwrite(s->data_file, (host_offset + cur_bytes) - 1, -- &data, 1); -+ file_length = bdrv_getlength(s->data_file->bs); -+ if (file_length < 0) { -+ error_setg_errno(errp, -file_length, "Could not get file size"); -+ return file_length; -+ } -+ -+ if (host_offset + cur_bytes > file_length) { -+ if (mode == PREALLOC_MODE_METADATA) { -+ mode = PREALLOC_MODE_OFF; -+ } -+ ret = bdrv_co_truncate(s->data_file, host_offset + cur_bytes, mode, -+ errp); - if (ret < 0) { -- error_setg_errno(errp, -ret, "Writing to EOF failed"); - return ret; - } - } -@@ -3748,10 +3757,16 @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset, - - switch (prealloc) { - case PREALLOC_MODE_OFF: -+ if (has_data_file(bs)) { -+ ret = bdrv_co_truncate(s->data_file, offset, prealloc, errp); -+ if (ret < 0) { -+ goto fail; -+ } -+ } - break; - - case PREALLOC_MODE_METADATA: -- ret = preallocate_co(bs, old_length, offset, errp); -+ ret = preallocate_co(bs, old_length, offset, prealloc, errp); - if (ret < 0) { - goto fail; - } -@@ -3768,7 +3783,7 @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset, - /* With a data file, preallocation means just allocating the metadata - * and forwarding the truncate request to the data file */ - if (has_data_file(bs)) { -- ret = preallocate_co(bs, old_length, offset, errp); -+ ret = preallocate_co(bs, old_length, offset, prealloc, errp); - if (ret < 0) { - goto fail; - } -@@ -3883,16 +3898,6 @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset, - - bs->total_sectors = offset / BDRV_SECTOR_SIZE; - -- if (has_data_file(bs)) { -- if (prealloc == PREALLOC_MODE_METADATA) { -- prealloc = PREALLOC_MODE_OFF; -- } -- ret = bdrv_co_truncate(s->data_file, offset, prealloc, errp); -- if (ret < 0) { -- goto fail; -- } -- } -- - /* write updated header.size */ - offset = cpu_to_be64(offset); - ret = bdrv_pwrite_sync(bs->file, offsetof(QCowHeader, size), --- -2.19.1 - diff --git a/qcow2-Fix-preallocation-on-block-devices.patch b/qcow2-Fix-preallocation-on-block-devices.patch new file mode 100644 index 0000000000000000000000000000000000000000..11bb702ce67f3a10c53cd1c791c1b12d38cd1875 --- /dev/null +++ b/qcow2-Fix-preallocation-on-block-devices.patch @@ -0,0 +1,77 @@ +From 4b96fa3846f001981ef6f33673cdb65f619b2997 Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Tue, 5 May 2020 16:18:01 +0200 +Subject: [PATCH 348/709] qcow2: Fix preallocation on block devices + +Calling bdrv_getlength() to get the pre-truncate file size will not +really work on block devices, because they have always the same length, +and trying to write beyond it will fail with a rather cryptic error +message. + +Instead, we should use qcow2_get_last_cluster() and bdrv_getlength() +only as a fallback. + +Before this patch: +$ truncate -s 1G test.img +$ sudo losetup -f --show test.img +/dev/loop0 +$ sudo qemu-img create -f qcow2 -o preallocation=full /dev/loop0 64M +Formatting '/dev/loop0', fmt=qcow2 size=67108864 cluster_size=65536 +preallocation=full lazy_refcounts=off refcount_bits=16 +qemu-img: /dev/loop0: Could not resize image: Failed to resize refcount +structures: No space left on device + +With this patch: +$ sudo qemu-img create -f qcow2 -o preallocation=full /dev/loop0 64M +Formatting '/dev/loop0', fmt=qcow2 size=67108864 cluster_size=65536 +preallocation=full lazy_refcounts=off refcount_bits=16 +qemu-img: /dev/loop0: Could not resize image: Failed to resize +underlying file: Preallocation mode 'full' unsupported for this +non-regular file + +So as you can see, it still fails, but now the problem is missing +support on the block device level, so we at least get a better error +message. + +Note that we cannot preallocate block devices on truncate by design, +because we do not know what area to preallocate. Their length is always +the same, the truncate operation does not change it. + +Signed-off-by: Max Reitz +Message-Id: <20200505141801.1096763-1-mreitz@redhat.com> +Signed-off-by: Kevin Wolf +--- + block/qcow2.c | 10 ++++++++-- + 1 file changed, 8 insertions(+), 2 deletions(-) + +diff --git a/block/qcow2.c b/block/qcow2.c +index fc7d4b185e..11903fb547 100644 +--- a/block/qcow2.c ++++ b/block/qcow2.c +@@ -4107,7 +4107,7 @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset, + { + int64_t allocation_start, host_offset, guest_offset; + int64_t clusters_allocated; +- int64_t old_file_size, new_file_size; ++ int64_t old_file_size, last_cluster, new_file_size; + uint64_t nb_new_data_clusters, nb_new_l2_tables; + + /* With a data file, preallocation means just allocating the metadata +@@ -4127,7 +4127,13 @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset, + ret = old_file_size; + goto fail; + } +- old_file_size = ROUND_UP(old_file_size, s->cluster_size); ++ ++ last_cluster = qcow2_get_last_cluster(bs, old_file_size); ++ if (last_cluster >= 0) { ++ old_file_size = (last_cluster + 1) * s->cluster_size; ++ } else { ++ old_file_size = ROUND_UP(old_file_size, s->cluster_size); ++ } + + nb_new_data_clusters = DIV_ROUND_UP(offset - old_length, + s->cluster_size); +-- +2.23.0 + diff --git a/qcow2-Fix-qcow2_make_empty-with-external-data-file.patch b/qcow2-Fix-qcow2_make_empty-with-external-data-file.patch deleted file mode 100644 index 636e6e7e4868fa435ad62ed9897afb6ba266a15b..0000000000000000000000000000000000000000 --- a/qcow2-Fix-qcow2_make_empty-with-external-data-file.patch +++ /dev/null @@ -1,49 +0,0 @@ -From db04524f820582ebf1189223b6378de238511da1 Mon Sep 17 00:00:00 2001 -From: Kevin Wolf -Date: Mon, 29 Apr 2019 12:52:21 +0200 -Subject: [PATCH] qcow2: Fix qcow2_make_empty() with external data file - -make_completely_empty() is an optimisated path for bdrv_make_empty() -where completely new metadata is created inside the image file instead -of going through all clusters and discarding them. For an external data -file, however, we actually need to do discard operations on the data -file; just overwriting the qcow2 file doesn't get rid of the data. - -The necessary slow path with an explicit discard operation already -exists for other cases. Use it for external data files, too. - -Cc: qemu-stable@nongnu.org -Signed-off-by: Kevin Wolf -Reviewed-by: Eric Blake -(cherry-picked from commit db04524f820582ebf1189223b6378de238511da1) ---- - block/qcow2.c | 7 +++++-- - 1 file changed, 5 insertions(+), 2 deletions(-) - -diff --git a/block/qcow2.c b/block/qcow2.c -index 7fbef97aab..840f289a48 100644 ---- a/block/qcow2.c -+++ b/block/qcow2.c -@@ -4384,14 +4384,17 @@ static int qcow2_make_empty(BlockDriverState *bs) - - if (s->qcow_version >= 3 && !s->snapshots && !s->nb_bitmaps && - 3 + l1_clusters <= s->refcount_block_size && -- s->crypt_method_header != QCOW_CRYPT_LUKS) { -+ s->crypt_method_header != QCOW_CRYPT_LUKS && -+ !has_data_file(bs)) { - /* The following function only works for qcow2 v3 images (it - * requires the dirty flag) and only as long as there are no - * features that reserve extra clusters (such as snapshots, - * LUKS header, or persistent bitmaps), because it completely - * empties the image. Furthermore, the L1 table and three - * additional clusters (image header, refcount table, one -- * refcount block) have to fit inside one refcount block. */ -+ * refcount block) have to fit inside one refcount block. It -+ * only resets the image file, i.e. does not work with an -+ * external data file. */ - return make_completely_empty(bs); - } - --- -2.19.1 - diff --git a/qcow2-Fix-the-calculation-of-the-maximum-L2-cache-size.patch b/qcow2-Fix-the-calculation-of-the-maximum-L2-cache-size.patch deleted file mode 100644 index 54c45123a82ba9e926fc1697035de74c656a3175..0000000000000000000000000000000000000000 --- a/qcow2-Fix-the-calculation-of-the-maximum-L2-cache-size.patch +++ /dev/null @@ -1,59 +0,0 @@ -From cb7630af20d353cbde66ddfb14d858737ffaf877 Mon Sep 17 00:00:00 2001 -From: Alberto Garcia -Date: Fri, 16 Aug 2019 15:17:42 +0300 -Subject: [PATCH] qcow2: Fix the calculation of the maximum L2 cache size - -The size of the qcow2 L2 cache defaults to 32 MB, which can be easily -larger than the maximum amount of L2 metadata that the image can have. -For example: with 64 KB clusters the user would need a qcow2 image -with a virtual size of 256 GB in order to have 32 MB of L2 metadata. - -Because of that, since commit b749562d9822d14ef69c9eaa5f85903010b86c30 -we forbid the L2 cache to become larger than the maximum amount of L2 -metadata for the image, calculated using this formula: - - uint64_t max_l2_cache = virtual_disk_size / (s->cluster_size / 8); - -The problem with this formula is that the result should be rounded up -to the cluster size because an L2 table on disk always takes one full -cluster. - -For example, a 1280 MB qcow2 image with 64 KB clusters needs exactly -160 KB of L2 metadata, but we need 192 KB on disk (3 clusters) even if -the last 32 KB of those are not going to be used. - -However QEMU rounds the numbers down and only creates 2 cache tables -(128 KB), which is not enough for the image. - -A quick test doing 4KB random writes on a 1280 MB image gives me -around 500 IOPS, while with the correct cache size I get 16K IOPS. - -Cc: qemu-stable@nongnu.org -Signed-off-by: Alberto Garcia -Signed-off-by: Kevin Wolf -(cherry picked from commit b70d08205b2e4044c529eefc21df2c8ab61b473b) -Signed-off-by: Michael Roth ---- - block/qcow2.c | 6 +++++- - 1 file changed, 5 insertions(+), 1 deletion(-) - -diff --git a/block/qcow2.c b/block/qcow2.c -index 840f289a48..c80f48a02b 100644 ---- a/block/qcow2.c -+++ b/block/qcow2.c -@@ -831,7 +831,11 @@ static void read_cache_sizes(BlockDriverState *bs, QemuOpts *opts, - bool l2_cache_entry_size_set; - int min_refcount_cache = MIN_REFCOUNT_CACHE_SIZE * s->cluster_size; - uint64_t virtual_disk_size = bs->total_sectors * BDRV_SECTOR_SIZE; -- uint64_t max_l2_cache = virtual_disk_size / (s->cluster_size / 8); -+ uint64_t max_l2_entries = DIV_ROUND_UP(virtual_disk_size, s->cluster_size); -+ /* An L2 table is always one cluster in size so the max cache size -+ * should be a multiple of the cluster size. */ -+ uint64_t max_l2_cache = ROUND_UP(max_l2_entries * sizeof(uint64_t), -+ s->cluster_size); - - combined_cache_size_set = qemu_opt_get(opts, QCOW2_OPT_CACHE_SIZE); - l2_cache_size_set = qemu_opt_get(opts, QCOW2_OPT_L2_CACHE_SIZE); --- -2.19.1 - diff --git a/qcow2-Forward-ZERO_WRITE-flag-for-full-preallocation.patch b/qcow2-Forward-ZERO_WRITE-flag-for-full-preallocation.patch new file mode 100644 index 0000000000000000000000000000000000000000..9de7539f36cb4b69b6c142cf085475badd584484 --- /dev/null +++ b/qcow2-Forward-ZERO_WRITE-flag-for-full-preallocation.patch @@ -0,0 +1,86 @@ +From eb8a0cf3ba26611f3981f8f45ac6a868975a68cc Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Fri, 24 Apr 2020 16:27:01 +0200 +Subject: [PATCH 135/709] qcow2: Forward ZERO_WRITE flag for full preallocation + +The BDRV_REQ_ZERO_WRITE is currently implemented in a way that first the +image is possibly preallocated and then the zero flag is added to all +clusters. This means that a copy-on-write operation may be needed when +writing to these clusters, despite having used preallocation, negating +one of the major benefits of preallocation. + +Instead, try to forward the BDRV_REQ_ZERO_WRITE to the protocol driver, +and if the protocol driver can ensure that the new area reads as zeros, +we can skip setting the zero flag in the qcow2 layer. + +Unfortunately, the same approach doesn't work for metadata +preallocation, so we'll still set the zero flag there. + +Signed-off-by: Kevin Wolf +Reviewed-by: Max Reitz +Message-Id: <20200424142701.67053-1-kwolf@redhat.com> +Reviewed-by: Vladimir Sementsov-Ogievskiy +Signed-off-by: Kevin Wolf +--- + block/qcow2.c | 22 +++++++++++++++++++--- + tests/qemu-iotests/274.out | 4 ++-- + 2 files changed, 21 insertions(+), 5 deletions(-) + +diff --git a/block/qcow2.c b/block/qcow2.c +index 98065d7808..2ba0b17c39 100644 +--- a/block/qcow2.c ++++ b/block/qcow2.c +@@ -4170,9 +4170,25 @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset, + /* Allocate the data area */ + new_file_size = allocation_start + + nb_new_data_clusters * s->cluster_size; +- /* Image file grows, so @exact does not matter */ +- ret = bdrv_co_truncate(bs->file, new_file_size, false, prealloc, 0, +- errp); ++ /* ++ * Image file grows, so @exact does not matter. ++ * ++ * If we need to zero out the new area, try first whether the protocol ++ * driver can already take care of this. ++ */ ++ if (flags & BDRV_REQ_ZERO_WRITE) { ++ ret = bdrv_co_truncate(bs->file, new_file_size, false, prealloc, ++ BDRV_REQ_ZERO_WRITE, NULL); ++ if (ret >= 0) { ++ flags &= ~BDRV_REQ_ZERO_WRITE; ++ } ++ } else { ++ ret = -1; ++ } ++ if (ret < 0) { ++ ret = bdrv_co_truncate(bs->file, new_file_size, false, prealloc, 0, ++ errp); ++ } + if (ret < 0) { + error_prepend(errp, "Failed to resize underlying file: "); + qcow2_free_clusters(bs, allocation_start, +diff --git a/tests/qemu-iotests/274.out b/tests/qemu-iotests/274.out +index 1a796fd07c..9d6fdeb1f7 100644 +--- a/tests/qemu-iotests/274.out ++++ b/tests/qemu-iotests/274.out +@@ -187,7 +187,7 @@ read 65536/65536 bytes at offset 9437184 + 10 MiB (0xa00000) bytes allocated at offset 5 MiB (0x500000) + + [{ "start": 0, "length": 5242880, "depth": 1, "zero": true, "data": false}, +-{ "start": 5242880, "length": 10485760, "depth": 0, "zero": true, "data": false, "offset": 327680}] ++{ "start": 5242880, "length": 10485760, "depth": 0, "zero": false, "data": true, "offset": 327680}] + + === preallocation=full === + Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=16777216 cluster_size=65536 lazy_refcounts=off refcount_bits=16 +@@ -206,7 +206,7 @@ read 65536/65536 bytes at offset 11534336 + 4 MiB (0x400000) bytes allocated at offset 8 MiB (0x800000) + + [{ "start": 0, "length": 8388608, "depth": 1, "zero": true, "data": false}, +-{ "start": 8388608, "length": 4194304, "depth": 0, "zero": true, "data": false, "offset": 327680}] ++{ "start": 8388608, "length": 4194304, "depth": 0, "zero": false, "data": true, "offset": 327680}] + + === preallocation=off === + Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=393216 cluster_size=65536 lazy_refcounts=off refcount_bits=16 +-- +2.23.0 + diff --git a/qcow2-Support-BDRV_REQ_ZERO_WRITE-for-truncate.patch b/qcow2-Support-BDRV_REQ_ZERO_WRITE-for-truncate.patch new file mode 100644 index 0000000000000000000000000000000000000000..8da7f1145e088ca4fba08c92dba272d45a68f155 --- /dev/null +++ b/qcow2-Support-BDRV_REQ_ZERO_WRITE-for-truncate.patch @@ -0,0 +1,89 @@ +From f01643fb8b47e8a70c04bbf45e0f12a9e5bc54de Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Fri, 24 Apr 2020 14:54:42 +0200 +Subject: [PATCH 129/709] qcow2: Support BDRV_REQ_ZERO_WRITE for truncate + +If BDRV_REQ_ZERO_WRITE is set and we're extending the image, calling +qcow2_cluster_zeroize() with flags=0 does the right thing: It doesn't +undo any previous preallocation, but just adds the zero flag to all +relevant L2 entries. If an external data file is in use, a write_zeroes +request to the data file is made instead. + +Signed-off-by: Kevin Wolf +Message-Id: <20200424125448.63318-5-kwolf@redhat.com> +Reviewed-by: Eric Blake +Reviewed-by: Max Reitz +Signed-off-by: Kevin Wolf +--- + block/qcow2-cluster.c | 2 +- + block/qcow2.c | 34 ++++++++++++++++++++++++++++++++++ + 2 files changed, 35 insertions(+), 1 deletion(-) + +diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c +index 17f1363279..4b5fc8c4a7 100644 +--- a/block/qcow2-cluster.c ++++ b/block/qcow2-cluster.c +@@ -1795,7 +1795,7 @@ int qcow2_cluster_zeroize(BlockDriverState *bs, uint64_t offset, + /* Caller must pass aligned values, except at image end */ + assert(QEMU_IS_ALIGNED(offset, s->cluster_size)); + assert(QEMU_IS_ALIGNED(end_offset, s->cluster_size) || +- end_offset == bs->total_sectors << BDRV_SECTOR_BITS); ++ end_offset >= bs->total_sectors << BDRV_SECTOR_BITS); + + /* The zero flag is only supported by version 3 and newer */ + if (s->qcow_version < 3) { +diff --git a/block/qcow2.c b/block/qcow2.c +index 9cfbdfc939..98065d7808 100644 +--- a/block/qcow2.c ++++ b/block/qcow2.c +@@ -1726,6 +1726,7 @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options, + + bs->supported_zero_flags = header.version >= 3 ? + BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK : 0; ++ bs->supported_truncate_flags = BDRV_REQ_ZERO_WRITE; + + /* Repair image if dirty */ + if (!(flags & (BDRV_O_CHECK | BDRV_O_INACTIVE)) && !bs->read_only && +@@ -4214,6 +4215,39 @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset, + g_assert_not_reached(); + } + ++ if ((flags & BDRV_REQ_ZERO_WRITE) && offset > old_length) { ++ uint64_t zero_start = QEMU_ALIGN_UP(old_length, s->cluster_size); ++ ++ /* ++ * Use zero clusters as much as we can. qcow2_cluster_zeroize() ++ * requires a cluster-aligned start. The end may be unaligned if it is ++ * at the end of the image (which it is here). ++ */ ++ ret = qcow2_cluster_zeroize(bs, zero_start, offset - zero_start, 0); ++ if (ret < 0) { ++ error_setg_errno(errp, -ret, "Failed to zero out new clusters"); ++ goto fail; ++ } ++ ++ /* Write explicit zeros for the unaligned head */ ++ if (zero_start > old_length) { ++ uint64_t len = zero_start - old_length; ++ uint8_t *buf = qemu_blockalign0(bs, len); ++ QEMUIOVector qiov; ++ qemu_iovec_init_buf(&qiov, buf, len); ++ ++ qemu_co_mutex_unlock(&s->lock); ++ ret = qcow2_co_pwritev_part(bs, old_length, len, &qiov, 0, 0); ++ qemu_co_mutex_lock(&s->lock); ++ ++ qemu_vfree(buf); ++ if (ret < 0) { ++ error_setg_errno(errp, -ret, "Failed to zero out the new area"); ++ goto fail; ++ } ++ } ++ } ++ + if (prealloc != PREALLOC_MODE_OFF) { + /* Flush metadata before actually changing the image size */ + ret = qcow2_write_caches(bs); +-- +2.23.0 + diff --git a/qcow2-Tweak-comment-about-bitmaps-vs.-resize.patch b/qcow2-Tweak-comment-about-bitmaps-vs.-resize.patch new file mode 100644 index 0000000000000000000000000000000000000000..4b0a232bcfec9f6851e912fcea119e5cf6ff2b33 --- /dev/null +++ b/qcow2-Tweak-comment-about-bitmaps-vs.-resize.patch @@ -0,0 +1,33 @@ +From ee1244a2e96288ba3c2f3a9a82b97f5617939d9f Mon Sep 17 00:00:00 2001 +From: Eric Blake +Date: Tue, 28 Apr 2020 14:26:48 -0500 +Subject: [PATCH 257/709] qcow2: Tweak comment about bitmaps vs. resize + +Our comment did not actually match the code. Rewrite the comment to +be less sensitive to any future changes to qcow2-bitmap.c that might +implement scenarios that we currently reject. + +Signed-off-by: Eric Blake +Reviewed-by: Max Reitz +Message-Id: <20200428192648.749066-4-eblake@redhat.com> +Signed-off-by: Max Reitz +--- + block/qcow2.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/block/qcow2.c b/block/qcow2.c +index 3e8b3d022b..ad934109a8 100644 +--- a/block/qcow2.c ++++ b/block/qcow2.c +@@ -3999,7 +3999,7 @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset, + goto fail; + } + +- /* cannot proceed if image has bitmaps */ ++ /* See qcow2-bitmap.c for which bitmap scenarios prevent a resize. */ + if (qcow2_truncate_bitmaps_check(bs, errp)) { + ret = -ENOTSUP; + goto fail; +-- +2.23.0 + diff --git a/qcow2-add-zstd-cluster-compression.patch b/qcow2-add-zstd-cluster-compression.patch new file mode 100644 index 0000000000000000000000000000000000000000..b3ee52f2f5c09a79dc1784961c810d3851a932b2 --- /dev/null +++ b/qcow2-add-zstd-cluster-compression.patch @@ -0,0 +1,322 @@ +From d298ac10add95e2b7f8850332f3b755c8a23d925 Mon Sep 17 00:00:00 2001 +From: Denis Plotnikov +Date: Thu, 7 May 2020 11:25:20 +0300 +Subject: [PATCH 395/709] qcow2: add zstd cluster compression + +zstd significantly reduces cluster compression time. +It provides better compression performance maintaining +the same level of the compression ratio in comparison with +zlib, which, at the moment, is the only compression +method available. + +The performance test results: +Test compresses and decompresses qemu qcow2 image with just +installed rhel-7.6 guest. +Image cluster size: 64K. Image on disk size: 2.2G + +The test was conducted with brd disk to reduce the influence +of disk subsystem to the test results. +The results is given in seconds. + +compress cmd: + time ./qemu-img convert -O qcow2 -c -o compression_type=[zlib|zstd] + src.img [zlib|zstd]_compressed.img +decompress cmd + time ./qemu-img convert -O qcow2 + [zlib|zstd]_compressed.img uncompressed.img + + compression decompression + zlib zstd zlib zstd +------------------------------------------------------------ +real 65.5 16.3 (-75 %) 1.9 1.6 (-16 %) +user 65.0 15.8 5.3 2.5 +sys 3.3 0.2 2.0 2.0 + +Both ZLIB and ZSTD gave the same compression ratio: 1.57 +compressed image size in both cases: 1.4G + +Signed-off-by: Denis Plotnikov +QAPI part: +Acked-by: Markus Armbruster +Message-Id: <20200507082521.29210-4-dplotnikov@virtuozzo.com> +Signed-off-by: Max Reitz +--- + block/qcow2-threads.c | 169 +++++++++++++++++++++++++++++++++++++++++ + block/qcow2.c | 7 ++ + configure | 2 +- + docs/interop/qcow2.txt | 1 + + qapi/block-core.json | 3 +- + 5 files changed, 180 insertions(+), 2 deletions(-) + +diff --git a/block/qcow2-threads.c b/block/qcow2-threads.c +index 7dbaf53489..1914baf456 100644 +--- a/block/qcow2-threads.c ++++ b/block/qcow2-threads.c +@@ -28,6 +28,11 @@ + #define ZLIB_CONST + #include + ++#ifdef CONFIG_ZSTD ++#include ++#include ++#endif ++ + #include "qcow2.h" + #include "block/thread-pool.h" + #include "crypto.h" +@@ -166,6 +171,160 @@ static ssize_t qcow2_zlib_decompress(void *dest, size_t dest_size, + return ret; + } + ++#ifdef CONFIG_ZSTD ++ ++/* ++ * qcow2_zstd_compress() ++ * ++ * Compress @src_size bytes of data using zstd compression method ++ * ++ * @dest - destination buffer, @dest_size bytes ++ * @src - source buffer, @src_size bytes ++ * ++ * Returns: compressed size on success ++ * -ENOMEM destination buffer is not enough to store compressed data ++ * -EIO on any other error ++ */ ++static ssize_t qcow2_zstd_compress(void *dest, size_t dest_size, ++ const void *src, size_t src_size) ++{ ++ ssize_t ret; ++ size_t zstd_ret; ++ ZSTD_outBuffer output = { ++ .dst = dest, ++ .size = dest_size, ++ .pos = 0 ++ }; ++ ZSTD_inBuffer input = { ++ .src = src, ++ .size = src_size, ++ .pos = 0 ++ }; ++ ZSTD_CCtx *cctx = ZSTD_createCCtx(); ++ ++ if (!cctx) { ++ return -EIO; ++ } ++ /* ++ * Use the zstd streamed interface for symmetry with decompression, ++ * where streaming is essential since we don't record the exact ++ * compressed size. ++ * ++ * ZSTD_compressStream2() tries to compress everything it could ++ * with a single call. Although, ZSTD docs says that: ++ * "You must continue calling ZSTD_compressStream2() with ZSTD_e_end ++ * until it returns 0, at which point you are free to start a new frame", ++ * in out tests we saw the only case when it returned with >0 - ++ * when the output buffer was too small. In that case, ++ * ZSTD_compressStream2() expects a bigger buffer on the next call. ++ * We can't provide a bigger buffer because we are limited with dest_size ++ * which we pass to the ZSTD_compressStream2() at once. ++ * So, we don't need any loops and just abort the compression when we ++ * don't get 0 result on the first call. ++ */ ++ zstd_ret = ZSTD_compressStream2(cctx, &output, &input, ZSTD_e_end); ++ ++ if (zstd_ret) { ++ if (zstd_ret > output.size - output.pos) { ++ ret = -ENOMEM; ++ } else { ++ ret = -EIO; ++ } ++ goto out; ++ } ++ ++ /* make sure that zstd didn't overflow the dest buffer */ ++ assert(output.pos <= dest_size); ++ ret = output.pos; ++out: ++ ZSTD_freeCCtx(cctx); ++ return ret; ++} ++ ++/* ++ * qcow2_zstd_decompress() ++ * ++ * Decompress some data (not more than @src_size bytes) to produce exactly ++ * @dest_size bytes using zstd compression method ++ * ++ * @dest - destination buffer, @dest_size bytes ++ * @src - source buffer, @src_size bytes ++ * ++ * Returns: 0 on success ++ * -EIO on any error ++ */ ++static ssize_t qcow2_zstd_decompress(void *dest, size_t dest_size, ++ const void *src, size_t src_size) ++{ ++ size_t zstd_ret = 0; ++ ssize_t ret = 0; ++ ZSTD_outBuffer output = { ++ .dst = dest, ++ .size = dest_size, ++ .pos = 0 ++ }; ++ ZSTD_inBuffer input = { ++ .src = src, ++ .size = src_size, ++ .pos = 0 ++ }; ++ ZSTD_DCtx *dctx = ZSTD_createDCtx(); ++ ++ if (!dctx) { ++ return -EIO; ++ } ++ ++ /* ++ * The compressed stream from the input buffer may consist of more ++ * than one zstd frame. So we iterate until we get a fully ++ * uncompressed cluster. ++ * From zstd docs related to ZSTD_decompressStream: ++ * "return : 0 when a frame is completely decoded and fully flushed" ++ * We suppose that this means: each time ZSTD_decompressStream reads ++ * only ONE full frame and returns 0 if and only if that frame ++ * is completely decoded and flushed. Only after returning 0, ++ * ZSTD_decompressStream reads another ONE full frame. ++ */ ++ while (output.pos < output.size) { ++ size_t last_in_pos = input.pos; ++ size_t last_out_pos = output.pos; ++ zstd_ret = ZSTD_decompressStream(dctx, &output, &input); ++ ++ if (ZSTD_isError(zstd_ret)) { ++ ret = -EIO; ++ break; ++ } ++ ++ /* ++ * The ZSTD manual is vague about what to do if it reads ++ * the buffer partially, and we don't want to get stuck ++ * in an infinite loop where ZSTD_decompressStream ++ * returns > 0 waiting for another input chunk. So, we add ++ * a check which ensures that the loop makes some progress ++ * on each step. ++ */ ++ if (last_in_pos >= input.pos && ++ last_out_pos >= output.pos) { ++ ret = -EIO; ++ break; ++ } ++ } ++ /* ++ * Make sure that we have the frame fully flushed here ++ * if not, we somehow managed to get uncompressed cluster ++ * greater then the cluster size, possibly because of its ++ * damage. ++ */ ++ if (zstd_ret > 0) { ++ ret = -EIO; ++ } ++ ++ ZSTD_freeDCtx(dctx); ++ assert(ret == 0 || ret == -EIO); ++ return ret; ++} ++#endif ++ + static int qcow2_compress_pool_func(void *opaque) + { + Qcow2CompressData *data = opaque; +@@ -217,6 +376,11 @@ qcow2_co_compress(BlockDriverState *bs, void *dest, size_t dest_size, + fn = qcow2_zlib_compress; + break; + ++#ifdef CONFIG_ZSTD ++ case QCOW2_COMPRESSION_TYPE_ZSTD: ++ fn = qcow2_zstd_compress; ++ break; ++#endif + default: + abort(); + } +@@ -249,6 +413,11 @@ qcow2_co_decompress(BlockDriverState *bs, void *dest, size_t dest_size, + fn = qcow2_zlib_decompress; + break; + ++#ifdef CONFIG_ZSTD ++ case QCOW2_COMPRESSION_TYPE_ZSTD: ++ fn = qcow2_zstd_decompress; ++ break; ++#endif + default: + abort(); + } +diff --git a/block/qcow2.c b/block/qcow2.c +index b878a6a474..ad9ab4fafa 100644 +--- a/block/qcow2.c ++++ b/block/qcow2.c +@@ -1246,6 +1246,9 @@ static int validate_compression_type(BDRVQcow2State *s, Error **errp) + { + switch (s->compression_type) { + case QCOW2_COMPRESSION_TYPE_ZLIB: ++#ifdef CONFIG_ZSTD ++ case QCOW2_COMPRESSION_TYPE_ZSTD: ++#endif + break; + + default: +@@ -3479,6 +3482,10 @@ qcow2_co_create(BlockdevCreateOptions *create_options, Error **errp) + } + + switch (qcow2_opts->compression_type) { ++#ifdef CONFIG_ZSTD ++ case QCOW2_COMPRESSION_TYPE_ZSTD: ++ break; ++#endif + default: + error_setg(errp, "Unknown compression type"); + goto out; +diff --git a/configure b/configure +index 0d69c360c0..c50c006b86 100755 +--- a/configure ++++ b/configure +@@ -1861,7 +1861,7 @@ disabled with --disable-FEATURE, default is enabled if available: + lzfse support of lzfse compression library + (for reading lzfse-compressed dmg images) + zstd support for zstd compression library +- (for migration compression) ++ (for migration compression and qcow2 cluster compression) + seccomp seccomp support + coroutine-pool coroutine freelist (better performance) + glusterfs GlusterFS backend +diff --git a/docs/interop/qcow2.txt b/docs/interop/qcow2.txt +index 298a031310..cb723463f2 100644 +--- a/docs/interop/qcow2.txt ++++ b/docs/interop/qcow2.txt +@@ -212,6 +212,7 @@ version 2. + + Available compression type values: + 0: zlib ++ 1: zstd + + + === Header padding === +diff --git a/qapi/block-core.json b/qapi/block-core.json +index 1522e2983f..6fbacddab2 100644 +--- a/qapi/block-core.json ++++ b/qapi/block-core.json +@@ -4293,11 +4293,12 @@ + # Compression type used in qcow2 image file + # + # @zlib: zlib compression, see ++# @zstd: zstd compression, see + # + # Since: 5.1 + ## + { 'enum': 'Qcow2CompressionType', +- 'data': [ 'zlib' ] } ++ 'data': [ 'zlib', { 'name': 'zstd', 'if': 'defined(CONFIG_ZSTD)' } ] } + + ## + # @BlockdevCreateOptionsQcow2: +-- +2.23.0 + diff --git a/qcow2-fix-memory-leak-in-qcow2_read_extensions.patch b/qcow2-fix-memory-leak-in-qcow2_read_extensions.patch deleted file mode 100644 index 2837a02342a4d6fde0e7f0370d64557089450870..0000000000000000000000000000000000000000 --- a/qcow2-fix-memory-leak-in-qcow2_read_extensions.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 76ab77108279f9d328e4a7fe1684141084698d97 Mon Sep 17 00:00:00 2001 -From: zhanghailiang -Date: Thu, 25 Jul 2019 16:05:11 +0800 -Subject: [PATCH] qcow2: fix memory leak in qcow2_read_extensions - -Free feature_table if it is failed in bdrv_pread. - -Signed-off-by: fangyi ---- - block/qcow2.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/block/qcow2.c b/block/qcow2.c -index 3ace3b22..5e85cf4b 100644 ---- a/block/qcow2.c -+++ b/block/qcow2.c -@@ -258,6 +258,7 @@ static int qcow2_read_extensions(BlockDriverState *bs, uint64_t start_offset, - void* feature_table = g_malloc0(ext.len + 2 * sizeof(Qcow2Feature)); - ret = bdrv_pread(bs->file, offset , feature_table, ext.len); - if (ret < 0) { -+ g_free(feature_table); - error_setg_errno(errp, -ret, "ERROR: ext_feature_table: " - "Could not read table"); - return ret; --- -2.19.1 - diff --git a/qcow2-introduce-compression-type-feature.patch b/qcow2-introduce-compression-type-feature.patch new file mode 100644 index 0000000000000000000000000000000000000000..465146c860a3968edee1fa20752a4f2bfb9ea0f3 --- /dev/null +++ b/qcow2-introduce-compression-type-feature.patch @@ -0,0 +1,1744 @@ +From 572ad9783f3e728a70617ce6bf144c09de3add50 Mon Sep 17 00:00:00 2001 +From: Denis Plotnikov +Date: Thu, 7 May 2020 11:25:18 +0300 +Subject: [PATCH 393/709] qcow2: introduce compression type feature + +The patch adds some preparation parts for incompatible compression type +feature to qcow2 allowing the use different compression methods for +image clusters (de)compressing. + +It is implied that the compression type is set on the image creation and +can be changed only later by image conversion, thus compression type +defines the only compression algorithm used for the image, and thus, +for all image clusters. + +The goal of the feature is to add support of other compression methods +to qcow2. For example, ZSTD which is more effective on compression than ZLIB. + +The default compression is ZLIB. Images created with ZLIB compression type +are backward compatible with older qemu versions. + +Adding of the compression type breaks a number of tests because now the +compression type is reported on image creation and there are some changes +in the qcow2 header in size and offsets. + +The tests are fixed in the following ways: + * filter out compression_type for many tests + * fix header size, feature table size and backing file offset + affected tests: 031, 036, 061, 080 + header_size +=8: 1 byte compression type + 7 bytes padding + feature_table += 48: incompatible feature compression type + backing_file_offset += 56 (8 + 48 -> header_change + feature_table_change) + * add "compression type" for test output matching when it isn't filtered + affected tests: 049, 060, 061, 065, 082, 085, 144, 182, 185, 198, 206, + 242, 255, 274, 280 + +Signed-off-by: Denis Plotnikov +Reviewed-by: Vladimir Sementsov-Ogievskiy +Reviewed-by: Eric Blake +Reviewed-by: Max Reitz +QAPI part: +Acked-by: Markus Armbruster +Message-Id: <20200507082521.29210-2-dplotnikov@virtuozzo.com> +Signed-off-by: Max Reitz +--- + block/qcow2.c | 113 +++++++++++++++++++++++++++++++ + block/qcow2.h | 20 +++++- + include/block/block_int.h | 1 + + qapi/block-core.json | 22 +++++- + tests/qemu-iotests/031.out | 14 ++-- + tests/qemu-iotests/036.out | 4 +- + tests/qemu-iotests/049.out | 102 ++++++++++++++-------------- + tests/qemu-iotests/060.out | 1 + + tests/qemu-iotests/061.out | 34 ++++++---- + tests/qemu-iotests/065 | 28 +++++--- + tests/qemu-iotests/080 | 2 +- + tests/qemu-iotests/082.out | 48 +++++++++++-- + tests/qemu-iotests/085.out | 38 +++++------ + tests/qemu-iotests/144.out | 4 +- + tests/qemu-iotests/182.out | 2 +- + tests/qemu-iotests/185.out | 8 +-- + tests/qemu-iotests/198.out | 2 + + tests/qemu-iotests/206.out | 5 ++ + tests/qemu-iotests/242.out | 5 ++ + tests/qemu-iotests/255.out | 8 +-- + tests/qemu-iotests/274.out | 49 +++++++------- + tests/qemu-iotests/280.out | 2 +- + tests/qemu-iotests/common.filter | 3 +- + 23 files changed, 365 insertions(+), 150 deletions(-) + +diff --git a/block/qcow2.c b/block/qcow2.c +index 1ad95ff048..b878a6a474 100644 +--- a/block/qcow2.c ++++ b/block/qcow2.c +@@ -1242,6 +1242,39 @@ static int qcow2_update_options(BlockDriverState *bs, QDict *options, + return ret; + } + ++static int validate_compression_type(BDRVQcow2State *s, Error **errp) ++{ ++ switch (s->compression_type) { ++ case QCOW2_COMPRESSION_TYPE_ZLIB: ++ break; ++ ++ default: ++ error_setg(errp, "qcow2: unknown compression type: %u", ++ s->compression_type); ++ return -ENOTSUP; ++ } ++ ++ /* ++ * if the compression type differs from QCOW2_COMPRESSION_TYPE_ZLIB ++ * the incompatible feature flag must be set ++ */ ++ if (s->compression_type == QCOW2_COMPRESSION_TYPE_ZLIB) { ++ if (s->incompatible_features & QCOW2_INCOMPAT_COMPRESSION) { ++ error_setg(errp, "qcow2: Compression type incompatible feature " ++ "bit must not be set"); ++ return -EINVAL; ++ } ++ } else { ++ if (!(s->incompatible_features & QCOW2_INCOMPAT_COMPRESSION)) { ++ error_setg(errp, "qcow2: Compression type incompatible feature " ++ "bit must be set"); ++ return -EINVAL; ++ } ++ } ++ ++ return 0; ++} ++ + /* Called with s->lock held. */ + static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options, + int flags, Error **errp) +@@ -1357,6 +1390,23 @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options, + s->compatible_features = header.compatible_features; + s->autoclear_features = header.autoclear_features; + ++ /* ++ * Handle compression type ++ * Older qcow2 images don't contain the compression type header. ++ * Distinguish them by the header length and use ++ * the only valid (default) compression type in that case ++ */ ++ if (header.header_length > offsetof(QCowHeader, compression_type)) { ++ s->compression_type = header.compression_type; ++ } else { ++ s->compression_type = QCOW2_COMPRESSION_TYPE_ZLIB; ++ } ++ ++ ret = validate_compression_type(s, errp); ++ if (ret) { ++ goto fail; ++ } ++ + if (s->incompatible_features & ~QCOW2_INCOMPAT_MASK) { + void *feature_table = NULL; + qcow2_read_extensions(bs, header.header_length, ext_end, +@@ -2728,6 +2778,11 @@ int qcow2_update_header(BlockDriverState *bs) + total_size = bs->total_sectors * BDRV_SECTOR_SIZE; + refcount_table_clusters = s->refcount_table_size >> (s->cluster_bits - 3); + ++ ret = validate_compression_type(s, NULL); ++ if (ret) { ++ goto fail; ++ } ++ + *header = (QCowHeader) { + /* Version 2 fields */ + .magic = cpu_to_be32(QCOW_MAGIC), +@@ -2750,6 +2805,7 @@ int qcow2_update_header(BlockDriverState *bs) + .autoclear_features = cpu_to_be64(s->autoclear_features), + .refcount_order = cpu_to_be32(s->refcount_order), + .header_length = cpu_to_be32(header_length), ++ .compression_type = s->compression_type, + }; + + /* For older versions, write a shorter header */ +@@ -2849,6 +2905,11 @@ int qcow2_update_header(BlockDriverState *bs) + .bit = QCOW2_INCOMPAT_DATA_FILE_BITNR, + .name = "external data file", + }, ++ { ++ .type = QCOW2_FEAT_TYPE_INCOMPATIBLE, ++ .bit = QCOW2_INCOMPAT_COMPRESSION_BITNR, ++ .name = "compression type", ++ }, + { + .type = QCOW2_FEAT_TYPE_COMPATIBLE, + .bit = QCOW2_COMPAT_LAZY_REFCOUNTS_BITNR, +@@ -3287,6 +3348,7 @@ qcow2_co_create(BlockdevCreateOptions *create_options, Error **errp) + uint64_t* refcount_table; + Error *local_err = NULL; + int ret; ++ uint8_t compression_type = QCOW2_COMPRESSION_TYPE_ZLIB; + + assert(create_options->driver == BLOCKDEV_DRIVER_QCOW2); + qcow2_opts = &create_options->u.qcow2; +@@ -3404,6 +3466,27 @@ qcow2_co_create(BlockdevCreateOptions *create_options, Error **errp) + } + } + ++ if (qcow2_opts->has_compression_type && ++ qcow2_opts->compression_type != QCOW2_COMPRESSION_TYPE_ZLIB) { ++ ++ ret = -EINVAL; ++ ++ if (version < 3) { ++ error_setg(errp, "Non-zlib compression type is only supported with " ++ "compatibility level 1.1 and above (use version=v3 or " ++ "greater)"); ++ goto out; ++ } ++ ++ switch (qcow2_opts->compression_type) { ++ default: ++ error_setg(errp, "Unknown compression type"); ++ goto out; ++ } ++ ++ compression_type = qcow2_opts->compression_type; ++ } ++ + /* Create BlockBackend to write to the image */ + blk = blk_new_with_bs(bs, BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL, + errp); +@@ -3426,6 +3509,8 @@ qcow2_co_create(BlockdevCreateOptions *create_options, Error **errp) + .refcount_table_offset = cpu_to_be64(cluster_size), + .refcount_table_clusters = cpu_to_be32(1), + .refcount_order = cpu_to_be32(refcount_order), ++ /* don't deal with endianness since compression_type is 1 byte long */ ++ .compression_type = compression_type, + .header_length = cpu_to_be32(sizeof(*header)), + }; + +@@ -3444,6 +3529,10 @@ qcow2_co_create(BlockdevCreateOptions *create_options, Error **errp) + header->autoclear_features |= + cpu_to_be64(QCOW2_AUTOCLEAR_DATA_FILE_RAW); + } ++ if (compression_type != QCOW2_COMPRESSION_TYPE_ZLIB) { ++ header->incompatible_features |= ++ cpu_to_be64(QCOW2_INCOMPAT_COMPRESSION); ++ } + + ret = blk_pwrite(blk, 0, header, cluster_size, 0); + g_free(header); +@@ -3629,6 +3718,7 @@ static int coroutine_fn qcow2_co_create_opts(BlockDriver *drv, + { BLOCK_OPT_ENCRYPT, BLOCK_OPT_ENCRYPT_FORMAT }, + { BLOCK_OPT_COMPAT_LEVEL, "version" }, + { BLOCK_OPT_DATA_FILE_RAW, "data-file-raw" }, ++ { BLOCK_OPT_COMPRESSION_TYPE, "compression-type" }, + { NULL, NULL }, + }; + +@@ -4925,6 +5015,7 @@ static ImageInfoSpecific *qcow2_get_specific_info(BlockDriverState *bs, + .data_file = g_strdup(s->image_data_file), + .has_data_file_raw = has_data_file(bs), + .data_file_raw = data_file_is_raw(bs), ++ .compression_type = s->compression_type, + }; + } else { + /* if this assertion fails, this probably means a new version was +@@ -5330,6 +5421,22 @@ static int qcow2_amend_options(BlockDriverState *bs, QemuOpts *opts, + "images"); + return -EINVAL; + } ++ } else if (!strcmp(desc->name, BLOCK_OPT_COMPRESSION_TYPE)) { ++ const char *ct_name = ++ qemu_opt_get(opts, BLOCK_OPT_COMPRESSION_TYPE); ++ int compression_type = ++ qapi_enum_parse(&Qcow2CompressionType_lookup, ct_name, -1, ++ NULL); ++ if (compression_type == -1) { ++ error_setg(errp, "Unknown compression type: %s", ct_name); ++ return -ENOTSUP; ++ } ++ ++ if (compression_type != s->compression_type) { ++ error_setg(errp, "Changing the compression type " ++ "is not supported"); ++ return -ENOTSUP; ++ } + } else { + /* if this point is reached, this probably means a new option was + * added without having it covered here */ +@@ -5596,6 +5703,12 @@ static QemuOptsList qcow2_create_opts = { + .help = "Width of a reference count entry in bits", + .def_value_str = "16" + }, ++ { ++ .name = BLOCK_OPT_COMPRESSION_TYPE, ++ .type = QEMU_OPT_STRING, ++ .help = "Compression method used for image cluster compression", ++ .def_value_str = "zlib" ++ }, + { /* end of list */ } + } + }; +diff --git a/block/qcow2.h b/block/qcow2.h +index f4de0a27d5..6a8b82e6cc 100644 +--- a/block/qcow2.h ++++ b/block/qcow2.h +@@ -146,8 +146,16 @@ typedef struct QCowHeader { + + uint32_t refcount_order; + uint32_t header_length; ++ ++ /* Additional fields */ ++ uint8_t compression_type; ++ ++ /* header must be a multiple of 8 */ ++ uint8_t padding[7]; + } QEMU_PACKED QCowHeader; + ++QEMU_BUILD_BUG_ON(!QEMU_IS_ALIGNED(sizeof(QCowHeader), 8)); ++ + typedef struct QEMU_PACKED QCowSnapshotHeader { + /* header is 8 byte aligned */ + uint64_t l1_table_offset; +@@ -216,13 +224,16 @@ enum { + QCOW2_INCOMPAT_DIRTY_BITNR = 0, + QCOW2_INCOMPAT_CORRUPT_BITNR = 1, + QCOW2_INCOMPAT_DATA_FILE_BITNR = 2, ++ QCOW2_INCOMPAT_COMPRESSION_BITNR = 3, + QCOW2_INCOMPAT_DIRTY = 1 << QCOW2_INCOMPAT_DIRTY_BITNR, + QCOW2_INCOMPAT_CORRUPT = 1 << QCOW2_INCOMPAT_CORRUPT_BITNR, + QCOW2_INCOMPAT_DATA_FILE = 1 << QCOW2_INCOMPAT_DATA_FILE_BITNR, ++ QCOW2_INCOMPAT_COMPRESSION = 1 << QCOW2_INCOMPAT_COMPRESSION_BITNR, + + QCOW2_INCOMPAT_MASK = QCOW2_INCOMPAT_DIRTY + | QCOW2_INCOMPAT_CORRUPT +- | QCOW2_INCOMPAT_DATA_FILE, ++ | QCOW2_INCOMPAT_DATA_FILE ++ | QCOW2_INCOMPAT_COMPRESSION, + }; + + /* Compatible feature bits */ +@@ -366,6 +377,13 @@ typedef struct BDRVQcow2State { + + bool metadata_preallocation_checked; + bool metadata_preallocation; ++ /* ++ * Compression type used for the image. Default: 0 - ZLIB ++ * The image compression type is set on image creation. ++ * For now, the only way to change the compression type ++ * is to convert the image with the desired compression type set. ++ */ ++ Qcow2CompressionType compression_type; + } BDRVQcow2State; + + typedef struct Qcow2COWRegion { +diff --git a/include/block/block_int.h b/include/block/block_int.h +index df6d0273d6..7ba8c89036 100644 +--- a/include/block/block_int.h ++++ b/include/block/block_int.h +@@ -57,6 +57,7 @@ + #define BLOCK_OPT_REFCOUNT_BITS "refcount_bits" + #define BLOCK_OPT_DATA_FILE "data_file" + #define BLOCK_OPT_DATA_FILE_RAW "data_file_raw" ++#define BLOCK_OPT_COMPRESSION_TYPE "compression_type" + + #define BLOCK_PROBE_BUF_SIZE 512 + +diff --git a/qapi/block-core.json b/qapi/block-core.json +index 943df1926a..1522e2983f 100644 +--- a/qapi/block-core.json ++++ b/qapi/block-core.json +@@ -78,6 +78,8 @@ + # + # @bitmaps: A list of qcow2 bitmap details (since 4.0) + # ++# @compression-type: the image cluster compression method (since 5.1) ++# + # Since: 1.7 + ## + { 'struct': 'ImageInfoSpecificQCow2', +@@ -89,7 +91,8 @@ + '*corrupt': 'bool', + 'refcount-bits': 'int', + '*encrypt': 'ImageInfoSpecificQCow2Encryption', +- '*bitmaps': ['Qcow2BitmapInfo'] ++ '*bitmaps': ['Qcow2BitmapInfo'], ++ 'compression-type': 'Qcow2CompressionType' + } } + + ## +@@ -4284,6 +4287,18 @@ + 'data': [ 'v2', 'v3' ] } + + ++## ++# @Qcow2CompressionType: ++# ++# Compression type used in qcow2 image file ++# ++# @zlib: zlib compression, see ++# ++# Since: 5.1 ++## ++{ 'enum': 'Qcow2CompressionType', ++ 'data': [ 'zlib' ] } ++ + ## + # @BlockdevCreateOptionsQcow2: + # +@@ -4307,6 +4322,8 @@ + # allowed values: off, falloc, full, metadata) + # @lazy-refcounts: True if refcounts may be updated lazily (default: off) + # @refcount-bits: Width of reference counts in bits (default: 16) ++# @compression-type: The image cluster compression method ++# (default: zlib, since 5.1) + # + # Since: 2.12 + ## +@@ -4322,7 +4339,8 @@ + '*cluster-size': 'size', + '*preallocation': 'PreallocMode', + '*lazy-refcounts': 'bool', +- '*refcount-bits': 'int' } } ++ '*refcount-bits': 'int', ++ '*compression-type':'Qcow2CompressionType' } } + + ## + # @BlockdevCreateOptionsQed: +diff --git a/tests/qemu-iotests/031.out b/tests/qemu-iotests/031.out +index 46f97c5a4e..5a4beda6a2 100644 +--- a/tests/qemu-iotests/031.out ++++ b/tests/qemu-iotests/031.out +@@ -113,11 +113,11 @@ incompatible_features [] + compatible_features [] + autoclear_features [] + refcount_order 4 +-header_length 104 ++header_length 112 + + Header extension: + magic 0x6803f857 +-length 288 ++length 336 + data + + Header extension: +@@ -146,11 +146,11 @@ incompatible_features [] + compatible_features [] + autoclear_features [] + refcount_order 4 +-header_length 104 ++header_length 112 + + Header extension: + magic 0x6803f857 +-length 288 ++length 336 + data + + Header extension: +@@ -164,7 +164,7 @@ No errors were found on the image. + + magic 0x514649fb + version 3 +-backing_file_offset 0x1d8 ++backing_file_offset 0x210 + backing_file_size 0x17 + cluster_bits 16 + size 67108864 +@@ -179,7 +179,7 @@ incompatible_features [] + compatible_features [] + autoclear_features [] + refcount_order 4 +-header_length 104 ++header_length 112 + + Header extension: + magic 0xe2792aca +@@ -188,7 +188,7 @@ data 'host_device' + + Header extension: + magic 0x6803f857 +-length 288 ++length 336 + data + + Header extension: +diff --git a/tests/qemu-iotests/036.out b/tests/qemu-iotests/036.out +index 23b699ce06..e409acf60e 100644 +--- a/tests/qemu-iotests/036.out ++++ b/tests/qemu-iotests/036.out +@@ -26,7 +26,7 @@ compatible_features [] + autoclear_features [63] + Header extension: + magic 0x6803f857 +-length 288 ++length 336 + data + + +@@ -38,7 +38,7 @@ compatible_features [] + autoclear_features [] + Header extension: + magic 0x6803f857 +-length 288 ++length 336 + data + + *** done +diff --git a/tests/qemu-iotests/049.out b/tests/qemu-iotests/049.out +index affa55b341..a5cfba1756 100644 +--- a/tests/qemu-iotests/049.out ++++ b/tests/qemu-iotests/049.out +@@ -4,90 +4,90 @@ QA output created by 049 + == 1. Traditional size parameter == + + qemu-img create -f qcow2 TEST_DIR/t.qcow2 1024 +-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib + + qemu-img create -f qcow2 TEST_DIR/t.qcow2 1024b +-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib + + qemu-img create -f qcow2 TEST_DIR/t.qcow2 1k +-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib + + qemu-img create -f qcow2 TEST_DIR/t.qcow2 1K +-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib + + qemu-img create -f qcow2 TEST_DIR/t.qcow2 1M +-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1048576 cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1048576 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib + + qemu-img create -f qcow2 TEST_DIR/t.qcow2 1G +-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1073741824 cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1073741824 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib + + qemu-img create -f qcow2 TEST_DIR/t.qcow2 1T +-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1099511627776 cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1099511627776 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib + + qemu-img create -f qcow2 TEST_DIR/t.qcow2 1024.0 +-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib + + qemu-img create -f qcow2 TEST_DIR/t.qcow2 1024.0b +-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib + + qemu-img create -f qcow2 TEST_DIR/t.qcow2 1.5k +-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1536 cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1536 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib + + qemu-img create -f qcow2 TEST_DIR/t.qcow2 1.5K +-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1536 cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1536 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib + + qemu-img create -f qcow2 TEST_DIR/t.qcow2 1.5M +-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1572864 cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1572864 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib + + qemu-img create -f qcow2 TEST_DIR/t.qcow2 1.5G +-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1610612736 cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1610612736 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib + + qemu-img create -f qcow2 TEST_DIR/t.qcow2 1.5T +-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1649267441664 cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1649267441664 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib + + == 2. Specifying size via -o == + + qemu-img create -f qcow2 -o size=1024 TEST_DIR/t.qcow2 +-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib + + qemu-img create -f qcow2 -o size=1024b TEST_DIR/t.qcow2 +-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib + + qemu-img create -f qcow2 -o size=1k TEST_DIR/t.qcow2 +-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib + + qemu-img create -f qcow2 -o size=1K TEST_DIR/t.qcow2 +-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib + + qemu-img create -f qcow2 -o size=1M TEST_DIR/t.qcow2 +-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1048576 cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1048576 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib + + qemu-img create -f qcow2 -o size=1G TEST_DIR/t.qcow2 +-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1073741824 cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1073741824 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib + + qemu-img create -f qcow2 -o size=1T TEST_DIR/t.qcow2 +-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1099511627776 cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1099511627776 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib + + qemu-img create -f qcow2 -o size=1024.0 TEST_DIR/t.qcow2 +-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib + + qemu-img create -f qcow2 -o size=1024.0b TEST_DIR/t.qcow2 +-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib + + qemu-img create -f qcow2 -o size=1.5k TEST_DIR/t.qcow2 +-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1536 cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1536 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib + + qemu-img create -f qcow2 -o size=1.5K TEST_DIR/t.qcow2 +-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1536 cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1536 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib + + qemu-img create -f qcow2 -o size=1.5M TEST_DIR/t.qcow2 +-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1572864 cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1572864 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib + + qemu-img create -f qcow2 -o size=1.5G TEST_DIR/t.qcow2 +-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1610612736 cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1610612736 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib + + qemu-img create -f qcow2 -o size=1.5T TEST_DIR/t.qcow2 +-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1649267441664 cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1649267441664 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib + + == 3. Invalid sizes == + +@@ -129,84 +129,84 @@ qemu-img: TEST_DIR/t.qcow2: The image size must be specified only once + == Check correct interpretation of suffixes for cluster size == + + qemu-img create -f qcow2 -o cluster_size=1024 TEST_DIR/t.qcow2 64M +-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 cluster_size=1024 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 cluster_size=1024 lazy_refcounts=off refcount_bits=16 compression_type=zlib + + qemu-img create -f qcow2 -o cluster_size=1024b TEST_DIR/t.qcow2 64M +-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 cluster_size=1024 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 cluster_size=1024 lazy_refcounts=off refcount_bits=16 compression_type=zlib + + qemu-img create -f qcow2 -o cluster_size=1k TEST_DIR/t.qcow2 64M +-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 cluster_size=1024 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 cluster_size=1024 lazy_refcounts=off refcount_bits=16 compression_type=zlib + + qemu-img create -f qcow2 -o cluster_size=1K TEST_DIR/t.qcow2 64M +-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 cluster_size=1024 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 cluster_size=1024 lazy_refcounts=off refcount_bits=16 compression_type=zlib + + qemu-img create -f qcow2 -o cluster_size=1M TEST_DIR/t.qcow2 64M +-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 cluster_size=1048576 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 cluster_size=1048576 lazy_refcounts=off refcount_bits=16 compression_type=zlib + + qemu-img create -f qcow2 -o cluster_size=1024.0 TEST_DIR/t.qcow2 64M +-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 cluster_size=1024 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 cluster_size=1024 lazy_refcounts=off refcount_bits=16 compression_type=zlib + + qemu-img create -f qcow2 -o cluster_size=1024.0b TEST_DIR/t.qcow2 64M +-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 cluster_size=1024 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 cluster_size=1024 lazy_refcounts=off refcount_bits=16 compression_type=zlib + + qemu-img create -f qcow2 -o cluster_size=0.5k TEST_DIR/t.qcow2 64M +-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 cluster_size=512 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 cluster_size=512 lazy_refcounts=off refcount_bits=16 compression_type=zlib + + qemu-img create -f qcow2 -o cluster_size=0.5K TEST_DIR/t.qcow2 64M +-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 cluster_size=512 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 cluster_size=512 lazy_refcounts=off refcount_bits=16 compression_type=zlib + + qemu-img create -f qcow2 -o cluster_size=0.5M TEST_DIR/t.qcow2 64M +-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 cluster_size=524288 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 cluster_size=524288 lazy_refcounts=off refcount_bits=16 compression_type=zlib + + == Check compat level option == + + qemu-img create -f qcow2 -o compat=0.10 TEST_DIR/t.qcow2 64M +-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat=0.10 cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat=0.10 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib + + qemu-img create -f qcow2 -o compat=1.1 TEST_DIR/t.qcow2 64M +-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat=1.1 cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat=1.1 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib + + qemu-img create -f qcow2 -o compat=0.42 TEST_DIR/t.qcow2 64M + qemu-img: TEST_DIR/t.qcow2: Invalid parameter '0.42' +-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat=0.42 cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat=0.42 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib + + qemu-img create -f qcow2 -o compat=foobar TEST_DIR/t.qcow2 64M + qemu-img: TEST_DIR/t.qcow2: Invalid parameter 'foobar' +-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat=foobar cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat=foobar cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib + + == Check preallocation option == + + qemu-img create -f qcow2 -o preallocation=off TEST_DIR/t.qcow2 64M +-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 cluster_size=65536 preallocation=off lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 cluster_size=65536 preallocation=off lazy_refcounts=off refcount_bits=16 compression_type=zlib + + qemu-img create -f qcow2 -o preallocation=metadata TEST_DIR/t.qcow2 64M +-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 cluster_size=65536 preallocation=metadata lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 cluster_size=65536 preallocation=metadata lazy_refcounts=off refcount_bits=16 compression_type=zlib + + qemu-img create -f qcow2 -o preallocation=1234 TEST_DIR/t.qcow2 64M + qemu-img: TEST_DIR/t.qcow2: Invalid parameter '1234' +-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 cluster_size=65536 preallocation=1234 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 cluster_size=65536 preallocation=1234 lazy_refcounts=off refcount_bits=16 compression_type=zlib + + == Check encryption option == + + qemu-img create -f qcow2 -o encryption=off TEST_DIR/t.qcow2 64M +-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib + + qemu-img create -f qcow2 --object secret,id=sec0,data=123456 -o encryption=on,encrypt.key-secret=sec0 TEST_DIR/t.qcow2 64M +-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=on encrypt.key-secret=sec0 cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=on encrypt.key-secret=sec0 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib + + == Check lazy_refcounts option (only with v3) == + + qemu-img create -f qcow2 -o compat=1.1,lazy_refcounts=off TEST_DIR/t.qcow2 64M +-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat=1.1 cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat=1.1 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib + + qemu-img create -f qcow2 -o compat=1.1,lazy_refcounts=on TEST_DIR/t.qcow2 64M +-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat=1.1 cluster_size=65536 lazy_refcounts=on refcount_bits=16 ++Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat=1.1 cluster_size=65536 lazy_refcounts=on refcount_bits=16 compression_type=zlib + + qemu-img create -f qcow2 -o compat=0.10,lazy_refcounts=off TEST_DIR/t.qcow2 64M +-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat=0.10 cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat=0.10 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib + + qemu-img create -f qcow2 -o compat=0.10,lazy_refcounts=on TEST_DIR/t.qcow2 64M + qemu-img: TEST_DIR/t.qcow2: Lazy refcounts only supported with compatibility level 1.1 and above (use version=v3 or greater) +-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat=0.10 cluster_size=65536 lazy_refcounts=on refcount_bits=16 ++Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat=0.10 cluster_size=65536 lazy_refcounts=on refcount_bits=16 compression_type=zlib + + *** done +diff --git a/tests/qemu-iotests/060.out b/tests/qemu-iotests/060.out +index 09caaea865..be5f8707a3 100644 +--- a/tests/qemu-iotests/060.out ++++ b/tests/qemu-iotests/060.out +@@ -17,6 +17,7 @@ virtual size: 64 MiB (67108864 bytes) + cluster_size: 65536 + Format specific information: + compat: 1.1 ++ compression type: zlib + lazy refcounts: false + refcount bits: 16 + corrupt: true +diff --git a/tests/qemu-iotests/061.out b/tests/qemu-iotests/061.out +index 5a8d36d005..a51ad1b5ba 100644 +--- a/tests/qemu-iotests/061.out ++++ b/tests/qemu-iotests/061.out +@@ -22,11 +22,11 @@ incompatible_features [] + compatible_features [0] + autoclear_features [] + refcount_order 4 +-header_length 104 ++header_length 112 + + Header extension: + magic 0x6803f857 +-length 288 ++length 336 + data + + magic 0x514649fb +@@ -80,11 +80,11 @@ incompatible_features [] + compatible_features [0] + autoclear_features [] + refcount_order 4 +-header_length 104 ++header_length 112 + + Header extension: + magic 0x6803f857 +-length 288 ++length 336 + data + + magic 0x514649fb +@@ -136,11 +136,11 @@ incompatible_features [0] + compatible_features [0] + autoclear_features [] + refcount_order 4 +-header_length 104 ++header_length 112 + + Header extension: + magic 0x6803f857 +-length 288 ++length 336 + data + + ERROR cluster 5 refcount=0 reference=1 +@@ -191,11 +191,11 @@ incompatible_features [] + compatible_features [42] + autoclear_features [42] + refcount_order 4 +-header_length 104 ++header_length 112 + + Header extension: + magic 0x6803f857 +-length 288 ++length 336 + data + + magic 0x514649fb +@@ -260,11 +260,11 @@ incompatible_features [] + compatible_features [0] + autoclear_features [] + refcount_order 4 +-header_length 104 ++header_length 112 + + Header extension: + magic 0x6803f857 +-length 288 ++length 336 + data + + read 65536/65536 bytes at offset 44040192 +@@ -322,11 +322,11 @@ incompatible_features [0] + compatible_features [0] + autoclear_features [] + refcount_order 4 +-header_length 104 ++header_length 112 + + Header extension: + magic 0x6803f857 +-length 288 ++length 336 + data + + ERROR cluster 5 refcount=0 reference=1 +@@ -351,11 +351,11 @@ incompatible_features [] + compatible_features [] + autoclear_features [] + refcount_order 4 +-header_length 104 ++header_length 112 + + Header extension: + magic 0x6803f857 +-length 288 ++length 336 + data + + read 131072/131072 bytes at offset 0 +@@ -519,6 +519,7 @@ virtual size: 64 MiB (67108864 bytes) + cluster_size: 65536 + Format specific information: + compat: 1.1 ++ compression type: zlib + lazy refcounts: false + refcount bits: 16 + data file: TEST_DIR/t.IMGFMT.data +@@ -539,6 +540,7 @@ virtual size: 64 MiB (67108864 bytes) + cluster_size: 65536 + Format specific information: + compat: 1.1 ++ compression type: zlib + lazy refcounts: false + refcount bits: 16 + data file: foo +@@ -552,6 +554,7 @@ virtual size: 64 MiB (67108864 bytes) + cluster_size: 65536 + Format specific information: + compat: 1.1 ++ compression type: zlib + lazy refcounts: false + refcount bits: 16 + data file raw: false +@@ -566,6 +569,7 @@ virtual size: 64 MiB (67108864 bytes) + cluster_size: 65536 + Format specific information: + compat: 1.1 ++ compression type: zlib + lazy refcounts: false + refcount bits: 16 + data file: TEST_DIR/t.IMGFMT.data +@@ -578,6 +582,7 @@ virtual size: 64 MiB (67108864 bytes) + cluster_size: 65536 + Format specific information: + compat: 1.1 ++ compression type: zlib + lazy refcounts: false + refcount bits: 16 + data file: TEST_DIR/t.IMGFMT.data +@@ -591,6 +596,7 @@ virtual size: 64 MiB (67108864 bytes) + cluster_size: 65536 + Format specific information: + compat: 1.1 ++ compression type: zlib + lazy refcounts: false + refcount bits: 16 + data file: TEST_DIR/t.IMGFMT.data +diff --git a/tests/qemu-iotests/065 b/tests/qemu-iotests/065 +index 6426474271..18dc488c7a 100755 +--- a/tests/qemu-iotests/065 ++++ b/tests/qemu-iotests/065 +@@ -88,24 +88,30 @@ class TestQMP(TestImageInfoSpecific): + class TestQCow2(TestQemuImgInfo): + '''Testing a qcow2 version 2 image''' + img_options = 'compat=0.10' +- json_compare = { 'compat': '0.10', 'refcount-bits': 16 } +- human_compare = [ 'compat: 0.10', 'refcount bits: 16' ] ++ json_compare = { 'compat': '0.10', 'refcount-bits': 16, ++ 'compression-type': 'zlib' } ++ human_compare = [ 'compat: 0.10', 'compression type: zlib', ++ 'refcount bits: 16' ] + + class TestQCow3NotLazy(TestQemuImgInfo): + '''Testing a qcow2 version 3 image with lazy refcounts disabled''' + img_options = 'compat=1.1,lazy_refcounts=off' + json_compare = { 'compat': '1.1', 'lazy-refcounts': False, +- 'refcount-bits': 16, 'corrupt': False } +- human_compare = [ 'compat: 1.1', 'lazy refcounts: false', +- 'refcount bits: 16', 'corrupt: false' ] ++ 'refcount-bits': 16, 'corrupt': False, ++ 'compression-type': 'zlib' } ++ human_compare = [ 'compat: 1.1', 'compression type: zlib', ++ 'lazy refcounts: false', 'refcount bits: 16', ++ 'corrupt: false' ] + + class TestQCow3Lazy(TestQemuImgInfo): + '''Testing a qcow2 version 3 image with lazy refcounts enabled''' + img_options = 'compat=1.1,lazy_refcounts=on' + json_compare = { 'compat': '1.1', 'lazy-refcounts': True, +- 'refcount-bits': 16, 'corrupt': False } +- human_compare = [ 'compat: 1.1', 'lazy refcounts: true', +- 'refcount bits: 16', 'corrupt: false' ] ++ 'refcount-bits': 16, 'corrupt': False, ++ 'compression-type': 'zlib' } ++ human_compare = [ 'compat: 1.1', 'compression type: zlib', ++ 'lazy refcounts: true', 'refcount bits: 16', ++ 'corrupt: false' ] + + class TestQCow3NotLazyQMP(TestQMP): + '''Testing a qcow2 version 3 image with lazy refcounts disabled, opening +@@ -113,7 +119,8 @@ class TestQCow3NotLazyQMP(TestQMP): + img_options = 'compat=1.1,lazy_refcounts=off' + qemu_options = 'lazy-refcounts=on' + compare = { 'compat': '1.1', 'lazy-refcounts': False, +- 'refcount-bits': 16, 'corrupt': False } ++ 'refcount-bits': 16, 'corrupt': False, ++ 'compression-type': 'zlib' } + + + class TestQCow3LazyQMP(TestQMP): +@@ -122,7 +129,8 @@ class TestQCow3LazyQMP(TestQMP): + img_options = 'compat=1.1,lazy_refcounts=on' + qemu_options = 'lazy-refcounts=off' + compare = { 'compat': '1.1', 'lazy-refcounts': True, +- 'refcount-bits': 16, 'corrupt': False } ++ 'refcount-bits': 16, 'corrupt': False, ++ 'compression-type': 'zlib' } + + TestImageInfoSpecific = None + TestQemuImgInfo = None +diff --git a/tests/qemu-iotests/080 b/tests/qemu-iotests/080 +index a3d13c414e..7588c63b6c 100755 +--- a/tests/qemu-iotests/080 ++++ b/tests/qemu-iotests/080 +@@ -45,7 +45,7 @@ _supported_os Linux + # - This is generally a test for compat=1.1 images + _unsupported_imgopts 'refcount_bits=1[^0-9]' data_file 'compat=0.10' + +-header_size=104 ++header_size=112 + + offset_backing_file_offset=8 + offset_backing_file_size=16 +diff --git a/tests/qemu-iotests/082.out b/tests/qemu-iotests/082.out +index 9d4ed4dc9d..529a1214e1 100644 +--- a/tests/qemu-iotests/082.out ++++ b/tests/qemu-iotests/082.out +@@ -3,38 +3,40 @@ QA output created by 082 + === create: Options specified more than once === + + Testing: create -f foo -f qcow2 TEST_DIR/t.qcow2 128M +-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=134217728 cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=134217728 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib + image: TEST_DIR/t.IMGFMT + file format: IMGFMT + virtual size: 128 MiB (134217728 bytes) + cluster_size: 65536 + + Testing: create -f qcow2 -o cluster_size=4k -o lazy_refcounts=on TEST_DIR/t.qcow2 128M +-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=134217728 cluster_size=4096 lazy_refcounts=on refcount_bits=16 ++Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=134217728 cluster_size=4096 lazy_refcounts=on refcount_bits=16 compression_type=zlib + image: TEST_DIR/t.IMGFMT + file format: IMGFMT + virtual size: 128 MiB (134217728 bytes) + cluster_size: 4096 + Format specific information: + compat: 1.1 ++ compression type: zlib + lazy refcounts: true + refcount bits: 16 + corrupt: false + + Testing: create -f qcow2 -o cluster_size=4k -o lazy_refcounts=on -o cluster_size=8k TEST_DIR/t.qcow2 128M +-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=134217728 cluster_size=8192 lazy_refcounts=on refcount_bits=16 ++Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=134217728 cluster_size=8192 lazy_refcounts=on refcount_bits=16 compression_type=zlib + image: TEST_DIR/t.IMGFMT + file format: IMGFMT + virtual size: 128 MiB (134217728 bytes) + cluster_size: 8192 + Format specific information: + compat: 1.1 ++ compression type: zlib + lazy refcounts: true + refcount bits: 16 + corrupt: false + + Testing: create -f qcow2 -o cluster_size=4k,cluster_size=8k TEST_DIR/t.qcow2 128M +-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=134217728 cluster_size=8192 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=134217728 cluster_size=8192 lazy_refcounts=off refcount_bits=16 compression_type=zlib + image: TEST_DIR/t.IMGFMT + file format: IMGFMT + virtual size: 128 MiB (134217728 bytes) +@@ -48,6 +50,7 @@ Supported options: + backing_fmt= - Image format of the base image + cluster_size= - qcow2 cluster size + compat= - Compatibility level (v2 [0.10] or v3 [1.1]) ++ compression_type= - Compression method used for image cluster compression + data_file= - File name of an external data file + data_file_raw= - The external data file must stay valid as a raw image + encrypt.cipher-alg= - Name of encryption cipher algorithm +@@ -71,6 +74,7 @@ Supported options: + backing_fmt= - Image format of the base image + cluster_size= - qcow2 cluster size + compat= - Compatibility level (v2 [0.10] or v3 [1.1]) ++ compression_type= - Compression method used for image cluster compression + data_file= - File name of an external data file + data_file_raw= - The external data file must stay valid as a raw image + encrypt.cipher-alg= - Name of encryption cipher algorithm +@@ -94,6 +98,7 @@ Supported options: + backing_fmt= - Image format of the base image + cluster_size= - qcow2 cluster size + compat= - Compatibility level (v2 [0.10] or v3 [1.1]) ++ compression_type= - Compression method used for image cluster compression + data_file= - File name of an external data file + data_file_raw= - The external data file must stay valid as a raw image + encrypt.cipher-alg= - Name of encryption cipher algorithm +@@ -117,6 +122,7 @@ Supported options: + backing_fmt= - Image format of the base image + cluster_size= - qcow2 cluster size + compat= - Compatibility level (v2 [0.10] or v3 [1.1]) ++ compression_type= - Compression method used for image cluster compression + data_file= - File name of an external data file + data_file_raw= - The external data file must stay valid as a raw image + encrypt.cipher-alg= - Name of encryption cipher algorithm +@@ -140,6 +146,7 @@ Supported options: + backing_fmt= - Image format of the base image + cluster_size= - qcow2 cluster size + compat= - Compatibility level (v2 [0.10] or v3 [1.1]) ++ compression_type= - Compression method used for image cluster compression + data_file= - File name of an external data file + data_file_raw= - The external data file must stay valid as a raw image + encrypt.cipher-alg= - Name of encryption cipher algorithm +@@ -163,6 +170,7 @@ Supported options: + backing_fmt= - Image format of the base image + cluster_size= - qcow2 cluster size + compat= - Compatibility level (v2 [0.10] or v3 [1.1]) ++ compression_type= - Compression method used for image cluster compression + data_file= - File name of an external data file + data_file_raw= - The external data file must stay valid as a raw image + encrypt.cipher-alg= - Name of encryption cipher algorithm +@@ -186,6 +194,7 @@ Supported options: + backing_fmt= - Image format of the base image + cluster_size= - qcow2 cluster size + compat= - Compatibility level (v2 [0.10] or v3 [1.1]) ++ compression_type= - Compression method used for image cluster compression + data_file= - File name of an external data file + data_file_raw= - The external data file must stay valid as a raw image + encrypt.cipher-alg= - Name of encryption cipher algorithm +@@ -209,6 +218,7 @@ Supported options: + backing_fmt= - Image format of the base image + cluster_size= - qcow2 cluster size + compat= - Compatibility level (v2 [0.10] or v3 [1.1]) ++ compression_type= - Compression method used for image cluster compression + data_file= - File name of an external data file + data_file_raw= - The external data file must stay valid as a raw image + encrypt.cipher-alg= - Name of encryption cipher algorithm +@@ -227,10 +237,10 @@ Supported options: + size= - Virtual disk size + + Testing: create -f qcow2 -u -o backing_file=TEST_DIR/t.qcow2,,help TEST_DIR/t.qcow2 128M +-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/t.qcow2,,help cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/t.qcow2,,help cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib + + Testing: create -f qcow2 -u -o backing_file=TEST_DIR/t.qcow2,,? TEST_DIR/t.qcow2 128M +-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/t.qcow2,,? cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/t.qcow2,,? cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib + + Testing: create -f qcow2 -o backing_file=TEST_DIR/t.qcow2, -o help TEST_DIR/t.qcow2 128M + qemu-img: Invalid option list: backing_file=TEST_DIR/t.qcow2, +@@ -247,6 +257,7 @@ Supported qcow2 options: + backing_fmt= - Image format of the base image + cluster_size= - qcow2 cluster size + compat= - Compatibility level (v2 [0.10] or v3 [1.1]) ++ compression_type= - Compression method used for image cluster compression + data_file= - File name of an external data file + data_file_raw= - The external data file must stay valid as a raw image + encrypt.cipher-alg= - Name of encryption cipher algorithm +@@ -279,7 +290,7 @@ qemu-img: Format driver 'bochs' does not support image creation + === convert: Options specified more than once === + + Testing: create -f qcow2 TEST_DIR/t.qcow2 128M +-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=134217728 cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=134217728 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib + + Testing: convert -f foo -f qcow2 TEST_DIR/t.qcow2 TEST_DIR/t.qcow2.base + image: TEST_DIR/t.IMGFMT.base +@@ -299,6 +310,7 @@ virtual size: 128 MiB (134217728 bytes) + cluster_size: 4096 + Format specific information: + compat: 1.1 ++ compression type: zlib + lazy refcounts: true + refcount bits: 16 + corrupt: false +@@ -310,6 +322,7 @@ virtual size: 128 MiB (134217728 bytes) + cluster_size: 8192 + Format specific information: + compat: 1.1 ++ compression type: zlib + lazy refcounts: true + refcount bits: 16 + corrupt: false +@@ -328,6 +341,7 @@ Supported options: + backing_fmt= - Image format of the base image + cluster_size= - qcow2 cluster size + compat= - Compatibility level (v2 [0.10] or v3 [1.1]) ++ compression_type= - Compression method used for image cluster compression + data_file= - File name of an external data file + data_file_raw= - The external data file must stay valid as a raw image + encrypt.cipher-alg= - Name of encryption cipher algorithm +@@ -351,6 +365,7 @@ Supported options: + backing_fmt= - Image format of the base image + cluster_size= - qcow2 cluster size + compat= - Compatibility level (v2 [0.10] or v3 [1.1]) ++ compression_type= - Compression method used for image cluster compression + data_file= - File name of an external data file + data_file_raw= - The external data file must stay valid as a raw image + encrypt.cipher-alg= - Name of encryption cipher algorithm +@@ -374,6 +389,7 @@ Supported options: + backing_fmt= - Image format of the base image + cluster_size= - qcow2 cluster size + compat= - Compatibility level (v2 [0.10] or v3 [1.1]) ++ compression_type= - Compression method used for image cluster compression + data_file= - File name of an external data file + data_file_raw= - The external data file must stay valid as a raw image + encrypt.cipher-alg= - Name of encryption cipher algorithm +@@ -397,6 +413,7 @@ Supported options: + backing_fmt= - Image format of the base image + cluster_size= - qcow2 cluster size + compat= - Compatibility level (v2 [0.10] or v3 [1.1]) ++ compression_type= - Compression method used for image cluster compression + data_file= - File name of an external data file + data_file_raw= - The external data file must stay valid as a raw image + encrypt.cipher-alg= - Name of encryption cipher algorithm +@@ -420,6 +437,7 @@ Supported options: + backing_fmt= - Image format of the base image + cluster_size= - qcow2 cluster size + compat= - Compatibility level (v2 [0.10] or v3 [1.1]) ++ compression_type= - Compression method used for image cluster compression + data_file= - File name of an external data file + data_file_raw= - The external data file must stay valid as a raw image + encrypt.cipher-alg= - Name of encryption cipher algorithm +@@ -443,6 +461,7 @@ Supported options: + backing_fmt= - Image format of the base image + cluster_size= - qcow2 cluster size + compat= - Compatibility level (v2 [0.10] or v3 [1.1]) ++ compression_type= - Compression method used for image cluster compression + data_file= - File name of an external data file + data_file_raw= - The external data file must stay valid as a raw image + encrypt.cipher-alg= - Name of encryption cipher algorithm +@@ -466,6 +485,7 @@ Supported options: + backing_fmt= - Image format of the base image + cluster_size= - qcow2 cluster size + compat= - Compatibility level (v2 [0.10] or v3 [1.1]) ++ compression_type= - Compression method used for image cluster compression + data_file= - File name of an external data file + data_file_raw= - The external data file must stay valid as a raw image + encrypt.cipher-alg= - Name of encryption cipher algorithm +@@ -489,6 +509,7 @@ Supported options: + backing_fmt= - Image format of the base image + cluster_size= - qcow2 cluster size + compat= - Compatibility level (v2 [0.10] or v3 [1.1]) ++ compression_type= - Compression method used for image cluster compression + data_file= - File name of an external data file + data_file_raw= - The external data file must stay valid as a raw image + encrypt.cipher-alg= - Name of encryption cipher algorithm +@@ -527,6 +548,7 @@ Supported qcow2 options: + backing_fmt= - Image format of the base image + cluster_size= - qcow2 cluster size + compat= - Compatibility level (v2 [0.10] or v3 [1.1]) ++ compression_type= - Compression method used for image cluster compression + data_file= - File name of an external data file + data_file_raw= - The external data file must stay valid as a raw image + encrypt.cipher-alg= - Name of encryption cipher algorithm +@@ -579,6 +601,7 @@ virtual size: 128 MiB (134217728 bytes) + cluster_size: 65536 + Format specific information: + compat: 1.1 ++ compression type: zlib + lazy refcounts: true + refcount bits: 16 + corrupt: false +@@ -590,6 +613,7 @@ virtual size: 130 MiB (136314880 bytes) + cluster_size: 65536 + Format specific information: + compat: 1.1 ++ compression type: zlib + lazy refcounts: false + refcount bits: 16 + corrupt: false +@@ -601,6 +625,7 @@ virtual size: 132 MiB (138412032 bytes) + cluster_size: 65536 + Format specific information: + compat: 1.1 ++ compression type: zlib + lazy refcounts: true + refcount bits: 16 + corrupt: false +@@ -619,6 +644,7 @@ Creation options for 'qcow2': + backing_fmt= - Image format of the base image + cluster_size= - qcow2 cluster size + compat= - Compatibility level (v2 [0.10] or v3 [1.1]) ++ compression_type= - Compression method used for image cluster compression + data_file= - File name of an external data file + data_file_raw= - The external data file must stay valid as a raw image + encrypt.cipher-alg= - Name of encryption cipher algorithm +@@ -643,6 +669,7 @@ Creation options for 'qcow2': + backing_fmt= - Image format of the base image + cluster_size= - qcow2 cluster size + compat= - Compatibility level (v2 [0.10] or v3 [1.1]) ++ compression_type= - Compression method used for image cluster compression + data_file= - File name of an external data file + data_file_raw= - The external data file must stay valid as a raw image + encrypt.cipher-alg= - Name of encryption cipher algorithm +@@ -667,6 +694,7 @@ Creation options for 'qcow2': + backing_fmt= - Image format of the base image + cluster_size= - qcow2 cluster size + compat= - Compatibility level (v2 [0.10] or v3 [1.1]) ++ compression_type= - Compression method used for image cluster compression + data_file= - File name of an external data file + data_file_raw= - The external data file must stay valid as a raw image + encrypt.cipher-alg= - Name of encryption cipher algorithm +@@ -691,6 +719,7 @@ Creation options for 'qcow2': + backing_fmt= - Image format of the base image + cluster_size= - qcow2 cluster size + compat= - Compatibility level (v2 [0.10] or v3 [1.1]) ++ compression_type= - Compression method used for image cluster compression + data_file= - File name of an external data file + data_file_raw= - The external data file must stay valid as a raw image + encrypt.cipher-alg= - Name of encryption cipher algorithm +@@ -715,6 +744,7 @@ Creation options for 'qcow2': + backing_fmt= - Image format of the base image + cluster_size= - qcow2 cluster size + compat= - Compatibility level (v2 [0.10] or v3 [1.1]) ++ compression_type= - Compression method used for image cluster compression + data_file= - File name of an external data file + data_file_raw= - The external data file must stay valid as a raw image + encrypt.cipher-alg= - Name of encryption cipher algorithm +@@ -739,6 +769,7 @@ Creation options for 'qcow2': + backing_fmt= - Image format of the base image + cluster_size= - qcow2 cluster size + compat= - Compatibility level (v2 [0.10] or v3 [1.1]) ++ compression_type= - Compression method used for image cluster compression + data_file= - File name of an external data file + data_file_raw= - The external data file must stay valid as a raw image + encrypt.cipher-alg= - Name of encryption cipher algorithm +@@ -763,6 +794,7 @@ Creation options for 'qcow2': + backing_fmt= - Image format of the base image + cluster_size= - qcow2 cluster size + compat= - Compatibility level (v2 [0.10] or v3 [1.1]) ++ compression_type= - Compression method used for image cluster compression + data_file= - File name of an external data file + data_file_raw= - The external data file must stay valid as a raw image + encrypt.cipher-alg= - Name of encryption cipher algorithm +@@ -787,6 +819,7 @@ Creation options for 'qcow2': + backing_fmt= - Image format of the base image + cluster_size= - qcow2 cluster size + compat= - Compatibility level (v2 [0.10] or v3 [1.1]) ++ compression_type= - Compression method used for image cluster compression + data_file= - File name of an external data file + data_file_raw= - The external data file must stay valid as a raw image + encrypt.cipher-alg= - Name of encryption cipher algorithm +@@ -828,6 +861,7 @@ Creation options for 'qcow2': + backing_fmt= - Image format of the base image + cluster_size= - qcow2 cluster size + compat= - Compatibility level (v2 [0.10] or v3 [1.1]) ++ compression_type= - Compression method used for image cluster compression + data_file= - File name of an external data file + data_file_raw= - The external data file must stay valid as a raw image + encrypt.cipher-alg= - Name of encryption cipher algorithm +diff --git a/tests/qemu-iotests/085.out b/tests/qemu-iotests/085.out +index fd11aae678..a822ff4ef6 100644 +--- a/tests/qemu-iotests/085.out ++++ b/tests/qemu-iotests/085.out +@@ -13,7 +13,7 @@ Formatting 'TEST_DIR/t.IMGFMT.2', fmt=IMGFMT size=134217728 + === Create a single snapshot on virtio0 === + + { 'execute': 'blockdev-snapshot-sync', 'arguments': { 'device': 'virtio0', 'snapshot-file':'TEST_DIR/1-snapshot-v0.IMGFMT', 'format': 'IMGFMT' } } +-Formatting 'TEST_DIR/1-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/t.qcow2.1 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/1-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/t.qcow2.1 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib + {"return": {}} + + === Invalid command - missing device and nodename === +@@ -30,40 +30,40 @@ Formatting 'TEST_DIR/1-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file + === Create several transactional group snapshots === + + { 'execute': 'transaction', 'arguments': {'actions': [ { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio0', 'snapshot-file': 'TEST_DIR/2-snapshot-v0.IMGFMT' } }, { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio1', 'snapshot-file': 'TEST_DIR/2-snapshot-v1.IMGFMT' } } ] } } +-Formatting 'TEST_DIR/2-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/1-snapshot-v0.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16 +-Formatting 'TEST_DIR/2-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/t.qcow2.2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/2-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/1-snapshot-v0.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib ++Formatting 'TEST_DIR/2-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/t.qcow2.2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib + {"return": {}} + { 'execute': 'transaction', 'arguments': {'actions': [ { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio0', 'snapshot-file': 'TEST_DIR/3-snapshot-v0.IMGFMT' } }, { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio1', 'snapshot-file': 'TEST_DIR/3-snapshot-v1.IMGFMT' } } ] } } +-Formatting 'TEST_DIR/3-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/2-snapshot-v0.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16 +-Formatting 'TEST_DIR/3-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/2-snapshot-v1.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/3-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/2-snapshot-v0.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib ++Formatting 'TEST_DIR/3-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/2-snapshot-v1.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib + {"return": {}} + { 'execute': 'transaction', 'arguments': {'actions': [ { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio0', 'snapshot-file': 'TEST_DIR/4-snapshot-v0.IMGFMT' } }, { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio1', 'snapshot-file': 'TEST_DIR/4-snapshot-v1.IMGFMT' } } ] } } +-Formatting 'TEST_DIR/4-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/3-snapshot-v0.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16 +-Formatting 'TEST_DIR/4-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/3-snapshot-v1.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/4-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/3-snapshot-v0.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib ++Formatting 'TEST_DIR/4-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/3-snapshot-v1.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib + {"return": {}} + { 'execute': 'transaction', 'arguments': {'actions': [ { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio0', 'snapshot-file': 'TEST_DIR/5-snapshot-v0.IMGFMT' } }, { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio1', 'snapshot-file': 'TEST_DIR/5-snapshot-v1.IMGFMT' } } ] } } +-Formatting 'TEST_DIR/5-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/4-snapshot-v0.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16 +-Formatting 'TEST_DIR/5-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/4-snapshot-v1.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/5-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/4-snapshot-v0.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib ++Formatting 'TEST_DIR/5-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/4-snapshot-v1.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib + {"return": {}} + { 'execute': 'transaction', 'arguments': {'actions': [ { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio0', 'snapshot-file': 'TEST_DIR/6-snapshot-v0.IMGFMT' } }, { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio1', 'snapshot-file': 'TEST_DIR/6-snapshot-v1.IMGFMT' } } ] } } +-Formatting 'TEST_DIR/6-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/5-snapshot-v0.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16 +-Formatting 'TEST_DIR/6-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/5-snapshot-v1.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/6-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/5-snapshot-v0.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib ++Formatting 'TEST_DIR/6-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/5-snapshot-v1.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib + {"return": {}} + { 'execute': 'transaction', 'arguments': {'actions': [ { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio0', 'snapshot-file': 'TEST_DIR/7-snapshot-v0.IMGFMT' } }, { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio1', 'snapshot-file': 'TEST_DIR/7-snapshot-v1.IMGFMT' } } ] } } +-Formatting 'TEST_DIR/7-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/6-snapshot-v0.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16 +-Formatting 'TEST_DIR/7-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/6-snapshot-v1.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/7-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/6-snapshot-v0.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib ++Formatting 'TEST_DIR/7-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/6-snapshot-v1.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib + {"return": {}} + { 'execute': 'transaction', 'arguments': {'actions': [ { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio0', 'snapshot-file': 'TEST_DIR/8-snapshot-v0.IMGFMT' } }, { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio1', 'snapshot-file': 'TEST_DIR/8-snapshot-v1.IMGFMT' } } ] } } +-Formatting 'TEST_DIR/8-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/7-snapshot-v0.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16 +-Formatting 'TEST_DIR/8-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/7-snapshot-v1.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/8-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/7-snapshot-v0.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib ++Formatting 'TEST_DIR/8-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/7-snapshot-v1.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib + {"return": {}} + { 'execute': 'transaction', 'arguments': {'actions': [ { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio0', 'snapshot-file': 'TEST_DIR/9-snapshot-v0.IMGFMT' } }, { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio1', 'snapshot-file': 'TEST_DIR/9-snapshot-v1.IMGFMT' } } ] } } +-Formatting 'TEST_DIR/9-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/8-snapshot-v0.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16 +-Formatting 'TEST_DIR/9-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/8-snapshot-v1.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/9-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/8-snapshot-v0.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib ++Formatting 'TEST_DIR/9-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/8-snapshot-v1.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib + {"return": {}} + { 'execute': 'transaction', 'arguments': {'actions': [ { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio0', 'snapshot-file': 'TEST_DIR/10-snapshot-v0.IMGFMT' } }, { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio1', 'snapshot-file': 'TEST_DIR/10-snapshot-v1.IMGFMT' } } ] } } +-Formatting 'TEST_DIR/10-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/9-snapshot-v0.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16 +-Formatting 'TEST_DIR/10-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/9-snapshot-v1.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/10-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/9-snapshot-v0.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib ++Formatting 'TEST_DIR/10-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/9-snapshot-v1.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib + {"return": {}} + + === Create a couple of snapshots using blockdev-snapshot === +diff --git a/tests/qemu-iotests/144.out b/tests/qemu-iotests/144.out +index c7aa2e4820..885a8874a5 100644 +--- a/tests/qemu-iotests/144.out ++++ b/tests/qemu-iotests/144.out +@@ -9,7 +9,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=536870912 + { 'execute': 'qmp_capabilities' } + {"return": {}} + { 'execute': 'blockdev-snapshot-sync', 'arguments': { 'device': 'virtio0', 'snapshot-file':'TEST_DIR/tmp.IMGFMT', 'format': 'IMGFMT' } } +-Formatting 'TEST_DIR/tmp.qcow2', fmt=qcow2 size=536870912 backing_file=TEST_DIR/t.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/tmp.qcow2', fmt=qcow2 size=536870912 backing_file=TEST_DIR/t.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib + {"return": {}} + + === Performing block-commit on active layer === +@@ -31,6 +31,6 @@ Formatting 'TEST_DIR/tmp.qcow2', fmt=qcow2 size=536870912 backing_file=TEST_DIR/ + === Performing Live Snapshot 2 === + + { 'execute': 'blockdev-snapshot-sync', 'arguments': { 'device': 'virtio0', 'snapshot-file':'TEST_DIR/tmp2.IMGFMT', 'format': 'IMGFMT' } } +-Formatting 'TEST_DIR/tmp2.qcow2', fmt=qcow2 size=536870912 backing_file=TEST_DIR/t.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/tmp2.qcow2', fmt=qcow2 size=536870912 backing_file=TEST_DIR/t.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib + {"return": {}} + *** done +diff --git a/tests/qemu-iotests/182.out b/tests/qemu-iotests/182.out +index a8eea166c3..ae43654d32 100644 +--- a/tests/qemu-iotests/182.out ++++ b/tests/qemu-iotests/182.out +@@ -13,7 +13,7 @@ Is another process using the image [TEST_DIR/t.qcow2]? + {'execute': 'blockdev-add', 'arguments': { 'node-name': 'node0', 'driver': 'file', 'filename': 'TEST_DIR/t.IMGFMT', 'locking': 'on' } } + {"return": {}} + {'execute': 'blockdev-snapshot-sync', 'arguments': { 'node-name': 'node0', 'snapshot-file': 'TEST_DIR/t.IMGFMT.overlay', 'snapshot-node-name': 'node1' } } +-Formatting 'TEST_DIR/t.qcow2.overlay', fmt=qcow2 size=197120 backing_file=TEST_DIR/t.qcow2 backing_fmt=file cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/t.qcow2.overlay', fmt=qcow2 size=197120 backing_file=TEST_DIR/t.qcow2 backing_fmt=file cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib + {"return": {}} + {'execute': 'blockdev-add', 'arguments': { 'node-name': 'node1', 'driver': 'file', 'filename': 'TEST_DIR/t.IMGFMT', 'locking': 'on' } } + {"return": {}} +diff --git a/tests/qemu-iotests/185.out b/tests/qemu-iotests/185.out +index 9a3b65782b..ac5ab16bc8 100644 +--- a/tests/qemu-iotests/185.out ++++ b/tests/qemu-iotests/185.out +@@ -9,14 +9,14 @@ Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=67108864 + === Creating backing chain === + + { 'execute': 'blockdev-snapshot-sync', 'arguments': { 'device': 'disk', 'snapshot-file': 'TEST_DIR/t.IMGFMT.mid', 'format': 'IMGFMT', 'mode': 'absolute-paths' } } +-Formatting 'TEST_DIR/t.qcow2.mid', fmt=qcow2 size=67108864 backing_file=TEST_DIR/t.qcow2.base backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/t.qcow2.mid', fmt=qcow2 size=67108864 backing_file=TEST_DIR/t.qcow2.base backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib + {"return": {}} + { 'execute': 'human-monitor-command', 'arguments': { 'command-line': 'qemu-io disk "write 0 4M"' } } + wrote 4194304/4194304 bytes at offset 0 + 4 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + {"return": ""} + { 'execute': 'blockdev-snapshot-sync', 'arguments': { 'device': 'disk', 'snapshot-file': 'TEST_DIR/t.IMGFMT', 'format': 'IMGFMT', 'mode': 'absolute-paths' } } +-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 backing_file=TEST_DIR/t.qcow2.mid backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 backing_file=TEST_DIR/t.qcow2.mid backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib + {"return": {}} + + === Start commit job and exit qemu === +@@ -48,7 +48,7 @@ Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 backing_file=TEST_DIR/t.q + { 'execute': 'qmp_capabilities' } + {"return": {}} + { 'execute': 'drive-mirror', 'arguments': { 'device': 'disk', 'target': 'TEST_DIR/t.IMGFMT.copy', 'format': 'IMGFMT', 'sync': 'full', 'speed': 65536 } } +-Formatting 'TEST_DIR/t.qcow2.copy', fmt=qcow2 size=67108864 cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/t.qcow2.copy', fmt=qcow2 size=67108864 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib + {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "disk"}} + {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "disk"}} + {"return": {}} +@@ -62,7 +62,7 @@ Formatting 'TEST_DIR/t.qcow2.copy', fmt=qcow2 size=67108864 cluster_size=65536 l + { 'execute': 'qmp_capabilities' } + {"return": {}} + { 'execute': 'drive-backup', 'arguments': { 'device': 'disk', 'target': 'TEST_DIR/t.IMGFMT.copy', 'format': 'IMGFMT', 'sync': 'full', 'speed': 65536 } } +-Formatting 'TEST_DIR/t.qcow2.copy', fmt=qcow2 size=67108864 cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/t.qcow2.copy', fmt=qcow2 size=67108864 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib + {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "disk"}} + {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "disk"}} + {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "paused", "id": "disk"}} +diff --git a/tests/qemu-iotests/198.out b/tests/qemu-iotests/198.out +index 831ce3a289..6280ae6eed 100644 +--- a/tests/qemu-iotests/198.out ++++ b/tests/qemu-iotests/198.out +@@ -36,6 +36,7 @@ image: json:{ /* filtered */ } + file format: IMGFMT + virtual size: 16 MiB (16777216 bytes) + Format specific information: ++ compression type: zlib + encrypt: + ivgen alg: plain64 + hash alg: sha256 +@@ -79,6 +80,7 @@ file format: IMGFMT + virtual size: 16 MiB (16777216 bytes) + backing file: TEST_DIR/t.IMGFMT.base + Format specific information: ++ compression type: zlib + encrypt: + ivgen alg: plain64 + hash alg: sha256 +diff --git a/tests/qemu-iotests/206.out b/tests/qemu-iotests/206.out +index 61e7241e0b..1a14255a83 100644 +--- a/tests/qemu-iotests/206.out ++++ b/tests/qemu-iotests/206.out +@@ -18,6 +18,7 @@ virtual size: 128 MiB (134217728 bytes) + cluster_size: 65536 + Format specific information: + compat: 1.1 ++ compression type: zlib + lazy refcounts: false + refcount bits: 16 + corrupt: false +@@ -40,6 +41,7 @@ virtual size: 64 MiB (67108864 bytes) + cluster_size: 65536 + Format specific information: + compat: 1.1 ++ compression type: zlib + lazy refcounts: false + refcount bits: 16 + corrupt: false +@@ -62,6 +64,7 @@ virtual size: 32 MiB (33554432 bytes) + cluster_size: 2097152 + Format specific information: + compat: 1.1 ++ compression type: zlib + lazy refcounts: true + refcount bits: 1 + corrupt: false +@@ -86,6 +89,7 @@ backing file: TEST_IMG.base + backing file format: IMGFMT + Format specific information: + compat: 0.10 ++ compression type: zlib + refcount bits: 16 + + === Successful image creation (encrypted) === +@@ -102,6 +106,7 @@ encrypted: yes + cluster_size: 65536 + Format specific information: + compat: 1.1 ++ compression type: zlib + lazy refcounts: false + refcount bits: 16 + encrypt: +diff --git a/tests/qemu-iotests/242.out b/tests/qemu-iotests/242.out +index 7ac8404d11..091b9126ce 100644 +--- a/tests/qemu-iotests/242.out ++++ b/tests/qemu-iotests/242.out +@@ -12,6 +12,7 @@ virtual size: 1 MiB (1048576 bytes) + cluster_size: 65536 + Format specific information: + compat: 1.1 ++ compression type: zlib + lazy refcounts: false + refcount bits: 16 + corrupt: false +@@ -32,6 +33,7 @@ virtual size: 1 MiB (1048576 bytes) + cluster_size: 65536 + Format specific information: + compat: 1.1 ++ compression type: zlib + lazy refcounts: false + bitmaps: + [0]: +@@ -64,6 +66,7 @@ virtual size: 1 MiB (1048576 bytes) + cluster_size: 65536 + Format specific information: + compat: 1.1 ++ compression type: zlib + lazy refcounts: false + bitmaps: + [0]: +@@ -104,6 +107,7 @@ virtual size: 1 MiB (1048576 bytes) + cluster_size: 65536 + Format specific information: + compat: 1.1 ++ compression type: zlib + lazy refcounts: false + bitmaps: + [0]: +@@ -153,6 +157,7 @@ virtual size: 1 MiB (1048576 bytes) + cluster_size: 65536 + Format specific information: + compat: 1.1 ++ compression type: zlib + lazy refcounts: false + bitmaps: + [0]: +diff --git a/tests/qemu-iotests/255.out b/tests/qemu-iotests/255.out +index 348909fdef..a3c99fd62e 100644 +--- a/tests/qemu-iotests/255.out ++++ b/tests/qemu-iotests/255.out +@@ -3,9 +3,9 @@ Finishing a commit job with background reads + + === Create backing chain and start VM === + +-Formatting 'TEST_DIR/PID-t.qcow2.mid', fmt=qcow2 size=134217728 cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/PID-t.qcow2.mid', fmt=qcow2 size=134217728 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib + +-Formatting 'TEST_DIR/PID-t.qcow2', fmt=qcow2 size=134217728 cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/PID-t.qcow2', fmt=qcow2 size=134217728 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib + + === Start background read requests === + +@@ -23,9 +23,9 @@ Closing the VM while a job is being cancelled + + === Create images and start VM === + +-Formatting 'TEST_DIR/PID-src.qcow2', fmt=qcow2 size=134217728 cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/PID-src.qcow2', fmt=qcow2 size=134217728 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib + +-Formatting 'TEST_DIR/PID-dst.qcow2', fmt=qcow2 size=134217728 cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/PID-dst.qcow2', fmt=qcow2 size=134217728 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib + + wrote 1048576/1048576 bytes at offset 0 + 1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +diff --git a/tests/qemu-iotests/274.out b/tests/qemu-iotests/274.out +index 9d6fdeb1f7..d24ff681af 100644 +--- a/tests/qemu-iotests/274.out ++++ b/tests/qemu-iotests/274.out +@@ -1,9 +1,9 @@ + == Commit tests == +-Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=2097152 cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=2097152 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib + +-Formatting 'TEST_DIR/PID-mid', fmt=qcow2 size=1048576 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/PID-mid', fmt=qcow2 size=1048576 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib + +-Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=2097152 backing_file=TEST_DIR/PID-mid cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=2097152 backing_file=TEST_DIR/PID-mid cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib + + wrote 2097152/2097152 bytes at offset 0 + 2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +@@ -52,6 +52,7 @@ cluster_size: 65536 + backing file: TEST_DIR/PID-base + Format specific information: + compat: 1.1 ++ compression type: zlib + lazy refcounts: false + refcount bits: 16 + corrupt: false +@@ -63,11 +64,11 @@ read 1048576/1048576 bytes at offset 1048576 + 1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + + === Testing HMP commit (top -> mid) === +-Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=2097152 cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=2097152 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib + +-Formatting 'TEST_DIR/PID-mid', fmt=qcow2 size=1048576 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/PID-mid', fmt=qcow2 size=1048576 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib + +-Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=2097152 backing_file=TEST_DIR/PID-mid cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=2097152 backing_file=TEST_DIR/PID-mid cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib + + wrote 2097152/2097152 bytes at offset 0 + 2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +@@ -81,6 +82,7 @@ cluster_size: 65536 + backing file: TEST_DIR/PID-base + Format specific information: + compat: 1.1 ++ compression type: zlib + lazy refcounts: false + refcount bits: 16 + corrupt: false +@@ -92,11 +94,11 @@ read 1048576/1048576 bytes at offset 1048576 + 1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + + === Testing QMP active commit (top -> mid) === +-Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=2097152 cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=2097152 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib + +-Formatting 'TEST_DIR/PID-mid', fmt=qcow2 size=1048576 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/PID-mid', fmt=qcow2 size=1048576 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib + +-Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=2097152 backing_file=TEST_DIR/PID-mid cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=2097152 backing_file=TEST_DIR/PID-mid cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib + + wrote 2097152/2097152 bytes at offset 0 + 2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +@@ -116,6 +118,7 @@ cluster_size: 65536 + backing file: TEST_DIR/PID-base + Format specific information: + compat: 1.1 ++ compression type: zlib + lazy refcounts: false + refcount bits: 16 + corrupt: false +@@ -128,9 +131,9 @@ read 1048576/1048576 bytes at offset 1048576 + + == Resize tests == + === preallocation=off === +-Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=6442450944 cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=6442450944 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib + +-Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=1073741824 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=1073741824 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib + + wrote 65536/65536 bytes at offset 5368709120 + 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +@@ -147,9 +150,9 @@ read 65536/65536 bytes at offset 5368709120 + { "start": 1073741824, "length": 7516192768, "depth": 0, "zero": true, "data": false}] + + === preallocation=metadata === +-Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=34359738368 cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=34359738368 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib + +-Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=32212254720 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=32212254720 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib + + wrote 65536/65536 bytes at offset 33285996544 + 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +@@ -171,9 +174,9 @@ read 65536/65536 bytes at offset 33285996544 + { "start": 34896609280, "length": 536870912, "depth": 0, "zero": true, "data": false, "offset": 2685075456}] + + === preallocation=falloc === +-Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=10485760 cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=10485760 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib + +-Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=5242880 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=5242880 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib + + wrote 65536/65536 bytes at offset 9437184 + 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +@@ -190,9 +193,9 @@ read 65536/65536 bytes at offset 9437184 + { "start": 5242880, "length": 10485760, "depth": 0, "zero": false, "data": true, "offset": 327680}] + + === preallocation=full === +-Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=16777216 cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=16777216 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib + +-Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=8388608 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=8388608 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib + + wrote 65536/65536 bytes at offset 11534336 + 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +@@ -209,9 +212,9 @@ read 65536/65536 bytes at offset 11534336 + { "start": 8388608, "length": 4194304, "depth": 0, "zero": false, "data": true, "offset": 327680}] + + === preallocation=off === +-Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=393216 cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=393216 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib + +-Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=259072 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=259072 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib + + wrote 65536/65536 bytes at offset 259072 + 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +@@ -229,9 +232,9 @@ read 65536/65536 bytes at offset 259072 + { "start": 262144, "length": 262144, "depth": 0, "zero": true, "data": false}] + + === preallocation=off === +-Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=409600 cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=409600 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib + +-Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=262144 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=262144 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib + + wrote 65536/65536 bytes at offset 344064 + 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +@@ -248,9 +251,9 @@ read 65536/65536 bytes at offset 344064 + { "start": 262144, "length": 262144, "depth": 0, "zero": true, "data": false}] + + === preallocation=off === +-Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=524288 cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=524288 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib + +-Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=262144 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=262144 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib + + wrote 65536/65536 bytes at offset 446464 + 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +diff --git a/tests/qemu-iotests/280.out b/tests/qemu-iotests/280.out +index 5d382faaa8..92e4d14079 100644 +--- a/tests/qemu-iotests/280.out ++++ b/tests/qemu-iotests/280.out +@@ -1,4 +1,4 @@ +-Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=67108864 cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=67108864 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib + + === Launch VM === + Enabling migration QMP events on VM... +diff --git a/tests/qemu-iotests/common.filter b/tests/qemu-iotests/common.filter +index 3f8ee3e5f7..279e0bbb0d 100644 +--- a/tests/qemu-iotests/common.filter ++++ b/tests/qemu-iotests/common.filter +@@ -152,7 +152,8 @@ _filter_img_create() + -e "s# refcount_bits=[0-9]\\+##g" \ + -e "s# key-secret=[a-zA-Z0-9]\\+##g" \ + -e "s# iter-time=[0-9]\\+##g" \ +- -e "s# force_size=\\(on\\|off\\)##g" ++ -e "s# force_size=\\(on\\|off\\)##g" \ ++ -e "s# compression_type=[a-zA-Z0-9]\\+##g" + } + + _filter_img_info() +-- +2.23.0 + diff --git a/qcow2-rework-the-cluster-compression-routine.patch b/qcow2-rework-the-cluster-compression-routine.patch new file mode 100644 index 0000000000000000000000000000000000000000..0ad137cf6303b72d61e710d95c3a126b19bc91f3 --- /dev/null +++ b/qcow2-rework-the-cluster-compression-routine.patch @@ -0,0 +1,144 @@ +From 25dd077d1d0aaef23f8608468cbef9a396583b1b Mon Sep 17 00:00:00 2001 +From: Denis Plotnikov +Date: Thu, 7 May 2020 11:25:19 +0300 +Subject: [PATCH 394/709] qcow2: rework the cluster compression routine + +The patch enables processing the image compression type defined +for the image and chooses an appropriate method for image clusters +(de)compression. + +Signed-off-by: Denis Plotnikov +Reviewed-by: Vladimir Sementsov-Ogievskiy +Reviewed-by: Alberto Garcia +Reviewed-by: Max Reitz +Message-Id: <20200507082521.29210-3-dplotnikov@virtuozzo.com> +Signed-off-by: Max Reitz +--- + block/qcow2-threads.c | 71 ++++++++++++++++++++++++++++++++++++------- + 1 file changed, 60 insertions(+), 11 deletions(-) + +diff --git a/block/qcow2-threads.c b/block/qcow2-threads.c +index a68126f291..7dbaf53489 100644 +--- a/block/qcow2-threads.c ++++ b/block/qcow2-threads.c +@@ -74,7 +74,9 @@ typedef struct Qcow2CompressData { + } Qcow2CompressData; + + /* +- * qcow2_compress() ++ * qcow2_zlib_compress() ++ * ++ * Compress @src_size bytes of data using zlib compression method + * + * @dest - destination buffer, @dest_size bytes + * @src - source buffer, @src_size bytes +@@ -83,8 +85,8 @@ typedef struct Qcow2CompressData { + * -ENOMEM destination buffer is not enough to store compressed data + * -EIO on any other error + */ +-static ssize_t qcow2_compress(void *dest, size_t dest_size, +- const void *src, size_t src_size) ++static ssize_t qcow2_zlib_compress(void *dest, size_t dest_size, ++ const void *src, size_t src_size) + { + ssize_t ret; + z_stream strm; +@@ -119,10 +121,10 @@ static ssize_t qcow2_compress(void *dest, size_t dest_size, + } + + /* +- * qcow2_decompress() ++ * qcow2_zlib_decompress() + * + * Decompress some data (not more than @src_size bytes) to produce exactly +- * @dest_size bytes. ++ * @dest_size bytes using zlib compression method + * + * @dest - destination buffer, @dest_size bytes + * @src - source buffer, @src_size bytes +@@ -130,8 +132,8 @@ static ssize_t qcow2_compress(void *dest, size_t dest_size, + * Returns: 0 on success + * -EIO on fail + */ +-static ssize_t qcow2_decompress(void *dest, size_t dest_size, +- const void *src, size_t src_size) ++static ssize_t qcow2_zlib_decompress(void *dest, size_t dest_size, ++ const void *src, size_t src_size) + { + int ret; + z_stream strm; +@@ -191,20 +193,67 @@ qcow2_co_do_compress(BlockDriverState *bs, void *dest, size_t dest_size, + return arg.ret; + } + ++/* ++ * qcow2_co_compress() ++ * ++ * Compress @src_size bytes of data using the compression ++ * method defined by the image compression type ++ * ++ * @dest - destination buffer, @dest_size bytes ++ * @src - source buffer, @src_size bytes ++ * ++ * Returns: compressed size on success ++ * a negative error code on failure ++ */ + ssize_t coroutine_fn + qcow2_co_compress(BlockDriverState *bs, void *dest, size_t dest_size, + const void *src, size_t src_size) + { +- return qcow2_co_do_compress(bs, dest, dest_size, src, src_size, +- qcow2_compress); ++ BDRVQcow2State *s = bs->opaque; ++ Qcow2CompressFunc fn; ++ ++ switch (s->compression_type) { ++ case QCOW2_COMPRESSION_TYPE_ZLIB: ++ fn = qcow2_zlib_compress; ++ break; ++ ++ default: ++ abort(); ++ } ++ ++ return qcow2_co_do_compress(bs, dest, dest_size, src, src_size, fn); + } + ++/* ++ * qcow2_co_decompress() ++ * ++ * Decompress some data (not more than @src_size bytes) to produce exactly ++ * @dest_size bytes using the compression method defined by the image ++ * compression type ++ * ++ * @dest - destination buffer, @dest_size bytes ++ * @src - source buffer, @src_size bytes ++ * ++ * Returns: 0 on success ++ * a negative error code on failure ++ */ + ssize_t coroutine_fn + qcow2_co_decompress(BlockDriverState *bs, void *dest, size_t dest_size, + const void *src, size_t src_size) + { +- return qcow2_co_do_compress(bs, dest, dest_size, src, src_size, +- qcow2_decompress); ++ BDRVQcow2State *s = bs->opaque; ++ Qcow2CompressFunc fn; ++ ++ switch (s->compression_type) { ++ case QCOW2_COMPRESSION_TYPE_ZLIB: ++ fn = qcow2_zlib_decompress; ++ break; ++ ++ default: ++ abort(); ++ } ++ ++ return qcow2_co_do_compress(bs, dest, dest_size, src, src_size, fn); + } + + +-- +2.23.0 + diff --git a/qdev-Clean-up-qdev_connect_gpio_out_named.patch b/qdev-Clean-up-qdev_connect_gpio_out_named.patch new file mode 100644 index 0000000000000000000000000000000000000000..bbccd7e5e9fb2226f0dbdd5d763a9038fe69e42b --- /dev/null +++ b/qdev-Clean-up-qdev_connect_gpio_out_named.patch @@ -0,0 +1,59 @@ +From 9f742c28f52d55ff83dc441a0cea365239a4906d Mon Sep 17 00:00:00 2001 +From: Markus Armbruster +Date: Tue, 5 May 2020 17:29:21 +0200 +Subject: [PATCH 475/709] qdev: Clean up qdev_connect_gpio_out_named() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Both qdev_connect_gpio_out_named() and device_set_realized() put +objects without a parent into the "/machine/unattached/" orphanage. + +qdev_connect_gpio_out_named() needs a lengthy comment to explain how +it works. It exploits that object_property_add_child() can fail only +when we got a parent already, and ignoring that error does what we +want. True. If it failed due to "duplicate property", we'd be in +trouble, but that would be a programming error. + +device_set_realized() is cleaner: it checks whether we need a parent, +then calls object_property_add_child(), aborting on failure. No need +for a comment, and programming errors get caught. + +Change qdev_connect_gpio_out_named() to match. + +Cc: Peter Crosthwaite +Signed-off-by: Markus Armbruster +Reviewed-by: Paolo Bonzini +Reviewed-by: Philippe Mathieu-Daudé +Message-Id: <20200505152926.18877-14-armbru@redhat.com> +--- + hw/core/qdev.c | 11 ++++------- + 1 file changed, 4 insertions(+), 7 deletions(-) + +diff --git a/hw/core/qdev.c b/hw/core/qdev.c +index ea7118ab0e..2e6c29ba78 100644 +--- a/hw/core/qdev.c ++++ b/hw/core/qdev.c +@@ -542,15 +542,12 @@ void qdev_connect_gpio_out_named(DeviceState *dev, const char *name, int n, + { + char *propname = g_strdup_printf("%s[%d]", + name ? name : "unnamed-gpio-out", n); +- if (pin) { +- /* We need a name for object_property_set_link to work. If the +- * object has a parent, object_property_add_child will come back +- * with an error without doing anything. If it has none, it will +- * never fail. So we can just call it with a NULL Error pointer. +- */ ++ if (pin && !OBJECT(pin)->parent) { ++ /* We need a name for object_property_set_link to work */ + object_property_add_child(container_get(qdev_get_machine(), + "/unattached"), +- "non-qdev-gpio[*]", OBJECT(pin), NULL); ++ "non-qdev-gpio[*]", OBJECT(pin), ++ &error_abort); + } + object_property_set_link(OBJECT(dev), OBJECT(pin), propname, &error_abort); + g_free(propname); +-- +2.23.0 + diff --git a/qdev-Unrealize-must-not-fail.patch b/qdev-Unrealize-must-not-fail.patch new file mode 100644 index 0000000000000000000000000000000000000000..c8e706ead18402678b923100877beee87dce6f33 --- /dev/null +++ b/qdev-Unrealize-must-not-fail.patch @@ -0,0 +1,2014 @@ +From b69c3c21a5d11075d42100d5cfe0a736593fae6b Mon Sep 17 00:00:00 2001 +From: Markus Armbruster +Date: Tue, 5 May 2020 17:29:24 +0200 +Subject: [PATCH 478/709] qdev: Unrealize must not fail +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Devices may have component devices and buses. + +Device realization may fail. Realization is recursive: a device's +realize() method realizes its components, and device_set_realized() +realizes its buses (which should in turn realize the devices on that +bus, except bus_set_realized() doesn't implement that, yet). + +When realization of a component or bus fails, we need to roll back: +unrealize everything we realized so far. If any of these unrealizes +failed, the device would be left in an inconsistent state. Must not +happen. + +device_set_realized() lets it happen: it ignores errors in the roll +back code starting at label child_realize_fail. + +Since realization is recursive, unrealization must be recursive, too. +But how could a partly failed unrealize be rolled back? We'd have to +re-realize, which can fail. This design is fundamentally broken. + +device_set_realized() does not roll back at all. Instead, it keeps +unrealizing, ignoring further errors. + +It can screw up even for a device with no buses: if the lone +dc->unrealize() fails, it still unregisters vmstate, and calls +listeners' unrealize() callback. + +bus_set_realized() does not roll back either. Instead, it stops +unrealizing. + +Fortunately, no unrealize method can fail, as we'll see below. + +To fix the design error, drop parameter @errp from all the unrealize +methods. + +Any unrealize method that uses @errp now needs an update. This leads +us to unrealize() methods that can fail. Merely passing it to another +unrealize method cannot cause failure, though. Here are the ones that +do other things with @errp: + +* virtio_serial_device_unrealize() + + Fails when qbus_set_hotplug_handler() fails, but still does all the + other work. On failure, the device would stay realized with its + resources completely gone. Oops. Can't happen, because + qbus_set_hotplug_handler() can't actually fail here. Pass + &error_abort to qbus_set_hotplug_handler() instead. + +* hw/ppc/spapr_drc.c's unrealize() + + Fails when object_property_del() fails, but all the other work is + already done. On failure, the device would stay realized with its + vmstate registration gone. Oops. Can't happen, because + object_property_del() can't actually fail here. Pass &error_abort + to object_property_del() instead. + +* spapr_phb_unrealize() + + Fails and bails out when remove_drcs() fails, but other work is + already done. On failure, the device would stay realized with some + of its resources gone. Oops. remove_drcs() fails only when + chassis_from_bus()'s object_property_get_uint() fails, and it can't + here. Pass &error_abort to remove_drcs() instead. + +Therefore, no unrealize method can fail before this patch. + +device_set_realized()'s recursive unrealization via bus uses +object_property_set_bool(). Can't drop @errp there, so pass +&error_abort. + +We similarly unrealize with object_property_set_bool() elsewhere, +always ignoring errors. Pass &error_abort instead. + +Several unrealize methods no longer handle errors from other unrealize +methods: virtio_9p_device_unrealize(), +virtio_input_device_unrealize(), scsi_qdev_unrealize(), ... +Much of the deleted error handling looks wrong anyway. + +One unrealize methods no longer ignore such errors: +usb_ehci_pci_exit(). + +Several realize methods no longer ignore errors when rolling back: +v9fs_device_realize_common(), pci_qdev_unrealize(), +spapr_phb_realize(), usb_qdev_realize(), vfio_ccw_realize(), +virtio_device_realize(). + +Signed-off-by: Markus Armbruster +Reviewed-by: Philippe Mathieu-Daudé +Reviewed-by: Paolo Bonzini +Message-Id: <20200505152926.18877-17-armbru@redhat.com> +--- + hw/9pfs/9p.c | 4 ++-- + hw/9pfs/9p.h | 2 +- + hw/9pfs/virtio-9p-device.c | 4 ++-- + hw/acpi/pcihp.c | 2 +- + hw/audio/intel-hda.c | 2 +- + hw/block/pflash_cfi02.c | 2 +- + hw/block/vhost-user-blk.c | 2 +- + hw/block/virtio-blk.c | 2 +- + hw/block/xen-block.c | 8 ++++---- + hw/char/serial-pci-multi.c | 2 +- + hw/char/serial-pci.c | 2 +- + hw/char/serial.c | 2 +- + hw/char/virtio-console.c | 2 +- + hw/char/virtio-serial-bus.c | 8 ++++---- + hw/core/bus.c | 17 ++++------------- + hw/core/cpu.c | 2 +- + hw/core/generic-loader.c | 2 +- + hw/core/qdev.c | 17 ++++++----------- + hw/display/virtio-gpu-base.c | 2 +- + hw/dma/rc4030.c | 2 +- + hw/i386/kvm/apic.c | 2 +- + hw/i386/pc.c | 4 ++-- + hw/ide/qdev.c | 4 ++-- + hw/input/virtio-input-hid.c | 2 +- + hw/input/virtio-input-host.c | 2 +- + hw/input/virtio-input.c | 9 ++------- + hw/intc/apic.c | 2 +- + hw/intc/apic_common.c | 4 ++-- + hw/intc/ioapic.c | 2 +- + hw/intc/xics.c | 2 +- + hw/ipack/ipack.c | 6 ++---- + hw/mem/pc-dimm.c | 2 +- + hw/net/virtio-net.c | 2 +- + hw/nvram/mac_nvram.c | 2 +- + hw/pci/pci.c | 14 +++++++------- + hw/pci/pcie.c | 2 +- + hw/pci/shpc.c | 2 +- + hw/ppc/pnv_core.c | 2 +- + hw/ppc/spapr.c | 8 ++++---- + hw/ppc/spapr_cpu_core.c | 2 +- + hw/ppc/spapr_drc.c | 14 ++++---------- + hw/ppc/spapr_iommu.c | 2 +- + hw/ppc/spapr_pci.c | 14 +++++--------- + hw/ppc/spapr_tpm_proxy.c | 2 +- + hw/s390x/css-bridge.c | 2 +- + hw/s390x/s390-ccw.c | 2 +- + hw/s390x/s390-pci-bus.c | 4 ++-- + hw/s390x/virtio-ccw.c | 8 ++++---- + hw/s390x/virtio-ccw.h | 2 +- + hw/scsi/lsi53c895a.c | 2 +- + hw/scsi/scsi-bus.c | 13 ++++--------- + hw/scsi/scsi-disk.c | 2 +- + hw/scsi/vhost-scsi.c | 2 +- + hw/scsi/vhost-user-scsi.c | 2 +- + hw/scsi/virtio-scsi.c | 2 +- + hw/sd/sdhci-internal.h | 2 +- + hw/sd/sdhci-pci.c | 2 +- + hw/sd/sdhci.c | 6 +++--- + hw/usb/bus.c | 12 ++++++------ + hw/usb/ccid-card-emulated.c | 2 +- + hw/usb/ccid.h | 2 +- + hw/usb/dev-audio.c | 2 +- + hw/usb/dev-hid.c | 2 +- + hw/usb/dev-hub.c | 2 +- + hw/usb/dev-network.c | 2 +- + hw/usb/dev-smartcard-reader.c | 11 +++-------- + hw/usb/dev-uas.c | 2 +- + hw/usb/dev-wacom.c | 2 +- + hw/usb/hcd-ehci-pci.c | 2 +- + hw/usb/hcd-ehci.c | 2 +- + hw/usb/hcd-ehci.h | 2 +- + hw/usb/host-libusb.c | 2 +- + hw/usb/redirect.c | 2 +- + hw/vfio/ap.c | 2 +- + hw/vfio/ccw.c | 6 +++--- + hw/virtio/vhost-user-fs.c | 2 +- + hw/virtio/vhost-vsock.c | 2 +- + hw/virtio/virtio-balloon.c | 2 +- + hw/virtio/virtio-crypto.c | 2 +- + hw/virtio/virtio-iommu.c | 2 +- + hw/virtio/virtio-pmem.c | 2 +- + hw/virtio/virtio-rng.c | 2 +- + hw/virtio/virtio.c | 11 +++-------- + hw/watchdog/wdt_diag288.c | 2 +- + hw/xen/xen-bus.c | 12 ++++++------ + include/hw/qdev-core.h | 4 ++-- + include/hw/s390x/s390-ccw.h | 2 +- + include/hw/scsi/scsi.h | 2 +- + include/hw/usb.h | 2 +- + include/hw/xen/xen-block.h | 2 +- + include/hw/xen/xen-bus.h | 2 +- + target/i386/cpu.c | 9 ++------- + target/ppc/translate_init.inc.c | 9 ++------- + 93 files changed, 158 insertions(+), 214 deletions(-) + +diff --git a/hw/9pfs/9p.c b/hw/9pfs/9p.c +index 9e046f7acb..a2a14b5979 100644 +--- a/hw/9pfs/9p.c ++++ b/hw/9pfs/9p.c +@@ -4124,13 +4124,13 @@ int v9fs_device_realize_common(V9fsState *s, const V9fsTransport *t, + rc = 0; + out: + if (rc) { +- v9fs_device_unrealize_common(s, NULL); ++ v9fs_device_unrealize_common(s); + } + v9fs_path_free(&path); + return rc; + } + +-void v9fs_device_unrealize_common(V9fsState *s, Error **errp) ++void v9fs_device_unrealize_common(V9fsState *s) + { + if (s->ops && s->ops->cleanup) { + s->ops->cleanup(&s->ctx); +diff --git a/hw/9pfs/9p.h b/hw/9pfs/9p.h +index b8f72a3bd9..dd1c6cb8d2 100644 +--- a/hw/9pfs/9p.h ++++ b/hw/9pfs/9p.h +@@ -423,7 +423,7 @@ int v9fs_name_to_path(V9fsState *s, V9fsPath *dirpath, + const char *name, V9fsPath *path); + int v9fs_device_realize_common(V9fsState *s, const V9fsTransport *t, + Error **errp); +-void v9fs_device_unrealize_common(V9fsState *s, Error **errp); ++void v9fs_device_unrealize_common(V9fsState *s); + + V9fsPDU *pdu_alloc(V9fsState *s); + void pdu_free(V9fsPDU *pdu); +diff --git a/hw/9pfs/virtio-9p-device.c b/hw/9pfs/virtio-9p-device.c +index 536447a355..e5b44977c7 100644 +--- a/hw/9pfs/virtio-9p-device.c ++++ b/hw/9pfs/virtio-9p-device.c +@@ -212,7 +212,7 @@ static void virtio_9p_device_realize(DeviceState *dev, Error **errp) + v->vq = virtio_add_queue(vdev, MAX_REQ, handle_9p_output); + } + +-static void virtio_9p_device_unrealize(DeviceState *dev, Error **errp) ++static void virtio_9p_device_unrealize(DeviceState *dev) + { + VirtIODevice *vdev = VIRTIO_DEVICE(dev); + V9fsVirtioState *v = VIRTIO_9P(dev); +@@ -220,7 +220,7 @@ static void virtio_9p_device_unrealize(DeviceState *dev, Error **errp) + + virtio_delete_queue(v->vq); + virtio_cleanup(vdev); +- v9fs_device_unrealize_common(s, errp); ++ v9fs_device_unrealize_common(s); + } + + /* virtio-9p device */ +diff --git a/hw/acpi/pcihp.c b/hw/acpi/pcihp.c +index fbc86af102..d42906ea19 100644 +--- a/hw/acpi/pcihp.c ++++ b/hw/acpi/pcihp.c +@@ -266,7 +266,7 @@ void acpi_pcihp_device_unplug_cb(HotplugHandler *hotplug_dev, AcpiPciHpState *s, + { + trace_acpi_pci_unplug(PCI_SLOT(PCI_DEVICE(dev)->devfn), + acpi_pcihp_get_bsel(pci_get_bus(PCI_DEVICE(dev)))); +- object_property_set_bool(OBJECT(dev), false, "realized", NULL); ++ object_property_set_bool(OBJECT(dev), false, "realized", &error_abort); + } + + void acpi_pcihp_device_unplug_request_cb(HotplugHandler *hotplug_dev, +diff --git a/hw/audio/intel-hda.c b/hw/audio/intel-hda.c +index e8d18b7c58..4696ae0d9a 100644 +--- a/hw/audio/intel-hda.c ++++ b/hw/audio/intel-hda.c +@@ -74,7 +74,7 @@ static void hda_codec_dev_realize(DeviceState *qdev, Error **errp) + } + } + +-static void hda_codec_dev_unrealize(DeviceState *qdev, Error **errp) ++static void hda_codec_dev_unrealize(DeviceState *qdev) + { + HDACodecDevice *dev = HDA_CODEC_DEVICE(qdev); + HDACodecDeviceClass *cdc = HDA_CODEC_DEVICE_GET_CLASS(dev); +diff --git a/hw/block/pflash_cfi02.c b/hw/block/pflash_cfi02.c +index 12f18d401a..f0579ecb17 100644 +--- a/hw/block/pflash_cfi02.c ++++ b/hw/block/pflash_cfi02.c +@@ -949,7 +949,7 @@ static Property pflash_cfi02_properties[] = { + DEFINE_PROP_END_OF_LIST(), + }; + +-static void pflash_cfi02_unrealize(DeviceState *dev, Error **errp) ++static void pflash_cfi02_unrealize(DeviceState *dev) + { + PFlashCFI02 *pfl = PFLASH_CFI02(dev); + timer_del(&pfl->timer); +diff --git a/hw/block/vhost-user-blk.c b/hw/block/vhost-user-blk.c +index 5263e0c9ad..9d8c0b3909 100644 +--- a/hw/block/vhost-user-blk.c ++++ b/hw/block/vhost-user-blk.c +@@ -452,7 +452,7 @@ virtio_err: + vhost_user_cleanup(&s->vhost_user); + } + +-static void vhost_user_blk_device_unrealize(DeviceState *dev, Error **errp) ++static void vhost_user_blk_device_unrealize(DeviceState *dev) + { + VirtIODevice *vdev = VIRTIO_DEVICE(dev); + VHostUserBlk *s = VHOST_USER_BLK(dev); +diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c +index fb32717a12..f5f6fc925e 100644 +--- a/hw/block/virtio-blk.c ++++ b/hw/block/virtio-blk.c +@@ -1223,7 +1223,7 @@ static void virtio_blk_device_realize(DeviceState *dev, Error **errp) + conf->conf.lsecs); + } + +-static void virtio_blk_device_unrealize(DeviceState *dev, Error **errp) ++static void virtio_blk_device_unrealize(DeviceState *dev) + { + VirtIODevice *vdev = VIRTIO_DEVICE(dev); + VirtIOBlock *s = VIRTIO_BLK(dev); +diff --git a/hw/block/xen-block.c b/hw/block/xen-block.c +index 99cb4c67cb..570489d6d9 100644 +--- a/hw/block/xen-block.c ++++ b/hw/block/xen-block.c +@@ -136,7 +136,7 @@ static void xen_block_connect(XenDevice *xendev, Error **errp) + g_free(ring_ref); + } + +-static void xen_block_unrealize(XenDevice *xendev, Error **errp) ++static void xen_block_unrealize(XenDevice *xendev) + { + XenBlockDevice *blockdev = XEN_BLOCK_DEVICE(xendev); + XenBlockDeviceClass *blockdev_class = +@@ -157,7 +157,7 @@ static void xen_block_unrealize(XenDevice *xendev, Error **errp) + blockdev->dataplane = NULL; + + if (blockdev_class->unrealize) { +- blockdev_class->unrealize(blockdev, errp); ++ blockdev_class->unrealize(blockdev); + } + } + +@@ -567,7 +567,7 @@ static const TypeInfo xen_block_type_info = { + .class_init = xen_block_class_init, + }; + +-static void xen_disk_unrealize(XenBlockDevice *blockdev, Error **errp) ++static void xen_disk_unrealize(XenBlockDevice *blockdev) + { + trace_xen_disk_unrealize(); + } +@@ -606,7 +606,7 @@ static const TypeInfo xen_disk_type_info = { + .class_init = xen_disk_class_init, + }; + +-static void xen_cdrom_unrealize(XenBlockDevice *blockdev, Error **errp) ++static void xen_cdrom_unrealize(XenBlockDevice *blockdev) + { + trace_xen_cdrom_unrealize(); + } +diff --git a/hw/char/serial-pci-multi.c b/hw/char/serial-pci-multi.c +index 1742cb77ec..5f9ccfcc93 100644 +--- a/hw/char/serial-pci-multi.c ++++ b/hw/char/serial-pci-multi.c +@@ -56,7 +56,7 @@ static void multi_serial_pci_exit(PCIDevice *dev) + + for (i = 0; i < pci->ports; i++) { + s = pci->state + i; +- object_property_set_bool(OBJECT(s), false, "realized", NULL); ++ object_property_set_bool(OBJECT(s), false, "realized", &error_abort); + memory_region_del_subregion(&pci->iobar, &s->io); + g_free(pci->name[i]); + } +diff --git a/hw/char/serial-pci.c b/hw/char/serial-pci.c +index 743552c56b..37818db156 100644 +--- a/hw/char/serial-pci.c ++++ b/hw/char/serial-pci.c +@@ -68,7 +68,7 @@ static void serial_pci_exit(PCIDevice *dev) + PCISerialState *pci = DO_UPCAST(PCISerialState, dev, dev); + SerialState *s = &pci->state; + +- object_property_set_bool(OBJECT(s), false, "realized", NULL); ++ object_property_set_bool(OBJECT(s), false, "realized", &error_abort); + qemu_free_irq(s->irq); + } + +diff --git a/hw/char/serial.c b/hw/char/serial.c +index c822a9ae6c..7d74694587 100644 +--- a/hw/char/serial.c ++++ b/hw/char/serial.c +@@ -950,7 +950,7 @@ static void serial_realize(DeviceState *dev, Error **errp) + serial_reset(s); + } + +-static void serial_unrealize(DeviceState *dev, Error **errp) ++static void serial_unrealize(DeviceState *dev) + { + SerialState *s = SERIAL(dev); + +diff --git a/hw/char/virtio-console.c b/hw/char/virtio-console.c +index b010c21de4..4f46753ea3 100644 +--- a/hw/char/virtio-console.c ++++ b/hw/char/virtio-console.c +@@ -249,7 +249,7 @@ static void virtconsole_realize(DeviceState *dev, Error **errp) + } + } + +-static void virtconsole_unrealize(DeviceState *dev, Error **errp) ++static void virtconsole_unrealize(DeviceState *dev) + { + VirtConsole *vcon = VIRTIO_CONSOLE(dev); + +diff --git a/hw/char/virtio-serial-bus.c b/hw/char/virtio-serial-bus.c +index 99a65bab7f..262089c0c9 100644 +--- a/hw/char/virtio-serial-bus.c ++++ b/hw/char/virtio-serial-bus.c +@@ -1010,7 +1010,7 @@ static void virtser_port_device_plug(HotplugHandler *hotplug_dev, + virtio_notify_config(VIRTIO_DEVICE(hotplug_dev)); + } + +-static void virtser_port_device_unrealize(DeviceState *dev, Error **errp) ++static void virtser_port_device_unrealize(DeviceState *dev) + { + VirtIOSerialPort *port = VIRTIO_SERIAL_PORT(dev); + VirtIOSerialPortClass *vsc = VIRTIO_SERIAL_PORT_GET_CLASS(dev); +@@ -1022,7 +1022,7 @@ static void virtser_port_device_unrealize(DeviceState *dev, Error **errp) + QTAILQ_REMOVE(&vser->ports, port, next); + + if (vsc->unrealize) { +- vsc->unrealize(dev, errp); ++ vsc->unrealize(dev); + } + } + +@@ -1122,7 +1122,7 @@ static const TypeInfo virtio_serial_port_type_info = { + .class_init = virtio_serial_port_class_init, + }; + +-static void virtio_serial_device_unrealize(DeviceState *dev, Error **errp) ++static void virtio_serial_device_unrealize(DeviceState *dev) + { + VirtIODevice *vdev = VIRTIO_DEVICE(dev); + VirtIOSerial *vser = VIRTIO_SERIAL(dev); +@@ -1147,7 +1147,7 @@ static void virtio_serial_device_unrealize(DeviceState *dev, Error **errp) + g_free(vser->post_load); + } + +- qbus_set_hotplug_handler(BUS(&vser->bus), NULL, errp); ++ qbus_set_hotplug_handler(BUS(&vser->bus), NULL, &error_abort); + + virtio_cleanup(vdev); + } +diff --git a/hw/core/bus.c b/hw/core/bus.c +index 4a57ae107e..a9e4118d3c 100644 +--- a/hw/core/bus.c ++++ b/hw/core/bus.c +@@ -176,11 +176,10 @@ static void bus_set_realized(Object *obj, bool value, Error **errp) + BusState *bus = BUS(obj); + BusClass *bc = BUS_GET_CLASS(bus); + BusChild *kid; +- Error *local_err = NULL; + + if (value && !bus->realized) { + if (bc->realize) { +- bc->realize(bus, &local_err); ++ bc->realize(bus, errp); + } + + /* TODO: recursive realization */ +@@ -188,21 +187,13 @@ static void bus_set_realized(Object *obj, bool value, Error **errp) + QTAILQ_FOREACH(kid, &bus->children, sibling) { + DeviceState *dev = kid->child; + object_property_set_bool(OBJECT(dev), false, "realized", +- &local_err); +- if (local_err != NULL) { +- break; +- } ++ &error_abort); + } +- if (bc->unrealize && local_err == NULL) { +- bc->unrealize(bus, &local_err); ++ if (bc->unrealize) { ++ bc->unrealize(bus); + } + } + +- if (local_err != NULL) { +- error_propagate(errp, local_err); +- return; +- } +- + bus->realized = value; + } + +diff --git a/hw/core/cpu.c b/hw/core/cpu.c +index 786a1bec8a..5284d384fb 100644 +--- a/hw/core/cpu.c ++++ b/hw/core/cpu.c +@@ -345,7 +345,7 @@ static void cpu_common_realizefn(DeviceState *dev, Error **errp) + trace_init_vcpu(cpu); + } + +-static void cpu_common_unrealizefn(DeviceState *dev, Error **errp) ++static void cpu_common_unrealizefn(DeviceState *dev) + { + CPUState *cpu = CPU(dev); + /* NOTE: latest generic point before the cpu is fully unrealized */ +diff --git a/hw/core/generic-loader.c b/hw/core/generic-loader.c +index b9aaa52706..a242c076f6 100644 +--- a/hw/core/generic-loader.c ++++ b/hw/core/generic-loader.c +@@ -173,7 +173,7 @@ static void generic_loader_realize(DeviceState *dev, Error **errp) + } + } + +-static void generic_loader_unrealize(DeviceState *dev, Error **errp) ++static void generic_loader_unrealize(DeviceState *dev) + { + qemu_unregister_reset(generic_loader_reset, dev); + } +diff --git a/hw/core/qdev.c b/hw/core/qdev.c +index 2afa2562b8..b9c7a2f904 100644 +--- a/hw/core/qdev.c ++++ b/hw/core/qdev.c +@@ -392,7 +392,7 @@ static void device_reset_child_foreach(Object *obj, ResettableChildCallback cb, + void qdev_simple_device_unplug_cb(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp) + { +- object_property_set_bool(OBJECT(dev), false, "realized", NULL); ++ object_property_set_bool(OBJECT(dev), false, "realized", &error_abort); + } + + /* +@@ -945,23 +945,18 @@ static void device_set_realized(Object *obj, bool value, Error **errp) + } + + } else if (!value && dev->realized) { +- /* We want local_err to track only the first error */ + QLIST_FOREACH(bus, &dev->child_bus, sibling) { + object_property_set_bool(OBJECT(bus), false, "realized", +- local_err ? NULL : &local_err); ++ &error_abort); + } + if (qdev_get_vmsd(dev)) { + vmstate_unregister(VMSTATE_IF(dev), qdev_get_vmsd(dev), dev); + } + if (dc->unrealize) { +- dc->unrealize(dev, local_err ? NULL : &local_err); ++ dc->unrealize(dev); + } + dev->pending_deleted_event = true; + DEVICE_LISTENER_CALL(unrealize, Reverse, dev); +- +- if (local_err != NULL) { +- goto fail; +- } + } + + assert(local_err == NULL); +@@ -971,7 +966,7 @@ static void device_set_realized(Object *obj, bool value, Error **errp) + child_realize_fail: + QLIST_FOREACH(bus, &dev->child_bus, sibling) { + object_property_set_bool(OBJECT(bus), false, "realized", +- NULL); ++ &error_abort); + } + + if (qdev_get_vmsd(dev)) { +@@ -982,7 +977,7 @@ post_realize_fail: + g_free(dev->canonical_path); + dev->canonical_path = NULL; + if (dc->unrealize) { +- dc->unrealize(dev, NULL); ++ dc->unrealize(dev); + } + + fail: +@@ -1083,7 +1078,7 @@ static void device_unparent(Object *obj) + BusState *bus; + + if (dev->realized) { +- object_property_set_bool(obj, false, "realized", NULL); ++ object_property_set_bool(obj, false, "realized", &error_abort); + } + while (dev->num_child_bus) { + bus = QLIST_FIRST(&dev->child_bus); +diff --git a/hw/display/virtio-gpu-base.c b/hw/display/virtio-gpu-base.c +index 55e07995fe..c159351be3 100644 +--- a/hw/display/virtio-gpu-base.c ++++ b/hw/display/virtio-gpu-base.c +@@ -203,7 +203,7 @@ virtio_gpu_base_set_features(VirtIODevice *vdev, uint64_t features) + } + + static void +-virtio_gpu_base_device_unrealize(DeviceState *qdev, Error **errp) ++virtio_gpu_base_device_unrealize(DeviceState *qdev) + { + VirtIOGPUBase *g = VIRTIO_GPU_BASE(qdev); + +diff --git a/hw/dma/rc4030.c b/hw/dma/rc4030.c +index 7434d274aa..eefbabd758 100644 +--- a/hw/dma/rc4030.c ++++ b/hw/dma/rc4030.c +@@ -690,7 +690,7 @@ static void rc4030_realize(DeviceState *dev, Error **errp) + address_space_init(&s->dma_as, MEMORY_REGION(&s->dma_mr), "rc4030-dma"); + } + +-static void rc4030_unrealize(DeviceState *dev, Error **errp) ++static void rc4030_unrealize(DeviceState *dev) + { + rc4030State *s = RC4030(dev); + +diff --git a/hw/i386/kvm/apic.c b/hw/i386/kvm/apic.c +index 91fb622d63..4eb2d77b87 100644 +--- a/hw/i386/kvm/apic.c ++++ b/hw/i386/kvm/apic.c +@@ -230,7 +230,7 @@ static void kvm_apic_realize(DeviceState *dev, Error **errp) + } + } + +-static void kvm_apic_unrealize(DeviceState *dev, Error **errp) ++static void kvm_apic_unrealize(DeviceState *dev) + { + } + +diff --git a/hw/i386/pc.c b/hw/i386/pc.c +index 33cf14363a..2128f3d6fe 100644 +--- a/hw/i386/pc.c ++++ b/hw/i386/pc.c +@@ -1385,7 +1385,7 @@ static void pc_memory_unplug(HotplugHandler *hotplug_dev, + } + + pc_dimm_unplug(PC_DIMM(dev), MACHINE(pcms)); +- object_property_set_bool(OBJECT(dev), false, "realized", NULL); ++ object_property_set_bool(OBJECT(dev), false, "realized", &error_abort); + out: + error_propagate(errp, local_err); + } +@@ -1493,7 +1493,7 @@ static void pc_cpu_unplug_cb(HotplugHandler *hotplug_dev, + + found_cpu = pc_find_cpu_slot(MACHINE(pcms), cpu->apic_id, NULL); + found_cpu->cpu = NULL; +- object_property_set_bool(OBJECT(dev), false, "realized", NULL); ++ object_property_set_bool(OBJECT(dev), false, "realized", &error_abort); + + /* decrement the number of CPUs */ + x86ms->boot_cpus--; +diff --git a/hw/ide/qdev.c b/hw/ide/qdev.c +index 4909b14b91..06b11583f5 100644 +--- a/hw/ide/qdev.c ++++ b/hw/ide/qdev.c +@@ -36,7 +36,7 @@ + /* --------------------------------- */ + + static char *idebus_get_fw_dev_path(DeviceState *dev); +-static void idebus_unrealize(BusState *qdev, Error **errp); ++static void idebus_unrealize(BusState *qdev); + + static Property ide_props[] = { + DEFINE_PROP_UINT32("unit", IDEDevice, unit, -1), +@@ -51,7 +51,7 @@ static void ide_bus_class_init(ObjectClass *klass, void *data) + k->unrealize = idebus_unrealize; + } + +-static void idebus_unrealize(BusState *bus, Error **errp) ++static void idebus_unrealize(BusState *bus) + { + IDEBus *ibus = IDE_BUS(bus); + +diff --git a/hw/input/virtio-input-hid.c b/hw/input/virtio-input-hid.c +index e8ae6c148a..09cf260985 100644 +--- a/hw/input/virtio-input-hid.c ++++ b/hw/input/virtio-input-hid.c +@@ -165,7 +165,7 @@ static void virtio_input_hid_realize(DeviceState *dev, Error **errp) + } + } + +-static void virtio_input_hid_unrealize(DeviceState *dev, Error **errp) ++static void virtio_input_hid_unrealize(DeviceState *dev) + { + VirtIOInputHID *vhid = VIRTIO_INPUT_HID(dev); + qemu_input_handler_unregister(vhid->hs); +diff --git a/hw/input/virtio-input-host.c b/hw/input/virtio-input-host.c +index f2ab6df676..85daf73f1a 100644 +--- a/hw/input/virtio-input-host.c ++++ b/hw/input/virtio-input-host.c +@@ -178,7 +178,7 @@ err_close: + return; + } + +-static void virtio_input_host_unrealize(DeviceState *dev, Error **errp) ++static void virtio_input_host_unrealize(DeviceState *dev) + { + VirtIOInputHost *vih = VIRTIO_INPUT_HOST(dev); + +diff --git a/hw/input/virtio-input.c b/hw/input/virtio-input.c +index 4d49790f50..54bcb46c74 100644 +--- a/hw/input/virtio-input.c ++++ b/hw/input/virtio-input.c +@@ -276,19 +276,14 @@ static void virtio_input_finalize(Object *obj) + g_free(vinput->queue); + } + +-static void virtio_input_device_unrealize(DeviceState *dev, Error **errp) ++static void virtio_input_device_unrealize(DeviceState *dev) + { + VirtIOInputClass *vic = VIRTIO_INPUT_GET_CLASS(dev); + VirtIODevice *vdev = VIRTIO_DEVICE(dev); + VirtIOInput *vinput = VIRTIO_INPUT(dev); +- Error *local_err = NULL; + + if (vic->unrealize) { +- vic->unrealize(dev, &local_err); +- if (local_err) { +- error_propagate(errp, local_err); +- return; +- } ++ vic->unrealize(dev); + } + virtio_delete_queue(vinput->evt); + virtio_delete_queue(vinput->sts); +diff --git a/hw/intc/apic.c b/hw/intc/apic.c +index bd40467965..6b46839ef4 100644 +--- a/hw/intc/apic.c ++++ b/hw/intc/apic.c +@@ -900,7 +900,7 @@ static void apic_realize(DeviceState *dev, Error **errp) + msi_nonbroken = true; + } + +-static void apic_unrealize(DeviceState *dev, Error **errp) ++static void apic_unrealize(DeviceState *dev) + { + APICCommonState *s = APIC(dev); + +diff --git a/hw/intc/apic_common.c b/hw/intc/apic_common.c +index 243bb69430..7da2862b3d 100644 +--- a/hw/intc/apic_common.c ++++ b/hw/intc/apic_common.c +@@ -293,13 +293,13 @@ static void apic_common_realize(DeviceState *dev, Error **errp) + s, -1, 0, NULL); + } + +-static void apic_common_unrealize(DeviceState *dev, Error **errp) ++static void apic_common_unrealize(DeviceState *dev) + { + APICCommonState *s = APIC_COMMON(dev); + APICCommonClass *info = APIC_COMMON_GET_CLASS(s); + + vmstate_unregister(NULL, &vmstate_apic_common, s); +- info->unrealize(dev, errp); ++ info->unrealize(dev); + + if (apic_report_tpr_access && info->enable_tpr_reporting) { + info->enable_tpr_reporting(s, false); +diff --git a/hw/intc/ioapic.c b/hw/intc/ioapic.c +index 15747fe2c2..ffe30dc457 100644 +--- a/hw/intc/ioapic.c ++++ b/hw/intc/ioapic.c +@@ -451,7 +451,7 @@ static void ioapic_realize(DeviceState *dev, Error **errp) + qemu_add_machine_init_done_notifier(&s->machine_done); + } + +-static void ioapic_unrealize(DeviceState *dev, Error **errp) ++static void ioapic_unrealize(DeviceState *dev) + { + IOAPICCommonState *s = IOAPIC_COMMON(dev); + +diff --git a/hw/intc/xics.c b/hw/intc/xics.c +index e56d578841..d5032c8f8a 100644 +--- a/hw/intc/xics.c ++++ b/hw/intc/xics.c +@@ -338,7 +338,7 @@ static void icp_realize(DeviceState *dev, Error **errp) + vmstate_register(NULL, icp->cs->cpu_index, &vmstate_icp_server, icp); + } + +-static void icp_unrealize(DeviceState *dev, Error **errp) ++static void icp_unrealize(DeviceState *dev) + { + ICPState *icp = ICP(dev); + +diff --git a/hw/ipack/ipack.c b/hw/ipack/ipack.c +index 49787a13bc..f19ecaeb1c 100644 +--- a/hw/ipack/ipack.c ++++ b/hw/ipack/ipack.c +@@ -60,15 +60,13 @@ static void ipack_device_realize(DeviceState *dev, Error **errp) + k->realize(dev, errp); + } + +-static void ipack_device_unrealize(DeviceState *dev, Error **errp) ++static void ipack_device_unrealize(DeviceState *dev) + { + IPackDevice *idev = IPACK_DEVICE(dev); + IPackDeviceClass *k = IPACK_DEVICE_GET_CLASS(dev); +- Error *err = NULL; + + if (k->unrealize) { +- k->unrealize(dev, &err); +- error_propagate(errp, err); ++ k->unrealize(dev); + return; + } + +diff --git a/hw/mem/pc-dimm.c b/hw/mem/pc-dimm.c +index b81c82f57b..f2a86ec4ee 100644 +--- a/hw/mem/pc-dimm.c ++++ b/hw/mem/pc-dimm.c +@@ -199,7 +199,7 @@ static void pc_dimm_realize(DeviceState *dev, Error **errp) + host_memory_backend_set_mapped(dimm->hostmem, true); + } + +-static void pc_dimm_unrealize(DeviceState *dev, Error **errp) ++static void pc_dimm_unrealize(DeviceState *dev) + { + PCDIMMDevice *dimm = PC_DIMM(dev); + +diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c +index b43fd7d608..b7f3d1b2eb 100644 +--- a/hw/net/virtio-net.c ++++ b/hw/net/virtio-net.c +@@ -3077,7 +3077,7 @@ static void virtio_net_device_realize(DeviceState *dev, Error **errp) + n->qdev = dev; + } + +-static void virtio_net_device_unrealize(DeviceState *dev, Error **errp) ++static void virtio_net_device_unrealize(DeviceState *dev) + { + VirtIODevice *vdev = VIRTIO_DEVICE(dev); + VirtIONet *n = VIRTIO_NET(dev); +diff --git a/hw/nvram/mac_nvram.c b/hw/nvram/mac_nvram.c +index 2e8a1e3812..ff5db03e6b 100644 +--- a/hw/nvram/mac_nvram.c ++++ b/hw/nvram/mac_nvram.c +@@ -107,7 +107,7 @@ static void macio_nvram_realizefn(DeviceState *dev, Error **errp) + sysbus_init_mmio(d, &s->mem); + } + +-static void macio_nvram_unrealizefn(DeviceState *dev, Error **errp) ++static void macio_nvram_unrealizefn(DeviceState *dev) + { + MacIONVRAMState *s = MACIO_NVRAM(dev); + +diff --git a/hw/pci/pci.c b/hw/pci/pci.c +index b5bc842fac..70c66965f5 100644 +--- a/hw/pci/pci.c ++++ b/hw/pci/pci.c +@@ -146,7 +146,7 @@ static void pcie_bus_realize(BusState *qbus, Error **errp) + } + } + +-static void pci_bus_unrealize(BusState *qbus, Error **errp) ++static void pci_bus_unrealize(BusState *qbus) + { + PCIBus *bus = PCI_BUS(qbus); + +@@ -456,7 +456,7 @@ void pci_root_bus_cleanup(PCIBus *bus) + { + pci_bus_uninit(bus); + /* the caller of the unplug hotplug handler will delete this device */ +- object_property_set_bool(OBJECT(bus), false, "realized", NULL); ++ object_property_set_bool(OBJECT(bus), false, "realized", &error_abort); + } + + void pci_bus_irqs(PCIBus *bus, pci_set_irq_fn set_irq, pci_map_irq_fn map_irq, +@@ -1118,7 +1118,7 @@ static void pci_unregister_io_regions(PCIDevice *pci_dev) + pci_unregister_vga(pci_dev); + } + +-static void pci_qdev_unrealize(DeviceState *dev, Error **errp) ++static void pci_qdev_unrealize(DeviceState *dev) + { + PCIDevice *pci_dev = PCI_DEVICE(dev); + PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(pci_dev); +@@ -2108,7 +2108,7 @@ static void pci_qdev_realize(DeviceState *qdev, Error **errp) + error_setg(errp, "failover primary device must be on " + "PCIExpress bus"); + error_propagate(errp, local_err); +- pci_qdev_unrealize(DEVICE(pci_dev), NULL); ++ pci_qdev_unrealize(DEVICE(pci_dev)); + return; + } + class_id = pci_get_word(pci_dev->config + PCI_CLASS_DEVICE); +@@ -2116,7 +2116,7 @@ static void pci_qdev_realize(DeviceState *qdev, Error **errp) + error_setg(errp, "failover primary device is not an " + "Ethernet device"); + error_propagate(errp, local_err); +- pci_qdev_unrealize(DEVICE(pci_dev), NULL); ++ pci_qdev_unrealize(DEVICE(pci_dev)); + return; + } + if (!(pci_dev->cap_present & QEMU_PCI_CAP_MULTIFUNCTION) +@@ -2126,7 +2126,7 @@ static void pci_qdev_realize(DeviceState *qdev, Error **errp) + error_setg(errp, "failover: primary device must be in its own " + "PCI slot"); + error_propagate(errp, local_err); +- pci_qdev_unrealize(DEVICE(pci_dev), NULL); ++ pci_qdev_unrealize(DEVICE(pci_dev)); + return; + } + qdev->allow_unplug_during_migration = true; +@@ -2142,7 +2142,7 @@ static void pci_qdev_realize(DeviceState *qdev, Error **errp) + pci_add_option_rom(pci_dev, is_default_rom, &local_err); + if (local_err) { + error_propagate(errp, local_err); +- pci_qdev_unrealize(DEVICE(pci_dev), NULL); ++ pci_qdev_unrealize(DEVICE(pci_dev)); + return; + } + } +diff --git a/hw/pci/pcie.c b/hw/pci/pcie.c +index abc99b6eff..f50e10b8fb 100644 +--- a/hw/pci/pcie.c ++++ b/hw/pci/pcie.c +@@ -457,7 +457,7 @@ void pcie_cap_slot_plug_cb(HotplugHandler *hotplug_dev, DeviceState *dev, + void pcie_cap_slot_unplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev, + Error **errp) + { +- object_property_set_bool(OBJECT(dev), false, "realized", NULL); ++ object_property_set_bool(OBJECT(dev), false, "realized", &error_abort); + } + + static void pcie_unplug_device(PCIBus *bus, PCIDevice *dev, void *opaque) +diff --git a/hw/pci/shpc.c b/hw/pci/shpc.c +index 7f0aa28e44..b76d3d2c9a 100644 +--- a/hw/pci/shpc.c ++++ b/hw/pci/shpc.c +@@ -547,7 +547,7 @@ void shpc_device_plug_cb(HotplugHandler *hotplug_dev, DeviceState *dev, + void shpc_device_unplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev, + Error **errp) + { +- object_property_set_bool(OBJECT(dev), false, "realized", NULL); ++ object_property_set_bool(OBJECT(dev), false, "realized", &error_abort); + } + + void shpc_device_unplug_request_cb(HotplugHandler *hotplug_dev, +diff --git a/hw/ppc/pnv_core.c b/hw/ppc/pnv_core.c +index 7033104676..96a446f001 100644 +--- a/hw/ppc/pnv_core.c ++++ b/hw/ppc/pnv_core.c +@@ -275,7 +275,7 @@ static void pnv_core_cpu_unrealize(PnvCore *pc, PowerPCCPU *cpu) + object_unparent(OBJECT(cpu)); + } + +-static void pnv_core_unrealize(DeviceState *dev, Error **errp) ++static void pnv_core_unrealize(DeviceState *dev) + { + PnvCore *pc = PNV_CORE(dev); + CPUCore *cc = CPU_CORE(dev); +diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c +index b73f4d94d3..c0bf8c8d4f 100644 +--- a/hw/ppc/spapr.c ++++ b/hw/ppc/spapr.c +@@ -3670,7 +3670,7 @@ static void spapr_memory_unplug(HotplugHandler *hotplug_dev, DeviceState *dev) + SpaprDimmState *ds = spapr_pending_dimm_unplugs_find(spapr, PC_DIMM(dev)); + + pc_dimm_unplug(PC_DIMM(dev), MACHINE(hotplug_dev)); +- object_property_set_bool(OBJECT(dev), false, "realized", NULL); ++ object_property_set_bool(OBJECT(dev), false, "realized", &error_abort); + spapr_pending_dimm_unplugs_remove(spapr, ds); + } + +@@ -3763,7 +3763,7 @@ static void spapr_core_unplug(HotplugHandler *hotplug_dev, DeviceState *dev) + + assert(core_slot); + core_slot->cpu = NULL; +- object_property_set_bool(OBJECT(dev), false, "realized", NULL); ++ object_property_set_bool(OBJECT(dev), false, "realized", &error_abort); + } + + static +@@ -4036,7 +4036,7 @@ void spapr_phb_release(DeviceState *dev) + + static void spapr_phb_unplug(HotplugHandler *hotplug_dev, DeviceState *dev) + { +- object_property_set_bool(OBJECT(dev), false, "realized", NULL); ++ object_property_set_bool(OBJECT(dev), false, "realized", &error_abort); + } + + static void spapr_phb_unplug_request(HotplugHandler *hotplug_dev, +@@ -4072,7 +4072,7 @@ static void spapr_tpm_proxy_unplug(HotplugHandler *hotplug_dev, DeviceState *dev + { + SpaprMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev)); + +- object_property_set_bool(OBJECT(dev), false, "realized", NULL); ++ object_property_set_bool(OBJECT(dev), false, "realized", &error_abort); + object_unparent(OBJECT(dev)); + spapr->tpm_proxy = NULL; + } +diff --git a/hw/ppc/spapr_cpu_core.c b/hw/ppc/spapr_cpu_core.c +index df5c7742ca..e1f76c74f3 100644 +--- a/hw/ppc/spapr_cpu_core.c ++++ b/hw/ppc/spapr_cpu_core.c +@@ -218,7 +218,7 @@ static void spapr_cpu_core_reset_handler(void *opaque) + spapr_cpu_core_reset(opaque); + } + +-static void spapr_cpu_core_unrealize(DeviceState *dev, Error **errp) ++static void spapr_cpu_core_unrealize(DeviceState *dev) + { + SpaprCpuCore *sc = SPAPR_CPU_CORE(OBJECT(dev)); + CPUCore *cc = CPU_CORE(dev); +diff --git a/hw/ppc/spapr_drc.c b/hw/ppc/spapr_drc.c +index 728307a992..8b2171f698 100644 +--- a/hw/ppc/spapr_drc.c ++++ b/hw/ppc/spapr_drc.c +@@ -541,7 +541,7 @@ static void realize(DeviceState *d, Error **errp) + trace_spapr_drc_realize_complete(spapr_drc_index(drc)); + } + +-static void unrealize(DeviceState *d, Error **errp) ++static void unrealize(DeviceState *d) + { + SpaprDrc *drc = SPAPR_DR_CONNECTOR(d); + Object *root_container; +@@ -551,7 +551,7 @@ static void unrealize(DeviceState *d, Error **errp) + vmstate_unregister(VMSTATE_IF(drc), &vmstate_spapr_drc, drc); + root_container = container_get(object_get_root(), DRC_CONTAINER_PATH); + name = g_strdup_printf("%x", spapr_drc_index(drc)); +- object_property_del(root_container, name, errp); ++ object_property_del(root_container, name, &error_abort); + g_free(name); + } + +@@ -650,17 +650,11 @@ static void realize_physical(DeviceState *d, Error **errp) + qemu_register_reset(drc_physical_reset, drcp); + } + +-static void unrealize_physical(DeviceState *d, Error **errp) ++static void unrealize_physical(DeviceState *d) + { + SpaprDrcPhysical *drcp = SPAPR_DRC_PHYSICAL(d); +- Error *local_err = NULL; +- +- unrealize(d, &local_err); +- if (local_err) { +- error_propagate(errp, local_err); +- return; +- } + ++ unrealize(d); + vmstate_unregister(VMSTATE_IF(drcp), &vmstate_spapr_drc_physical, drcp); + qemu_unregister_reset(drc_physical_reset, drcp); + } +diff --git a/hw/ppc/spapr_iommu.c b/hw/ppc/spapr_iommu.c +index 601b896214..7e1d6d59ac 100644 +--- a/hw/ppc/spapr_iommu.c ++++ b/hw/ppc/spapr_iommu.c +@@ -416,7 +416,7 @@ void spapr_tce_table_disable(SpaprTceTable *tcet) + tcet->nb_table = 0; + } + +-static void spapr_tce_table_unrealize(DeviceState *dev, Error **errp) ++static void spapr_tce_table_unrealize(DeviceState *dev) + { + SpaprTceTable *tcet = SPAPR_TCE_TABLE(dev); + +diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c +index 61b84a392d..616034222d 100644 +--- a/hw/ppc/spapr_pci.c ++++ b/hw/ppc/spapr_pci.c +@@ -1627,7 +1627,8 @@ static void spapr_pci_unplug(HotplugHandler *plug_handler, + return; + } + +- object_property_set_bool(OBJECT(plugged_dev), false, "realized", NULL); ++ object_property_set_bool(OBJECT(plugged_dev), false, "realized", ++ &error_abort); + } + + static void spapr_pci_unplug_request(HotplugHandler *plug_handler, +@@ -1715,7 +1716,7 @@ static void spapr_phb_finalizefn(Object *obj) + sphb->dtbusname = NULL; + } + +-static void spapr_phb_unrealize(DeviceState *dev, Error **errp) ++static void spapr_phb_unrealize(DeviceState *dev) + { + SpaprMachineState *spapr = SPAPR_MACHINE(qdev_get_machine()); + SysBusDevice *s = SYS_BUS_DEVICE(dev); +@@ -1724,7 +1725,6 @@ static void spapr_phb_unrealize(DeviceState *dev, Error **errp) + SpaprTceTable *tcet; + int i; + const unsigned windows_supported = spapr_phb_windows_supported(sphb); +- Error *local_err = NULL; + + spapr_phb_nvgpu_free(sphb); + +@@ -1745,11 +1745,7 @@ static void spapr_phb_unrealize(DeviceState *dev, Error **errp) + } + } + +- remove_drcs(sphb, phb->bus, &local_err); +- if (local_err) { +- error_propagate(errp, local_err); +- return; +- } ++ remove_drcs(sphb, phb->bus, &error_abort); + + for (i = PCI_NUM_PINS - 1; i >= 0; i--) { + if (sphb->lsi_table[i].irq) { +@@ -2011,7 +2007,7 @@ static void spapr_phb_realize(DeviceState *dev, Error **errp) + return; + + unrealize: +- spapr_phb_unrealize(dev, NULL); ++ spapr_phb_unrealize(dev); + } + + static int spapr_phb_children_reset(Object *child, void *opaque) +diff --git a/hw/ppc/spapr_tpm_proxy.c b/hw/ppc/spapr_tpm_proxy.c +index 991615d77a..a01f81f9e0 100644 +--- a/hw/ppc/spapr_tpm_proxy.c ++++ b/hw/ppc/spapr_tpm_proxy.c +@@ -140,7 +140,7 @@ static void spapr_tpm_proxy_realize(DeviceState *d, Error **errp) + qemu_register_reset(spapr_tpm_proxy_reset, tpm_proxy); + } + +-static void spapr_tpm_proxy_unrealize(DeviceState *d, Error **errp) ++static void spapr_tpm_proxy_unrealize(DeviceState *d) + { + SpaprTpmProxy *tpm_proxy = SPAPR_TPM_PROXY(d); + +diff --git a/hw/s390x/css-bridge.c b/hw/s390x/css-bridge.c +index 5d5286bc6e..3f6aec6b6a 100644 +--- a/hw/s390x/css-bridge.c ++++ b/hw/s390x/css-bridge.c +@@ -54,7 +54,7 @@ static void ccw_device_unplug(HotplugHandler *hotplug_dev, + + css_generate_sch_crws(sch->cssid, sch->ssid, sch->schid, 1, 0); + +- object_property_set_bool(OBJECT(dev), false, "realized", NULL); ++ object_property_set_bool(OBJECT(dev), false, "realized", &error_abort); + } + + static void virtual_css_bus_reset(BusState *qbus) +diff --git a/hw/s390x/s390-ccw.c b/hw/s390x/s390-ccw.c +index 569020dae4..c48510f9e5 100644 +--- a/hw/s390x/s390-ccw.c ++++ b/hw/s390x/s390-ccw.c +@@ -132,7 +132,7 @@ out_err_propagate: + error_propagate(errp, err); + } + +-static void s390_ccw_unrealize(S390CCWDevice *cdev, Error **errp) ++static void s390_ccw_unrealize(S390CCWDevice *cdev) + { + CcwDevice *ccw_dev = CCW_DEVICE(cdev); + SubchDev *sch = ccw_dev->sch; +diff --git a/hw/s390x/s390-pci-bus.c b/hw/s390x/s390-pci-bus.c +index ed8be124da..c4a4259f0c 100644 +--- a/hw/s390x/s390-pci-bus.c ++++ b/hw/s390x/s390-pci-bus.c +@@ -1003,7 +1003,7 @@ static void s390_pcihost_unplug(HotplugHandler *hotplug_dev, DeviceState *dev, + pbdev->fh, pbdev->fid); + bus = pci_get_bus(pci_dev); + devfn = pci_dev->devfn; +- object_property_set_bool(OBJECT(dev), false, "realized", NULL); ++ object_property_set_bool(OBJECT(dev), false, "realized", &error_abort); + + s390_pci_msix_free(pbdev); + s390_pci_iommu_free(s, bus, devfn); +@@ -1014,7 +1014,7 @@ static void s390_pcihost_unplug(HotplugHandler *hotplug_dev, DeviceState *dev, + pbdev->fid = 0; + QTAILQ_REMOVE(&s->zpci_devs, pbdev, link); + g_hash_table_remove(s->zpci_table, &pbdev->idx); +- object_property_set_bool(OBJECT(dev), false, "realized", NULL); ++ object_property_set_bool(OBJECT(dev), false, "realized", &error_abort); + } + } + +diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c +index 64f928fc7d..c1f4bb1d33 100644 +--- a/hw/s390x/virtio-ccw.c ++++ b/hw/s390x/virtio-ccw.c +@@ -752,14 +752,14 @@ out_err: + g_free(sch); + } + +-static void virtio_ccw_device_unrealize(VirtioCcwDevice *dev, Error **errp) ++static void virtio_ccw_device_unrealize(VirtioCcwDevice *dev) + { + VirtIOCCWDeviceClass *dc = VIRTIO_CCW_DEVICE_GET_CLASS(dev); + CcwDevice *ccw_dev = CCW_DEVICE(dev); + SubchDev *sch = ccw_dev->sch; + + if (dc->unrealize) { +- dc->unrealize(dev, errp); ++ dc->unrealize(dev); + } + + if (sch) { +@@ -1155,11 +1155,11 @@ static void virtio_ccw_busdev_realize(DeviceState *dev, Error **errp) + virtio_ccw_device_realize(_dev, errp); + } + +-static void virtio_ccw_busdev_unrealize(DeviceState *dev, Error **errp) ++static void virtio_ccw_busdev_unrealize(DeviceState *dev) + { + VirtioCcwDevice *_dev = (VirtioCcwDevice *)dev; + +- virtio_ccw_device_unrealize(_dev, errp); ++ virtio_ccw_device_unrealize(_dev); + } + + static void virtio_ccw_busdev_unplug(HotplugHandler *hotplug_dev, +diff --git a/hw/s390x/virtio-ccw.h b/hw/s390x/virtio-ccw.h +index 3453aa1f98..c0e3355248 100644 +--- a/hw/s390x/virtio-ccw.h ++++ b/hw/s390x/virtio-ccw.h +@@ -76,7 +76,7 @@ typedef struct VirtioCcwDevice VirtioCcwDevice; + typedef struct VirtIOCCWDeviceClass { + CCWDeviceClass parent_class; + void (*realize)(VirtioCcwDevice *dev, Error **errp); +- void (*unrealize)(VirtioCcwDevice *dev, Error **errp); ++ void (*unrealize)(VirtioCcwDevice *dev); + void (*parent_reset)(DeviceState *dev); + } VirtIOCCWDeviceClass; + +diff --git a/hw/scsi/lsi53c895a.c b/hw/scsi/lsi53c895a.c +index ec53b14f7f..63ff4181de 100644 +--- a/hw/scsi/lsi53c895a.c ++++ b/hw/scsi/lsi53c895a.c +@@ -2312,7 +2312,7 @@ static void lsi_scsi_realize(PCIDevice *dev, Error **errp) + scsi_bus_new(&s->bus, sizeof(s->bus), d, &lsi_scsi_info, NULL); + } + +-static void lsi_scsi_unrealize(DeviceState *dev, Error **errp) ++static void lsi_scsi_unrealize(DeviceState *dev) + { + LSIState *s = LSI53C895A(dev); + +diff --git a/hw/scsi/scsi-bus.c b/hw/scsi/scsi-bus.c +index 1733307407..2836f807a0 100644 +--- a/hw/scsi/scsi-bus.c ++++ b/hw/scsi/scsi-bus.c +@@ -59,11 +59,11 @@ static void scsi_device_realize(SCSIDevice *s, Error **errp) + } + } + +-static void scsi_device_unrealize(SCSIDevice *s, Error **errp) ++static void scsi_device_unrealize(SCSIDevice *s) + { + SCSIDeviceClass *sc = SCSI_DEVICE_GET_CLASS(s); + if (sc->unrealize) { +- sc->unrealize(s, errp); ++ sc->unrealize(s); + } + } + +@@ -222,10 +222,9 @@ static void scsi_qdev_realize(DeviceState *qdev, Error **errp) + scsi_dma_restart_cb, dev); + } + +-static void scsi_qdev_unrealize(DeviceState *qdev, Error **errp) ++static void scsi_qdev_unrealize(DeviceState *qdev) + { + SCSIDevice *dev = SCSI_DEVICE(qdev); +- Error *local_err = NULL; + + if (dev->vmsentry) { + qemu_del_vm_change_state_handler(dev->vmsentry); +@@ -233,11 +232,7 @@ static void scsi_qdev_unrealize(DeviceState *qdev, Error **errp) + + scsi_device_purge_requests(dev, SENSE_CODE(NO_SENSE)); + +- scsi_device_unrealize(dev, &local_err); +- if (local_err) { +- error_propagate(errp, local_err); +- return; +- } ++ scsi_device_unrealize(dev); + + blockdev_mark_auto_del(dev->conf.blk); + } +diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c +index e5bcd0baf8..387503e11b 100644 +--- a/hw/scsi/scsi-disk.c ++++ b/hw/scsi/scsi-disk.c +@@ -2421,7 +2421,7 @@ static void scsi_realize(SCSIDevice *dev, Error **errp) + dev->conf.lsecs); + } + +-static void scsi_unrealize(SCSIDevice *dev, Error **errp) ++static void scsi_unrealize(SCSIDevice *dev) + { + del_boot_device_lchs(&dev->qdev, NULL); + } +diff --git a/hw/scsi/vhost-scsi.c b/hw/scsi/vhost-scsi.c +index ffa667171d..c1b012aea4 100644 +--- a/hw/scsi/vhost-scsi.c ++++ b/hw/scsi/vhost-scsi.c +@@ -248,7 +248,7 @@ static void vhost_scsi_realize(DeviceState *dev, Error **errp) + return; + } + +-static void vhost_scsi_unrealize(DeviceState *dev, Error **errp) ++static void vhost_scsi_unrealize(DeviceState *dev) + { + VirtIODevice *vdev = VIRTIO_DEVICE(dev); + VHostSCSICommon *vsc = VHOST_SCSI_COMMON(dev); +diff --git a/hw/scsi/vhost-user-scsi.c b/hw/scsi/vhost-user-scsi.c +index ae380b63b4..cbb5d97599 100644 +--- a/hw/scsi/vhost-user-scsi.c ++++ b/hw/scsi/vhost-user-scsi.c +@@ -143,7 +143,7 @@ free_virtio: + virtio_scsi_common_unrealize(dev); + } + +-static void vhost_user_scsi_unrealize(DeviceState *dev, Error **errp) ++static void vhost_user_scsi_unrealize(DeviceState *dev) + { + VirtIODevice *vdev = VIRTIO_DEVICE(dev); + VHostUserSCSI *s = VHOST_USER_SCSI(dev); +diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c +index 472bbd233b..9b72094a61 100644 +--- a/hw/scsi/virtio-scsi.c ++++ b/hw/scsi/virtio-scsi.c +@@ -954,7 +954,7 @@ void virtio_scsi_common_unrealize(DeviceState *dev) + virtio_cleanup(vdev); + } + +-static void virtio_scsi_device_unrealize(DeviceState *dev, Error **errp) ++static void virtio_scsi_device_unrealize(DeviceState *dev) + { + VirtIOSCSI *s = VIRTIO_SCSI(dev); + +diff --git a/hw/sd/sdhci-internal.h b/hw/sd/sdhci-internal.h +index 34141400f8..e7c8a523b5 100644 +--- a/hw/sd/sdhci-internal.h ++++ b/hw/sd/sdhci-internal.h +@@ -335,7 +335,7 @@ extern const VMStateDescription sdhci_vmstate; + void sdhci_initfn(SDHCIState *s); + void sdhci_uninitfn(SDHCIState *s); + void sdhci_common_realize(SDHCIState *s, Error **errp); +-void sdhci_common_unrealize(SDHCIState *s, Error **errp); ++void sdhci_common_unrealize(SDHCIState *s); + void sdhci_common_class_init(ObjectClass *klass, void *data); + + #endif +diff --git a/hw/sd/sdhci-pci.c b/hw/sd/sdhci-pci.c +index 19fa8bd8ed..4f5977d487 100644 +--- a/hw/sd/sdhci-pci.c ++++ b/hw/sd/sdhci-pci.c +@@ -50,7 +50,7 @@ static void sdhci_pci_exit(PCIDevice *dev) + { + SDHCIState *s = PCI_SDHCI(dev); + +- sdhci_common_unrealize(s, &error_abort); ++ sdhci_common_unrealize(s); + sdhci_uninitfn(s); + } + +diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c +index 70531ad360..1b75d7bab9 100644 +--- a/hw/sd/sdhci.c ++++ b/hw/sd/sdhci.c +@@ -1346,7 +1346,7 @@ void sdhci_common_realize(SDHCIState *s, Error **errp) + SDHC_REGISTERS_MAP_SIZE); + } + +-void sdhci_common_unrealize(SDHCIState *s, Error **errp) ++void sdhci_common_unrealize(SDHCIState *s) + { + /* This function is expected to be called only once for each class: + * - SysBus: via DeviceClass->unrealize(), +@@ -1479,11 +1479,11 @@ static void sdhci_sysbus_realize(DeviceState *dev, Error **errp) + sysbus_init_mmio(sbd, &s->iomem); + } + +-static void sdhci_sysbus_unrealize(DeviceState *dev, Error **errp) ++static void sdhci_sysbus_unrealize(DeviceState *dev) + { + SDHCIState *s = SYSBUS_SDHCI(dev); + +- sdhci_common_unrealize(s, &error_abort); ++ sdhci_common_unrealize(s); + + if (s->dma_mr) { + address_space_destroy(s->dma_as); +diff --git a/hw/usb/bus.c b/hw/usb/bus.c +index 686f492112..fa07df98a2 100644 +--- a/hw/usb/bus.c ++++ b/hw/usb/bus.c +@@ -14,7 +14,7 @@ static void usb_bus_dev_print(Monitor *mon, DeviceState *qdev, int indent); + + static char *usb_get_dev_path(DeviceState *dev); + static char *usb_get_fw_dev_path(DeviceState *qdev); +-static void usb_qdev_unrealize(DeviceState *qdev, Error **errp); ++static void usb_qdev_unrealize(DeviceState *qdev); + + static Property usb_props[] = { + DEFINE_PROP_STRING("port", USBDevice, port_path), +@@ -130,12 +130,12 @@ USBDevice *usb_device_find_device(USBDevice *dev, uint8_t addr) + return NULL; + } + +-static void usb_device_unrealize(USBDevice *dev, Error **errp) ++static void usb_device_unrealize(USBDevice *dev) + { + USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev); + + if (klass->unrealize) { +- klass->unrealize(dev, errp); ++ klass->unrealize(dev); + } + } + +@@ -265,14 +265,14 @@ static void usb_qdev_realize(DeviceState *qdev, Error **errp) + if (dev->auto_attach) { + usb_device_attach(dev, &local_err); + if (local_err) { +- usb_qdev_unrealize(qdev, NULL); ++ usb_qdev_unrealize(qdev); + error_propagate(errp, local_err); + return; + } + } + } + +-static void usb_qdev_unrealize(DeviceState *qdev, Error **errp) ++static void usb_qdev_unrealize(DeviceState *qdev) + { + USBDevice *dev = USB_DEVICE(qdev); + USBDescString *s, *next; +@@ -286,7 +286,7 @@ static void usb_qdev_unrealize(DeviceState *qdev, Error **errp) + if (dev->attached) { + usb_device_detach(dev); + } +- usb_device_unrealize(dev, errp); ++ usb_device_unrealize(dev); + if (dev->port) { + usb_release_port(dev); + } +diff --git a/hw/usb/ccid-card-emulated.c b/hw/usb/ccid-card-emulated.c +index 3083124556..7d6105ef34 100644 +--- a/hw/usb/ccid-card-emulated.c ++++ b/hw/usb/ccid-card-emulated.c +@@ -562,7 +562,7 @@ out1: + qemu_mutex_destroy(&card->event_list_mutex); + } + +-static void emulated_unrealize(CCIDCardState *base, Error **errp) ++static void emulated_unrealize(CCIDCardState *base) + { + EmulatedState *card = EMULATED_CCID_CARD(base); + VEvent *vevent = vevent_new(VEVENT_LAST, NULL, NULL); +diff --git a/hw/usb/ccid.h b/hw/usb/ccid.h +index bb2fdbfff3..531bf28fb0 100644 +--- a/hw/usb/ccid.h ++++ b/hw/usb/ccid.h +@@ -36,7 +36,7 @@ typedef struct CCIDCardClass { + const uint8_t *apdu, + uint32_t len); + void (*realize)(CCIDCardState *card, Error **errp); +- void (*unrealize)(CCIDCardState *card, Error **errp); ++ void (*unrealize)(CCIDCardState *card); + } CCIDCardClass; + + /* +diff --git a/hw/usb/dev-audio.c b/hw/usb/dev-audio.c +index 6fa213fad5..1371c44f48 100644 +--- a/hw/usb/dev-audio.c ++++ b/hw/usb/dev-audio.c +@@ -923,7 +923,7 @@ static void usb_audio_handle_data(USBDevice *dev, USBPacket *p) + } + } + +-static void usb_audio_unrealize(USBDevice *dev, Error **errp) ++static void usb_audio_unrealize(USBDevice *dev) + { + USBAudioState *s = USB_AUDIO(dev); + +diff --git a/hw/usb/dev-hid.c b/hw/usb/dev-hid.c +index 67ec8b69ec..89f63b698b 100644 +--- a/hw/usb/dev-hid.c ++++ b/hw/usb/dev-hid.c +@@ -699,7 +699,7 @@ static void usb_hid_handle_data(USBDevice *dev, USBPacket *p) + } + } + +-static void usb_hid_unrealize(USBDevice *dev, Error **errp) ++static void usb_hid_unrealize(USBDevice *dev) + { + USBHIDState *us = USB_HID(dev); + +diff --git a/hw/usb/dev-hub.c b/hw/usb/dev-hub.c +index 49a573b346..5f19dd9fb5 100644 +--- a/hw/usb/dev-hub.c ++++ b/hw/usb/dev-hub.c +@@ -565,7 +565,7 @@ static void usb_hub_handle_data(USBDevice *dev, USBPacket *p) + } + } + +-static void usb_hub_unrealize(USBDevice *dev, Error **errp) ++static void usb_hub_unrealize(USBDevice *dev) + { + USBHubState *s = (USBHubState *)dev; + int i; +diff --git a/hw/usb/dev-network.c b/hw/usb/dev-network.c +index 720744488b..c69756709b 100644 +--- a/hw/usb/dev-network.c ++++ b/hw/usb/dev-network.c +@@ -1326,7 +1326,7 @@ static void usbnet_cleanup(NetClientState *nc) + s->nic = NULL; + } + +-static void usb_net_unrealize(USBDevice *dev, Error **errp) ++static void usb_net_unrealize(USBDevice *dev) + { + USBNetState *s = (USBNetState *) dev; + +diff --git a/hw/usb/dev-smartcard-reader.c b/hw/usb/dev-smartcard-reader.c +index ef72738ced..ada18c1983 100644 +--- a/hw/usb/dev-smartcard-reader.c ++++ b/hw/usb/dev-smartcard-reader.c +@@ -1146,7 +1146,7 @@ static void ccid_handle_data(USBDevice *dev, USBPacket *p) + } + } + +-static void ccid_unrealize(USBDevice *dev, Error **errp) ++static void ccid_unrealize(USBDevice *dev) + { + USBCCIDState *s = USB_CCID_DEV(dev); + +@@ -1269,23 +1269,18 @@ void ccid_card_card_inserted(CCIDCardState *card) + ccid_on_slot_change(s, true); + } + +-static void ccid_card_unrealize(DeviceState *qdev, Error **errp) ++static void ccid_card_unrealize(DeviceState *qdev) + { + CCIDCardState *card = CCID_CARD(qdev); + CCIDCardClass *cc = CCID_CARD_GET_CLASS(card); + USBDevice *dev = USB_DEVICE(qdev->parent_bus->parent); + USBCCIDState *s = USB_CCID_DEV(dev); +- Error *local_err = NULL; + + if (ccid_card_inserted(s)) { + ccid_card_card_removed(card); + } + if (cc->unrealize) { +- cc->unrealize(card, &local_err); +- if (local_err != NULL) { +- error_propagate(errp, local_err); +- return; +- } ++ cc->unrealize(card); + } + s->card = NULL; + } +diff --git a/hw/usb/dev-uas.c b/hw/usb/dev-uas.c +index 11a8684cc2..a3a4d41c07 100644 +--- a/hw/usb/dev-uas.c ++++ b/hw/usb/dev-uas.c +@@ -894,7 +894,7 @@ static void usb_uas_handle_data(USBDevice *dev, USBPacket *p) + } + } + +-static void usb_uas_unrealize(USBDevice *dev, Error **errp) ++static void usb_uas_unrealize(USBDevice *dev) + { + UASDevice *uas = USB_UAS(dev); + +diff --git a/hw/usb/dev-wacom.c b/hw/usb/dev-wacom.c +index 8ed57b3b44..8aba44b8bc 100644 +--- a/hw/usb/dev-wacom.c ++++ b/hw/usb/dev-wacom.c +@@ -331,7 +331,7 @@ static void usb_wacom_handle_data(USBDevice *dev, USBPacket *p) + } + } + +-static void usb_wacom_unrealize(USBDevice *dev, Error **errp) ++static void usb_wacom_unrealize(USBDevice *dev) + { + USBWacomState *s = (USBWacomState *) dev; + +diff --git a/hw/usb/hcd-ehci-pci.c b/hw/usb/hcd-ehci-pci.c +index fc73a054c6..4c37c8e227 100644 +--- a/hw/usb/hcd-ehci-pci.c ++++ b/hw/usb/hcd-ehci-pci.c +@@ -105,7 +105,7 @@ static void usb_ehci_pci_exit(PCIDevice *dev) + EHCIPCIState *i = PCI_EHCI(dev); + EHCIState *s = &i->ehci; + +- usb_ehci_unrealize(s, DEVICE(dev), NULL); ++ usb_ehci_unrealize(s, DEVICE(dev)); + + g_free(s->irq); + s->irq = NULL; +diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c +index 29d49c2d7e..1495e8f7fa 100644 +--- a/hw/usb/hcd-ehci.c ++++ b/hw/usb/hcd-ehci.c +@@ -2522,7 +2522,7 @@ void usb_ehci_realize(EHCIState *s, DeviceState *dev, Error **errp) + s->vmstate = qemu_add_vm_change_state_handler(usb_ehci_vm_state_change, s); + } + +-void usb_ehci_unrealize(EHCIState *s, DeviceState *dev, Error **errp) ++void usb_ehci_unrealize(EHCIState *s, DeviceState *dev) + { + trace_usb_ehci_unrealize(); + +diff --git a/hw/usb/hcd-ehci.h b/hw/usb/hcd-ehci.h +index edb59311c4..57b38cfc05 100644 +--- a/hw/usb/hcd-ehci.h ++++ b/hw/usb/hcd-ehci.h +@@ -324,7 +324,7 @@ extern const VMStateDescription vmstate_ehci; + void usb_ehci_init(EHCIState *s, DeviceState *dev); + void usb_ehci_finalize(EHCIState *s); + void usb_ehci_realize(EHCIState *s, DeviceState *dev, Error **errp); +-void usb_ehci_unrealize(EHCIState *s, DeviceState *dev, Error **errp); ++void usb_ehci_unrealize(EHCIState *s, DeviceState *dev); + void ehci_reset(void *opaque); + + #define TYPE_PCI_EHCI "pci-ehci-usb" +diff --git a/hw/usb/host-libusb.c b/hw/usb/host-libusb.c +index 78a5c2ba55..e28441379d 100644 +--- a/hw/usb/host-libusb.c ++++ b/hw/usb/host-libusb.c +@@ -1104,7 +1104,7 @@ static void usb_host_instance_init(Object *obj) + &udev->qdev); + } + +-static void usb_host_unrealize(USBDevice *udev, Error **errp) ++static void usb_host_unrealize(USBDevice *udev) + { + USBHostDevice *s = USB_HOST_DEVICE(udev); + +diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c +index e9a97feaed..417a60a2e6 100644 +--- a/hw/usb/redirect.c ++++ b/hw/usb/redirect.c +@@ -1468,7 +1468,7 @@ static void usbredir_cleanup_device_queues(USBRedirDevice *dev) + } + } + +-static void usbredir_unrealize(USBDevice *udev, Error **errp) ++static void usbredir_unrealize(USBDevice *udev) + { + USBRedirDevice *dev = USB_REDIRECT(udev); + +diff --git a/hw/vfio/ap.c b/hw/vfio/ap.c +index 8649ac15f9..95564c17ed 100644 +--- a/hw/vfio/ap.c ++++ b/hw/vfio/ap.c +@@ -124,7 +124,7 @@ out_get_dev_err: + vfio_put_group(vfio_group); + } + +-static void vfio_ap_unrealize(DeviceState *dev, Error **errp) ++static void vfio_ap_unrealize(DeviceState *dev) + { + APDevice *apdev = AP_DEVICE(dev); + VFIOAPDevice *vapdev = VFIO_AP_DEVICE(apdev); +diff --git a/hw/vfio/ccw.c b/hw/vfio/ccw.c +index 50cc2ec75c..c8624943c1 100644 +--- a/hw/vfio/ccw.c ++++ b/hw/vfio/ccw.c +@@ -521,13 +521,13 @@ out_device_err: + vfio_put_group(group); + out_group_err: + if (cdc->unrealize) { +- cdc->unrealize(cdev, NULL); ++ cdc->unrealize(cdev); + } + out_err_propagate: + error_propagate(errp, err); + } + +-static void vfio_ccw_unrealize(DeviceState *dev, Error **errp) ++static void vfio_ccw_unrealize(DeviceState *dev) + { + CcwDevice *ccw_dev = DO_UPCAST(CcwDevice, parent_obj, dev); + S390CCWDevice *cdev = DO_UPCAST(S390CCWDevice, parent_obj, ccw_dev); +@@ -541,7 +541,7 @@ static void vfio_ccw_unrealize(DeviceState *dev, Error **errp) + vfio_put_group(group); + + if (cdc->unrealize) { +- cdc->unrealize(cdev, errp); ++ cdc->unrealize(cdev); + } + } + +diff --git a/hw/virtio/vhost-user-fs.c b/hw/virtio/vhost-user-fs.c +index 6136768875..1bc5d03a00 100644 +--- a/hw/virtio/vhost-user-fs.c ++++ b/hw/virtio/vhost-user-fs.c +@@ -241,7 +241,7 @@ err_virtio: + return; + } + +-static void vuf_device_unrealize(DeviceState *dev, Error **errp) ++static void vuf_device_unrealize(DeviceState *dev) + { + VirtIODevice *vdev = VIRTIO_DEVICE(dev); + VHostUserFS *fs = VHOST_USER_FS(dev); +diff --git a/hw/virtio/vhost-vsock.c b/hw/virtio/vhost-vsock.c +index 09b6b07f94..4a228f5168 100644 +--- a/hw/virtio/vhost-vsock.c ++++ b/hw/virtio/vhost-vsock.c +@@ -377,7 +377,7 @@ err_virtio: + return; + } + +-static void vhost_vsock_device_unrealize(DeviceState *dev, Error **errp) ++static void vhost_vsock_device_unrealize(DeviceState *dev) + { + VirtIODevice *vdev = VIRTIO_DEVICE(dev); + VHostVSock *vsock = VHOST_VSOCK(dev); +diff --git a/hw/virtio/virtio-balloon.c b/hw/virtio/virtio-balloon.c +index 6d3ddf6449..065cd450f1 100644 +--- a/hw/virtio/virtio-balloon.c ++++ b/hw/virtio/virtio-balloon.c +@@ -819,7 +819,7 @@ static void virtio_balloon_device_realize(DeviceState *dev, Error **errp) + reset_stats(s); + } + +-static void virtio_balloon_device_unrealize(DeviceState *dev, Error **errp) ++static void virtio_balloon_device_unrealize(DeviceState *dev) + { + VirtIODevice *vdev = VIRTIO_DEVICE(dev); + VirtIOBalloon *s = VIRTIO_BALLOON(dev); +diff --git a/hw/virtio/virtio-crypto.c b/hw/virtio/virtio-crypto.c +index 4c65114de5..bd9165c565 100644 +--- a/hw/virtio/virtio-crypto.c ++++ b/hw/virtio/virtio-crypto.c +@@ -822,7 +822,7 @@ static void virtio_crypto_device_realize(DeviceState *dev, Error **errp) + cryptodev_backend_set_used(vcrypto->cryptodev, true); + } + +-static void virtio_crypto_device_unrealize(DeviceState *dev, Error **errp) ++static void virtio_crypto_device_unrealize(DeviceState *dev) + { + VirtIODevice *vdev = VIRTIO_DEVICE(dev); + VirtIOCrypto *vcrypto = VIRTIO_CRYPTO(dev); +diff --git a/hw/virtio/virtio-iommu.c b/hw/virtio/virtio-iommu.c +index 22ba8848c2..483883ec1d 100644 +--- a/hw/virtio/virtio-iommu.c ++++ b/hw/virtio/virtio-iommu.c +@@ -688,7 +688,7 @@ static void virtio_iommu_device_realize(DeviceState *dev, Error **errp) + } + } + +-static void virtio_iommu_device_unrealize(DeviceState *dev, Error **errp) ++static void virtio_iommu_device_unrealize(DeviceState *dev) + { + VirtIODevice *vdev = VIRTIO_DEVICE(dev); + VirtIOIOMMU *s = VIRTIO_IOMMU(dev); +diff --git a/hw/virtio/virtio-pmem.c b/hw/virtio/virtio-pmem.c +index 43399522f5..c3374b2f3f 100644 +--- a/hw/virtio/virtio-pmem.c ++++ b/hw/virtio/virtio-pmem.c +@@ -124,7 +124,7 @@ static void virtio_pmem_realize(DeviceState *dev, Error **errp) + pmem->rq_vq = virtio_add_queue(vdev, 128, virtio_pmem_flush); + } + +-static void virtio_pmem_unrealize(DeviceState *dev, Error **errp) ++static void virtio_pmem_unrealize(DeviceState *dev) + { + VirtIODevice *vdev = VIRTIO_DEVICE(dev); + VirtIOPMEM *pmem = VIRTIO_PMEM(dev); +diff --git a/hw/virtio/virtio-rng.c b/hw/virtio/virtio-rng.c +index 672619c780..a8df41b11b 100644 +--- a/hw/virtio/virtio-rng.c ++++ b/hw/virtio/virtio-rng.c +@@ -230,7 +230,7 @@ static void virtio_rng_device_realize(DeviceState *dev, Error **errp) + vrng); + } + +-static void virtio_rng_device_unrealize(DeviceState *dev, Error **errp) ++static void virtio_rng_device_unrealize(DeviceState *dev) + { + VirtIODevice *vdev = VIRTIO_DEVICE(dev); + VirtIORNG *vrng = VIRTIO_RNG(dev); +diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c +index b6c8ef5bc0..850fcce5e7 100644 +--- a/hw/virtio/virtio.c ++++ b/hw/virtio/virtio.c +@@ -3622,7 +3622,7 @@ static void virtio_device_realize(DeviceState *dev, Error **errp) + virtio_bus_device_plugged(vdev, &err); + if (err != NULL) { + error_propagate(errp, err); +- vdc->unrealize(dev, NULL); ++ vdc->unrealize(dev); + return; + } + +@@ -3630,20 +3630,15 @@ static void virtio_device_realize(DeviceState *dev, Error **errp) + memory_listener_register(&vdev->listener, vdev->dma_as); + } + +-static void virtio_device_unrealize(DeviceState *dev, Error **errp) ++static void virtio_device_unrealize(DeviceState *dev) + { + VirtIODevice *vdev = VIRTIO_DEVICE(dev); + VirtioDeviceClass *vdc = VIRTIO_DEVICE_GET_CLASS(dev); +- Error *err = NULL; + + virtio_bus_device_unplugged(vdev); + + if (vdc->unrealize != NULL) { +- vdc->unrealize(dev, &err); +- if (err != NULL) { +- error_propagate(errp, err); +- return; +- } ++ vdc->unrealize(dev); + } + + g_free(vdev->bus_name); +diff --git a/hw/watchdog/wdt_diag288.c b/hw/watchdog/wdt_diag288.c +index 5b6eb2b09f..71a945f0bd 100644 +--- a/hw/watchdog/wdt_diag288.c ++++ b/hw/watchdog/wdt_diag288.c +@@ -108,7 +108,7 @@ static void wdt_diag288_realize(DeviceState *dev, Error **errp) + dev); + } + +-static void wdt_diag288_unrealize(DeviceState *dev, Error **errp) ++static void wdt_diag288_unrealize(DeviceState *dev) + { + DIAG288State *diag288 = DIAG288(dev); + +diff --git a/hw/xen/xen-bus.c b/hw/xen/xen-bus.c +index 18237b34ea..32dd4461be 100644 +--- a/hw/xen/xen-bus.c ++++ b/hw/xen/xen-bus.c +@@ -428,7 +428,7 @@ static void xen_bus_backend_changed(void *opaque) + xen_bus_cleanup(xenbus); + } + +-static void xen_bus_unrealize(BusState *bus, Error **errp) ++static void xen_bus_unrealize(BusState *bus) + { + XenBus *xenbus = XEN_BUS(bus); + +@@ -486,7 +486,7 @@ static void xen_bus_realize(BusState *bus, Error **errp) + return; + + fail: +- xen_bus_unrealize(bus, &error_abort); ++ xen_bus_unrealize(bus); + } + + static void xen_bus_unplug_request(HotplugHandler *hotplug, +@@ -1189,7 +1189,7 @@ void xen_device_unbind_event_channel(XenDevice *xendev, + g_free(channel); + } + +-static void xen_device_unrealize(DeviceState *dev, Error **errp) ++static void xen_device_unrealize(DeviceState *dev) + { + XenDevice *xendev = XEN_DEVICE(dev); + XenDeviceClass *xendev_class = XEN_DEVICE_GET_CLASS(xendev); +@@ -1208,7 +1208,7 @@ static void xen_device_unrealize(DeviceState *dev, Error **errp) + } + + if (xendev_class->unrealize) { +- xendev_class->unrealize(xendev, errp); ++ xendev_class->unrealize(xendev); + } + + /* Make sure all event channels are cleaned up */ +@@ -1242,7 +1242,7 @@ static void xen_device_exit(Notifier *n, void *data) + { + XenDevice *xendev = container_of(n, XenDevice, exit); + +- xen_device_unrealize(DEVICE(xendev), &error_abort); ++ xen_device_unrealize(DEVICE(xendev)); + } + + static void xen_device_realize(DeviceState *dev, Error **errp) +@@ -1336,7 +1336,7 @@ static void xen_device_realize(DeviceState *dev, Error **errp) + return; + + unrealize: +- xen_device_unrealize(dev, &error_abort); ++ xen_device_unrealize(dev); + } + + static Property xen_device_props[] = { +diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h +index 6f537f687f..b870b27966 100644 +--- a/include/hw/qdev-core.h ++++ b/include/hw/qdev-core.h +@@ -30,10 +30,10 @@ typedef enum DeviceCategory { + } DeviceCategory; + + typedef void (*DeviceRealize)(DeviceState *dev, Error **errp); +-typedef void (*DeviceUnrealize)(DeviceState *dev, Error **errp); ++typedef void (*DeviceUnrealize)(DeviceState *dev); + typedef void (*DeviceReset)(DeviceState *dev); + typedef void (*BusRealize)(BusState *bus, Error **errp); +-typedef void (*BusUnrealize)(BusState *bus, Error **errp); ++typedef void (*BusUnrealize)(BusState *bus); + + /** + * DeviceClass: +diff --git a/include/hw/s390x/s390-ccw.h b/include/hw/s390x/s390-ccw.h +index fffb54562f..7f27bc2f53 100644 +--- a/include/hw/s390x/s390-ccw.h ++++ b/include/hw/s390x/s390-ccw.h +@@ -33,7 +33,7 @@ typedef struct S390CCWDevice { + typedef struct S390CCWDeviceClass { + CCWDeviceClass parent_class; + void (*realize)(S390CCWDevice *dev, char *sysfsdev, Error **errp); +- void (*unrealize)(S390CCWDevice *dev, Error **errp); ++ void (*unrealize)(S390CCWDevice *dev); + IOInstEnding (*handle_request) (SubchDev *sch); + int (*handle_halt) (SubchDev *sch); + int (*handle_clear) (SubchDev *sch); +diff --git a/include/hw/scsi/scsi.h b/include/hw/scsi/scsi.h +index 332ef602f4..2fc23e44ba 100644 +--- a/include/hw/scsi/scsi.h ++++ b/include/hw/scsi/scsi.h +@@ -59,7 +59,7 @@ struct SCSIRequest { + typedef struct SCSIDeviceClass { + DeviceClass parent_class; + void (*realize)(SCSIDevice *dev, Error **errp); +- void (*unrealize)(SCSIDevice *dev, Error **errp); ++ void (*unrealize)(SCSIDevice *dev); + int (*parse_cdb)(SCSIDevice *dev, SCSICommand *cmd, uint8_t *buf, + void *hba_private); + SCSIRequest *(*alloc_req)(SCSIDevice *s, uint32_t tag, uint32_t lun, +diff --git a/include/hw/usb.h b/include/hw/usb.h +index c24d968a19..1cf1cd9584 100644 +--- a/include/hw/usb.h ++++ b/include/hw/usb.h +@@ -272,7 +272,7 @@ struct USBDevice { + OBJECT_GET_CLASS(USBDeviceClass, (obj), TYPE_USB_DEVICE) + + typedef void (*USBDeviceRealize)(USBDevice *dev, Error **errp); +-typedef void (*USBDeviceUnrealize)(USBDevice *dev, Error **errp); ++typedef void (*USBDeviceUnrealize)(USBDevice *dev); + + typedef struct USBDeviceClass { + DeviceClass parent_class; +diff --git a/include/hw/xen/xen-block.h b/include/hw/xen/xen-block.h +index 11d351b4b3..2cd2fc2701 100644 +--- a/include/hw/xen/xen-block.h ++++ b/include/hw/xen/xen-block.h +@@ -57,7 +57,7 @@ typedef struct XenBlockDevice { + } XenBlockDevice; + + typedef void (*XenBlockDeviceRealize)(XenBlockDevice *blockdev, Error **errp); +-typedef void (*XenBlockDeviceUnrealize)(XenBlockDevice *blockdev, Error **errp); ++typedef void (*XenBlockDeviceUnrealize)(XenBlockDevice *blockdev); + + typedef struct XenBlockDeviceClass { + /*< private >*/ +diff --git a/include/hw/xen/xen-bus.h b/include/hw/xen/xen-bus.h +index c18c1372af..4ec0bb072f 100644 +--- a/include/hw/xen/xen-bus.h ++++ b/include/hw/xen/xen-bus.h +@@ -42,7 +42,7 @@ typedef void (*XenDeviceRealize)(XenDevice *xendev, Error **errp); + typedef void (*XenDeviceFrontendChanged)(XenDevice *xendev, + enum xenbus_state frontend_state, + Error **errp); +-typedef void (*XenDeviceUnrealize)(XenDevice *xendev, Error **errp); ++typedef void (*XenDeviceUnrealize)(XenDevice *xendev); + + typedef struct XenDeviceClass { + /*< private >*/ +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index 6a64d2a5cd..7a4a8e3847 100644 +--- a/target/i386/cpu.c ++++ b/target/i386/cpu.c +@@ -6722,11 +6722,10 @@ out: + } + } + +-static void x86_cpu_unrealizefn(DeviceState *dev, Error **errp) ++static void x86_cpu_unrealizefn(DeviceState *dev) + { + X86CPU *cpu = X86_CPU(dev); + X86CPUClass *xcc = X86_CPU_GET_CLASS(dev); +- Error *local_err = NULL; + + #ifndef CONFIG_USER_ONLY + cpu_remove_sync(CPU(dev)); +@@ -6738,11 +6737,7 @@ static void x86_cpu_unrealizefn(DeviceState *dev, Error **errp) + cpu->apic_state = NULL; + } + +- xcc->parent_unrealize(dev, &local_err); +- if (local_err != NULL) { +- error_propagate(errp, local_err); +- return; +- } ++ xcc->parent_unrealize(dev); + } + + typedef struct BitProperty { +diff --git a/target/ppc/translate_init.inc.c b/target/ppc/translate_init.inc.c +index 2b6e832c4c..d8adc1bd49 100644 +--- a/target/ppc/translate_init.inc.c ++++ b/target/ppc/translate_init.inc.c +@@ -10293,19 +10293,14 @@ unrealize: + cpu_exec_unrealizefn(cs); + } + +-static void ppc_cpu_unrealize(DeviceState *dev, Error **errp) ++static void ppc_cpu_unrealize(DeviceState *dev) + { + PowerPCCPU *cpu = POWERPC_CPU(dev); + PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu); +- Error *local_err = NULL; + opc_handler_t **table, **table_2; + int i, j, k; + +- pcc->parent_unrealize(dev, &local_err); +- if (local_err != NULL) { +- error_propagate(errp, local_err); +- return; +- } ++ pcc->parent_unrealize(dev); + + for (i = 0; i < PPC_CPU_OPCODES_LEN; i++) { + if (cpu->opcodes[i] == &invalid_handler) { +-- +2.23.0 + diff --git a/qdev-add-clock-input-output-support-to-devices.patch b/qdev-add-clock-input-output-support-to-devices.patch new file mode 100644 index 0000000000000000000000000000000000000000..5bc6797f55a57e2a8a7535ab87e46e92a8e511e3 --- /dev/null +++ b/qdev-add-clock-input-output-support-to-devices.patch @@ -0,0 +1,421 @@ +From 0e6934f26484abef4a96946078a34746f8855801 Mon Sep 17 00:00:00 2001 +From: Damien Hedde +Date: Mon, 6 Apr 2020 15:52:45 +0200 +Subject: [PATCH 104/709] qdev: add clock input&output support to devices. + +Add functions to easily handle clocks with devices. +Clock inputs and outputs should be used to handle clock propagation +between devices. +The API is very similar the GPIO API. + +This is based on the original work of Frederic Konrad. + +Signed-off-by: Damien Hedde +Reviewed-by: Edgar E. Iglesias +Reviewed-by: Alistair Francis +Message-id: 20200406135251.157596-4-damien.hedde@greensocs.com +Signed-off-by: Peter Maydell +--- + hw/core/Makefile.objs | 2 +- + hw/core/qdev-clock.c | 168 ++++++++++++++++++++++++++++++++++++++++ + hw/core/qdev.c | 12 +++ + include/hw/qdev-clock.h | 104 +++++++++++++++++++++++++ + include/hw/qdev-core.h | 12 +++ + tests/Makefile.include | 1 + + 6 files changed, 298 insertions(+), 1 deletion(-) + create mode 100644 hw/core/qdev-clock.c + create mode 100644 include/hw/qdev-clock.h + +diff --git a/hw/core/Makefile.objs b/hw/core/Makefile.objs +index 115df55087..1d540ed6e7 100644 +--- a/hw/core/Makefile.objs ++++ b/hw/core/Makefile.objs +@@ -7,7 +7,7 @@ common-obj-y += hotplug.o + common-obj-y += vmstate-if.o + # irq.o needed for qdev GPIO handling: + common-obj-y += irq.o +-common-obj-y += clock.o ++common-obj-y += clock.o qdev-clock.o + + common-obj-$(CONFIG_SOFTMMU) += reset.o + common-obj-$(CONFIG_SOFTMMU) += qdev-fw.o +diff --git a/hw/core/qdev-clock.c b/hw/core/qdev-clock.c +new file mode 100644 +index 0000000000..62035aef83 +--- /dev/null ++++ b/hw/core/qdev-clock.c +@@ -0,0 +1,168 @@ ++/* ++ * Device's clock input and output ++ * ++ * Copyright GreenSocs 2016-2020 ++ * ++ * Authors: ++ * Frederic Konrad ++ * Damien Hedde ++ * ++ * 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 "hw/qdev-clock.h" ++#include "hw/qdev-core.h" ++#include "qapi/error.h" ++ ++/* ++ * qdev_init_clocklist: ++ * Add a new clock in a device ++ */ ++static NamedClockList *qdev_init_clocklist(DeviceState *dev, const char *name, ++ bool output, Clock *clk) ++{ ++ NamedClockList *ncl; ++ ++ /* ++ * Clock must be added before realize() so that we can compute the ++ * clock's canonical path during device_realize(). ++ */ ++ assert(!dev->realized); ++ ++ /* ++ * The ncl structure is freed by qdev_finalize_clocklist() which will ++ * be called during @dev's device_finalize(). ++ */ ++ ncl = g_new0(NamedClockList, 1); ++ ncl->name = g_strdup(name); ++ ncl->output = output; ++ ncl->alias = (clk != NULL); ++ ++ /* ++ * Trying to create a clock whose name clashes with some other ++ * clock or property is a bug in the caller and we will abort(). ++ */ ++ if (clk == NULL) { ++ clk = CLOCK(object_new(TYPE_CLOCK)); ++ object_property_add_child(OBJECT(dev), name, OBJECT(clk), &error_abort); ++ if (output) { ++ /* ++ * Remove object_new()'s initial reference. ++ * Note that for inputs, the reference created by object_new() ++ * will be deleted in qdev_finalize_clocklist(). ++ */ ++ object_unref(OBJECT(clk)); ++ } ++ } else { ++ object_property_add_link(OBJECT(dev), name, ++ object_get_typename(OBJECT(clk)), ++ (Object **) &ncl->clock, ++ NULL, OBJ_PROP_LINK_STRONG, &error_abort); ++ } ++ ++ ncl->clock = clk; ++ ++ QLIST_INSERT_HEAD(&dev->clocks, ncl, node); ++ return ncl; ++} ++ ++void qdev_finalize_clocklist(DeviceState *dev) ++{ ++ /* called by @dev's device_finalize() */ ++ NamedClockList *ncl, *ncl_next; ++ ++ QLIST_FOREACH_SAFE(ncl, &dev->clocks, node, ncl_next) { ++ QLIST_REMOVE(ncl, node); ++ if (!ncl->output && !ncl->alias) { ++ /* ++ * We kept a reference on the input clock to ensure it lives up to ++ * this point so we can safely remove the callback. ++ * It avoids having a callback to a deleted object if ncl->clock ++ * is still referenced somewhere else (eg: by a clock output). ++ */ ++ clock_clear_callback(ncl->clock); ++ object_unref(OBJECT(ncl->clock)); ++ } ++ g_free(ncl->name); ++ g_free(ncl); ++ } ++} ++ ++Clock *qdev_init_clock_out(DeviceState *dev, const char *name) ++{ ++ NamedClockList *ncl; ++ ++ assert(name); ++ ++ ncl = qdev_init_clocklist(dev, name, true, NULL); ++ ++ return ncl->clock; ++} ++ ++Clock *qdev_init_clock_in(DeviceState *dev, const char *name, ++ ClockCallback *callback, void *opaque) ++{ ++ NamedClockList *ncl; ++ ++ assert(name); ++ ++ ncl = qdev_init_clocklist(dev, name, false, NULL); ++ ++ if (callback) { ++ clock_set_callback(ncl->clock, callback, opaque); ++ } ++ return ncl->clock; ++} ++ ++static NamedClockList *qdev_get_clocklist(DeviceState *dev, const char *name) ++{ ++ NamedClockList *ncl; ++ ++ QLIST_FOREACH(ncl, &dev->clocks, node) { ++ if (strcmp(name, ncl->name) == 0) { ++ return ncl; ++ } ++ } ++ ++ return NULL; ++} ++ ++Clock *qdev_get_clock_in(DeviceState *dev, const char *name) ++{ ++ NamedClockList *ncl; ++ ++ assert(name); ++ ++ ncl = qdev_get_clocklist(dev, name); ++ assert(!ncl->output); ++ ++ return ncl->clock; ++} ++ ++Clock *qdev_get_clock_out(DeviceState *dev, const char *name) ++{ ++ NamedClockList *ncl; ++ ++ assert(name); ++ ++ ncl = qdev_get_clocklist(dev, name); ++ assert(ncl->output); ++ ++ return ncl->clock; ++} ++ ++Clock *qdev_alias_clock(DeviceState *dev, const char *name, ++ DeviceState *alias_dev, const char *alias_name) ++{ ++ NamedClockList *ncl; ++ ++ assert(name && alias_name); ++ ++ ncl = qdev_get_clocklist(dev, name); ++ ++ qdev_init_clocklist(alias_dev, alias_name, ncl->output, ncl->clock); ++ ++ return ncl->clock; ++} +diff --git a/hw/core/qdev.c b/hw/core/qdev.c +index 85f062def7..dd77a56067 100644 +--- a/hw/core/qdev.c ++++ b/hw/core/qdev.c +@@ -37,6 +37,7 @@ + #include "hw/qdev-properties.h" + #include "hw/boards.h" + #include "hw/sysbus.h" ++#include "hw/qdev-clock.h" + #include "migration/vmstate.h" + #include "trace.h" + +@@ -855,6 +856,7 @@ static void device_set_realized(Object *obj, bool value, Error **errp) + DeviceClass *dc = DEVICE_GET_CLASS(dev); + HotplugHandler *hotplug_ctrl; + BusState *bus; ++ NamedClockList *ncl; + Error *local_err = NULL; + bool unattached_parent = false; + static int unattached_count; +@@ -902,6 +904,13 @@ static void device_set_realized(Object *obj, bool value, Error **errp) + */ + g_free(dev->canonical_path); + dev->canonical_path = object_get_canonical_path(OBJECT(dev)); ++ QLIST_FOREACH(ncl, &dev->clocks, node) { ++ if (ncl->alias) { ++ continue; ++ } else { ++ clock_setup_canonical_path(ncl->clock); ++ } ++ } + + if (qdev_get_vmsd(dev)) { + if (vmstate_register_with_alias_id(VMSTATE_IF(dev), +@@ -1025,6 +1034,7 @@ static void device_initfn(Object *obj) + dev->allow_unplug_during_migration = false; + + QLIST_INIT(&dev->gpios); ++ QLIST_INIT(&dev->clocks); + } + + static void device_post_init(Object *obj) +@@ -1054,6 +1064,8 @@ static void device_finalize(Object *obj) + */ + } + ++ qdev_finalize_clocklist(dev); ++ + /* Only send event if the device had been completely realized */ + if (dev->pending_deleted_event) { + g_assert(dev->canonical_path); +diff --git a/include/hw/qdev-clock.h b/include/hw/qdev-clock.h +new file mode 100644 +index 0000000000..b3b3a3e021 +--- /dev/null ++++ b/include/hw/qdev-clock.h +@@ -0,0 +1,104 @@ ++/* ++ * Device's clock input and output ++ * ++ * Copyright GreenSocs 2016-2020 ++ * ++ * Authors: ++ * Frederic Konrad ++ * Damien Hedde ++ * ++ * This work is licensed under the terms of the GNU GPL, version 2 or later. ++ * See the COPYING file in the top-level directory. ++ */ ++ ++#ifndef QDEV_CLOCK_H ++#define QDEV_CLOCK_H ++ ++#include "hw/clock.h" ++ ++/** ++ * qdev_init_clock_in: ++ * @dev: the device to add an input clock to ++ * @name: the name of the clock (can't be NULL). ++ * @callback: optional callback to be called on update or NULL. ++ * @opaque: argument for the callback ++ * @returns: a pointer to the newly added clock ++ * ++ * Add an input clock to device @dev as a clock named @name. ++ * This adds a child<> property. ++ * The callback will be called with @opaque as opaque parameter. ++ */ ++Clock *qdev_init_clock_in(DeviceState *dev, const char *name, ++ ClockCallback *callback, void *opaque); ++ ++/** ++ * qdev_init_clock_out: ++ * @dev: the device to add an output clock to ++ * @name: the name of the clock (can't be NULL). ++ * @returns: a pointer to the newly added clock ++ * ++ * Add an output clock to device @dev as a clock named @name. ++ * This adds a child<> property. ++ */ ++Clock *qdev_init_clock_out(DeviceState *dev, const char *name); ++ ++/** ++ * qdev_get_clock_in: ++ * @dev: the device which has the clock ++ * @name: the name of the clock (can't be NULL). ++ * @returns: a pointer to the clock ++ * ++ * Get the input clock @name from @dev or NULL if does not exist. ++ */ ++Clock *qdev_get_clock_in(DeviceState *dev, const char *name); ++ ++/** ++ * qdev_get_clock_out: ++ * @dev: the device which has the clock ++ * @name: the name of the clock (can't be NULL). ++ * @returns: a pointer to the clock ++ * ++ * Get the output clock @name from @dev or NULL if does not exist. ++ */ ++Clock *qdev_get_clock_out(DeviceState *dev, const char *name); ++ ++/** ++ * qdev_connect_clock_in: ++ * @dev: a device ++ * @name: the name of an input clock in @dev ++ * @source: the source clock (an output clock of another device for example) ++ * ++ * Set the source clock of input clock @name of device @dev to @source. ++ * @source period update will be propagated to @name clock. ++ */ ++static inline void qdev_connect_clock_in(DeviceState *dev, const char *name, ++ Clock *source) ++{ ++ clock_set_source(qdev_get_clock_in(dev, name), source); ++} ++ ++/** ++ * qdev_alias_clock: ++ * @dev: the device which has the clock ++ * @name: the name of the clock in @dev (can't be NULL) ++ * @alias_dev: the device to add the clock ++ * @alias_name: the name of the clock in @container ++ * @returns: a pointer to the clock ++ * ++ * Add a clock @alias_name in @alias_dev which is an alias of the clock @name ++ * in @dev. The direction _in_ or _out_ will the same as the original. ++ * An alias clock must not be modified or used by @alias_dev and should ++ * typically be only only for device composition purpose. ++ */ ++Clock *qdev_alias_clock(DeviceState *dev, const char *name, ++ DeviceState *alias_dev, const char *alias_name); ++ ++/** ++ * qdev_finalize_clocklist: ++ * @dev: the device being finalized ++ * ++ * Clear the clocklist from @dev. Only used internally in qdev. ++ */ ++void qdev_finalize_clocklist(DeviceState *dev); ++ ++#endif /* QDEV_CLOCK_H */ +diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h +index 1405b8a990..d87d989e72 100644 +--- a/include/hw/qdev-core.h ++++ b/include/hw/qdev-core.h +@@ -149,6 +149,17 @@ struct NamedGPIOList { + QLIST_ENTRY(NamedGPIOList) node; + }; + ++typedef struct Clock Clock; ++typedef struct NamedClockList NamedClockList; ++ ++struct NamedClockList { ++ char *name; ++ Clock *clock; ++ bool output; ++ bool alias; ++ QLIST_ENTRY(NamedClockList) node; ++}; ++ + /** + * DeviceState: + * @realized: Indicates whether the device has been fully constructed. +@@ -171,6 +182,7 @@ struct DeviceState { + bool allow_unplug_during_migration; + BusState *parent_bus; + QLIST_HEAD(, NamedGPIOList) gpios; ++ QLIST_HEAD(, NamedClockList) clocks; + QLIST_HEAD(, BusState) child_bus; + int num_child_bus; + int instance_id_alias; +diff --git a/tests/Makefile.include b/tests/Makefile.include +index 51de676298..03a74b60f6 100644 +--- a/tests/Makefile.include ++++ b/tests/Makefile.include +@@ -439,6 +439,7 @@ tests/test-qdev-global-props$(EXESUF): tests/test-qdev-global-props.o \ + hw/core/fw-path-provider.o \ + hw/core/reset.o \ + hw/core/vmstate-if.o \ ++ hw/core/clock.o hw/core/qdev-clock.o \ + $(test-qapi-obj-y) + tests/test-vmstate$(EXESUF): tests/test-vmstate.o \ + migration/vmstate.o migration/vmstate-types.o migration/qemu-file.o \ +-- +2.23.0 + diff --git a/qdev-clock-introduce-an-init-array-to-ease-the-devic.patch b/qdev-clock-introduce-an-init-array-to-ease-the-devic.patch new file mode 100644 index 0000000000000000000000000000000000000000..b866ddbeca1464fb5580959c8c064170393fa041 --- /dev/null +++ b/qdev-clock-introduce-an-init-array-to-ease-the-devic.patch @@ -0,0 +1,126 @@ +From f0bc2a64c08b94e1333b0a210f19f1a43bd2f412 Mon Sep 17 00:00:00 2001 +From: Damien Hedde +Date: Mon, 6 Apr 2020 15:52:46 +0200 +Subject: [PATCH 105/709] qdev-clock: introduce an init array to ease the + device construction +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Introduce a function and macro helpers to setup several clocks +in a device from a static array description. + +An element of the array describes the clock (name and direction) as +well as the related callback and an optional offset to store the +created object pointer in the device state structure. + +The array must be terminated by a special element QDEV_CLOCK_END. + +This is based on the original work of Frederic Konrad. + +Signed-off-by: Damien Hedde +Reviewed-by: Philippe Mathieu-Daudé +Reviewed-by: Alistair Francis +Reviewed-by: Edgar E. Iglesias +Message-id: 20200406135251.157596-5-damien.hedde@greensocs.com +Signed-off-by: Peter Maydell +--- + hw/core/qdev-clock.c | 17 +++++++++++++ + include/hw/qdev-clock.h | 55 +++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 72 insertions(+) + +diff --git a/hw/core/qdev-clock.c b/hw/core/qdev-clock.c +index 62035aef83..a94cc44437 100644 +--- a/hw/core/qdev-clock.c ++++ b/hw/core/qdev-clock.c +@@ -116,6 +116,23 @@ Clock *qdev_init_clock_in(DeviceState *dev, const char *name, + return ncl->clock; + } + ++void qdev_init_clocks(DeviceState *dev, const ClockPortInitArray clocks) ++{ ++ const struct ClockPortInitElem *elem; ++ ++ for (elem = &clocks[0]; elem->name != NULL; elem++) { ++ Clock **clkp; ++ /* offset cannot be inside the DeviceState part */ ++ assert(elem->offset > sizeof(DeviceState)); ++ clkp = (Clock **)(((void *) dev) + elem->offset); ++ if (elem->is_output) { ++ *clkp = qdev_init_clock_out(dev, elem->name); ++ } else { ++ *clkp = qdev_init_clock_in(dev, elem->name, elem->callback, dev); ++ } ++ } ++} ++ + static NamedClockList *qdev_get_clocklist(DeviceState *dev, const char *name) + { + NamedClockList *ncl; +diff --git a/include/hw/qdev-clock.h b/include/hw/qdev-clock.h +index b3b3a3e021..a340f65ff9 100644 +--- a/include/hw/qdev-clock.h ++++ b/include/hw/qdev-clock.h +@@ -101,4 +101,59 @@ Clock *qdev_alias_clock(DeviceState *dev, const char *name, + */ + void qdev_finalize_clocklist(DeviceState *dev); + ++/** ++ * ClockPortInitElem: ++ * @name: name of the clock (can't be NULL) ++ * @output: indicates whether the clock is input or output ++ * @callback: for inputs, optional callback to be called on clock's update ++ * with device as opaque ++ * @offset: optional offset to store the ClockIn or ClockOut pointer in device ++ * state structure (0 means unused) ++ */ ++struct ClockPortInitElem { ++ const char *name; ++ bool is_output; ++ ClockCallback *callback; ++ size_t offset; ++}; ++ ++#define clock_offset_value(devstate, field) \ ++ (offsetof(devstate, field) + \ ++ type_check(Clock *, typeof_field(devstate, field))) ++ ++#define QDEV_CLOCK(out_not_in, devstate, field, cb) { \ ++ .name = (stringify(field)), \ ++ .is_output = out_not_in, \ ++ .callback = cb, \ ++ .offset = clock_offset_value(devstate, field), \ ++} ++ ++/** ++ * QDEV_CLOCK_(IN|OUT): ++ * @devstate: structure type. @dev argument of qdev_init_clocks below must be ++ * a pointer to that same type. ++ * @field: a field in @_devstate (must be Clock*) ++ * @callback: (for input only) callback (or NULL) to be called with the device ++ * state as argument ++ * ++ * The name of the clock will be derived from @field ++ */ ++#define QDEV_CLOCK_IN(devstate, field, callback) \ ++ QDEV_CLOCK(false, devstate, field, callback) ++ ++#define QDEV_CLOCK_OUT(devstate, field) \ ++ QDEV_CLOCK(true, devstate, field, NULL) ++ ++#define QDEV_CLOCK_END { .name = NULL } ++ ++typedef struct ClockPortInitElem ClockPortInitArray[]; ++ ++/** ++ * qdev_init_clocks: ++ * @dev: the device to add clocks to ++ * @clocks: a QDEV_CLOCK_END-terminated array which contains the ++ * clocks information. ++ */ ++void qdev_init_clocks(DeviceState *dev, const ClockPortInitArray clocks); ++ + #endif /* QDEV_CLOCK_H */ +-- +2.23.0 + diff --git a/qdev-monitor-print-the-device-s-clock-with-info-qtre.patch b/qdev-monitor-print-the-device-s-clock-with-info-qtre.patch new file mode 100644 index 0000000000000000000000000000000000000000..2c27b38719d5e453ab2c4930e505da5de805391d --- /dev/null +++ b/qdev-monitor-print-the-device-s-clock-with-info-qtre.patch @@ -0,0 +1,86 @@ +From 9f2ff99c7f2392fe30e9e74d3e26a4c01820f53e Mon Sep 17 00:00:00 2001 +From: Damien Hedde +Date: Mon, 6 Apr 2020 15:52:51 +0200 +Subject: [PATCH 110/709] qdev-monitor: print the device's clock with info + qtree +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This prints the clocks attached to a DeviceState when using +"info qtree" monitor command. For every clock, it displays the +direction, the name and if the clock is forwarded. For input clock, +it displays also the frequency. + +This is based on the original work of Frederic Konrad. + +Here follows a sample of `info qtree` output on xilinx_zynq machine +after linux boot with only one uart clocked: +> bus: main-system-bus +> type System +> [...] +> dev: cadence_uart, id "" +> gpio-out "sysbus-irq" 1 +> clock-in "refclk" freq_hz=0.000000e+00 +> chardev = "" +> mmio 00000000e0001000/0000000000001000 +> dev: cadence_uart, id "" +> gpio-out "sysbus-irq" 1 +> clock-in "refclk" freq_hz=1.375661e+07 +> chardev = "serial0" +> mmio 00000000e0000000/0000000000001000 +> [...] +> dev: xilinx,zynq_slcr, id "" +> clock-out "uart1_ref_clk" freq_hz=0.000000e+00 +> clock-out "uart0_ref_clk" freq_hz=1.375661e+07 +> clock-in "ps_clk" freq_hz=3.333333e+07 +> mmio 00000000f8000000/0000000000001000 + +Signed-off-by: Damien Hedde +Reviewed-by: Philippe Mathieu-Daudé +Reviewed-by: Peter Maydell +Reviewed-by: Alistair Francis +Reviewed-by: Edgar E. Iglesias +Message-id: 20200406135251.157596-10-damien.hedde@greensocs.com +Signed-off-by: Peter Maydell +--- + qdev-monitor.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/qdev-monitor.c b/qdev-monitor.c +index 9833b33549..56cee1483f 100644 +--- a/qdev-monitor.c ++++ b/qdev-monitor.c +@@ -38,6 +38,7 @@ + #include "migration/misc.h" + #include "migration/migration.h" + #include "qemu/cutils.h" ++#include "hw/clock.h" + + /* + * Aliases were a bad idea from the start. Let's keep them +@@ -737,6 +738,7 @@ static void qdev_print(Monitor *mon, DeviceState *dev, int indent) + ObjectClass *class; + BusState *child; + NamedGPIOList *ngl; ++ NamedClockList *ncl; + + qdev_printf("dev: %s, id \"%s\"\n", object_get_typename(OBJECT(dev)), + dev->id ? dev->id : ""); +@@ -751,6 +753,13 @@ static void qdev_print(Monitor *mon, DeviceState *dev, int indent) + ngl->num_out); + } + } ++ QLIST_FOREACH(ncl, &dev->clocks, node) { ++ qdev_printf("clock-%s%s \"%s\" freq_hz=%e\n", ++ ncl->output ? "out" : "in", ++ ncl->alias ? " (alias)" : "", ++ ncl->name, ++ CLOCK_PERIOD_TO_HZ(1.0 * clock_get(ncl->clock))); ++ } + class = object_get_class(OBJECT(dev)); + do { + qdev_print_props(mon, dev, DEVICE_CLASS(class)->props_, indent); +-- +2.23.0 + diff --git a/qemu-4.0.0.tar.xz b/qemu-5.0.0.tar.xz similarity index 76% rename from qemu-4.0.0.tar.xz rename to qemu-5.0.0.tar.xz index dd626a42feee356cefd342d5a1d5f34abae5656e..d68ae0a460785f0033361dbf16673e67dd30544c 100644 Binary files a/qemu-4.0.0.tar.xz and b/qemu-5.0.0.tar.xz differ diff --git a/qemu-bridge-helper-move-repeating-code-in-parse_acl.patch b/qemu-bridge-helper-move-repeating-code-in-parse_acl.patch deleted file mode 100644 index 8cd599a13bf7a4e4e2b45ab014cd05809051e4f7..0000000000000000000000000000000000000000 --- a/qemu-bridge-helper-move-repeating-code-in-parse_acl.patch +++ /dev/null @@ -1,75 +0,0 @@ -From 3283dde4b5b5cce0f96f48d536bebff66d97ce0b Mon Sep 17 00:00:00 2001 -From: Prasad J Pandit -Date: Tue, 23 Jul 2019 16:17:53 +0530 -Subject: [PATCH 2/2] qemu-bridge-helper: move repeating code in parse_acl_file -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Move repeating error handling sequence in parse_acl_file routine -to an 'err' label. - -This patch fixes CVE-2019-13164. - -Signed-off-by: Prasad J Pandit -Reviewed-by: Stefan Hajnoczi -Reviewed-by: Daniel P. Berrangé -Reviewed-by: Li Qiang -Signed-off-by: Jason Wang -(cherry-picked from commit 3283dde4b5b5cce0f96f48d536bebff66d97ce0b) ---- - qemu-bridge-helper.c | 19 +++++++++---------- - 1 file changed, 9 insertions(+), 10 deletions(-) - -diff --git a/qemu-bridge-helper.c b/qemu-bridge-helper.c -index 2058e10454..3d50ec094c 100644 ---- a/qemu-bridge-helper.c -+++ b/qemu-bridge-helper.c -@@ -102,9 +102,7 @@ static int parse_acl_file(const char *filename, ACLList *acl_list) - - if (arg == NULL) { - fprintf(stderr, "Invalid config line:\n %s\n", line); -- fclose(f); -- errno = EINVAL; -- return -1; -+ goto err; - } - - *arg = 0; -@@ -121,9 +119,7 @@ static int parse_acl_file(const char *filename, ACLList *acl_list) - - if (!g_str_equal(cmd, "include") && strlen(arg) >= IFNAMSIZ) { - fprintf(stderr, "name `%s' too long: %zu\n", arg, strlen(arg)); -- fclose(f); -- errno = EINVAL; -- return -1; -+ goto err; - } - - if (strcmp(cmd, "deny") == 0) { -@@ -149,15 +145,18 @@ static int parse_acl_file(const char *filename, ACLList *acl_list) - parse_acl_file(arg, acl_list); - } else { - fprintf(stderr, "Unknown command `%s'\n", cmd); -- fclose(f); -- errno = EINVAL; -- return -1; -+ goto err; - } - } - - fclose(f); -- - return 0; -+ -+err: -+ fclose(f); -+ errno = EINVAL; -+ return -1; -+ - } - - static bool has_vnet_hdr(int fd) --- -2.19.1 - diff --git a/qemu-bridge-helper-restrict-interface-name-to-IFNAMS.patch b/qemu-bridge-helper-restrict-interface-name-to-IFNAMS.patch deleted file mode 100644 index b6dc25e4dfdc9e204c78c545ad5582c52c07dc26..0000000000000000000000000000000000000000 --- a/qemu-bridge-helper-restrict-interface-name-to-IFNAMS.patch +++ /dev/null @@ -1,60 +0,0 @@ -From 6f5d8671225dc77190647f18a27a0d156d4ca97a Mon Sep 17 00:00:00 2001 -From: Prasad J Pandit -Date: Tue, 23 Jul 2019 16:17:52 +0530 -Subject: [PATCH 1/2] qemu-bridge-helper: restrict interface name to IFNAMSIZ -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -The network interface name in Linux is defined to be of size -IFNAMSIZ(=16), including the terminating null('\0') byte. -The same is applied to interface names read from 'bridge.conf' -file to form ACL rules. If user supplied '--br=bridge' name -is not restricted to the same length, it could lead to ACL bypass -issue. Restrict interface name to IFNAMSIZ, including null byte. - -This patch fixes CVE-2019-13164. - -Reported-by: Riccardo Schirone -Signed-off-by: Prasad J Pandit -Reviewed-by: Stefan Hajnoczi -Reviewed-by: Daniel P. Berrangé -Reviewed-by: Li Qiang -Signed-off-by: Jason Wang -(cherry-picked from commit 6f5d8671225dc77190647f18a27a0d156d4ca97a) ---- - qemu-bridge-helper.c | 11 +++++++++++ - 1 file changed, 11 insertions(+) - -diff --git a/qemu-bridge-helper.c b/qemu-bridge-helper.c -index 95624bc300..2058e10454 100644 ---- a/qemu-bridge-helper.c -+++ b/qemu-bridge-helper.c -@@ -119,6 +119,13 @@ static int parse_acl_file(const char *filename, ACLList *acl_list) - } - *argend = 0; - -+ if (!g_str_equal(cmd, "include") && strlen(arg) >= IFNAMSIZ) { -+ fprintf(stderr, "name `%s' too long: %zu\n", arg, strlen(arg)); -+ fclose(f); -+ errno = EINVAL; -+ return -1; -+ } -+ - if (strcmp(cmd, "deny") == 0) { - acl_rule = g_malloc(sizeof(*acl_rule)); - if (strcmp(arg, "all") == 0) { -@@ -269,6 +276,10 @@ int main(int argc, char **argv) - usage(); - return EXIT_FAILURE; - } -+ if (strlen(bridge) >= IFNAMSIZ) { -+ fprintf(stderr, "name `%s' too long: %zu\n", bridge, strlen(bridge)); -+ return EXIT_FAILURE; -+ } - - /* parse default acl file */ - QSIMPLEQ_INIT(&acl_list); --- -2.19.1 - diff --git a/qemu-img-Add-bitmap-sub-command.patch b/qemu-img-Add-bitmap-sub-command.patch new file mode 100644 index 0000000000000000000000000000000000000000..76668441c6933bd499860f692e4be44d93b6aa63 --- /dev/null +++ b/qemu-img-Add-bitmap-sub-command.patch @@ -0,0 +1,374 @@ +From 3b51ab4bf0f49a01cc2db7b954e0669e081719b5 Mon Sep 17 00:00:00 2001 +From: Eric Blake +Date: Tue, 12 May 2020 20:16:45 -0500 +Subject: [PATCH 602/709] qemu-img: Add bitmap sub-command + +Include actions for --add, --remove, --clear, --enable, --disable, and +--merge (note that --clear is a bit of fluff, because the same can be +accomplished by removing a bitmap and then adding a new one in its +place, but it matches what QMP commands exist). Listing is omitted, +because it does not require a bitmap name and because it was already +possible with 'qemu-img info'. A single command line can play one or +more bitmap commands in sequence on the same bitmap name (although all +added bitmaps share the same granularity, and and all merged bitmaps +come from the same source file). Merge defaults to other bitmaps in +the primary image, but can also be told to merge bitmaps from a +distinct image. + +While this supports --image-opts for the file being modified, I did +not think it worth the extra complexity to support that for the source +file in a cross-file merges. Likewise, I chose to have --merge only +take a single source rather than following the QMP support for +multiple merges in one go (although you can still use more than one +--merge in the command line); in part because qemu-img is offline and +therefore atomicity is not an issue. + +Upcoming patches will add iotest coverage of these commands while +also testing other features. + +Signed-off-by: Eric Blake +Reviewed-by: Max Reitz +Message-Id: <20200513011648.166876-7-eblake@redhat.com> +Reviewed-by: Vladimir Sementsov-Ogievskiy +--- + docs/tools/qemu-img.rst | 24 ++++ + qemu-img-cmds.hx | 7 ++ + qemu-img.c | 248 ++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 279 insertions(+) + +diff --git a/docs/tools/qemu-img.rst b/docs/tools/qemu-img.rst +index 3b6223b5d6..38d464ea3f 100644 +--- a/docs/tools/qemu-img.rst ++++ b/docs/tools/qemu-img.rst +@@ -281,6 +281,30 @@ Command description: + For write tests, by default a buffer filled with zeros is written. This can be + overridden with a pattern byte specified by *PATTERN*. + ++.. option:: bitmap (--merge SOURCE | --add | --remove | --clear | --enable | --disable)... [-b SOURCE_FILE [-F SOURCE_FMT]] [-g GRANULARITY] [--object OBJECTDEF] [--image-opts | -f FMT] FILENAME BITMAP ++ ++ Perform one or more modifications of the persistent bitmap *BITMAP* ++ in the disk image *FILENAME*. The various modifications are: ++ ++ ``--add`` to create *BITMAP*, enabled to record future edits. ++ ++ ``--remove`` to remove *BITMAP*. ++ ++ ``--clear`` to clear *BITMAP*. ++ ++ ``--enable`` to change *BITMAP* to start recording future edits. ++ ++ ``--disable`` to change *BITMAP* to stop recording future edits. ++ ++ ``--merge`` to merge the contents of *SOURCE_BITMAP* into *BITMAP*. ++ ++ Additional options include ``-g`` which sets a non-default ++ *GRANULARITY* for ``--add``, and ``-b`` and ``-F`` which select an ++ alternative source file for all *SOURCE* bitmaps used by ++ ``--merge``. ++ ++ To see what bitmaps are present in an image, use ``qemu-img info``. ++ + .. option:: check [--object OBJECTDEF] [--image-opts] [-q] [-f FMT] [--output=OFMT] [-r [leaks | all]] [-T SRC_CACHE] [-U] FILENAME + + Perform a consistency check on the disk image *FILENAME*. The command can +diff --git a/qemu-img-cmds.hx b/qemu-img-cmds.hx +index cfe8f37587..a87d3cb264 100644 +--- a/qemu-img-cmds.hx ++++ b/qemu-img-cmds.hx +@@ -20,6 +20,13 @@ DEF("bench", img_bench, + SRST + .. option:: bench [-c COUNT] [-d DEPTH] [-f FMT] [--flush-interval=FLUSH_INTERVAL] [-i AIO] [-n] [--no-drain] [-o OFFSET] [--pattern=PATTERN] [-q] [-s BUFFER_SIZE] [-S STEP_SIZE] [-t CACHE] [-w] [-U] FILENAME + ERST ++ ++DEF("bitmap", img_bitmap, ++ "bitmap (--merge SOURCE | --add | --remove | --clear | --enable | --disable)... [-b source_file [-F source_fmt]] [-g granularity] [--object objectdef] [--image-opts | -f fmt] filename bitmap") ++SRST ++.. option:: bitmap (--merge SOURCE | --add | --remove | --clear | --enable | --disable)... [-b SOURCE_FILE [-F SOURCE_FMT]] [-g GRANULARITY] [--object OBJECTDEF] [--image-opts | -f FMT] FILENAME BITMAP ++ERST ++ + DEF("check", img_check, + "check [--object objectdef] [--image-opts] [-q] [-f fmt] [--output=ofmt] [-r [leaks | all]] [-T src_cache] [-U] filename") + SRST +diff --git a/qemu-img.c b/qemu-img.c +index 4740de082f..2d30682f12 100644 +--- a/qemu-img.c ++++ b/qemu-img.c +@@ -28,6 +28,7 @@ + #include "qemu-common.h" + #include "qemu-version.h" + #include "qapi/error.h" ++#include "qapi/qapi-commands-block-core.h" + #include "qapi/qapi-visit-block-core.h" + #include "qapi/qobject-output-visitor.h" + #include "qapi/qmp/qjson.h" +@@ -71,6 +72,12 @@ enum { + OPTION_SHRINK = 266, + OPTION_SALVAGE = 267, + OPTION_TARGET_IS_ZERO = 268, ++ OPTION_ADD = 269, ++ OPTION_REMOVE = 270, ++ OPTION_CLEAR = 271, ++ OPTION_ENABLE = 272, ++ OPTION_DISABLE = 273, ++ OPTION_MERGE = 274, + }; + + typedef enum OutputFormat { +@@ -169,6 +176,14 @@ static void QEMU_NORETURN help(void) + " '-n' skips the target volume creation (useful if the volume is created\n" + " prior to running qemu-img)\n" + "\n" ++ "Parameters to bitmap subcommand:\n" ++ " 'bitmap' is the name of the bitmap to manipulate, through one or more\n" ++ " actions from '--add', '--remove', '--clear', '--enable', '--disable',\n" ++ " or '--merge source'\n" ++ " '-g granularity' sets the granularity for '--add' actions\n" ++ " '-b source' and '-F src_fmt' tell '--merge' actions to find the source\n" ++ " bitmaps from an alternative file\n" ++ "\n" + "Parameters to check subcommand:\n" + " '-r' tries to repair any inconsistencies that are found during the check.\n" + " '-r leaks' repairs only cluster leaks, whereas '-r all' fixes all\n" +@@ -4502,6 +4517,239 @@ out: + return 0; + } + ++enum ImgBitmapAct { ++ BITMAP_ADD, ++ BITMAP_REMOVE, ++ BITMAP_CLEAR, ++ BITMAP_ENABLE, ++ BITMAP_DISABLE, ++ BITMAP_MERGE, ++}; ++typedef struct ImgBitmapAction { ++ enum ImgBitmapAct act; ++ const char *src; /* only used for merge */ ++ QSIMPLEQ_ENTRY(ImgBitmapAction) next; ++} ImgBitmapAction; ++ ++static int img_bitmap(int argc, char **argv) ++{ ++ Error *err = NULL; ++ int c, ret = 1; ++ QemuOpts *opts = NULL; ++ const char *fmt = NULL, *src_fmt = NULL, *src_filename = NULL; ++ const char *filename, *bitmap; ++ BlockBackend *blk = NULL, *src = NULL; ++ BlockDriverState *bs = NULL, *src_bs = NULL; ++ bool image_opts = false; ++ int64_t granularity = 0; ++ bool add = false, merge = false; ++ QSIMPLEQ_HEAD(, ImgBitmapAction) actions; ++ ImgBitmapAction *act, *act_next; ++ const char *op; ++ ++ QSIMPLEQ_INIT(&actions); ++ ++ for (;;) { ++ static const struct option long_options[] = { ++ {"help", no_argument, 0, 'h'}, ++ {"object", required_argument, 0, OPTION_OBJECT}, ++ {"image-opts", no_argument, 0, OPTION_IMAGE_OPTS}, ++ {"add", no_argument, 0, OPTION_ADD}, ++ {"remove", no_argument, 0, OPTION_REMOVE}, ++ {"clear", no_argument, 0, OPTION_CLEAR}, ++ {"enable", no_argument, 0, OPTION_ENABLE}, ++ {"disable", no_argument, 0, OPTION_DISABLE}, ++ {"merge", required_argument, 0, OPTION_MERGE}, ++ {"granularity", required_argument, 0, 'g'}, ++ {"source-file", required_argument, 0, 'b'}, ++ {"source-format", required_argument, 0, 'F'}, ++ {0, 0, 0, 0} ++ }; ++ c = getopt_long(argc, argv, ":b:f:F:g:h", long_options, NULL); ++ if (c == -1) { ++ break; ++ } ++ ++ switch (c) { ++ case ':': ++ missing_argument(argv[optind - 1]); ++ break; ++ case '?': ++ unrecognized_option(argv[optind - 1]); ++ break; ++ case 'h': ++ help(); ++ break; ++ case 'b': ++ src_filename = optarg; ++ break; ++ case 'f': ++ fmt = optarg; ++ break; ++ case 'F': ++ src_fmt = optarg; ++ break; ++ case 'g': ++ granularity = cvtnum("granularity", optarg); ++ if (granularity < 0) { ++ return 1; ++ } ++ break; ++ case OPTION_ADD: ++ act = g_new0(ImgBitmapAction, 1); ++ act->act = BITMAP_ADD; ++ QSIMPLEQ_INSERT_TAIL(&actions, act, next); ++ add = true; ++ break; ++ case OPTION_REMOVE: ++ act = g_new0(ImgBitmapAction, 1); ++ act->act = BITMAP_REMOVE; ++ QSIMPLEQ_INSERT_TAIL(&actions, act, next); ++ break; ++ case OPTION_CLEAR: ++ act = g_new0(ImgBitmapAction, 1); ++ act->act = BITMAP_CLEAR; ++ QSIMPLEQ_INSERT_TAIL(&actions, act, next); ++ break; ++ case OPTION_ENABLE: ++ act = g_new0(ImgBitmapAction, 1); ++ act->act = BITMAP_ENABLE; ++ QSIMPLEQ_INSERT_TAIL(&actions, act, next); ++ break; ++ case OPTION_DISABLE: ++ act = g_new0(ImgBitmapAction, 1); ++ act->act = BITMAP_DISABLE; ++ QSIMPLEQ_INSERT_TAIL(&actions, act, next); ++ break; ++ case OPTION_MERGE: ++ act = g_new0(ImgBitmapAction, 1); ++ act->act = BITMAP_MERGE; ++ act->src = optarg; ++ QSIMPLEQ_INSERT_TAIL(&actions, act, next); ++ merge = true; ++ break; ++ case OPTION_OBJECT: ++ opts = qemu_opts_parse_noisily(&qemu_object_opts, optarg, true); ++ if (!opts) { ++ goto out; ++ } ++ break; ++ case OPTION_IMAGE_OPTS: ++ image_opts = true; ++ break; ++ } ++ } ++ ++ if (qemu_opts_foreach(&qemu_object_opts, ++ user_creatable_add_opts_foreach, ++ qemu_img_object_print_help, &error_fatal)) { ++ goto out; ++ } ++ ++ if (QSIMPLEQ_EMPTY(&actions)) { ++ error_report("Need at least one of --add, --remove, --clear, " ++ "--enable, --disable, or --merge"); ++ goto out; ++ } ++ ++ if (granularity && !add) { ++ error_report("granularity only supported with --add"); ++ goto out; ++ } ++ if (src_fmt && !src_filename) { ++ error_report("-F only supported with -b"); ++ goto out; ++ } ++ if (src_filename && !merge) { ++ error_report("Merge bitmap source file only supported with " ++ "--merge"); ++ goto out; ++ } ++ ++ if (optind != argc - 2) { ++ error_report("Expecting filename and bitmap name"); ++ goto out; ++ } ++ ++ filename = argv[optind]; ++ bitmap = argv[optind + 1]; ++ ++ blk = img_open(image_opts, filename, fmt, BDRV_O_RDWR, false, false, ++ false); ++ if (!blk) { ++ goto out; ++ } ++ bs = blk_bs(blk); ++ if (src_filename) { ++ src = img_open(false, src_filename, src_fmt, 0, false, false, false); ++ if (!src) { ++ goto out; ++ } ++ src_bs = blk_bs(src); ++ } else { ++ src_bs = bs; ++ } ++ ++ QSIMPLEQ_FOREACH_SAFE(act, &actions, next, act_next) { ++ switch (act->act) { ++ case BITMAP_ADD: ++ qmp_block_dirty_bitmap_add(bs->node_name, bitmap, ++ !!granularity, granularity, true, true, ++ false, false, &err); ++ op = "add"; ++ break; ++ case BITMAP_REMOVE: ++ qmp_block_dirty_bitmap_remove(bs->node_name, bitmap, &err); ++ op = "remove"; ++ break; ++ case BITMAP_CLEAR: ++ qmp_block_dirty_bitmap_clear(bs->node_name, bitmap, &err); ++ op = "clear"; ++ break; ++ case BITMAP_ENABLE: ++ qmp_block_dirty_bitmap_enable(bs->node_name, bitmap, &err); ++ op = "enable"; ++ break; ++ case BITMAP_DISABLE: ++ qmp_block_dirty_bitmap_disable(bs->node_name, bitmap, &err); ++ op = "disable"; ++ break; ++ case BITMAP_MERGE: { ++ BlockDirtyBitmapMergeSource *merge_src; ++ BlockDirtyBitmapMergeSourceList *list; ++ ++ merge_src = g_new0(BlockDirtyBitmapMergeSource, 1); ++ merge_src->type = QTYPE_QDICT; ++ merge_src->u.external.node = g_strdup(src_bs->node_name); ++ merge_src->u.external.name = g_strdup(act->src); ++ list = g_new0(BlockDirtyBitmapMergeSourceList, 1); ++ list->value = merge_src; ++ qmp_block_dirty_bitmap_merge(bs->node_name, bitmap, list, &err); ++ qapi_free_BlockDirtyBitmapMergeSourceList(list); ++ op = "merge"; ++ break; ++ } ++ default: ++ g_assert_not_reached(); ++ } ++ ++ if (err) { ++ error_reportf_err(err, "Operation %s on bitmap %s failed: ", ++ op, bitmap); ++ goto out; ++ } ++ g_free(act); ++ } ++ ++ ret = 0; ++ ++ out: ++ blk_unref(src); ++ blk_unref(blk); ++ qemu_opts_del(opts); ++ return ret; ++} ++ + #define C_BS 01 + #define C_COUNT 02 + #define C_IF 04 +-- +2.23.0 + diff --git a/qemu-img-Add-start-offset-and-max-length-to-map.patch b/qemu-img-Add-start-offset-and-max-length-to-map.patch new file mode 100644 index 0000000000000000000000000000000000000000..796c97731cc7d1b4da6b061702af305bef767aa9 --- /dev/null +++ b/qemu-img-Add-start-offset-and-max-length-to-map.patch @@ -0,0 +1,115 @@ +From c0469496b32910a6a092d5b614efbf4088b13a29 Mon Sep 17 00:00:00 2001 +From: Eyal Moscovici +Date: Wed, 13 May 2020 16:36:29 +0300 +Subject: [PATCH 519/709] qemu-img: Add --start-offset and --max-length to map + +The mapping operation of large disks especially ones stored over a +long chain of QCOW2 files can take a long time to finish. +Additionally when mapping fails there was no way recover by +restarting the mapping from the failed location. + +The new options, --start-offset and --max-length allows the user to +divide these type of map operations into shorter independent tasks. + +Reviewed-by: Eric Blake +Acked-by: Mark Kanda +Co-developed-by: Yoav Elnekave +Signed-off-by: Yoav Elnekave +Signed-off-by: Eyal Moscovici +Message-Id: <20200513133629.18508-5-eyal.moscovici@oracle.com> +Signed-off-by: Eric Blake +--- + docs/tools/qemu-img.rst | 2 +- + qemu-img-cmds.hx | 4 ++-- + qemu-img.c | 22 +++++++++++++++++++++- + 3 files changed, 24 insertions(+), 4 deletions(-) + +diff --git a/docs/tools/qemu-img.rst b/docs/tools/qemu-img.rst +index 0080f83a76..f4ffe528ea 100644 +--- a/docs/tools/qemu-img.rst ++++ b/docs/tools/qemu-img.rst +@@ -519,7 +519,7 @@ Command description: + ``ImageInfoSpecific*`` QAPI object (e.g. ``ImageInfoSpecificQCow2`` + for qcow2 images). + +-.. option:: map [--object OBJECTDEF] [--image-opts] [-f FMT] [--output=OFMT] [-U] FILENAME ++.. option:: map [--object OBJECTDEF] [--image-opts] [-f FMT] [--start-offset=OFFSET] [--max-length=LEN] [--output=OFMT] [-U] FILENAME + + Dump the metadata of image *FILENAME* and its backing file chain. + In particular, this commands dumps the allocation state of every sector +diff --git a/qemu-img-cmds.hx b/qemu-img-cmds.hx +index c9c54de1df..35f832816f 100644 +--- a/qemu-img-cmds.hx ++++ b/qemu-img-cmds.hx +@@ -63,9 +63,9 @@ SRST + ERST + + DEF("map", img_map, +- "map [--object objectdef] [--image-opts] [-f fmt] [--output=ofmt] [-U] filename") ++ "map [--object objectdef] [--image-opts] [-f fmt] [--start-offset=offset] [--max-length=len] [--output=ofmt] [-U] filename") + SRST +-.. option:: map [--object OBJECTDEF] [--image-opts] [-f FMT] [--output=OFMT] [-U] FILENAME ++.. option:: map [--object OBJECTDEF] [--image-opts] [-f FMT] [--start-offset=OFFSET] [--max-length=LEN] [--output=OFMT] [-U] FILENAME + ERST + + DEF("measure", img_measure, +diff --git a/qemu-img.c b/qemu-img.c +index 4aa9414aba..947bf8b34b 100644 +--- a/qemu-img.c ++++ b/qemu-img.c +@@ -3009,6 +3009,8 @@ static int img_map(int argc, char **argv) + int ret = 0; + bool image_opts = false; + bool force_share = false; ++ int64_t start_offset = 0; ++ int64_t max_length = -1; + + fmt = NULL; + output = NULL; +@@ -3021,9 +3023,11 @@ static int img_map(int argc, char **argv) + {"object", required_argument, 0, OPTION_OBJECT}, + {"image-opts", no_argument, 0, OPTION_IMAGE_OPTS}, + {"force-share", no_argument, 0, 'U'}, ++ {"start-offset", required_argument, 0, 's'}, ++ {"max-length", required_argument, 0, 'l'}, + {0, 0, 0, 0} + }; +- c = getopt_long(argc, argv, ":f:hU", ++ c = getopt_long(argc, argv, ":f:s:l:hU", + long_options, &option_index); + if (c == -1) { + break; +@@ -3047,6 +3051,18 @@ static int img_map(int argc, char **argv) + case OPTION_OUTPUT: + output = optarg; + break; ++ case 's': ++ start_offset = cvtnum("start offset", optarg); ++ if (start_offset < 0) { ++ return 1; ++ } ++ break; ++ case 'l': ++ max_length = cvtnum("max length", optarg); ++ if (max_length < 0) { ++ return 1; ++ } ++ break; + case OPTION_OBJECT: { + QemuOpts *opts; + opts = qemu_opts_parse_noisily(&qemu_object_opts, +@@ -3097,7 +3113,11 @@ static int img_map(int argc, char **argv) + error_report("Failed to get size for '%s'", filename); + return 1; + } ++ if (max_length != -1) { ++ length = MIN(start_offset + max_length, length); ++ } + ++ curr.start = start_offset; + while (curr.start + curr.length < length) { + int64_t offset = curr.start + curr.length; + int64_t n; +-- +2.23.0 + diff --git a/qemu-img-Factor-out-accumulate_options-helper.patch b/qemu-img-Factor-out-accumulate_options-helper.patch new file mode 100644 index 0000000000000000000000000000000000000000..66e859294aad191916752d6124fed0092445c6d2 --- /dev/null +++ b/qemu-img-Factor-out-accumulate_options-helper.patch @@ -0,0 +1,123 @@ +From 6d2b5cbafb8fb4bb3563cbf698b3a0903a993d7a Mon Sep 17 00:00:00 2001 +From: Markus Armbruster +Date: Wed, 15 Apr 2020 09:49:25 +0200 +Subject: [PATCH 011/709] qemu-img: Factor out accumulate_options() helper + +Signed-off-by: Markus Armbruster +Reviewed-by: Eric Blake +Reviewed-by: Kevin Wolf +Message-Id: <20200415074927.19897-8-armbru@redhat.com> +--- + qemu-img.c | 59 +++++++++++++++++++++--------------------------------- + 1 file changed, 23 insertions(+), 36 deletions(-) + +diff --git a/qemu-img.c b/qemu-img.c +index 821cbf610e..d36b21b758 100644 +--- a/qemu-img.c ++++ b/qemu-img.c +@@ -223,6 +223,25 @@ static bool qemu_img_object_print_help(const char *type, QemuOpts *opts) + return true; + } + ++static int accumulate_options(char **options, char *optarg) ++{ ++ char *new_options; ++ ++ if (!is_valid_option_list(optarg)) { ++ error_report("Invalid option list: %s", optarg); ++ return -1; ++ } ++ ++ if (!*options) { ++ *options = g_strdup(optarg); ++ } else { ++ new_options = g_strdup_printf("%s,%s", *options, optarg); ++ g_free(*options); ++ *options = new_options; ++ } ++ return 0; ++} ++ + static QemuOptsList qemu_source_opts = { + .name = "source", + .implied_opt_name = "file", +@@ -482,17 +501,9 @@ static int img_create(int argc, char **argv) + fmt = optarg; + break; + case 'o': +- if (!is_valid_option_list(optarg)) { +- error_report("Invalid option list: %s", optarg); ++ if (accumulate_options(&options, optarg) < 0) { + goto fail; + } +- if (!options) { +- options = g_strdup(optarg); +- } else { +- char *old_options = options; +- options = g_strdup_printf("%s,%s", options, optarg); +- g_free(old_options); +- } + break; + case 'q': + quiet = true; +@@ -2127,17 +2138,9 @@ static int img_convert(int argc, char **argv) + s.compressed = true; + break; + case 'o': +- if (!is_valid_option_list(optarg)) { +- error_report("Invalid option list: %s", optarg); ++ if (accumulate_options(&options, optarg) < 0) { + goto fail_getopt; + } +- if (!options) { +- options = g_strdup(optarg); +- } else { +- char *old_options = options; +- options = g_strdup_printf("%s,%s", options, optarg); +- g_free(old_options); +- } + break; + case 'l': + if (strstart(optarg, SNAPSHOT_OPT_BASE, NULL)) { +@@ -3953,18 +3956,10 @@ static int img_amend(int argc, char **argv) + help(); + break; + case 'o': +- if (!is_valid_option_list(optarg)) { +- error_report("Invalid option list: %s", optarg); ++ if (accumulate_options(&options, optarg) < 0) { + ret = -1; + goto out_no_progress; + } +- if (!options) { +- options = g_strdup(optarg); +- } else { +- char *old_options = options; +- options = g_strdup_printf("%s,%s", options, optarg); +- g_free(old_options); +- } + break; + case 'f': + fmt = optarg; +@@ -4855,17 +4850,9 @@ static int img_measure(int argc, char **argv) + out_fmt = optarg; + break; + case 'o': +- if (!is_valid_option_list(optarg)) { +- error_report("Invalid option list: %s", optarg); ++ if (accumulate_options(&options, optarg) < 0) { + goto out; + } +- if (!options) { +- options = g_strdup(optarg); +- } else { +- char *old_options = options; +- options = g_strdup_printf("%s,%s", options, optarg); +- g_free(old_options); +- } + break; + case 'l': + if (strstart(optarg, SNAPSHOT_OPT_BASE, NULL)) { +-- +2.23.0 + diff --git a/qemu-img-Fix-stale-comments-on-doc-location.patch b/qemu-img-Fix-stale-comments-on-doc-location.patch new file mode 100644 index 0000000000000000000000000000000000000000..70a2df4af141047ac892e78b4cca46296dce038a --- /dev/null +++ b/qemu-img-Fix-stale-comments-on-doc-location.patch @@ -0,0 +1,45 @@ +From 0562adf51712c3c0354d68e745afb7e6705668f1 Mon Sep 17 00:00:00 2001 +From: Eric Blake +Date: Tue, 12 May 2020 20:16:41 -0500 +Subject: [PATCH 588/709] qemu-img: Fix stale comments on doc location + +Missed in commit e13c59fa. + +Signed-off-by: Eric Blake +Reviewed-by: Max Reitz +Message-Id: <20200513011648.166876-3-eblake@redhat.com> +Reviewed-by: Vladimir Sementsov-Ogievskiy +--- + qemu-img-cmds.hx | 2 +- + qemu-img.c | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/qemu-img-cmds.hx b/qemu-img-cmds.hx +index 35f832816f..cfe8f37587 100644 +--- a/qemu-img-cmds.hx ++++ b/qemu-img-cmds.hx +@@ -7,7 +7,7 @@ HXCOMM command structures and help message. + HXCOMM HXCOMM can be used for comments, discarded from both rST and C + + HXCOMM When amending the rST sections, please remember to copy the usage +-HXCOMM over to the per-command sections in qemu-img.texi. ++HXCOMM over to the per-command sections in docs/tools/qemu-img.rst. + + DEF("amend", img_amend, + "amend [--object objectdef] [--image-opts] [-p] [-q] [-f fmt] [-t cache] -o options filename") +diff --git a/qemu-img.c b/qemu-img.c +index 2a9186139d..4740de082f 100644 +--- a/qemu-img.c ++++ b/qemu-img.c +@@ -108,7 +108,7 @@ static void QEMU_NORETURN unrecognized_option(const char *option) + error_exit("unrecognized option '%s'", option); + } + +-/* Please keep in synch with qemu-img.texi */ ++/* Please keep in synch with docs/tools/qemu-img.rst */ + static void QEMU_NORETURN help(void) + { + const char *help_msg = +-- +2.23.0 + diff --git a/qemu-img-Move-is_valid_option_list-to-qemu-img.c-and.patch b/qemu-img-Move-is_valid_option_list-to-qemu-img.c-and.patch new file mode 100644 index 0000000000000000000000000000000000000000..ee99f9ae6095dc5ea14c0502066077febac3df1f --- /dev/null +++ b/qemu-img-Move-is_valid_option_list-to-qemu-img.c-and.patch @@ -0,0 +1,114 @@ +From 80c710cb06ff40b45de033e4352528b3adcd2de9 Mon Sep 17 00:00:00 2001 +From: Markus Armbruster +Date: Wed, 15 Apr 2020 09:49:26 +0200 +Subject: [PATCH 012/709] qemu-img: Move is_valid_option_list() to qemu-img.c + and rewrite + +is_valid_option_list()'s purpose is ensuring qemu-img.c's can safely +join multiple parameter strings separated by ',' like this: + + g_strdup_printf("%s,%s", params1, params2); + +How it does that is anything but obvious. A close reading of the code +reveals that it fails exactly when its argument starts with ',' or +ends with an odd number of ','. Makes sense, actually, because when +the argument starts with ',', a separating ',' preceding it would get +escaped, and when it ends with an odd number of ',', a separating ',' +following it would get escaped. + +Move it to qemu-img.c and rewrite it the obvious way. + +Signed-off-by: Markus Armbruster +Reviewed-by: Eric Blake +Message-Id: <20200415074927.19897-9-armbru@redhat.com> +--- + include/qemu/option.h | 1 - + qemu-img.c | 26 ++++++++++++++++++++++++++ + util/qemu-option.c | 22 ---------------------- + 3 files changed, 26 insertions(+), 23 deletions(-) + +diff --git a/include/qemu/option.h b/include/qemu/option.h +index 844587cab3..eb4097889d 100644 +--- a/include/qemu/option.h ++++ b/include/qemu/option.h +@@ -33,7 +33,6 @@ const char *get_opt_value(const char *p, char **value); + void parse_option_size(const char *name, const char *value, + uint64_t *ret, Error **errp); + bool has_help_option(const char *param); +-bool is_valid_option_list(const char *param); + + enum QemuOptType { + QEMU_OPT_STRING = 0, /* no parsing (use string as-is) */ +diff --git a/qemu-img.c b/qemu-img.c +index d36b21b758..cc51db7ed4 100644 +--- a/qemu-img.c ++++ b/qemu-img.c +@@ -223,6 +223,32 @@ static bool qemu_img_object_print_help(const char *type, QemuOpts *opts) + return true; + } + ++/* ++ * Is @optarg safe for accumulate_options()? ++ * It is when multiple of them can be joined together separated by ','. ++ * To make that work, @optarg must not start with ',' (or else a ++ * separating ',' preceding it gets escaped), and it must not end with ++ * an odd number of ',' (or else a separating ',' following it gets ++ * escaped). ++ */ ++static bool is_valid_option_list(const char *optarg) ++{ ++ size_t len = strlen(optarg); ++ size_t i; ++ ++ if (optarg[0] == ',') { ++ return false; ++ } ++ ++ for (i = len; i > 0 && optarg[i - 1] == ','; i--) { ++ } ++ if ((len - i) % 2) { ++ return false; ++ } ++ ++ return true; ++} ++ + static int accumulate_options(char **options, char *optarg) + { + char *new_options; +diff --git a/util/qemu-option.c b/util/qemu-option.c +index 2d0d24ee27..9542988183 100644 +--- a/util/qemu-option.c ++++ b/util/qemu-option.c +@@ -165,28 +165,6 @@ void parse_option_size(const char *name, const char *value, + *ret = size; + } + +-bool is_valid_option_list(const char *p) +-{ +- char *value = NULL; +- bool result = false; +- +- while (*p) { +- p = get_opt_value(p, &value); +- if ((*p && !*++p) || +- (!*value || *value == ',')) { +- goto out; +- } +- +- g_free(value); +- value = NULL; +- } +- +- result = true; +-out: +- g_free(value); +- return result; +-} +- + static const char *opt_type_to_string(enum QemuOptType type) + { + switch (type) { +-- +2.23.0 + diff --git a/qemu-img-Reject-broken-o.patch b/qemu-img-Reject-broken-o.patch new file mode 100644 index 0000000000000000000000000000000000000000..872dd0bb1bd2531e240be2f0070c8e4790d0f61d --- /dev/null +++ b/qemu-img-Reject-broken-o.patch @@ -0,0 +1,66 @@ +From f62514b3def5fb2acbef64d0e053c0c31fa45aff Mon Sep 17 00:00:00 2001 +From: Markus Armbruster +Date: Wed, 15 Apr 2020 09:49:27 +0200 +Subject: [PATCH 013/709] qemu-img: Reject broken -o "" + +qemu-img create, convert, amend, and measure use accumulate_options() +to merge multiple -o options. This is broken for -o "": + + $ qemu-img create -f qcow2 -o backing_file=a -o "" -o backing_fmt=raw,size=1M new.qcow2 + qemu-img: warning: Could not verify backing image. This may become an error in future versions. + Could not open 'a,backing_fmt=raw': No such file or directory + Formatting 'new.qcow2', fmt=qcow2 size=1048576 backing_file=a,,backing_fmt=raw cluster_size=65536 lazy_refcounts=off refcount_bits=16 + $ qemu-img info new.qcow2 + image: new.qcow2 + file format: qcow2 + virtual size: 1 MiB (1048576 bytes) + disk size: 196 KiB + cluster_size: 65536 +--> backing file: a,backing_fmt=raw + Format specific information: + compat: 1.1 + lazy refcounts: false + refcount bits: 16 + corrupt: false + +Merging these three -o the obvious way is wrong, because it results in +an unwanted ',' escape: + + backing_file=a,,backing_fmt=raw,size=1M + ~~ + +We could silently drop -o "", but Kevin asked me to reject it instead. + +Signed-off-by: Markus Armbruster +Message-Id: <20200415074927.19897-10-armbru@redhat.com> +Reviewed-by: Eric Blake +--- + qemu-img.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/qemu-img.c b/qemu-img.c +index cc51db7ed4..a2369766f0 100644 +--- a/qemu-img.c ++++ b/qemu-img.c +@@ -229,14 +229,16 @@ static bool qemu_img_object_print_help(const char *type, QemuOpts *opts) + * To make that work, @optarg must not start with ',' (or else a + * separating ',' preceding it gets escaped), and it must not end with + * an odd number of ',' (or else a separating ',' following it gets +- * escaped). ++ * escaped), or be empty (or else a separating ',' preceding it can ++ * escape a separating ',' following it). ++ * + */ + static bool is_valid_option_list(const char *optarg) + { + size_t len = strlen(optarg); + size_t i; + +- if (optarg[0] == ',') { ++ if (!optarg[0] || optarg[0] == ',') { + return false; + } + +-- +2.23.0 + diff --git a/qemu-img-refactor-dump_map_entry-JSON-format-output.patch b/qemu-img-refactor-dump_map_entry-JSON-format-output.patch new file mode 100644 index 0000000000000000000000000000000000000000..0a6185de6dd504916de803e5e2c78108cea88071 --- /dev/null +++ b/qemu-img-refactor-dump_map_entry-JSON-format-output.patch @@ -0,0 +1,67 @@ +From e46c0b18cfd02195a0d527ca73f3ed9f3ce5eacb Mon Sep 17 00:00:00 2001 +From: Eyal Moscovici +Date: Wed, 13 May 2020 16:36:28 +0300 +Subject: [PATCH 518/709] qemu-img: refactor dump_map_entry JSON format output + +Previously dump_map_entry identified whether we need to start a new JSON +array based on whether start address == 0. In this refactor we remove +this assumption as in following patches we will allow map to start from +an arbitrary position. + +Reviewed-by: Eric Blake +Acked-by: Mark Kanda +Signed-off-by: Eyal Moscovici +Message-Id: <20200513133629.18508-4-eyal.moscovici@oracle.com> +Signed-off-by: Eric Blake +--- + qemu-img.c | 12 ++++++++---- + 1 file changed, 8 insertions(+), 4 deletions(-) + +diff --git a/qemu-img.c b/qemu-img.c +index c88f412333..4aa9414aba 100644 +--- a/qemu-img.c ++++ b/qemu-img.c +@@ -2902,9 +2902,8 @@ static int dump_map_entry(OutputFormat output_format, MapEntry *e, + } + break; + case OFORMAT_JSON: +- printf("%s{ \"start\": %"PRId64", \"length\": %"PRId64"," ++ printf("{ \"start\": %"PRId64", \"length\": %"PRId64"," + " \"depth\": %"PRId64", \"zero\": %s, \"data\": %s", +- (e->start == 0 ? "[" : ",\n"), + e->start, e->length, e->depth, + e->zero ? "true" : "false", + e->data ? "true" : "false"); +@@ -2913,8 +2912,8 @@ static int dump_map_entry(OutputFormat output_format, MapEntry *e, + } + putchar('}'); + +- if (!next) { +- printf("]\n"); ++ if (next) { ++ puts(","); + } + break; + } +@@ -3089,6 +3088,8 @@ static int img_map(int argc, char **argv) + + if (output_format == OFORMAT_HUMAN) { + printf("%-16s%-16s%-16s%s\n", "Offset", "Length", "Mapped to", "File"); ++ } else if (output_format == OFORMAT_JSON) { ++ putchar('['); + } + + length = blk_getlength(blk); +@@ -3125,6 +3126,9 @@ static int img_map(int argc, char **argv) + } + + ret = dump_map_entry(output_format, &curr, NULL); ++ if (output_format == OFORMAT_JSON) { ++ puts("]"); ++ } + + out: + blk_unref(blk); +-- +2.23.0 + diff --git a/qemu-img-validate-image-length-in-img_map.patch b/qemu-img-validate-image-length-in-img_map.patch new file mode 100644 index 0000000000000000000000000000000000000000..5d2a762a0aae6eb5e44b6d48eb12c84af2a59dfd --- /dev/null +++ b/qemu-img-validate-image-length-in-img_map.patch @@ -0,0 +1,37 @@ +From 8f282e83edd3d1b4ea6e9258f5a4081b490c33cc Mon Sep 17 00:00:00 2001 +From: Eyal Moscovici +Date: Wed, 13 May 2020 16:36:27 +0300 +Subject: [PATCH 517/709] qemu-img: validate image length in img_map + +The code handles this case correctly: we merely skip the loop. However it +is probably best to return an explicit error. + +Reviewed-by: Eric Blake +Acked-by: Mark Kanda +Signed-off-by: Eyal Moscovici +Message-Id: <20200513133629.18508-3-eyal.moscovici@oracle.com> +[eblake: commit message tweak] +Signed-off-by: Eric Blake +--- + qemu-img.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/qemu-img.c b/qemu-img.c +index 5d824fc15f..c88f412333 100644 +--- a/qemu-img.c ++++ b/qemu-img.c +@@ -3092,6 +3092,11 @@ static int img_map(int argc, char **argv) + } + + length = blk_getlength(blk); ++ if (length < 0) { ++ error_report("Failed to get size for '%s'", filename); ++ return 1; ++ } ++ + while (curr.start + curr.length < length) { + int64_t offset = curr.start + curr.length; + int64_t n; +-- +2.23.0 + diff --git a/qemu-iotests-allow-qcow2-external-discarded-clusters.patch b/qemu-iotests-allow-qcow2-external-discarded-clusters.patch new file mode 100644 index 0000000000000000000000000000000000000000..e497c9e190e1e82b7fa8798b3fded82404956e0d --- /dev/null +++ b/qemu-iotests-allow-qcow2-external-discarded-clusters.patch @@ -0,0 +1,84 @@ +From 3fb61087074474b088fee23bb81ffd258cb9cb2a Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Thu, 9 Apr 2020 15:10:06 -0400 +Subject: [PATCH 125/709] qemu-iotests: allow qcow2 external discarded clusters + to contain stale data + +Test 244 checks the expected behavior of qcow2 external data files +with respect to zero and discarded clusters. Filesystems however +are free to ignore discard requests, and this seems to be the +case for overlayfs. Relax the tests to skip checks on the +external data file for discarded areas, which implies not using +qemu-img compare in the data_file_raw=on case. + +This fixes docker tests on RHEL8. + +Cc: Kevin Wolf +Cc: qemu-block@nongnu.org +Signed-off-by: Paolo Bonzini +Message-Id: <20200409191006.24429-1-pbonzini@redhat.com> +Signed-off-by: Kevin Wolf +--- + tests/qemu-iotests/244 | 10 ++++++++-- + tests/qemu-iotests/244.out | 9 ++++++--- + 2 files changed, 14 insertions(+), 5 deletions(-) + +diff --git a/tests/qemu-iotests/244 b/tests/qemu-iotests/244 +index 2ec1815e6f..efe3c0428b 100755 +--- a/tests/qemu-iotests/244 ++++ b/tests/qemu-iotests/244 +@@ -143,7 +143,6 @@ $QEMU_IO -c 'read -P 0 0 1M' \ + echo + $QEMU_IO -c 'read -P 0 0 1M' \ + -c 'read -P 0x11 1M 1M' \ +- -c 'read -P 0 2M 2M' \ + -c 'read -P 0x11 4M 1M' \ + -c 'read -P 0 5M 1M' \ + -f raw "$TEST_IMG.data" | +@@ -180,8 +179,15 @@ $QEMU_IO -c 'read -P 0 0 1M' \ + -f $IMGFMT "$TEST_IMG" | + _filter_qemu_io + ++# Discarded clusters are only marked as such in the qcow2 metadata, but ++# they can contain stale data in the external data file. Instead, zero ++# clusters must be zeroed in the external data file too. + echo +-$QEMU_IMG compare "$TEST_IMG" "$TEST_IMG.data" ++$QEMU_IO -c 'read -P 0 0 1M' \ ++ -c 'read -P 0x11 1M 1M' \ ++ -c 'read -P 0 3M 3M' \ ++ -f raw "$TEST_IMG".data | ++ _filter_qemu_io + + echo -n "qcow2 file size after I/O: " + du -b $TEST_IMG | cut -f1 +diff --git a/tests/qemu-iotests/244.out b/tests/qemu-iotests/244.out +index 56329deb4b..dbab7359a9 100644 +--- a/tests/qemu-iotests/244.out ++++ b/tests/qemu-iotests/244.out +@@ -74,8 +74,6 @@ read 1048576/1048576 bytes at offset 0 + 1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + read 1048576/1048576 bytes at offset 1048576 + 1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +-read 2097152/2097152 bytes at offset 2097152 +-2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + read 1048576/1048576 bytes at offset 4194304 + 1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + read 1048576/1048576 bytes at offset 5242880 +@@ -108,7 +106,12 @@ read 1048576/1048576 bytes at offset 1048576 + read 4194304/4194304 bytes at offset 2097152 + 4 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +-Images are identical. ++read 1048576/1048576 bytes at offset 0 ++1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++read 1048576/1048576 bytes at offset 1048576 ++1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++read 3145728/3145728 bytes at offset 3145728 ++3 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + qcow2 file size after I/O: 327680 + + === bdrv_co_block_status test for file and offset=0 === +-- +2.23.0 + diff --git a/qemu-nbd-Close-inherited-stderr.patch b/qemu-nbd-Close-inherited-stderr.patch new file mode 100644 index 0000000000000000000000000000000000000000..ef04a2fb3cd9abf7c64f88c3983be4eb07c1f02d --- /dev/null +++ b/qemu-nbd-Close-inherited-stderr.patch @@ -0,0 +1,39 @@ +From 0eaf453ebf6788885fbb5d40426b154ef8805407 Mon Sep 17 00:00:00 2001 +From: Raphael Pour +Date: Fri, 15 May 2020 08:36:07 +0200 +Subject: [PATCH 515/709] qemu-nbd: Close inherited stderr + +Close inherited stderr of the parent if fork_process is false. +Otherwise no one will close it. (introduced by e6df58a5) + +This only affected 'qemu-nbd -c /dev/nbd0'. + +Signed-off-by: Raphael Pour +Message-Id: +Reviewed-by: Eric Blake +[eblake: Enhance commit message] +Signed-off-by: Eric Blake +--- + qemu-nbd.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/qemu-nbd.c b/qemu-nbd.c +index 4aa005004e..306e44fb0a 100644 +--- a/qemu-nbd.c ++++ b/qemu-nbd.c +@@ -916,7 +916,11 @@ int main(int argc, char **argv) + } else if (pid == 0) { + close(stderr_fd[0]); + +- old_stderr = dup(STDERR_FILENO); ++ /* Remember parent's stderr if we will be restoring it. */ ++ if (fork_process) { ++ old_stderr = dup(STDERR_FILENO); ++ } ++ + ret = qemu_daemon(1, 0); + + /* Temporarily redirect stderr to the parent's pipe... */ +-- +2.23.0 + diff --git a/qemu-option-Avoid-has_help_option-in-qemu_opts_parse.patch b/qemu-option-Avoid-has_help_option-in-qemu_opts_parse.patch new file mode 100644 index 0000000000000000000000000000000000000000..5c31f1d90beeadf7eb0edc8b5c8bde6d29ee15bd --- /dev/null +++ b/qemu-option-Avoid-has_help_option-in-qemu_opts_parse.patch @@ -0,0 +1,97 @@ +From 56a9efa199a603b77e7f2bd0e84e11e897bf7473 Mon Sep 17 00:00:00 2001 +From: Markus Armbruster +Date: Wed, 15 Apr 2020 09:49:24 +0200 +Subject: [PATCH 010/709] qemu-option: Avoid has_help_option() in + qemu_opts_parse_noisily() + +When opts_parse() sets @invalidp to true, qemu_opts_parse_noisily() +uses has_help_option() to decide whether to print help. This parses +the input string a second time. + +Easy to avoid: replace @invalidp by @help_wanted. + +Signed-off-by: Markus Armbruster +Reviewed-by: Eric Blake +Message-Id: <20200415074927.19897-7-armbru@redhat.com> +--- + util/qemu-option.c | 20 ++++++++++---------- + 1 file changed, 10 insertions(+), 10 deletions(-) + +diff --git a/util/qemu-option.c b/util/qemu-option.c +index 0abf26b61f..2d0d24ee27 100644 +--- a/util/qemu-option.c ++++ b/util/qemu-option.c +@@ -519,7 +519,7 @@ int qemu_opt_unset(QemuOpts *opts, const char *name) + } + + static void opt_set(QemuOpts *opts, const char *name, char *value, +- bool prepend, bool *invalidp, Error **errp) ++ bool prepend, bool *help_wanted, Error **errp) + { + QemuOpt *opt; + const QemuOptDesc *desc; +@@ -529,8 +529,8 @@ static void opt_set(QemuOpts *opts, const char *name, char *value, + if (!desc && !opts_accepts_any(opts)) { + g_free(value); + error_setg(errp, QERR_INVALID_PARAMETER, name); +- if (invalidp) { +- *invalidp = true; ++ if (help_wanted && is_help_option(name)) { ++ *help_wanted = true; + } + return; + } +@@ -827,7 +827,7 @@ static const char *get_opt_name_value(const char *params, + + static void opts_do_parse(QemuOpts *opts, const char *params, + const char *firstname, bool prepend, +- bool *invalidp, Error **errp) ++ bool *help_wanted, Error **errp) + { + Error *local_err = NULL; + char *option, *value; +@@ -843,7 +843,7 @@ static void opts_do_parse(QemuOpts *opts, const char *params, + continue; + } + +- opt_set(opts, option, value, prepend, invalidp, &local_err); ++ opt_set(opts, option, value, prepend, help_wanted, &local_err); + g_free(option); + if (local_err) { + error_propagate(errp, local_err); +@@ -903,7 +903,7 @@ void qemu_opts_do_parse(QemuOpts *opts, const char *params, + + static QemuOpts *opts_parse(QemuOptsList *list, const char *params, + bool permit_abbrev, bool defaults, +- bool *invalidp, Error **errp) ++ bool *help_wanted, Error **errp) + { + const char *firstname; + char *id = opts_parse_id(params); +@@ -928,7 +928,7 @@ static QemuOpts *opts_parse(QemuOptsList *list, const char *params, + return NULL; + } + +- opts_do_parse(opts, params, firstname, defaults, invalidp, &local_err); ++ opts_do_parse(opts, params, firstname, defaults, help_wanted, &local_err); + if (local_err) { + error_propagate(errp, local_err); + qemu_opts_del(opts); +@@ -964,11 +964,11 @@ QemuOpts *qemu_opts_parse_noisily(QemuOptsList *list, const char *params, + { + Error *err = NULL; + QemuOpts *opts; +- bool invalidp = false; ++ bool help_wanted = false; + +- opts = opts_parse(list, params, permit_abbrev, false, &invalidp, &err); ++ opts = opts_parse(list, params, permit_abbrev, false, &help_wanted, &err); + if (err) { +- if (invalidp && has_help_option(params)) { ++ if (help_wanted) { + qemu_opts_print_help(list, true); + error_free(err); + } else { +-- +2.23.0 + diff --git a/qemu-option-Clean-up-after-the-previous-commit.patch b/qemu-option-Clean-up-after-the-previous-commit.patch new file mode 100644 index 0000000000000000000000000000000000000000..977a5b35368b64f2970526a9fbfdb5c6d1fcd7d7 --- /dev/null +++ b/qemu-option-Clean-up-after-the-previous-commit.patch @@ -0,0 +1,112 @@ +From 2500f6f30b547b9c301dfe7571a16b028f7b848d Mon Sep 17 00:00:00 2001 +From: Markus Armbruster +Date: Wed, 15 Apr 2020 10:30:48 +0200 +Subject: [PATCH 072/709] qemu-option: Clean up after the previous commit + +Signed-off-by: Markus Armbruster +Message-Id: <20200415083048.14339-6-armbru@redhat.com> +Reviewed-by: Eric Blake +--- + util/qemu-option.c | 43 +++++++++++++++---------------------------- + 1 file changed, 15 insertions(+), 28 deletions(-) + +diff --git a/util/qemu-option.c b/util/qemu-option.c +index 2784757ef5..0ebfd97a98 100644 +--- a/util/qemu-option.c ++++ b/util/qemu-option.c +@@ -965,18 +965,16 @@ void qemu_opts_set_defaults(QemuOptsList *list, const char *params, + assert(opts); + } + +-typedef struct OptsFromQDictState { +- QemuOpts *opts; +- Error **errp; +-} OptsFromQDictState; +- +-static void qemu_opts_from_qdict_1(const char *key, QObject *obj, void *opaque) ++static void qemu_opts_from_qdict_entry(QemuOpts *opts, ++ const QDictEntry *entry, ++ Error **errp) + { +- OptsFromQDictState *state = opaque; ++ const char *key = qdict_entry_key(entry); ++ QObject *obj = qdict_entry_value(entry); + char buf[32], *tmp = NULL; + const char *value; + +- if (!strcmp(key, "id") || *state->errp) { ++ if (!strcmp(key, "id")) { + return; + } + +@@ -997,7 +995,7 @@ static void qemu_opts_from_qdict_1(const char *key, QObject *obj, void *opaque) + return; + } + +- qemu_opt_set(state->opts, key, value, state->errp); ++ qemu_opt_set(opts, key, value, errp); + g_free(tmp); + } + +@@ -1010,7 +1008,6 @@ static void qemu_opts_from_qdict_1(const char *key, QObject *obj, void *opaque) + QemuOpts *qemu_opts_from_qdict(QemuOptsList *list, const QDict *qdict, + Error **errp) + { +- OptsFromQDictState state; + Error *local_err = NULL; + QemuOpts *opts; + const QDictEntry *entry; +@@ -1024,20 +1021,15 @@ QemuOpts *qemu_opts_from_qdict(QemuOptsList *list, const QDict *qdict, + + assert(opts != NULL); + +- state.errp = &local_err; +- state.opts = opts; +- + for (entry = qdict_first(qdict); + entry; + entry = qdict_next(qdict, entry)) { +- qemu_opts_from_qdict_1(qdict_entry_key(entry), +- qdict_entry_value(entry), +- &state); +- } +- if (local_err) { +- error_propagate(errp, local_err); +- qemu_opts_del(opts); +- return NULL; ++ qemu_opts_from_qdict_entry(opts, entry, &local_err); ++ if (local_err) { ++ error_propagate(errp, local_err); ++ qemu_opts_del(opts); ++ return NULL; ++ } + } + + return opts; +@@ -1056,21 +1048,16 @@ void qemu_opts_absorb_qdict(QemuOpts *opts, QDict *qdict, Error **errp) + + while (entry != NULL) { + Error *local_err = NULL; +- OptsFromQDictState state = { +- .errp = &local_err, +- .opts = opts, +- }; + + next = qdict_next(qdict, entry); + + if (find_desc_by_name(opts->list->desc, entry->key)) { +- qemu_opts_from_qdict_1(entry->key, entry->value, &state); ++ qemu_opts_from_qdict_entry(opts, entry, &local_err); + if (local_err) { + error_propagate(errp, local_err); + return; +- } else { +- qdict_del(qdict, entry->key); + } ++ qdict_del(qdict, entry->key); + } + + entry = next; +-- +2.23.0 + diff --git a/qemu-option-Fix-has_help_option-s-sloppy-parsing.patch b/qemu-option-Fix-has_help_option-s-sloppy-parsing.patch new file mode 100644 index 0000000000000000000000000000000000000000..70d424d6339de212f3fddcbe2dffc20a0cda76ed --- /dev/null +++ b/qemu-option-Fix-has_help_option-s-sloppy-parsing.patch @@ -0,0 +1,92 @@ +From 80a94855737622436a9b5cd25315b9c80d7e3ffa Mon Sep 17 00:00:00 2001 +From: Markus Armbruster +Date: Wed, 15 Apr 2020 09:49:22 +0200 +Subject: [PATCH 008/709] qemu-option: Fix has_help_option()'s sloppy parsing + +has_help_option() uses its own parser. It's inconsistent with +qemu_opts_parse(), as demonstrated by test-qemu-opts case +/qemu-opts/has_help_option. Fix by reusing the common parser. + +Signed-off-by: Markus Armbruster +Message-Id: <20200415074927.19897-5-armbru@redhat.com> +Reviewed-by: Eric Blake +--- + tests/test-qemu-opts.c | 4 ++-- + util/qemu-option.c | 39 +++++++++++++++++++-------------------- + 2 files changed, 21 insertions(+), 22 deletions(-) + +diff --git a/tests/test-qemu-opts.c b/tests/test-qemu-opts.c +index 8ff97268d8..77c944c4aa 100644 +--- a/tests/test-qemu-opts.c ++++ b/tests/test-qemu-opts.c +@@ -749,8 +749,8 @@ static void test_has_help_option(void) + { "a=0,?,b", true, true, true }, + { "help,b=1", true, true, false }, + { "?,b=1", true, true, false }, +- { "a,b,,help", false /* BUG */, true, true }, +- { "a,b,,?", false /* BUG */, true, true }, ++ { "a,b,,help", true, true, true }, ++ { "a,b,,?", true, true, true }, + }; + int i; + QemuOpts *opts; +diff --git a/util/qemu-option.c b/util/qemu-option.c +index d2956082bd..0abf26b61f 100644 +--- a/util/qemu-option.c ++++ b/util/qemu-option.c +@@ -165,26 +165,6 @@ void parse_option_size(const char *name, const char *value, + *ret = size; + } + +-bool has_help_option(const char *param) +-{ +- const char *p = param; +- bool result = false; +- +- while (*p && !result) { +- char *value; +- +- p = get_opt_value(p, &value); +- if (*p) { +- p++; +- } +- +- result = is_help_option(value); +- g_free(value); +- } +- +- return result; +-} +- + bool is_valid_option_list(const char *p) + { + char *value = NULL; +@@ -890,6 +870,25 @@ static char *opts_parse_id(const char *params) + return NULL; + } + ++bool has_help_option(const char *params) ++{ ++ const char *p; ++ char *name, *value; ++ bool ret; ++ ++ for (p = params; *p;) { ++ p = get_opt_name_value(p, NULL, &name, &value); ++ ret = is_help_option(name); ++ g_free(name); ++ g_free(value); ++ if (ret) { ++ return true; ++ } ++ } ++ ++ return false; ++} ++ + /** + * Store options parsed from @params into @opts. + * If @firstname is non-null, the first key=value in @params may omit +-- +2.23.0 + diff --git a/qemu-option-Fix-sloppy-recognition-of-id-.-after.patch b/qemu-option-Fix-sloppy-recognition-of-id-.-after.patch new file mode 100644 index 0000000000000000000000000000000000000000..252a48afed820913333936cf31a2b431ffbdaf26 --- /dev/null +++ b/qemu-option-Fix-sloppy-recognition-of-id-.-after.patch @@ -0,0 +1,86 @@ +From 933d1527785fe839300459abb486905094d192a7 Mon Sep 17 00:00:00 2001 +From: Markus Armbruster +Date: Wed, 15 Apr 2020 09:49:21 +0200 +Subject: [PATCH 007/709] qemu-option: Fix sloppy recognition of "id=..." after + ",," + +Signed-off-by: Markus Armbruster +Reviewed-by: Eric Blake +Reviewed-by: Kevin Wolf +Message-Id: <20200415074927.19897-4-armbru@redhat.com> +--- + tests/test-qemu-opts.c | 4 ++-- + util/qemu-option.c | 27 +++++++++++++++++++-------- + 2 files changed, 21 insertions(+), 10 deletions(-) + +diff --git a/tests/test-qemu-opts.c b/tests/test-qemu-opts.c +index 88a3e7bdf4..8ff97268d8 100644 +--- a/tests/test-qemu-opts.c ++++ b/tests/test-qemu-opts.c +@@ -500,10 +500,10 @@ static void test_opts_parse(void) + g_assert(!opts); + /* TODO Cover .merge_lists = true */ + +- /* Buggy ID recognition */ ++ /* Buggy ID recognition (fixed) */ + opts = qemu_opts_parse(&opts_list_03, "x=,,id=bar", false, &error_abort); + g_assert_cmpuint(opts_count(opts), ==, 1); +- g_assert_cmpstr(qemu_opts_id(opts), ==, "bar"); /* BUG */ ++ g_assert(!qemu_opts_id(opts)); + g_assert_cmpstr(qemu_opt_get(opts, "x"), ==, ",id=bar"); + + /* Anti-social ID */ +diff --git a/util/qemu-option.c b/util/qemu-option.c +index f08f4bc458..d2956082bd 100644 +--- a/util/qemu-option.c ++++ b/util/qemu-option.c +@@ -872,6 +872,24 @@ static void opts_do_parse(QemuOpts *opts, const char *params, + } + } + ++static char *opts_parse_id(const char *params) ++{ ++ const char *p; ++ char *name, *value; ++ ++ for (p = params; *p;) { ++ p = get_opt_name_value(p, NULL, &name, &value); ++ if (!strcmp(name, "id")) { ++ g_free(name); ++ return value; ++ } ++ g_free(name); ++ g_free(value); ++ } ++ ++ return NULL; ++} ++ + /** + * Store options parsed from @params into @opts. + * If @firstname is non-null, the first key=value in @params may omit +@@ -889,20 +907,13 @@ static QemuOpts *opts_parse(QemuOptsList *list, const char *params, + bool *invalidp, Error **errp) + { + const char *firstname; +- char *id = NULL; +- const char *p; ++ char *id = opts_parse_id(params); + QemuOpts *opts; + Error *local_err = NULL; + + assert(!permit_abbrev || list->implied_opt_name); + firstname = permit_abbrev ? list->implied_opt_name : NULL; + +- if (strncmp(params, "id=", 3) == 0) { +- get_opt_value(params + 3, &id); +- } else if ((p = strstr(params, ",id=")) != NULL) { +- get_opt_value(p + 4, &id); +- } +- + /* + * This code doesn't work for defaults && !list->merge_lists: when + * params has no id=, and list has an element with !opts->id, it +-- +2.23.0 + diff --git a/qemu-option-pass-NULL-rather-than-0-to-the-id-of-qem.patch b/qemu-option-pass-NULL-rather-than-0-to-the-id-of-qem.patch new file mode 100644 index 0000000000000000000000000000000000000000..4d4692b0198ff26e65aa331f88e5212df351f45e --- /dev/null +++ b/qemu-option-pass-NULL-rather-than-0-to-the-id-of-qem.patch @@ -0,0 +1,56 @@ +From 8ef3a4be27efccd791d05e74b7b17d918f511a76 Mon Sep 17 00:00:00 2001 +From: Masahiro Yamada +Date: Mon, 27 Apr 2020 09:57:04 +0900 +Subject: [PATCH 035/709] qemu-option: pass NULL rather than 0 to the id of + qemu_opts_set() + +The second argument 'id' is a pointer. Pass NULL rather than 0. + +Signed-off-by: Masahiro Yamada +Message-Id: <20200427005704.2475782-1-masahiroy@kernel.org> +Reviewed-by: Markus Armbruster +Signed-off-by: Markus Armbruster +--- + softmmu/vl.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/softmmu/vl.c b/softmmu/vl.c +index 32c0047889..afd2615fb3 100644 +--- a/softmmu/vl.c ++++ b/softmmu/vl.c +@@ -3059,19 +3059,19 @@ void qemu_init(int argc, char **argv, char **envp) + } + break; + case QEMU_OPTION_kernel: +- qemu_opts_set(qemu_find_opts("machine"), 0, "kernel", optarg, ++ qemu_opts_set(qemu_find_opts("machine"), NULL, "kernel", optarg, + &error_abort); + break; + case QEMU_OPTION_initrd: +- qemu_opts_set(qemu_find_opts("machine"), 0, "initrd", optarg, ++ qemu_opts_set(qemu_find_opts("machine"), NULL, "initrd", optarg, + &error_abort); + break; + case QEMU_OPTION_append: +- qemu_opts_set(qemu_find_opts("machine"), 0, "append", optarg, ++ qemu_opts_set(qemu_find_opts("machine"), NULL, "append", optarg, + &error_abort); + break; + case QEMU_OPTION_dtb: +- qemu_opts_set(qemu_find_opts("machine"), 0, "dtb", optarg, ++ qemu_opts_set(qemu_find_opts("machine"), NULL, "dtb", optarg, + &error_abort); + break; + case QEMU_OPTION_cdrom: +@@ -3182,7 +3182,7 @@ void qemu_init(int argc, char **argv, char **envp) + } + break; + case QEMU_OPTION_bios: +- qemu_opts_set(qemu_find_opts("machine"), 0, "firmware", optarg, ++ qemu_opts_set(qemu_find_opts("machine"), NULL, "firmware", optarg, + &error_abort); + break; + case QEMU_OPTION_singlestep: +-- +2.23.0 + diff --git a/qemu-options-Factor-out-get_opt_name_value-helper.patch b/qemu-options-Factor-out-get_opt_name_value-helper.patch new file mode 100644 index 0000000000000000000000000000000000000000..8d37bd54f47ce27bad1c1a991447e35f07837483 --- /dev/null +++ b/qemu-options-Factor-out-get_opt_name_value-helper.patch @@ -0,0 +1,140 @@ +From 6129803b55553b90805aa5012077b21c6c6eacdc Mon Sep 17 00:00:00 2001 +From: Markus Armbruster +Date: Wed, 15 Apr 2020 09:49:20 +0200 +Subject: [PATCH 006/709] qemu-options: Factor out get_opt_name_value() helper + +The next commits will put it to use. + +Signed-off-by: Markus Armbruster +Reviewed-by: Eric Blake +Reviewed-by: Kevin Wolf +Message-Id: <20200415074927.19897-3-armbru@redhat.com> +--- + util/qemu-option.c | 102 +++++++++++++++++++++++++-------------------- + 1 file changed, 56 insertions(+), 46 deletions(-) + +diff --git a/util/qemu-option.c b/util/qemu-option.c +index 97172b5eaa..f08f4bc458 100644 +--- a/util/qemu-option.c ++++ b/util/qemu-option.c +@@ -805,61 +805,71 @@ void qemu_opts_print(QemuOpts *opts, const char *separator) + } + } + ++static const char *get_opt_name_value(const char *params, ++ const char *firstname, ++ char **name, char **value) ++{ ++ const char *p, *pe, *pc; ++ ++ pe = strchr(params, '='); ++ pc = strchr(params, ','); ++ ++ if (!pe || (pc && pc < pe)) { ++ /* found "foo,more" */ ++ if (firstname) { ++ /* implicitly named first option */ ++ *name = g_strdup(firstname); ++ p = get_opt_value(params, value); ++ } else { ++ /* option without value, must be a flag */ ++ p = get_opt_name(params, name, ','); ++ if (strncmp(*name, "no", 2) == 0) { ++ memmove(*name, *name + 2, strlen(*name + 2) + 1); ++ *value = g_strdup("off"); ++ } else { ++ *value = g_strdup("on"); ++ } ++ } ++ } else { ++ /* found "foo=bar,more" */ ++ p = get_opt_name(params, name, '='); ++ assert(*p == '='); ++ p++; ++ p = get_opt_value(p, value); ++ } ++ ++ assert(!*p || *p == ','); ++ if (*p == ',') { ++ p++; ++ } ++ return p; ++} ++ + static void opts_do_parse(QemuOpts *opts, const char *params, + const char *firstname, bool prepend, + bool *invalidp, Error **errp) + { +- char *option = NULL; +- char *value = NULL; +- const char *p,*pe,*pc; + Error *local_err = NULL; ++ char *option, *value; ++ const char *p; + +- for (p = params; *p != '\0'; p++) { +- pe = strchr(p, '='); +- pc = strchr(p, ','); +- if (!pe || (pc && pc < pe)) { +- /* found "foo,more" */ +- if (p == params && firstname) { +- /* implicitly named first option */ +- option = g_strdup(firstname); +- p = get_opt_value(p, &value); +- } else { +- /* option without value, probably a flag */ +- p = get_opt_name(p, &option, ','); +- if (strncmp(option, "no", 2) == 0) { +- memmove(option, option+2, strlen(option+2)+1); +- value = g_strdup("off"); +- } else { +- value = g_strdup("on"); +- } +- } +- } else { +- /* found "foo=bar,more" */ +- p = get_opt_name(p, &option, '='); +- assert(*p == '='); +- p++; +- p = get_opt_value(p, &value); +- } +- if (strcmp(option, "id") != 0) { +- /* store and parse */ +- opt_set(opts, option, value, prepend, invalidp, &local_err); +- value = NULL; +- if (local_err) { +- error_propagate(errp, local_err); +- goto cleanup; +- } +- } +- if (*p != ',') { +- break; ++ for (p = params; *p;) { ++ p = get_opt_name_value(p, firstname, &option, &value); ++ firstname = NULL; ++ ++ if (!strcmp(option, "id")) { ++ g_free(option); ++ g_free(value); ++ continue; + } ++ ++ opt_set(opts, option, value, prepend, invalidp, &local_err); + g_free(option); +- g_free(value); +- option = value = NULL; ++ if (local_err) { ++ error_propagate(errp, local_err); ++ return; ++ } + } +- +- cleanup: +- g_free(option); +- g_free(value); + } + + /** +-- +2.23.0 + diff --git a/qemu-options-updates-for-abstract-unix-sockets.patch b/qemu-options-updates-for-abstract-unix-sockets.patch new file mode 100644 index 0000000000000000000000000000000000000000..0b174fd8a2d032f42b20f527100ca3a6549da879 --- /dev/null +++ b/qemu-options-updates-for-abstract-unix-sockets.patch @@ -0,0 +1,47 @@ +From e339273bfc514824410a49837e4f16dd4e51ae8e Mon Sep 17 00:00:00 2001 +From: xiaoqiang zhao +Date: Sat, 16 May 2020 11:13:27 +0800 +Subject: [PATCH 605/709] qemu-options: updates for abstract unix sockets +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +add options documents changes for -chardev + +Signed-off-by: xiaoqiang zhao +Signed-off-by: Daniel P. Berrangé +--- + qemu-options.hx | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/qemu-options.hx b/qemu-options.hx +index e2dca8a4e9..93bde2bbc8 100644 +--- a/qemu-options.hx ++++ b/qemu-options.hx +@@ -2938,7 +2938,7 @@ DEF("chardev", HAS_ARG, QEMU_OPTION_chardev, + " [,server][,nowait][,telnet][,websocket][,reconnect=seconds][,mux=on|off]\n" + " [,logfile=PATH][,logappend=on|off][,tls-creds=ID][,tls-authz=ID] (tcp)\n" + "-chardev socket,id=id,path=path[,server][,nowait][,telnet][,websocket][,reconnect=seconds]\n" +- " [,mux=on|off][,logfile=PATH][,logappend=on|off] (unix)\n" ++ " [,mux=on|off][,logfile=PATH][,logappend=on|off][,abstract=on|off][,tight=on|off] (unix)\n" + "-chardev udp,id=id[,host=host],port=port[,localaddr=localaddr]\n" + " [,localport=localport][,ipv4][,ipv6][,mux=on|off]\n" + " [,logfile=PATH][,logappend=on|off]\n" +@@ -3105,9 +3105,13 @@ The available backends are: + + ``nodelay`` disables the Nagle algorithm. + +- ``unix options: path=path`` ++ ``unix options: path=path[,abstract=on|off][,tight=on|off]`` + ``path`` specifies the local path of the unix socket. ``path`` + is required. ++ ``abstract`` specifies the use of the abstract socket namespace, ++ rather than the filesystem. Optional, defaults to false. ++ ``tight`` sets the socket length of abstract sockets to their minimum, ++ rather than the full sun_path length. Optional, defaults to true. + + ``-chardev udp,id=id[,host=host],port=port[,localaddr=localaddr][,localport=localport][,ipv4][,ipv6]`` + Sends all traffic from the guest to a remote host over UDP. +-- +2.23.0 + diff --git a/qemu-options.hx-9p-clarify-virtfs-vs.-fsdev.patch b/qemu-options.hx-9p-clarify-virtfs-vs.-fsdev.patch new file mode 100644 index 0000000000000000000000000000000000000000..2c62b441fdc2e28144ed4ac30e13e024fc128732 --- /dev/null +++ b/qemu-options.hx-9p-clarify-virtfs-vs.-fsdev.patch @@ -0,0 +1,49 @@ +From 65abaa01ee5781f525e1b9a0d6e6e5a3d8696d5f Mon Sep 17 00:00:00 2001 +From: Christian Schoenebeck +Date: Thu, 14 May 2020 08:06:43 +0200 +Subject: [PATCH 399/709] qemu-options.hx: 9p: clarify -virtfs vs. -fsdev + +The docs are ambiguous about the difference (or actually their +equality) between options '-virtfs' vs. '-fsdev'. So clarify that +'-virtfs' is actually just a convenience shortcut for its +generalized form '-fsdev' in conjunction with '-device virtio-9p-pci'. + +And as we're at it, also be a bit more descriptive what 9pfs is +actually used for. + +Signed-off-by: Christian Schoenebeck +Acked-by: Cornelia Huck +Message-Id: <208f1fceffce2feaf7c900b29e326b967dce7762.1585661532.git.qemu_oss@crudebyte.com> +Signed-off-by: Greg Kurz +--- + qemu-options.hx | 14 +++++++++++--- + 1 file changed, 11 insertions(+), 3 deletions(-) + +diff --git a/qemu-options.hx b/qemu-options.hx +index 292d4e7c0c..e2dca8a4e9 100644 +--- a/qemu-options.hx ++++ b/qemu-options.hx +@@ -1542,9 +1542,17 @@ SRST + ``-virtfs proxy,sock_fd=sock_fd,mount_tag=mount_tag [,writeout=writeout][,readonly]`` + \ + ``-virtfs synth,mount_tag=mount_tag`` +- Define a new filesystem device and expose it to the guest using a +- virtio-9p-device. The general form of a Virtual File system +- pass-through options are: ++ Define a new virtual filesystem device and expose it to the guest using ++ a virtio-9p-device (a.k.a. 9pfs), which essentially means that a certain ++ directory on host is made directly accessible by guest as a pass-through ++ file system by using the 9P network protocol for communication between ++ host and guests, if desired even accessible, shared by several guests ++ simultaniously. ++ ++ Note that ``-virtfs`` is actually just a convenience shortcut for its ++ generalized form ``-fsdev -device virtio-9p-pci``. ++ ++ The general form of pass-through file system options are: + + ``local`` + Accesses to the filesystem are done by QEMU. +-- +2.23.0 + diff --git a/qemu-plugin-Move-CONFIG_PLUGIN-stubs-altogether.patch b/qemu-plugin-Move-CONFIG_PLUGIN-stubs-altogether.patch new file mode 100644 index 0000000000000000000000000000000000000000..d9549902faf4ea5467741905c3ca42e6ed33db70 --- /dev/null +++ b/qemu-plugin-Move-CONFIG_PLUGIN-stubs-altogether.patch @@ -0,0 +1,80 @@ +From 1b9905ca0a7fdfdb691131646ee311e7e7dd1dda Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Wed, 13 May 2020 18:31:54 +0100 +Subject: [PATCH 500/709] qemu/plugin: Move !CONFIG_PLUGIN stubs altogether +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Simplify the ifdef'ry by moving all stubs together. + +Signed-off-by: Philippe Mathieu-Daudé +Reviewed-by: Emilio G. Cota +Signed-off-by: Alex Bennée +Message-Id: <20200510171119.20827-3-f4bug@amsat.org> +Message-Id: <20200513173200.11830-3-alex.bennee@linaro.org> +--- + include/qemu/plugin.h | 33 +++++++++++++++------------------ + 1 file changed, 15 insertions(+), 18 deletions(-) + +diff --git a/include/qemu/plugin.h b/include/qemu/plugin.h +index e45f950fe3..ab790ad105 100644 +--- a/include/qemu/plugin.h ++++ b/include/qemu/plugin.h +@@ -46,22 +46,6 @@ static inline void qemu_plugin_add_opts(void) + + void qemu_plugin_opt_parse(const char *optarg, QemuPluginList *head); + int qemu_plugin_load_list(QemuPluginList *head); +-#else /* !CONFIG_PLUGIN */ +-static inline void qemu_plugin_add_opts(void) +-{ } +- +-static inline void qemu_plugin_opt_parse(const char *optarg, +- QemuPluginList *head) +-{ +- error_report("plugin interface not enabled in this build"); +- exit(1); +-} +- +-static inline int qemu_plugin_load_list(QemuPluginList *head) +-{ +- return 0; +-} +-#endif /* !CONFIG_PLUGIN */ + + union qemu_plugin_cb_sig { + qemu_plugin_simple_cb_t simple; +@@ -182,8 +166,6 @@ struct qemu_plugin_insn *qemu_plugin_tb_insn_get(struct qemu_plugin_tb *tb) + return insn; + } + +-#ifdef CONFIG_PLUGIN +- + void qemu_plugin_vcpu_init_hook(CPUState *cpu); + void qemu_plugin_vcpu_exit_hook(CPUState *cpu); + void qemu_plugin_tb_trans_cb(CPUState *cpu, struct qemu_plugin_tb *tb); +@@ -207,6 +189,21 @@ void qemu_plugin_disable_mem_helpers(CPUState *cpu); + + #else /* !CONFIG_PLUGIN */ + ++static inline void qemu_plugin_add_opts(void) ++{ } ++ ++static inline void qemu_plugin_opt_parse(const char *optarg, ++ QemuPluginList *head) ++{ ++ error_report("plugin interface not enabled in this build"); ++ exit(1); ++} ++ ++static inline int qemu_plugin_load_list(QemuPluginList *head) ++{ ++ return 0; ++} ++ + static inline void qemu_plugin_vcpu_init_hook(CPUState *cpu) + { } + +-- +2.23.0 + diff --git a/qemu-plugin-Trivial-code-movement.patch b/qemu-plugin-Trivial-code-movement.patch new file mode 100644 index 0000000000000000000000000000000000000000..f171ba6864955bb530555d635e07e7a19d13e9d6 --- /dev/null +++ b/qemu-plugin-Trivial-code-movement.patch @@ -0,0 +1,73 @@ +From d2f6dc0790b5a87adb91b150c6a1a88163a0e2d5 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Wed, 13 May 2020 18:31:53 +0100 +Subject: [PATCH 499/709] qemu/plugin: Trivial code movement +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Move the qemu_plugin_event enum declaration earlier. +This will make the next commit easier to review. + +Signed-off-by: Philippe Mathieu-Daudé +Reviewed-by: Emilio G. Cota +Signed-off-by: Alex Bennée +Message-Id: <20200510171119.20827-2-f4bug@amsat.org> +Message-Id: <20200513173200.11830-2-alex.bennee@linaro.org> +--- + include/qemu/plugin.h | 32 ++++++++++++++++---------------- + 1 file changed, 16 insertions(+), 16 deletions(-) + +diff --git a/include/qemu/plugin.h b/include/qemu/plugin.h +index 11687e8cdc..e45f950fe3 100644 +--- a/include/qemu/plugin.h ++++ b/include/qemu/plugin.h +@@ -13,6 +13,22 @@ + #include "qemu/queue.h" + #include "qemu/option.h" + ++/* ++ * Events that plugins can subscribe to. ++ */ ++enum qemu_plugin_event { ++ QEMU_PLUGIN_EV_VCPU_INIT, ++ QEMU_PLUGIN_EV_VCPU_EXIT, ++ QEMU_PLUGIN_EV_VCPU_TB_TRANS, ++ QEMU_PLUGIN_EV_VCPU_IDLE, ++ QEMU_PLUGIN_EV_VCPU_RESUME, ++ QEMU_PLUGIN_EV_VCPU_SYSCALL, ++ QEMU_PLUGIN_EV_VCPU_SYSCALL_RET, ++ QEMU_PLUGIN_EV_FLUSH, ++ QEMU_PLUGIN_EV_ATEXIT, ++ QEMU_PLUGIN_EV_MAX, /* total number of plugin events we support */ ++}; ++ + /* + * Option parsing/processing. + * Note that we can load an arbitrary number of plugins. +@@ -47,22 +63,6 @@ static inline int qemu_plugin_load_list(QemuPluginList *head) + } + #endif /* !CONFIG_PLUGIN */ + +-/* +- * Events that plugins can subscribe to. +- */ +-enum qemu_plugin_event { +- QEMU_PLUGIN_EV_VCPU_INIT, +- QEMU_PLUGIN_EV_VCPU_EXIT, +- QEMU_PLUGIN_EV_VCPU_TB_TRANS, +- QEMU_PLUGIN_EV_VCPU_IDLE, +- QEMU_PLUGIN_EV_VCPU_RESUME, +- QEMU_PLUGIN_EV_VCPU_SYSCALL, +- QEMU_PLUGIN_EV_VCPU_SYSCALL_RET, +- QEMU_PLUGIN_EV_FLUSH, +- QEMU_PLUGIN_EV_ATEXIT, +- QEMU_PLUGIN_EV_MAX, /* total number of plugin events we support */ +-}; +- + union qemu_plugin_cb_sig { + qemu_plugin_simple_cb_t simple; + qemu_plugin_udata_cb_t udata; +-- +2.23.0 + diff --git a/qemu-qemu-plugin-Make-qemu_plugin_hwaddr_is_io-hwadd.patch b/qemu-qemu-plugin-Make-qemu_plugin_hwaddr_is_io-hwadd.patch new file mode 100644 index 0000000000000000000000000000000000000000..15a1a8eafebf8017e1936db67b69111bb0a61252 --- /dev/null +++ b/qemu-qemu-plugin-Make-qemu_plugin_hwaddr_is_io-hwadd.patch @@ -0,0 +1,56 @@ +From 308e7549642eb74b9671b94dd56d1e20773c358a Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Wed, 13 May 2020 18:31:55 +0100 +Subject: [PATCH 501/709] qemu/qemu-plugin: Make qemu_plugin_hwaddr_is_io() + hwaddr argument const +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Rename qemu_plugin_hwaddr_is_io() address argument 'haddr' +similarly to qemu_plugin_hwaddr_device_offset(), and make +it const. + +Signed-off-by: Philippe Mathieu-Daudé +Reviewed-by: Emilio G. Cota +Signed-off-by: Alex Bennée +Message-Id: <20200510171119.20827-4-f4bug@amsat.org> +Message-Id: <20200513173200.11830-4-alex.bennee@linaro.org> +--- + include/qemu/qemu-plugin.h | 2 +- + plugins/api.c | 4 ++-- + 2 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/include/qemu/qemu-plugin.h b/include/qemu/qemu-plugin.h +index 5502e112c8..89ed579f55 100644 +--- a/include/qemu/qemu-plugin.h ++++ b/include/qemu/qemu-plugin.h +@@ -331,7 +331,7 @@ struct qemu_plugin_hwaddr *qemu_plugin_get_hwaddr(qemu_plugin_meminfo_t info, + * to return information about it. For non-IO accesses the device + * offset will be into the appropriate block of RAM. + */ +-bool qemu_plugin_hwaddr_is_io(struct qemu_plugin_hwaddr *hwaddr); ++bool qemu_plugin_hwaddr_is_io(const struct qemu_plugin_hwaddr *haddr); + uint64_t qemu_plugin_hwaddr_device_offset(const struct qemu_plugin_hwaddr *haddr); + + typedef void +diff --git a/plugins/api.c b/plugins/api.c +index 53c8a73582..bbdc5a4eb4 100644 +--- a/plugins/api.c ++++ b/plugins/api.c +@@ -275,10 +275,10 @@ struct qemu_plugin_hwaddr *qemu_plugin_get_hwaddr(qemu_plugin_meminfo_t info, + } + #endif + +-bool qemu_plugin_hwaddr_is_io(struct qemu_plugin_hwaddr *hwaddr) ++bool qemu_plugin_hwaddr_is_io(const struct qemu_plugin_hwaddr *haddr) + { + #ifdef CONFIG_SOFTMMU +- return hwaddr->is_io; ++ return haddr->is_io; + #else + return false; + #endif +-- +2.23.0 + diff --git a/qemu-sockets-add-abstract-UNIX-domain-socket-support.patch b/qemu-sockets-add-abstract-UNIX-domain-socket-support.patch new file mode 100644 index 0000000000000000000000000000000000000000..b450eaba794ae9a69d1f2f294c0f420a139d068e --- /dev/null +++ b/qemu-sockets-add-abstract-UNIX-domain-socket-support.patch @@ -0,0 +1,196 @@ +From 776b97d3605ed0fc94443048fdf988c7725e38a9 Mon Sep 17 00:00:00 2001 +From: xiaoqiang zhao +Date: Sat, 16 May 2020 11:13:25 +0800 +Subject: [PATCH 603/709] qemu-sockets: add abstract UNIX domain socket support +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +unix_listen/connect_saddr now support abstract address types + +two aditional BOOL switches are introduced: +tight: whether to set @addrlen to the minimal string length, + or the maximum sun_path length. default is TRUE +abstract: whether we use abstract address. default is FALSE + +cli example: +-monitor unix:/tmp/unix.socket,abstract,tight=off +OR +-chardev socket,path=/tmp/unix.socket,id=unix1,abstract,tight=on + +Signed-off-by: xiaoqiang zhao +Signed-off-by: Daniel P. Berrangé +--- + chardev/char-socket.c | 4 ++++ + chardev/char.c | 7 +++++++ + qapi/sockets.json | 8 +++++++- + util/qemu-sockets.c | 39 ++++++++++++++++++++++++++++++++------- + 4 files changed, 50 insertions(+), 8 deletions(-) + +diff --git a/chardev/char-socket.c b/chardev/char-socket.c +index 232e0a8604..e77699db48 100644 +--- a/chardev/char-socket.c ++++ b/chardev/char-socket.c +@@ -1380,6 +1380,8 @@ static void qemu_chr_parse_socket(QemuOpts *opts, ChardevBackend *backend, + const char *host = qemu_opt_get(opts, "host"); + const char *port = qemu_opt_get(opts, "port"); + const char *fd = qemu_opt_get(opts, "fd"); ++ bool tight = qemu_opt_get_bool(opts, "tight", true); ++ bool abstract = qemu_opt_get_bool(opts, "abstract", false); + SocketAddressLegacy *addr; + ChardevSocket *sock; + +@@ -1431,6 +1433,8 @@ static void qemu_chr_parse_socket(QemuOpts *opts, ChardevBackend *backend, + addr->type = SOCKET_ADDRESS_LEGACY_KIND_UNIX; + q_unix = addr->u.q_unix.data = g_new0(UnixSocketAddress, 1); + q_unix->path = g_strdup(path); ++ q_unix->tight = tight; ++ q_unix->abstract = abstract; + } else if (host) { + addr->type = SOCKET_ADDRESS_LEGACY_KIND_INET; + addr->u.inet.data = g_new(InetSocketAddress, 1); +diff --git a/chardev/char.c b/chardev/char.c +index 0196e2887b..ea06c5ff4d 100644 +--- a/chardev/char.c ++++ b/chardev/char.c +@@ -939,6 +939,13 @@ QemuOptsList qemu_chardev_opts = { + },{ + .name = "logappend", + .type = QEMU_OPT_BOOL, ++ },{ ++ .name = "tight", ++ .type = QEMU_OPT_BOOL, ++ .def_value_str = "on", ++ },{ ++ .name = "abstract", ++ .type = QEMU_OPT_BOOL, + }, + { /* end of list */ } + }, +diff --git a/qapi/sockets.json b/qapi/sockets.json +index ea933ed4b2..cbd6ef35d0 100644 +--- a/qapi/sockets.json ++++ b/qapi/sockets.json +@@ -73,12 +73,18 @@ + # Captures a socket address in the local ("Unix socket") namespace. + # + # @path: filesystem path to use ++# @tight: pass a socket address length confined to the minimum length of the ++# abstract string, rather than the full sockaddr_un record length ++# (only matters for abstract sockets, default true). (Since 5.1) ++# @abstract: whether this is an abstract address, default false. (Since 5.1) + # + # Since: 1.3 + ## + { 'struct': 'UnixSocketAddress', + 'data': { +- 'path': 'str' } } ++ 'path': 'str', ++ '*tight': 'bool', ++ '*abstract': 'bool' } } + + ## + # @VsockSocketAddress: +diff --git a/util/qemu-sockets.c b/util/qemu-sockets.c +index 86c48b9fa5..b37d288866 100644 +--- a/util/qemu-sockets.c ++++ b/util/qemu-sockets.c +@@ -863,6 +863,7 @@ static int unix_listen_saddr(UnixSocketAddress *saddr, + char *pathbuf = NULL; + const char *path; + size_t pathlen; ++ size_t addrlen; + + sock = qemu_socket(PF_UNIX, SOCK_STREAM, 0); + if (sock < 0) { +@@ -879,9 +880,11 @@ static int unix_listen_saddr(UnixSocketAddress *saddr, + } + + pathlen = strlen(path); +- if (pathlen > sizeof(un.sun_path)) { ++ if (pathlen > sizeof(un.sun_path) || ++ (saddr->abstract && pathlen > (sizeof(un.sun_path) - 1))) { + error_setg(errp, "UNIX socket path '%s' is too long", path); + error_append_hint(errp, "Path must be less than %zu bytes\n", ++ saddr->abstract ? sizeof(un.sun_path) - 1 : + sizeof(un.sun_path)); + goto err; + } +@@ -903,7 +906,7 @@ static int unix_listen_saddr(UnixSocketAddress *saddr, + close(fd); + } + +- if (unlink(path) < 0 && errno != ENOENT) { ++ if (!saddr->abstract && unlink(path) < 0 && errno != ENOENT) { + error_setg_errno(errp, errno, + "Failed to unlink socket %s", path); + goto err; +@@ -911,9 +914,19 @@ static int unix_listen_saddr(UnixSocketAddress *saddr, + + memset(&un, 0, sizeof(un)); + un.sun_family = AF_UNIX; +- memcpy(un.sun_path, path, pathlen); ++ addrlen = sizeof(un); + +- if (bind(sock, (struct sockaddr*) &un, sizeof(un)) < 0) { ++ if (saddr->abstract) { ++ un.sun_path[0] = '\0'; ++ memcpy(&un.sun_path[1], path, pathlen); ++ if (saddr->tight) { ++ addrlen = offsetof(struct sockaddr_un, sun_path) + 1 + pathlen; ++ } ++ } else { ++ memcpy(un.sun_path, path, pathlen); ++ } ++ ++ if (bind(sock, (struct sockaddr *) &un, addrlen) < 0) { + error_setg_errno(errp, errno, "Failed to bind socket to %s", path); + goto err; + } +@@ -936,6 +949,7 @@ static int unix_connect_saddr(UnixSocketAddress *saddr, Error **errp) + struct sockaddr_un un; + int sock, rc; + size_t pathlen; ++ size_t addrlen; + + if (saddr->path == NULL) { + error_setg(errp, "unix connect: no path specified"); +@@ -949,21 +963,32 @@ static int unix_connect_saddr(UnixSocketAddress *saddr, Error **errp) + } + + pathlen = strlen(saddr->path); +- if (pathlen > sizeof(un.sun_path)) { ++ if (pathlen > sizeof(un.sun_path) || ++ (saddr->abstract && pathlen > (sizeof(un.sun_path) - 1))) { + error_setg(errp, "UNIX socket path '%s' is too long", saddr->path); + error_append_hint(errp, "Path must be less than %zu bytes\n", ++ saddr->abstract ? sizeof(un.sun_path) - 1 : + sizeof(un.sun_path)); + goto err; + } + + memset(&un, 0, sizeof(un)); + un.sun_family = AF_UNIX; +- memcpy(un.sun_path, saddr->path, pathlen); ++ addrlen = sizeof(un); + ++ if (saddr->abstract) { ++ un.sun_path[0] = '\0'; ++ memcpy(&un.sun_path[1], saddr->path, pathlen); ++ if (saddr->tight) { ++ addrlen = offsetof(struct sockaddr_un, sun_path) + 1 + pathlen; ++ } ++ } else { ++ memcpy(un.sun_path, saddr->path, pathlen); ++ } + /* connect to peer */ + do { + rc = 0; +- if (connect(sock, (struct sockaddr *) &un, sizeof(un)) < 0) { ++ if (connect(sock, (struct sockaddr *) &un, addrlen) < 0) { + rc = -errno; + } + } while (rc == -EINTR); +-- +2.23.0 + diff --git a/qemu-storage-daemon-Fix-non-string-object-properties.patch b/qemu-storage-daemon-Fix-non-string-object-properties.patch new file mode 100644 index 0000000000000000000000000000000000000000..aae272a09ee8cf02d56996d3a04278d6be273781 --- /dev/null +++ b/qemu-storage-daemon-Fix-non-string-object-properties.patch @@ -0,0 +1,117 @@ +From eaae29ef89d498d0eac553c77b554f310a47f809 Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Thu, 16 Apr 2020 17:26:06 +0200 +Subject: [PATCH 138/709] qemu-storage-daemon: Fix non-string --object + properties + +After processing the option string with the keyval parser, we get a +QDict that contains only strings. This QDict must be fed to a keyval +visitor which converts the strings into the right data types. + +qmp_object_add(), however, uses the normal QObject input visitor, which +expects a QDict where all properties already have the QType that matches +the data type required by the QOM object type. + +Change the --object implementation in qemu-storage-daemon so that it +doesn't call qmp_object_add(), but calls user_creatable_add_dict() +directly instead and pass it a new keyval boolean that decides which +visitor must be used. + +Reported-by: Coiby Xu +Signed-off-by: Kevin Wolf +--- + include/qom/object_interfaces.h | 6 +++++- + qemu-storage-daemon.c | 4 +--- + qom/object_interfaces.c | 8 ++++++-- + qom/qom-qmp-cmds.c | 2 +- + 4 files changed, 13 insertions(+), 7 deletions(-) + +diff --git a/include/qom/object_interfaces.h b/include/qom/object_interfaces.h +index a0037968a4..65172120fa 100644 +--- a/include/qom/object_interfaces.h ++++ b/include/qom/object_interfaces.h +@@ -90,6 +90,10 @@ Object *user_creatable_add_type(const char *type, const char *id, + /** + * user_creatable_add_dict: + * @qdict: the object definition ++ * @keyval: if true, use a keyval visitor for processing @qdict (i.e. ++ * assume that all @qdict values are strings); otherwise, use ++ * the normal QObject visitor (i.e. assume all @qdict values ++ * have the QType expected by the QOM object type) + * @errp: if an error occurs, a pointer to an area to store the error + * + * Create an instance of the user creatable object that is defined by +@@ -97,7 +101,7 @@ Object *user_creatable_add_type(const char *type, const char *id, + * ID from the key 'id'. The remaining entries in @qdict are used to + * initialize the object properties. + */ +-void user_creatable_add_dict(QDict *qdict, Error **errp); ++void user_creatable_add_dict(QDict *qdict, bool keyval, Error **errp); + + /** + * user_creatable_add_opts: +diff --git a/qemu-storage-daemon.c b/qemu-storage-daemon.c +index dd128978cc..9e7adfe3a6 100644 +--- a/qemu-storage-daemon.c ++++ b/qemu-storage-daemon.c +@@ -278,7 +278,6 @@ static void process_options(int argc, char *argv[]) + QemuOpts *opts; + const char *type; + QDict *args; +- QObject *ret_data = NULL; + + /* FIXME The keyval parser rejects 'help' arguments, so we must + * unconditionall try QemuOpts first. */ +@@ -291,9 +290,8 @@ static void process_options(int argc, char *argv[]) + qemu_opts_del(opts); + + args = keyval_parse(optarg, "qom-type", &error_fatal); +- qmp_object_add(args, &ret_data, &error_fatal); ++ user_creatable_add_dict(args, true, &error_fatal); + qobject_unref(args); +- qobject_unref(ret_data); + break; + } + default: +diff --git a/qom/object_interfaces.c b/qom/object_interfaces.c +index 739e3e5172..bc36f96e47 100644 +--- a/qom/object_interfaces.c ++++ b/qom/object_interfaces.c +@@ -106,7 +106,7 @@ out: + return obj; + } + +-void user_creatable_add_dict(QDict *qdict, Error **errp) ++void user_creatable_add_dict(QDict *qdict, bool keyval, Error **errp) + { + Visitor *v; + Object *obj; +@@ -127,7 +127,11 @@ void user_creatable_add_dict(QDict *qdict, Error **errp) + } + qdict_del(qdict, "id"); + +- v = qobject_input_visitor_new(QOBJECT(qdict)); ++ if (keyval) { ++ v = qobject_input_visitor_new_keyval(QOBJECT(qdict)); ++ } else { ++ v = qobject_input_visitor_new(QOBJECT(qdict)); ++ } + obj = user_creatable_add_type(type, id, qdict, v, errp); + visit_free(v); + object_unref(obj); +diff --git a/qom/qom-qmp-cmds.c b/qom/qom-qmp-cmds.c +index 35db44b50e..c5249e44d0 100644 +--- a/qom/qom-qmp-cmds.c ++++ b/qom/qom-qmp-cmds.c +@@ -263,7 +263,7 @@ void qmp_object_add(QDict *qdict, QObject **ret_data, Error **errp) + qobject_unref(pdict); + } + +- user_creatable_add_dict(qdict, errp); ++ user_creatable_add_dict(qdict, false, errp); + } + + void qmp_object_del(const char *id, Error **errp) +-- +2.23.0 + diff --git a/qemu.spec b/qemu.spec index f7bcb642f4f10ac1184c8db2d034f508e4f5810e..0cb9019f15fa534d52cbd5fb4563cdde72bc4e63 100644 --- a/qemu.spec +++ b/qemu.spec @@ -1,133 +1,736 @@ Name: qemu -Version: 4.0.0 -Release: 6 +Version: 5.0.0 +Release: 0 Epoch: 2 -Summary: QEMU is a generic and open source machine emulator and virtualizer +Summary: QEMU is a generic and open source machine and virtualizer License: GPLv2 and BSD and MIT and CC-BY URL: http://www.qemu.org Source0: https://www.qemu.org/download/%{name}-%{version}%{?rcstr}.tar.xz -Source1: 80-kvm.rules -Source2: 99-qemu-guest-agent.rules -Source3: bridge.conf -Patch0001: qxl-check-release-info-object.patch -Patch0002: target-i386-define-md-clear-bit.patch -Patch0003: Revert-Enable-build-and-install-of-our-rST-docs.patch -Patch0004: ARM64-record-vtimer-tick-when-cpu-is-stopped.patch -Patch0005: pl011-reset-read-FIFO-when-UARTTIMSC-0-UARTICR-0xfff.patch -Patch0006: pl031-support-rtc-timer-property-for-pl031.patch -Patch0007: vhost-cancel-migration-when-vhost-user-restarted.patch -Patch0008: qcow2-fix-memory-leak-in-qcow2_read_extensions.patch -Patch0009: hw-arm-expose-host-CPU-frequency-info-to-guest.patch -Patch0010: block-Fix-AioContext-switch-for-bs-drv-NULL.patch -Patch0011: cutils-Fix-size_to_str-on-32-bit-platforms.patch -Patch0012: qcow2-Avoid-COW-during-metadata-preallocation.patch -Patch0013: qcow2-Add-errp-to-preallocate_co.patch -Patch0014: qcow2-Fix-full-preallocation-with-external-data-file.patch -Patch0015: qcow2-Fix-qcow2_make_empty-with-external-data-file.patch -Patch0016: megasas-fix-mapped-frame-size.patch -Patch0017: kbd-state-fix-autorepeat-handling.patch -Patch0018: block-file-posix-Unaligned-O_DIRECT-block-status.patch -Patch0019: hw-add-compat-machines-for-4.1.patch -Patch0020: usb-tablet-fix-serial-compat-property.patch -Patch0021: q35-Revert-to-kernel-irqchip.patch -Patch0022: hw-Nuke-hw_compat_4_0_1-and-pc_compat_4_0_1.patch -Patch0023: vl-Fix-drive-blockdev-persistent-reservation-management.patch -Patch0024: vhost-fix-vhost_log-size-overflow-during-migration.patch -Patch0025: virtio-pci-fix-missing-device-properties.patch -Patch0026: i386-acpi-fix-gint-overflow-in-crs_range_compare.patch -Patch0027: ioapic-kvm-Skip-route-updates-for-masked-pins.patch -Patch0028: i386-acpi-show-PCI-Express-bus-on-pxb-pcie-expanders.patch -Patch0029: virtio-balloon-fix-QEMU-4.0-config-size-migration-in.patch -Patch0030: virtio-balloon-Fix-wrong-sign-extension-of-PFNs.patch -Patch0031: virtio-balloon-Fix-QEMU-crashes-on-pagesize-BALLOON_.patch -Patch0032: virtio-balloon-Simplify-deflate-with-pbp.patch -Patch0033: virtio-balloon-Better-names-for-offset-variables.patch -Patch0034: virtio-balloon-Rework-pbp-tracking-data.patch -Patch0035: virtio-balloon-Use-temporary-PBP-only.patch -Patch0036: virtio-balloon-don-t-track-subpages-for-the-PBP.patch -Patch0037: virtio-balloon-free-pbp-more-aggressively.patch -Patch0038: qemu-bridge-helper-restrict-interface-name-to-IFNAMS.patch -Patch0039: qemu-bridge-helper-move-repeating-code-in-parse_acl.patch -Patch0040: smbios-Add-missing-member-of-type-4-for-smbios-3.0.patch -Patch0041: hw-arm-virt-Introduce-cpu-topology-support.patch -Patch0042: hw-arm64-add-vcpu-cache-info-support.patch -Patch0043: xhci-Fix-memory-leak-in-xhci_address_slot.patch -Patch0044: xhci-Fix-memory-leak-in-xhci_kick_epctx.patch -Patch0045: ehci-fix-queue-dev-null-ptr-dereference.patch -Patch0046: memory-unref-the-memory-region-in-simplify-flatview.patch -Patch0047: scsi-lsi-exit-infinite-loop-while-executing-script.patch -Patch0048: util-async-hold-AioContext-ref-to-prevent-use-after-free.patch -Patch0049: vhost-user-scsi-prevent-using-uninitialized-vqs.patch -Patch0050: cpu-add-Kunpeng-920-cpu-support.patch -Patch0051: cpu-parse-feature-to-avoid-failure.patch -Patch0052: cpu-add-Cortex-A72-processor-kvm-target-support.patch -Patch0053: vnc-fix-memory-leak-when-vnc-disconnect.patch -Patch0054: pcie-disable-the-PCI_EXP_LINKSTA_DLLA-cap.patch -Patch0055: blockdev-backup-don-t-check-aio_context-too-early.patch -Patch0056: migration-dirty-bitmaps-change-bitmap-enumeration-method.patch -Patch0057: target-i386-add-MDS-NO-feature.patch -Patch0058: usbredir-fix-buffer-overflow-on-vmload.patch -Patch0059: util-hbitmap-update-orig_size-on-truncate.patch -Patch0060: mirror-Only-mirror-granularity-aligned-chunks.patch -Patch0061: qcow2-Fix-the-calculation-of-the-maximum-L2-cache-size.patch -Patch0062: dma-helpers-ensure-AIO-callback-is-invoked-after-can.patch -Patch0063: pr-manager-Fix-invalid-g_free-crash-bug.patch -Patch0064: block-create-Do-not-abort-if-a-block-driver-is-not-available.patch -Patch0065: block-nfs-tear-down-aio-before-nfs_close.patch -Patch0066: blockjob-update-nodes-head-while-removing-all-bdrv.patch -Patch0067: slirp-Fix-heap-overflow-in-ip_reass-on-big-packet-input.patch -Patch0068: slirp-ip_reass-Fix-use-after-free.patch -Patch0069: hw-core-loader-Fix-possible-crash-in-rom_copy.patch -Patch0070: migration-Fix-use-after-free-during-process-exit.patch -Patch0071: linux-headers-update-against-KVM-ARM-Fix-256-vcpus.patch -Patch0072: intc-arm_gic-Support-IRQ-injection-for-more-than-256.patch -Patch0073: ARM-KVM-Check-KVM_CAP_ARM_IRQ_LINE_LAYOUT_2-for-smp_.patch -Patch0074: 9pfs-local-Fix-possible-memory-leak-in-local_link.patch -Patch0075: scsi-disk-define-props-in-scsi_block_disk-to-avoid-memleaks.patch -Patch0076: arm-translate-a64-fix-uninitialized-variable-warning.patch -Patch0077: nbd-fix-uninitialized-variable-warning.patch -Patch0078: xhci-Fix-memory-leak-in-xhci_kick_epctx-when-poweroff.patch -Patch0079: block-fix-memleaks-in-bdrv_refresh_filename.patch +Patch0001: virtio-net-fix-rsc_ext-compat-handling.patch +Patch0002: linux-headers-update-against-Linux-5.7-rc3.patch +Patch0003: s390x-Move-diagnose-308-subcodes-and-rcs-into-ipl.h.patch +Patch0004: various-Remove-suspicious-character-outside-of-defin.patch +Patch0005: tests-qemu-opts-Cover-has_help_option-qemu_opt_has_h.patch +Patch0006: qemu-options-Factor-out-get_opt_name_value-helper.patch +Patch0007: qemu-option-Fix-sloppy-recognition-of-id-.-after.patch +Patch0008: qemu-option-Fix-has_help_option-s-sloppy-parsing.patch +Patch0009: test-qemu-opts-Simplify-test_has_help_option-after-b.patch +Patch0010: qemu-option-Avoid-has_help_option-in-qemu_opts_parse.patch +Patch0011: qemu-img-Factor-out-accumulate_options-helper.patch +Patch0012: qemu-img-Move-is_valid_option_list-to-qemu-img.c-and.patch +Patch0013: qemu-img-Reject-broken-o.patch +Patch0014: cryptodev-Fix-cryptodev_builtin_cleanup-error-API-vi.patch +Patch0015: block-file-posix-Fix-check_cache_dropped-error-handl.patch +Patch0016: cpus-Fix-configure_icount-error-API-violation.patch +Patch0017: cpus-Proper-range-checking-for-icount-shift-N.patch +Patch0018: arm-virt-Fix-virt_machine_device_plug_cb-error-API-v.patch +Patch0019: fdc-Fix-fallback-auto-error-handling.patch +Patch0020: bochs-display-Fix-vgamem-SIZE-error-handling.patch +Patch0021: virtio-net-Fix-duplex-.-and-speed-.-error-handling.patch +Patch0022: xen-pt-Fix-flawed-conversion-to-realize.patch +Patch0023: io-Fix-qio_channel_socket_close-error-handling.patch +Patch0024: migration-colo-Fix-qmp_xen_colo_do_checkpoint-error-.patch +Patch0025: tests-test-logging-Fix-test-for-dfilter-0.0xffffffff.patch +Patch0026: qga-Fix-qmp_guest_get_memory_blocks-error-handling.patch +Patch0027: qga-Fix-qmp_guest_suspend_-disk-ram-error-handling.patch +Patch0028: sam460ex-Suppress-useless-warning-on-m-32-and-m-64.patch +Patch0029: smbus-Fix-spd_data_generate-error-API-violation.patch +Patch0030: bamboo-sam460ex-Tidy-up-error-message-for-unsupporte.patch +Patch0031: smbus-Fix-spd_data_generate-for-number-of-banks-2.patch +Patch0032: Makefile-Drop-unused-broken-target-recurse-fuzz.patch +Patch0033: fuzz-Simplify-how-we-compute-available-machines-and-.patch +Patch0034: libqos-Give-get_machine_allocator-internal-linkage.patch +Patch0035: qemu-option-pass-NULL-rather-than-0-to-the-id-of-qem.patch +Patch0036: s390x-protvirt-Support-unpack-facility.patch +Patch0037: s390x-protvirt-Add-migration-blocker.patch +Patch0038: s390x-protvirt-Inhibit-balloon-when-switching-to-pro.patch +Patch0039: s390x-protvirt-KVM-intercept-changes.patch +Patch0040: s390x-Add-SIDA-memory-ops.patch +Patch0041: s390x-protvirt-Move-STSI-data-over-SIDAD.patch +Patch0042: s390x-protvirt-SCLP-interpretation.patch +Patch0043: s390x-protvirt-Set-guest-IPL-PSW.patch +Patch0044: s390x-protvirt-Move-diag-308-data-over-SIDA.patch +Patch0045: s390x-protvirt-Disable-address-checks-for-PV-guest-I.patch +Patch0046: s390x-protvirt-Move-IO-control-structures-over-SIDA.patch +Patch0047: s390x-protvirt-Handle-SIGP-store-status-correctly.patch +Patch0048: docs-system-Add-protvirt-docs.patch +Patch0049: s390x-Add-unpack-facility-feature-to-GA1.patch +Patch0050: s390x-protvirt-Fix-stray-error_report_err-in-s390_ma.patch +Patch0051: s390x-pv-Retry-ioctls-on-EINTR.patch +Patch0052: s390x-s390-virtio-ccw-Fix-build-on-systems-without-K.patch +Patch0053: Open-5.1-development-tree.patch +Patch0054: riscv-sifive_u-Fix-up-file-ordering.patch +Patch0055: riscv-sifive_u-Add-a-serial-property-to-the-sifive_u.patch +Patch0056: riscv-sifive_u-Add-a-serial-property-to-the-sifive_u-m.patch +Patch0057: riscv-Don-t-use-stage-2-PTE-lookup-protection-flags.patch +Patch0058: riscv-AND-stage-1-and-stage-2-protection-flags.patch +Patch0059: riscv-Fix-Stage2-SV32-page-table-walk.patch +Patch0060: hw-riscv-Generate-correct-mmu-type-for-32-bit-machin.patch +Patch0061: riscv-sifive_e-Support-changing-CPU-type.patch +Patch0062: target-riscv-Add-a-sifive-e34-cpu-type.patch +Patch0063: linux-user-riscv-fix-up-struct-target_ucontext-defin.patch +Patch0064: hw-riscv-Add-optional-symbol-callback-ptr-to-riscv_l.patch +Patch0065: hw-riscv-spike-Allow-loading-firmware-separately-usi.patch +Patch0066: hw-riscv-spike-Allow-more-than-one-CPUs.patch +Patch0067: qobject-Clean-up-QLIST_FOREACH_ENTRY.patch +Patch0068: qobject-Factor-out-helper-json_pretty_newline.patch +Patch0069: qobject-Eliminate-qlist_iter-use-QLIST_FOREACH_ENTRY.patch +Patch0070: qobject-Eliminate-qdict_iter-use-qdict_first-qdict_n.patch +Patch0071: qemu-option-Clean-up-after-the-previous-commit.patch +Patch0072: qapi-Belatedly-update-visitor.h-s-big-comment-for-QA.patch +Patch0073: qapi-Fix-the-virtual-walk-example-in-visitor.h-s-big.patch +Patch0074: qapi-Fix-typo-in-visit_start_list-s-contract.patch +Patch0075: qapi-Document-errp-usage-more-thoroughly-in-visitor..patch +Patch0076: qapi-Polish-prose-in-visitor.h.patch +Patch0077: qapi-Assert-incomplete-object-occurs-only-in-dealloc.patch +Patch0078: qapi-Fix-Visitor-contract-for-start_alternate.patch +Patch0079: qapi-Assert-output-visitors-see-only-valid-enum-valu.patch +Patch0080: qapi-Assert-non-input-visitors-see-only-valid-narrow.patch +Patch0081: qapi-Clean-up-visitor-s-recovery-from-input-with-inv.patch +Patch0082: qapi-Assert-non-input-visitors-see-only-valid-altern.patch +Patch0083: qapi-Only-input-visitors-can-actually-fail.patch +Patch0084: qom-Simplify-object_property_get_enum.patch +Patch0085: qapi-Disallow-qmp_marshal_FOO-NULL.patch +Patch0086: qapi-Generate-simpler-marshalling-code-when-no-argum.patch +Patch0087: target-microblaze-Add-the-opcode-0x0-illegal-CPU-pro.patch +Patch0088: target-microblaze-Add-the-ill-opcode-exception-prope.patch +Patch0089: target-microblaze-Add-the-div-zero-exception-propert.patch +Patch0090: target-microblaze-Add-the-unaligned-exceptions-prope.patch +Patch0091: target-microblaze-Add-the-pvr-user1-property.patch +Patch0092: target-microblaze-Add-the-pvr-user2-property.patch +Patch0093: dma-xlnx-zdma-Fix-descriptor-loading-MEM-wrt-endiann.patch +Patch0094: dma-xlnx-zdma-Fix-descriptor-loading-REG-wrt-endiann.patch +Patch0095: nrf51-Fix-last-GPIO-CNF-address.patch +Patch0096: bugfix-Use-gicr_typer-in-arm_gicv3_icc_reset.patch +Patch0097: Typo-Correct-the-name-of-CPU-hotplug-memory-region.patch +Patch0098: hw-net-Add-Smartfusion2-emac-block.patch +Patch0099: msf2-Add-EMAC-block-to-SmartFusion2-SoC.patch +Patch0100: tests-boot_linux_console-Add-ethernet-test-to-SmartF.patch +Patch0101: hw-core-clock-introduce-clock-object.patch +Patch0102: hw-core-clock-vmstate-define-a-vmstate-entry-for-clo.patch +Patch0103: qdev-add-clock-input-output-support-to-devices.patch +Patch0104: qdev-clock-introduce-an-init-array-to-ease-the-devic.patch +Patch0105: docs-clocks-add-device-s-clock-documentation.patch +Patch0106: hw-misc-zynq_slcr-add-clock-generation-for-uarts.patch +Patch0107: hw-char-cadence_uart-add-clock-support.patch +Patch0108: hw-arm-xilinx_zynq-connect-uart-clocks-to-slcr.patch +Patch0109: qdev-monitor-print-the-device-s-clock-with-info-qtre.patch +Patch0110: hw-arm-versal-Setup-the-ADMA-with-128bit-bus-width.patch +Patch0111: Cadence-gem-fix-wraparound-in-64bit-descriptors.patch +Patch0112: net-cadence_gem-clear-RX-control-descriptor.patch +Patch0113: target-arm-Vectorize-integer-comparison-vs-zero.patch +Patch0114: hw-arm-virt-dt-move-creation-of-secure-chosen-to-cre.patch +Patch0115: hw-arm-virt-dt-add-kaslr-seed-property.patch +Patch0116: target-arm-Restrict-the-Address-Translate-write-oper.patch +Patch0117: target-arm-Make-cpu_register-available-for-other-fil.patch +Patch0118: target-arm-cpu-Update-coding-style-to-make-checkpatc.patch +Patch0119: device_tree-Allow-name-wildcards-in-qemu_fdt_node_pa.patch +Patch0120: device_tree-Constify-compat-in-qemu_fdt_node_path.patch +Patch0121: hw-arm-xlnx-zcu102-Move-arm_boot_info-into-XlnxZCU10.patch +Patch0122: hw-arm-xlnx-zcu102-Disable-unsupported-FDT-firmware-.patch +Patch0123: qcow2-Add-incompatibility-note-between-backing-files.patch +Patch0124: qemu-iotests-allow-qcow2-external-discarded-clusters.patch +Patch0125: block-Add-flags-to-BlockDriver.bdrv_co_truncate.patch +Patch0126: block-Add-flags-to-bdrv-_co-_truncate.patch +Patch0127: block-backend-Add-flags-to-blk_truncate.patch +Patch0128: qcow2-Support-BDRV_REQ_ZERO_WRITE-for-truncate.patch +Patch0129: raw-format-Support-BDRV_REQ_ZERO_WRITE-for-truncate.patch +Patch0130: file-posix-Support-BDRV_REQ_ZERO_WRITE-for-truncate.patch +Patch0131: block-truncate-Don-t-make-backing-file-data-visible.patch +Patch0132: iotests-Filter-testfiles-out-in-filter_img_info.patch +Patch0133: iotests-Test-committing-to-short-backing-file.patch +Patch0134: qcow2-Forward-ZERO_WRITE-flag-for-full-preallocation.patch +Patch0135: nvme-introduce-PMR-support-from-NVMe-1.4-spec.patch +Patch0136: qom-Factor-out-user_creatable_add_dict.patch +Patch0137: qemu-storage-daemon-Fix-non-string-object-properties.patch +Patch0138: virtiofsd-add-rlimit-nofile-NUM-option.patch +Patch0139: virtiofsd-stay-below-fs.file-max-sysctl-value-CVE-20.patch +Patch0140: virtiofsd-jail-lo-proc_self_fd.patch +Patch0141: virtiofsd-Show-submounts.patch +Patch0142: virtiofsd-only-retain-file-system-capabilities.patch +Patch0143: virtiofsd-drop-all-capabilities-in-the-wait-parent-p.patch +Patch0144: hw-rdma-Destroy-list-mutex-when-list-is-destroyed.patch +Patch0145: scsi-esp-pci-add-g_assert-for-fix-clang-analyzer-war.patch +Patch0146: display-blizzard-use-extract16-for-fix-clang-analyze.patch +Patch0147: timer-exynos4210_mct-Remove-redundant-statement-in-e.patch +Patch0148: target-arm-Make-VQDMULL-undefined-when-U-1.patch +Patch0149: hw-arm-mps2-tz-Use-TYPE_IOTKIT-instead-of-hardcoded-.patch +Patch0150: target-arm-Don-t-use-a-TLB-for-ARMMMUIdx_Stage2.patch +Patch0151: target-arm-Use-enum-constant-in-get_phys_addr_lpae-c.patch +Patch0152: target-arm-Add-new-s1_is_el0-argument-to-get_phys_ad.patch +Patch0153: target-arm-Implement-ARMv8.2-TTS2UXN.patch +Patch0154: target-arm-Use-correct-variable-for-setting-max-cpu-.patch +Patch0155: target-arm-Use-uint64_t-for-midr-field-in-CPU-state-.patch +Patch0156: hw-arm-versal-Remove-inclusion-of-arm_gicv3_common.h.patch +Patch0157: hw-arm-versal-Move-misplaced-comment.patch +Patch0158: hw-arm-versal-virt-Fix-typo-xlnx-ve-xlnx-versal.patch +Patch0159: hw-arm-versal-Embed-the-UARTs-into-the-SoC-type.patch +Patch0160: hw-arm-versal-Embed-the-GEMs-into-the-SoC-type.patch +Patch0161: hw-arm-versal-Embed-the-ADMAs-into-the-SoC-type.patch +Patch0162: hw-arm-versal-Embed-the-APUs-into-the-SoC-type.patch +Patch0163: hw-arm-versal-Add-support-for-SD.patch +Patch0164: hw-arm-versal-Add-support-for-the-RTC.patch +Patch0165: hw-arm-versal-virt-Add-support-for-SD.patch +Patch0166: hw-arm-versal-virt-Add-support-for-the-RTC.patch +Patch0167: target-arm-translate-vfp.inc.c-Remove-duplicate-simd.patch +Patch0168: target-arm-Don-t-allow-Thumb-Neon-insns-without-FEAT.patch +Patch0169: target-arm-Add-stubs-for-AArch32-Neon-decodetree.patch +Patch0170: target-arm-Convert-VCMLA-vector-to-decodetree.patch +Patch0171: target-arm-Convert-VCADD-vector-to-decodetree.patch +Patch0172: target-arm-Convert-V-US-DOT-vector-to-decodetree.patch +Patch0173: target-arm-Convert-VFM-AS-L-vector-to-decodetree.patch +Patch0174: target-arm-Convert-VCMLA-scalar-to-decodetree.patch +Patch0175: target-arm-Convert-V-US-DOT-scalar-to-decodetree.patch +Patch0176: target-arm-Convert-VFM-AS-L-scalar-to-decodetree.patch +Patch0177: target-arm-Convert-Neon-load-store-multiple-structur.patch +Patch0178: target-arm-Convert-Neon-load-single-structure-to-all.patch +Patch0179: target-arm-Convert-Neon-load-store-single-structure-.patch +Patch0180: target-arm-Convert-Neon-3-reg-same-VADD-VSUB-to-deco.patch +Patch0181: target-arm-Convert-Neon-3-reg-same-logic-ops-to-deco.patch +Patch0182: target-arm-Convert-Neon-3-reg-same-VMAX-VMIN-to-deco.patch +Patch0183: target-arm-Convert-Neon-3-reg-same-comparisons-to-de.patch +Patch0184: target-arm-Convert-Neon-3-reg-same-VQADD-VQSUB-to-de.patch +Patch0185: target-arm-Convert-Neon-3-reg-same-VMUL-VMLA-VMLS-VS.patch +Patch0186: target-arm-Move-gen_-function-typedefs-to-translate..patch +Patch0187: MAINTAINERS-Mark-the-LatticeMico32-target-as-orphan.patch +Patch0188: hw-mem-pc-dimm-Print-slot-number-on-error-at-pc_dimm.patch +Patch0189: hw-mem-pc-dimm-Fix-line-over-80-characters-warning.patch +Patch0190: elf_ops-Don-t-try-to-g_mapped_file_unref-NULL.patch +Patch0191: MAINTAINERS-Update-Keith-Busch-s-email-address.patch +Patch0192: chardev-Add-macOS-to-list-of-OSes-that-support-chard.patch +Patch0193: Compress-lines-for-immediate-return.patch +Patch0194: block-Avoid-dead-assignment.patch +Patch0195: blockdev-Remove-dead-assignment.patch +Patch0196: hw-i2c-pm_smbus-Remove-dead-assignment.patch +Patch0197: hw-input-adb-kbd-Remove-dead-assignment.patch +Patch0198: hw-ide-sii3112-Remove-dead-assignment.patch +Patch0199: hw-isa-i82378-Remove-dead-assignment.patch +Patch0200: hw-gpio-aspeed_gpio-Remove-dead-assignment.patch +Patch0201: hw-timer-stm32f2xx_timer-Remove-dead-assignment.patch +Patch0202: hw-timer-pxa2xx_timer-Add-assertion-to-silent-static.patch +Patch0203: hw-pci-pcie-Forbid-hot-plug-if-it-s-disabled-on-the-.patch +Patch0204: hw-pci-pcie-Replace-PCI_DEVICE-casts-with-existing-v.patch +Patch0205: move-typedef-Aml-to-qemu-types.h.patch +Patch0206: acpi-add-aml-builder-stubs.patch +Patch0207: qtest-allow-DSDT-acpi-table-changes.patch +Patch0208: acpi-drop-pointless-_STA-method.patch +Patch0209: acpi-add-ISADeviceClass-build_aml.patch +Patch0210: rtc-add-RTC_ISA_BASE.patch +Patch0211: virtio-vga-fix-virtio-vga-bar-ordering.patch +Patch0212: virtio-pci-update-virtio-pci-bar-layout-documentatio.patch +Patch0213: vhost-user-blk-fix-invalid-memory-access.patch +Patch0214: checkpatch-fix-acpi-check-with-multiple-file-name.patch +Patch0215: checkpatch-ignore-allowed-diff-list.patch +Patch0216: acpi-DSDT-without-_STA.patch +Patch0217: hw-acpi-nvdimm-Fix-for-NVDIMM-incorrect-DSM-output-b.patch +Patch0218: nvdimm-Use-configurable-ACPI-IO-base-and-size.patch +Patch0219: hw-arm-virt-Add-nvdimm-hot-plug-infrastructure.patch +Patch0220: hw-arm-virt-Add-nvdimm-hotplug-support.patch +Patch0221: tests-Update-ACPI-tables-list-for-upcoming-arm-virt-.patch +Patch0222: bios-tables-test-test-pc-dimm-and-nvdimm-coldplug-fo.patch +Patch0223: tests-acpi-add-expected-tables-for-bios-tables-test.patch +Patch0224: Refactor-vhost_user_set_mem_table-functions.patch +Patch0225: acpi-unit-test-Ignore-diff-in-WAET-ACPI-table.patch +Patch0226: acpi-Add-Windows-ACPI-Emulated-Device-Table-WAET.patch +Patch0227: acpi-unit-test-Update-WAET-ACPI-Table-expected-binar.patch +Patch0228: hw-i386-pc-Create-vmport-device-in-place.patch +Patch0229: hw-i386-vmport-Remove-unused-hw-input-i8042.h-includ.patch +Patch0230: hw-i386-Add-vmport.h-local-header.patch +Patch0231: hw-i386-Make-vmmouse-helpers-static.patch +Patch0232: fuzz-select-fuzz-target-using-executable-name.patch +Patch0233: lockable-fix-__COUNTER__-macro-to-be-referenced-prop.patch +Patch0234: lockable-replaced-locks-with-lock-guard-macros-where.patch +Patch0235: lockable-Replace-locks-with-lock-guard-macros.patch +Patch0236: tools-Fix-use-of-fcntl-F_SETFD-during-socket-activat.patch +Patch0237: iotests-041-Fix-NBD-socket-path.patch +Patch0238: block-nbd-client-drop-max_block-restriction-from-blo.patch +Patch0239: block-nbd-client-drop-max_block-restriction-from-dis.patch +Patch0240: iotests-do-a-light-delinting.patch +Patch0241: iotests-don-t-use-format-for-drive_add.patch +Patch0242: iotests-ignore-import-warnings-from-pylint.patch +Patch0243: iotests-replace-mutable-list-default-args.patch +Patch0244: iotests-add-pylintrc-file.patch +Patch0245: iotests-alphabetize-standard-imports.patch +Patch0246: iotests-drop-pre-Python-3.4-compatibility-code.patch +Patch0247: iotests-touch-up-log-function-signature.patch +Patch0248: iotests-limit-line-length-to-79-chars.patch +Patch0249: iotests-add-hmp-helper-with-logging.patch +Patch0250: iotests-add-script_initialize.patch +Patch0251: iotest-258-use-script_main.patch +Patch0252: iotests-Mark-verify-functions-as-private.patch +Patch0253: iotests-use-python-logging-for-iotests.log.patch +Patch0254: block-Add-blk_new_with_bs-helper.patch +Patch0255: qcow2-Allow-resize-of-images-with-internal-snapshots.patch +Patch0256: qcow2-Tweak-comment-about-bitmaps-vs.-resize.patch +Patch0257: block-Comment-cleanups.patch +Patch0258: Fix-iotest-153.patch +Patch0259: block-block-copy-rename-in-flight-requests-to-tasks.patch +Patch0260: block-block-copy-alloc-task-on-each-iteration.patch +Patch0261: block-block-copy-add-state-pointer-to-BlockCopyTask.patch +Patch0262: block-block-copy-refactor-task-creation.patch +Patch0263: block-block-copy-use-aio-task-pool-API.patch +Patch0264: hw-core-register-Add-register_init_block8-helper.patch +Patch0265: travis.yml-show-free-disk-space-at-end-of-run.patch +Patch0266: travis.yml-drop-MacOSX.patch +Patch0267: cirrus.yml-bump-FreeBSD-to-the-current-stable-relea.patch +Patch0268: cirrus.yml-bootstrap-pkg-unconditionally.patch +Patch0269: travis.yml-reduce-the-load-on-ppc64-GCC-check-tcg.patch +Patch0270: configure-favour-gdb-multiarch-if-we-have-it.patch +Patch0271: gdbstub-Introduce-gdb_get_float64-to-get-64-bit-floa.patch +Patch0272: tests-tcg-better-trap-gdb-failures.patch +Patch0273: tests-tcg-drop-inferior.was_attached-test.patch +Patch0274: gdbstub-eliminate-gdbserver_fd-global.patch +Patch0275: gdbstub-linux-user-support-debugging-over-a-unix-soc.patch +Patch0276: tests-guest-debug-use-the-unix-socket-for-linux-user.patch +Patch0277: tests-tcg-add-a-multiarch-linux-user-gdb-test.patch +Patch0278: target-m68k-fix-gdb-for-m68xxx.patch +Patch0279: tpm-tpm-tis-device-set-PPI-to-false-by-default.patch +Patch0280: hw-arm-virt-Remove-the-compat-forcing-tpm-tis-device.patch +Patch0281: hw-add-compat-machines-for-5.1.patch +Patch0282: tcg-Add-tcg_gen_gvec_dup_imm.patch +Patch0283: target-s390x-Use-tcg_gen_gvec_dup_imm.patch +Patch0284: target-ppc-Use-tcg_gen_gvec_dup_imm.patch +Patch0285: target-arm-Use-tcg_gen_gvec_dup_imm.patch +Patch0286: tcg-Use-tcg_gen_gvec_dup_imm-in-logical-simplificati.patch +Patch0287: tcg-Remove-tcg_gen_gvec_dup-8-16-32-64-i.patch +Patch0288: tcg-Add-tcg_gen_gvec_dup_tl.patch +Patch0289: tcg-Improve-vector-tail-clearing.patch +Patch0290: tcg-Add-load_dest-parameter-to-GVecGen2.patch +Patch0291: tcg-Fix-integral-argument-type-to-tcg_gen_rot-rl-i_i.patch +Patch0292: target-ppc-Improve-syscall-exception-logging.patch +Patch0293: spapr-Don-t-check-capabilities-removed-between-CAS-c.patch +Patch0294: ppc-spapr-tweak-change-system-reset-helper.patch +Patch0295: ppc-pnv-Add-support-for-NMI-interface.patch +Patch0296: spapr-Simplify-selection-of-radix-hash-during-CAS.patch +Patch0297: spapr-cas-Separate-CAS-handling-from-rebuilding-the-.patch +Patch0298: spapr-Drop-CAS-reboot-flag.patch +Patch0299: target-ppc-Enforce-that-the-root-page-directory-size.patch +Patch0300: target-ppc-Introduce-a-relocation-bool-in-ppc_radix6.patch +Patch0301: target-ppc-Assert-if-HV-mode-is-set-when-running-und.patch +Patch0302: spapr-Don-t-allow-unplug-of-NVLink2-devices.patch +Patch0303: target-ppc-Introduce-ppc_radix64_xlate-for-Radix-tre.patch +Patch0304: target-ppc-Extend-ppc_radix64_check_prot-with-a-part.patch +Patch0305: target-ppc-Rework-ppc_radix64_walk_tree-for-partitio.patch +Patch0306: target-ppc-Add-support-for-Radix-partition-scoped-tr.patch +Patch0307: spapr_nvdimm.c-make-label-size-mandatory.patch +Patch0308: spapr_nvdimm-Tweak-error-messages.patch +Patch0309: target-ppc-fix-rlwimi-rlwinm-rlwnm-for-Clang-9.patch +Patch0310: crypto-fix-getter-of-a-QCryptoSecret-s-property.patch +Patch0311: crypto-secret-fix-inconsequential-errors.patch +Patch0312: crypto-Redundant-type-conversion-for-AES_KEY-pointer.patch +Patch0313: block-luks-better-error-message-when-creating-too-la.patch +Patch0314: crypto-extend-hash-benchmark-to-cover-more-algorithm.patch +Patch0315: migration-fix-bad-indentation-in-error_report.patch +Patch0316: migration-migration-improve-error-reporting-for-migr.patch +Patch0317: monitor-hmp-cmds-add-hmp_handle_error-for-hmp_migrat.patch +Patch0318: migration-move-the-units-of-migrate-parameters-from-.patch +Patch0319: docs-devel-migration-start-a-debugging-section.patch +Patch0320: migration-colo-Add-missing-error-propagation-code.patch +Patch0321: migration-throttle-Add-cpu-throttle-tailslow-migrati.patch +Patch0322: migration-ram-Consolidate-variable-reset-after-place.patch +Patch0323: migration-rdma-fix-a-memleak-on-error-path-in-rdma_s.patch +Patch0324: migration-xbzrle-add-encoding-rate.patch +Patch0325: migration-multifd-fix-memleaks-in-multifd_new_send_c.patch +Patch0326: migration-multifd-Do-error_free-after-migrate_set_er.patch +Patch0327: iotests-handle-tmpfs.patch +Patch0328: iotests-082-require-bochs.patch +Patch0329: iotests-148-use-skip_if_unsupported.patch +Patch0330: iotests-041-drop-self.assert_no_active_block_jobs.patch +Patch0331: iotests-055-refactor-compressed-backup-to-vmdk.patch +Patch0332: iotests-055-skip-vmdk-target-tests-if-vmdk-is-not-wh.patch +Patch0333: iotests-109-mark-required-formats-as-required-to-sup.patch +Patch0334: iotests-113-mark-bochs-as-required-to-support-whitel.patch +Patch0335: qcow2-Avoid-integer-wraparound-in-qcow2_co_truncate.patch +Patch0336: vmdk-Rename-VmdkMetaData.valid-to-new_allocation.patch +Patch0337: vmdk-Fix-zero-cluster-allocation.patch +Patch0338: vmdk-Fix-partial-overwrite-of-zero-cluster.patch +Patch0339: vmdk-Don-t-update-L2-table-for-zero-write-on-zero-cl.patch +Patch0340: vmdk-Flush-only-once-in-vmdk_L2update.patch +Patch0341: iotests-vmdk-Enable-zeroed_grained-on-by-default.patch +Patch0342: iotests-283-Use-consistent-size-for-source-and-targe.patch +Patch0343: backup-Improve-error-for-bdrv_getlength-failure.patch +Patch0344: backup-Make-sure-that-source-and-target-size-match.patch +Patch0345: iotests-Backup-with-different-source-target-size.patch +Patch0346: iotests-055-Use-cache.no-flush-for-vmdk-target.patch +Patch0347: qcow2-Fix-preallocation-on-block-devices.patch +Patch0348: gluster-Drop-useless-has_zero_init-callback.patch +Patch0349: file-win32-Support-BDRV_REQ_ZERO_WRITE-for-truncate.patch +Patch0350: nfs-Support-BDRV_REQ_ZERO_WRITE-for-truncate.patch +Patch0351: rbd-Support-BDRV_REQ_ZERO_WRITE-for-truncate.patch +Patch0352: sheepdog-Support-BDRV_REQ_ZERO_WRITE-for-truncate.patch +Patch0353: ssh-Support-BDRV_REQ_ZERO_WRITE-for-truncate.patch +Patch0354: parallels-Rework-truncation-logic.patch +Patch0355: vhdx-Rework-truncation-logic.patch +Patch0356: block-Drop-unused-.bdrv_has_zero_init_truncate.patch +Patch0357: aspeed-Add-boot-stub-for-smp-booting.patch +Patch0358: target-arm-Drop-access_el3_aa32ns_aa64any.patch +Patch0359: aspeed-Support-AST2600A1-silicon-revision.patch +Patch0360: aspeed-sdmc-Implement-AST2600-locking-behaviour.patch +Patch0361: hw-arm-nrf51-Add-NRF51_PERIPHERAL_SIZE-definition.patch +Patch0362: hw-timer-nrf51_timer-Display-timer-ID-in-trace-event.patch +Patch0363: hw-timer-nrf51_timer-Add-trace-event-of-counter-valu.patch +Patch0364: exec-Add-block-comments-for-watchpoint-routines.patch +Patch0365: exec-Fix-cpu_watchpoint_address_matches-address-leng.patch +Patch0366: accel-tcg-Add-block-comment-for-probe_access.patch +Patch0367: accel-tcg-Adjust-probe_access-call-to-page_check_ran.patch +Patch0368: accel-tcg-Add-probe_access_flags.patch +Patch0369: accel-tcg-Add-endian-specific-cpu_-ld-st-operations.patch +Patch0370: target-arm-Use-cpu_-_data_ra-for-sve_ldst_tlb_fn.patch +Patch0371: target-arm-Drop-manual-handling-of-set-clear_helper_.patch +Patch0372: target-arm-Add-sve-infrastructure-for-page-lookup.patch +Patch0373: target-arm-Adjust-interface-of-sve_ld1_host_fn.patch +Patch0374: target-arm-Use-SVEContLdSt-in-sve_ld1_r.patch +Patch0375: target-arm-Handle-watchpoints-in-sve_ld1_r.patch +Patch0376: target-arm-Use-SVEContLdSt-for-multi-register-contig.patch +Patch0377: target-arm-Update-contiguous-first-fault-and-no-faul.patch +Patch0378: target-arm-Use-SVEContLdSt-for-contiguous-stores.patch +Patch0379: target-arm-Reuse-sve_probe_page-for-gather-first-fau.patch +Patch0380: target-arm-Reuse-sve_probe_page-for-scatter-stores.patch +Patch0381: target-arm-Reuse-sve_probe_page-for-gather-loads.patch +Patch0382: target-arm-Remove-sve_memopidx.patch +Patch0383: target-arm-kvm-Inline-set_feature-calls.patch +Patch0384: target-arm-Make-set_feature-available-for-other-file.patch +Patch0385: target-arm-cpu-Use-ARRAY_SIZE-to-iterate-over-ARMCPU.patch +Patch0386: target-arm-cpu-Restrict-v8M-IDAU-interface-to-Aarch3.patch +Patch0387: target-arm-Restrict-TCG-cpus-to-TCG-accel.patch +Patch0388: hw-arm-musicpal-Map-the-UART-devices-unconditionally.patch +Patch0389: target-arm-Use-tcg_gen_gvec_5_ptr-for-sve-FMLA-FCMLA.patch +Patch0390: target-arm-Fix-tcg_gen_gvec_dup_imm-vs-DUP-indexed.patch +Patch0391: hw-tpm-fix-usage-of-bool-in-tpm-tis.c.patch +Patch0392: qcow2-introduce-compression-type-feature.patch +Patch0393: qcow2-rework-the-cluster-compression-routine.patch +Patch0394: qcow2-add-zstd-cluster-compression.patch +Patch0395: iotests-287-add-qcow2-compression-type-test.patch +Patch0396: block-block-copy-fix-use-after-free-of-task-pointer.patch +Patch0397: MAINTAINERS-Upgrade-myself-as-9pfs-co-maintainer.patch +Patch0398: qemu-options.hx-9p-clarify-virtfs-vs.-fsdev.patch +Patch0399: 9pfs-local-ignore-O_NOATIME-if-we-don-t-have-permiss.patch +Patch0400: xen-9pfs-Fix-log-messages-of-reply-errors.patch +Patch0401: hw-net-xilinx_axienet-Auto-clear-PHY-Autoneg.patch +Patch0402: hw-net-xilinx_axienet-Cleanup-stream-push-assignment.patch +Patch0403: hw-net-xilinx_axienet-Remove-unncessary-cast.patch +Patch0404: hw-dma-xilinx_axidma-Add-DMA-memory-region-property.patch +Patch0405: hw-core-stream-Add-an-end-of-packet-flag.patch +Patch0406: hw-net-xilinx_axienet-Handle-fragmented-packets-from.patch +Patch0407: hw-dma-xilinx_axidma-mm2s-Stream-descriptor-by-descr.patch +Patch0408: hw-dma-xilinx_axidma-s2mm-Support-stream-fragments.patch +Patch0409: MAINTAINERS-Add-myself-as-streams-maintainer.patch +Patch0410: target-microblaze-Add-MFS-Rd-EDR-translation.patch +Patch0411: target-microblaze-Fix-FPU2-instruction-check.patch +Patch0412: ui-improve-show-cursor-deprecation-message.patch +Patch0413: ui-sdl2-fix-segment-fault-caused-by-null-pointer-der.patch +Patch0414: target-microblaze-gdb-Extend-the-number-of-registers.patch +Patch0415: target-microblaze-gdb-Fix-incorrect-SReg-reporting.patch +Patch0416: target-microblaze-monitor-Increase-the-number-of-reg.patch +Patch0417: target-arm-Use-correct-GDB-XML-for-M-profile-cores.patch +Patch0418: target-arm-Create-gen_gvec_-us-sra.patch +Patch0419: target-arm-Create-gen_gvec_-u-s-rshr-rsra.patch +Patch0420: target-arm-Create-gen_gvec_-sri-sli.patch +Patch0421: target-arm-Remove-unnecessary-range-check-for-VSHL.patch +Patch0422: target-arm-Tidy-handle_vec_simd_shri.patch +Patch0423: target-arm-Create-gen_gvec_-ceq-clt-cle-cgt-cge-0.patch +Patch0424: target-arm-Create-gen_gvec_-mla-mls.patch +Patch0425: target-arm-Swap-argument-order-for-VSHL-during-decod.patch +Patch0426: target-arm-Create-gen_gvec_-cmtst-ushl-sshl.patch +Patch0427: target-arm-Create-gen_gvec_-uqadd-sqadd-uqsub-sqsub.patch +Patch0428: target-arm-Remove-fp_status-from-helper_-recpe-rsqrt.patch +Patch0429: target-arm-Create-gen_gvec_-qrdmla-qrdmls.patch +Patch0430: target-arm-Pass-pointer-to-qc-to-qrdmla-qrdmls.patch +Patch0431: target-arm-Clear-tail-in-gvec_fmul_idx_-gvec_fmla_id.patch +Patch0432: target-arm-Vectorize-SABD-UABD.patch +Patch0433: target-arm-Vectorize-SABA-UABA.patch +Patch0434: aspeed-Add-support-for-the-sonorapass-bmc-board.patch +Patch0435: acpi-nvdimm-change-NVDIMM_UUID_LE-to-a-common-macro.patch +Patch0436: hw-arm-virt-Introduce-a-RAS-machine-option.patch +Patch0437: docs-APEI-GHES-generation-and-CPER-record-descriptio.patch +Patch0438: ACPI-Build-related-register-address-fields-via-hardw.patch +Patch0439: ACPI-Build-Hardware-Error-Source-Table.patch +Patch0440: ACPI-Record-the-Generic-Error-Status-Block-address.patch +Patch0441: KVM-Move-hwpoison-page-related-functions-into-kvm-al.patch +Patch0442: ACPI-Record-Generic-Error-Status-Block-GESB-table.patch +Patch0443: target-arm-kvm64-handle-SIGBUS-signal-from-kernel-or.patch +Patch0444: MAINTAINERS-Add-ACPI-HEST-GHES-entries.patch +Patch0445: target-arm-Convert-Neon-3-reg-same-VQRDMLAH-VQRDMLSH.patch +Patch0446: target-arm-Convert-Neon-3-reg-same-SHA-to-decodetree.patch +Patch0447: target-arm-Convert-Neon-64-bit-element-3-reg-same-in.patch +Patch0448: target-arm-Convert-Neon-VHADD-3-reg-same-insns.patch +Patch0449: target-arm-Convert-Neon-VABA-VABD-3-reg-same-to-deco.patch +Patch0450: target-arm-Convert-Neon-VRHADD-VHSUB-3-reg-same-insn.patch +Patch0451: target-arm-Convert-Neon-VQSHL-VRSHL-VQRSHL-3-reg-sam.patch +Patch0452: target-arm-Convert-Neon-VPMAX-VPMIN-3-reg-same-insns.patch +Patch0453: target-arm-Convert-Neon-VPADD-3-reg-same-insns-to-de.patch +Patch0454: target-arm-Convert-Neon-VQDMULH-VQRDMULH-3-reg-same-.patch +Patch0455: target-arm-Convert-Neon-VADD-VSUB-VABD-3-reg-same-in.patch +Patch0456: target-arm-Convert-Neon-VPMIN-VPMAX-VPADD-float-3-re.patch +Patch0457: target-arm-Convert-Neon-fp-VMUL-VMLA-VMLS-3-reg-same.patch +Patch0458: target-arm-Convert-Neon-3-reg-same-compare-insns-to-.patch +Patch0459: target-arm-Move-env-argument-of-recps_f32-and-rsqrts.patch +Patch0460: target-arm-Convert-Neon-fp-VMAX-VMIN-VMAXNM-VMINNM-V.patch +Patch0461: target-arm-Convert-NEON-VFMA-VFMS-3-reg-same-insns-t.patch +Patch0462: qom-Clearer-reference-counting-in-object_initialize_.patch +Patch0463: qom-Clean-up-inconsistent-use-of-gchar-vs.-char.patch +Patch0464: qom-Drop-object_property_del_child-s-unused-paramete.patch +Patch0465: qom-Simplify-object_property_get_enum_get_str.patch +Patch0466: qom-Drop-convenience-method-object_property_get_uint.patch +Patch0467: qom-Make-all-the-object_property_add_FOO-return-the-.patch +Patch0468: qom-Drop-object_property_set_description-parameter-e.patch +Patch0469: tests-check-qom-proplist-Improve-iterator-coverage.patch +Patch0470: s390x-cpumodel-Fix-UI-to-CPU-features-pcc-cmac-aes-e.patch +Patch0471: hw-isa-superio-Make-the-components-QOM-children.patch +Patch0472: e1000-Don-t-run-e1000_instance_init-twice.patch +Patch0473: hw-arm-bcm2835-Drop-futile-attempts-at-QOM-adopting-.patch +Patch0474: qdev-Clean-up-qdev_connect_gpio_out_named.patch +Patch0475: qom-Drop-parameter-errp-of-object_property_add-frien.patch +Patch0476: Drop-more-errp-parameters-after-previous-commit.patch +Patch0477: qdev-Unrealize-must-not-fail.patch +Patch0478: spapr_pci-Drop-some-dead-error-handling.patch +Patch0479: qom-Drop-errp-parameter-of-object_property_del.patch +Patch0480: target-Remove-unnecessary-CPU-cast.patch +Patch0481: various-Remove-unnecessary-OBJECT-cast.patch +Patch0482: hw-Remove-unnecessary-DEVICE-cast.patch +Patch0483: tests-fuzz-Makefile-Do-not-link-code-using-unavailab.patch +Patch0484: Makefile-List-fuzz-targets-in-make-help.patch +Patch0485: tests-fuzz-Add-missing-space-in-test-description.patch +Patch0486: tests-fuzz-Remove-unuseful-unused-typedefs.patch +Patch0487: tests-fuzz-Extract-pciconfig_fuzz_qos-method.patch +Patch0488: tests-fuzz-Extract-ioport_fuzz_qtest-method.patch +Patch0489: tests-guest-debug-catch-hanging-guests.patch +Patch0490: travis.yml-Improve-the-disable-tcg-test-on-s390x.patch +Patch0491: linux-user-completely-re-write-init_guest_space.patch +Patch0492: exec-cpu-all-Use-bool-for-have_guest_base.patch +Patch0493: accel-tcg-Relax-va-restrictions-on-64-bit-guests.patch +Patch0494: accel-tcg-don-t-disable-exec_tb-trace-events.patch +Patch0495: disas-include-an-optional-note-for-the-start-of-disa.patch +Patch0496: disas-add-optional-note-support-to-cap_disas.patch +Patch0497: translate-all-include-guest-address-in-out_asm-outpu.patch +Patch0498: qemu-plugin-Trivial-code-movement.patch +Patch0499: qemu-plugin-Move-CONFIG_PLUGIN-stubs-altogether.patch +Patch0500: qemu-qemu-plugin-Make-qemu_plugin_hwaddr_is_io-hwadd.patch +Patch0501: MAINTAINERS-update-the-orphaned-cpus-common.c-file.patch +Patch0502: softfloat-silence-sNaN-for-conversions-to-from-float.patch +Patch0503: softfloat-fix-floatx80-pseudo-denormal-addition-subt.patch +Patch0504: softfloat-fix-floatx80-pseudo-denormal-comparisons.patch +Patch0505: softfloat-fix-floatx80-pseudo-denormal-round-to-inte.patch +Patch0506: ati-vga-Do-not-allow-unaligned-access-via-index-regi.patch +Patch0507: hw-display-Include-local-framebuffer.h.patch +Patch0508: Revert-hw-display-ramfb-initialize-fw-config-space-w.patch +Patch0509: Revert-hw-display-ramfb-lock-guest-resolution-after-.patch +Patch0510: ramfb-drop-leftover-debug-message.patch +Patch0511: ramfb-don-t-update-RAMFBState-on-errors.patch +Patch0512: ramfb-add-sanity-checks-to-ramfb_create_display_surf.patch +Patch0513: ramfb-fix-size-calculation.patch +Patch0514: qemu-nbd-Close-inherited-stderr.patch +Patch0515: qemu_img-add-cvtnum_full-to-print-error-reports.patch +Patch0516: qemu-img-validate-image-length-in-img_map.patch +Patch0517: qemu-img-refactor-dump_map_entry-JSON-format-output.patch +Patch0518: qemu-img-Add-start-offset-and-max-length-to-map.patch +Patch0519: iotests-Enhance-223-to-cover-qemu-img-map-improvemen.patch +Patch0520: iotests-109-Don-t-mirror-with-mismatched-size.patch +Patch0521: iotests-229-Use-blkdebug-to-inject-an-error.patch +Patch0522: mirror-Make-sure-that-source-and-target-size-match.patch +Patch0523: iotests-Mirror-with-different-source-target-size.patch +Patch0524: block-replication.c-Avoid-cancelling-the-job-twice.patch +Patch0525: iotests-Fix-incomplete-type-declarations.patch +Patch0526: iotests-Run-pylint-and-mypy-in-a-testcase.patch +Patch0527: block-Add-bdrv_make_empty.patch +Patch0528: block-Add-blk_make_empty.patch +Patch0529: block-Use-blk_make_empty-after-commits.patch +Patch0530: replication-Avoid-blk_make_empty-on-read-only-child.patch +Patch0531: block-Use-bdrv_make_empty-where-possible.patch +Patch0532: block-Mark-commit-mirror-blkreplay-as-filters.patch +Patch0533: block-Add-BlockDriver.is_format.patch +Patch0534: block-Rename-BdrvChildRole-to-BdrvChildClass.patch +Patch0535: block-Add-BdrvChildRole-and-BdrvChildRoleBits.patch +Patch0536: block-Add-BdrvChildRole-to-BdrvChild.patch +Patch0537: block-Pass-BdrvChildRole-to-bdrv_child_perm.patch +Patch0538: block-Pass-BdrvChildRole-to-.inherit_options.patch +Patch0539: block-Pass-parent_is_format-to-.inherit_options.patch +Patch0540: block-Rename-bdrv_inherited_options.patch +Patch0541: block-Add-generic-bdrv_inherited_options.patch +Patch0542: block-Use-bdrv_inherited_options.patch +Patch0543: block-Unify-bdrv_child_cb_attach.patch +Patch0544: block-Unify-bdrv_child_cb_detach.patch +Patch0545: block-Add-child_of_bds.patch +Patch0546: block-Distinguish-paths-in-_format_default_perms.patch +Patch0547: block-Pull-out-bdrv_default_perms_for_cow.patch +Patch0548: block-Pull-out-bdrv_default_perms_for_storage.patch +Patch0549: block-Relax-perms_for_storage-for-data-children.patch +Patch0550: block-Add-bdrv_default_perms.patch +Patch0551: raw-format-Split-raw_read_options.patch +Patch0552: block-Switch-child_format-users-to-child_of_bds.patch +Patch0553: block-Drop-child_format.patch +Patch0554: block-Make-backing-files-child_of_bds-children.patch +Patch0555: block-Drop-child_backing.patch +Patch0556: block-Make-format-drivers-use-child_of_bds.patch +Patch0557: block-Make-filter-drivers-use-child_of_bds.patch +Patch0558: block-Use-child_of_bds-in-remaining-places.patch +Patch0559: tests-Use-child_of_bds-instead-of-child_file.patch +Patch0560: block-Use-bdrv_default_perms.patch +Patch0561: block-Make-bdrv_filter_default_perms-static.patch +Patch0562: block-Drop-bdrv_format_default_perms.patch +Patch0563: block-Drop-child_file.patch +Patch0564: block-Pass-BdrvChildRole-in-remaining-cases.patch +Patch0565: block-Drop-child_class-from-bdrv_child_perm.patch +Patch0566: block-block-copy-Fix-uninitialized-variable-in-block.patch +Patch0567: block-block-copy-Simplify-block_copy_do_copy.patch +Patch0568: iotests-log-messages-from-notrun.patch +Patch0569: hw-ide-ahci-Log-lost-IRQs.patch +Patch0570: iotests-030-Reduce-run-time-by-unthrottling-job-earl.patch +Patch0571: hw-Use-QEMU_IS_ALIGNED-on-parallel-flash-block-size.patch +Patch0572: aio-posix-don-t-duplicate-fd-handler-deletion-in-fdm.patch +Patch0573: aio-posix-disable-fdmon-io_uring-when-GSource-is-use.patch +Patch0574: ui-win32-kbd-hook-handle-AltGr-in-a-hook-procedure.patch +Patch0575: ui-gtk-fix-handling-of-AltGr-key-on-Windows.patch +Patch0576: ui-gkt-release-all-keys-on-grab-broken-event.patch +Patch0577: ui-gtk-remove-unused-code.patch +Patch0578: ui-gtk-remove-unused-variable-ignore_keys.patch +Patch0579: ui-sdl2-fix-handling-of-AltGr-key-on-Windows.patch +Patch0580: ui-sdl2-start-in-full-screen-with-grab-enabled.patch +Patch0581: ui-sdl2-input-use-trace-events-to-debug-key-events.patch +Patch0582: ui-gtk-don-t-pass-on-win-keys-without-keyboard-grab.patch +Patch0583: ui-gtk-use-native-keyboard-scancodes-on-Windows.patch +Patch0584: ui-increase-min-required-GTK-version-to-3.22.0.patch +Patch0585: bitmaps-Update-maintainer.patch +Patch0586: docs-Sort-sections-on-qemu-img-subcommand-parameters.patch +Patch0587: qemu-img-Fix-stale-comments-on-doc-location.patch +Patch0588: block-Make-it-easier-to-learn-which-BDS-support-bitm.patch +Patch0589: blockdev-Promote-several-bitmap-functions-to-non-sta.patch +Patch0590: blockdev-Split-off-basic-bitmap-operations-for-qemu-.patch +Patch0591: softfloat-Use-post-test-for-floatN_mul.patch +Patch0592: softfloat-Replace-flag-with-bool.patch +Patch0593: softfloat-Change-tininess_before_rounding-to-bool.patch +Patch0594: softfloat-Name-rounding-mode-enum.patch +Patch0595: softfloat-Name-compare-relation-enum.patch +Patch0596: softfloat-Inline-float32-compare-specializations.patch +Patch0597: softfloat-Inline-float64-compare-specializations.patch +Patch0598: softfloat-Inline-float128-compare-specializations.patch +Patch0599: softfloat-Inline-floatx80-compare-specializations.patch +Patch0600: softfloat-Return-bool-from-all-classification-predic.patch +Patch0601: qemu-img-Add-bitmap-sub-command.patch +Patch0602: qemu-sockets-add-abstract-UNIX-domain-socket-support.patch +Patch0603: tests-util-sockets-add-abstract-unix-socket-cases.patch +Patch0604: qemu-options-updates-for-abstract-unix-sockets.patch +Patch0605: tests-acceptance-Add-a-test-for-the-canon-a1100-mach.patch +Patch0606: docs-system-Add-Arm-to-the-Integrator-CP-document-ti.patch +Patch0607: docs-system-Sort-Arm-board-index-into-alphabetical-o.patch +Patch0608: docs-system-Document-Arm-Versatile-Express-boards.patch +Patch0609: docs-system-Document-the-various-MPS2-models.patch +Patch0610: docs-system-Document-Musca-boards.patch +Patch0611: linux-user-arm-BKPT-should-cause-SIGTRAP-not-be-a-sy.patch +Patch0612: linux-user-arm-Remove-bogus-SVC-0xf0002-handling.patch +Patch0613: linux-user-arm-Handle-invalid-arm-specific-syscalls-.patch +Patch0614: linux-user-arm-Fix-identification-of-syscall-numbers.patch +Patch0615: target-arm-Remove-unused-GEN_NEON_INTEGER_OP-macro.patch +Patch0616: hw-Move-i.MX-watchdog-driver-to-hw-watchdog.patch +Patch0617: hw-watchdog-Implement-full-i.MX-watchdog-support.patch +Patch0618: hw-arm-fsl-imx25-Wire-up-watchdog.patch +Patch0619: hw-arm-fsl-imx31-Wire-up-watchdog.patch +Patch0620: hw-arm-fsl-imx6-Connect-watchdog-interrupts.patch +Patch0621: hw-arm-fsl-imx6ul-Connect-watchdog-interrupts.patch +Patch0622: hw-arm-fsl-imx7-Instantiate-various-unimplemented-de.patch +Patch0623: hw-arm-fsl-imx7-Connect-watchdog-interrupts.patch +Patch0624: hw-arm-integratorcp-Replace-hw_error-by-qemu_log_mas.patch +Patch0625: hw-arm-pxa2xx-Replace-hw_error-by-qemu_log_mask.patch +Patch0626: hw-char-xilinx_uartlite-Replace-hw_error-by-qemu_log.patch +Patch0627: hw-timer-exynos4210_mct-Replace-hw_error-by-qemu_log.patch +Patch0628: ARM-PL061-Introduce-N_GPIOS.patch +Patch0629: target-arm-Use-tcg_gen_gvec_mov-for-clear_vec_high.patch +Patch0630: target-arm-Use-clear_vec_high-more-effectively.patch +Patch0631: target-arm-Allow-user-mode-code-to-write-CPSR.E-via-.patch +Patch0632: linux-user-arm-Reset-CPSR_E-when-entering-a-signal-h.patch +Patch0633: linux-user-arm-signal.c-Drop-TARGET_CONFIG_CPU_32.patch +Patch0634: hw-block-pflash_cfi01-Removed-an-unused-timer.patch +Patch0635: hw-block-pflash_cfi01-Document-use-of-non-CFI-compli.patch +Patch0636: hw-block-pflash_cfi01-Rename-reset_flash-label-as-mo.patch +Patch0637: hw-block-pflash-Check-return-value-of-blk_pwrite.patch +Patch0638: 9pfs-include-linux-limits.h-for-XATTR_SIZE_MAX.patch +Patch0639: 9p-Lock-directory-streams-with-a-CoMutex.patch +Patch0640: es1370-check-total-frame-count-against-current-frame.patch +Patch0641: hw-audio-gus-Use-AUDIO_HOST_ENDIANNESS-definition-fr.patch +Patch0642: audio-jack-add-JACK-client-audiodev.patch +Patch0643: Revert-9p-init_in_iov_from_pdu-can-truncate-the-size.patch +Patch0644: xen-9pfs-yield-when-there-isn-t-enough-room-on-the-r.patch +Patch0645: xen-9pfs-increase-max-ring-order-to-9.patch +Patch0646: audio-mixeng-fix-clang-10-warning.patch +Patch0647: audio-fix-wavcapture-segfault.patch +Patch0648: audio-Let-audio_sample_to_uint64-use-const-samples-a.patch +Patch0649: audio-Let-capture_callback-handler-use-const-buffer-.patch +Patch0650: hw-mips-mips_fulong2e-Remove-unused-audio-audio.h-in.patch +Patch0651: MAINTAINERS-Add-Huacai-Chen-as-fuloong2e-co-maintain.patch +Patch0652: hw-pci-host-Use-CONFIG_PCI_BONITO-to-select-the-Boni.patch +Patch0653: hw-pci-host-bonito-Fix-DPRINTF-format-strings.patch +Patch0654: hw-pci-host-bonito-Map-peripheral-using-physical-add.patch +Patch0655: hw-pci-host-bonito-Map-all-the-Bonito64-I-O-range.patch +Patch0656: hw-pci-host-bonito-Map-the-different-PCI-ranges-more.patch +Patch0657: hw-pci-host-bonito-Better-describe-the-I-O-CS-region.patch +Patch0658: hw-pci-host-bonito-Set-the-Config-register-reset-val.patch +Patch0659: hw-mips-fuloong2e-Move-code-and-update-a-comment.patch +Patch0660: hw-mips-fuloong2e-Fix-typo-in-Fuloong-machine-name.patch +Patch0661: hw-mips-Rename-malta-mipssim-r4k-jazz-files.patch +Patch0662: hw-mips-malta-Add-some-logging-for-bad-register-offs.patch +Patch0663: hw-mips-mips_int-De-duplicate-KVM-interrupt-delivery.patch +Patch0664: MAINTAINERS-Change-Aleksandar-Rikalo-s-email-address.patch +Patch0665: hw-riscv-spike-Remove-deprecated-ISA-specific-machin.patch +Patch0666: target-riscv-Remove-the-deprecated-CPUs.patch +Patch0667: target-riscv-Drop-support-for-ISA-spec-version-1.09..patch +Patch0668: COVER-RISC-V-Remove-deprecated-ISA-CPUs-and-machines.patch +Patch0669: target-riscv-Set-access-as-data_load-when-validating.patch +Patch0670: target-riscv-Report-errors-validating-2nd-stage-PTEs.patch +Patch0671: target-riscv-Move-the-hfence-instructions-to-the-rvh.patch +Patch0672: target-riscv-Implement-checks-for-hfence.patch +Patch0673: target-riscv-Allow-setting-a-two-stage-lookup-in-the.patch +Patch0674: target-riscv-Allow-generating-hlv-hlvx-hsv-instructi.patch +Patch0675: target-riscv-Do-two-stage-lookups-on-hlv-hlvx-hsv-in.patch +Patch0676: target-riscv-Don-t-allow-guest-to-write-to-htinst.patch +Patch0677: target-riscv-Convert-MSTATUS-MTL-to-GVA.patch +Patch0678: target-riscv-Fix-the-interrupt-cause-code.patch +Patch0679: target-riscv-Update-the-Hypervisor-trap-return-entry.patch +Patch0680: target-riscv-Update-the-CSRs-to-the-v0.6-Hyp-extensi.patch +Patch0681: target-riscv-Only-support-a-single-VSXL-length.patch +Patch0682: target-riscv-Only-support-little-endian-guests.patch +Patch0683: target-riscv-Support-the-v0.6-Hypervisor-extension-C.patch +Patch0684: target-riscv-Return-the-exception-from-invalid-CSR-a.patch +Patch0685: target-riscv-Support-the-Virtual-Instruction-fault.patch +Patch0686: COVER-RISC-V-Update-the-Hypervisor-spec-to-v0.6.1.patch +Patch0687: target-riscv-Fix-HSV-HLV-implementation.patch +Patch0688: hw-riscv-Allow-creating-multiple-instances-of-CLINT.patch +Patch0689: hw-riscv-Allow-creating-multiple-instances-of-PLIC.patch +Patch0690: hw-riscv-Add-helpers-for-RISC-V-multi-socket-NUMA-ma.patch +Patch0691: hw-riscv-spike-Allow-creating-multiple-NUMA-sockets.patch +Patch0692: hw-riscv-virt-Allow-creating-multiple-NUMA-sockets.patch +Patch0693: linux-header-Update-linux-kvm.h.patch +Patch0694: target-riscv-Add-target-riscv-kvm.c-to-place-the-pub.patch +Patch0695: target-riscv-Implement-function-kvm_arch_init_vcpu.patch +Patch0696: target-riscv-Implement-kvm_arch_get_registers.patch +Patch0697: target-riscv-Implement-kvm_arch_put_registers.patch +Patch0698: target-riscv-Support-start-kernel-directly-by-KVM.patch +Patch0699: hw-riscv-PLIC-update-external-interrupt-by-KVM-when-.patch +Patch0700: target-riscv-Handler-KVM_EXIT_RISCV_SBI-exit.patch +Patch0701: target-riscv-add-host-cpu-type.patch +Patch0702: target-riscv-raise-exception-to-HS-mode-at-get_physi.patch +Patch0703: target-riscv-Add-sifive_plic-vmstate.patch +Patch0704: target-riscv-Support-riscv-cpu-vmstate.patch +Patch0705: target-riscv-Add-kvm_riscv_get-put_regs_timer.patch +Patch0706: target-riscv-Implement-virtual-time-adjusting-with-v.patch +Patch0707: target-riscv-Support-virtual-time-context-synchroniz.patch BuildRequires: flex BuildRequires: bison BuildRequires: texinfo BuildRequires: perl-podlators -BuildRequires: kernel BuildRequires: chrpath BuildRequires: gettext BuildRequires: zlib-devel -BuildRequires: gtk3-devel -BuildRequires: gnutls-devel BuildRequires: numactl-devel -BuildRequires: device-mapper-multipath-devel -BuildRequires: rdma-core-devel BuildRequires: libcap-devel -BuildRequires: libcap-ng-devel -BuildRequires: cyrus-sasl-devel -BuildRequires: libaio-devel -BuildRequires: usbredir-devel >= 0.5.2 -BuildRequires: libseccomp-devel >= 2.3.0 -BuildRequires: systemd-devel -BuildRequires: libiscsi-devel -BuildRequires: snappy-devel -BuildRequires: lzo-devel BuildRequires: ncurses-devel BuildRequires: libattr-devel -BuildRequires: libcurl-devel -BuildRequires: libjpeg-devel BuildRequires: libpng-devel -BuildRequires: brlapi-devel BuildRequires: pixman-devel -BuildRequires: libusbx-devel BuildRequires: bzip2-devel -BuildRequires: libepoxy-devel -BuildRequires: libtasn1-devel BuildRequires: libxml2-devel -BuildRequires: libudev-devel -BuildRequires: pam-devel BuildRequires: perl-Test-Harness BuildRequires: python3-devel %ifarch aarch64 @@ -135,13 +738,6 @@ BuildRequires: libfdt-devel BuildRequires: virglrenderer-devel %endif -Requires(post): /usr/bin/getent -Requires(post): /usr/sbin/groupadd -Requires(post): /usr/sbin/useradd -Requires(post): systemd-units -Requires(preun): systemd-units -Requires(postun): systemd-units - %description QEMU is a FAST! processor emulator using dynamic translation to achieve good emulation speed. @@ -177,13 +773,6 @@ Summary: QEMU command line tool for manipulating disk images %description img This package provides a command line tool for manipulating disk images -%ifarch %{ix86} x86_64 -%package seabios -Summary: QEMU seabios -%description seabios -This package include bios-256k.bin and bios.bin of seabios -%endif - %prep %setup -q -n qemu-%{version}%{?rcstr} %autopatch -p1 @@ -195,56 +784,31 @@ buildarch="x86_64-softmmu" %ifarch aarch64 buildarch="aarch64-softmmu" %endif +%ifarch riscv64 +buildarch="riscv64-softmmu" +%endif buildldflags="VL_LDFLAGS=-Wl,--build-id" ./configure \ - --prefix=%{_prefix} \ - --target-list=${buildarch} \ - --extra-cflags="%{optflags} -fPIE -DPIE -fPIC" \ - --extra-ldflags="-Wl,--build-id -pie -Wl,-z,relro -Wl,-z,now -Wl,-z,noexecstack" \ + --prefix=%{_prefix} \ + --target-list=${buildarch} \ --datadir=%{_datadir} \ - --docdir=%{_docdir}/%{name} \ - --libdir=%{_libdir} \ + --docdir=%{_docdir}/%{name} \ + --libdir=%{_libdir} \ --libexecdir=%{_libexecdir} \ --localstatedir=%{_localstatedir} \ --sysconfdir=%{_sysconfdir} \ --interp-prefix=%{_prefix}/qemu-%%M \ - --firmwarepath=%{_datadir}/%{name} \ --with-pkgversion=%{name}-%{version}-%{release} \ - --disable-strip \ - --disable-werror \ - --disable-slirp \ - --enable-gtk \ - --enable-docs \ - --enable-guest-agent \ - --enable-pie \ - --enable-numa \ - --enable-mpath \ - --disable-libnfs \ - --disable-bzip2 \ --enable-kvm \ - --enable-tcg \ - --enable-rdma \ - --enable-linux-aio \ - --enable-cap-ng \ - --enable-vhost-user \ -%ifarch aarch64 - --enable-fdt \ - --enable-virglrenderer \ -%endif - --enable-cap-ng \ - --enable-libusb \ - --disable-bluez \ - --disable-dmg \ - --disable-qcow1 \ - --disable-vdi \ - --disable-vvfat \ - --disable-qed \ - --disable-parallels \ - --disable-sheepdog \ - --disable-capstone \ - --disable-smartcard + --disable-libiscsi \ + --disable-glusterfs \ + --disable-libusb \ + --disable-usb-redir \ + --audio-drv-list= \ + --disable-opengl \ + --disable-libxml2 make %{?_smp_mflags} $buildldflags V=1 @@ -255,7 +819,7 @@ cp -a ${buildarch}/qemu-system-* qemu-kvm make %{?_smp_mflags} DESTDIR=%{buildroot} \ install -%find_lang %{name} +# %find_lang %{name} install -m 0755 qemu-kvm %{buildroot}%{_libexecdir}/ ln -s %{_libexecdir}/qemu-kvm %{buildroot}/%{_bindir}/qemu-kvm @@ -263,20 +827,17 @@ rm %{buildroot}/%{_bindir}/qemu-system-* install -D -p -m 0644 contrib/systemd/qemu-pr-helper.service %{buildroot}%{_unitdir}/qemu-pr-helper.service install -D -p -m 0644 contrib/systemd/qemu-pr-helper.socket %{buildroot}%{_unitdir}/qemu-pr-helper.socket install -D -p -m 0644 qemu.sasl %{buildroot}%{_sysconfdir}/sasl2/qemu.conf -install -D -m 0644 %{_sourcedir}/bridge.conf %{buildroot}%{_sysconfdir}/qemu/bridge.conf -install -D -m 0644 %{_sourcedir}/80-kvm.rules %{buildroot}/usr/lib/udev/rules.d/80-kvm.rules # For qemu-guest-agent package %global _udevdir /lib/udev/rules.d -install -D -p -m 0644 contrib/systemd/qemu-guest-agent.service %{buildroot}%{_unitdir}/qemu-guest-agent.service -install -D -m 0644 %{_sourcedir}/99-qemu-guest-agent.rules %{buildroot}%{_udevdir}/99-qemu-guest-agent.rules mkdir -p %{buildroot}%{_localstatedir}/log touch %{buildroot}%{_localstatedir}/log/qga-fsfreeze-hook.log +# For qemu docs package %global qemudocdir %{_docdir}/%{name} -install -D -p -m 0644 -t %{buildroot}%{qemudocdir} Changelog README COPYING COPYING.LIB LICENSE -chmod -x %{buildroot}%{_mandir}/man1/* - +rm -rf %{buildroot}%{qemudocdir}/specs +install -D -p -m 0644 -t %{buildroot}%{qemudocdir} Changelog COPYING COPYING.LIB LICENSE +# chmod -x %{buildroot}%{_mandir}/man1/* %ifarch aarch64 rm -rf %{buildroot}%{_datadir}/%{name}/vgabios*bin @@ -285,6 +846,11 @@ rm -rf %{buildroot}%{_datadir}/%{name}/linuxboot.bin rm -rf %{buildroot}%{_datadir}/%{name}/kvmvapic.bin rm -rf %{buildroot}%{_datadir}/%{name}/sgabios.bin rm -rf %{buildroot}%{_datadir}/%{name}/multiboot.bin +rm -rf %{buildroot}%{_datadir}/%{name}/linuxboot_dma.bin +rm -rf %{buildroot}%{_datadir}/%{name}/pvh.bin +%endif +%ifarch x86_64 +rm -rf %{buildroot}%{_datadir}/%{name}/vgabios-ati.bin %endif rm -rf %{buildroot}%{_datadir}/%{name}/openbios-* rm -rf %{buildroot}%{_datadir}/%{name}/slof.bin @@ -292,25 +858,32 @@ rm -rf %{buildroot}%{_datadir}/%{name}/QEMU,*.bin rm -rf %{buildroot}%{_datadir}/%{name}/bamboo.dtb rm -rf %{buildroot}%{_datadir}/%{name}/canyonlands.dtb rm -rf %{buildroot}%{_datadir}/%{name}/hppa-firmware.img -rm -rf %{buildroot}%{_datadir}/%{name}/linuxboot_dma.bin rm -rf %{buildroot}%{_datadir}/%{name}/palcode-clipper rm -rf %{buildroot}%{_datadir}/%{name}/petalogix-* rm -rf %{buildroot}%{_datadir}/%{name}/ppc_* -rm -rf %{buildroot}%{_datadir}/%{name}/pvh.bin rm -rf %{buildroot}%{_datadir}/%{name}/qemu_vga.ndrv rm -rf %{buildroot}%{_datadir}/%{name}/s390-* rm -rf %{buildroot}%{_datadir}/%{name}/skiboot.lid rm -rf %{buildroot}%{_datadir}/%{name}/spapr-* rm -rf %{buildroot}%{_datadir}/%{name}/u-boot* rm -rf %{buildroot}%{_bindir}/ivshmem* +rm -f %{buildroot}%{_datadir}/%{name}/edk2* +rm -rf %{buildroot}%{_datadir}/%{name}/firmware +rm -rf %{buildroot}%{_datadir}/%{name}/opensbi* +rm -rf %{buildroot}%{_datadir}/%{name}/qemu-nsis.bmp +%ifarch riscv64 +rm -rf %{buildroot}%{_datadir}/%{name}/* +rm -rf %{buildroot}%{_datadir}/icons/* +rm -rf %{buildroot}%{_datadir}/applications/* +%endif for f in %{buildroot}%{_bindir}/* %{buildroot}%{_libdir}/* \ %{buildroot}%{_libexecdir}/*; do if file $f | grep -q ELF | grep -q -i shared; then chrpath --delete $f; fi done -%check -make check V=1 +# %check +# make check %pre getent group kvm >/dev/null || groupadd -g 36 -r kvm @@ -319,92 +892,26 @@ getent passwd qemu >/dev/null || \ useradd -r -u 107 -g qemu -G kvm -d / -s /sbin/nologin \ -c "qemu user" qemu -%post guest-agent -%systemd_post qemu-guest-agent.service -%preun guest-agent -%systemd_preun qemu-guest-agent.service -%postun guest-agent -%systemd_postun_with_restart qemu-guest-agent.service - -%files -f %{name}.lang -%dir %{_datadir}/%{name}/ +%files %{_libexecdir}/qemu-kvm %{_bindir}/qemu-kvm -%{_datadir}/%{name}/efi-virtio.rom -%{_datadir}/%{name}/efi-e1000.rom -%{_datadir}/%{name}/efi-e1000e.rom -%{_datadir}/%{name}/efi-rtl8139.rom -%{_datadir}/%{name}/efi-pcnet.rom -%{_datadir}/%{name}/efi-ne2k_pci.rom -%{_datadir}/%{name}/efi-eepro100.rom -%{_datadir}/%{name}/efi-vmxnet3.rom -%{_datadir}/%{name}/pxe-virtio.rom -%{_datadir}/%{name}/pxe-e1000.rom -%{_datadir}/%{name}/pxe-ne2k_pci.rom -%{_datadir}/%{name}/pxe-pcnet.rom -%{_datadir}/%{name}/pxe-rtl8139.rom -%{_datadir}/%{name}/pxe-eepro100.rom -%{_datadir}/%{name}/trace-events-all -%{_datadir}/applications/qemu.desktop -%{_datadir}/icons/hicolor/*/apps/* -%{_datadir}/%{name}/keymaps/ -%{_bindir}/elf2dmp %{_bindir}/qemu-edid -%{_bindir}/qemu-keymap %{_bindir}/qemu-pr-helper -%{_bindir}/virtfs-proxy-helper +%{_bindir}/qemu-storage-daemon %{_unitdir}/qemu-pr-helper.service %{_unitdir}/qemu-pr-helper.socket %attr(4755, root, root) %{_libexecdir}/qemu-bridge-helper %config(noreplace) %{_sysconfdir}/sasl2/qemu.conf -%dir %{_sysconfdir}/qemu -%config(noreplace) %{_sysconfdir}/qemu/bridge.conf -/usr/lib/udev/rules.d/80-kvm.rules -%doc %{qemudocdir}/COPYING -%doc %{qemudocdir}/COPYING.LIB -%doc %{qemudocdir}/LICENSE -%ifarch x86_64 -%{_datadir}/%{name}/bios.bin -%{_datadir}/%{name}/bios-256k.bin -%{_datadir}/%{name}/vgabios.bin -%{_datadir}/%{name}/vgabios-cirrus.bin -%{_datadir}/%{name}/vgabios-qxl.bin -%{_datadir}/%{name}/vgabios-stdvga.bin -%{_datadir}/%{name}/vgabios-vmware.bin -%{_datadir}/%{name}/vgabios-virtio.bin -%{_datadir}/%{name}/vgabios-ramfb.bin -%{_datadir}/%{name}/vgabios-bochs-display.bin -%{_datadir}/%{name}/linuxboot.bin -%{_datadir}/%{name}/multiboot.bin -%{_datadir}/%{name}/kvmvapic.bin -%{_datadir}/%{name}/sgabios.bin -%endif %files help %dir %{qemudocdir} -%doc %{qemudocdir}/qemu-doc.html -%doc %{qemudocdir}/qemu-doc.txt -%doc %{qemudocdir}/qemu-ga-ref.html -%doc %{qemudocdir}/qemu-ga-ref.txt -%doc %{qemudocdir}/qemu-qmp-ref.html -%doc %{qemudocdir}/qemu-qmp-ref.txt -%doc %{qemudocdir}/README %doc %{qemudocdir}/Changelog -%{_mandir}/man1/qemu.1* -%{_mandir}/man1/virtfs-proxy-helper.1* -%{_mandir}/man7/qemu-block-drivers.7* -%{_mandir}/man7/qemu-cpu-models.7* -%{_mandir}/man7/qemu-ga-ref.7* -%{_mandir}/man7/qemu-qmp-ref.7* -%{_mandir}/man1/qemu-img.1* -%{_mandir}/man8/qemu-nbd.8* +%doc %{qemudocdir}/COPYING +%doc %{qemudocdir}/COPYING.LIB +%doc %{qemudocdir}/LICENSE %files guest-agent -%defattr(-,root,root,-) %{_bindir}/qemu-ga -%{_mandir}/man8/qemu-ga.8* -%{_unitdir}/qemu-guest-agent.service -%{_udevdir}/99-qemu-guest-agent.rules %ghost %{_localstatedir}/log/qga-fsfreeze-hook.log %files img @@ -412,117 +919,6 @@ getent passwd qemu >/dev/null || \ %{_bindir}/qemu-io %{_bindir}/qemu-nbd -%ifarch %{ix86} x86_64 -%files seabios -%{_datadir}/%{name}/bios-256k.bin -%{_datadir}/%{name}/bios.bin -%endif - %changelog -* Thu Feb 6 2020 Huawei Technologies Co., Ltd. -- spec: remove fno-inline option for configure - -* Thu Jan 16 2020 Huawei Technologies Co., Ltd. -- block: fix memleaks in bdrv_refresh_filename - -* Mon Jan 13 2020 Huawei Technologies Co., Ltd. -- 9pfs: Fix a possible memory leak in local_link -- scsi-disk: disk define props in scsi_block to avoid memleaks -- arm/translate-a64: fix uninitialized variable warning -- nbd: fix uninitialized variable warning -- xhci: Fix memory leak in xhci_kick_epctx when poweroff - -* Mon Jan 6 2020 backport from qemu upstream -- linux headers: update against "KVM/ARM: Fix >256 vcp -- intc/arm_gic: Support IRQ injection for more than 256 vpus -- ARM: KVM: Check KVM_CAP_ARM_IRQ_LINE_LAYOUT_2 for smp_cpus > 256 - -* Thu Dec 12 2019 backport from qemu upstream v4.0.1 release -- usb-tablet: fix serial compat property -- blockdev-backup: don't check aio_context too early -- migration/dirty-bitmaps: change bitmap enumeration method -- target/i386: add MDS-NO feature -- usbredir: fix buffer-overflow on vmload -- tpm: Exit in reset when backend indicates failure -- tpm_emulator: Translate TPM error codes to strings -- util/hbitmap: update orig_size on truncate -- mirror: Only mirror granularity-aligned chunks -- qcow2: Fix the calculation of the maximum L2 cache size -- dma-helpers: ensure AIO callback is invoked after cancellation -- pr-manager: Fix invalid g_free() crash bug -- block/nfs: tear down aio before nfs_close -- blockjob: update nodes head while removing all bdrv -- slirp: Fix heap overflow in ip_reass on big packet input -- slirp: ip_reass: Fix use after free -- hw/core/loader: Fix possible crash in rom_copy() -- migration: Fix use-after-free during process exit - -* Thu Oct 17 2019 backport from qemu upstream -- vnc-fix-memory-leak-when-vnc-disconnect.patch - -* Mon Sep 9 2019 backport from qemu upstream -- ehci-fix-queue-dev-null-ptr-dereference.patch -- memory-unref-the-memory-region-in-simplify-flatview.patch -- scsi-lsi-exit-infinite-loop-while-executing-script-C.patch -- util-async-hold-AioContext-ref-to-prevent-use-after-.patch -- vhost-user-scsi-prevent-using-uninitialized-vqs.patch - -* Fri Aug 30 2019 Huawei Technologies Co., Ltd. -- xhci: Fix memory leak in xhci_address_slot -- xhci: Fix memory leak in xhci_kick_epctx - -* Wed Aug 7 2019 Huawei Technologies Co., Ltd. -- hw/arm/virt: Introduce cpu topology support -- hw/arm64: add vcpu cache info support - -* Tue Aug 6 2019 Huawei Technologies Co., Ltd. -- Update release version to 4.0.0-2 - -* Mon Aug 5 2019 Huawei Technologies Co., Ltd. -- enable make check -- smbios: Add missing member of type 4 for smbios 3.0 - -* Mon Aug 5 2019 fix CVE-2019-13164 -- qemu-bridge-helper: restrict interface name to IFNAMSIZ -- qemu-bridge-helper: move repeating code in parse_acl_file - -* Wed Jul 31 2019 backport from qemu upstream -- block: Fix AioContext switch for bs->drv == NULL -- cutils: Fix size_to_str() on 32-bit platforms -- qcow2: Avoid COW during metadata preallocation -- qcow2: Add errp to preallocate_co() -- qcow2: qcow2: Fix full preallocation with external data file -- qcow2: Fix qcow2_make_empty() with external data file -- megasas: fix mapped frame size -- kbd-state: fix autorepeat handling -- block/file-posix: Unaligned O_DIRECT block-status -- hw: add compat machines for 4.1 -- q35: Revert to kernel irqchip -- hw: Nuke hw_compat_4_0_1 and pc_compat_4_0_1 -- vl: Fix -drive / -blockdev persistent reservation management -- vhost: fix vhost_log size overflow during migration -- virtio-pci: fix missing device properties -- i386/acpi: fix gint overflow in crs_range_compare -- ioapic: kvm: Skip route updates for masked pins -- i386/acpi: show PCI Express bus on pxb-pcie expanders -- virtio-balloon: Fix wrong sign extension of PFNs -- virtio-balloon: Fix QEMU crashes on pagesize > BALLOON_PAGE_SIZE -- virtio-balloon: Simplify deflate with pbp -- virtio-balloon: Better names for offset variables in inflate/deflate code -- virtio-balloon: Rework pbp tracking data -- virtio-balloon: Use temporary PBP only -- virtio-balloon: virtio-balloon: don't track subpages for the PBP -- virtio-balloon: free pbp more aggressively - -* Tue Jul 30 2019 Huawei Technologies Co., Ltd. -- vhost: cancel migration when vhost-user restarted -- pl031: support rtc-timer property for pl031 -- pl011: reset read FIFO when UARTTIMSC=0 & UARTICR=0xffff -- ARM64: record vtimer tick when cpu is stopped - -* Tue Jul 23 2019 openEuler Buildteam - version-release +* Wed Sep 2 2020 Huawei Technologies Co., Ltd - Package init diff --git a/qemu_img-add-cvtnum_full-to-print-error-reports.patch b/qemu_img-add-cvtnum_full-to-print-error-reports.patch new file mode 100644 index 0000000000000000000000000000000000000000..918d689b53f2488f409f36ea3e0f58e8f190a888 --- /dev/null +++ b/qemu_img-add-cvtnum_full-to-print-error-reports.patch @@ -0,0 +1,226 @@ +From 43d589b074370ebc9b340340b5f641b385da9df8 Mon Sep 17 00:00:00 2001 +From: Eyal Moscovici +Date: Wed, 13 May 2020 16:36:26 +0300 +Subject: [PATCH 516/709] qemu_img: add cvtnum_full to print error reports + +All calls to cvtnum check the return value and print the same error +message more or less. And so error reporting moved to cvtnum_full to +reduce code duplication and provide a single error +message. Additionally, cvtnum now wraps cvtnum_full with the existing +default range of 0 to MAX_INT64. + +Acked-by: Mark Kanda +Signed-off-by: Eyal Moscovici +Message-Id: <20200513133629.18508-2-eyal.moscovici@oracle.com> +Reviewed-by: Eric Blake +[eblake: fix printf formatting, avoid trailing space, change error wording, +reformat commit message] +Signed-off-by: Eric Blake +--- + qemu-img.c | 76 +++++++++++++++++--------------------- + tests/qemu-iotests/049.out | 8 ++-- + 2 files changed, 38 insertions(+), 46 deletions(-) + +diff --git a/qemu-img.c b/qemu-img.c +index 6a4327aaba..5d824fc15f 100644 +--- a/qemu-img.c ++++ b/qemu-img.c +@@ -470,19 +470,31 @@ static int add_old_style_options(const char *fmt, QemuOpts *opts, + return 0; + } + +-static int64_t cvtnum(const char *s) ++static int64_t cvtnum_full(const char *name, const char *value, int64_t min, ++ int64_t max) + { + int err; +- uint64_t value; +- +- err = qemu_strtosz(s, NULL, &value); +- if (err < 0) { ++ uint64_t res; ++ ++ err = qemu_strtosz(value, NULL, &res); ++ if (err < 0 && err != -ERANGE) { ++ error_report("Invalid %s specified. You may use " ++ "k, M, G, T, P or E suffixes for", name); ++ error_report("kilobytes, megabytes, gigabytes, terabytes, " ++ "petabytes and exabytes."); + return err; + } +- if (value > INT64_MAX) { ++ if (err == -ERANGE || res > max || res < min) { ++ error_report("Invalid %s specified. Must be between %" PRId64 ++ " and %" PRId64 ".", name, min, max); + return -ERANGE; + } +- return value; ++ return res; ++} ++ ++static int64_t cvtnum(const char *name, const char *value) ++{ ++ return cvtnum_full(name, value, 0, INT64_MAX); + } + + static int img_create(int argc, char **argv) +@@ -572,16 +584,8 @@ static int img_create(int argc, char **argv) + if (optind < argc) { + int64_t sval; + +- sval = cvtnum(argv[optind++]); ++ sval = cvtnum("image size", argv[optind++]); + if (sval < 0) { +- if (sval == -ERANGE) { +- error_report("Image size must be less than 8 EiB!"); +- } else { +- error_report("Invalid image size specified! You may use k, M, " +- "G, T, P or E suffixes for "); +- error_report("kilobytes, megabytes, gigabytes, terabytes, " +- "petabytes and exabytes."); +- } + goto fail; + } + img_size = (uint64_t)sval; +@@ -2187,8 +2191,10 @@ static int img_convert(int argc, char **argv) + { + int64_t sval; + +- sval = cvtnum(optarg); +- if (sval < 0 || !QEMU_IS_ALIGNED(sval, BDRV_SECTOR_SIZE) || ++ sval = cvtnum("buffer size for sparse output", optarg); ++ if (sval < 0) { ++ goto fail_getopt; ++ } else if (!QEMU_IS_ALIGNED(sval, BDRV_SECTOR_SIZE) || + sval / BDRV_SECTOR_SIZE > MAX_BUF_SECTORS) { + error_report("Invalid buffer size for sparse output specified. " + "Valid sizes are multiples of %llu up to %llu. Select " +@@ -4291,9 +4297,8 @@ static int img_bench(int argc, char **argv) + break; + case 'o': + { +- offset = cvtnum(optarg); ++ offset = cvtnum("offset", optarg); + if (offset < 0) { +- error_report("Invalid offset specified"); + return 1; + } + break; +@@ -4306,9 +4311,8 @@ static int img_bench(int argc, char **argv) + { + int64_t sval; + +- sval = cvtnum(optarg); +- if (sval < 0 || sval > INT_MAX) { +- error_report("Invalid buffer size specified"); ++ sval = cvtnum_full("buffer size", optarg, 0, INT_MAX); ++ if (sval < 0) { + return 1; + } + +@@ -4319,9 +4323,8 @@ static int img_bench(int argc, char **argv) + { + int64_t sval; + +- sval = cvtnum(optarg); +- if (sval < 0 || sval > INT_MAX) { +- error_report("Invalid step size specified"); ++ sval = cvtnum_full("step_size", optarg, 0, INT_MAX); ++ if (sval < 0) { + return 1; + } + +@@ -4491,10 +4494,9 @@ static int img_dd_bs(const char *arg, + { + int64_t res; + +- res = cvtnum(arg); ++ res = cvtnum_full("bs", arg, 1, INT_MAX); + +- if (res <= 0 || res > INT_MAX) { +- error_report("invalid number: '%s'", arg); ++ if (res < 0) { + return 1; + } + in->bsz = out->bsz = res; +@@ -4506,10 +4508,9 @@ static int img_dd_count(const char *arg, + struct DdIo *in, struct DdIo *out, + struct DdInfo *dd) + { +- dd->count = cvtnum(arg); ++ dd->count = cvtnum("count", arg); + + if (dd->count < 0) { +- error_report("invalid number: '%s'", arg); + return 1; + } + +@@ -4538,10 +4539,9 @@ static int img_dd_skip(const char *arg, + struct DdIo *in, struct DdIo *out, + struct DdInfo *dd) + { +- in->offset = cvtnum(arg); ++ in->offset = cvtnum("skip", arg); + + if (in->offset < 0) { +- error_report("invalid number: '%s'", arg); + return 1; + } + +@@ -4923,16 +4923,8 @@ static int img_measure(int argc, char **argv) + { + int64_t sval; + +- sval = cvtnum(optarg); ++ sval = cvtnum("image size", optarg); + if (sval < 0) { +- if (sval == -ERANGE) { +- error_report("Image size must be less than 8 EiB!"); +- } else { +- error_report("Invalid image size specified! You may use " +- "k, M, G, T, P or E suffixes for "); +- error_report("kilobytes, megabytes, gigabytes, terabytes, " +- "petabytes and exabytes."); +- } + goto out; + } + img_size = (uint64_t)sval; +diff --git a/tests/qemu-iotests/049.out b/tests/qemu-iotests/049.out +index a5cfba1756..c54ae21b86 100644 +--- a/tests/qemu-iotests/049.out ++++ b/tests/qemu-iotests/049.out +@@ -92,19 +92,19 @@ Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1649267441664 cluster_size=65536 l + == 3. Invalid sizes == + + qemu-img create -f qcow2 TEST_DIR/t.qcow2 -- -1024 +-qemu-img: Image size must be less than 8 EiB! ++qemu-img: Invalid image size specified. Must be between 0 and 9223372036854775807. + + qemu-img create -f qcow2 -o size=-1024 TEST_DIR/t.qcow2 + qemu-img: TEST_DIR/t.qcow2: Value '-1024' is out of range for parameter 'size' + + qemu-img create -f qcow2 TEST_DIR/t.qcow2 -- -1k +-qemu-img: Image size must be less than 8 EiB! ++qemu-img: Invalid image size specified. Must be between 0 and 9223372036854775807. + + qemu-img create -f qcow2 -o size=-1k TEST_DIR/t.qcow2 + qemu-img: TEST_DIR/t.qcow2: Value '-1k' is out of range for parameter 'size' + + qemu-img create -f qcow2 TEST_DIR/t.qcow2 -- 1kilobyte +-qemu-img: Invalid image size specified! You may use k, M, G, T, P or E suffixes for ++qemu-img: Invalid image size specified. You may use k, M, G, T, P or E suffixes for + qemu-img: kilobytes, megabytes, gigabytes, terabytes, petabytes and exabytes. + + qemu-img create -f qcow2 -o size=1kilobyte TEST_DIR/t.qcow2 +@@ -113,7 +113,7 @@ Optional suffix k, M, G, T, P or E means kilo-, mega-, giga-, tera-, peta- + and exabytes, respectively. + + qemu-img create -f qcow2 TEST_DIR/t.qcow2 -- foobar +-qemu-img: Invalid image size specified! You may use k, M, G, T, P or E suffixes for ++qemu-img: Invalid image size specified. You may use k, M, G, T, P or E suffixes for + qemu-img: kilobytes, megabytes, gigabytes, terabytes, petabytes and exabytes. + + qemu-img create -f qcow2 -o size=foobar TEST_DIR/t.qcow2 +-- +2.23.0 + diff --git a/qga-Fix-qmp_guest_get_memory_blocks-error-handling.patch b/qga-Fix-qmp_guest_get_memory_blocks-error-handling.patch new file mode 100644 index 0000000000000000000000000000000000000000..7a64b8f2e3b674e6cd7d3c0cdb1a4255f101aa4b --- /dev/null +++ b/qga-Fix-qmp_guest_get_memory_blocks-error-handling.patch @@ -0,0 +1,42 @@ +From 4155c998b6f7618aad0e67c34c2a4aea841114cf Mon Sep 17 00:00:00 2001 +From: Markus Armbruster +Date: Wed, 22 Apr 2020 15:07:18 +0200 +Subject: [PATCH 026/709] qga: Fix qmp_guest_get_memory_blocks() error handling + +The Error ** argument must be NULL, &error_abort, &error_fatal, or a +pointer to a variable containing NULL. Passing an argument of the +latter kind twice without clearing it in between is wrong: if the +first call sets an error, it no longer points to NULL for the second +call. + +qmp_guest_get_memory_blocks() passes &local_err to +transfer_memory_block() in a loop. If this fails in more than one +iteration, it can trip error_setv()'s assertion. + +Fix it to break the loop. + +Cc: Michael Roth +Signed-off-by: Markus Armbruster +Message-Id: <20200422130719.28225-14-armbru@redhat.com> +Reviewed-by: Eric Blake +--- + qga/commands-posix.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/qga/commands-posix.c b/qga/commands-posix.c +index a52af0315f..ae1348dc8f 100644 +--- a/qga/commands-posix.c ++++ b/qga/commands-posix.c +@@ -2518,6 +2518,9 @@ GuestMemoryBlockList *qmp_guest_get_memory_blocks(Error **errp) + mem_blk->phys_index = strtoul(&de->d_name[6], NULL, 10); + mem_blk->has_can_offline = true; /* lolspeak ftw */ + transfer_memory_block(mem_blk, true, NULL, &local_err); ++ if (local_err) { ++ break; ++ } + + entry = g_malloc0(sizeof *entry); + entry->value = mem_blk; +-- +2.23.0 + diff --git a/qga-Fix-qmp_guest_suspend_-disk-ram-error-handling.patch b/qga-Fix-qmp_guest_suspend_-disk-ram-error-handling.patch new file mode 100644 index 0000000000000000000000000000000000000000..16034b23f6da5e3e2c731fb902b98e1dcaf926e3 --- /dev/null +++ b/qga-Fix-qmp_guest_suspend_-disk-ram-error-handling.patch @@ -0,0 +1,71 @@ +From 51bd45816615bdb22a31a86f02d601ce536034e3 Mon Sep 17 00:00:00 2001 +From: Markus Armbruster +Date: Wed, 22 Apr 2020 15:07:19 +0200 +Subject: [PATCH 027/709] qga: Fix qmp_guest_suspend_{disk, ram}() error + handling +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The Error ** argument must be NULL, &error_abort, &error_fatal, or a +pointer to a variable containing NULL. Passing an argument of the +latter kind twice without clearing it in between is wrong: if the +first call sets an error, it no longer points to NULL for the second + +qmp_guest_suspend_disk() and qmp_guest_suspend_ram() pass @local_err +first to check_suspend_mode(), then to acquire_privilege(), then to +execute_async(). Continuing after errors here can only end in tears. +For instance, we risk tripping error_setv()'s assertion. + +Fixes: aa59637ea1c6a4c83430933f9c44c43e6c3f1b69 +Fixes: f54603b6aa765514b2519e74114a2f417759d727 +Cc: Michael Roth +Signed-off-by: Markus Armbruster +Message-Id: <20200422130719.28225-15-armbru@redhat.com> +Reviewed-by: Eric Blake +Reviewed-by: Philippe Mathieu-Daudé +--- + qga/commands-win32.c | 14 ++++++++++++++ + 1 file changed, 14 insertions(+) + +diff --git a/qga/commands-win32.c b/qga/commands-win32.c +index 9717a8d52d..5ba56327dd 100644 +--- a/qga/commands-win32.c ++++ b/qga/commands-win32.c +@@ -1322,9 +1322,16 @@ void qmp_guest_suspend_disk(Error **errp) + + *mode = GUEST_SUSPEND_MODE_DISK; + check_suspend_mode(*mode, &local_err); ++ if (local_err) { ++ goto out; ++ } + acquire_privilege(SE_SHUTDOWN_NAME, &local_err); ++ if (local_err) { ++ goto out; ++ } + execute_async(do_suspend, mode, &local_err); + ++out: + if (local_err) { + error_propagate(errp, local_err); + g_free(mode); +@@ -1338,9 +1345,16 @@ void qmp_guest_suspend_ram(Error **errp) + + *mode = GUEST_SUSPEND_MODE_RAM; + check_suspend_mode(*mode, &local_err); ++ if (local_err) { ++ goto out; ++ } + acquire_privilege(SE_SHUTDOWN_NAME, &local_err); ++ if (local_err) { ++ goto out; ++ } + execute_async(do_suspend, mode, &local_err); + ++out: + if (local_err) { + error_propagate(errp, local_err); + g_free(mode); +-- +2.23.0 + diff --git a/qobject-Clean-up-QLIST_FOREACH_ENTRY.patch b/qobject-Clean-up-QLIST_FOREACH_ENTRY.patch new file mode 100644 index 0000000000000000000000000000000000000000..161aa698ee2219c0dd0d12e381411aa68eeb5cbf --- /dev/null +++ b/qobject-Clean-up-QLIST_FOREACH_ENTRY.patch @@ -0,0 +1,37 @@ +From 64594e2bcc9a734bfabfaa8a75e08b4c9d920569 Mon Sep 17 00:00:00 2001 +From: Markus Armbruster +Date: Wed, 15 Apr 2020 10:30:44 +0200 +Subject: [PATCH 068/709] qobject: Clean up QLIST_FOREACH_ENTRY() + +QLIST_FOREACH_ENTRY() traverses a tail queue manually. Use +QTAILQ_FIRST() and QTAILQ_NEXT() instead. + +Signed-off-by: Markus Armbruster +Message-Id: <20200415083048.14339-2-armbru@redhat.com> +Reviewed-by: Eric Blake +--- + include/qapi/qmp/qlist.h | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/include/qapi/qmp/qlist.h b/include/qapi/qmp/qlist.h +index 8d2c32ca28..07ecae81e4 100644 +--- a/include/qapi/qmp/qlist.h ++++ b/include/qapi/qmp/qlist.h +@@ -34,10 +34,10 @@ void qlist_append_int(QList *qlist, int64_t value); + void qlist_append_null(QList *qlist); + void qlist_append_str(QList *qlist, const char *value); + +-#define QLIST_FOREACH_ENTRY(qlist, var) \ +- for ((var) = ((qlist)->head.tqh_first); \ +- (var); \ +- (var) = ((var)->next.tqe_next)) ++#define QLIST_FOREACH_ENTRY(qlist, var) \ ++ for ((var) = QTAILQ_FIRST(&(qlist)->head); \ ++ (var); \ ++ (var) = QTAILQ_NEXT((var), next)) + + static inline QObject *qlist_entry_obj(const QListEntry *entry) + { +-- +2.23.0 + diff --git a/qobject-Eliminate-qdict_iter-use-qdict_first-qdict_n.patch b/qobject-Eliminate-qdict_iter-use-qdict_first-qdict_n.patch new file mode 100644 index 0000000000000000000000000000000000000000..4970b7942a20aaa00bad4f09fbd4134e2c7c57fc --- /dev/null +++ b/qobject-Eliminate-qdict_iter-use-qdict_first-qdict_n.patch @@ -0,0 +1,225 @@ +From 7b1cd1c65abad70b26fbe9b11991bd88f0d956e1 Mon Sep 17 00:00:00 2001 +From: Markus Armbruster +Date: Wed, 15 Apr 2020 10:30:47 +0200 +Subject: [PATCH 071/709] qobject: Eliminate qdict_iter(), use qdict_first(), + qdict_next() + +qdict_iter() has just three uses and no test coverage. Replace by +qdict_first(), qdict_next() for more concise code and less type +punning. + +Signed-off-by: Markus Armbruster +Message-Id: <20200415083048.14339-5-armbru@redhat.com> +Reviewed-by: Eric Blake +--- + include/qapi/qmp/qdict.h | 3 -- + qapi/qobject-input-visitor.c | 21 +++++++------- + qobject/qdict.c | 19 ------------- + qobject/qjson.c | 54 +++++++++++++----------------------- + util/qemu-option.c | 10 ++++++- + 5 files changed, 40 insertions(+), 67 deletions(-) + +diff --git a/include/qapi/qmp/qdict.h b/include/qapi/qmp/qdict.h +index 7f3ec10a10..da942347a7 100644 +--- a/include/qapi/qmp/qdict.h ++++ b/include/qapi/qmp/qdict.h +@@ -40,9 +40,6 @@ void qdict_del(QDict *qdict, const char *key); + int qdict_haskey(const QDict *qdict, const char *key); + QObject *qdict_get(const QDict *qdict, const char *key); + bool qdict_is_equal(const QObject *x, const QObject *y); +-void qdict_iter(const QDict *qdict, +- void (*iter)(const char *key, QObject *obj, void *opaque), +- void *opaque); + const QDictEntry *qdict_first(const QDict *qdict); + const QDictEntry *qdict_next(const QDict *qdict, const QDictEntry *entry); + void qdict_destroy_obj(QObject *obj); +diff --git a/qapi/qobject-input-visitor.c b/qapi/qobject-input-visitor.c +index 32236cbcb1..5ce3ec2e5f 100644 +--- a/qapi/qobject-input-visitor.c ++++ b/qapi/qobject-input-visitor.c +@@ -203,31 +203,32 @@ static const char *qobject_input_get_keyval(QObjectInputVisitor *qiv, + return qstring_get_str(qstr); + } + +-static void qdict_add_key(const char *key, QObject *obj, void *opaque) +-{ +- GHashTable *h = opaque; +- g_hash_table_insert(h, (gpointer) key, NULL); +-} +- + static const QListEntry *qobject_input_push(QObjectInputVisitor *qiv, + const char *name, + QObject *obj, void *qapi) + { + GHashTable *h; + StackObject *tos = g_new0(StackObject, 1); ++ QDict *qdict = qobject_to(QDict, obj); ++ QList *qlist = qobject_to(QList, obj); ++ const QDictEntry *entry; + + assert(obj); + tos->name = name; + tos->obj = obj; + tos->qapi = qapi; + +- if (qobject_type(obj) == QTYPE_QDICT) { ++ if (qdict) { + h = g_hash_table_new(g_str_hash, g_str_equal); +- qdict_iter(qobject_to(QDict, obj), qdict_add_key, h); ++ for (entry = qdict_first(qdict); ++ entry; ++ entry = qdict_next(qdict, entry)) { ++ g_hash_table_insert(h, (void *)qdict_entry_key(entry), NULL); ++ } + tos->h = h; + } else { +- assert(qobject_type(obj) == QTYPE_QLIST); +- tos->entry = qlist_first(qobject_to(QList, obj)); ++ assert(qlist); ++ tos->entry = qlist_first(qlist); + tos->index = -1; + } + +diff --git a/qobject/qdict.c b/qobject/qdict.c +index 3d8c2f7bbc..526de54ceb 100644 +--- a/qobject/qdict.c ++++ b/qobject/qdict.c +@@ -298,25 +298,6 @@ const char *qdict_get_try_str(const QDict *qdict, const char *key) + return qstr ? qstring_get_str(qstr) : NULL; + } + +-/** +- * qdict_iter(): Iterate over all the dictionary's stored values. +- * +- * This function allows the user to provide an iterator, which will be +- * called for each stored value in the dictionary. +- */ +-void qdict_iter(const QDict *qdict, +- void (*iter)(const char *key, QObject *obj, void *opaque), +- void *opaque) +-{ +- int i; +- QDictEntry *entry; +- +- for (i = 0; i < QDICT_BUCKET_MAX; i++) { +- QLIST_FOREACH(entry, &qdict->table[i], next) +- iter(entry->key, entry->value, opaque); +- } +-} +- + static QDictEntry *qdict_next_entry(const QDict *qdict, int first_bucket) + { + int i; +diff --git a/qobject/qjson.c b/qobject/qjson.c +index f0eebc5fda..f1f2c69704 100644 +--- a/qobject/qjson.c ++++ b/qobject/qjson.c +@@ -149,14 +149,6 @@ QDict *qdict_from_jsonf_nofail(const char *string, ...) + return qdict; + } + +-typedef struct ToJsonIterState +-{ +- int indent; +- int pretty; +- int count; +- QString *str; +-} ToJsonIterState; +- + static void to_json(const QObject *obj, QString *str, int pretty, int indent); + + static void json_pretty_newline(QString *str, bool pretty, int indent) +@@ -171,26 +163,6 @@ static void json_pretty_newline(QString *str, bool pretty, int indent) + } + } + +-static void to_json_dict_iter(const char *key, QObject *obj, void *opaque) +-{ +- ToJsonIterState *s = opaque; +- QString *qkey; +- +- if (s->count) { +- qstring_append(s->str, s->pretty ? "," : ", "); +- } +- +- json_pretty_newline(s->str, s->pretty, s->indent); +- +- qkey = qstring_from_str(key); +- to_json(QOBJECT(qkey), s->str, s->pretty, s->indent); +- qobject_unref(qkey); +- +- qstring_append(s->str, ": "); +- to_json(obj, s->str, s->pretty, s->indent); +- s->count++; +-} +- + static void to_json(const QObject *obj, QString *str, int pretty, int indent) + { + switch (qobject_type(obj)) { +@@ -261,15 +233,29 @@ static void to_json(const QObject *obj, QString *str, int pretty, int indent) + break; + } + case QTYPE_QDICT: { +- ToJsonIterState s; + QDict *val = qobject_to(QDict, obj); ++ const char *comma = pretty ? "," : ", "; ++ const char *sep = ""; ++ const QDictEntry *entry; ++ QString *qkey; + +- s.count = 0; +- s.str = str; +- s.indent = indent + 1; +- s.pretty = pretty; + qstring_append(str, "{"); +- qdict_iter(val, to_json_dict_iter, &s); ++ ++ for (entry = qdict_first(val); ++ entry; ++ entry = qdict_next(val, entry)) { ++ qstring_append(str, sep); ++ json_pretty_newline(str, pretty, indent + 1); ++ ++ qkey = qstring_from_str(qdict_entry_key(entry)); ++ to_json(QOBJECT(qkey), str, pretty, indent + 1); ++ qobject_unref(qkey); ++ ++ qstring_append(str, ": "); ++ to_json(qdict_entry_value(entry), str, pretty, indent + 1); ++ sep = comma; ++ } ++ + json_pretty_newline(str, pretty, indent); + qstring_append(str, "}"); + break; +diff --git a/util/qemu-option.c b/util/qemu-option.c +index 9542988183..2784757ef5 100644 +--- a/util/qemu-option.c ++++ b/util/qemu-option.c +@@ -1013,6 +1013,7 @@ QemuOpts *qemu_opts_from_qdict(QemuOptsList *list, const QDict *qdict, + OptsFromQDictState state; + Error *local_err = NULL; + QemuOpts *opts; ++ const QDictEntry *entry; + + opts = qemu_opts_create(list, qdict_get_try_str(qdict, "id"), 1, + &local_err); +@@ -1025,7 +1026,14 @@ QemuOpts *qemu_opts_from_qdict(QemuOptsList *list, const QDict *qdict, + + state.errp = &local_err; + state.opts = opts; +- qdict_iter(qdict, qemu_opts_from_qdict_1, &state); ++ ++ for (entry = qdict_first(qdict); ++ entry; ++ entry = qdict_next(qdict, entry)) { ++ qemu_opts_from_qdict_1(qdict_entry_key(entry), ++ qdict_entry_value(entry), ++ &state); ++ } + if (local_err) { + error_propagate(errp, local_err); + qemu_opts_del(opts); +-- +2.23.0 + diff --git a/qobject-Eliminate-qlist_iter-use-QLIST_FOREACH_ENTRY.patch b/qobject-Eliminate-qlist_iter-use-QLIST_FOREACH_ENTRY.patch new file mode 100644 index 0000000000000000000000000000000000000000..9b0ab7ff3c6465258ef26d1c3716438e9ea954ef --- /dev/null +++ b/qobject-Eliminate-qlist_iter-use-QLIST_FOREACH_ENTRY.patch @@ -0,0 +1,222 @@ +From 2f2ec111795119b2e020bc0cbf4b5f42878574b2 Mon Sep 17 00:00:00 2001 +From: Markus Armbruster +Date: Wed, 15 Apr 2020 10:30:46 +0200 +Subject: [PATCH 070/709] qobject: Eliminate qlist_iter(), use + QLIST_FOREACH_ENTRY() instead + +qlist_iter() has just three uses outside tests/. Replace by +QLIST_FOREACH_ENTRY() for more concise code and less type punning. + +Signed-off-by: Markus Armbruster +Message-Id: <20200415083048.14339-4-armbru@redhat.com> +Reviewed-by: Eric Blake +--- + include/qapi/qmp/qlist.h | 2 -- + qobject/qjson.c | 31 ++++++++++------------------ + qobject/qlist.c | 44 +++++++++++----------------------------- + tests/check-qlist.c | 37 +++++++++++++-------------------- + 4 files changed, 37 insertions(+), 77 deletions(-) + +diff --git a/include/qapi/qmp/qlist.h b/include/qapi/qmp/qlist.h +index 07ecae81e4..595b7943e1 100644 +--- a/include/qapi/qmp/qlist.h ++++ b/include/qapi/qmp/qlist.h +@@ -47,8 +47,6 @@ static inline QObject *qlist_entry_obj(const QListEntry *entry) + QList *qlist_new(void); + QList *qlist_copy(QList *src); + void qlist_append_obj(QList *qlist, QObject *obj); +-void qlist_iter(const QList *qlist, +- void (*iter)(QObject *obj, void *opaque), void *opaque); + QObject *qlist_pop(QList *qlist); + QObject *qlist_peek(QList *qlist); + int qlist_empty(const QList *qlist); +diff --git a/qobject/qjson.c b/qobject/qjson.c +index 87422f600d..f0eebc5fda 100644 +--- a/qobject/qjson.c ++++ b/qobject/qjson.c +@@ -191,20 +191,6 @@ static void to_json_dict_iter(const char *key, QObject *obj, void *opaque) + s->count++; + } + +-static void to_json_list_iter(QObject *obj, void *opaque) +-{ +- ToJsonIterState *s = opaque; +- +- if (s->count) { +- qstring_append(s->str, s->pretty ? "," : ", "); +- } +- +- json_pretty_newline(s->str, s->pretty, s->indent); +- +- to_json(obj, s->str, s->pretty, s->indent); +- s->count++; +-} +- + static void to_json(const QObject *obj, QString *str, int pretty, int indent) + { + switch (qobject_type(obj)) { +@@ -289,15 +275,20 @@ static void to_json(const QObject *obj, QString *str, int pretty, int indent) + break; + } + case QTYPE_QLIST: { +- ToJsonIterState s; + QList *val = qobject_to(QList, obj); ++ const char *comma = pretty ? "," : ", "; ++ const char *sep = ""; ++ QListEntry *entry; + +- s.count = 0; +- s.str = str; +- s.indent = indent + 1; +- s.pretty = pretty; + qstring_append(str, "["); +- qlist_iter(val, (void *)to_json_list_iter, &s); ++ ++ QLIST_FOREACH_ENTRY(val, entry) { ++ qstring_append(str, sep); ++ json_pretty_newline(str, pretty, indent + 1); ++ to_json(qlist_entry_obj(entry), str, pretty, indent + 1); ++ sep = comma; ++ } ++ + json_pretty_newline(str, pretty, indent); + qstring_append(str, "]"); + break; +diff --git a/qobject/qlist.c b/qobject/qlist.c +index b3274af88b..1be95367d1 100644 +--- a/qobject/qlist.c ++++ b/qobject/qlist.c +@@ -34,20 +34,17 @@ QList *qlist_new(void) + return qlist; + } + +-static void qlist_copy_elem(QObject *obj, void *opaque) +-{ +- QList *dst = opaque; +- +- qobject_ref(obj); +- qlist_append_obj(dst, obj); +-} +- + QList *qlist_copy(QList *src) + { + QList *dst = qlist_new(); ++ QListEntry *entry; ++ QObject *elt; + +- qlist_iter(src, qlist_copy_elem, dst); +- ++ QLIST_FOREACH_ENTRY(src, entry) { ++ elt = qlist_entry_obj(entry); ++ qobject_ref(elt); ++ qlist_append_obj(dst, elt); ++ } + return dst; + } + +@@ -86,21 +83,6 @@ void qlist_append_null(QList *qlist) + qlist_append(qlist, qnull()); + } + +-/** +- * qlist_iter(): Iterate over all the list's stored values. +- * +- * This function allows the user to provide an iterator, which will be +- * called for each stored value in the list. +- */ +-void qlist_iter(const QList *qlist, +- void (*iter)(QObject *obj, void *opaque), void *opaque) +-{ +- QListEntry *entry; +- +- QTAILQ_FOREACH(entry, &qlist->head, next) +- iter(entry->value, opaque); +-} +- + QObject *qlist_pop(QList *qlist) + { + QListEntry *entry; +@@ -137,16 +119,14 @@ int qlist_empty(const QList *qlist) + return QTAILQ_EMPTY(&qlist->head); + } + +-static void qlist_size_iter(QObject *obj, void *opaque) +-{ +- size_t *count = opaque; +- (*count)++; +-} +- + size_t qlist_size(const QList *qlist) + { + size_t count = 0; +- qlist_iter(qlist, qlist_size_iter, &count); ++ QListEntry *entry; ++ ++ QLIST_FOREACH_ENTRY(qlist, entry) { ++ count++; ++ } + return count; + } + +diff --git a/tests/check-qlist.c b/tests/check-qlist.c +index ece83e293d..3cd0ccbf19 100644 +--- a/tests/check-qlist.c ++++ b/tests/check-qlist.c +@@ -61,40 +61,31 @@ static void qobject_to_qlist_test(void) + qobject_unref(qlist); + } + +-static int iter_called; +-static const int iter_max = 42; +- +-static void iter_func(QObject *obj, void *opaque) +-{ +- QNum *qi; +- int64_t val; +- +- g_assert(opaque == NULL); +- +- qi = qobject_to(QNum, obj); +- g_assert(qi != NULL); +- +- g_assert(qnum_get_try_int(qi, &val)); +- g_assert_cmpint(val, >=, 0); +- g_assert_cmpint(val, <=, iter_max); +- +- iter_called++; +-} +- + static void qlist_iter_test(void) + { ++ const int iter_max = 42; + int i; + QList *qlist; ++ QListEntry *entry; ++ QNum *qi; ++ int64_t val; + + qlist = qlist_new(); + + for (i = 0; i < iter_max; i++) + qlist_append_int(qlist, i); + +- iter_called = 0; +- qlist_iter(qlist, iter_func, NULL); ++ i = 0; ++ QLIST_FOREACH_ENTRY(qlist, entry) { ++ qi = qobject_to(QNum, qlist_entry_obj(entry)); ++ g_assert(qi != NULL); ++ ++ g_assert(qnum_get_try_int(qi, &val)); ++ g_assert_cmpint(val, ==, i); ++ i++; ++ } + +- g_assert(iter_called == iter_max); ++ g_assert(i == iter_max); + + qobject_unref(qlist); + } +-- +2.23.0 + diff --git a/qobject-Factor-out-helper-json_pretty_newline.patch b/qobject-Factor-out-helper-json_pretty_newline.patch new file mode 100644 index 0000000000000000000000000000000000000000..d87a77e3e84d321ce1448f076733cdd3ca64898e --- /dev/null +++ b/qobject-Factor-out-helper-json_pretty_newline.patch @@ -0,0 +1,102 @@ +From 1cd7741ef18e4333b17d64aaed3cd48e3e182a57 Mon Sep 17 00:00:00 2001 +From: Markus Armbruster +Date: Wed, 15 Apr 2020 10:30:45 +0200 +Subject: [PATCH 069/709] qobject: Factor out helper json_pretty_newline() + +Signed-off-by: Markus Armbruster +Message-Id: <20200415083048.14339-3-armbru@redhat.com> +Reviewed-by: Eric Blake +[Coding style in moved code tidied up] +--- + qobject/qjson.c | 40 ++++++++++++++++------------------------ + 1 file changed, 16 insertions(+), 24 deletions(-) + +diff --git a/qobject/qjson.c b/qobject/qjson.c +index db36101f3b..87422f600d 100644 +--- a/qobject/qjson.c ++++ b/qobject/qjson.c +@@ -159,21 +159,28 @@ typedef struct ToJsonIterState + + static void to_json(const QObject *obj, QString *str, int pretty, int indent); + ++static void json_pretty_newline(QString *str, bool pretty, int indent) ++{ ++ int i; ++ ++ if (pretty) { ++ qstring_append(str, "\n"); ++ for (i = 0; i < indent; i++) { ++ qstring_append(str, " "); ++ } ++ } ++} ++ + static void to_json_dict_iter(const char *key, QObject *obj, void *opaque) + { + ToJsonIterState *s = opaque; + QString *qkey; +- int j; + + if (s->count) { + qstring_append(s->str, s->pretty ? "," : ", "); + } + +- if (s->pretty) { +- qstring_append(s->str, "\n"); +- for (j = 0 ; j < s->indent ; j++) +- qstring_append(s->str, " "); +- } ++ json_pretty_newline(s->str, s->pretty, s->indent); + + qkey = qstring_from_str(key); + to_json(QOBJECT(qkey), s->str, s->pretty, s->indent); +@@ -187,17 +194,12 @@ static void to_json_dict_iter(const char *key, QObject *obj, void *opaque) + static void to_json_list_iter(QObject *obj, void *opaque) + { + ToJsonIterState *s = opaque; +- int j; + + if (s->count) { + qstring_append(s->str, s->pretty ? "," : ", "); + } + +- if (s->pretty) { +- qstring_append(s->str, "\n"); +- for (j = 0 ; j < s->indent ; j++) +- qstring_append(s->str, " "); +- } ++ json_pretty_newline(s->str, s->pretty, s->indent); + + to_json(obj, s->str, s->pretty, s->indent); + s->count++; +@@ -282,12 +284,7 @@ static void to_json(const QObject *obj, QString *str, int pretty, int indent) + s.pretty = pretty; + qstring_append(str, "{"); + qdict_iter(val, to_json_dict_iter, &s); +- if (pretty) { +- int j; +- qstring_append(str, "\n"); +- for (j = 0 ; j < indent ; j++) +- qstring_append(str, " "); +- } ++ json_pretty_newline(str, pretty, indent); + qstring_append(str, "}"); + break; + } +@@ -301,12 +298,7 @@ static void to_json(const QObject *obj, QString *str, int pretty, int indent) + s.pretty = pretty; + qstring_append(str, "["); + qlist_iter(val, (void *)to_json_list_iter, &s); +- if (pretty) { +- int j; +- qstring_append(str, "\n"); +- for (j = 0 ; j < indent ; j++) +- qstring_append(str, " "); +- } ++ json_pretty_newline(str, pretty, indent); + qstring_append(str, "]"); + break; + } +-- +2.23.0 + diff --git a/qom-Clean-up-inconsistent-use-of-gchar-vs.-char.patch b/qom-Clean-up-inconsistent-use-of-gchar-vs.-char.patch new file mode 100644 index 0000000000000000000000000000000000000000..db3db2f92d22db8470e84ef6cf5d619fd7b8647c --- /dev/null +++ b/qom-Clean-up-inconsistent-use-of-gchar-vs.-char.patch @@ -0,0 +1,367 @@ +From ddfb0baaf26e9e1b9869506c6e389dc8eb016de0 Mon Sep 17 00:00:00 2001 +From: Markus Armbruster +Date: Tue, 5 May 2020 17:29:10 +0200 +Subject: [PATCH 464/709] qom: Clean up inconsistent use of gchar * vs. char * + +Uses of gchar * in qom/object.h: + +* ObjectProperty member @name + + Functions that take a property name argument all use char *. Change + the member to match. + +* ObjectProperty member @type + + Functions that take a property type argument or return it all use + char *. Change the member to match. + +* ObjectProperty member @description + + Functions that take a property description argument all use char *. + Change the member to match. + +* object_resolve_path_component() parameter @part + + Path components are property names. Most callers pass char * + arguments. Change the parameter to match. Adjust the few callers + that pass gchar * to pass char *. + +* Return value of object_get_canonical_path_component(), + object_get_canonical_path() + + Most callers convert their return values right back to char *. + Change the return value to match. Adjust the few callers where that + would add a conversion to gchar * to use char * instead. + +Signed-off-by: Markus Armbruster +Reviewed-by: Eric Blake +Reviewed-by: Paolo Bonzini +Message-Id: <20200505152926.18877-3-armbru@redhat.com> +--- + hw/dma/xlnx-zdma.c | 4 ++-- + hw/net/virtio-net.c | 2 +- + hw/ppc/spapr_drc.c | 2 +- + include/qom/object.h | 12 +++++----- + memory.c | 4 ++-- + monitor/monitor-internal.h | 2 +- + qom/container.c | 2 +- + qom/object.c | 46 ++++++++++++++++++++------------------ + 8 files changed, 38 insertions(+), 36 deletions(-) + +diff --git a/hw/dma/xlnx-zdma.c b/hw/dma/xlnx-zdma.c +index 4121a1b489..2dec4a2643 100644 +--- a/hw/dma/xlnx-zdma.c ++++ b/hw/dma/xlnx-zdma.c +@@ -719,7 +719,7 @@ static uint64_t zdma_read(void *opaque, hwaddr addr, unsigned size) + RegisterInfo *r = &s->regs_info[addr / 4]; + + if (!r->data) { +- gchar *path = object_get_canonical_path(OBJECT(s)); ++ char *path = object_get_canonical_path(OBJECT(s)); + qemu_log("%s: Decode error: read from %" HWADDR_PRIx "\n", + path, + addr); +@@ -738,7 +738,7 @@ static void zdma_write(void *opaque, hwaddr addr, uint64_t value, + RegisterInfo *r = &s->regs_info[addr / 4]; + + if (!r->data) { +- gchar *path = object_get_canonical_path(OBJECT(s)); ++ char *path = object_get_canonical_path(OBJECT(s)); + qemu_log("%s: Decode error: write to %" HWADDR_PRIx "=%" PRIx64 "\n", + path, + addr, value); +diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c +index 3301869d4f..e51231e795 100644 +--- a/hw/net/virtio-net.c ++++ b/hw/net/virtio-net.c +@@ -399,7 +399,7 @@ static void rxfilter_notify(NetClientState *nc) + VirtIONet *n = qemu_get_nic_opaque(nc); + + if (nc->rxfilter_notify_enabled) { +- gchar *path = object_get_canonical_path(OBJECT(n->qdev)); ++ char *path = object_get_canonical_path(OBJECT(n->qdev)); + qapi_event_send_nic_rx_filter_changed(!!n->netclient_name, + n->netclient_name, path); + g_free(path); +diff --git a/hw/ppc/spapr_drc.c b/hw/ppc/spapr_drc.c +index 47e6bb12f9..0b66d59867 100644 +--- a/hw/ppc/spapr_drc.c ++++ b/hw/ppc/spapr_drc.c +@@ -518,7 +518,7 @@ static void realize(DeviceState *d, Error **errp) + SpaprDrc *drc = SPAPR_DR_CONNECTOR(d); + Object *root_container; + gchar *link_name; +- gchar *child_name; ++ char *child_name; + Error *err = NULL; + + trace_spapr_drc_realize(spapr_drc_index(drc)); +diff --git a/include/qom/object.h b/include/qom/object.h +index 784c97c0e1..ccfa82e33d 100644 +--- a/include/qom/object.h ++++ b/include/qom/object.h +@@ -369,9 +369,9 @@ typedef void (ObjectPropertyInit)(Object *obj, ObjectProperty *prop); + + struct ObjectProperty + { +- gchar *name; +- gchar *type; +- gchar *description; ++ char *name; ++ char *type; ++ char *description; + ObjectPropertyAccessor *get; + ObjectPropertyAccessor *set; + ObjectPropertyResolve *resolve; +@@ -1421,7 +1421,7 @@ Object *object_get_internal_root(void); + * path is the path within the composition tree starting from the root. + * %NULL if the object doesn't have a parent (and thus a canonical path). + */ +-gchar *object_get_canonical_path_component(Object *obj); ++char *object_get_canonical_path_component(Object *obj); + + /** + * object_get_canonical_path: +@@ -1429,7 +1429,7 @@ gchar *object_get_canonical_path_component(Object *obj); + * Returns: The canonical path for a object. This is the path within the + * composition tree starting from the root. + */ +-gchar *object_get_canonical_path(Object *obj); ++char *object_get_canonical_path(Object *obj); + + /** + * object_resolve_path: +@@ -1487,7 +1487,7 @@ Object *object_resolve_path_type(const char *path, const char *typename, + * + * Returns: The resolved object or NULL on path lookup failure. + */ +-Object *object_resolve_path_component(Object *parent, const gchar *part); ++Object *object_resolve_path_component(Object *parent, const char *part); + + /** + * object_property_add_child: +diff --git a/memory.c b/memory.c +index 601b749906..936c1b23d4 100644 +--- a/memory.c ++++ b/memory.c +@@ -1175,7 +1175,7 @@ static void memory_region_get_container(Object *obj, Visitor *v, + Error **errp) + { + MemoryRegion *mr = MEMORY_REGION(obj); +- gchar *path = (gchar *)""; ++ char *path = (char *)""; + + if (mr->container) { + path = object_get_canonical_path(OBJECT(mr->container)); +@@ -2845,7 +2845,7 @@ static void mtree_expand_owner(const char *label, Object *obj) + if (dev && dev->id) { + qemu_printf(" id=%s", dev->id); + } else { +- gchar *canonical_path = object_get_canonical_path(obj); ++ char *canonical_path = object_get_canonical_path(obj); + if (canonical_path) { + qemu_printf(" path=%s", canonical_path); + g_free(canonical_path); +diff --git a/monitor/monitor-internal.h b/monitor/monitor-internal.h +index 8f60ccc70a..b39e03b744 100644 +--- a/monitor/monitor-internal.h ++++ b/monitor/monitor-internal.h +@@ -91,7 +91,7 @@ struct Monitor { + bool skip_flush; + bool use_io_thread; + +- gchar *mon_cpu_path; ++ char *mon_cpu_path; + QTAILQ_ENTRY(Monitor) entry; + + /* +diff --git a/qom/container.c b/qom/container.c +index f6ccaf7ea7..e635e8ee76 100644 +--- a/qom/container.c ++++ b/qom/container.c +@@ -28,7 +28,7 @@ static void container_register_types(void) + Object *container_get(Object *root, const char *path) + { + Object *obj, *child; +- gchar **parts; ++ char **parts; + int i; + + parts = g_strsplit(path, "/", 0); +diff --git a/qom/object.c b/qom/object.c +index 5511649502..07762cc331 100644 +--- a/qom/object.c ++++ b/qom/object.c +@@ -1357,7 +1357,7 @@ void object_property_set_link(Object *obj, Object *value, + const char *name, Error **errp) + { + if (value) { +- gchar *path = object_get_canonical_path(value); ++ char *path = object_get_canonical_path(value); + object_property_set_str(obj, path, name, errp); + g_free(path); + } else { +@@ -1651,14 +1651,15 @@ static void object_get_child_property(Object *obj, Visitor *v, + Error **errp) + { + Object *child = opaque; +- gchar *path; ++ char *path; + + path = object_get_canonical_path(child); + visit_type_str(v, name, &path, errp); + g_free(path); + } + +-static Object *object_resolve_child_property(Object *parent, void *opaque, const gchar *part) ++static Object *object_resolve_child_property(Object *parent, void *opaque, ++ const char *part) + { + return opaque; + } +@@ -1679,7 +1680,7 @@ void object_property_add_child(Object *obj, const char *name, + Object *child, Error **errp) + { + Error *local_err = NULL; +- gchar *type; ++ char *type; + ObjectProperty *op; + + if (child->parent != NULL) { +@@ -1738,14 +1739,14 @@ static void object_get_link_property(Object *obj, Visitor *v, + { + LinkProperty *lprop = opaque; + Object **targetp = object_link_get_targetp(obj, lprop); +- gchar *path; ++ char *path; + + if (*targetp) { + path = object_get_canonical_path(*targetp); + visit_type_str(v, name, &path, errp); + g_free(path); + } else { +- path = (gchar *)""; ++ path = (char *)""; + visit_type_str(v, name, &path, errp); + } + } +@@ -1763,7 +1764,7 @@ static Object *object_resolve_link(Object *obj, const char *name, + const char *path, Error **errp) + { + const char *type; +- gchar *target_type; ++ char *target_type; + bool ambiguous = false; + Object *target; + +@@ -1826,7 +1827,8 @@ static void object_set_link_property(Object *obj, Visitor *v, + } + } + +-static Object *object_resolve_link_property(Object *parent, void *opaque, const gchar *part) ++static Object *object_resolve_link_property(Object *parent, void *opaque, ++ const char *part) + { + LinkProperty *lprop = opaque; + +@@ -1856,7 +1858,7 @@ static void object_add_link_prop(Object *obj, const char *name, + { + Error *local_err = NULL; + LinkProperty *prop = g_malloc(sizeof(*prop)); +- gchar *full_type; ++ char *full_type; + ObjectProperty *op; + + if (flags & OBJ_PROP_LINK_DIRECT) { +@@ -1908,7 +1910,7 @@ object_class_property_add_link(ObjectClass *oc, + { + Error *local_err = NULL; + LinkProperty *prop = g_new0(LinkProperty, 1); +- gchar *full_type; ++ char *full_type; + ObjectProperty *op; + + prop->offset = offset; +@@ -1943,7 +1945,7 @@ void object_property_add_const_link(Object *obj, const char *name, + NULL, OBJ_PROP_LINK_DIRECT, errp); + } + +-gchar *object_get_canonical_path_component(Object *obj) ++char *object_get_canonical_path_component(Object *obj) + { + ObjectProperty *prop = NULL; + GHashTableIter iter; +@@ -1968,7 +1970,7 @@ gchar *object_get_canonical_path_component(Object *obj) + return NULL; + } + +-gchar *object_get_canonical_path(Object *obj) ++char *object_get_canonical_path(Object *obj) + { + Object *root = object_get_root(); + char *newpath, *path = NULL; +@@ -1998,7 +2000,7 @@ gchar *object_get_canonical_path(Object *obj) + return path; + } + +-Object *object_resolve_path_component(Object *parent, const gchar *part) ++Object *object_resolve_path_component(Object *parent, const char *part) + { + ObjectProperty *prop = object_property_find(parent, part, NULL); + if (prop == NULL) { +@@ -2013,9 +2015,9 @@ Object *object_resolve_path_component(Object *parent, const gchar *part) + } + + static Object *object_resolve_abs_path(Object *parent, +- gchar **parts, +- const char *typename, +- int index) ++ char **parts, ++ const char *typename, ++ int index) + { + Object *child; + +@@ -2036,9 +2038,9 @@ static Object *object_resolve_abs_path(Object *parent, + } + + static Object *object_resolve_partial_path(Object *parent, +- gchar **parts, +- const char *typename, +- bool *ambiguous) ++ char **parts, ++ const char *typename, ++ bool *ambiguous) + { + Object *obj; + GHashTableIter iter; +@@ -2076,7 +2078,7 @@ Object *object_resolve_path_type(const char *path, const char *typename, + bool *ambiguousp) + { + Object *obj; +- gchar **parts; ++ char **parts; + + parts = g_strsplit(path, "/", 0); + assert(parts); +@@ -2767,7 +2769,7 @@ static void property_set_alias(Object *obj, Visitor *v, const char *name, + } + + static Object *property_resolve_alias(Object *obj, void *opaque, +- const gchar *part) ++ const char *part) + { + AliasProperty *prop = opaque; + +@@ -2789,7 +2791,7 @@ void object_property_add_alias(Object *obj, const char *name, + AliasProperty *prop; + ObjectProperty *op; + ObjectProperty *target_prop; +- gchar *prop_type; ++ char *prop_type; + Error *local_err = NULL; + + target_prop = object_property_find(target_obj, target_name, errp); +-- +2.23.0 + diff --git a/qom-Clearer-reference-counting-in-object_initialize_.patch b/qom-Clearer-reference-counting-in-object_initialize_.patch new file mode 100644 index 0000000000000000000000000000000000000000..fe92fd1b786d6d894f57df6f9f81f0070e66ff96 --- /dev/null +++ b/qom-Clearer-reference-counting-in-object_initialize_.patch @@ -0,0 +1,48 @@ +From 975ac4559c4c00010e05f7a3e782eeb9497837ea Mon Sep 17 00:00:00 2001 +From: Markus Armbruster +Date: Tue, 5 May 2020 17:29:09 +0200 +Subject: [PATCH 463/709] qom: Clearer reference counting in + object_initialize_childv() + +Signed-off-by: Markus Armbruster +Reviewed-by: Eric Blake +Reviewed-by: Paolo Bonzini +Message-Id: <20200505152926.18877-2-armbru@redhat.com> +--- + qom/object.c | 16 ++++++++-------- + 1 file changed, 8 insertions(+), 8 deletions(-) + +diff --git a/qom/object.c b/qom/object.c +index be700e831f..5511649502 100644 +--- a/qom/object.c ++++ b/qom/object.c +@@ -571,18 +571,18 @@ void object_initialize_childv(Object *parentobj, const char *propname, + } + } + ++out: + /* +- * Since object_property_add_child added a reference to the child object, +- * we can drop the reference added by object_initialize(), so the child +- * property will own the only reference to the object. ++ * We want @obj's reference to be 1 on success, 0 on failure. ++ * On success, it's 2: one taken by object_initialize(), and one ++ * by object_property_add_child(). ++ * On failure in object_initialize() or earlier, it's 1. ++ * On failure afterwards, it's also 1: object_unparent() releases ++ * the reference taken by object_property_add_child(). + */ + object_unref(obj); + +-out: +- if (local_err) { +- error_propagate(errp, local_err); +- object_unref(obj); +- } ++ error_propagate(errp, local_err); + } + + static inline bool object_property_is_child(ObjectProperty *prop) +-- +2.23.0 + diff --git a/qom-Drop-convenience-method-object_property_get_uint.patch b/qom-Drop-convenience-method-object_property_get_uint.patch new file mode 100644 index 0000000000000000000000000000000000000000..d64a79d785ba779a56be87a640e5aab9e66428b6 --- /dev/null +++ b/qom-Drop-convenience-method-object_property_get_uint.patch @@ -0,0 +1,141 @@ +From 44a17fe05a363d0f94cd0706fbe64cb4524adf54 Mon Sep 17 00:00:00 2001 +From: Markus Armbruster +Date: Tue, 5 May 2020 17:29:13 +0200 +Subject: [PATCH 467/709] qom: Drop convenience method + object_property_get_uint16List() + +qom/object.c provides object_property_get_TYPE() and +object_property_set_TYPE() for a number of common types. These are +all convenience wrappers around object_property_get_qobject() and +object_property_set_qobject(). + +Except for object_property_get_uint16List(), which is unusual in two ways: + +* It bypasses object_property_get_qobject(). Fixable; the previous + commit did it for object_property_get_enum()) + +* It stores the value through a parameter. Its contract claims it + returns the value, like the other functions do. Also fixable. + +Fixing is not worthwhile, though: object_property_get_uint16List() has +seen exactly one user in six years. + +Convert the lone user to do its job with the generic +object_property_get_qobject(), and drop object_property_get_uint16List(). + +Signed-off-by: Markus Armbruster +Message-Id: <20200505152926.18877-6-armbru@redhat.com> +Reviewed-by: Paolo Bonzini +[Commit message typo fixed] +--- + hw/core/machine-qmp-cmds.c | 16 +++++++++++++--- + include/qom/object.h | 14 -------------- + qom/object.c | 23 ----------------------- + 3 files changed, 13 insertions(+), 40 deletions(-) + +diff --git a/hw/core/machine-qmp-cmds.c b/hw/core/machine-qmp-cmds.c +index eed5aeb2f7..2c5da8413d 100644 +--- a/hw/core/machine-qmp-cmds.c ++++ b/hw/core/machine-qmp-cmds.c +@@ -11,9 +11,13 @@ + #include "cpu.h" + #include "hw/boards.h" + #include "qapi/error.h" ++#include "qapi/qapi-builtin-visit.h" + #include "qapi/qapi-commands-machine.h" + #include "qapi/qmp/qerror.h" ++#include "qapi/qmp/qobject.h" ++#include "qapi/qobject-input-visitor.h" + #include "qemu/main-loop.h" ++#include "qom/qom-qobject.h" + #include "sysemu/hostmem.h" + #include "sysemu/hw_accel.h" + #include "sysemu/numa.h" +@@ -303,6 +307,8 @@ static int query_memdev(Object *obj, void *opaque) + { + MemdevList **list = opaque; + MemdevList *m = NULL; ++ QObject *host_nodes; ++ Visitor *v; + + if (object_dynamic_cast(obj, TYPE_MEMORY_BACKEND)) { + m = g_malloc0(sizeof(*m)); +@@ -325,9 +331,13 @@ static int query_memdev(Object *obj, void *opaque) + "policy", + "HostMemPolicy", + &error_abort); +- object_property_get_uint16List(obj, "host-nodes", +- &m->value->host_nodes, +- &error_abort); ++ host_nodes = object_property_get_qobject(obj, ++ "host-nodes", ++ &error_abort); ++ v = qobject_input_visitor_new(host_nodes); ++ visit_type_uint16List(v, NULL, &m->value->host_nodes, &error_abort); ++ visit_free(v); ++ qobject_unref(host_nodes); + + m->next = *list; + *list = m; +diff --git a/include/qom/object.h b/include/qom/object.h +index ccfa82e33d..4df9ecebad 100644 +--- a/include/qom/object.h ++++ b/include/qom/object.h +@@ -1320,20 +1320,6 @@ uint64_t object_property_get_uint(Object *obj, const char *name, + int object_property_get_enum(Object *obj, const char *name, + const char *typename, Error **errp); + +-/** +- * object_property_get_uint16List: +- * @obj: the object +- * @name: the name of the property +- * @list: the returned int list +- * @errp: returns an error if this function fails +- * +- * Returns: the value of the property, converted to integers, or +- * undefined if an error occurs (including when the property value is not +- * an list of integers). +- */ +-void object_property_get_uint16List(Object *obj, const char *name, +- uint16List **list, Error **errp); +- + /** + * object_property_set: + * @obj: the object +diff --git a/qom/object.c b/qom/object.c +index b374af302c..54a26ed16a 100644 +--- a/qom/object.c ++++ b/qom/object.c +@@ -1550,29 +1550,6 @@ int object_property_get_enum(Object *obj, const char *name, + return ret; + } + +-void object_property_get_uint16List(Object *obj, const char *name, +- uint16List **list, Error **errp) +-{ +- Error *err = NULL; +- Visitor *v; +- char *str; +- +- v = string_output_visitor_new(false, &str); +- object_property_get(obj, v, name, &err); +- if (err) { +- error_propagate(errp, err); +- goto out; +- } +- visit_complete(v, &str); +- visit_free(v); +- v = string_input_visitor_new(str); +- visit_type_uint16List(v, NULL, list, errp); +- +- g_free(str); +-out: +- visit_free(v); +-} +- + void object_property_parse(Object *obj, const char *string, + const char *name, Error **errp) + { +-- +2.23.0 + diff --git a/qom-Drop-errp-parameter-of-object_property_del.patch b/qom-Drop-errp-parameter-of-object_property_del.patch new file mode 100644 index 0000000000000000000000000000000000000000..8f8abc6bce5ea17370d45b1630d2efe49ecc395e --- /dev/null +++ b/qom-Drop-errp-parameter-of-object_property_del.patch @@ -0,0 +1,144 @@ +From df4fe0b291b2baf1694517a4a67be7525102656b Mon Sep 17 00:00:00 2001 +From: Markus Armbruster +Date: Tue, 5 May 2020 17:29:26 +0200 +Subject: [PATCH 480/709] qom: Drop @errp parameter of object_property_del() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Same story as for object_property_add(): the only way +object_property_del() can fail is when the property with this name +does not exist. Since our property names are all hardcoded, failure +is a programming error, and the appropriate way to handle it is +passing &error_abort. Most callers do that, the commit before +previous fixed one that didn't (and got the error handling wrong), and +the two remaining exceptions ignore errors. + +Drop the @errp parameter. + +Signed-off-by: Markus Armbruster +Reviewed-by: Paolo Bonzini +Message-Id: <20200505152926.18877-19-armbru@redhat.com> +Reviewed-by: Philippe Mathieu-Daudé +--- + hw/core/qdev.c | 2 +- + hw/i386/pc_sysfw.c | 2 +- + hw/ppc/spapr_drc.c | 4 ++-- + include/qom/object.h | 2 +- + qom/object.c | 7 +------ + qom/object_interfaces.c | 3 +-- + tests/check-qom-proplist.c | 2 +- + 7 files changed, 8 insertions(+), 14 deletions(-) + +diff --git a/hw/core/qdev.c b/hw/core/qdev.c +index b9c7a2f904..9e5538aeae 100644 +--- a/hw/core/qdev.c ++++ b/hw/core/qdev.c +@@ -65,7 +65,7 @@ static void bus_remove_child(BusState *bus, DeviceState *child) + bus->num_children--; + + /* This gives back ownership of kid->child back to us. */ +- object_property_del(OBJECT(bus), name, NULL); ++ object_property_del(OBJECT(bus), name); + object_unref(OBJECT(kid->child)); + g_free(kid); + return; +diff --git a/hw/i386/pc_sysfw.c b/hw/i386/pc_sysfw.c +index 002133a2d8..2abab3a27c 100644 +--- a/hw/i386/pc_sysfw.c ++++ b/hw/i386/pc_sysfw.c +@@ -120,7 +120,7 @@ static void pc_system_flash_cleanup_unused(PCMachineState *pcms) + dev_obj = OBJECT(pcms->flash[i]); + if (!object_property_get_bool(dev_obj, "realized", &error_abort)) { + prop_name = g_strdup_printf("pflash%d", i); +- object_property_del(OBJECT(pcms), prop_name, &error_abort); ++ object_property_del(OBJECT(pcms), prop_name); + g_free(prop_name); + object_unparent(dev_obj); + pcms->flash[i] = NULL; +diff --git a/hw/ppc/spapr_drc.c b/hw/ppc/spapr_drc.c +index 8b2171f698..b958f8acb5 100644 +--- a/hw/ppc/spapr_drc.c ++++ b/hw/ppc/spapr_drc.c +@@ -405,7 +405,7 @@ static void spapr_drc_release(SpaprDrc *drc) + g_free(drc->fdt); + drc->fdt = NULL; + drc->fdt_start_offset = 0; +- object_property_del(OBJECT(drc), "device", &error_abort); ++ object_property_del(OBJECT(drc), "device"); + drc->dev = NULL; + } + +@@ -551,7 +551,7 @@ static void unrealize(DeviceState *d) + vmstate_unregister(VMSTATE_IF(drc), &vmstate_spapr_drc, drc); + root_container = container_get(object_get_root(), DRC_CONTAINER_PATH); + name = g_strdup_printf("%x", spapr_drc_index(drc)); +- object_property_del(root_container, name, &error_abort); ++ object_property_del(root_container, name); + g_free(name); + } + +diff --git a/include/qom/object.h b/include/qom/object.h +index 990e28e408..fd453dc8d6 100644 +--- a/include/qom/object.h ++++ b/include/qom/object.h +@@ -1047,7 +1047,7 @@ ObjectProperty *object_property_add(Object *obj, const char *name, + ObjectPropertyRelease *release, + void *opaque); + +-void object_property_del(Object *obj, const char *name, Error **errp); ++void object_property_del(Object *obj, const char *name); + + ObjectProperty *object_class_property_add(ObjectClass *klass, const char *name, + const char *type, +diff --git a/qom/object.c b/qom/object.c +index 23f481ca46..e89ffbe3d1 100644 +--- a/qom/object.c ++++ b/qom/object.c +@@ -1280,15 +1280,10 @@ ObjectProperty *object_class_property_find(ObjectClass *klass, const char *name, + return prop; + } + +-void object_property_del(Object *obj, const char *name, Error **errp) ++void object_property_del(Object *obj, const char *name) + { + ObjectProperty *prop = g_hash_table_lookup(obj->properties, name); + +- if (!prop) { +- error_setg(errp, "Property '.%s' not found", name); +- return; +- } +- + if (prop->release) { + prop->release(obj, name, prop->opaque); + } +diff --git a/qom/object_interfaces.c b/qom/object_interfaces.c +index 054e75043d..7e26f86fa6 100644 +--- a/qom/object_interfaces.c ++++ b/qom/object_interfaces.c +@@ -89,8 +89,7 @@ Object *user_creatable_add_type(const char *type, const char *id, + user_creatable_complete(USER_CREATABLE(obj), &local_err); + if (local_err) { + if (id != NULL) { +- object_property_del(object_get_objects_root(), +- id, &error_abort); ++ object_property_del(object_get_objects_root(), id); + } + goto out; + } +diff --git a/tests/check-qom-proplist.c b/tests/check-qom-proplist.c +index 84f48fe592..13a824cfae 100644 +--- a/tests/check-qom-proplist.c ++++ b/tests/check-qom-proplist.c +@@ -280,7 +280,7 @@ static void dummy_bus_init(Object *obj) + static void dummy_bus_unparent(Object *obj) + { + DummyBus *bus = DUMMY_BUS(obj); +- object_property_del(obj->parent, "backend", NULL); ++ object_property_del(obj->parent, "backend"); + object_unparent(OBJECT(bus->backend)); + } + +-- +2.23.0 + diff --git a/qom-Drop-object_property_del_child-s-unused-paramete.patch b/qom-Drop-object_property_del_child-s-unused-paramete.patch new file mode 100644 index 0000000000000000000000000000000000000000..b3a26d820f09ed5d083b057322e533f55c4a8162 --- /dev/null +++ b/qom-Drop-object_property_del_child-s-unused-paramete.patch @@ -0,0 +1,39 @@ +From f73a32a5147ef7ff90f682d6ba3a6ef11ff97d9e Mon Sep 17 00:00:00 2001 +From: Markus Armbruster +Date: Tue, 5 May 2020 17:29:11 +0200 +Subject: [PATCH 465/709] qom: Drop object_property_del_child()'s unused + parameter @errp + +Signed-off-by: Markus Armbruster +Reviewed-by: Eric Blake +Reviewed-by: Paolo Bonzini +Message-Id: <20200505152926.18877-4-armbru@redhat.com> +--- + qom/object.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/qom/object.c b/qom/object.c +index 07762cc331..3d65658059 100644 +--- a/qom/object.c ++++ b/qom/object.c +@@ -614,7 +614,7 @@ static void object_property_del_all(Object *obj) + g_hash_table_unref(obj->properties); + } + +-static void object_property_del_child(Object *obj, Object *child, Error **errp) ++static void object_property_del_child(Object *obj, Object *child) + { + ObjectProperty *prop; + GHashTableIter iter; +@@ -644,7 +644,7 @@ static void object_property_del_child(Object *obj, Object *child, Error **errp) + void object_unparent(Object *obj) + { + if (obj->parent) { +- object_property_del_child(obj->parent, obj, NULL); ++ object_property_del_child(obj->parent, obj); + } + } + +-- +2.23.0 + diff --git a/qom-Drop-object_property_set_description-parameter-e.patch b/qom-Drop-object_property_set_description-parameter-e.patch new file mode 100644 index 0000000000000000000000000000000000000000..cb2c7edc8ecc417d66328898fa0a32f51ca03997 --- /dev/null +++ b/qom-Drop-object_property_set_description-parameter-e.patch @@ -0,0 +1,981 @@ +From 7eecec7d1224890b0d04479dd4736e1eefaa72dc Mon Sep 17 00:00:00 2001 +From: Markus Armbruster +Date: Tue, 5 May 2020 17:29:15 +0200 +Subject: [PATCH 469/709] qom: Drop object_property_set_description() parameter + @errp + +object_property_set_description() and +object_class_property_set_description() fail only when property @name +is not found. + +There are 85 calls of object_property_set_description() and +object_class_property_set_description(). None of them can fail: + +* 84 immediately follow the creation of the property. + +* The one in spapr_rng_instance_init() refers to a property created in + spapr_rng_class_init(), from spapr_rng_properties[]. + +Every one of them still gets to decide what to pass for @errp. + +51 calls pass &error_abort, 32 calls pass NULL, one receives the error +and propagates it to &error_abort, and one propagates it to +&error_fatal. I'm actually surprised none of them violates the Error +API. + +What are we gaining by letting callers handle the "property not found" +error? Use when the property is not known to exist is simpler: you +don't have to guard the call with a check. We haven't found such a +use in 5+ years. Until we do, let's make life a bit simpler and drop +the @errp parameter. + +Signed-off-by: Markus Armbruster +Reviewed-by: Eric Blake +Reviewed-by: Paolo Bonzini +Message-Id: <20200505152926.18877-8-armbru@redhat.com> +[One semantic rebase conflict resolved] +--- + accel/kvm/kvm-all.c | 4 ++-- + accel/tcg/tcg-all.c | 2 +- + backends/hostmem-memfd.c | 9 +++------ + backends/hostmem.c | 16 +++++++-------- + hw/arm/aspeed.c | 2 +- + hw/arm/vexpress.c | 6 ++---- + hw/arm/virt.c | 23 ++++++++------------- + hw/arm/xlnx-zcu102.c | 6 ++---- + hw/core/machine.c | 41 ++++++++++++++++++-------------------- + hw/core/qdev.c | 6 ++---- + hw/i386/microvm.c | 14 ++++++------- + hw/i386/pc.c | 2 +- + hw/i386/x86.c | 6 +++--- + hw/ppc/mac_newworld.c | 3 +-- + hw/ppc/pnv.c | 3 +-- + hw/ppc/spapr.c | 21 ++++++++----------- + hw/ppc/spapr_caps.c | 6 +----- + hw/ppc/spapr_rng.c | 3 +-- + hw/riscv/sifive_u.c | 5 ++--- + hw/s390x/css-bridge.c | 3 +-- + hw/s390x/s390-virtio-ccw.c | 9 +++------ + hw/sparc/sun4m.c | 3 +-- + hw/xen/xen-common.c | 2 +- + include/qom/object.h | 6 ++---- + qom/object.c | 19 ++++-------------- + target/arm/cpu64.c | 3 +-- + target/arm/kvm.c | 2 +- + target/i386/sev.c | 6 +++--- + target/ppc/compat.c | 2 +- + target/s390x/cpu_models.c | 4 ++-- + 30 files changed, 92 insertions(+), 145 deletions(-) + +diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c +index 36be11795d..9b712aac77 100644 +--- a/accel/kvm/kvm-all.c ++++ b/accel/kvm/kvm-all.c +@@ -3113,13 +3113,13 @@ static void kvm_accel_class_init(ObjectClass *oc, void *data) + NULL, kvm_set_kernel_irqchip, + NULL, NULL, &error_abort); + object_class_property_set_description(oc, "kernel-irqchip", +- "Configure KVM in-kernel irqchip", &error_abort); ++ "Configure KVM in-kernel irqchip"); + + object_class_property_add(oc, "kvm-shadow-mem", "int", + kvm_get_kvm_shadow_mem, kvm_set_kvm_shadow_mem, + NULL, NULL, &error_abort); + object_class_property_set_description(oc, "kvm-shadow-mem", +- "KVM shadow MMU size", &error_abort); ++ "KVM shadow MMU size"); + } + + static const TypeInfo kvm_accel_type = { +diff --git a/accel/tcg/tcg-all.c b/accel/tcg/tcg-all.c +index acfdcfdf59..3398a56ef9 100644 +--- a/accel/tcg/tcg-all.c ++++ b/accel/tcg/tcg-all.c +@@ -210,7 +210,7 @@ static void tcg_accel_class_init(ObjectClass *oc, void *data) + tcg_get_tb_size, tcg_set_tb_size, + NULL, NULL, &error_abort); + object_class_property_set_description(oc, "tb-size", +- "TCG translation block cache size", &error_abort); ++ "TCG translation block cache size"); + + } + +diff --git a/backends/hostmem-memfd.c b/backends/hostmem-memfd.c +index 74ba9879c4..5991f31459 100644 +--- a/backends/hostmem-memfd.c ++++ b/backends/hostmem-memfd.c +@@ -144,23 +144,20 @@ memfd_backend_class_init(ObjectClass *oc, void *data) + memfd_backend_set_hugetlb, + &error_abort); + object_class_property_set_description(oc, "hugetlb", +- "Use huge pages", +- &error_abort); ++ "Use huge pages"); + object_class_property_add(oc, "hugetlbsize", "int", + memfd_backend_get_hugetlbsize, + memfd_backend_set_hugetlbsize, + NULL, NULL, &error_abort); + object_class_property_set_description(oc, "hugetlbsize", +- "Huge pages size (ex: 2M, 1G)", +- &error_abort); ++ "Huge pages size (ex: 2M, 1G)"); + } + object_class_property_add_bool(oc, "seal", + memfd_backend_get_seal, + memfd_backend_set_seal, + &error_abort); + object_class_property_set_description(oc, "seal", +- "Seal growing & shrinking", +- &error_abort); ++ "Seal growing & shrinking"); + } + + static const TypeInfo memfd_backend_info = { +diff --git a/backends/hostmem.c b/backends/hostmem.c +index 327f9eebc3..946d176435 100644 +--- a/backends/hostmem.c ++++ b/backends/hostmem.c +@@ -465,46 +465,46 @@ host_memory_backend_class_init(ObjectClass *oc, void *data) + host_memory_backend_get_merge, + host_memory_backend_set_merge, &error_abort); + object_class_property_set_description(oc, "merge", +- "Mark memory as mergeable", &error_abort); ++ "Mark memory as mergeable"); + object_class_property_add_bool(oc, "dump", + host_memory_backend_get_dump, + host_memory_backend_set_dump, &error_abort); + object_class_property_set_description(oc, "dump", +- "Set to 'off' to exclude from core dump", &error_abort); ++ "Set to 'off' to exclude from core dump"); + object_class_property_add_bool(oc, "prealloc", + host_memory_backend_get_prealloc, + host_memory_backend_set_prealloc, &error_abort); + object_class_property_set_description(oc, "prealloc", +- "Preallocate memory", &error_abort); ++ "Preallocate memory"); + object_class_property_add(oc, "prealloc-threads", "int", + host_memory_backend_get_prealloc_threads, + host_memory_backend_set_prealloc_threads, + NULL, NULL, &error_abort); + object_class_property_set_description(oc, "prealloc-threads", +- "Number of CPU threads to use for prealloc", &error_abort); ++ "Number of CPU threads to use for prealloc"); + object_class_property_add(oc, "size", "int", + host_memory_backend_get_size, + host_memory_backend_set_size, + NULL, NULL, &error_abort); + object_class_property_set_description(oc, "size", +- "Size of the memory region (ex: 500M)", &error_abort); ++ "Size of the memory region (ex: 500M)"); + object_class_property_add(oc, "host-nodes", "int", + host_memory_backend_get_host_nodes, + host_memory_backend_set_host_nodes, + NULL, NULL, &error_abort); + object_class_property_set_description(oc, "host-nodes", +- "Binds memory to the list of NUMA host nodes", &error_abort); ++ "Binds memory to the list of NUMA host nodes"); + object_class_property_add_enum(oc, "policy", "HostMemPolicy", + &HostMemPolicy_lookup, + host_memory_backend_get_policy, + host_memory_backend_set_policy, &error_abort); + object_class_property_set_description(oc, "policy", +- "Set the NUMA policy", &error_abort); ++ "Set the NUMA policy"); + object_class_property_add_bool(oc, "share", + host_memory_backend_get_share, host_memory_backend_set_share, + &error_abort); + object_class_property_set_description(oc, "share", +- "Mark the memory as private to QEMU or shared", &error_abort); ++ "Mark the memory as private to QEMU or shared"); + object_class_property_add_bool(oc, "x-use-canonical-path-for-ramblock-id", + host_memory_backend_get_use_canonical_path, + host_memory_backend_set_use_canonical_path, &error_abort); +diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c +index 4d57d1e436..231527c6c8 100644 +--- a/hw/arm/aspeed.c ++++ b/hw/arm/aspeed.c +@@ -546,7 +546,7 @@ static void aspeed_machine_class_props_init(ObjectClass *oc) + aspeed_get_mmio_exec, + aspeed_set_mmio_exec, &error_abort); + object_class_property_set_description(oc, "execute-in-place", +- "boot directly from CE0 flash device", &error_abort); ++ "boot directly from CE0 flash device"); + } + + static void aspeed_machine_class_init(ObjectClass *oc, void *data) +diff --git a/hw/arm/vexpress.c b/hw/arm/vexpress.c +index ed683eeea5..5372ab6c9b 100644 +--- a/hw/arm/vexpress.c ++++ b/hw/arm/vexpress.c +@@ -752,8 +752,7 @@ static void vexpress_instance_init(Object *obj) + vexpress_set_secure, NULL); + object_property_set_description(obj, "secure", + "Set on/off to enable/disable the ARM " +- "Security Extensions (TrustZone)", +- NULL); ++ "Security Extensions (TrustZone)"); + } + + static void vexpress_a15_instance_init(Object *obj) +@@ -770,8 +769,7 @@ static void vexpress_a15_instance_init(Object *obj) + object_property_set_description(obj, "virtualization", + "Set on/off to enable/disable the ARM " + "Virtualization Extensions " +- "(defaults to same as 'secure')", +- NULL); ++ "(defaults to same as 'secure')"); + } + + static void vexpress_a9_instance_init(Object *obj) +diff --git a/hw/arm/virt.c b/hw/arm/virt.c +index 9e76fa7b01..de66def51e 100644 +--- a/hw/arm/virt.c ++++ b/hw/arm/virt.c +@@ -2272,7 +2272,7 @@ static void virt_machine_class_init(ObjectClass *oc, void *data) + virt_get_acpi, virt_set_acpi, + NULL, NULL, &error_abort); + object_class_property_set_description(oc, "acpi", +- "Enable ACPI", &error_abort); ++ "Enable ACPI"); + } + + static void virt_instance_init(Object *obj) +@@ -2289,8 +2289,7 @@ static void virt_instance_init(Object *obj) + virt_set_secure, NULL); + object_property_set_description(obj, "secure", + "Set on/off to enable/disable the ARM " +- "Security Extensions (TrustZone)", +- NULL); ++ "Security Extensions (TrustZone)"); + + /* EL2 is also disabled by default, for similar reasons */ + vms->virt = false; +@@ -2299,8 +2298,7 @@ static void virt_instance_init(Object *obj) + object_property_set_description(obj, "virtualization", + "Set on/off to enable/disable emulating a " + "guest CPU which implements the ARM " +- "Virtualization Extensions", +- NULL); ++ "Virtualization Extensions"); + + /* High memory is enabled by default */ + vms->highmem = true; +@@ -2308,15 +2306,13 @@ static void virt_instance_init(Object *obj) + virt_set_highmem, NULL); + object_property_set_description(obj, "highmem", + "Set on/off to enable/disable using " +- "physical address space above 32 bits", +- NULL); ++ "physical address space above 32 bits"); + vms->gic_version = VIRT_GIC_VERSION_NOSEL; + object_property_add_str(obj, "gic-version", virt_get_gic_version, + virt_set_gic_version, NULL); + object_property_set_description(obj, "gic-version", + "Set GIC version. " +- "Valid values are 2, 3, host and max", +- NULL); ++ "Valid values are 2, 3, host and max"); + + vms->highmem_ecam = !vmc->no_highmem_ecam; + +@@ -2329,8 +2325,7 @@ static void virt_instance_init(Object *obj) + virt_set_its, NULL); + object_property_set_description(obj, "its", + "Set on/off to enable/disable " +- "ITS instantiation", +- NULL); ++ "ITS instantiation"); + } + + /* Default disallows iommu instantiation */ +@@ -2338,8 +2333,7 @@ static void virt_instance_init(Object *obj) + object_property_add_str(obj, "iommu", virt_get_iommu, virt_set_iommu, NULL); + object_property_set_description(obj, "iommu", + "Set the IOMMU type. " +- "Valid values are none and smmuv3", +- NULL); ++ "Valid values are none and smmuv3"); + + /* Default disallows RAS instantiation */ + vms->ras = false; +@@ -2347,8 +2341,7 @@ static void virt_instance_init(Object *obj) + virt_set_ras, NULL); + object_property_set_description(obj, "ras", + "Set on/off to enable/disable reporting host memory errors " +- "to a KVM guest using ACPI and guest external abort exceptions", +- NULL); ++ "to a KVM guest using ACPI and guest external abort exceptions"); + + vms->irqmap = a15irqmap; + +diff --git a/hw/arm/xlnx-zcu102.c b/hw/arm/xlnx-zcu102.c +index a798e228b7..808fdae804 100644 +--- a/hw/arm/xlnx-zcu102.c ++++ b/hw/arm/xlnx-zcu102.c +@@ -212,8 +212,7 @@ static void xlnx_zcu102_machine_instance_init(Object *obj) + zcu102_set_secure, NULL); + object_property_set_description(obj, "secure", + "Set on/off to enable/disable the ARM " +- "Security Extensions (TrustZone)", +- NULL); ++ "Security Extensions (TrustZone)"); + + /* Default to virt (EL2) being disabled */ + s->virt = false; +@@ -222,8 +221,7 @@ static void xlnx_zcu102_machine_instance_init(Object *obj) + object_property_set_description(obj, "virtualization", + "Set on/off to enable/disable emulating a " + "guest CPU which implements the ARM " +- "Virtualization Extensions", +- NULL); ++ "Virtualization Extensions"); + } + + static void xlnx_zcu102_machine_class_init(ObjectClass *oc, void *data) +diff --git a/hw/core/machine.c b/hw/core/machine.c +index 7a50dd518f..0cd2033b1f 100644 +--- a/hw/core/machine.c ++++ b/hw/core/machine.c +@@ -789,83 +789,82 @@ static void machine_class_init(ObjectClass *oc, void *data) + object_class_property_add_str(oc, "kernel", + machine_get_kernel, machine_set_kernel, &error_abort); + object_class_property_set_description(oc, "kernel", +- "Linux kernel image file", &error_abort); ++ "Linux kernel image file"); + + object_class_property_add_str(oc, "initrd", + machine_get_initrd, machine_set_initrd, &error_abort); + object_class_property_set_description(oc, "initrd", +- "Linux initial ramdisk file", &error_abort); ++ "Linux initial ramdisk file"); + + object_class_property_add_str(oc, "append", + machine_get_append, machine_set_append, &error_abort); + object_class_property_set_description(oc, "append", +- "Linux kernel command line", &error_abort); ++ "Linux kernel command line"); + + object_class_property_add_str(oc, "dtb", + machine_get_dtb, machine_set_dtb, &error_abort); + object_class_property_set_description(oc, "dtb", +- "Linux kernel device tree file", &error_abort); ++ "Linux kernel device tree file"); + + object_class_property_add_str(oc, "dumpdtb", + machine_get_dumpdtb, machine_set_dumpdtb, &error_abort); + object_class_property_set_description(oc, "dumpdtb", +- "Dump current dtb to a file and quit", &error_abort); ++ "Dump current dtb to a file and quit"); + + object_class_property_add(oc, "phandle-start", "int", + machine_get_phandle_start, machine_set_phandle_start, + NULL, NULL, &error_abort); + object_class_property_set_description(oc, "phandle-start", +- "The first phandle ID we may generate dynamically", &error_abort); ++ "The first phandle ID we may generate dynamically"); + + object_class_property_add_str(oc, "dt-compatible", + machine_get_dt_compatible, machine_set_dt_compatible, &error_abort); + object_class_property_set_description(oc, "dt-compatible", +- "Overrides the \"compatible\" property of the dt root node", +- &error_abort); ++ "Overrides the \"compatible\" property of the dt root node"); + + object_class_property_add_bool(oc, "dump-guest-core", + machine_get_dump_guest_core, machine_set_dump_guest_core, &error_abort); + object_class_property_set_description(oc, "dump-guest-core", +- "Include guest memory in a core dump", &error_abort); ++ "Include guest memory in a core dump"); + + object_class_property_add_bool(oc, "mem-merge", + machine_get_mem_merge, machine_set_mem_merge, &error_abort); + object_class_property_set_description(oc, "mem-merge", +- "Enable/disable memory merge support", &error_abort); ++ "Enable/disable memory merge support"); + + object_class_property_add_bool(oc, "usb", + machine_get_usb, machine_set_usb, &error_abort); + object_class_property_set_description(oc, "usb", +- "Set on/off to enable/disable usb", &error_abort); ++ "Set on/off to enable/disable usb"); + + object_class_property_add_bool(oc, "graphics", + machine_get_graphics, machine_set_graphics, &error_abort); + object_class_property_set_description(oc, "graphics", +- "Set on/off to enable/disable graphics emulation", &error_abort); ++ "Set on/off to enable/disable graphics emulation"); + + object_class_property_add_str(oc, "firmware", + machine_get_firmware, machine_set_firmware, + &error_abort); + object_class_property_set_description(oc, "firmware", +- "Firmware image", &error_abort); ++ "Firmware image"); + + object_class_property_add_bool(oc, "suppress-vmdesc", + machine_get_suppress_vmdesc, machine_set_suppress_vmdesc, + &error_abort); + object_class_property_set_description(oc, "suppress-vmdesc", +- "Set on to disable self-describing migration", &error_abort); ++ "Set on to disable self-describing migration"); + + object_class_property_add_bool(oc, "enforce-config-section", + machine_get_enforce_config_section, machine_set_enforce_config_section, + &error_abort); + object_class_property_set_description(oc, "enforce-config-section", +- "Set on to enforce configuration section migration", &error_abort); ++ "Set on to enforce configuration section migration"); + + object_class_property_add_str(oc, "memory-encryption", + machine_get_memory_encryption, machine_set_memory_encryption, + &error_abort); + object_class_property_set_description(oc, "memory-encryption", +- "Set memory encryption object to use", &error_abort); ++ "Set memory encryption object to use"); + } + + static void machine_class_base_init(ObjectClass *oc, void *data) +@@ -898,7 +897,7 @@ static void machine_initfn(Object *obj) + &error_abort); + object_property_set_description(obj, "nvdimm", + "Set on/off to enable/disable " +- "NVDIMM instantiation", NULL); ++ "NVDIMM instantiation"); + + object_property_add_str(obj, "nvdimm-persistence", + machine_get_nvdimm_persistence, +@@ -906,8 +905,7 @@ static void machine_initfn(Object *obj) + &error_abort); + object_property_set_description(obj, "nvdimm-persistence", + "Set NVDIMM persistence" +- "Valid values are cpu, mem-ctrl", +- NULL); ++ "Valid values are cpu, mem-ctrl"); + } + + if (mc->cpu_index_to_instance_props && mc->get_default_cpu_node_id) { +@@ -918,7 +916,7 @@ static void machine_initfn(Object *obj) + object_property_set_description(obj, "hmat", + "Set on/off to enable/disable " + "ACPI Heterogeneous Memory Attribute " +- "Table (HMAT)", NULL); ++ "Table (HMAT)"); + } + + object_property_add_str(obj, "memory-backend", +@@ -926,8 +924,7 @@ static void machine_initfn(Object *obj) + &error_abort); + object_property_set_description(obj, "memory-backend", + "Set RAM backend" +- "Valid value is ID of hostmem based backend", +- &error_abort); ++ "Valid value is ID of hostmem based backend"); + + /* Register notifier when init is done for sysbus sanity checks */ + ms->sysbus_notifier.notify = machine_init_notify; +diff --git a/hw/core/qdev.c b/hw/core/qdev.c +index dd77a56067..ea7118ab0e 100644 +--- a/hw/core/qdev.c ++++ b/hw/core/qdev.c +@@ -775,8 +775,7 @@ void qdev_property_add_static(DeviceState *dev, Property *prop) + prop, &error_abort); + + object_property_set_description(obj, prop->name, +- prop->info->description, +- &error_abort); ++ prop->info->description); + + if (prop->set_default) { + prop->info->set_default_value(op, prop); +@@ -805,8 +804,7 @@ static void qdev_class_add_property(DeviceClass *klass, Property *prop) + } + } + object_class_property_set_description(oc, prop->name, +- prop->info->description, +- &error_abort); ++ prop->info->description); + } + + /* @qdev_alias_all_properties - Add alias properties to the source object for +diff --git a/hw/i386/microvm.c b/hw/i386/microvm.c +index 38d8e51703..76aaa7a8d8 100644 +--- a/hw/i386/microvm.c ++++ b/hw/i386/microvm.c +@@ -512,36 +512,35 @@ static void microvm_class_init(ObjectClass *oc, void *data) + microvm_machine_set_pic, + NULL, NULL, &error_abort); + object_class_property_set_description(oc, MICROVM_MACHINE_PIC, +- "Enable i8259 PIC", &error_abort); ++ "Enable i8259 PIC"); + + object_class_property_add(oc, MICROVM_MACHINE_PIT, "OnOffAuto", + microvm_machine_get_pit, + microvm_machine_set_pit, + NULL, NULL, &error_abort); + object_class_property_set_description(oc, MICROVM_MACHINE_PIT, +- "Enable i8254 PIT", &error_abort); ++ "Enable i8254 PIT"); + + object_class_property_add(oc, MICROVM_MACHINE_RTC, "OnOffAuto", + microvm_machine_get_rtc, + microvm_machine_set_rtc, + NULL, NULL, &error_abort); + object_class_property_set_description(oc, MICROVM_MACHINE_RTC, +- "Enable MC146818 RTC", &error_abort); ++ "Enable MC146818 RTC"); + + object_class_property_add_bool(oc, MICROVM_MACHINE_ISA_SERIAL, + microvm_machine_get_isa_serial, + microvm_machine_set_isa_serial, + &error_abort); + object_class_property_set_description(oc, MICROVM_MACHINE_ISA_SERIAL, +- "Set off to disable the instantiation an ISA serial port", +- &error_abort); ++ "Set off to disable the instantiation an ISA serial port"); + + object_class_property_add_bool(oc, MICROVM_MACHINE_OPTION_ROMS, + microvm_machine_get_option_roms, + microvm_machine_set_option_roms, + &error_abort); + object_class_property_set_description(oc, MICROVM_MACHINE_OPTION_ROMS, +- "Set off to disable loading option ROMs", &error_abort); ++ "Set off to disable loading option ROMs"); + + object_class_property_add_bool(oc, MICROVM_MACHINE_AUTO_KERNEL_CMDLINE, + microvm_machine_get_auto_kernel_cmdline, +@@ -549,8 +548,7 @@ static void microvm_class_init(ObjectClass *oc, void *data) + &error_abort); + object_class_property_set_description(oc, + MICROVM_MACHINE_AUTO_KERNEL_CMDLINE, +- "Set off to disable adding virtio-mmio devices to the kernel cmdline", +- &error_abort); ++ "Set off to disable adding virtio-mmio devices to the kernel cmdline"); + } + + static const TypeInfo microvm_machine_info = { +diff --git a/hw/i386/pc.c b/hw/i386/pc.c +index 97e345faea..21d4a8ec3a 100644 +--- a/hw/i386/pc.c ++++ b/hw/i386/pc.c +@@ -1971,7 +1971,7 @@ static void pc_machine_class_init(ObjectClass *oc, void *data) + pc_machine_get_vmport, pc_machine_set_vmport, + NULL, NULL, &error_abort); + object_class_property_set_description(oc, PC_MACHINE_VMPORT, +- "Enable vmport (pc & q35)", &error_abort); ++ "Enable vmport (pc & q35)"); + + object_class_property_add_bool(oc, PC_MACHINE_SMBUS, + pc_machine_get_smbus, pc_machine_set_smbus, &error_abort); +diff --git a/hw/i386/x86.c b/hw/i386/x86.c +index b82770024c..e2bf601273 100644 +--- a/hw/i386/x86.c ++++ b/hw/i386/x86.c +@@ -984,19 +984,19 @@ static void x86_machine_class_init(ObjectClass *oc, void *data) + x86_machine_get_max_ram_below_4g, x86_machine_set_max_ram_below_4g, + NULL, NULL, &error_abort); + object_class_property_set_description(oc, X86_MACHINE_MAX_RAM_BELOW_4G, +- "Maximum ram below the 4G boundary (32bit boundary)", &error_abort); ++ "Maximum ram below the 4G boundary (32bit boundary)"); + + object_class_property_add(oc, X86_MACHINE_SMM, "OnOffAuto", + x86_machine_get_smm, x86_machine_set_smm, + NULL, NULL, &error_abort); + object_class_property_set_description(oc, X86_MACHINE_SMM, +- "Enable SMM", &error_abort); ++ "Enable SMM"); + + object_class_property_add(oc, X86_MACHINE_ACPI, "OnOffAuto", + x86_machine_get_acpi, x86_machine_set_acpi, + NULL, NULL, &error_abort); + object_class_property_set_description(oc, X86_MACHINE_ACPI, +- "Enable ACPI", &error_abort); ++ "Enable ACPI"); + } + + static const TypeInfo x86_machine_info = { +diff --git a/hw/ppc/mac_newworld.c b/hw/ppc/mac_newworld.c +index 428cf63578..55d1419442 100644 +--- a/hw/ppc/mac_newworld.c ++++ b/hw/ppc/mac_newworld.c +@@ -631,8 +631,7 @@ static void core99_instance_init(Object *obj) + core99_set_via_config, NULL); + object_property_set_description(obj, "via", + "Set VIA configuration. " +- "Valid values are cuda, pmu and pmu-adb", +- NULL); ++ "Valid values are cuda, pmu and pmu-adb"); + + return; + } +diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c +index a3b7a8d0ff..4666dbbe7a 100644 +--- a/hw/ppc/pnv.c ++++ b/hw/ppc/pnv.c +@@ -2030,8 +2030,7 @@ static void pnv_machine_class_init(ObjectClass *oc, void *data) + pnv_machine_get_hb, pnv_machine_set_hb, + &error_abort); + object_class_property_set_description(oc, "hb-mode", +- "Use a hostboot like boot loader", +- NULL); ++ "Use a hostboot like boot loader"); + } + + #define DEFINE_PNV8_CHIP_TYPE(type, class_initfn) \ +diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c +index c18eab0a23..aa281e727a 100644 +--- a/hw/ppc/spapr.c ++++ b/hw/ppc/spapr.c +@@ -3307,8 +3307,7 @@ static void spapr_instance_init(Object *obj) + object_property_add_str(obj, "kvm-type", + spapr_get_kvm_type, spapr_set_kvm_type, NULL); + object_property_set_description(obj, "kvm-type", +- "Specifies the KVM virtualization mode (HV, PR)", +- NULL); ++ "Specifies the KVM virtualization mode (HV, PR)"); + object_property_add_bool(obj, "modern-hotplug-events", + spapr_get_modern_hotplug_events, + spapr_set_modern_hotplug_events, +@@ -3316,8 +3315,7 @@ static void spapr_instance_init(Object *obj) + object_property_set_description(obj, "modern-hotplug-events", + "Use dedicated hotplug event mechanism in" + " place of standard EPOW events when possible" +- " (required for memory hot-unplug support)", +- NULL); ++ " (required for memory hot-unplug support)"); + ppc_compat_add_property(obj, "max-cpu-compat", &spapr->max_compat_pvr, + "Maximum permitted CPU compatibility mode", + &error_fatal); +@@ -3325,14 +3323,13 @@ static void spapr_instance_init(Object *obj) + object_property_add_str(obj, "resize-hpt", + spapr_get_resize_hpt, spapr_set_resize_hpt, NULL); + object_property_set_description(obj, "resize-hpt", +- "Resizing of the Hash Page Table (enabled, disabled, required)", +- NULL); ++ "Resizing of the Hash Page Table (enabled, disabled, required)"); + object_property_add_uint32_ptr(obj, "vsmt", + &spapr->vsmt, OBJ_PROP_FLAG_READWRITE, + &error_abort); + object_property_set_description(obj, "vsmt", + "Virtual SMT: KVM behaves as if this were" +- " the host's SMT mode", &error_abort); ++ " the host's SMT mode"); + + object_property_add_bool(obj, "vfio-no-msix-emulation", + spapr_get_msix_emulation, NULL, NULL); +@@ -3342,27 +3339,25 @@ static void spapr_instance_init(Object *obj) + &error_abort); + object_property_set_description(obj, "kernel-addr", + stringify(KERNEL_LOAD_ADDR) +- " for -kernel is the default", +- NULL); ++ " for -kernel is the default"); + spapr->kernel_addr = KERNEL_LOAD_ADDR; + /* The machine class defines the default interrupt controller mode */ + spapr->irq = smc->irq; + object_property_add_str(obj, "ic-mode", spapr_get_ic_mode, + spapr_set_ic_mode, NULL); + object_property_set_description(obj, "ic-mode", +- "Specifies the interrupt controller mode (xics, xive, dual)", +- NULL); ++ "Specifies the interrupt controller mode (xics, xive, dual)"); + + object_property_add_str(obj, "host-model", + spapr_get_host_model, spapr_set_host_model, + &error_abort); + object_property_set_description(obj, "host-model", +- "Host model to advertise in guest device tree", &error_abort); ++ "Host model to advertise in guest device tree"); + object_property_add_str(obj, "host-serial", + spapr_get_host_serial, spapr_set_host_serial, + &error_abort); + object_property_set_description(obj, "host-serial", +- "Host serial number to advertise in guest device tree", &error_abort); ++ "Host serial number to advertise in guest device tree"); + } + + static void spapr_machine_finalizefn(Object *obj) +diff --git a/hw/ppc/spapr_caps.c b/hw/ppc/spapr_caps.c +index eb54f94227..0870961fc9 100644 +--- a/hw/ppc/spapr_caps.c ++++ b/hw/ppc/spapr_caps.c +@@ -845,12 +845,8 @@ void spapr_caps_add_properties(SpaprMachineClass *smc, Error **errp) + } + + desc = g_strdup_printf("%s", cap->description); +- object_class_property_set_description(klass, name, desc, &local_err); ++ object_class_property_set_description(klass, name, desc); + g_free(name); + g_free(desc); +- if (local_err) { +- error_propagate(errp, local_err); +- return; +- } + } + } +diff --git a/hw/ppc/spapr_rng.c b/hw/ppc/spapr_rng.c +index e8e8d65ec0..85bf64d68e 100644 +--- a/hw/ppc/spapr_rng.c ++++ b/hw/ppc/spapr_rng.c +@@ -103,8 +103,7 @@ static void spapr_rng_instance_init(Object *obj) + } + + object_property_set_description(obj, "rng", +- "ID of the random number generator backend", +- NULL); ++ "ID of the random number generator backend"); + } + + static void spapr_rng_realize(DeviceState *dev, Error **errp) +diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c +index bed10fcfa8..da48c958e2 100644 +--- a/hw/riscv/sifive_u.c ++++ b/hw/riscv/sifive_u.c +@@ -445,13 +445,12 @@ static void sifive_u_machine_instance_init(Object *obj) + sifive_u_machine_set_start_in_flash, NULL); + object_property_set_description(obj, "start-in-flash", + "Set on to tell QEMU's ROM to jump to " +- "flash. Otherwise QEMU will jump to DRAM", +- NULL); ++ "flash. Otherwise QEMU will jump to DRAM"); + + s->serial = OTP_SERIAL; + object_property_add(obj, "serial", "uint32", sifive_u_machine_get_serial, + sifive_u_machine_set_serial, NULL, &s->serial, NULL); +- object_property_set_description(obj, "serial", "Board serial number", NULL); ++ object_property_set_description(obj, "serial", "Board serial number"); + } + + static void sifive_u_machine_class_init(ObjectClass *oc, void *data) +diff --git a/hw/s390x/css-bridge.c b/hw/s390x/css-bridge.c +index a306a78e6c..c9ce06b043 100644 +--- a/hw/s390x/css-bridge.c ++++ b/hw/s390x/css-bridge.c +@@ -144,8 +144,7 @@ static void virtual_css_bridge_class_init(ObjectClass *klass, void *data) + prop_get_true, NULL, NULL); + object_class_property_set_description(klass, "cssid-unrestricted", + "A css device can use any cssid, regardless whether virtual" +- " or not (read only, always true)", +- NULL); ++ " or not (read only, always true)"); + } + + static const TypeInfo virtual_css_bridge_info = { +diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c +index f660070d22..2f94061ff6 100644 +--- a/hw/s390x/s390-virtio-ccw.c ++++ b/hw/s390x/s390-virtio-ccw.c +@@ -731,24 +731,21 @@ static inline void s390_machine_initfn(Object *obj) + machine_get_aes_key_wrap, + machine_set_aes_key_wrap, NULL); + object_property_set_description(obj, "aes-key-wrap", +- "enable/disable AES key wrapping using the CPACF wrapping key", +- NULL); ++ "enable/disable AES key wrapping using the CPACF wrapping key"); + object_property_set_bool(obj, true, "aes-key-wrap", NULL); + + object_property_add_bool(obj, "dea-key-wrap", + machine_get_dea_key_wrap, + machine_set_dea_key_wrap, NULL); + object_property_set_description(obj, "dea-key-wrap", +- "enable/disable DEA key wrapping using the CPACF wrapping key", +- NULL); ++ "enable/disable DEA key wrapping using the CPACF wrapping key"); + object_property_set_bool(obj, true, "dea-key-wrap", NULL); + object_property_add_str(obj, "loadparm", + machine_get_loadparm, machine_set_loadparm, NULL); + object_property_set_description(obj, "loadparm", + "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", +- NULL); ++ " and guest kernel"); + } + + static const TypeInfo ccw_machine_info = { +diff --git a/hw/sparc/sun4m.c b/hw/sparc/sun4m.c +index 36ee1a0a3d..7472d24e2c 100644 +--- a/hw/sparc/sun4m.c ++++ b/hw/sparc/sun4m.c +@@ -797,8 +797,7 @@ static void ram_initfn(Object *obj) + object_property_allow_set_link, + OBJ_PROP_LINK_STRONG, &error_abort); + object_property_set_description(obj, "memdev", "Set RAM backend" +- "Valid value is ID of a hostmem backend", +- &error_abort); ++ "Valid value is ID of a hostmem backend"); + } + + static void ram_class_init(ObjectClass *klass, void *data) +diff --git a/hw/xen/xen-common.c b/hw/xen/xen-common.c +index a15070f7f6..adaab81ce0 100644 +--- a/hw/xen/xen-common.c ++++ b/hw/xen/xen-common.c +@@ -201,7 +201,7 @@ static void xen_accel_class_init(ObjectClass *oc, void *data) + xen_get_igd_gfx_passthru, xen_set_igd_gfx_passthru, + &error_abort); + object_class_property_set_description(oc, "igd-passthru", +- "Set on/off to enable/disable igd passthrou", &error_abort); ++ "Set on/off to enable/disable igd passthrou"); + } + + #define TYPE_XEN_ACCEL ACCEL_CLASS_NAME("xen") +diff --git a/include/qom/object.h b/include/qom/object.h +index 0ea5808432..1f0386a231 100644 +--- a/include/qom/object.h ++++ b/include/qom/object.h +@@ -1813,16 +1813,14 @@ ObjectProperty *object_property_add_const_link(Object *obj, const char *name, + * @obj: the object owning the property + * @name: the name of the property + * @description: the description of the property on the object +- * @errp: if an error occurs, a pointer to an area to store the error + * + * Set an object property's description. + * + */ + void object_property_set_description(Object *obj, const char *name, +- const char *description, Error **errp); ++ const char *description); + void object_class_property_set_description(ObjectClass *klass, const char *name, +- const char *description, +- Error **errp); ++ const char *description); + + /** + * object_child_foreach: +diff --git a/qom/object.c b/qom/object.c +index 4e5b2ecacd..58a6ec9b1b 100644 +--- a/qom/object.c ++++ b/qom/object.c +@@ -2802,38 +2802,27 @@ object_property_add_alias(Object *obj, const char *name, + } + + object_property_set_description(obj, op->name, +- target_prop->description, +- &error_abort); ++ target_prop->description); + return op; + } + + void object_property_set_description(Object *obj, const char *name, +- const char *description, Error **errp) ++ const char *description) + { + ObjectProperty *op; + +- op = object_property_find(obj, name, errp); +- if (!op) { +- return; +- } +- ++ op = object_property_find(obj, name, &error_abort); + g_free(op->description); + op->description = g_strdup(description); + } + + void object_class_property_set_description(ObjectClass *klass, + const char *name, +- const char *description, +- Error **errp) ++ const char *description) + { + ObjectProperty *op; + + op = g_hash_table_lookup(klass->properties, name); +- if (!op) { +- error_setg(errp, "Property '.%s' not found", name); +- return; +- } +- + g_free(op->description); + op->description = g_strdup(description); + } +diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c +index f5c49ee32d..18a0af88e2 100644 +--- a/target/arm/cpu64.c ++++ b/target/arm/cpu64.c +@@ -770,8 +770,7 @@ static void aarch64_cpu_initfn(Object *obj) + aarch64_cpu_set_aarch64, NULL); + object_property_set_description(obj, "aarch64", + "Set on/off to enable/disable aarch64 " +- "execution state ", +- NULL); ++ "execution state "); + } + + static void aarch64_cpu_finalizefn(Object *obj) +diff --git a/target/arm/kvm.c b/target/arm/kvm.c +index 390077c518..1ea2d047e3 100644 +--- a/target/arm/kvm.c ++++ b/target/arm/kvm.c +@@ -204,7 +204,7 @@ void kvm_arm_add_vcpu_properties(Object *obj) + object_property_set_description(obj, "kvm-no-adjvtime", + "Set on to disable the adjustment of " + "the virtual counter. VM stopped time " +- "will be counted.", &error_abort); ++ "will be counted."); + } + + bool kvm_arm_pmu_supported(CPUState *cpu) +diff --git a/target/i386/sev.c b/target/i386/sev.c +index 846018a12d..6842cfc26d 100644 +--- a/target/i386/sev.c ++++ b/target/i386/sev.c +@@ -251,19 +251,19 @@ qsev_guest_class_init(ObjectClass *oc, void *data) + qsev_guest_set_sev_device, + NULL); + object_class_property_set_description(oc, "sev-device", +- "SEV device to use", NULL); ++ "SEV device to use"); + object_class_property_add_str(oc, "dh-cert-file", + qsev_guest_get_dh_cert_file, + qsev_guest_set_dh_cert_file, + NULL); + object_class_property_set_description(oc, "dh-cert-file", +- "guest owners DH certificate (encoded with base64)", NULL); ++ "guest owners DH certificate (encoded with base64)"); + object_class_property_add_str(oc, "session-file", + qsev_guest_get_session_file, + qsev_guest_set_session_file, + NULL); + object_class_property_set_description(oc, "session-file", +- "guest owners session parameters (encoded with base64)", NULL); ++ "guest owners session parameters (encoded with base64)"); + } + + static void +diff --git a/target/ppc/compat.c b/target/ppc/compat.c +index f48df25944..46ffb6da6d 100644 +--- a/target/ppc/compat.c ++++ b/target/ppc/compat.c +@@ -324,7 +324,7 @@ void ppc_compat_add_property(Object *obj, const char *name, + + names = g_strjoinv(", ", namesv); + desc = g_strdup_printf("%s. Valid values are %s.", basedesc, names); +- object_property_set_description(obj, name, desc, &local_err); ++ object_property_set_description(obj, name, desc); + + g_free(names); + g_free(desc); +diff --git a/target/s390x/cpu_models.c b/target/s390x/cpu_models.c +index 7c32180269..aa7fc713ca 100644 +--- a/target/s390x/cpu_models.c ++++ b/target/s390x/cpu_models.c +@@ -1107,13 +1107,13 @@ void s390_cpu_model_register_props(Object *obj) + const S390FeatDef *def = s390_feat_def(feat); + object_property_add(obj, def->name, "bool", get_feature, + set_feature, NULL, (void *) feat, NULL); +- object_property_set_description(obj, def->name, def->desc , NULL); ++ object_property_set_description(obj, def->name, def->desc); + } + for (group = 0; group < S390_FEAT_GROUP_MAX; group++) { + const S390FeatGroupDef *def = s390_feat_group_def(group); + object_property_add(obj, def->name, "bool", get_feature_group, + set_feature_group, NULL, (void *) group, NULL); +- object_property_set_description(obj, def->name, def->desc , NULL); ++ object_property_set_description(obj, def->name, def->desc); + } + } + +-- +2.23.0 + diff --git a/qom-Drop-parameter-errp-of-object_property_add-frien.patch b/qom-Drop-parameter-errp-of-object_property_add-frien.patch new file mode 100644 index 0000000000000000000000000000000000000000..66737ab16df5801f263cba7797b004b5c1113928 --- /dev/null +++ b/qom-Drop-parameter-errp-of-object_property_add-frien.patch @@ -0,0 +1,5860 @@ +From d2623129a7dec1d3041ad1221dda1ca49c667532 Mon Sep 17 00:00:00 2001 +From: Markus Armbruster +Date: Tue, 5 May 2020 17:29:22 +0200 +Subject: [PATCH 476/709] qom: Drop parameter @errp of object_property_add() & + friends + +The only way object_property_add() can fail is when a property with +the same name already exists. Since our property names are all +hardcoded, failure is a programming error, and the appropriate way to +handle it is passing &error_abort. + +Same for its variants, except for object_property_add_child(), which +additionally fails when the child already has a parent. Parentage is +also under program control, so this is a programming error, too. + +We have a bit over 500 callers. Almost half of them pass +&error_abort, slightly fewer ignore errors, one test case handles +errors, and the remaining few callers pass them to their own callers. + +The previous few commits demonstrated once again that ignoring +programming errors is a bad idea. + +Of the few ones that pass on errors, several violate the Error API. +The Error ** argument must be NULL, &error_abort, &error_fatal, or a +pointer to a variable containing NULL. Passing an argument of the +latter kind twice without clearing it in between is wrong: if the +first call sets an error, it no longer points to NULL for the second +call. ich9_pm_add_properties(), sparc32_ledma_realize(), +sparc32_dma_realize(), xilinx_axidma_realize(), xilinx_enet_realize() +are wrong that way. + +When the one appropriate choice of argument is &error_abort, letting +users pick the argument is a bad idea. + +Drop parameter @errp and assert the preconditions instead. + +There's one exception to "duplicate property name is a programming +error": the way object_property_add() implements the magic (and +undocumented) "automatic arrayification". Don't drop @errp there. +Instead, rename object_property_add() to object_property_try_add(), +and add the obvious wrapper object_property_add(). + +Signed-off-by: Markus Armbruster +Reviewed-by: Eric Blake +Reviewed-by: Paolo Bonzini +Message-Id: <20200505152926.18877-15-armbru@redhat.com> +[Two semantic rebase conflicts resolved] +--- + accel/kvm/kvm-all.c | 4 +- + accel/tcg/tcg-all.c | 5 +- + authz/list.c | 5 +- + authz/listfile.c | 6 +- + authz/pamacct.c | 3 +- + authz/simple.c | 3 +- + backends/cryptodev-vhost-user.c | 3 +- + backends/cryptodev.c | 2 +- + backends/dbus-vmstate.c | 6 +- + backends/hostmem-file.c | 11 +- + backends/hostmem-memfd.c | 8 +- + backends/hostmem.c | 19 +- + backends/rng-egd.c | 3 +- + backends/rng-random.c | 3 +- + backends/rng.c | 3 +- + backends/vhost-user.c | 2 +- + block/throttle-groups.c | 6 +- + bootdevice.c | 8 +- + chardev/char-socket.c | 4 +- + chardev/char.c | 7 +- + crypto/secret.c | 18 +- + crypto/tlscreds.c | 12 +- + crypto/tlscredsanon.c | 3 +- + crypto/tlscredspsk.c | 6 +- + crypto/tlscredsx509.c | 9 +- + hw/acpi/ich9.c | 23 +-- + hw/acpi/pcihp.c | 7 +- + hw/acpi/piix4.c | 15 +- + hw/arm/allwinner-a10.c | 2 +- + hw/arm/allwinner-h3.c | 12 +- + hw/arm/armv7m.c | 2 +- + hw/arm/aspeed.c | 2 +- + hw/arm/aspeed_ast2600.c | 13 +- + hw/arm/aspeed_soc.c | 13 +- + hw/arm/bcm2835_peripherals.c | 26 +-- + hw/arm/bcm2836.c | 16 +- + hw/arm/cubieboard.c | 3 +- + hw/arm/mcimx6ul-evk.c | 2 +- + hw/arm/mcimx7d-sabre.c | 2 +- + hw/arm/msf2-soc.c | 3 +- + hw/arm/nrf51_soc.c | 3 +- + hw/arm/orangepi.c | 3 +- + hw/arm/raspi.c | 3 +- + hw/arm/sabrelite.c | 2 +- + hw/arm/sbsa-ref.c | 5 +- + hw/arm/vexpress.c | 4 +- + hw/arm/virt.c | 21 +- + hw/arm/xilinx_zynq.c | 2 +- + hw/arm/xlnx-versal-virt.c | 6 +- + hw/arm/xlnx-versal.c | 2 +- + hw/arm/xlnx-zcu102.c | 4 +- + hw/arm/xlnx-zynqmp.c | 9 +- + hw/audio/marvell_88w8618.c | 2 +- + hw/audio/pcspk.c | 2 +- + hw/core/bus.c | 7 +- + hw/core/machine.c | 46 ++--- + hw/core/qdev-clock.c | 4 +- + hw/core/qdev-properties.c | 9 +- + hw/core/qdev.c | 40 ++-- + hw/cpu/core.c | 4 +- + hw/display/bochs-display.c | 3 +- + hw/display/sm501.c | 2 +- + hw/display/vga-pci.c | 4 +- + hw/display/vhost-user-gpu-pci.c | 3 +- + hw/display/vhost-user-gpu.c | 2 +- + hw/display/vhost-user-vga.c | 3 +- + hw/display/xlnx_dp.c | 7 +- + hw/dma/sparc32_dma.c | 10 +- + hw/dma/xilinx_axidma.c | 12 +- + hw/dma/xlnx-zdma.c | 3 +- + hw/gpio/aspeed_gpio.c | 2 +- + hw/hyperv/hyperv.c | 2 +- + hw/i386/microvm.c | 15 +- + hw/i386/pc.c | 12 +- + hw/i386/pc_piix.c | 2 +- + hw/i386/pc_q35.c | 4 +- + hw/i386/pc_sysfw.c | 5 +- + hw/i386/x86.c | 8 +- + hw/ide/macio.c | 2 +- + hw/ide/qdev.c | 2 +- + hw/input/vhost-user-input.c | 2 +- + hw/intc/apic_common.c | 2 +- + hw/intc/s390_flic.c | 4 +- + hw/intc/xics.c | 2 +- + hw/intc/xive.c | 2 +- + hw/ipmi/ipmi.c | 3 +- + hw/isa/isa-superio.c | 15 +- + hw/isa/lpc_ich9.c | 6 +- + hw/mem/nvdimm.c | 4 +- + hw/mem/pc-dimm.c | 2 +- + hw/microblaze/petalogix_ml605_mmu.c | 6 +- + hw/misc/aspeed_sdmc.c | 2 +- + hw/misc/edu.c | 3 +- + hw/misc/mac_via.c | 4 +- + hw/misc/macio/gpio.c | 2 +- + hw/misc/macio/macio.c | 4 +- + hw/misc/macio/pmu.c | 2 +- + hw/misc/pca9552.c | 2 +- + hw/misc/tmp105.c | 2 +- + hw/misc/tmp421.c | 8 +- + hw/net/cadence_gem.c | 3 +- + hw/net/can/can_kvaser_pci.c | 2 +- + hw/net/can/can_mioe3680_pci.c | 4 +- + hw/net/can/can_pcm3680_pci.c | 4 +- + hw/net/ne2000-isa.c | 2 +- + hw/net/xilinx_axienet.c | 9 +- + hw/nios2/10m50_devboard.c | 3 +- + hw/nvram/fw_cfg.c | 4 +- + hw/pci-host/grackle.c | 2 +- + hw/pci-host/i440fx.c | 12 +- + hw/pci-host/pnv_phb3_msi.c | 3 +- + hw/pci-host/pnv_phb3_pbcq.c | 3 +- + hw/pci-host/q35.c | 20 +- + hw/pci-host/sabre.c | 2 +- + hw/pci-host/uninorth.c | 8 +- + hw/pcmcia/pxa2xx.c | 2 +- + hw/ppc/e500.c | 8 +- + hw/ppc/mac_newworld.c | 4 +- + hw/ppc/mac_oldworld.c | 2 +- + hw/ppc/pnv.c | 13 +- + hw/ppc/pnv_bmc.c | 5 +- + hw/ppc/pnv_core.c | 2 +- + hw/ppc/pnv_psi.c | 2 +- + hw/ppc/prep.c | 6 +- + hw/ppc/spapr.c | 25 +-- + hw/ppc/spapr_caps.c | 8 +- + hw/ppc/spapr_cpu_core.c | 5 +- + hw/ppc/spapr_drc.c | 18 +- + hw/ppc/spapr_iommu.c | 2 +- + hw/ppc/spapr_irq.c | 2 +- + hw/ppc/spapr_rtc.c | 2 +- + hw/riscv/sifive_u.c | 10 +- + hw/riscv/virt.c | 5 +- + hw/rtc/mc146818rtc.c | 4 +- + hw/s390x/ap-bridge.c | 2 +- + hw/s390x/css-bridge.c | 4 +- + hw/s390x/event-facility.c | 6 +- + hw/s390x/s390-skeys.c | 4 +- + hw/s390x/s390-stattrib.c | 4 +- + hw/s390x/s390-virtio-ccw.c | 10 +- + hw/s390x/sclp.c | 5 +- + hw/s390x/tod.c | 2 +- + hw/s390x/virtio-ccw-balloon.c | 4 +- + hw/s390x/virtio-ccw-blk.c | 2 +- + hw/s390x/virtio-ccw-net.c | 2 +- + hw/scsi/scsi-bus.c | 2 +- + hw/sparc/sun4m.c | 4 +- + hw/sparc64/sun4u.c | 2 +- + hw/ssi/xilinx_spips.c | 3 +- + hw/usb/bus.c | 6 +- + hw/usb/dev-storage.c | 2 +- + hw/vfio/pci-quirks.c | 6 +- + hw/virtio/vhost-scsi-pci.c | 2 +- + hw/virtio/vhost-user-blk-pci.c | 2 +- + hw/virtio/vhost-user-input-pci.c | 3 +- + hw/virtio/vhost-user-scsi-pci.c | 2 +- + hw/virtio/virtio-balloon-pci.c | 4 +- + hw/virtio/virtio-balloon.c | 4 +- + hw/virtio/virtio-blk-pci.c | 2 +- + hw/virtio/virtio-net-pci.c | 2 +- + hw/virtio/virtio-rng.c | 2 +- + hw/xen/xen-common.c | 3 +- + include/qom/object.h | 81 +++----- + iothread.c | 6 +- + memory.c | 10 +- + net/can/can_host.c | 3 +- + net/can/can_socketcan.c | 3 +- + net/colo-compare.c | 20 +- + net/dump.c | 4 +- + net/filter-buffer.c | 2 +- + net/filter-mirror.c | 10 +- + net/filter-rewriter.c | 2 +- + net/filter.c | 15 +- + qdev-monitor.c | 4 +- + qom/container.c | 2 +- + qom/object.c | 302 +++++++++------------------- + qom/object_interfaces.c | 5 +- + scsi/pr-manager-helper.c | 3 +- + softmmu/vl.c | 7 +- + target/arm/cpu.c | 11 +- + target/arm/cpu64.c | 8 +- + target/arm/kvm.c | 2 +- + target/i386/cpu.c | 85 ++++---- + target/i386/sev.c | 17 +- + target/ppc/compat.c | 9 +- + target/s390x/cpu.c | 2 +- + target/s390x/cpu_models.c | 11 +- + tests/check-qom-proplist.c | 29 +-- + tests/test-qdev-global-props.c | 4 +- + ui/console.c | 7 +- + ui/input-barrier.c | 14 +- + ui/input-linux.c | 8 +- + 192 files changed, 651 insertions(+), 995 deletions(-) + +diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c +index 9b712aac77..d06cc04079 100644 +--- a/accel/kvm/kvm-all.c ++++ b/accel/kvm/kvm-all.c +@@ -3111,13 +3111,13 @@ static void kvm_accel_class_init(ObjectClass *oc, void *data) + + object_class_property_add(oc, "kernel-irqchip", "on|off|split", + NULL, kvm_set_kernel_irqchip, +- NULL, NULL, &error_abort); ++ NULL, NULL); + object_class_property_set_description(oc, "kernel-irqchip", + "Configure KVM in-kernel irqchip"); + + object_class_property_add(oc, "kvm-shadow-mem", "int", + kvm_get_kvm_shadow_mem, kvm_set_kvm_shadow_mem, +- NULL, NULL, &error_abort); ++ NULL, NULL); + object_class_property_set_description(oc, "kvm-shadow-mem", + "KVM shadow MMU size"); + } +diff --git a/accel/tcg/tcg-all.c b/accel/tcg/tcg-all.c +index 3398a56ef9..3b4fda5640 100644 +--- a/accel/tcg/tcg-all.c ++++ b/accel/tcg/tcg-all.c +@@ -203,12 +203,11 @@ static void tcg_accel_class_init(ObjectClass *oc, void *data) + + object_class_property_add_str(oc, "thread", + tcg_get_thread, +- tcg_set_thread, +- NULL); ++ tcg_set_thread); + + object_class_property_add(oc, "tb-size", "int", + tcg_get_tb_size, tcg_set_tb_size, +- NULL, NULL, &error_abort); ++ NULL, NULL); + object_class_property_set_description(oc, "tb-size", + "TCG translation block cache size"); + +diff --git a/authz/list.c b/authz/list.c +index 5a48074d0a..8e904bfc93 100644 +--- a/authz/list.c ++++ b/authz/list.c +@@ -124,13 +124,12 @@ qauthz_list_class_init(ObjectClass *oc, void *data) + "QAuthZListPolicy", + &QAuthZListPolicy_lookup, + qauthz_list_prop_get_policy, +- qauthz_list_prop_set_policy, +- NULL); ++ qauthz_list_prop_set_policy); + + object_class_property_add(oc, "rules", "QAuthZListRule", + qauthz_list_prop_get_rules, + qauthz_list_prop_set_rules, +- NULL, NULL, NULL); ++ NULL, NULL); + + authz->is_allowed = qauthz_list_is_allowed; + } +diff --git a/authz/listfile.c b/authz/listfile.c +index b71f57d30a..666df872ad 100644 +--- a/authz/listfile.c ++++ b/authz/listfile.c +@@ -221,12 +221,10 @@ qauthz_list_file_class_init(ObjectClass *oc, void *data) + + object_class_property_add_str(oc, "filename", + qauthz_list_file_prop_get_filename, +- qauthz_list_file_prop_set_filename, +- NULL); ++ qauthz_list_file_prop_set_filename); + object_class_property_add_bool(oc, "refresh", + qauthz_list_file_prop_get_refresh, +- qauthz_list_file_prop_set_refresh, +- NULL); ++ qauthz_list_file_prop_set_refresh); + + authz->is_allowed = qauthz_list_file_is_allowed; + } +diff --git a/authz/pamacct.c b/authz/pamacct.c +index a8ad25b6c7..3c6be43916 100644 +--- a/authz/pamacct.c ++++ b/authz/pamacct.c +@@ -107,8 +107,7 @@ qauthz_pam_class_init(ObjectClass *oc, void *data) + + object_class_property_add_str(oc, "service", + qauthz_pam_prop_get_service, +- qauthz_pam_prop_set_service, +- NULL); ++ qauthz_pam_prop_set_service); + } + + +diff --git a/authz/simple.c b/authz/simple.c +index 008912d247..84954b80a5 100644 +--- a/authz/simple.c ++++ b/authz/simple.c +@@ -74,8 +74,7 @@ qauthz_simple_class_init(ObjectClass *oc, void *data) + + object_class_property_add_str(oc, "identity", + qauthz_simple_prop_get_identity, +- qauthz_simple_prop_set_identity, +- NULL); ++ qauthz_simple_prop_set_identity); + } + + +diff --git a/backends/cryptodev-vhost-user.c b/backends/cryptodev-vhost-user.c +index 6edada8e9e..8b8cbc4223 100644 +--- a/backends/cryptodev-vhost-user.c ++++ b/backends/cryptodev-vhost-user.c +@@ -340,8 +340,7 @@ static void cryptodev_vhost_user_instance_int(Object *obj) + { + object_property_add_str(obj, "chardev", + cryptodev_vhost_user_get_chardev, +- cryptodev_vhost_user_set_chardev, +- NULL); ++ cryptodev_vhost_user_set_chardev); + } + + static void cryptodev_vhost_user_finalize(Object *obj) +diff --git a/backends/cryptodev.c b/backends/cryptodev.c +index 5a9735684e..a3841c4e41 100644 +--- a/backends/cryptodev.c ++++ b/backends/cryptodev.c +@@ -213,7 +213,7 @@ static void cryptodev_backend_instance_init(Object *obj) + object_property_add(obj, "queues", "uint32", + cryptodev_backend_get_queues, + cryptodev_backend_set_queues, +- NULL, NULL, NULL); ++ NULL, NULL); + /* Initialize devices' queues property to 1 */ + object_property_set_int(obj, 1, "queues", NULL); + } +diff --git a/backends/dbus-vmstate.c b/backends/dbus-vmstate.c +index cc594a722e..56361a6272 100644 +--- a/backends/dbus-vmstate.c ++++ b/backends/dbus-vmstate.c +@@ -481,11 +481,9 @@ dbus_vmstate_class_init(ObjectClass *oc, void *data) + vc->get_id = dbus_vmstate_get_id; + + object_class_property_add_str(oc, "addr", +- get_dbus_addr, set_dbus_addr, +- &error_abort); ++ get_dbus_addr, set_dbus_addr); + object_class_property_add_str(oc, "id-list", +- get_id_list, set_id_list, +- &error_abort); ++ get_id_list, set_id_list); + } + + static const TypeInfo dbus_vmstate_info = { +diff --git a/backends/hostmem-file.c b/backends/hostmem-file.c +index c8c355f5aa..cdabb412e6 100644 +--- a/backends/hostmem-file.c ++++ b/backends/hostmem-file.c +@@ -184,18 +184,15 @@ file_backend_class_init(ObjectClass *oc, void *data) + oc->unparent = file_backend_unparent; + + object_class_property_add_bool(oc, "discard-data", +- file_memory_backend_get_discard_data, file_memory_backend_set_discard_data, +- &error_abort); ++ file_memory_backend_get_discard_data, file_memory_backend_set_discard_data); + object_class_property_add_str(oc, "mem-path", +- get_mem_path, set_mem_path, +- &error_abort); ++ get_mem_path, set_mem_path); + object_class_property_add(oc, "align", "int", + file_memory_backend_get_align, + file_memory_backend_set_align, +- NULL, NULL, &error_abort); ++ NULL, NULL); + object_class_property_add_bool(oc, "pmem", +- file_memory_backend_get_pmem, file_memory_backend_set_pmem, +- &error_abort); ++ file_memory_backend_get_pmem, file_memory_backend_set_pmem); + } + + static void file_backend_instance_finalize(Object *o) +diff --git a/backends/hostmem-memfd.c b/backends/hostmem-memfd.c +index 5991f31459..1b5e4bfe0d 100644 +--- a/backends/hostmem-memfd.c ++++ b/backends/hostmem-memfd.c +@@ -141,21 +141,19 @@ memfd_backend_class_init(ObjectClass *oc, void *data) + if (qemu_memfd_check(MFD_HUGETLB)) { + object_class_property_add_bool(oc, "hugetlb", + memfd_backend_get_hugetlb, +- memfd_backend_set_hugetlb, +- &error_abort); ++ memfd_backend_set_hugetlb); + object_class_property_set_description(oc, "hugetlb", + "Use huge pages"); + object_class_property_add(oc, "hugetlbsize", "int", + memfd_backend_get_hugetlbsize, + memfd_backend_set_hugetlbsize, +- NULL, NULL, &error_abort); ++ NULL, NULL); + object_class_property_set_description(oc, "hugetlbsize", + "Huge pages size (ex: 2M, 1G)"); + } + object_class_property_add_bool(oc, "seal", + memfd_backend_get_seal, +- memfd_backend_set_seal, +- &error_abort); ++ memfd_backend_set_seal); + object_class_property_set_description(oc, "seal", + "Seal growing & shrinking"); + } +diff --git a/backends/hostmem.c b/backends/hostmem.c +index 946d176435..4ee4354898 100644 +--- a/backends/hostmem.c ++++ b/backends/hostmem.c +@@ -463,51 +463,50 @@ host_memory_backend_class_init(ObjectClass *oc, void *data) + + object_class_property_add_bool(oc, "merge", + host_memory_backend_get_merge, +- host_memory_backend_set_merge, &error_abort); ++ host_memory_backend_set_merge); + object_class_property_set_description(oc, "merge", + "Mark memory as mergeable"); + object_class_property_add_bool(oc, "dump", + host_memory_backend_get_dump, +- host_memory_backend_set_dump, &error_abort); ++ host_memory_backend_set_dump); + object_class_property_set_description(oc, "dump", + "Set to 'off' to exclude from core dump"); + object_class_property_add_bool(oc, "prealloc", + host_memory_backend_get_prealloc, +- host_memory_backend_set_prealloc, &error_abort); ++ host_memory_backend_set_prealloc); + object_class_property_set_description(oc, "prealloc", + "Preallocate memory"); + object_class_property_add(oc, "prealloc-threads", "int", + host_memory_backend_get_prealloc_threads, + host_memory_backend_set_prealloc_threads, +- NULL, NULL, &error_abort); ++ NULL, NULL); + object_class_property_set_description(oc, "prealloc-threads", + "Number of CPU threads to use for prealloc"); + object_class_property_add(oc, "size", "int", + host_memory_backend_get_size, + host_memory_backend_set_size, +- NULL, NULL, &error_abort); ++ NULL, NULL); + object_class_property_set_description(oc, "size", + "Size of the memory region (ex: 500M)"); + object_class_property_add(oc, "host-nodes", "int", + host_memory_backend_get_host_nodes, + host_memory_backend_set_host_nodes, +- NULL, NULL, &error_abort); ++ NULL, NULL); + object_class_property_set_description(oc, "host-nodes", + "Binds memory to the list of NUMA host nodes"); + object_class_property_add_enum(oc, "policy", "HostMemPolicy", + &HostMemPolicy_lookup, + host_memory_backend_get_policy, +- host_memory_backend_set_policy, &error_abort); ++ host_memory_backend_set_policy); + object_class_property_set_description(oc, "policy", + "Set the NUMA policy"); + object_class_property_add_bool(oc, "share", +- host_memory_backend_get_share, host_memory_backend_set_share, +- &error_abort); ++ host_memory_backend_get_share, host_memory_backend_set_share); + object_class_property_set_description(oc, "share", + "Mark the memory as private to QEMU or shared"); + object_class_property_add_bool(oc, "x-use-canonical-path-for-ramblock-id", + host_memory_backend_get_use_canonical_path, +- host_memory_backend_set_use_canonical_path, &error_abort); ++ host_memory_backend_set_use_canonical_path); + } + + static const TypeInfo host_memory_backend_info = { +diff --git a/backends/rng-egd.c b/backends/rng-egd.c +index e380519408..7aaa6ee239 100644 +--- a/backends/rng-egd.c ++++ b/backends/rng-egd.c +@@ -138,8 +138,7 @@ static char *rng_egd_get_chardev(Object *obj, Error **errp) + static void rng_egd_init(Object *obj) + { + object_property_add_str(obj, "chardev", +- rng_egd_get_chardev, rng_egd_set_chardev, +- NULL); ++ rng_egd_get_chardev, rng_egd_set_chardev); + } + + static void rng_egd_finalize(Object *obj) +diff --git a/backends/rng-random.c b/backends/rng-random.c +index a810581393..32998d8ee7 100644 +--- a/backends/rng-random.c ++++ b/backends/rng-random.c +@@ -110,8 +110,7 @@ static void rng_random_init(Object *obj) + + object_property_add_str(obj, "filename", + rng_random_get_filename, +- rng_random_set_filename, +- NULL); ++ rng_random_set_filename); + + s->filename = g_strdup("/dev/urandom"); + s->fd = -1; +diff --git a/backends/rng.c b/backends/rng.c +index 391888b8b3..597f0ec268 100644 +--- a/backends/rng.c ++++ b/backends/rng.c +@@ -108,8 +108,7 @@ static void rng_backend_init(Object *obj) + + object_property_add_bool(obj, "opened", + rng_backend_prop_get_opened, +- rng_backend_prop_set_opened, +- NULL); ++ rng_backend_prop_set_opened); + } + + static void rng_backend_finalize(Object *obj) +diff --git a/backends/vhost-user.c b/backends/vhost-user.c +index 2bf3406525..9e6e198546 100644 +--- a/backends/vhost-user.c ++++ b/backends/vhost-user.c +@@ -177,7 +177,7 @@ static char *get_chardev(Object *obj, Error **errp) + + static void vhost_user_backend_init(Object *obj) + { +- object_property_add_str(obj, "chardev", get_chardev, set_chardev, NULL); ++ object_property_add_str(obj, "chardev", get_chardev, set_chardev); + } + + static void vhost_user_backend_finalize(Object *obj) +diff --git a/block/throttle-groups.c b/block/throttle-groups.c +index 37695b0cd7..784fa4a16c 100644 +--- a/block/throttle-groups.c ++++ b/block/throttle-groups.c +@@ -954,8 +954,7 @@ static void throttle_group_obj_class_init(ObjectClass *klass, void *class_data) + "int", + throttle_group_get, + throttle_group_set, +- NULL, &properties[i], +- &error_abort); ++ NULL, &properties[i]); + } + + /* ThrottleLimits */ +@@ -963,8 +962,7 @@ static void throttle_group_obj_class_init(ObjectClass *klass, void *class_data) + "limits", "ThrottleLimits", + throttle_group_get_limits, + throttle_group_set_limits, +- NULL, NULL, +- &error_abort); ++ NULL, NULL); + } + + static const TypeInfo throttle_group_info = { +diff --git a/bootdevice.c b/bootdevice.c +index 03aaffcc8d..d11576d575 100644 +--- a/bootdevice.c ++++ b/bootdevice.c +@@ -329,7 +329,6 @@ void device_add_bootindex_property(Object *obj, int32_t *bootindex, + const char *name, const char *suffix, + DeviceState *dev, Error **errp) + { +- Error *local_err = NULL; + BootIndexProperty *prop = g_malloc0(sizeof(*prop)); + + prop->bootindex = bootindex; +@@ -340,13 +339,8 @@ void device_add_bootindex_property(Object *obj, int32_t *bootindex, + device_get_bootindex, + device_set_bootindex, + property_release_bootindex, +- prop, &local_err); ++ prop); + +- if (local_err) { +- error_propagate(errp, local_err); +- g_free(prop); +- return; +- } + /* initialize devices' bootindex property to -1 */ + object_property_set_int(obj, -1, name, NULL); + } +diff --git a/chardev/char-socket.c b/chardev/char-socket.c +index 185fe38dda..232e0a8604 100644 +--- a/chardev/char-socket.c ++++ b/chardev/char-socket.c +@@ -1489,10 +1489,10 @@ static void char_socket_class_init(ObjectClass *oc, void *data) + + object_class_property_add(oc, "addr", "SocketAddress", + char_socket_get_addr, NULL, +- NULL, NULL, &error_abort); ++ NULL, NULL); + + object_class_property_add_bool(oc, "connected", char_socket_get_connected, +- NULL, &error_abort); ++ NULL); + } + + static const TypeInfo char_socket_type_info = { +diff --git a/chardev/char.c b/chardev/char.c +index e77564060d..0196e2887b 100644 +--- a/chardev/char.c ++++ b/chardev/char.c +@@ -986,10 +986,7 @@ static Chardev *chardev_new(const char *id, const char *typename, + } + + if (id) { +- object_property_add_child(get_chardevs_root(), id, obj, &local_err); +- if (local_err) { +- goto end; +- } ++ object_property_add_child(get_chardevs_root(), id, obj); + object_unref(obj); + } + +@@ -1116,7 +1113,7 @@ ChardevReturn *qmp_chardev_change(const char *id, ChardevBackend *backend, + + object_unparent(OBJECT(chr)); + object_property_add_child(get_chardevs_root(), chr_new->label, +- OBJECT(chr_new), &error_abort); ++ OBJECT(chr_new)); + object_unref(OBJECT(chr_new)); + + ret = g_new0(ChardevReturn, 1); +diff --git a/crypto/secret.c b/crypto/secret.c +index a846a3c87c..3107aecb47 100644 +--- a/crypto/secret.c ++++ b/crypto/secret.c +@@ -369,30 +369,24 @@ qcrypto_secret_class_init(ObjectClass *oc, void *data) + + object_class_property_add_bool(oc, "loaded", + qcrypto_secret_prop_get_loaded, +- qcrypto_secret_prop_set_loaded, +- NULL); ++ qcrypto_secret_prop_set_loaded); + object_class_property_add_enum(oc, "format", + "QCryptoSecretFormat", + &QCryptoSecretFormat_lookup, + qcrypto_secret_prop_get_format, +- qcrypto_secret_prop_set_format, +- NULL); ++ qcrypto_secret_prop_set_format); + object_class_property_add_str(oc, "data", + qcrypto_secret_prop_get_data, +- qcrypto_secret_prop_set_data, +- NULL); ++ qcrypto_secret_prop_set_data); + object_class_property_add_str(oc, "file", + qcrypto_secret_prop_get_file, +- qcrypto_secret_prop_set_file, +- NULL); ++ qcrypto_secret_prop_set_file); + object_class_property_add_str(oc, "keyid", + qcrypto_secret_prop_get_keyid, +- qcrypto_secret_prop_set_keyid, +- NULL); ++ qcrypto_secret_prop_set_keyid); + object_class_property_add_str(oc, "iv", + qcrypto_secret_prop_get_iv, +- qcrypto_secret_prop_set_iv, +- NULL); ++ qcrypto_secret_prop_set_iv); + } + + +diff --git a/crypto/tlscreds.c b/crypto/tlscreds.c +index 4e657b850c..b68735f06f 100644 +--- a/crypto/tlscreds.c ++++ b/crypto/tlscreds.c +@@ -226,22 +226,18 @@ qcrypto_tls_creds_class_init(ObjectClass *oc, void *data) + { + object_class_property_add_bool(oc, "verify-peer", + qcrypto_tls_creds_prop_get_verify, +- qcrypto_tls_creds_prop_set_verify, +- NULL); ++ qcrypto_tls_creds_prop_set_verify); + object_class_property_add_str(oc, "dir", + qcrypto_tls_creds_prop_get_dir, +- qcrypto_tls_creds_prop_set_dir, +- NULL); ++ qcrypto_tls_creds_prop_set_dir); + object_class_property_add_enum(oc, "endpoint", + "QCryptoTLSCredsEndpoint", + &QCryptoTLSCredsEndpoint_lookup, + qcrypto_tls_creds_prop_get_endpoint, +- qcrypto_tls_creds_prop_set_endpoint, +- NULL); ++ qcrypto_tls_creds_prop_set_endpoint); + object_class_property_add_str(oc, "priority", + qcrypto_tls_creds_prop_get_priority, +- qcrypto_tls_creds_prop_set_priority, +- NULL); ++ qcrypto_tls_creds_prop_set_priority); + } + + +diff --git a/crypto/tlscredsanon.c b/crypto/tlscredsanon.c +index a235f60146..fc078d5b97 100644 +--- a/crypto/tlscredsanon.c ++++ b/crypto/tlscredsanon.c +@@ -187,8 +187,7 @@ qcrypto_tls_creds_anon_class_init(ObjectClass *oc, void *data) + + object_class_property_add_bool(oc, "loaded", + qcrypto_tls_creds_anon_prop_get_loaded, +- qcrypto_tls_creds_anon_prop_set_loaded, +- NULL); ++ qcrypto_tls_creds_anon_prop_set_loaded); + } + + +diff --git a/crypto/tlscredspsk.c b/crypto/tlscredspsk.c +index 15d12e2448..f01b64d8bc 100644 +--- a/crypto/tlscredspsk.c ++++ b/crypto/tlscredspsk.c +@@ -275,12 +275,10 @@ qcrypto_tls_creds_psk_class_init(ObjectClass *oc, void *data) + + object_class_property_add_bool(oc, "loaded", + qcrypto_tls_creds_psk_prop_get_loaded, +- qcrypto_tls_creds_psk_prop_set_loaded, +- NULL); ++ qcrypto_tls_creds_psk_prop_set_loaded); + object_class_property_add_str(oc, "username", + qcrypto_tls_creds_psk_prop_get_username, +- qcrypto_tls_creds_psk_prop_set_username, +- NULL); ++ qcrypto_tls_creds_psk_prop_set_username); + } + + +diff --git a/crypto/tlscredsx509.c b/crypto/tlscredsx509.c +index 53a4368f49..e337d68c4f 100644 +--- a/crypto/tlscredsx509.c ++++ b/crypto/tlscredsx509.c +@@ -806,16 +806,13 @@ qcrypto_tls_creds_x509_class_init(ObjectClass *oc, void *data) + + object_class_property_add_bool(oc, "loaded", + qcrypto_tls_creds_x509_prop_get_loaded, +- qcrypto_tls_creds_x509_prop_set_loaded, +- NULL); ++ qcrypto_tls_creds_x509_prop_set_loaded); + object_class_property_add_bool(oc, "sanity-check", + qcrypto_tls_creds_x509_prop_get_sanity, +- qcrypto_tls_creds_x509_prop_set_sanity, +- NULL); ++ qcrypto_tls_creds_x509_prop_set_sanity); + object_class_property_add_str(oc, "passwordid", + qcrypto_tls_creds_x509_prop_get_passwordid, +- qcrypto_tls_creds_x509_prop_set_passwordid, +- NULL); ++ qcrypto_tls_creds_x509_prop_set_passwordid); + } + + +diff --git a/hw/acpi/ich9.c b/hw/acpi/ich9.c +index 336cacea41..9e4c03bef8 100644 +--- a/hw/acpi/ich9.c ++++ b/hw/acpi/ich9.c +@@ -379,32 +379,27 @@ void ich9_pm_add_properties(Object *obj, ICH9LPCPMRegs *pm, Error **errp) + pm->s4_val = 2; + + object_property_add_uint32_ptr(obj, ACPI_PM_PROP_PM_IO_BASE, +- &pm->pm_io_base, OBJ_PROP_FLAG_READ, errp); ++ &pm->pm_io_base, OBJ_PROP_FLAG_READ); + object_property_add(obj, ACPI_PM_PROP_GPE0_BLK, "uint32", + ich9_pm_get_gpe0_blk, +- NULL, NULL, pm, NULL); ++ NULL, NULL, pm); + object_property_add_uint32_ptr(obj, ACPI_PM_PROP_GPE0_BLK_LEN, +- &gpe0_len, OBJ_PROP_FLAG_READ, errp); ++ &gpe0_len, OBJ_PROP_FLAG_READ); + object_property_add_bool(obj, "memory-hotplug-support", + ich9_pm_get_memory_hotplug_support, +- ich9_pm_set_memory_hotplug_support, +- NULL); ++ ich9_pm_set_memory_hotplug_support); + object_property_add_bool(obj, "cpu-hotplug-legacy", + ich9_pm_get_cpu_hotplug_legacy, +- ich9_pm_set_cpu_hotplug_legacy, +- NULL); ++ ich9_pm_set_cpu_hotplug_legacy); + object_property_add_uint8_ptr(obj, ACPI_PM_PROP_S3_DISABLED, +- &pm->disable_s3, OBJ_PROP_FLAG_READWRITE, +- NULL); ++ &pm->disable_s3, OBJ_PROP_FLAG_READWRITE); + object_property_add_uint8_ptr(obj, ACPI_PM_PROP_S4_DISABLED, +- &pm->disable_s4, OBJ_PROP_FLAG_READWRITE, +- NULL); ++ &pm->disable_s4, OBJ_PROP_FLAG_READWRITE); + object_property_add_uint8_ptr(obj, ACPI_PM_PROP_S4_VAL, +- &pm->s4_val, OBJ_PROP_FLAG_READWRITE, NULL); ++ &pm->s4_val, OBJ_PROP_FLAG_READWRITE); + object_property_add_bool(obj, ACPI_PM_PROP_TCO_ENABLED, + ich9_pm_get_enable_tco, +- ich9_pm_set_enable_tco, +- NULL); ++ ich9_pm_set_enable_tco); + } + + void ich9_pm_device_pre_plug_cb(HotplugHandler *hotplug_dev, DeviceState *dev, +diff --git a/hw/acpi/pcihp.c b/hw/acpi/pcihp.c +index 0dc963e983..fbc86af102 100644 +--- a/hw/acpi/pcihp.c ++++ b/hw/acpi/pcihp.c +@@ -80,8 +80,7 @@ static void *acpi_set_bsel(PCIBus *bus, void *opaque) + + *bus_bsel = (*bsel_alloc)++; + object_property_add_uint32_ptr(OBJECT(bus), ACPI_PCIHP_PROP_BSEL, +- bus_bsel, OBJ_PROP_FLAG_READ, +- &error_abort); ++ bus_bsel, OBJ_PROP_FLAG_READ); + } + + return bsel_alloc; +@@ -374,9 +373,9 @@ void acpi_pcihp_init(Object *owner, AcpiPciHpState *s, PCIBus *root_bus, + memory_region_add_subregion(address_space_io, s->io_base, &s->io); + + object_property_add_uint16_ptr(owner, ACPI_PCIHP_IO_BASE_PROP, &s->io_base, +- OBJ_PROP_FLAG_READ, &error_abort); ++ OBJ_PROP_FLAG_READ); + object_property_add_uint16_ptr(owner, ACPI_PCIHP_IO_LEN_PROP, &s->io_len, +- OBJ_PROP_FLAG_READ, &error_abort); ++ OBJ_PROP_FLAG_READ); + } + + const VMStateDescription vmstate_acpi_pcihp_pci_status = { +diff --git a/hw/acpi/piix4.c b/hw/acpi/piix4.c +index 964d6f5990..85c199b30d 100644 +--- a/hw/acpi/piix4.c ++++ b/hw/acpi/piix4.c +@@ -444,17 +444,17 @@ static void piix4_pm_add_propeties(PIIX4PMState *s) + static const uint16_t sci_int = 9; + + object_property_add_uint8_ptr(OBJECT(s), ACPI_PM_PROP_ACPI_ENABLE_CMD, +- &acpi_enable_cmd, OBJ_PROP_FLAG_READ, NULL); ++ &acpi_enable_cmd, OBJ_PROP_FLAG_READ); + object_property_add_uint8_ptr(OBJECT(s), ACPI_PM_PROP_ACPI_DISABLE_CMD, +- &acpi_disable_cmd, OBJ_PROP_FLAG_READ, NULL); ++ &acpi_disable_cmd, OBJ_PROP_FLAG_READ); + object_property_add_uint32_ptr(OBJECT(s), ACPI_PM_PROP_GPE0_BLK, +- &gpe0_blk, OBJ_PROP_FLAG_READ, NULL); ++ &gpe0_blk, OBJ_PROP_FLAG_READ); + object_property_add_uint32_ptr(OBJECT(s), ACPI_PM_PROP_GPE0_BLK_LEN, +- &gpe0_blk_len, OBJ_PROP_FLAG_READ, NULL); ++ &gpe0_blk_len, OBJ_PROP_FLAG_READ); + object_property_add_uint16_ptr(OBJECT(s), ACPI_PM_PROP_SCI_INT, +- &sci_int, OBJ_PROP_FLAG_READ, NULL); ++ &sci_int, OBJ_PROP_FLAG_READ); + object_property_add_uint32_ptr(OBJECT(s), ACPI_PM_PROP_PM_IO_BASE, +- &s->io_base, OBJ_PROP_FLAG_READ, NULL); ++ &s->io_base, OBJ_PROP_FLAG_READ); + } + + static void piix4_pm_realize(PCIDevice *dev, Error **errp) +@@ -598,8 +598,7 @@ static void piix4_acpi_system_hot_add_init(MemoryRegion *parent, + s->cpu_hotplug_legacy = true; + object_property_add_bool(OBJECT(s), "cpu-hotplug-legacy", + piix4_get_cpu_hotplug_legacy, +- piix4_set_cpu_hotplug_legacy, +- NULL); ++ piix4_set_cpu_hotplug_legacy); + legacy_acpi_cpu_hotplug_init(parent, OBJECT(s), &s->gpe_cpu, + PIIX4_CPU_HOTPLUG_IO_BASE); + +diff --git a/hw/arm/allwinner-a10.c b/hw/arm/allwinner-a10.c +index 62a67a3e1a..6e1329a4a2 100644 +--- a/hw/arm/allwinner-a10.c ++++ b/hw/arm/allwinner-a10.c +@@ -178,7 +178,7 @@ static void aw_a10_realize(DeviceState *dev, Error **errp) + sysbus_mmio_map(SYS_BUS_DEVICE(&s->mmc0), 0, AW_A10_MMC0_BASE); + sysbus_connect_irq(SYS_BUS_DEVICE(&s->mmc0), 0, qdev_get_gpio_in(dev, 32)); + object_property_add_alias(OBJECT(s), "sd-bus", OBJECT(&s->mmc0), +- "sd-bus", &error_abort); ++ "sd-bus"); + + /* RTC */ + qdev_init_nofail(DEVICE(&s->rtc)); +diff --git a/hw/arm/allwinner-h3.c b/hw/arm/allwinner-h3.c +index 9e4ce36093..f10674da5a 100644 +--- a/hw/arm/allwinner-h3.c ++++ b/hw/arm/allwinner-h3.c +@@ -205,9 +205,9 @@ static void allwinner_h3_init(Object *obj) + sysbus_init_child_obj(obj, "timer", &s->timer, sizeof(s->timer), + TYPE_AW_A10_PIT); + object_property_add_alias(obj, "clk0-freq", OBJECT(&s->timer), +- "clk0-freq", &error_abort); ++ "clk0-freq"); + object_property_add_alias(obj, "clk1-freq", OBJECT(&s->timer), +- "clk1-freq", &error_abort); ++ "clk1-freq"); + + sysbus_init_child_obj(obj, "ccu", &s->ccu, sizeof(s->ccu), + TYPE_AW_H3_CCU); +@@ -221,7 +221,7 @@ static void allwinner_h3_init(Object *obj) + sysbus_init_child_obj(obj, "sid", &s->sid, sizeof(s->sid), + TYPE_AW_SID); + object_property_add_alias(obj, "identifier", OBJECT(&s->sid), +- "identifier", &error_abort); ++ "identifier"); + + sysbus_init_child_obj(obj, "mmc0", &s->mmc0, sizeof(s->mmc0), + TYPE_AW_SDHOST_SUN5I); +@@ -232,9 +232,9 @@ static void allwinner_h3_init(Object *obj) + sysbus_init_child_obj(obj, "dramc", &s->dramc, sizeof(s->dramc), + TYPE_AW_H3_DRAMC); + object_property_add_alias(obj, "ram-addr", OBJECT(&s->dramc), +- "ram-addr", &error_abort); ++ "ram-addr"); + object_property_add_alias(obj, "ram-size", OBJECT(&s->dramc), +- "ram-size", &error_abort); ++ "ram-size"); + + sysbus_init_child_obj(obj, "rtc", &s->rtc, sizeof(s->rtc), + TYPE_AW_RTC_SUN6I); +@@ -366,7 +366,7 @@ static void allwinner_h3_realize(DeviceState *dev, Error **errp) + qdev_get_gpio_in(DEVICE(&s->gic), AW_H3_GIC_SPI_MMC0)); + + object_property_add_alias(OBJECT(s), "sd-bus", OBJECT(&s->mmc0), +- "sd-bus", &error_abort); ++ "sd-bus"); + + /* EMAC */ + if (nd_table[0].used) { +diff --git a/hw/arm/armv7m.c b/hw/arm/armv7m.c +index 7531b97ccd..7da57f56d3 100644 +--- a/hw/arm/armv7m.c ++++ b/hw/arm/armv7m.c +@@ -138,7 +138,7 @@ static void armv7m_instance_init(Object *obj) + + sysbus_init_child_obj(obj, "nvnic", &s->nvic, sizeof(s->nvic), TYPE_NVIC); + object_property_add_alias(obj, "num-irq", +- OBJECT(&s->nvic), "num-irq", &error_abort); ++ OBJECT(&s->nvic), "num-irq"); + + for (i = 0; i < ARRAY_SIZE(s->bitband); i++) { + sysbus_init_child_obj(obj, "bitband[*]", &s->bitband[i], +diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c +index 231527c6c8..2c23297edf 100644 +--- a/hw/arm/aspeed.c ++++ b/hw/arm/aspeed.c +@@ -544,7 +544,7 @@ static void aspeed_machine_class_props_init(ObjectClass *oc) + { + object_class_property_add_bool(oc, "execute-in-place", + aspeed_get_mmio_exec, +- aspeed_set_mmio_exec, &error_abort); ++ aspeed_set_mmio_exec); + object_class_property_set_description(oc, "execute-in-place", + "boot directly from CE0 flash device"); + } +diff --git a/hw/arm/aspeed_ast2600.c b/hw/arm/aspeed_ast2600.c +index c6e0ab84ac..71a0acfe26 100644 +--- a/hw/arm/aspeed_ast2600.c ++++ b/hw/arm/aspeed_ast2600.c +@@ -138,11 +138,11 @@ static void aspeed_soc_ast2600_init(Object *obj) + qdev_prop_set_uint32(DEVICE(&s->scu), "silicon-rev", + sc->silicon_rev); + object_property_add_alias(obj, "hw-strap1", OBJECT(&s->scu), +- "hw-strap1", &error_abort); ++ "hw-strap1"); + object_property_add_alias(obj, "hw-strap2", OBJECT(&s->scu), +- "hw-strap2", &error_abort); ++ "hw-strap2"); + object_property_add_alias(obj, "hw-prot-key", OBJECT(&s->scu), +- "hw-prot-key", &error_abort); ++ "hw-prot-key"); + + sysbus_init_child_obj(obj, "a7mpcore", &s->a7mpcore, + sizeof(s->a7mpcore), TYPE_A15MPCORE_PRIV); +@@ -161,8 +161,7 @@ static void aspeed_soc_ast2600_init(Object *obj) + snprintf(typename, sizeof(typename), "aspeed.fmc-%s", socname); + sysbus_init_child_obj(obj, "fmc", OBJECT(&s->fmc), sizeof(s->fmc), + typename); +- object_property_add_alias(obj, "num-cs", OBJECT(&s->fmc), "num-cs", +- &error_abort); ++ object_property_add_alias(obj, "num-cs", OBJECT(&s->fmc), "num-cs"); + + for (i = 0; i < sc->spis_num; i++) { + snprintf(typename, sizeof(typename), "aspeed.spi%d-%s", i + 1, socname); +@@ -179,9 +178,9 @@ static void aspeed_soc_ast2600_init(Object *obj) + sysbus_init_child_obj(obj, "sdmc", OBJECT(&s->sdmc), sizeof(s->sdmc), + typename); + object_property_add_alias(obj, "ram-size", OBJECT(&s->sdmc), +- "ram-size", &error_abort); ++ "ram-size"); + object_property_add_alias(obj, "max-ram-size", OBJECT(&s->sdmc), +- "max-ram-size", &error_abort); ++ "max-ram-size"); + + for (i = 0; i < sc->wdts_num; i++) { + snprintf(typename, sizeof(typename), "aspeed.wdt-%s", socname); +diff --git a/hw/arm/aspeed_soc.c b/hw/arm/aspeed_soc.c +index 696c7fda14..cf6b6dd116 100644 +--- a/hw/arm/aspeed_soc.c ++++ b/hw/arm/aspeed_soc.c +@@ -153,11 +153,11 @@ static void aspeed_soc_init(Object *obj) + qdev_prop_set_uint32(DEVICE(&s->scu), "silicon-rev", + sc->silicon_rev); + object_property_add_alias(obj, "hw-strap1", OBJECT(&s->scu), +- "hw-strap1", &error_abort); ++ "hw-strap1"); + object_property_add_alias(obj, "hw-strap2", OBJECT(&s->scu), +- "hw-strap2", &error_abort); ++ "hw-strap2"); + object_property_add_alias(obj, "hw-prot-key", OBJECT(&s->scu), +- "hw-prot-key", &error_abort); ++ "hw-prot-key"); + + sysbus_init_child_obj(obj, "vic", OBJECT(&s->vic), sizeof(s->vic), + TYPE_ASPEED_VIC); +@@ -176,8 +176,7 @@ static void aspeed_soc_init(Object *obj) + snprintf(typename, sizeof(typename), "aspeed.fmc-%s", socname); + sysbus_init_child_obj(obj, "fmc", OBJECT(&s->fmc), sizeof(s->fmc), + typename); +- object_property_add_alias(obj, "num-cs", OBJECT(&s->fmc), "num-cs", +- &error_abort); ++ object_property_add_alias(obj, "num-cs", OBJECT(&s->fmc), "num-cs"); + + for (i = 0; i < sc->spis_num; i++) { + snprintf(typename, sizeof(typename), "aspeed.spi%d-%s", i + 1, socname); +@@ -194,9 +193,9 @@ static void aspeed_soc_init(Object *obj) + sysbus_init_child_obj(obj, "sdmc", OBJECT(&s->sdmc), sizeof(s->sdmc), + typename); + object_property_add_alias(obj, "ram-size", OBJECT(&s->sdmc), +- "ram-size", &error_abort); ++ "ram-size"); + object_property_add_alias(obj, "max-ram-size", OBJECT(&s->sdmc), +- "max-ram-size", &error_abort); ++ "max-ram-size"); + + for (i = 0; i < sc->wdts_num; i++) { + snprintf(typename, sizeof(typename), "aspeed.wdt-%s", socname); +diff --git a/hw/arm/bcm2835_peripherals.c b/hw/arm/bcm2835_peripherals.c +index 8b399d67ff..f1bcc14f55 100644 +--- a/hw/arm/bcm2835_peripherals.c ++++ b/hw/arm/bcm2835_peripherals.c +@@ -74,26 +74,25 @@ static void bcm2835_peripherals_init(Object *obj) + TYPE_BCM2835_MBOX); + + object_property_add_const_link(OBJECT(&s->mboxes), "mbox-mr", +- OBJECT(&s->mbox_mr), &error_abort); ++ OBJECT(&s->mbox_mr)); + + /* Framebuffer */ + sysbus_init_child_obj(obj, "fb", &s->fb, sizeof(s->fb), TYPE_BCM2835_FB); +- object_property_add_alias(obj, "vcram-size", OBJECT(&s->fb), "vcram-size", +- &error_abort); ++ object_property_add_alias(obj, "vcram-size", OBJECT(&s->fb), "vcram-size"); + + object_property_add_const_link(OBJECT(&s->fb), "dma-mr", +- OBJECT(&s->gpu_bus_mr), &error_abort); ++ OBJECT(&s->gpu_bus_mr)); + + /* Property channel */ + sysbus_init_child_obj(obj, "property", &s->property, sizeof(s->property), + TYPE_BCM2835_PROPERTY); + object_property_add_alias(obj, "board-rev", OBJECT(&s->property), +- "board-rev", &error_abort); ++ "board-rev"); + + object_property_add_const_link(OBJECT(&s->property), "fb", +- OBJECT(&s->fb), &error_abort); ++ OBJECT(&s->fb)); + object_property_add_const_link(OBJECT(&s->property), "dma-mr", +- OBJECT(&s->gpu_bus_mr), &error_abort); ++ OBJECT(&s->gpu_bus_mr)); + + /* Random Number Generator */ + sysbus_init_child_obj(obj, "rng", &s->rng, sizeof(s->rng), +@@ -112,7 +111,7 @@ static void bcm2835_peripherals_init(Object *obj) + TYPE_BCM2835_DMA); + + object_property_add_const_link(OBJECT(&s->dma), "dma-mr", +- OBJECT(&s->gpu_bus_mr), &error_abort); ++ OBJECT(&s->gpu_bus_mr)); + + /* Thermal */ + sysbus_init_child_obj(obj, "thermal", &s->thermal, sizeof(s->thermal), +@@ -123,9 +122,9 @@ static void bcm2835_peripherals_init(Object *obj) + TYPE_BCM2835_GPIO); + + object_property_add_const_link(OBJECT(&s->gpio), "sdbus-sdhci", +- OBJECT(&s->sdhci.sdbus), &error_abort); ++ OBJECT(&s->sdhci.sdbus)); + object_property_add_const_link(OBJECT(&s->gpio), "sdbus-sdhost", +- OBJECT(&s->sdhost.sdbus), &error_abort); ++ OBJECT(&s->sdhost.sdbus)); + } + + static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp) +@@ -359,12 +358,7 @@ static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp) + memory_region_add_subregion(&s->peri_mr, GPIO_OFFSET, + sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->gpio), 0)); + +- object_property_add_alias(OBJECT(s), "sd-bus", OBJECT(&s->gpio), "sd-bus", +- &err); +- if (err) { +- error_propagate(errp, err); +- return; +- } ++ object_property_add_alias(OBJECT(s), "sd-bus", OBJECT(&s->gpio), "sd-bus"); + + create_unimp(s, &s->armtmr, "bcm2835-sp804", ARMCTRL_TIMER0_1_OFFSET, 0x40); + create_unimp(s, &s->cprman, "bcm2835-cprman", CPRMAN_OFFSET, 0x1000); +diff --git a/hw/arm/bcm2836.c b/hw/arm/bcm2836.c +index 43022b83f5..e51b4e0c43 100644 +--- a/hw/arm/bcm2836.c ++++ b/hw/arm/bcm2836.c +@@ -63,9 +63,9 @@ static void bcm2836_init(Object *obj) + sysbus_init_child_obj(obj, "peripherals", &s->peripherals, + sizeof(s->peripherals), TYPE_BCM2835_PERIPHERALS); + object_property_add_alias(obj, "board-rev", OBJECT(&s->peripherals), +- "board-rev", &error_abort); ++ "board-rev"); + object_property_add_alias(obj, "vcram-size", OBJECT(&s->peripherals), +- "vcram-size", &error_abort); ++ "vcram-size"); + } + + static void bcm2836_realize(DeviceState *dev, Error **errp) +@@ -86,11 +86,7 @@ static void bcm2836_realize(DeviceState *dev, Error **errp) + return; + } + +- object_property_add_const_link(OBJECT(&s->peripherals), "ram", obj, &err); +- if (err) { +- error_propagate(errp, err); +- return; +- } ++ object_property_add_const_link(OBJECT(&s->peripherals), "ram", obj); + + object_property_set_bool(OBJECT(&s->peripherals), true, "realized", &err); + if (err) { +@@ -99,11 +95,7 @@ static void bcm2836_realize(DeviceState *dev, Error **errp) + } + + object_property_add_alias(OBJECT(s), "sd-bus", OBJECT(&s->peripherals), +- "sd-bus", &err); +- if (err) { +- error_propagate(errp, err); +- return; +- } ++ "sd-bus"); + + sysbus_mmio_map_overlap(SYS_BUS_DEVICE(&s->peripherals), 0, + info->peri_base, 1); +diff --git a/hw/arm/cubieboard.c b/hw/arm/cubieboard.c +index 0b8ba44976..cd1b6d3e19 100644 +--- a/hw/arm/cubieboard.c ++++ b/hw/arm/cubieboard.c +@@ -59,8 +59,7 @@ static void cubieboard_init(MachineState *machine) + } + + a10 = AW_A10(object_new(TYPE_AW_A10)); +- object_property_add_child(OBJECT(machine), "soc", OBJECT(a10), +- &error_abort); ++ object_property_add_child(OBJECT(machine), "soc", OBJECT(a10)); + object_unref(OBJECT(a10)); + + object_property_set_int(OBJECT(&a10->emac), 1, "phy-addr", &err); +diff --git a/hw/arm/mcimx6ul-evk.c b/hw/arm/mcimx6ul-evk.c +index 23a71ed378..5b5f23a6d4 100644 +--- a/hw/arm/mcimx6ul-evk.c ++++ b/hw/arm/mcimx6ul-evk.c +@@ -39,7 +39,7 @@ static void mcimx6ul_evk_init(MachineState *machine) + }; + + s = FSL_IMX6UL(object_new(TYPE_FSL_IMX6UL)); +- object_property_add_child(OBJECT(machine), "soc", OBJECT(s), &error_fatal); ++ object_property_add_child(OBJECT(machine), "soc", OBJECT(s)); + object_property_set_bool(OBJECT(s), true, "realized", &error_fatal); + + memory_region_add_subregion(get_system_memory(), FSL_IMX6UL_MMDC_ADDR, +diff --git a/hw/arm/mcimx7d-sabre.c b/hw/arm/mcimx7d-sabre.c +index de1e264217..3851cd9e3e 100644 +--- a/hw/arm/mcimx7d-sabre.c ++++ b/hw/arm/mcimx7d-sabre.c +@@ -41,7 +41,7 @@ static void mcimx7d_sabre_init(MachineState *machine) + }; + + s = FSL_IMX7(object_new(TYPE_FSL_IMX7)); +- object_property_add_child(OBJECT(machine), "soc", OBJECT(s), &error_fatal); ++ object_property_add_child(OBJECT(machine), "soc", OBJECT(s)); + object_property_set_bool(OBJECT(s), true, "realized", &error_fatal); + + memory_region_add_subregion(get_system_memory(), FSL_IMX7_MMDC_ADDR, +diff --git a/hw/arm/msf2-soc.c b/hw/arm/msf2-soc.c +index a455b8831f..f4579e5a08 100644 +--- a/hw/arm/msf2-soc.c ++++ b/hw/arm/msf2-soc.c +@@ -197,8 +197,7 @@ static void m2sxxx_soc_realize(DeviceState *dev_soc, Error **errp) + /* Alias controller SPI bus to the SoC itself */ + bus_name = g_strdup_printf("spi%d", i); + object_property_add_alias(OBJECT(s), bus_name, +- OBJECT(&s->spi[i]), "spi", +- &error_abort); ++ OBJECT(&s->spi[i]), "spi"); + g_free(bus_name); + } + +diff --git a/hw/arm/nrf51_soc.c b/hw/arm/nrf51_soc.c +index 71309e53cc..fe126581e4 100644 +--- a/hw/arm/nrf51_soc.c ++++ b/hw/arm/nrf51_soc.c +@@ -197,8 +197,7 @@ static void nrf51_soc_init(Object *obj) + + sysbus_init_child_obj(obj, "uart", &s->uart, sizeof(s->uart), + TYPE_NRF51_UART); +- object_property_add_alias(obj, "serial0", OBJECT(&s->uart), "chardev", +- &error_abort); ++ object_property_add_alias(obj, "serial0", OBJECT(&s->uart), "chardev"); + + sysbus_init_child_obj(obj, "rng", &s->rng, sizeof(s->rng), + TYPE_NRF51_RNG); +diff --git a/hw/arm/orangepi.c b/hw/arm/orangepi.c +index a9f64c5680..b291715f27 100644 +--- a/hw/arm/orangepi.c ++++ b/hw/arm/orangepi.c +@@ -59,8 +59,7 @@ static void orangepi_init(MachineState *machine) + } + + h3 = AW_H3(object_new(TYPE_AW_H3)); +- object_property_add_child(OBJECT(machine), "soc", OBJECT(h3), +- &error_abort); ++ object_property_add_child(OBJECT(machine), "soc", OBJECT(h3)); + object_unref(OBJECT(h3)); + + /* Setup timer properties */ +diff --git a/hw/arm/raspi.c b/hw/arm/raspi.c +index fe3b9bc78b..a2efe0b94d 100644 +--- a/hw/arm/raspi.c ++++ b/hw/arm/raspi.c +@@ -284,8 +284,7 @@ static void raspi_machine_init(MachineState *machine) + /* Setup the SOC */ + object_initialize_child(OBJECT(machine), "soc", &s->soc, sizeof(s->soc), + board_soc_type(board_rev), &error_abort, NULL); +- object_property_add_const_link(OBJECT(&s->soc), "ram", OBJECT(machine->ram), +- &error_abort); ++ object_property_add_const_link(OBJECT(&s->soc), "ram", OBJECT(machine->ram)); + object_property_set_int(OBJECT(&s->soc), board_rev, "board-rev", + &error_abort); + object_property_set_bool(OBJECT(&s->soc), true, "realized", &error_abort); +diff --git a/hw/arm/sabrelite.c b/hw/arm/sabrelite.c +index e31694bb92..6f0e233d77 100644 +--- a/hw/arm/sabrelite.c ++++ b/hw/arm/sabrelite.c +@@ -51,7 +51,7 @@ static void sabrelite_init(MachineState *machine) + } + + s = FSL_IMX6(object_new(TYPE_FSL_IMX6)); +- object_property_add_child(OBJECT(machine), "soc", OBJECT(s), &error_fatal); ++ object_property_add_child(OBJECT(machine), "soc", OBJECT(s)); + object_property_set_bool(OBJECT(s), true, "realized", &err); + if (err != NULL) { + error_report("%s", error_get_pretty(err)); +diff --git a/hw/arm/sbsa-ref.c b/hw/arm/sbsa-ref.c +index 8409ba853d..a6cdb4fb7b 100644 +--- a/hw/arm/sbsa-ref.c ++++ b/hw/arm/sbsa-ref.c +@@ -222,10 +222,9 @@ static PFlashCFI01 *sbsa_flash_create1(SBSAMachineState *sms, + qdev_prop_set_uint16(dev, "id2", 0x00); + qdev_prop_set_uint16(dev, "id3", 0x00); + qdev_prop_set_string(dev, "name", name); +- object_property_add_child(OBJECT(sms), name, OBJECT(dev), +- &error_abort); ++ object_property_add_child(OBJECT(sms), name, OBJECT(dev)); + object_property_add_alias(OBJECT(sms), alias_prop_name, +- OBJECT(dev), "drive", &error_abort); ++ OBJECT(dev), "drive"); + return PFLASH_CFI01(dev); + } + +diff --git a/hw/arm/vexpress.c b/hw/arm/vexpress.c +index 5372ab6c9b..69ee4988f9 100644 +--- a/hw/arm/vexpress.c ++++ b/hw/arm/vexpress.c +@@ -749,7 +749,7 @@ static void vexpress_instance_init(Object *obj) + /* EL3 is enabled by default on vexpress */ + vms->secure = true; + object_property_add_bool(obj, "secure", vexpress_get_secure, +- vexpress_set_secure, NULL); ++ vexpress_set_secure); + object_property_set_description(obj, "secure", + "Set on/off to enable/disable the ARM " + "Security Extensions (TrustZone)"); +@@ -765,7 +765,7 @@ static void vexpress_a15_instance_init(Object *obj) + */ + vms->virt = true; + object_property_add_bool(obj, "virtualization", vexpress_get_virt, +- vexpress_set_virt, NULL); ++ vexpress_set_virt); + object_property_set_description(obj, "virtualization", + "Set on/off to enable/disable the ARM " + "Virtualization Extensions " +diff --git a/hw/arm/virt.c b/hw/arm/virt.c +index de66def51e..c41d5f9778 100644 +--- a/hw/arm/virt.c ++++ b/hw/arm/virt.c +@@ -959,10 +959,9 @@ static PFlashCFI01 *virt_flash_create1(VirtMachineState *vms, + qdev_prop_set_uint16(dev, "id2", 0x00); + qdev_prop_set_uint16(dev, "id3", 0x00); + qdev_prop_set_string(dev, "name", name); +- object_property_add_child(OBJECT(vms), name, OBJECT(dev), +- &error_abort); ++ object_property_add_child(OBJECT(vms), name, OBJECT(dev)); + object_property_add_alias(OBJECT(vms), alias_prop_name, +- OBJECT(dev), "drive", &error_abort); ++ OBJECT(dev), "drive"); + return PFLASH_CFI01(dev); + } + +@@ -2270,7 +2269,7 @@ static void virt_machine_class_init(ObjectClass *oc, void *data) + + object_class_property_add(oc, "acpi", "OnOffAuto", + virt_get_acpi, virt_set_acpi, +- NULL, NULL, &error_abort); ++ NULL, NULL); + object_class_property_set_description(oc, "acpi", + "Enable ACPI"); + } +@@ -2286,7 +2285,7 @@ static void virt_instance_init(Object *obj) + */ + vms->secure = false; + object_property_add_bool(obj, "secure", virt_get_secure, +- virt_set_secure, NULL); ++ virt_set_secure); + object_property_set_description(obj, "secure", + "Set on/off to enable/disable the ARM " + "Security Extensions (TrustZone)"); +@@ -2294,7 +2293,7 @@ static void virt_instance_init(Object *obj) + /* EL2 is also disabled by default, for similar reasons */ + vms->virt = false; + object_property_add_bool(obj, "virtualization", virt_get_virt, +- virt_set_virt, NULL); ++ virt_set_virt); + object_property_set_description(obj, "virtualization", + "Set on/off to enable/disable emulating a " + "guest CPU which implements the ARM " +@@ -2303,13 +2302,13 @@ static void virt_instance_init(Object *obj) + /* High memory is enabled by default */ + vms->highmem = true; + object_property_add_bool(obj, "highmem", virt_get_highmem, +- virt_set_highmem, NULL); ++ virt_set_highmem); + object_property_set_description(obj, "highmem", + "Set on/off to enable/disable using " + "physical address space above 32 bits"); + vms->gic_version = VIRT_GIC_VERSION_NOSEL; + object_property_add_str(obj, "gic-version", virt_get_gic_version, +- virt_set_gic_version, NULL); ++ virt_set_gic_version); + object_property_set_description(obj, "gic-version", + "Set GIC version. " + "Valid values are 2, 3, host and max"); +@@ -2322,7 +2321,7 @@ static void virt_instance_init(Object *obj) + /* Default allows ITS instantiation */ + vms->its = true; + object_property_add_bool(obj, "its", virt_get_its, +- virt_set_its, NULL); ++ virt_set_its); + object_property_set_description(obj, "its", + "Set on/off to enable/disable " + "ITS instantiation"); +@@ -2330,7 +2329,7 @@ static void virt_instance_init(Object *obj) + + /* Default disallows iommu instantiation */ + vms->iommu = VIRT_IOMMU_NONE; +- object_property_add_str(obj, "iommu", virt_get_iommu, virt_set_iommu, NULL); ++ object_property_add_str(obj, "iommu", virt_get_iommu, virt_set_iommu); + object_property_set_description(obj, "iommu", + "Set the IOMMU type. " + "Valid values are none and smmuv3"); +@@ -2338,7 +2337,7 @@ static void virt_instance_init(Object *obj) + /* Default disallows RAS instantiation */ + vms->ras = false; + object_property_add_bool(obj, "ras", virt_get_ras, +- virt_set_ras, NULL); ++ virt_set_ras); + object_property_set_description(obj, "ras", + "Set on/off to enable/disable reporting host memory errors " + "to a KVM guest using ACPI and guest external abort exceptions"); +diff --git a/hw/arm/xilinx_zynq.c b/hw/arm/xilinx_zynq.c +index 91b498dd5d..cb933efb49 100644 +--- a/hw/arm/xilinx_zynq.c ++++ b/hw/arm/xilinx_zynq.c +@@ -229,7 +229,7 @@ static void zynq_init(MachineState *machine) + /* Create the main clock source, and feed slcr with it */ + zynq_machine->ps_clk = CLOCK(object_new(TYPE_CLOCK)); + object_property_add_child(OBJECT(zynq_machine), "ps_clk", +- OBJECT(zynq_machine->ps_clk), &error_abort); ++ OBJECT(zynq_machine->ps_clk)); + object_unref(OBJECT(zynq_machine->ps_clk)); + clock_set_hz(zynq_machine->ps_clk, PS_CLK_FREQUENCY); + qdev_connect_clock_in(slcr, "ps_clk", zynq_machine->ps_clk); +diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c +index 7e749e1926..43a71e2eea 100644 +--- a/hw/arm/xlnx-versal-virt.c ++++ b/hw/arm/xlnx-versal-virt.c +@@ -433,8 +433,7 @@ static void create_virtio_regions(VersalVirt *s) + + pic_irq = qdev_get_gpio_in(DEVICE(&s->soc.fpd.apu.gic), irq); + dev = qdev_create(NULL, "virtio-mmio"); +- object_property_add_child(OBJECT(&s->soc), name, OBJECT(dev), +- &error_fatal); ++ object_property_add_child(OBJECT(&s->soc), name, OBJECT(dev)); + qdev_init_nofail(dev); + sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic_irq); + mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0); +@@ -465,8 +464,7 @@ static void sd_plugin_card(SDHCIState *sd, DriveInfo *di) + DeviceState *card; + + card = qdev_create(qdev_get_child_bus(DEVICE(sd), "sd-bus"), TYPE_SD_CARD); +- object_property_add_child(OBJECT(sd), "card[*]", OBJECT(card), +- &error_fatal); ++ object_property_add_child(OBJECT(sd), "card[*]", OBJECT(card)); + qdev_prop_set_drive(card, "drive", blk, &error_fatal); + object_property_set_bool(OBJECT(card), true, "realized", &error_fatal); + } +diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c +index 321171bcce..809a31390f 100644 +--- a/hw/arm/xlnx-versal.c ++++ b/hw/arm/xlnx-versal.c +@@ -309,7 +309,7 @@ static void versal_unimp_area(Versal *s, const char *name, + + qdev_prop_set_string(dev, "name", name); + qdev_prop_set_uint64(dev, "size", size); +- object_property_add_child(OBJECT(s), name, OBJECT(dev), &error_fatal); ++ object_property_add_child(OBJECT(s), name, OBJECT(dev)); + qdev_init_nofail(dev); + + mr_dev = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0); +diff --git a/hw/arm/xlnx-zcu102.c b/hw/arm/xlnx-zcu102.c +index 808fdae804..b01e575b58 100644 +--- a/hw/arm/xlnx-zcu102.c ++++ b/hw/arm/xlnx-zcu102.c +@@ -209,7 +209,7 @@ static void xlnx_zcu102_machine_instance_init(Object *obj) + /* Default to secure mode being disabled */ + s->secure = false; + object_property_add_bool(obj, "secure", zcu102_get_secure, +- zcu102_set_secure, NULL); ++ zcu102_set_secure); + object_property_set_description(obj, "secure", + "Set on/off to enable/disable the ARM " + "Security Extensions (TrustZone)"); +@@ -217,7 +217,7 @@ static void xlnx_zcu102_machine_instance_init(Object *obj) + /* Default to virt (EL2) being disabled */ + s->virt = false; + object_property_add_bool(obj, "virtualization", zcu102_get_virt, +- zcu102_set_virt, NULL); ++ zcu102_set_virt); + object_property_set_description(obj, "virtualization", + "Set on/off to enable/disable emulating a " + "guest CPU which implements the ARM " +diff --git a/hw/arm/xlnx-zynqmp.c b/hw/arm/xlnx-zynqmp.c +index b84d153d56..f08abf60d7 100644 +--- a/hw/arm/xlnx-zynqmp.c ++++ b/hw/arm/xlnx-zynqmp.c +@@ -554,8 +554,7 @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp) + + /* Alias controller SD bus to the SoC itself */ + bus_name = g_strdup_printf("sd-bus%d", i); +- object_property_add_alias(OBJECT(s), bus_name, sdhci, "sd-bus", +- &error_abort); ++ object_property_add_alias(OBJECT(s), bus_name, sdhci, "sd-bus"); + g_free(bus_name); + } + +@@ -575,8 +574,7 @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp) + /* Alias controller SPI bus to the SoC itself */ + bus_name = g_strdup_printf("spi%d", i); + object_property_add_alias(OBJECT(s), bus_name, +- OBJECT(&s->spi[i]), "spi0", +- &error_abort); ++ OBJECT(&s->spi[i]), "spi0"); + g_free(bus_name); + } + +@@ -597,8 +595,7 @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp) + bus_name = g_strdup_printf("qspi%d", i); + target_bus = g_strdup_printf("spi%d", i); + object_property_add_alias(OBJECT(s), bus_name, +- OBJECT(&s->qspi), target_bus, +- &error_abort); ++ OBJECT(&s->qspi), target_bus); + g_free(bus_name); + g_free(target_bus); + } +diff --git a/hw/audio/marvell_88w8618.c b/hw/audio/marvell_88w8618.c +index 883ef74c8b..8dfacec693 100644 +--- a/hw/audio/marvell_88w8618.c ++++ b/hw/audio/marvell_88w8618.c +@@ -259,7 +259,7 @@ static void mv88w8618_audio_init(Object *obj) + object_property_add_link(OBJECT(dev), "wm8750", TYPE_WM8750, + (Object **) &s->wm, + qdev_prop_allow_set_link_before_realize, +- 0, &error_abort); ++ 0); + } + + static void mv88w8618_audio_realize(DeviceState *dev, Error **errp) +diff --git a/hw/audio/pcspk.c b/hw/audio/pcspk.c +index 29dc00bf8d..c37a387861 100644 +--- a/hw/audio/pcspk.c ++++ b/hw/audio/pcspk.c +@@ -175,7 +175,7 @@ static void pcspk_initfn(Object *obj) + object_property_add_link(obj, "pit", TYPE_PIT_COMMON, + (Object **)&s->pit, + qdev_prop_allow_set_link_before_realize, +- 0, &error_abort); ++ 0); + } + + static void pcspk_realizefn(DeviceState *dev, Error **errp) +diff --git a/hw/core/bus.c b/hw/core/bus.c +index 3dc0a825f0..4a57ae107e 100644 +--- a/hw/core/bus.c ++++ b/hw/core/bus.c +@@ -122,7 +122,7 @@ static void qbus_realize(BusState *bus, DeviceState *parent, const char *name) + if (bus->parent) { + QLIST_INSERT_HEAD(&bus->parent->child_bus, bus, sibling); + bus->parent->num_child_bus++; +- object_property_add_child(OBJECT(bus->parent), bus->name, OBJECT(bus), NULL); ++ object_property_add_child(OBJECT(bus->parent), bus->name, OBJECT(bus)); + object_unref(OBJECT(bus)); + } else { + /* The only bus without a parent is the main system bus */ +@@ -215,10 +215,9 @@ static void qbus_initfn(Object *obj) + TYPE_HOTPLUG_HANDLER, + (Object **)&bus->hotplug_handler, + object_property_allow_set_link, +- 0, +- NULL); ++ 0); + object_property_add_bool(obj, "realized", +- bus_get_realized, bus_set_realized, NULL); ++ bus_get_realized, bus_set_realized); + } + + static char *default_bus_get_fw_dev_path(DeviceState *dev) +diff --git a/hw/core/machine.c b/hw/core/machine.c +index 0cd2033b1f..bb3a7b18b1 100644 +--- a/hw/core/machine.c ++++ b/hw/core/machine.c +@@ -787,82 +787,78 @@ static void machine_class_init(ObjectClass *oc, void *data) + mc->numa_auto_assign_ram = numa_default_auto_assign_ram; + + object_class_property_add_str(oc, "kernel", +- machine_get_kernel, machine_set_kernel, &error_abort); ++ machine_get_kernel, machine_set_kernel); + object_class_property_set_description(oc, "kernel", + "Linux kernel image file"); + + object_class_property_add_str(oc, "initrd", +- machine_get_initrd, machine_set_initrd, &error_abort); ++ machine_get_initrd, machine_set_initrd); + object_class_property_set_description(oc, "initrd", + "Linux initial ramdisk file"); + + object_class_property_add_str(oc, "append", +- machine_get_append, machine_set_append, &error_abort); ++ machine_get_append, machine_set_append); + object_class_property_set_description(oc, "append", + "Linux kernel command line"); + + object_class_property_add_str(oc, "dtb", +- machine_get_dtb, machine_set_dtb, &error_abort); ++ machine_get_dtb, machine_set_dtb); + object_class_property_set_description(oc, "dtb", + "Linux kernel device tree file"); + + object_class_property_add_str(oc, "dumpdtb", +- machine_get_dumpdtb, machine_set_dumpdtb, &error_abort); ++ machine_get_dumpdtb, machine_set_dumpdtb); + object_class_property_set_description(oc, "dumpdtb", + "Dump current dtb to a file and quit"); + + object_class_property_add(oc, "phandle-start", "int", + machine_get_phandle_start, machine_set_phandle_start, +- NULL, NULL, &error_abort); ++ NULL, NULL); + object_class_property_set_description(oc, "phandle-start", + "The first phandle ID we may generate dynamically"); + + object_class_property_add_str(oc, "dt-compatible", +- machine_get_dt_compatible, machine_set_dt_compatible, &error_abort); ++ machine_get_dt_compatible, machine_set_dt_compatible); + object_class_property_set_description(oc, "dt-compatible", + "Overrides the \"compatible\" property of the dt root node"); + + object_class_property_add_bool(oc, "dump-guest-core", +- machine_get_dump_guest_core, machine_set_dump_guest_core, &error_abort); ++ machine_get_dump_guest_core, machine_set_dump_guest_core); + object_class_property_set_description(oc, "dump-guest-core", + "Include guest memory in a core dump"); + + object_class_property_add_bool(oc, "mem-merge", +- machine_get_mem_merge, machine_set_mem_merge, &error_abort); ++ machine_get_mem_merge, machine_set_mem_merge); + object_class_property_set_description(oc, "mem-merge", + "Enable/disable memory merge support"); + + object_class_property_add_bool(oc, "usb", +- machine_get_usb, machine_set_usb, &error_abort); ++ machine_get_usb, machine_set_usb); + object_class_property_set_description(oc, "usb", + "Set on/off to enable/disable usb"); + + object_class_property_add_bool(oc, "graphics", +- machine_get_graphics, machine_set_graphics, &error_abort); ++ machine_get_graphics, machine_set_graphics); + object_class_property_set_description(oc, "graphics", + "Set on/off to enable/disable graphics emulation"); + + object_class_property_add_str(oc, "firmware", +- machine_get_firmware, machine_set_firmware, +- &error_abort); ++ machine_get_firmware, machine_set_firmware); + object_class_property_set_description(oc, "firmware", + "Firmware image"); + + object_class_property_add_bool(oc, "suppress-vmdesc", +- machine_get_suppress_vmdesc, machine_set_suppress_vmdesc, +- &error_abort); ++ machine_get_suppress_vmdesc, machine_set_suppress_vmdesc); + object_class_property_set_description(oc, "suppress-vmdesc", + "Set on to disable self-describing migration"); + + object_class_property_add_bool(oc, "enforce-config-section", +- machine_get_enforce_config_section, machine_set_enforce_config_section, +- &error_abort); ++ machine_get_enforce_config_section, machine_set_enforce_config_section); + object_class_property_set_description(oc, "enforce-config-section", + "Set on to enforce configuration section migration"); + + object_class_property_add_str(oc, "memory-encryption", +- machine_get_memory_encryption, machine_set_memory_encryption, +- &error_abort); ++ machine_get_memory_encryption, machine_set_memory_encryption); + object_class_property_set_description(oc, "memory-encryption", + "Set memory encryption object to use"); + } +@@ -893,16 +889,14 @@ static void machine_initfn(Object *obj) + + ms->nvdimms_state = g_new0(NVDIMMState, 1); + object_property_add_bool(obj, "nvdimm", +- machine_get_nvdimm, machine_set_nvdimm, +- &error_abort); ++ machine_get_nvdimm, machine_set_nvdimm); + object_property_set_description(obj, "nvdimm", + "Set on/off to enable/disable " + "NVDIMM instantiation"); + + object_property_add_str(obj, "nvdimm-persistence", + machine_get_nvdimm_persistence, +- machine_set_nvdimm_persistence, +- &error_abort); ++ machine_set_nvdimm_persistence); + object_property_set_description(obj, "nvdimm-persistence", + "Set NVDIMM persistence" + "Valid values are cpu, mem-ctrl"); +@@ -911,8 +905,7 @@ static void machine_initfn(Object *obj) + if (mc->cpu_index_to_instance_props && mc->get_default_cpu_node_id) { + ms->numa_state = g_new0(NumaState, 1); + object_property_add_bool(obj, "hmat", +- machine_get_hmat, machine_set_hmat, +- &error_abort); ++ machine_get_hmat, machine_set_hmat); + object_property_set_description(obj, "hmat", + "Set on/off to enable/disable " + "ACPI Heterogeneous Memory Attribute " +@@ -920,8 +913,7 @@ static void machine_initfn(Object *obj) + } + + object_property_add_str(obj, "memory-backend", +- machine_get_memdev, machine_set_memdev, +- &error_abort); ++ machine_get_memdev, machine_set_memdev); + object_property_set_description(obj, "memory-backend", + "Set RAM backend" + "Valid value is ID of hostmem based backend"); +diff --git a/hw/core/qdev-clock.c b/hw/core/qdev-clock.c +index a94cc44437..5cc1e82e51 100644 +--- a/hw/core/qdev-clock.c ++++ b/hw/core/qdev-clock.c +@@ -46,7 +46,7 @@ static NamedClockList *qdev_init_clocklist(DeviceState *dev, const char *name, + */ + if (clk == NULL) { + clk = CLOCK(object_new(TYPE_CLOCK)); +- object_property_add_child(OBJECT(dev), name, OBJECT(clk), &error_abort); ++ object_property_add_child(OBJECT(dev), name, OBJECT(clk)); + if (output) { + /* + * Remove object_new()'s initial reference. +@@ -59,7 +59,7 @@ static NamedClockList *qdev_init_clocklist(DeviceState *dev, const char *name, + object_property_add_link(OBJECT(dev), name, + object_get_typename(OBJECT(clk)), + (Object **) &ncl->clock, +- NULL, OBJ_PROP_LINK_STRONG, &error_abort); ++ NULL, OBJ_PROP_LINK_STRONG); + } + + ncl->clock = clk; +diff --git a/hw/core/qdev-properties.c b/hw/core/qdev-properties.c +index 2047114fca..2f294ec4a4 100644 +--- a/hw/core/qdev-properties.c ++++ b/hw/core/qdev-properties.c +@@ -1043,11 +1043,7 @@ static void set_prop_arraylen(Object *obj, Visitor *v, const char *name, + arrayprop->prop.info->get, + arrayprop->prop.info->set, + array_element_release, +- arrayprop, &local_err); +- if (local_err) { +- error_propagate(errp, local_err); +- return; +- } ++ arrayprop); + } + } + +@@ -1259,8 +1255,7 @@ static void create_link_property(ObjectClass *oc, Property *prop, Error **errp) + object_class_property_add_link(oc, prop->name, prop->link_type, + prop->offset, + qdev_prop_allow_set_link_before_realize, +- OBJ_PROP_LINK_STRONG, +- errp); ++ OBJ_PROP_LINK_STRONG); + } + + const PropertyInfo qdev_prop_link = { +diff --git a/hw/core/qdev.c b/hw/core/qdev.c +index 2e6c29ba78..3f91bff712 100644 +--- a/hw/core/qdev.c ++++ b/hw/core/qdev.c +@@ -91,8 +91,7 @@ static void bus_add_child(BusState *bus, DeviceState *child) + object_get_typename(OBJECT(child)), + (Object **)&kid->child, + NULL, /* read-only property */ +- 0, /* return ownership on prop deletion */ +- NULL); ++ 0); + } + + void qdev_set_parent_bus(DeviceState *dev, BusState *bus) +@@ -481,7 +480,7 @@ void qdev_init_gpio_in_named_with_opaque(DeviceState *dev, + gchar *propname = g_strdup_printf("%s[%u]", name, i); + + object_property_add_child(OBJECT(dev), propname, +- OBJECT(gpio_list->in[i]), &error_abort); ++ OBJECT(gpio_list->in[i])); + g_free(propname); + } + +@@ -512,8 +511,7 @@ void qdev_init_gpio_out_named(DeviceState *dev, qemu_irq *pins, + object_property_add_link(OBJECT(dev), propname, TYPE_IRQ, + (Object **)&pins[i], + object_property_allow_set_link, +- OBJ_PROP_LINK_STRONG, +- &error_abort); ++ OBJ_PROP_LINK_STRONG); + g_free(propname); + } + gpio_list->num_out += n; +@@ -546,8 +544,7 @@ void qdev_connect_gpio_out_named(DeviceState *dev, const char *name, int n, + /* We need a name for object_property_set_link to work */ + object_property_add_child(container_get(qdev_get_machine(), + "/unattached"), +- "non-qdev-gpio[*]", OBJECT(pin), +- &error_abort); ++ "non-qdev-gpio[*]", OBJECT(pin)); + } + object_property_set_link(OBJECT(dev), OBJECT(pin), propname, &error_abort); + g_free(propname); +@@ -605,8 +602,7 @@ void qdev_pass_gpios(DeviceState *dev, DeviceState *container, + char *propname = g_strdup_printf("%s[%d]", nm, i); + + object_property_add_alias(OBJECT(container), propname, +- OBJECT(dev), propname, +- &error_abort); ++ OBJECT(dev), propname); + g_free(propname); + } + for (i = 0; i < ngl->num_out; i++) { +@@ -614,8 +610,7 @@ void qdev_pass_gpios(DeviceState *dev, DeviceState *container, + char *propname = g_strdup_printf("%s[%d]", nm, i); + + object_property_add_alias(OBJECT(container), propname, +- OBJECT(dev), propname, +- &error_abort); ++ OBJECT(dev), propname); + g_free(propname); + } + QLIST_REMOVE(ngl, node); +@@ -756,7 +751,7 @@ static void qdev_class_add_legacy_property(DeviceClass *dc, Property *prop) + name = g_strdup_printf("legacy-%s", prop->name); + object_class_property_add(OBJECT_CLASS(dc), name, "str", + prop->info->print ? qdev_get_legacy_property : prop->info->get, +- NULL, NULL, prop, &error_abort); ++ NULL, NULL, prop); + } + + void qdev_property_add_static(DeviceState *dev, Property *prop) +@@ -769,7 +764,7 @@ void qdev_property_add_static(DeviceState *dev, Property *prop) + op = object_property_add(obj, prop->name, prop->info->name, + prop->info->get, prop->info->set, + prop->info->release, +- prop, &error_abort); ++ prop); + + object_property_set_description(obj, prop->name, + prop->info->description); +@@ -795,7 +790,7 @@ static void qdev_class_add_property(DeviceClass *klass, Property *prop) + prop->name, prop->info->name, + prop->info->get, prop->info->set, + prop->info->release, +- prop, &error_abort); ++ prop); + if (prop->set_default) { + prop->info->set_default_value(op, prop); + } +@@ -818,8 +813,7 @@ void qdev_alias_all_properties(DeviceState *target, Object *source) + + for (prop = dc->props_; prop && prop->name; prop++) { + object_property_add_alias(source, prop->name, +- OBJECT(target), prop->name, +- &error_abort); ++ OBJECT(target), prop->name); + } + class = object_class_get_parent(class); + } while (class != object_class_by_name(TYPE_DEVICE)); +@@ -871,7 +865,7 @@ static void device_set_realized(Object *obj, bool value, Error **errp) + + object_property_add_child(container_get(qdev_get_machine(), + "/unattached"), +- name, obj, &error_abort); ++ name, obj); + unattached_parent = true; + g_free(name); + } +@@ -1198,17 +1192,13 @@ static void device_class_init(ObjectClass *class, void *data) + rc->get_transitional_function = device_get_transitional_reset; + + object_class_property_add_bool(class, "realized", +- device_get_realized, device_set_realized, +- &error_abort); ++ device_get_realized, device_set_realized); + object_class_property_add_bool(class, "hotpluggable", +- device_get_hotpluggable, NULL, +- &error_abort); ++ device_get_hotpluggable, NULL); + object_class_property_add_bool(class, "hotplugged", +- device_get_hotplugged, NULL, +- &error_abort); ++ device_get_hotplugged, NULL); + object_class_property_add_link(class, "parent_bus", TYPE_BUS, +- offsetof(DeviceState, parent_bus), NULL, 0, +- &error_abort); ++ offsetof(DeviceState, parent_bus), NULL, 0); + } + + void device_class_set_props(DeviceClass *dc, Property *props) +diff --git a/hw/cpu/core.c b/hw/cpu/core.c +index 9874c5c870..a92ac597ca 100644 +--- a/hw/cpu/core.c ++++ b/hw/cpu/core.c +@@ -76,9 +76,9 @@ static void cpu_core_instance_init(Object *obj) + CPUCore *core = CPU_CORE(obj); + + object_property_add(obj, "core-id", "int", core_prop_get_core_id, +- core_prop_set_core_id, NULL, NULL, NULL); ++ core_prop_set_core_id, NULL, NULL); + object_property_add(obj, "nr-threads", "int", core_prop_get_nr_threads, +- core_prop_set_nr_threads, NULL, NULL, NULL); ++ core_prop_set_nr_threads, NULL, NULL); + core->nr_threads = ms->smp.threads; + } + +diff --git a/hw/display/bochs-display.c b/hw/display/bochs-display.c +index e763a0a72d..a8e8ab8325 100644 +--- a/hw/display/bochs-display.c ++++ b/hw/display/bochs-display.c +@@ -333,8 +333,7 @@ static void bochs_display_init(Object *obj) + /* Expose framebuffer byteorder via QOM */ + object_property_add_bool(obj, "big-endian-framebuffer", + bochs_display_get_big_endian_fb, +- bochs_display_set_big_endian_fb, +- NULL); ++ bochs_display_set_big_endian_fb); + + dev->cap_present |= QEMU_PCI_CAP_EXPRESS; + } +diff --git a/hw/display/sm501.c b/hw/display/sm501.c +index de0ab9d977..296cd56c4a 100644 +--- a/hw/display/sm501.c ++++ b/hw/display/sm501.c +@@ -2011,7 +2011,7 @@ static void sm501_sysbus_init(Object *o) + qdev_prop_set_uint8(DEVICE(smm), "endianness", DEVICE_LITTLE_ENDIAN); + + object_property_add_alias(o, "chardev", +- OBJECT(smm), "chardev", &error_abort); ++ OBJECT(smm), "chardev"); + } + + static const TypeInfo sm501_sysbus_info = { +diff --git a/hw/display/vga-pci.c b/hw/display/vga-pci.c +index 6b9db86e36..a640fd866d 100644 +--- a/hw/display/vga-pci.c ++++ b/hw/display/vga-pci.c +@@ -270,7 +270,7 @@ static void pci_std_vga_init(Object *obj) + { + /* Expose framebuffer byteorder via QOM */ + object_property_add_bool(obj, "big-endian-framebuffer", +- vga_get_big_endian_fb, vga_set_big_endian_fb, NULL); ++ vga_get_big_endian_fb, vga_set_big_endian_fb); + } + + static void pci_secondary_vga_realize(PCIDevice *dev, Error **errp) +@@ -321,7 +321,7 @@ static void pci_secondary_vga_init(Object *obj) + { + /* Expose framebuffer byteorder via QOM */ + object_property_add_bool(obj, "big-endian-framebuffer", +- vga_get_big_endian_fb, vga_set_big_endian_fb, NULL); ++ vga_get_big_endian_fb, vga_set_big_endian_fb); + } + + static void pci_secondary_vga_reset(DeviceState *dev) +diff --git a/hw/display/vhost-user-gpu-pci.c b/hw/display/vhost-user-gpu-pci.c +index 7d9b1f5a8c..23ce655e0f 100644 +--- a/hw/display/vhost-user-gpu-pci.c ++++ b/hw/display/vhost-user-gpu-pci.c +@@ -32,8 +32,7 @@ static void vhost_user_gpu_pci_initfn(Object *obj) + VIRTIO_GPU_PCI_BASE(obj)->vgpu = VIRTIO_GPU_BASE(&dev->vdev); + + object_property_add_alias(obj, "chardev", +- OBJECT(&dev->vdev), "chardev", +- &error_abort); ++ OBJECT(&dev->vdev), "chardev"); + } + + static const VirtioPCIDeviceTypeInfo vhost_user_gpu_pci_info = { +diff --git a/hw/display/vhost-user-gpu.c b/hw/display/vhost-user-gpu.c +index f0c7c6fb9a..4cdaee1bde 100644 +--- a/hw/display/vhost-user-gpu.c ++++ b/hw/display/vhost-user-gpu.c +@@ -512,7 +512,7 @@ vhost_user_gpu_instance_init(Object *obj) + + g->vhost = VHOST_USER_BACKEND(object_new(TYPE_VHOST_USER_BACKEND)); + object_property_add_alias(obj, "chardev", +- OBJECT(g->vhost), "chardev", &error_abort); ++ OBJECT(g->vhost), "chardev"); + } + + static void +diff --git a/hw/display/vhost-user-vga.c b/hw/display/vhost-user-vga.c +index a7195276d9..1690f6b610 100644 +--- a/hw/display/vhost-user-vga.c ++++ b/hw/display/vhost-user-vga.c +@@ -33,8 +33,7 @@ static void vhost_user_vga_inst_initfn(Object *obj) + VIRTIO_VGA_BASE(dev)->vgpu = VIRTIO_GPU_BASE(&dev->vdev); + + object_property_add_alias(obj, "chardev", +- OBJECT(&dev->vdev), "chardev", +- &error_abort); ++ OBJECT(&dev->vdev), "chardev"); + } + + static const VirtioPCIDeviceTypeInfo vhost_user_vga_info = { +diff --git a/hw/display/xlnx_dp.c b/hw/display/xlnx_dp.c +index 7058443797..3e5fb44e06 100644 +--- a/hw/display/xlnx_dp.c ++++ b/hw/display/xlnx_dp.c +@@ -1237,8 +1237,7 @@ static void xlnx_dp_init(Object *obj) + object_property_add_link(obj, "dpdma", TYPE_XLNX_DPDMA, + (Object **) &s->dpdma, + xlnx_dp_set_dpdma, +- OBJ_PROP_LINK_STRONG, +- &error_abort); ++ OBJ_PROP_LINK_STRONG); + + /* + * Initialize AUX Bus. +@@ -1249,11 +1248,11 @@ static void xlnx_dp_init(Object *obj) + * Initialize DPCD and EDID.. + */ + s->dpcd = DPCD(aux_create_slave(s->aux_bus, "dpcd")); +- object_property_add_child(OBJECT(s), "dpcd", OBJECT(s->dpcd), NULL); ++ object_property_add_child(OBJECT(s), "dpcd", OBJECT(s->dpcd)); + + s->edid = I2CDDC(qdev_create(BUS(aux_get_i2c_bus(s->aux_bus)), "i2c-ddc")); + i2c_set_slave_address(I2C_SLAVE(s->edid), 0x50); +- object_property_add_child(OBJECT(s), "edid", OBJECT(s->edid), NULL); ++ object_property_add_child(OBJECT(s), "edid", OBJECT(s->edid)); + + fifo8_create(&s->rx_fifo, 16); + fifo8_create(&s->tx_fifo, 16); +diff --git a/hw/dma/sparc32_dma.c b/hw/dma/sparc32_dma.c +index 3e4da0c47f..84b9c5dc77 100644 +--- a/hw/dma/sparc32_dma.c ++++ b/hw/dma/sparc32_dma.c +@@ -264,7 +264,7 @@ static void sparc32_dma_device_init(Object *obj) + object_property_add_link(OBJECT(dev), "iommu", TYPE_SUN4M_IOMMU, + (Object **) &s->iommu, + qdev_prop_allow_set_link_before_realize, +- 0, NULL); ++ 0); + + qdev_init_gpio_in(dev, dma_set_irq, 1); + qdev_init_gpio_out(dev, s->gpio, 2); +@@ -302,7 +302,7 @@ static void sparc32_espdma_device_realize(DeviceState *dev, Error **errp) + ESPState *esp; + + d = qdev_create(NULL, TYPE_ESP); +- object_property_add_child(OBJECT(dev), "esp", OBJECT(d), errp); ++ object_property_add_child(OBJECT(dev), "esp", OBJECT(d)); + sysbus = ESP_STATE(d); + esp = &sysbus->esp; + esp->dma_memory_read = espdma_memory_read; +@@ -344,7 +344,7 @@ static void sparc32_ledma_device_realize(DeviceState *dev, Error **errp) + qemu_check_nic_model(nd, TYPE_LANCE); + + d = qdev_create(NULL, TYPE_LANCE); +- object_property_add_child(OBJECT(dev), "lance", OBJECT(d), errp); ++ object_property_add_child(OBJECT(dev), "lance", OBJECT(d)); + qdev_set_nic_properties(d, nd); + object_property_set_link(OBJECT(d), OBJECT(dev), "dma", errp); + qdev_init_nofail(d); +@@ -380,7 +380,7 @@ static void sparc32_dma_realize(DeviceState *dev, Error **errp) + + espdma = qdev_create(NULL, TYPE_SPARC32_ESPDMA_DEVICE); + object_property_set_link(OBJECT(espdma), iommu, "iommu", errp); +- object_property_add_child(OBJECT(s), "espdma", OBJECT(espdma), errp); ++ object_property_add_child(OBJECT(s), "espdma", OBJECT(espdma)); + qdev_init_nofail(espdma); + + esp = DEVICE(object_resolve_path_component(OBJECT(espdma), "esp")); +@@ -395,7 +395,7 @@ static void sparc32_dma_realize(DeviceState *dev, Error **errp) + + ledma = qdev_create(NULL, TYPE_SPARC32_LEDMA_DEVICE); + object_property_set_link(OBJECT(ledma), iommu, "iommu", errp); +- object_property_add_child(OBJECT(s), "ledma", OBJECT(ledma), errp); ++ object_property_add_child(OBJECT(s), "ledma", OBJECT(ledma)); + qdev_init_nofail(ledma); + + lance = DEVICE(object_resolve_path_component(OBJECT(ledma), "lance")); +diff --git a/hw/dma/xilinx_axidma.c b/hw/dma/xilinx_axidma.c +index 87be9cade7..460102b142 100644 +--- a/hw/dma/xilinx_axidma.c ++++ b/hw/dma/xilinx_axidma.c +@@ -543,16 +543,11 @@ static void xilinx_axidma_realize(DeviceState *dev, Error **errp) + object_property_add_link(OBJECT(ds), "dma", TYPE_XILINX_AXI_DMA, + (Object **)&ds->dma, + object_property_allow_set_link, +- OBJ_PROP_LINK_STRONG, +- &local_err); ++ OBJ_PROP_LINK_STRONG); + object_property_add_link(OBJECT(cs), "dma", TYPE_XILINX_AXI_DMA, + (Object **)&cs->dma, + object_property_allow_set_link, +- OBJ_PROP_LINK_STRONG, +- &local_err); +- if (local_err) { +- goto xilinx_axidma_realize_fail; +- } ++ OBJ_PROP_LINK_STRONG); + object_property_set_link(OBJECT(ds), OBJECT(s), "dma", &local_err); + object_property_set_link(OBJECT(cs), OBJECT(s), "dma", &local_err); + if (local_err) { +@@ -594,8 +589,7 @@ static void xilinx_axidma_init(Object *obj) + object_property_add_link(obj, "dma", TYPE_MEMORY_REGION, + (Object **)&s->dma_mr, + qdev_prop_allow_set_link_before_realize, +- OBJ_PROP_LINK_STRONG, +- &error_abort); ++ OBJ_PROP_LINK_STRONG); + + sysbus_init_irq(sbd, &s->streams[0].irq); + sysbus_init_irq(sbd, &s->streams[1].irq); +diff --git a/hw/dma/xlnx-zdma.c b/hw/dma/xlnx-zdma.c +index 2dec4a2643..fa38a55634 100644 +--- a/hw/dma/xlnx-zdma.c ++++ b/hw/dma/xlnx-zdma.c +@@ -799,8 +799,7 @@ static void zdma_init(Object *obj) + object_property_add_link(obj, "dma", TYPE_MEMORY_REGION, + (Object **)&s->dma_mr, + qdev_prop_allow_set_link_before_realize, +- OBJ_PROP_LINK_STRONG, +- &error_abort); ++ OBJ_PROP_LINK_STRONG); + } + + static const VMStateDescription vmstate_zdma = { +diff --git a/hw/gpio/aspeed_gpio.c b/hw/gpio/aspeed_gpio.c +index 4c75b5c80c..dfa9db3d33 100644 +--- a/hw/gpio/aspeed_gpio.c ++++ b/hw/gpio/aspeed_gpio.c +@@ -873,7 +873,7 @@ static void aspeed_gpio_init(Object *obj) + name = g_strdup_printf("gpio%s%d", props->group_label[group_idx], + pin_idx % GPIOS_PER_GROUP); + object_property_add(obj, name, "bool", aspeed_gpio_get_pin, +- aspeed_gpio_set_pin, NULL, NULL, NULL); ++ aspeed_gpio_set_pin, NULL, NULL); + g_free(name); + } + } +diff --git a/hw/hyperv/hyperv.c b/hw/hyperv/hyperv.c +index 4ddafe1de1..4b11f7a76b 100644 +--- a/hw/hyperv/hyperv.c ++++ b/hw/hyperv/hyperv.c +@@ -131,7 +131,7 @@ void hyperv_synic_add(CPUState *cs) + obj = object_new(TYPE_SYNIC); + synic = SYNIC(obj); + synic->cs = cs; +- object_property_add_child(OBJECT(cs), "synic", obj, &error_abort); ++ object_property_add_child(OBJECT(cs), "synic", obj); + object_unref(obj); + object_property_set_bool(obj, true, "realized", &error_abort); + } +diff --git a/hw/i386/microvm.c b/hw/i386/microvm.c +index 76aaa7a8d8..937db10ae6 100644 +--- a/hw/i386/microvm.c ++++ b/hw/i386/microvm.c +@@ -510,42 +510,39 @@ static void microvm_class_init(ObjectClass *oc, void *data) + object_class_property_add(oc, MICROVM_MACHINE_PIC, "OnOffAuto", + microvm_machine_get_pic, + microvm_machine_set_pic, +- NULL, NULL, &error_abort); ++ NULL, NULL); + object_class_property_set_description(oc, MICROVM_MACHINE_PIC, + "Enable i8259 PIC"); + + object_class_property_add(oc, MICROVM_MACHINE_PIT, "OnOffAuto", + microvm_machine_get_pit, + microvm_machine_set_pit, +- NULL, NULL, &error_abort); ++ NULL, NULL); + object_class_property_set_description(oc, MICROVM_MACHINE_PIT, + "Enable i8254 PIT"); + + object_class_property_add(oc, MICROVM_MACHINE_RTC, "OnOffAuto", + microvm_machine_get_rtc, + microvm_machine_set_rtc, +- NULL, NULL, &error_abort); ++ NULL, NULL); + object_class_property_set_description(oc, MICROVM_MACHINE_RTC, + "Enable MC146818 RTC"); + + object_class_property_add_bool(oc, MICROVM_MACHINE_ISA_SERIAL, + microvm_machine_get_isa_serial, +- microvm_machine_set_isa_serial, +- &error_abort); ++ microvm_machine_set_isa_serial); + object_class_property_set_description(oc, MICROVM_MACHINE_ISA_SERIAL, + "Set off to disable the instantiation an ISA serial port"); + + object_class_property_add_bool(oc, MICROVM_MACHINE_OPTION_ROMS, + microvm_machine_get_option_roms, +- microvm_machine_set_option_roms, +- &error_abort); ++ microvm_machine_set_option_roms); + object_class_property_set_description(oc, MICROVM_MACHINE_OPTION_ROMS, + "Set off to disable loading option ROMs"); + + object_class_property_add_bool(oc, MICROVM_MACHINE_AUTO_KERNEL_CMDLINE, + microvm_machine_get_auto_kernel_cmdline, +- microvm_machine_set_auto_kernel_cmdline, +- &error_abort); ++ microvm_machine_set_auto_kernel_cmdline); + object_class_property_set_description(oc, + MICROVM_MACHINE_AUTO_KERNEL_CMDLINE, + "Set off to disable adding virtio-mmio devices to the kernel cmdline"); +diff --git a/hw/i386/pc.c b/hw/i386/pc.c +index 21d4a8ec3a..33cf14363a 100644 +--- a/hw/i386/pc.c ++++ b/hw/i386/pc.c +@@ -662,7 +662,7 @@ void pc_cmos_init(PCMachineState *pcms, + TYPE_ISA_DEVICE, + (Object **)&x86ms->rtc, + object_property_allow_set_link, +- OBJ_PROP_LINK_STRONG, &error_abort); ++ OBJ_PROP_LINK_STRONG); + object_property_set_link(OBJECT(pcms), OBJECT(s), + "rtc_state", &error_abort); + +@@ -1965,22 +1965,22 @@ static void pc_machine_class_init(ObjectClass *oc, void *data) + + object_class_property_add(oc, PC_MACHINE_DEVMEM_REGION_SIZE, "int", + pc_machine_get_device_memory_region_size, NULL, +- NULL, NULL, &error_abort); ++ NULL, NULL); + + object_class_property_add(oc, PC_MACHINE_VMPORT, "OnOffAuto", + pc_machine_get_vmport, pc_machine_set_vmport, +- NULL, NULL, &error_abort); ++ NULL, NULL); + object_class_property_set_description(oc, PC_MACHINE_VMPORT, + "Enable vmport (pc & q35)"); + + object_class_property_add_bool(oc, PC_MACHINE_SMBUS, +- pc_machine_get_smbus, pc_machine_set_smbus, &error_abort); ++ pc_machine_get_smbus, pc_machine_set_smbus); + + object_class_property_add_bool(oc, PC_MACHINE_SATA, +- pc_machine_get_sata, pc_machine_set_sata, &error_abort); ++ pc_machine_get_sata, pc_machine_set_sata); + + object_class_property_add_bool(oc, PC_MACHINE_PIT, +- pc_machine_get_pit, pc_machine_set_pit, &error_abort); ++ pc_machine_get_pit, pc_machine_set_pit); + } + + static const TypeInfo pc_machine_info = { +diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c +index 3862e5120e..f66e1d73ce 100644 +--- a/hw/i386/pc_piix.c ++++ b/hw/i386/pc_piix.c +@@ -291,7 +291,7 @@ static void pc_init1(MachineState *machine, + TYPE_HOTPLUG_HANDLER, + (Object **)&pcms->acpi_dev, + object_property_allow_set_link, +- OBJ_PROP_LINK_STRONG, &error_abort); ++ OBJ_PROP_LINK_STRONG); + object_property_set_link(OBJECT(machine), OBJECT(piix4_pm), + PC_MACHINE_ACPI_DEVICE_PROP, &error_abort); + } +diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c +index 3349e38a4c..4ba8ac8774 100644 +--- a/hw/i386/pc_q35.c ++++ b/hw/i386/pc_q35.c +@@ -214,7 +214,7 @@ static void pc_q35_init(MachineState *machine) + /* create pci host bus */ + q35_host = Q35_HOST_DEVICE(qdev_create(NULL, TYPE_Q35_HOST_DEVICE)); + +- object_property_add_child(qdev_get_machine(), "q35", OBJECT(q35_host), NULL); ++ object_property_add_child(qdev_get_machine(), "q35", OBJECT(q35_host)); + object_property_set_link(OBJECT(q35_host), OBJECT(ram_memory), + MCH_HOST_PROP_RAM_MEM, NULL); + object_property_set_link(OBJECT(q35_host), OBJECT(pci_memory), +@@ -240,7 +240,7 @@ static void pc_q35_init(MachineState *machine) + TYPE_HOTPLUG_HANDLER, + (Object **)&pcms->acpi_dev, + object_property_allow_set_link, +- OBJ_PROP_LINK_STRONG, &error_abort); ++ OBJ_PROP_LINK_STRONG); + object_property_set_link(OBJECT(machine), OBJECT(lpc), + PC_MACHINE_ACPI_DEVICE_PROP, &error_abort); + +diff --git a/hw/i386/pc_sysfw.c b/hw/i386/pc_sysfw.c +index f5f3f466b0..002133a2d8 100644 +--- a/hw/i386/pc_sysfw.c ++++ b/hw/i386/pc_sysfw.c +@@ -90,10 +90,9 @@ static PFlashCFI01 *pc_pflash_create(PCMachineState *pcms, + qdev_prop_set_uint64(dev, "sector-length", FLASH_SECTOR_SIZE); + qdev_prop_set_uint8(dev, "width", 1); + qdev_prop_set_string(dev, "name", name); +- object_property_add_child(OBJECT(pcms), name, OBJECT(dev), +- &error_abort); ++ object_property_add_child(OBJECT(pcms), name, OBJECT(dev)); + object_property_add_alias(OBJECT(pcms), alias_prop_name, +- OBJECT(dev), "drive", &error_abort); ++ OBJECT(dev), "drive"); + return PFLASH_CFI01(dev); + } + +diff --git a/hw/i386/x86.c b/hw/i386/x86.c +index e2bf601273..7a3bc7ab66 100644 +--- a/hw/i386/x86.c ++++ b/hw/i386/x86.c +@@ -350,7 +350,7 @@ void ioapic_init_gsi(GSIState *gsi_state, const char *parent_name) + dev = qdev_create(NULL, TYPE_IOAPIC); + } + object_property_add_child(object_resolve_path(parent_name, NULL), +- "ioapic", OBJECT(dev), NULL); ++ "ioapic", OBJECT(dev)); + qdev_init_nofail(dev); + d = SYS_BUS_DEVICE(dev); + sysbus_mmio_map(d, 0, IO_APIC_DEFAULT_ADDRESS); +@@ -982,19 +982,19 @@ static void x86_machine_class_init(ObjectClass *oc, void *data) + + object_class_property_add(oc, X86_MACHINE_MAX_RAM_BELOW_4G, "size", + x86_machine_get_max_ram_below_4g, x86_machine_set_max_ram_below_4g, +- NULL, NULL, &error_abort); ++ NULL, NULL); + object_class_property_set_description(oc, X86_MACHINE_MAX_RAM_BELOW_4G, + "Maximum ram below the 4G boundary (32bit boundary)"); + + object_class_property_add(oc, X86_MACHINE_SMM, "OnOffAuto", + x86_machine_get_smm, x86_machine_set_smm, +- NULL, NULL, &error_abort); ++ NULL, NULL); + object_class_property_set_description(oc, X86_MACHINE_SMM, + "Enable SMM"); + + object_class_property_add(oc, X86_MACHINE_ACPI, "OnOffAuto", + x86_machine_get_acpi, x86_machine_set_acpi, +- NULL, NULL, &error_abort); ++ NULL, NULL); + object_class_property_set_description(oc, X86_MACHINE_ACPI, + "Enable ACPI"); + } +diff --git a/hw/ide/macio.c b/hw/ide/macio.c +index a9f25e5d02..30af0e93e6 100644 +--- a/hw/ide/macio.c ++++ b/hw/ide/macio.c +@@ -459,7 +459,7 @@ static void macio_ide_initfn(Object *obj) + + object_property_add_link(obj, "dbdma", TYPE_MAC_DBDMA, + (Object **) &s->dbdma, +- qdev_prop_allow_set_link_before_realize, 0, NULL); ++ qdev_prop_allow_set_link_before_realize, 0); + } + + static Property macio_ide_properties[] = { +diff --git a/hw/ide/qdev.c b/hw/ide/qdev.c +index c22afdb8ee..4909b14b91 100644 +--- a/hw/ide/qdev.c ++++ b/hw/ide/qdev.c +@@ -266,7 +266,7 @@ static void ide_dev_instance_init(Object *obj) + { + object_property_add(obj, "bootindex", "int32", + ide_dev_get_bootindex, +- ide_dev_set_bootindex, NULL, NULL, NULL); ++ ide_dev_set_bootindex, NULL, NULL); + object_property_set_int(obj, -1, "bootindex", NULL); + } + +diff --git a/hw/input/vhost-user-input.c b/hw/input/vhost-user-input.c +index 544452a234..63984a8ba7 100644 +--- a/hw/input/vhost-user-input.c ++++ b/hw/input/vhost-user-input.c +@@ -101,7 +101,7 @@ static void vhost_input_init(Object *obj) + + vhi->vhost = VHOST_USER_BACKEND(object_new(TYPE_VHOST_USER_BACKEND)); + object_property_add_alias(obj, "chardev", +- OBJECT(vhi->vhost), "chardev", &error_abort); ++ OBJECT(vhi->vhost), "chardev"); + } + + static void vhost_input_finalize(Object *obj) +diff --git a/hw/intc/apic_common.c b/hw/intc/apic_common.c +index 9ec0f2deb2..243bb69430 100644 +--- a/hw/intc/apic_common.c ++++ b/hw/intc/apic_common.c +@@ -445,7 +445,7 @@ static void apic_common_initfn(Object *obj) + s->id = s->initial_apic_id = -1; + object_property_add(obj, "id", "uint32", + apic_common_get_id, +- apic_common_set_id, NULL, NULL, NULL); ++ apic_common_set_id, NULL, NULL); + } + + static void apic_common_class_init(ObjectClass *klass, void *data) +diff --git a/hw/intc/s390_flic.c b/hw/intc/s390_flic.c +index 5f290f5410..baca4d8a2d 100644 +--- a/hw/intc/s390_flic.c ++++ b/hw/intc/s390_flic.c +@@ -65,11 +65,11 @@ void s390_flic_init(void) + if (kvm_enabled()) { + dev = qdev_create(NULL, TYPE_KVM_S390_FLIC); + object_property_add_child(qdev_get_machine(), TYPE_KVM_S390_FLIC, +- OBJECT(dev), NULL); ++ OBJECT(dev)); + } else { + dev = qdev_create(NULL, TYPE_QEMU_S390_FLIC); + object_property_add_child(qdev_get_machine(), TYPE_QEMU_S390_FLIC, +- OBJECT(dev), NULL); ++ OBJECT(dev)); + } + qdev_init_nofail(dev); + } +diff --git a/hw/intc/xics.c b/hw/intc/xics.c +index c5d507e707..e56d578841 100644 +--- a/hw/intc/xics.c ++++ b/hw/intc/xics.c +@@ -380,7 +380,7 @@ Object *icp_create(Object *cpu, const char *type, XICSFabric *xi, Error **errp) + Object *obj; + + obj = object_new(type); +- object_property_add_child(cpu, type, obj, &error_abort); ++ object_property_add_child(cpu, type, obj); + object_unref(obj); + object_property_set_link(obj, OBJECT(xi), ICP_PROP_XICS, &error_abort); + object_property_set_link(obj, cpu, ICP_PROP_CPU, &error_abort); +diff --git a/hw/intc/xive.c b/hw/intc/xive.c +index d6183f8ae4..8f2b4050cb 100644 +--- a/hw/intc/xive.c ++++ b/hw/intc/xive.c +@@ -761,7 +761,7 @@ Object *xive_tctx_create(Object *cpu, XivePresenter *xptr, Error **errp) + Object *obj; + + obj = object_new(TYPE_XIVE_TCTX); +- object_property_add_child(cpu, TYPE_XIVE_TCTX, obj, &error_abort); ++ object_property_add_child(cpu, TYPE_XIVE_TCTX, obj); + object_unref(obj); + object_property_set_link(obj, cpu, "cpu", &error_abort); + object_property_set_link(obj, OBJECT(xptr), "presenter", &error_abort); +diff --git a/hw/ipmi/ipmi.c b/hw/ipmi/ipmi.c +index 46c6a79527..8d35c9fdd6 100644 +--- a/hw/ipmi/ipmi.c ++++ b/hw/ipmi/ipmi.c +@@ -105,8 +105,7 @@ void ipmi_bmc_find_and_link(Object *obj, Object **bmc) + { + object_property_add_link(obj, "bmc", TYPE_IPMI_BMC, bmc, + isa_ipmi_bmc_check, +- OBJ_PROP_LINK_STRONG, +- &error_abort); ++ OBJ_PROP_LINK_STRONG); + } + + static Property ipmi_bmc_properties[] = { +diff --git a/hw/isa/isa-superio.c b/hw/isa/isa-superio.c +index 0d9d848280..3dcdc234a4 100644 +--- a/hw/isa/isa-superio.c ++++ b/hw/isa/isa-superio.c +@@ -62,8 +62,7 @@ static void isa_superio_realize(DeviceState *dev, Error **errp) + qdev_prop_set_uint32(d, "irq", k->parallel.get_irq(sio, i)); + } + qdev_prop_set_chr(d, "chardev", chr); +- object_property_add_child(OBJECT(sio), name, OBJECT(isa), +- &error_abort); ++ object_property_add_child(OBJECT(dev), name, OBJECT(isa)); + qdev_init_nofail(d); + sio->parallel[i] = isa; + trace_superio_create_parallel(i, +@@ -102,8 +101,7 @@ static void isa_superio_realize(DeviceState *dev, Error **errp) + qdev_prop_set_uint32(d, "irq", k->serial.get_irq(sio, i)); + } + qdev_prop_set_chr(d, "chardev", chr); +- object_property_add_child(OBJECT(sio), name, OBJECT(isa), +- &error_abort); ++ object_property_add_child(OBJECT(dev), name, OBJECT(isa)); + qdev_init_nofail(d); + sio->serial[i] = isa; + trace_superio_create_serial(i, +@@ -137,8 +135,7 @@ static void isa_superio_realize(DeviceState *dev, Error **errp) + qdev_prop_set_drive(d, "driveB", blk_by_legacy_dinfo(drive), + &error_fatal); + } +- object_property_add_child(OBJECT(sio), "isa-fdc", OBJECT(isa), +- &error_abort); ++ object_property_add_child(OBJECT(sio), "isa-fdc", OBJECT(isa)); + qdev_init_nofail(d); + sio->floppy = isa; + trace_superio_create_floppy(0, +@@ -150,8 +147,7 @@ static void isa_superio_realize(DeviceState *dev, Error **errp) + + /* Keyboard, mouse */ + isa = isa_create(bus, TYPE_I8042); +- object_property_add_child(OBJECT(sio), TYPE_I8042, OBJECT(isa), +- &error_abort); ++ object_property_add_child(OBJECT(sio), TYPE_I8042, OBJECT(isa)); + qdev_init_nofail(DEVICE(isa)); + sio->kbc = isa; + +@@ -169,8 +165,7 @@ static void isa_superio_realize(DeviceState *dev, Error **errp) + qdev_prop_set_uint32(d, "irq", k->ide.get_irq(sio, 0)); + } + qdev_init_nofail(d); +- object_property_add_child(OBJECT(sio), "isa-ide", OBJECT(isa), +- &error_abort); ++ object_property_add_child(OBJECT(sio), "isa-ide", OBJECT(isa)); + sio->ide = isa; + trace_superio_create_ide(0, + k->ide.get_iobase ? +diff --git a/hw/isa/lpc_ich9.c b/hw/isa/lpc_ich9.c +index fbc3165d03..c975d46675 100644 +--- a/hw/isa/lpc_ich9.c ++++ b/hw/isa/lpc_ich9.c +@@ -633,11 +633,11 @@ static void ich9_lpc_initfn(Object *obj) + static const uint8_t acpi_disable_cmd = ICH9_APM_ACPI_DISABLE; + + object_property_add_uint8_ptr(obj, ACPI_PM_PROP_SCI_INT, +- &lpc->sci_gsi, OBJ_PROP_FLAG_READ, NULL); ++ &lpc->sci_gsi, OBJ_PROP_FLAG_READ); + object_property_add_uint8_ptr(OBJECT(lpc), ACPI_PM_PROP_ACPI_ENABLE_CMD, +- &acpi_enable_cmd, OBJ_PROP_FLAG_READ, NULL); ++ &acpi_enable_cmd, OBJ_PROP_FLAG_READ); + object_property_add_uint8_ptr(OBJECT(lpc), ACPI_PM_PROP_ACPI_DISABLE_CMD, +- &acpi_disable_cmd, OBJ_PROP_FLAG_READ, NULL); ++ &acpi_disable_cmd, OBJ_PROP_FLAG_READ); + + ich9_pm_add_properties(obj, &lpc->pm, NULL); + } +diff --git a/hw/mem/nvdimm.c b/hw/mem/nvdimm.c +index 8e426d24bb..c5adedcc69 100644 +--- a/hw/mem/nvdimm.c ++++ b/hw/mem/nvdimm.c +@@ -110,10 +110,10 @@ static void nvdimm_init(Object *obj) + { + object_property_add(obj, NVDIMM_LABEL_SIZE_PROP, "int", + nvdimm_get_label_size, nvdimm_set_label_size, NULL, +- NULL, NULL); ++ NULL); + + object_property_add(obj, NVDIMM_UUID_PROP, "QemuUUID", nvdimm_get_uuid, +- nvdimm_set_uuid, NULL, NULL, NULL); ++ nvdimm_set_uuid, NULL, NULL); + } + + static void nvdimm_finalize(Object *obj) +diff --git a/hw/mem/pc-dimm.c b/hw/mem/pc-dimm.c +index 6d62588fea..b81c82f57b 100644 +--- a/hw/mem/pc-dimm.c ++++ b/hw/mem/pc-dimm.c +@@ -165,7 +165,7 @@ static void pc_dimm_get_size(Object *obj, Visitor *v, const char *name, + static void pc_dimm_init(Object *obj) + { + object_property_add(obj, PC_DIMM_SIZE_PROP, "uint64", pc_dimm_get_size, +- NULL, NULL, NULL, &error_abort); ++ NULL, NULL, NULL); + } + + static void pc_dimm_realize(DeviceState *dev, Error **errp) +diff --git a/hw/microblaze/petalogix_ml605_mmu.c b/hw/microblaze/petalogix_ml605_mmu.c +index 0a2640c40b..536571db7f 100644 +--- a/hw/microblaze/petalogix_ml605_mmu.c ++++ b/hw/microblaze/petalogix_ml605_mmu.c +@@ -138,10 +138,8 @@ petalogix_ml605_init(MachineState *machine) + dma = qdev_create(NULL, "xlnx.axi-dma"); + + /* FIXME: attach to the sysbus instead */ +- object_property_add_child(qdev_get_machine(), "xilinx-eth", OBJECT(eth0), +- NULL); +- object_property_add_child(qdev_get_machine(), "xilinx-dma", OBJECT(dma), +- NULL); ++ object_property_add_child(qdev_get_machine(), "xilinx-eth", OBJECT(eth0)); ++ object_property_add_child(qdev_get_machine(), "xilinx-dma", OBJECT(dma)); + + ds = object_property_get_link(OBJECT(dma), + "axistream-connected-target", NULL); +diff --git a/hw/misc/aspeed_sdmc.c b/hw/misc/aspeed_sdmc.c +index 14db9cfc1f..25e1e58356 100644 +--- a/hw/misc/aspeed_sdmc.c ++++ b/hw/misc/aspeed_sdmc.c +@@ -250,7 +250,7 @@ static void aspeed_sdmc_initfn(Object *obj) + { + object_property_add(obj, "ram-size", "int", + aspeed_sdmc_get_ram_size, aspeed_sdmc_set_ram_size, +- NULL, NULL, NULL); ++ NULL, NULL); + } + + static void aspeed_sdmc_realize(DeviceState *dev, Error **errp) +diff --git a/hw/misc/edu.c b/hw/misc/edu.c +index ff10f5b794..ec617e63f3 100644 +--- a/hw/misc/edu.c ++++ b/hw/misc/edu.c +@@ -402,8 +402,7 @@ static void edu_instance_init(Object *obj) + + edu->dma_mask = (1UL << 28) - 1; + object_property_add_uint64_ptr(obj, "dma_mask", +- &edu->dma_mask, OBJ_PROP_FLAG_READWRITE, +- NULL); ++ &edu->dma_mask, OBJ_PROP_FLAG_READWRITE); + } + + static void edu_class_init(ObjectClass *class, void *data) +diff --git a/hw/misc/mac_via.c b/hw/misc/mac_via.c +index 81343301b1..e05623d730 100644 +--- a/hw/misc/mac_via.c ++++ b/hw/misc/mac_via.c +@@ -885,10 +885,10 @@ static void mac_via_realize(DeviceState *dev, Error **errp) + /* Pass through mos6522 output IRQs */ + ms = MOS6522(&m->mos6522_via1); + object_property_add_alias(OBJECT(dev), "irq[0]", OBJECT(ms), +- SYSBUS_DEVICE_GPIO_IRQ "[0]", &error_abort); ++ SYSBUS_DEVICE_GPIO_IRQ "[0]"); + ms = MOS6522(&m->mos6522_via2); + object_property_add_alias(OBJECT(dev), "irq[1]", OBJECT(ms), +- SYSBUS_DEVICE_GPIO_IRQ "[0]", &error_abort); ++ SYSBUS_DEVICE_GPIO_IRQ "[0]"); + + /* Pass through mos6522 input IRQs */ + qdev_pass_gpios(DEVICE(&m->mos6522_via1), dev, "via1-irq"); +diff --git a/hw/misc/macio/gpio.c b/hw/misc/macio/gpio.c +index 6cca6b27d6..0fef8fb335 100644 +--- a/hw/misc/macio/gpio.c ++++ b/hw/misc/macio/gpio.c +@@ -170,7 +170,7 @@ static void macio_gpio_init(Object *obj) + object_property_add_link(obj, "pic", TYPE_OPENPIC, + (Object **) &s->pic, + qdev_prop_allow_set_link_before_realize, +- 0, NULL); ++ 0); + + memory_region_init_io(&s->gpiomem, OBJECT(s), &macio_gpio_ops, obj, + "gpio", 0x30); +diff --git a/hw/misc/macio/macio.c b/hw/misc/macio/macio.c +index 79222192e8..3779865ab2 100644 +--- a/hw/misc/macio/macio.c ++++ b/hw/misc/macio/macio.c +@@ -241,7 +241,7 @@ static void macio_oldworld_init(Object *obj) + object_property_add_link(obj, "pic", TYPE_HEATHROW, + (Object **) &os->pic, + qdev_prop_allow_set_link_before_realize, +- 0, NULL); ++ 0); + + macio_init_child_obj(s, "cuda", &s->cuda, sizeof(s->cuda), TYPE_CUDA); + +@@ -397,7 +397,7 @@ static void macio_newworld_init(Object *obj) + object_property_add_link(obj, "pic", TYPE_OPENPIC, + (Object **) &ns->pic, + qdev_prop_allow_set_link_before_realize, +- 0, NULL); ++ 0); + + macio_init_child_obj(s, "gpio", &ns->gpio, sizeof(ns->gpio), + TYPE_MACIO_GPIO); +diff --git a/hw/misc/macio/pmu.c b/hw/misc/macio/pmu.c +index b8466a4a3f..5fa792846c 100644 +--- a/hw/misc/macio/pmu.c ++++ b/hw/misc/macio/pmu.c +@@ -773,7 +773,7 @@ static void pmu_init(Object *obj) + object_property_add_link(obj, "gpio", TYPE_MACIO_GPIO, + (Object **) &s->gpio, + qdev_prop_allow_set_link_before_realize, +- 0, NULL); ++ 0); + + sysbus_init_child_obj(obj, "mos6522-pmu", &s->mos6522_pmu, + sizeof(s->mos6522_pmu), TYPE_MOS6522_PMU); +diff --git a/hw/misc/pca9552.c b/hw/misc/pca9552.c +index efd961e041..cac729e35a 100644 +--- a/hw/misc/pca9552.c ++++ b/hw/misc/pca9552.c +@@ -298,7 +298,7 @@ static void pca9552_initfn(Object *obj) + + name = g_strdup_printf("led%d", led); + object_property_add(obj, name, "bool", pca9552_get_led, pca9552_set_led, +- NULL, NULL, NULL); ++ NULL, NULL); + g_free(name); + } + } +diff --git a/hw/misc/tmp105.c b/hw/misc/tmp105.c +index 75ddad3a12..58dbebca90 100644 +--- a/hw/misc/tmp105.c ++++ b/hw/misc/tmp105.c +@@ -245,7 +245,7 @@ static void tmp105_initfn(Object *obj) + { + object_property_add(obj, "temperature", "int", + tmp105_get_temperature, +- tmp105_set_temperature, NULL, NULL, NULL); ++ tmp105_set_temperature, NULL, NULL); + } + + static void tmp105_class_init(ObjectClass *klass, void *data) +diff --git a/hw/misc/tmp421.c b/hw/misc/tmp421.c +index c0bc150bca..74864cd93d 100644 +--- a/hw/misc/tmp421.c ++++ b/hw/misc/tmp421.c +@@ -347,16 +347,16 @@ static void tmp421_initfn(Object *obj) + { + object_property_add(obj, "temperature0", "int", + tmp421_get_temperature, +- tmp421_set_temperature, NULL, NULL, NULL); ++ tmp421_set_temperature, NULL, NULL); + object_property_add(obj, "temperature1", "int", + tmp421_get_temperature, +- tmp421_set_temperature, NULL, NULL, NULL); ++ tmp421_set_temperature, NULL, NULL); + object_property_add(obj, "temperature2", "int", + tmp421_get_temperature, +- tmp421_set_temperature, NULL, NULL, NULL); ++ tmp421_set_temperature, NULL, NULL); + object_property_add(obj, "temperature3", "int", + tmp421_get_temperature, +- tmp421_set_temperature, NULL, NULL, NULL); ++ tmp421_set_temperature, NULL, NULL); + } + + static void tmp421_class_init(ObjectClass *klass, void *data) +diff --git a/hw/net/cadence_gem.c b/hw/net/cadence_gem.c +index 22a0b1b1f9..e8f9cc7f1e 100644 +--- a/hw/net/cadence_gem.c ++++ b/hw/net/cadence_gem.c +@@ -1600,8 +1600,7 @@ static void gem_init(Object *obj) + object_property_add_link(obj, "dma", TYPE_MEMORY_REGION, + (Object **)&s->dma_mr, + qdev_prop_allow_set_link_before_realize, +- OBJ_PROP_LINK_STRONG, +- &error_abort); ++ OBJ_PROP_LINK_STRONG); + } + + static const VMStateDescription vmstate_cadence_gem = { +diff --git a/hw/net/can/can_kvaser_pci.c b/hw/net/can/can_kvaser_pci.c +index 16861b8f9f..4b941370d0 100644 +--- a/hw/net/can/can_kvaser_pci.c ++++ b/hw/net/can/can_kvaser_pci.c +@@ -282,7 +282,7 @@ static void kvaser_pci_instance_init(Object *obj) + object_property_add_link(obj, "canbus", TYPE_CAN_BUS, + (Object **)&d->canbus, + qdev_prop_allow_set_link_before_realize, +- 0, &error_abort); ++ 0); + } + + static void kvaser_pci_class_init(ObjectClass *klass, void *data) +diff --git a/hw/net/can/can_mioe3680_pci.c b/hw/net/can/can_mioe3680_pci.c +index 965e252d9d..695e762a8d 100644 +--- a/hw/net/can/can_mioe3680_pci.c ++++ b/hw/net/can/can_mioe3680_pci.c +@@ -219,11 +219,11 @@ static void mioe3680_pci_instance_init(Object *obj) + object_property_add_link(obj, "canbus0", TYPE_CAN_BUS, + (Object **)&d->canbus[0], + qdev_prop_allow_set_link_before_realize, +- 0, &error_abort); ++ 0); + object_property_add_link(obj, "canbus1", TYPE_CAN_BUS, + (Object **)&d->canbus[1], + qdev_prop_allow_set_link_before_realize, +- 0, &error_abort); ++ 0); + } + + static void mioe3680_pci_class_init(ObjectClass *klass, void *data) +diff --git a/hw/net/can/can_pcm3680_pci.c b/hw/net/can/can_pcm3680_pci.c +index 51b6540072..4218e63eb2 100644 +--- a/hw/net/can/can_pcm3680_pci.c ++++ b/hw/net/can/can_pcm3680_pci.c +@@ -220,11 +220,11 @@ static void pcm3680i_pci_instance_init(Object *obj) + object_property_add_link(obj, "canbus0", TYPE_CAN_BUS, + (Object **)&d->canbus[0], + qdev_prop_allow_set_link_before_realize, +- 0, &error_abort); ++ 0); + object_property_add_link(obj, "canbus1", TYPE_CAN_BUS, + (Object **)&d->canbus[1], + qdev_prop_allow_set_link_before_realize, +- 0, &error_abort); ++ 0); + } + + static void pcm3680i_pci_class_init(ObjectClass *klass, void *data) +diff --git a/hw/net/ne2000-isa.c b/hw/net/ne2000-isa.c +index e744eff153..fdf8faa0d9 100644 +--- a/hw/net/ne2000-isa.c ++++ b/hw/net/ne2000-isa.c +@@ -133,7 +133,7 @@ static void isa_ne2000_instance_init(Object *obj) + { + object_property_add(obj, "bootindex", "int32", + isa_ne2000_get_bootindex, +- isa_ne2000_set_bootindex, NULL, NULL, NULL); ++ isa_ne2000_set_bootindex, NULL, NULL); + object_property_set_int(obj, -1, "bootindex", NULL); + } + static const TypeInfo ne2000_isa_info = { +diff --git a/hw/net/xilinx_axienet.c b/hw/net/xilinx_axienet.c +index 498afe2f54..44fe04d889 100644 +--- a/hw/net/xilinx_axienet.c ++++ b/hw/net/xilinx_axienet.c +@@ -985,16 +985,11 @@ static void xilinx_enet_realize(DeviceState *dev, Error **errp) + object_property_add_link(OBJECT(ds), "enet", "xlnx.axi-ethernet", + (Object **) &ds->enet, + object_property_allow_set_link, +- OBJ_PROP_LINK_STRONG, +- &local_err); ++ OBJ_PROP_LINK_STRONG); + object_property_add_link(OBJECT(cs), "enet", "xlnx.axi-ethernet", + (Object **) &cs->enet, + object_property_allow_set_link, +- OBJ_PROP_LINK_STRONG, +- &local_err); +- if (local_err) { +- goto xilinx_enet_realize_fail; +- } ++ OBJ_PROP_LINK_STRONG); + object_property_set_link(OBJECT(ds), OBJECT(s), "enet", &local_err); + object_property_set_link(OBJECT(cs), OBJECT(s), "enet", &local_err); + if (local_err) { +diff --git a/hw/nios2/10m50_devboard.c b/hw/nios2/10m50_devboard.c +index 33dc2bf511..4c60a27fb7 100644 +--- a/hw/nios2/10m50_devboard.c ++++ b/hw/nios2/10m50_devboard.c +@@ -81,8 +81,7 @@ static void nios2_10m50_ghrd_init(MachineState *machine) + + /* Register: Internal Interrupt Controller (IIC) */ + dev = qdev_create(NULL, "altera,iic"); +- object_property_add_const_link(OBJECT(dev), "cpu", OBJECT(cpu), +- &error_abort); ++ object_property_add_const_link(OBJECT(dev), "cpu", OBJECT(cpu)); + qdev_init_nofail(dev); + sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, cpu_irq[0]); + for (i = 0; i < 32; i++) { +diff --git a/hw/nvram/fw_cfg.c b/hw/nvram/fw_cfg.c +index 4be6c9d9fd..8dd50c2c72 100644 +--- a/hw/nvram/fw_cfg.c ++++ b/hw/nvram/fw_cfg.c +@@ -1105,7 +1105,7 @@ FWCfgState *fw_cfg_init_io_dma(uint32_t iobase, uint32_t dma_iobase, + } + + object_property_add_child(OBJECT(qdev_get_machine()), TYPE_FW_CFG, +- OBJECT(dev), NULL); ++ OBJECT(dev)); + qdev_init_nofail(dev); + + sbd = SYS_BUS_DEVICE(dev); +@@ -1145,7 +1145,7 @@ FWCfgState *fw_cfg_init_mem_wide(hwaddr ctl_addr, + } + + object_property_add_child(OBJECT(qdev_get_machine()), TYPE_FW_CFG, +- OBJECT(dev), NULL); ++ OBJECT(dev)); + qdev_init_nofail(dev); + + sbd = SYS_BUS_DEVICE(dev); +diff --git a/hw/pci-host/grackle.c b/hw/pci-host/grackle.c +index 24ccdf6ceb..4b3af0c704 100644 +--- a/hw/pci-host/grackle.c ++++ b/hw/pci-host/grackle.c +@@ -109,7 +109,7 @@ static void grackle_init(Object *obj) + object_property_add_link(obj, "pic", TYPE_HEATHROW, + (Object **) &s->pic, + qdev_prop_allow_set_link_before_realize, +- 0, NULL); ++ 0); + + sysbus_init_mmio(sbd, &phb->conf_mem); + sysbus_init_mmio(sbd, &phb->data_mem); +diff --git a/hw/pci-host/i440fx.c b/hw/pci-host/i440fx.c +index d980c97049..0adbd77553 100644 +--- a/hw/pci-host/i440fx.c ++++ b/hw/pci-host/i440fx.c +@@ -212,19 +212,19 @@ static void i440fx_pcihost_initfn(Object *obj) + + object_property_add(obj, PCI_HOST_PROP_PCI_HOLE_START, "uint32", + i440fx_pcihost_get_pci_hole_start, +- NULL, NULL, NULL, NULL); ++ NULL, NULL, NULL); + + object_property_add(obj, PCI_HOST_PROP_PCI_HOLE_END, "uint32", + i440fx_pcihost_get_pci_hole_end, +- NULL, NULL, NULL, NULL); ++ NULL, NULL, NULL); + + object_property_add(obj, PCI_HOST_PROP_PCI_HOLE64_START, "uint64", + i440fx_pcihost_get_pci_hole64_start, +- NULL, NULL, NULL, NULL); ++ NULL, NULL, NULL); + + object_property_add(obj, PCI_HOST_PROP_PCI_HOLE64_END, "uint64", + i440fx_pcihost_get_pci_hole64_end, +- NULL, NULL, NULL, NULL); ++ NULL, NULL, NULL); + } + + static void i440fx_pcihost_realize(DeviceState *dev, Error **errp) +@@ -275,7 +275,7 @@ PCIBus *i440fx_init(const char *host_type, const char *pci_type, + b = pci_root_bus_new(dev, NULL, pci_address_space, + address_space_io, 0, TYPE_PCI_BUS); + s->bus = b; +- object_property_add_child(qdev_get_machine(), "i440fx", OBJECT(dev), NULL); ++ object_property_add_child(qdev_get_machine(), "i440fx", OBJECT(dev)); + qdev_init_nofail(dev); + + d = pci_create_simple(b, 0, pci_type); +@@ -308,7 +308,7 @@ PCIBus *i440fx_init(const char *host_type, const char *pci_type, + memory_region_set_enabled(&f->low_smram, true); + memory_region_add_subregion(&f->smram, 0xa0000, &f->low_smram); + object_property_add_const_link(qdev_get_machine(), "smram", +- OBJECT(&f->smram), &error_abort); ++ OBJECT(&f->smram)); + + init_pam(dev, f->ram_memory, f->system_memory, f->pci_address_space, + &f->pam_regions[0], PAM_BIOS_BASE, PAM_BIOS_SIZE); +diff --git a/hw/pci-host/pnv_phb3_msi.c b/hw/pci-host/pnv_phb3_msi.c +index d645468f4a..099d2092a2 100644 +--- a/hw/pci-host/pnv_phb3_msi.c ++++ b/hw/pci-host/pnv_phb3_msi.c +@@ -282,8 +282,7 @@ static void phb3_msi_instance_init(Object *obj) + object_property_add_link(obj, "phb", TYPE_PNV_PHB3, + (Object **)&msi->phb, + object_property_allow_set_link, +- OBJ_PROP_LINK_STRONG, +- &error_abort); ++ OBJ_PROP_LINK_STRONG); + + /* Will be overriden later */ + ics->offset = 0; +diff --git a/hw/pci-host/pnv_phb3_pbcq.c b/hw/pci-host/pnv_phb3_pbcq.c +index 7b9a121246..a0526aa1ec 100644 +--- a/hw/pci-host/pnv_phb3_pbcq.c ++++ b/hw/pci-host/pnv_phb3_pbcq.c +@@ -324,8 +324,7 @@ static void phb3_pbcq_instance_init(Object *obj) + object_property_add_link(obj, "phb", TYPE_PNV_PHB3, + (Object **)&pbcq->phb, + object_property_allow_set_link, +- OBJ_PROP_LINK_STRONG, +- &error_abort); ++ OBJ_PROP_LINK_STRONG); + } + + static void pnv_pbcq_class_init(ObjectClass *klass, void *data) +diff --git a/hw/pci-host/q35.c b/hw/pci-host/q35.c +index 2bbc90b28f..352aeecfa7 100644 +--- a/hw/pci-host/q35.c ++++ b/hw/pci-host/q35.c +@@ -222,38 +222,38 @@ static void q35_host_initfn(Object *obj) + Q35_PCI_HOST_HOLE64_SIZE_DEFAULT); + object_property_add(obj, PCI_HOST_PROP_PCI_HOLE_START, "uint32", + q35_host_get_pci_hole_start, +- NULL, NULL, NULL, NULL); ++ NULL, NULL, NULL); + + object_property_add(obj, PCI_HOST_PROP_PCI_HOLE_END, "uint32", + q35_host_get_pci_hole_end, +- NULL, NULL, NULL, NULL); ++ NULL, NULL, NULL); + + object_property_add(obj, PCI_HOST_PROP_PCI_HOLE64_START, "uint64", + q35_host_get_pci_hole64_start, +- NULL, NULL, NULL, NULL); ++ NULL, NULL, NULL); + + object_property_add(obj, PCI_HOST_PROP_PCI_HOLE64_END, "uint64", + q35_host_get_pci_hole64_end, +- NULL, NULL, NULL, NULL); ++ NULL, NULL, NULL); + + object_property_add_uint64_ptr(obj, PCIE_HOST_MCFG_SIZE, +- &pehb->size, OBJ_PROP_FLAG_READ, NULL); ++ &pehb->size, OBJ_PROP_FLAG_READ); + + object_property_add_link(obj, MCH_HOST_PROP_RAM_MEM, TYPE_MEMORY_REGION, + (Object **) &s->mch.ram_memory, +- qdev_prop_allow_set_link_before_realize, 0, NULL); ++ qdev_prop_allow_set_link_before_realize, 0); + + object_property_add_link(obj, MCH_HOST_PROP_PCI_MEM, TYPE_MEMORY_REGION, + (Object **) &s->mch.pci_address_space, +- qdev_prop_allow_set_link_before_realize, 0, NULL); ++ qdev_prop_allow_set_link_before_realize, 0); + + object_property_add_link(obj, MCH_HOST_PROP_SYSTEM_MEM, TYPE_MEMORY_REGION, + (Object **) &s->mch.system_memory, +- qdev_prop_allow_set_link_before_realize, 0, NULL); ++ qdev_prop_allow_set_link_before_realize, 0); + + object_property_add_link(obj, MCH_HOST_PROP_IO_MEM, TYPE_MEMORY_REGION, + (Object **) &s->mch.address_space_io, +- qdev_prop_allow_set_link_before_realize, 0, NULL); ++ qdev_prop_allow_set_link_before_realize, 0); + } + + static const TypeInfo q35_host_info = { +@@ -638,7 +638,7 @@ static void mch_realize(PCIDevice *d, Error **errp) + &mch->smbase_window); + + object_property_add_const_link(qdev_get_machine(), "smram", +- OBJECT(&mch->smram), &error_abort); ++ OBJECT(&mch->smram)); + + init_pam(DEVICE(mch), mch->ram_memory, mch->system_memory, + mch->pci_address_space, &mch->pam_regions[0], +diff --git a/hw/pci-host/sabre.c b/hw/pci-host/sabre.c +index 2b8503b709..475bcb01d7 100644 +--- a/hw/pci-host/sabre.c ++++ b/hw/pci-host/sabre.c +@@ -442,7 +442,7 @@ static void sabre_init(Object *obj) + object_property_add_link(obj, "iommu", TYPE_SUN4U_IOMMU, + (Object **) &s->iommu, + qdev_prop_allow_set_link_before_realize, +- 0, NULL); ++ 0); + + /* sabre_config */ + memory_region_init_io(&s->sabre_config, OBJECT(s), &sabre_config_ops, s, +diff --git a/hw/pci-host/uninorth.c b/hw/pci-host/uninorth.c +index cf70b76fe2..1ed1072eeb 100644 +--- a/hw/pci-host/uninorth.c ++++ b/hw/pci-host/uninorth.c +@@ -175,7 +175,7 @@ static void pci_unin_main_init(Object *obj) + object_property_add_link(obj, "pic", TYPE_OPENPIC, + (Object **) &s->pic, + qdev_prop_allow_set_link_before_realize, +- 0, NULL); ++ 0); + + sysbus_init_mmio(sbd, &h->conf_mem); + sysbus_init_mmio(sbd, &h->data_mem); +@@ -223,7 +223,7 @@ static void pci_u3_agp_init(Object *obj) + object_property_add_link(obj, "pic", TYPE_OPENPIC, + (Object **) &s->pic, + qdev_prop_allow_set_link_before_realize, +- 0, NULL); ++ 0); + + sysbus_init_mmio(sbd, &h->conf_mem); + sysbus_init_mmio(sbd, &h->data_mem); +@@ -262,7 +262,7 @@ static void pci_unin_agp_init(Object *obj) + object_property_add_link(obj, "pic", TYPE_OPENPIC, + (Object **) &s->pic, + qdev_prop_allow_set_link_before_realize, +- 0, NULL); ++ 0); + + sysbus_init_mmio(sbd, &h->conf_mem); + sysbus_init_mmio(sbd, &h->data_mem); +@@ -299,7 +299,7 @@ static void pci_unin_internal_init(Object *obj) + object_property_add_link(obj, "pic", TYPE_OPENPIC, + (Object **) &s->pic, + qdev_prop_allow_set_link_before_realize, +- 0, NULL); ++ 0); + + sysbus_init_mmio(sbd, &h->conf_mem); + sysbus_init_mmio(sbd, &h->data_mem); +diff --git a/hw/pcmcia/pxa2xx.c b/hw/pcmcia/pxa2xx.c +index 14e4dfe8b1..8667244df4 100644 +--- a/hw/pcmcia/pxa2xx.c ++++ b/hw/pcmcia/pxa2xx.c +@@ -189,7 +189,7 @@ static void pxa2xx_pcmcia_initfn(Object *obj) + object_property_add_link(obj, "card", TYPE_PCMCIA_CARD, + (Object **)&s->card, + NULL, /* read-only property */ +- 0, NULL); ++ 0); + } + + /* Insert a new card into a slot */ +diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c +index 0d1f41197c..2a0b66a152 100644 +--- a/hw/ppc/e500.c ++++ b/hw/ppc/e500.c +@@ -744,8 +744,7 @@ static DeviceState *ppce500_init_mpic_qemu(PPCE500MachineState *pms, + const PPCE500MachineClass *pmc = PPCE500_MACHINE_GET_CLASS(pms); + + dev = qdev_create(NULL, TYPE_OPENPIC); +- object_property_add_child(OBJECT(machine), "pic", OBJECT(dev), +- &error_fatal); ++ object_property_add_child(OBJECT(machine), "pic", OBJECT(dev)); + qdev_prop_set_uint32(dev, "model", pmc->mpic_version); + qdev_prop_set_uint32(dev, "nb_cpus", smp_cpus); + +@@ -916,7 +915,7 @@ void ppce500_init(MachineState *machine) + + dev = qdev_create(NULL, "e500-ccsr"); + object_property_add_child(qdev_get_machine(), "e500-ccsr", +- OBJECT(dev), NULL); ++ OBJECT(dev)); + qdev_init_nofail(dev); + ccsr = CCSR(dev); + ccsr_addr_space = &ccsr->ccsr_space; +@@ -957,8 +956,7 @@ void ppce500_init(MachineState *machine) + + /* PCI */ + dev = qdev_create(NULL, "e500-pcihost"); +- object_property_add_child(qdev_get_machine(), "pci-host", OBJECT(dev), +- &error_abort); ++ object_property_add_child(qdev_get_machine(), "pci-host", OBJECT(dev)); + qdev_prop_set_uint32(dev, "first_slot", pmc->pci_first_slot); + qdev_prop_set_uint32(dev, "first_pin_irq", pci_irq_nrs[0]); + qdev_init_nofail(dev); +diff --git a/hw/ppc/mac_newworld.c b/hw/ppc/mac_newworld.c +index 55d1419442..3507f26f6e 100644 +--- a/hw/ppc/mac_newworld.c ++++ b/hw/ppc/mac_newworld.c +@@ -455,7 +455,7 @@ static void ppc_core99_init(MachineState *machine) + qdev_prop_set_uint32(dev, "data_width", 1); + qdev_prop_set_bit(dev, "dma_enabled", false); + object_property_add_child(OBJECT(qdev_get_machine()), TYPE_FW_CFG, +- OBJECT(fw_cfg), NULL); ++ OBJECT(fw_cfg)); + qdev_init_nofail(dev); + s = SYS_BUS_DEVICE(dev); + sysbus_mmio_map(s, 0, CFG_ADDR); +@@ -628,7 +628,7 @@ static void core99_instance_init(Object *obj) + /* Default via_config is CORE99_VIA_CONFIG_CUDA */ + cms->via_config = CORE99_VIA_CONFIG_CUDA; + object_property_add_str(obj, "via", core99_get_via_config, +- core99_set_via_config, NULL); ++ core99_set_via_config); + object_property_set_description(obj, "via", + "Set VIA configuration. " + "Valid values are cuda, pmu and pmu-adb"); +diff --git a/hw/ppc/mac_oldworld.c b/hw/ppc/mac_oldworld.c +index 101bdc5c4d..0b4c1c6373 100644 +--- a/hw/ppc/mac_oldworld.c ++++ b/hw/ppc/mac_oldworld.c +@@ -314,7 +314,7 @@ static void ppc_heathrow_init(MachineState *machine) + qdev_prop_set_uint32(dev, "data_width", 1); + qdev_prop_set_bit(dev, "dma_enabled", false); + object_property_add_child(OBJECT(qdev_get_machine()), TYPE_FW_CFG, +- OBJECT(fw_cfg), NULL); ++ OBJECT(fw_cfg)); + qdev_init_nofail(dev); + s = SYS_BUS_DEVICE(dev); + sysbus_mmio_map(s, 0, CFG_ADDR); +diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c +index 4666dbbe7a..da637822f9 100644 +--- a/hw/ppc/pnv.c ++++ b/hw/ppc/pnv.c +@@ -832,7 +832,7 @@ static void pnv_init(MachineState *machine) + } + + snprintf(chip_name, sizeof(chip_name), "chip[%d]", PNV_CHIP_HWID(i)); +- object_property_add_child(OBJECT(pnv), chip_name, chip, &error_fatal); ++ object_property_add_child(OBJECT(pnv), chip_name, chip); + object_property_set_int(chip, PNV_CHIP_HWID(i), "chip-id", + &error_fatal); + object_property_set_int(chip, machine->smp.cores, +@@ -1060,8 +1060,7 @@ static void pnv_chip_power8_instance_init(Object *obj) + object_property_add_link(obj, "xics", TYPE_XICS_FABRIC, + (Object **)&chip8->xics, + object_property_allow_set_link, +- OBJ_PROP_LINK_STRONG, +- &error_abort); ++ OBJ_PROP_LINK_STRONG); + + object_initialize_child(obj, "psi", &chip8->psi, sizeof(chip8->psi), + TYPE_PNV8_PSI, &error_abort, NULL); +@@ -1321,7 +1320,7 @@ static void pnv_chip_power9_instance_init(Object *obj) + object_initialize_child(obj, "xive", &chip9->xive, sizeof(chip9->xive), + TYPE_PNV_XIVE, &error_abort, NULL); + object_property_add_alias(obj, "xive-fabric", OBJECT(&chip9->xive), +- "xive-fabric", &error_abort); ++ "xive-fabric"); + + object_initialize_child(obj, "psi", &chip9->psi, sizeof(chip9->psi), + TYPE_PNV9_PSI, &error_abort, NULL); +@@ -1739,8 +1738,7 @@ static void pnv_chip_core_realize(PnvChip *chip, Error **errp) + pnv_core = PNV_CORE(object_new(typename)); + + snprintf(core_name, sizeof(core_name), "core[%d]", core_hwid); +- object_property_add_child(OBJECT(chip), core_name, OBJECT(pnv_core), +- &error_abort); ++ object_property_add_child(OBJECT(chip), core_name, OBJECT(pnv_core)); + chip->cores[i] = pnv_core; + object_property_set_int(OBJECT(pnv_core), chip->nr_threads, + "nr-threads", &error_fatal); +@@ -2027,8 +2025,7 @@ static void pnv_machine_class_init(ObjectClass *oc, void *data) + nc->nmi_monitor_handler = pnv_nmi; + + object_class_property_add_bool(oc, "hb-mode", +- pnv_machine_get_hb, pnv_machine_set_hb, +- &error_abort); ++ pnv_machine_get_hb, pnv_machine_set_hb); + object_class_property_set_description(oc, "hb-mode", + "Use a hostboot like boot loader"); + } +diff --git a/hw/ppc/pnv_bmc.c b/hw/ppc/pnv_bmc.c +index 4e018b8b70..5f86453b6a 100644 +--- a/hw/ppc/pnv_bmc.c ++++ b/hw/ppc/pnv_bmc.c +@@ -217,8 +217,7 @@ static const IPMINetfn hiomap_netfn = { + void pnv_bmc_set_pnor(IPMIBmc *bmc, PnvPnor *pnor) + { + object_ref(OBJECT(pnor)); +- object_property_add_const_link(OBJECT(bmc), "pnor", OBJECT(pnor), +- &error_abort); ++ object_property_add_const_link(OBJECT(bmc), "pnor", OBJECT(pnor)); + + /* Install the HIOMAP protocol handlers to access the PNOR */ + ipmi_sim_register_netfn(IPMI_BMC_SIMULATOR(bmc), IPMI_NETFN_OEM, +@@ -235,7 +234,7 @@ IPMIBmc *pnv_bmc_create(PnvPnor *pnor) + + obj = object_new(TYPE_IPMI_BMC_SIMULATOR); + object_ref(OBJECT(pnor)); +- object_property_add_const_link(obj, "pnor", OBJECT(pnor), &error_abort); ++ object_property_add_const_link(obj, "pnor", OBJECT(pnor)); + object_property_set_bool(obj, true, "realized", &error_fatal); + + /* Install the HIOMAP protocol handlers to access the PNOR */ +diff --git a/hw/ppc/pnv_core.c b/hw/ppc/pnv_core.c +index 234562040d..7033104676 100644 +--- a/hw/ppc/pnv_core.c ++++ b/hw/ppc/pnv_core.c +@@ -232,7 +232,7 @@ static void pnv_core_realize(DeviceState *dev, Error **errp) + pc->threads[i] = POWERPC_CPU(obj); + + snprintf(name, sizeof(name), "thread[%d]", i); +- object_property_add_child(OBJECT(pc), name, obj, &error_abort); ++ object_property_add_child(OBJECT(pc), name, obj); + + cpu->machine_data = g_new0(PnvCPUState, 1); + +diff --git a/hw/ppc/pnv_psi.c b/hw/ppc/pnv_psi.c +index c34a49b000..cfd5b7bc25 100644 +--- a/hw/ppc/pnv_psi.c ++++ b/hw/ppc/pnv_psi.c +@@ -486,7 +486,7 @@ static void pnv_psi_power8_instance_init(Object *obj) + object_initialize_child(obj, "ics-psi", &psi8->ics, sizeof(psi8->ics), + TYPE_ICS, &error_abort, NULL); + object_property_add_alias(obj, ICS_PROP_XICS, OBJECT(&psi8->ics), +- ICS_PROP_XICS, &error_abort); ++ ICS_PROP_XICS); + } + + static const uint8_t irq_to_xivr[] = { +diff --git a/hw/ppc/prep.c b/hw/ppc/prep.c +index 44be9d25a2..9266453dd9 100644 +--- a/hw/ppc/prep.c ++++ b/hw/ppc/prep.c +@@ -229,7 +229,7 @@ static int prep_set_cmos_checksum(DeviceState *dev, void *opaque) + rtc_set_memory(rtc, 0x3f, checksum >> 8); + + object_property_add_alias(qdev_get_machine(), "rtc-time", OBJECT(rtc), +- "date", NULL); ++ "date"); + } + return 0; + } +@@ -275,7 +275,7 @@ static void ibm_40p_init(MachineState *machine) + qdev_prop_set_string(dev, "bios-name", bios_name); + qdev_prop_set_uint32(dev, "elf-machine", PPC_ELF_MACHINE); + pcihost = SYS_BUS_DEVICE(dev); +- object_property_add_child(qdev_get_machine(), "raven", OBJECT(dev), NULL); ++ object_property_add_child(qdev_get_machine(), "raven", OBJECT(dev)); + qdev_init_nofail(dev); + pci_bus = PCI_BUS(qdev_get_child_bus(dev, "pci.0")); + if (!pci_bus) { +@@ -343,7 +343,7 @@ static void ibm_40p_init(MachineState *machine) + qdev_prop_set_uint32(dev, "data_width", 1); + qdev_prop_set_bit(dev, "dma_enabled", false); + object_property_add_child(OBJECT(qdev_get_machine()), TYPE_FW_CFG, +- OBJECT(fw_cfg), NULL); ++ OBJECT(fw_cfg)); + qdev_init_nofail(dev); + s = SYS_BUS_DEVICE(dev); + sysbus_mmio_map(s, 0, CFG_ADDR); +diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c +index aa281e727a..976d40f60f 100644 +--- a/hw/ppc/spapr.c ++++ b/hw/ppc/spapr.c +@@ -1732,7 +1732,7 @@ static void spapr_rtc_create(SpaprMachineState *spapr) + object_property_set_bool(OBJECT(&spapr->rtc), true, "realized", + &error_fatal); + object_property_add_alias(OBJECT(spapr), "rtc-time", OBJECT(&spapr->rtc), +- "date", &error_fatal); ++ "date"); + } + + /* Returns whether we want to use VGA or not */ +@@ -3305,13 +3305,12 @@ static void spapr_instance_init(Object *obj) + spapr->htab_fd = -1; + spapr->use_hotplug_event_source = true; + object_property_add_str(obj, "kvm-type", +- spapr_get_kvm_type, spapr_set_kvm_type, NULL); ++ spapr_get_kvm_type, spapr_set_kvm_type); + object_property_set_description(obj, "kvm-type", + "Specifies the KVM virtualization mode (HV, PR)"); + object_property_add_bool(obj, "modern-hotplug-events", + spapr_get_modern_hotplug_events, +- spapr_set_modern_hotplug_events, +- NULL); ++ spapr_set_modern_hotplug_events); + object_property_set_description(obj, "modern-hotplug-events", + "Use dedicated hotplug event mechanism in" + " place of standard EPOW events when possible" +@@ -3321,22 +3320,20 @@ static void spapr_instance_init(Object *obj) + &error_fatal); + + object_property_add_str(obj, "resize-hpt", +- spapr_get_resize_hpt, spapr_set_resize_hpt, NULL); ++ spapr_get_resize_hpt, spapr_set_resize_hpt); + object_property_set_description(obj, "resize-hpt", + "Resizing of the Hash Page Table (enabled, disabled, required)"); + object_property_add_uint32_ptr(obj, "vsmt", +- &spapr->vsmt, OBJ_PROP_FLAG_READWRITE, +- &error_abort); ++ &spapr->vsmt, OBJ_PROP_FLAG_READWRITE); + object_property_set_description(obj, "vsmt", + "Virtual SMT: KVM behaves as if this were" + " the host's SMT mode"); + + object_property_add_bool(obj, "vfio-no-msix-emulation", +- spapr_get_msix_emulation, NULL, NULL); ++ spapr_get_msix_emulation, NULL); + + object_property_add_uint64_ptr(obj, "kernel-addr", +- &spapr->kernel_addr, OBJ_PROP_FLAG_READWRITE, +- &error_abort); ++ &spapr->kernel_addr, OBJ_PROP_FLAG_READWRITE); + object_property_set_description(obj, "kernel-addr", + stringify(KERNEL_LOAD_ADDR) + " for -kernel is the default"); +@@ -3344,18 +3341,16 @@ static void spapr_instance_init(Object *obj) + /* The machine class defines the default interrupt controller mode */ + spapr->irq = smc->irq; + object_property_add_str(obj, "ic-mode", spapr_get_ic_mode, +- spapr_set_ic_mode, NULL); ++ spapr_set_ic_mode); + object_property_set_description(obj, "ic-mode", + "Specifies the interrupt controller mode (xics, xive, dual)"); + + object_property_add_str(obj, "host-model", +- spapr_get_host_model, spapr_set_host_model, +- &error_abort); ++ spapr_get_host_model, spapr_set_host_model); + object_property_set_description(obj, "host-model", + "Host model to advertise in guest device tree"); + object_property_add_str(obj, "host-serial", +- spapr_get_host_serial, spapr_set_host_serial, +- &error_abort); ++ spapr_get_host_serial, spapr_set_host_serial); + object_property_set_description(obj, "host-serial", + "Host serial number to advertise in guest device tree"); + } +diff --git a/hw/ppc/spapr_caps.c b/hw/ppc/spapr_caps.c +index 0870961fc9..184563e608 100644 +--- a/hw/ppc/spapr_caps.c ++++ b/hw/ppc/spapr_caps.c +@@ -826,7 +826,6 @@ void spapr_caps_cpu_apply(SpaprMachineState *spapr, PowerPCCPU *cpu) + + void spapr_caps_add_properties(SpaprMachineClass *smc, Error **errp) + { +- Error *local_err = NULL; + ObjectClass *klass = OBJECT_CLASS(smc); + int i; + +@@ -837,12 +836,7 @@ void spapr_caps_add_properties(SpaprMachineClass *smc, Error **errp) + + object_class_property_add(klass, name, cap->type, + cap->get, cap->set, +- NULL, cap, &local_err); +- if (local_err) { +- error_propagate(errp, local_err); +- g_free(name); +- return; +- } ++ NULL, cap); + + desc = g_strdup_printf("%s", cap->description); + object_class_property_set_description(klass, name, desc); +diff --git a/hw/ppc/spapr_cpu_core.c b/hw/ppc/spapr_cpu_core.c +index ac1c109427..df5c7742ca 100644 +--- a/hw/ppc/spapr_cpu_core.c ++++ b/hw/ppc/spapr_cpu_core.c +@@ -290,11 +290,8 @@ static PowerPCCPU *spapr_create_vcpu(SpaprCpuCore *sc, int i, Error **errp) + cpu->node_id = sc->node_id; + + id = g_strdup_printf("thread[%d]", i); +- object_property_add_child(OBJECT(sc), id, obj, &local_err); ++ object_property_add_child(OBJECT(sc), id, obj); + g_free(id); +- if (local_err) { +- goto err; +- } + + cpu->machine_data = g_new0(SpaprCpuState, 1); + +diff --git a/hw/ppc/spapr_drc.c b/hw/ppc/spapr_drc.c +index 0b66d59867..728307a992 100644 +--- a/hw/ppc/spapr_drc.c ++++ b/hw/ppc/spapr_drc.c +@@ -392,7 +392,7 @@ void spapr_drc_attach(SpaprDrc *drc, DeviceState *d, Error **errp) + object_property_add_link(OBJECT(drc), "device", + object_get_typename(OBJECT(drc->dev)), + (Object **)(&drc->dev), +- NULL, 0, NULL); ++ NULL, 0); + } + + static void spapr_drc_release(SpaprDrc *drc) +@@ -519,7 +519,6 @@ static void realize(DeviceState *d, Error **errp) + Object *root_container; + gchar *link_name; + char *child_name; +- Error *err = NULL; + + trace_spapr_drc_realize(spapr_drc_index(drc)); + /* NOTE: we do this as part of realize/unrealize due to the fact +@@ -534,13 +533,9 @@ static void realize(DeviceState *d, Error **errp) + child_name = object_get_canonical_path_component(OBJECT(drc)); + trace_spapr_drc_realize_child(spapr_drc_index(drc), child_name); + object_property_add_alias(root_container, link_name, +- drc->owner, child_name, &err); ++ drc->owner, child_name); + g_free(child_name); + g_free(link_name); +- if (err) { +- error_propagate(errp, err); +- return; +- } + vmstate_register(VMSTATE_IF(drc), spapr_drc_index(drc), &vmstate_spapr_drc, + drc); + trace_spapr_drc_realize_complete(spapr_drc_index(drc)); +@@ -570,7 +565,7 @@ SpaprDrc *spapr_dr_connector_new(Object *owner, const char *type, + drc->owner = owner; + prop_name = g_strdup_printf("dr-connector[%"PRIu32"]", + spapr_drc_index(drc)); +- object_property_add_child(owner, prop_name, OBJECT(drc), &error_abort); ++ object_property_add_child(owner, prop_name, OBJECT(drc)); + object_unref(OBJECT(drc)); + object_property_set_bool(OBJECT(drc), true, "realized", NULL); + g_free(prop_name); +@@ -583,12 +578,11 @@ static void spapr_dr_connector_instance_init(Object *obj) + SpaprDrc *drc = SPAPR_DR_CONNECTOR(obj); + SpaprDrcClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); + +- object_property_add_uint32_ptr(obj, "id", &drc->id, OBJ_PROP_FLAG_READ, +- NULL); ++ object_property_add_uint32_ptr(obj, "id", &drc->id, OBJ_PROP_FLAG_READ); + object_property_add(obj, "index", "uint32", prop_get_index, +- NULL, NULL, NULL, NULL); ++ NULL, NULL, NULL); + object_property_add(obj, "fdt", "struct", prop_get_fdt, +- NULL, NULL, NULL, NULL); ++ NULL, NULL, NULL); + drc->state = drck->empty_state; + } + +diff --git a/hw/ppc/spapr_iommu.c b/hw/ppc/spapr_iommu.c +index 5704fe6051..601b896214 100644 +--- a/hw/ppc/spapr_iommu.c ++++ b/hw/ppc/spapr_iommu.c +@@ -365,7 +365,7 @@ SpaprTceTable *spapr_tce_new_table(DeviceState *owner, uint32_t liobn) + tcet->liobn = liobn; + + tmp = g_strdup_printf("tce-table-%x", liobn); +- object_property_add_child(OBJECT(owner), tmp, OBJECT(tcet), NULL); ++ object_property_add_child(OBJECT(owner), tmp, OBJECT(tcet)); + g_free(tmp); + object_unref(OBJECT(tcet)); + +diff --git a/hw/ppc/spapr_irq.c b/hw/ppc/spapr_irq.c +index 1f630f296b..0c594aa72e 100644 +--- a/hw/ppc/spapr_irq.c ++++ b/hw/ppc/spapr_irq.c +@@ -307,7 +307,7 @@ void spapr_irq_init(SpaprMachineState *spapr, Error **errp) + + obj = object_new(TYPE_ICS_SPAPR); + +- object_property_add_child(OBJECT(spapr), "ics", obj, &error_abort); ++ object_property_add_child(OBJECT(spapr), "ics", obj); + object_property_set_link(obj, OBJECT(spapr), ICS_PROP_XICS, + &error_abort); + object_property_set_int(obj, smc->nr_xirqs, "nr-irqs", &error_abort); +diff --git a/hw/ppc/spapr_rtc.c b/hw/ppc/spapr_rtc.c +index 42ff72c269..68cfc578a3 100644 +--- a/hw/ppc/spapr_rtc.c ++++ b/hw/ppc/spapr_rtc.c +@@ -149,7 +149,7 @@ static void spapr_rtc_realize(DeviceState *dev, Error **errp) + rtc_ns = qemu_clock_get_ns(rtc_clock); + rtc->ns_offset = host_s * NANOSECONDS_PER_SECOND - rtc_ns; + +- object_property_add_tm(OBJECT(rtc), "date", spapr_rtc_qom_date, NULL); ++ object_property_add_tm(OBJECT(rtc), "date", spapr_rtc_qom_date); + } + + static const VMStateDescription vmstate_spapr_rtc = { +diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c +index da48c958e2..4299bdf480 100644 +--- a/hw/riscv/sifive_u.c ++++ b/hw/riscv/sifive_u.c +@@ -441,15 +441,17 @@ static void sifive_u_machine_instance_init(Object *obj) + SiFiveUState *s = RISCV_U_MACHINE(obj); + + s->start_in_flash = false; +- object_property_add_bool(obj, "start-in-flash", sifive_u_machine_get_start_in_flash, +- sifive_u_machine_set_start_in_flash, NULL); ++ object_property_add_bool(obj, "start-in-flash", ++ sifive_u_machine_get_start_in_flash, ++ sifive_u_machine_set_start_in_flash); + object_property_set_description(obj, "start-in-flash", + "Set on to tell QEMU's ROM to jump to " + "flash. Otherwise QEMU will jump to DRAM"); + + s->serial = OTP_SERIAL; +- object_property_add(obj, "serial", "uint32", sifive_u_machine_get_serial, +- sifive_u_machine_set_serial, NULL, &s->serial, NULL); ++ object_property_add(obj, "serial", "uint32", ++ sifive_u_machine_get_serial, ++ sifive_u_machine_set_serial, NULL, &s->serial); + object_property_set_description(obj, "serial", "Board serial number"); + } + +diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c +index daae3ebdbb..c695a44979 100644 +--- a/hw/riscv/virt.c ++++ b/hw/riscv/virt.c +@@ -92,10 +92,9 @@ static PFlashCFI01 *virt_flash_create1(RISCVVirtState *s, + qdev_prop_set_uint16(dev, "id3", 0x00); + qdev_prop_set_string(dev, "name", name); + +- object_property_add_child(OBJECT(s), name, OBJECT(dev), +- &error_abort); ++ object_property_add_child(OBJECT(s), name, OBJECT(dev)); + object_property_add_alias(OBJECT(s), alias_prop_name, +- OBJECT(dev), "drive", &error_abort); ++ OBJECT(dev), "drive"); + + return PFLASH_CFI01(dev); + } +diff --git a/hw/rtc/mc146818rtc.c b/hw/rtc/mc146818rtc.c +index d18c09911b..9c30cbdcd7 100644 +--- a/hw/rtc/mc146818rtc.c ++++ b/hw/rtc/mc146818rtc.c +@@ -962,7 +962,7 @@ static void rtc_realizefn(DeviceState *dev, Error **errp) + qdev_set_legacy_instance_id(dev, RTC_ISA_BASE, 3); + qemu_register_reset(rtc_reset, s); + +- object_property_add_tm(OBJECT(s), "date", rtc_get_date, NULL); ++ object_property_add_tm(OBJECT(s), "date", rtc_get_date); + + qdev_init_gpio_out(dev, &s->irq, 1); + QLIST_INSERT_HEAD(&rtc_devices, s, link); +@@ -984,7 +984,7 @@ ISADevice *mc146818_rtc_init(ISABus *bus, int base_year, qemu_irq intercept_irq) + } + + object_property_add_alias(qdev_get_machine(), "rtc-time", OBJECT(isadev), +- "date", NULL); ++ "date"); + + return isadev; + } +diff --git a/hw/s390x/ap-bridge.c b/hw/s390x/ap-bridge.c +index 9284de4eec..d0dbd0f1b6 100644 +--- a/hw/s390x/ap-bridge.c ++++ b/hw/s390x/ap-bridge.c +@@ -51,7 +51,7 @@ void s390_init_ap(void) + /* Create bridge device */ + dev = qdev_create(NULL, TYPE_AP_BRIDGE); + object_property_add_child(qdev_get_machine(), TYPE_AP_BRIDGE, +- OBJECT(dev), NULL); ++ OBJECT(dev)); + qdev_init_nofail(dev); + + /* Create bus on bridge device */ +diff --git a/hw/s390x/css-bridge.c b/hw/s390x/css-bridge.c +index c9ce06b043..5d5286bc6e 100644 +--- a/hw/s390x/css-bridge.c ++++ b/hw/s390x/css-bridge.c +@@ -103,7 +103,7 @@ VirtualCssBus *virtual_css_bus_init(void) + /* Create bridge device */ + dev = qdev_create(NULL, TYPE_VIRTUAL_CSS_BRIDGE); + object_property_add_child(qdev_get_machine(), TYPE_VIRTUAL_CSS_BRIDGE, +- OBJECT(dev), NULL); ++ OBJECT(dev)); + qdev_init_nofail(dev); + + /* Create bus on bridge device */ +@@ -141,7 +141,7 @@ static void virtual_css_bridge_class_init(ObjectClass *klass, void *data) + set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); + device_class_set_props(dc, virtual_css_bridge_properties); + object_class_property_add_bool(klass, "cssid-unrestricted", +- prop_get_true, NULL, NULL); ++ prop_get_true, NULL); + object_class_property_set_description(klass, "cssid-unrestricted", + "A css device can use any cssid, regardless whether virtual" + " or not (read only, always true)"); +diff --git a/hw/s390x/event-facility.c b/hw/s390x/event-facility.c +index 9d6972afa8..97a4f0b1f5 100644 +--- a/hw/s390x/event-facility.c ++++ b/hw/s390x/event-facility.c +@@ -449,18 +449,18 @@ static void init_event_facility(Object *obj) + event_facility->allow_all_mask_sizes = true; + object_property_add_bool(obj, "allow_all_mask_sizes", + sclp_event_get_allow_all_mask_sizes, +- sclp_event_set_allow_all_mask_sizes, NULL); ++ sclp_event_set_allow_all_mask_sizes); + /* Spawn a new bus for SCLP events */ + qbus_create_inplace(&event_facility->sbus, sizeof(event_facility->sbus), + TYPE_SCLP_EVENTS_BUS, sdev, NULL); + + new = object_new(TYPE_SCLP_QUIESCE); +- object_property_add_child(obj, TYPE_SCLP_QUIESCE, new, NULL); ++ object_property_add_child(obj, TYPE_SCLP_QUIESCE, new); + object_unref(new); + qdev_set_parent_bus(DEVICE(new), BUS(&event_facility->sbus)); + + new = object_new(TYPE_SCLP_CPU_HOTPLUG); +- object_property_add_child(obj, TYPE_SCLP_CPU_HOTPLUG, new, NULL); ++ object_property_add_child(obj, TYPE_SCLP_CPU_HOTPLUG, new); + object_unref(new); + qdev_set_parent_bus(DEVICE(new), BUS(&event_facility->sbus)); + /* the facility will automatically realize the devices via the bus */ +diff --git a/hw/s390x/s390-skeys.c b/hw/s390x/s390-skeys.c +index a9a4ae7b39..d304b85640 100644 +--- a/hw/s390x/s390-skeys.c ++++ b/hw/s390x/s390-skeys.c +@@ -45,7 +45,7 @@ void s390_skeys_init(void) + obj = object_new(TYPE_QEMU_S390_SKEYS); + } + object_property_add_child(qdev_get_machine(), TYPE_S390_SKEYS, +- obj, NULL); ++ obj); + object_unref(obj); + + qdev_init_nofail(DEVICE(obj)); +@@ -400,7 +400,7 @@ static void s390_skeys_instance_init(Object *obj) + { + object_property_add_bool(obj, "migration-enabled", + s390_skeys_get_migration_enabled, +- s390_skeys_set_migration_enabled, NULL); ++ s390_skeys_set_migration_enabled); + object_property_set_bool(obj, true, "migration-enabled", NULL); + } + +diff --git a/hw/s390x/s390-stattrib.c b/hw/s390x/s390-stattrib.c +index 58121b9f68..6d1e587527 100644 +--- a/hw/s390x/s390-stattrib.c ++++ b/hw/s390x/s390-stattrib.c +@@ -47,7 +47,7 @@ void s390_stattrib_init(void) + } + + object_property_add_child(qdev_get_machine(), TYPE_S390_STATTRIB, +- obj, NULL); ++ obj); + object_unref(obj); + + qdev_init_nofail(DEVICE(obj)); +@@ -387,7 +387,7 @@ static void s390_stattrib_instance_init(Object *obj) + + object_property_add_bool(obj, "migration-enabled", + s390_stattrib_get_migration_enabled, +- s390_stattrib_set_migration_enabled, NULL); ++ s390_stattrib_set_migration_enabled); + object_property_set_bool(obj, true, "migration-enabled", NULL); + sas->migration_cur_gfn = 0; + } +diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c +index 2f94061ff6..67ae2e02ff 100644 +--- a/hw/s390x/s390-virtio-ccw.c ++++ b/hw/s390x/s390-virtio-ccw.c +@@ -208,7 +208,7 @@ static void s390_init_ipl_dev(const char *kernel_filename, + } + g_free(netboot_fw_prop); + object_property_add_child(qdev_get_machine(), TYPE_S390_IPL, +- new, NULL); ++ new); + object_unref(new); + qdev_init_nofail(dev); + } +@@ -271,7 +271,7 @@ static void ccw_init(MachineState *machine) + + dev = qdev_create(NULL, TYPE_S390_PCI_HOST_BRIDGE); + object_property_add_child(qdev_get_machine(), TYPE_S390_PCI_HOST_BRIDGE, +- OBJECT(dev), NULL); ++ OBJECT(dev)); + qdev_init_nofail(dev); + + /* register hypercalls */ +@@ -729,19 +729,19 @@ static inline void s390_machine_initfn(Object *obj) + { + object_property_add_bool(obj, "aes-key-wrap", + machine_get_aes_key_wrap, +- machine_set_aes_key_wrap, NULL); ++ machine_set_aes_key_wrap); + object_property_set_description(obj, "aes-key-wrap", + "enable/disable AES key wrapping using the CPACF wrapping key"); + object_property_set_bool(obj, true, "aes-key-wrap", NULL); + + object_property_add_bool(obj, "dea-key-wrap", + machine_get_dea_key_wrap, +- machine_set_dea_key_wrap, NULL); ++ machine_set_dea_key_wrap); + object_property_set_description(obj, "dea-key-wrap", + "enable/disable DEA key wrapping using the CPACF wrapping key"); + object_property_set_bool(obj, true, "dea-key-wrap", NULL); + object_property_add_str(obj, "loadparm", +- machine_get_loadparm, machine_set_loadparm, NULL); ++ machine_get_loadparm, machine_set_loadparm); + object_property_set_description(obj, "loadparm", + "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," +diff --git a/hw/s390x/sclp.c b/hw/s390x/sclp.c +index ede056b3ef..43cc1e0a41 100644 +--- a/hw/s390x/sclp.c ++++ b/hw/s390x/sclp.c +@@ -320,8 +320,7 @@ void s390_sclp_init(void) + { + Object *new = object_new(TYPE_SCLP); + +- object_property_add_child(qdev_get_machine(), TYPE_SCLP, new, +- NULL); ++ object_property_add_child(qdev_get_machine(), TYPE_SCLP, new); + object_unref(OBJECT(new)); + qdev_init_nofail(DEVICE(new)); + } +@@ -383,7 +382,7 @@ static void sclp_init(Object *obj) + Object *new; + + new = object_new(TYPE_SCLP_EVENT_FACILITY); +- object_property_add_child(obj, TYPE_SCLP_EVENT_FACILITY, new, NULL); ++ object_property_add_child(obj, TYPE_SCLP_EVENT_FACILITY, new); + object_unref(new); + sclp->event_facility = EVENT_FACILITY(new); + +diff --git a/hw/s390x/tod.c b/hw/s390x/tod.c +index 2499d6f656..7324e37b5e 100644 +--- a/hw/s390x/tod.c ++++ b/hw/s390x/tod.c +@@ -26,7 +26,7 @@ void s390_init_tod(void) + } else { + obj = object_new(TYPE_QEMU_S390_TOD); + } +- object_property_add_child(qdev_get_machine(), TYPE_S390_TOD, obj, NULL); ++ object_property_add_child(qdev_get_machine(), TYPE_S390_TOD, obj); + object_unref(obj); + + qdev_init_nofail(DEVICE(obj)); +diff --git a/hw/s390x/virtio-ccw-balloon.c b/hw/s390x/virtio-ccw-balloon.c +index 5d28e72345..ef3308ecab 100644 +--- a/hw/s390x/virtio-ccw-balloon.c ++++ b/hw/s390x/virtio-ccw-balloon.c +@@ -32,10 +32,10 @@ static void virtio_ccw_balloon_instance_init(Object *obj) + virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev), + TYPE_VIRTIO_BALLOON); + object_property_add_alias(obj, "guest-stats", OBJECT(&dev->vdev), +- "guest-stats", &error_abort); ++ "guest-stats"); + object_property_add_alias(obj, "guest-stats-polling-interval", + OBJECT(&dev->vdev), +- "guest-stats-polling-interval", &error_abort); ++ "guest-stats-polling-interval"); + } + + static Property virtio_ccw_balloon_properties[] = { +diff --git a/hw/s390x/virtio-ccw-blk.c b/hw/s390x/virtio-ccw-blk.c +index bf8520e60a..7287932b7e 100644 +--- a/hw/s390x/virtio-ccw-blk.c ++++ b/hw/s390x/virtio-ccw-blk.c +@@ -32,7 +32,7 @@ static void virtio_ccw_blk_instance_init(Object *obj) + virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev), + TYPE_VIRTIO_BLK); + object_property_add_alias(obj, "bootindex", OBJECT(&dev->vdev), +- "bootindex", &error_abort); ++ "bootindex"); + } + + static Property virtio_ccw_blk_properties[] = { +diff --git a/hw/s390x/virtio-ccw-net.c b/hw/s390x/virtio-ccw-net.c +index cd02699934..26c4d873bf 100644 +--- a/hw/s390x/virtio-ccw-net.c ++++ b/hw/s390x/virtio-ccw-net.c +@@ -35,7 +35,7 @@ static void virtio_ccw_net_instance_init(Object *obj) + virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev), + TYPE_VIRTIO_NET); + object_property_add_alias(obj, "bootindex", OBJECT(&dev->vdev), +- "bootindex", &error_abort); ++ "bootindex"); + } + + static Property virtio_ccw_net_properties[] = { +diff --git a/hw/scsi/scsi-bus.c b/hw/scsi/scsi-bus.c +index 1c980cab38..ab5459a589 100644 +--- a/hw/scsi/scsi-bus.c ++++ b/hw/scsi/scsi-bus.c +@@ -268,7 +268,7 @@ SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, BlockBackend *blk, + } + dev = qdev_create(&bus->qbus, driver); + name = g_strdup_printf("legacy[%d]", unit); +- object_property_add_child(OBJECT(bus), name, OBJECT(dev), NULL); ++ object_property_add_child(OBJECT(bus), name, OBJECT(dev)); + g_free(name); + + qdev_prop_set_uint32(dev, "scsi-id", unit); +diff --git a/hw/sparc/sun4m.c b/hw/sparc/sun4m.c +index 7472d24e2c..8dda3f7292 100644 +--- a/hw/sparc/sun4m.c ++++ b/hw/sparc/sun4m.c +@@ -795,7 +795,7 @@ static void ram_initfn(Object *obj) + object_property_add_link(obj, "memdev", TYPE_MEMORY_BACKEND, + (Object **)&d->memdev, + object_property_allow_set_link, +- OBJ_PROP_LINK_STRONG, &error_abort); ++ OBJ_PROP_LINK_STRONG); + object_property_set_description(obj, "memdev", "Set RAM backend" + "Valid value is ID of a hostmem backend"); + } +@@ -1060,7 +1060,7 @@ static void sun4m_hw_init(const struct sun4m_hwdef *hwdef, + qdev_prop_set_uint32(dev, "data_width", 1); + qdev_prop_set_bit(dev, "dma_enabled", false); + object_property_add_child(OBJECT(qdev_get_machine()), TYPE_FW_CFG, +- OBJECT(fw_cfg), NULL); ++ OBJECT(fw_cfg)); + qdev_init_nofail(dev); + s = SYS_BUS_DEVICE(dev); + sysbus_mmio_map(s, 0, CFG_ADDR); +diff --git a/hw/sparc64/sun4u.c b/hw/sparc64/sun4u.c +index 6abfcb30f8..3a757ec42e 100644 +--- a/hw/sparc64/sun4u.c ++++ b/hw/sparc64/sun4u.c +@@ -691,7 +691,7 @@ static void sun4uv_init(MemoryRegion *address_space_mem, + + dev = qdev_create(NULL, TYPE_FW_CFG_IO); + qdev_prop_set_bit(dev, "dma_enabled", false); +- object_property_add_child(OBJECT(ebus), TYPE_FW_CFG, OBJECT(dev), NULL); ++ object_property_add_child(OBJECT(ebus), TYPE_FW_CFG, OBJECT(dev)); + qdev_init_nofail(dev); + memory_region_add_subregion(pci_address_space_io(ebus), BIOS_CFG_IOPORT, + &FW_CFG_IO(dev)->comb_iomem); +diff --git a/hw/ssi/xilinx_spips.c b/hw/ssi/xilinx_spips.c +index 4cfce882ab..e76cf290c8 100644 +--- a/hw/ssi/xilinx_spips.c ++++ b/hw/ssi/xilinx_spips.c +@@ -1360,8 +1360,7 @@ static void xlnx_zynqmp_qspips_init(Object *obj) + object_property_add_link(obj, "stream-connected-dma", TYPE_STREAM_SLAVE, + (Object **)&rq->dma, + object_property_allow_set_link, +- OBJ_PROP_LINK_STRONG, +- NULL); ++ OBJ_PROP_LINK_STRONG); + } + + static int xilinx_spips_post_load(void *opaque, int version_id) +diff --git a/hw/usb/bus.c b/hw/usb/bus.c +index c9a390063f..686f492112 100644 +--- a/hw/usb/bus.c ++++ b/hw/usb/bus.c +@@ -753,12 +753,10 @@ static void usb_device_instance_init(Object *obj) + + if (klass->attached_settable) { + object_property_add_bool(obj, "attached", +- usb_get_attached, usb_set_attached, +- NULL); ++ usb_get_attached, usb_set_attached); + } else { + object_property_add_bool(obj, "attached", +- usb_get_attached, NULL, +- NULL); ++ usb_get_attached, NULL); + } + } + +diff --git a/hw/usb/dev-storage.c b/hw/usb/dev-storage.c +index 5c4b57b06b..4eba47538d 100644 +--- a/hw/usb/dev-storage.c ++++ b/hw/usb/dev-storage.c +@@ -753,7 +753,7 @@ static void usb_msd_instance_init(Object *obj) + { + object_property_add(obj, "bootindex", "int32", + usb_msd_get_bootindex, +- usb_msd_set_bootindex, NULL, NULL, NULL); ++ usb_msd_set_bootindex, NULL, NULL); + object_property_set_int(obj, -1, "bootindex", NULL); + } + +diff --git a/hw/vfio/pci-quirks.c b/hw/vfio/pci-quirks.c +index 2d348f8237..3bd05fed12 100644 +--- a/hw/vfio/pci-quirks.c ++++ b/hw/vfio/pci-quirks.c +@@ -1634,7 +1634,7 @@ int vfio_pci_nvidia_v100_ram_init(VFIOPCIDevice *vdev, Error **errp) + + object_property_add(OBJECT(vdev), "nvlink2-tgt", "uint64", + vfio_pci_nvlink2_get_tgt, NULL, NULL, +- (void *) (uintptr_t) cap->tgt, NULL); ++ (void *) (uintptr_t) cap->tgt); + trace_vfio_pci_nvidia_gpu_setup_quirk(vdev->vbasedev.name, cap->tgt, + nv2reg->size); + free_exit: +@@ -1695,13 +1695,13 @@ int vfio_pci_nvlink2_init(VFIOPCIDevice *vdev, Error **errp) + + object_property_add(OBJECT(vdev), "nvlink2-tgt", "uint64", + vfio_pci_nvlink2_get_tgt, NULL, NULL, +- (void *) (uintptr_t) captgt->tgt, NULL); ++ (void *) (uintptr_t) captgt->tgt); + trace_vfio_pci_nvlink2_setup_quirk_ssatgt(vdev->vbasedev.name, captgt->tgt, + atsdreg->size); + + object_property_add(OBJECT(vdev), "nvlink2-link-speed", "uint32", + vfio_pci_nvlink2_get_link_speed, NULL, NULL, +- (void *) (uintptr_t) capspeed->link_speed, NULL); ++ (void *) (uintptr_t) capspeed->link_speed); + trace_vfio_pci_nvlink2_setup_quirk_lnkspd(vdev->vbasedev.name, + capspeed->link_speed); + free_exit: +diff --git a/hw/virtio/vhost-scsi-pci.c b/hw/virtio/vhost-scsi-pci.c +index 5dce640eaf..5da6bb6449 100644 +--- a/hw/virtio/vhost-scsi-pci.c ++++ b/hw/virtio/vhost-scsi-pci.c +@@ -78,7 +78,7 @@ static void vhost_scsi_pci_instance_init(Object *obj) + virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev), + TYPE_VHOST_SCSI); + object_property_add_alias(obj, "bootindex", OBJECT(&dev->vdev), +- "bootindex", &error_abort); ++ "bootindex"); + } + + static const VirtioPCIDeviceTypeInfo vhost_scsi_pci_info = { +diff --git a/hw/virtio/vhost-user-blk-pci.c b/hw/virtio/vhost-user-blk-pci.c +index 8d3d766427..58d7c31735 100644 +--- a/hw/virtio/vhost-user-blk-pci.c ++++ b/hw/virtio/vhost-user-blk-pci.c +@@ -84,7 +84,7 @@ static void vhost_user_blk_pci_instance_init(Object *obj) + virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev), + TYPE_VHOST_USER_BLK); + object_property_add_alias(obj, "bootindex", OBJECT(&dev->vdev), +- "bootindex", &error_abort); ++ "bootindex"); + } + + static const VirtioPCIDeviceTypeInfo vhost_user_blk_pci_info = { +diff --git a/hw/virtio/vhost-user-input-pci.c b/hw/virtio/vhost-user-input-pci.c +index ae9cff9aed..0a50015599 100644 +--- a/hw/virtio/vhost-user-input-pci.c ++++ b/hw/virtio/vhost-user-input-pci.c +@@ -31,8 +31,7 @@ static void vhost_user_input_pci_instance_init(Object *obj) + TYPE_VHOST_USER_INPUT); + + object_property_add_alias(obj, "chardev", +- OBJECT(&dev->vhi), "chardev", +- &error_abort); ++ OBJECT(&dev->vhi), "chardev"); + } + + static const VirtioPCIDeviceTypeInfo vhost_user_input_pci_info = { +diff --git a/hw/virtio/vhost-user-scsi-pci.c b/hw/virtio/vhost-user-scsi-pci.c +index 32febb2daa..6f3375fe55 100644 +--- a/hw/virtio/vhost-user-scsi-pci.c ++++ b/hw/virtio/vhost-user-scsi-pci.c +@@ -84,7 +84,7 @@ static void vhost_user_scsi_pci_instance_init(Object *obj) + virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev), + TYPE_VHOST_USER_SCSI); + object_property_add_alias(obj, "bootindex", OBJECT(&dev->vdev), +- "bootindex", &error_abort); ++ "bootindex"); + } + + static const VirtioPCIDeviceTypeInfo vhost_user_scsi_pci_info = { +diff --git a/hw/virtio/virtio-balloon-pci.c b/hw/virtio/virtio-balloon-pci.c +index 56962aeb43..cc25df0a3d 100644 +--- a/hw/virtio/virtio-balloon-pci.c ++++ b/hw/virtio/virtio-balloon-pci.c +@@ -73,10 +73,10 @@ static void virtio_balloon_pci_instance_init(Object *obj) + virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev), + TYPE_VIRTIO_BALLOON); + object_property_add_alias(obj, "guest-stats", OBJECT(&dev->vdev), +- "guest-stats", &error_abort); ++ "guest-stats"); + object_property_add_alias(obj, "guest-stats-polling-interval", + OBJECT(&dev->vdev), +- "guest-stats-polling-interval", &error_abort); ++ "guest-stats-polling-interval"); + } + + static const VirtioPCIDeviceTypeInfo virtio_balloon_pci_info = { +diff --git a/hw/virtio/virtio-balloon.c b/hw/virtio/virtio-balloon.c +index a4729f7fc9..6d3ddf6449 100644 +--- a/hw/virtio/virtio-balloon.c ++++ b/hw/virtio/virtio-balloon.c +@@ -893,12 +893,12 @@ static void virtio_balloon_instance_init(Object *obj) + VirtIOBalloon *s = VIRTIO_BALLOON(obj); + + object_property_add(obj, "guest-stats", "guest statistics", +- balloon_stats_get_all, NULL, NULL, s, NULL); ++ balloon_stats_get_all, NULL, NULL, s); + + object_property_add(obj, "guest-stats-polling-interval", "int", + balloon_stats_get_poll_interval, + balloon_stats_set_poll_interval, +- NULL, s, NULL); ++ NULL, s); + } + + static const VMStateDescription vmstate_virtio_balloon = { +diff --git a/hw/virtio/virtio-blk-pci.c b/hw/virtio/virtio-blk-pci.c +index efb2c22a1d..28838fa958 100644 +--- a/hw/virtio/virtio-blk-pci.c ++++ b/hw/virtio/virtio-blk-pci.c +@@ -81,7 +81,7 @@ static void virtio_blk_pci_instance_init(Object *obj) + virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev), + TYPE_VIRTIO_BLK); + object_property_add_alias(obj, "bootindex", OBJECT(&dev->vdev), +- "bootindex", &error_abort); ++ "bootindex"); + } + + static const VirtioPCIDeviceTypeInfo virtio_blk_pci_info = { +diff --git a/hw/virtio/virtio-net-pci.c b/hw/virtio/virtio-net-pci.c +index 5ca71d4c34..ea43040f7b 100644 +--- a/hw/virtio/virtio-net-pci.c ++++ b/hw/virtio/virtio-net-pci.c +@@ -79,7 +79,7 @@ static void virtio_net_pci_instance_init(Object *obj) + virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev), + TYPE_VIRTIO_NET); + object_property_add_alias(obj, "bootindex", OBJECT(&dev->vdev), +- "bootindex", &error_abort); ++ "bootindex"); + } + + static const VirtioPCIDeviceTypeInfo virtio_net_pci_info = { +diff --git a/hw/virtio/virtio-rng.c b/hw/virtio/virtio-rng.c +index 1e363ad07b..672619c780 100644 +--- a/hw/virtio/virtio-rng.c ++++ b/hw/virtio/virtio-rng.c +@@ -203,7 +203,7 @@ static void virtio_rng_device_realize(DeviceState *dev, Error **errp) + } + + object_property_add_child(OBJECT(dev), "default-backend", +- default_backend, &error_abort); ++ default_backend); + + /* The child property took a reference, we can safely drop ours now */ + object_unref(default_backend); +diff --git a/hw/xen/xen-common.c b/hw/xen/xen-common.c +index adaab81ce0..70564cc952 100644 +--- a/hw/xen/xen-common.c ++++ b/hw/xen/xen-common.c +@@ -198,8 +198,7 @@ static void xen_accel_class_init(ObjectClass *oc, void *data) + compat_props_add(ac->compat_props, compat, G_N_ELEMENTS(compat)); + + object_class_property_add_bool(oc, "igd-passthru", +- xen_get_igd_gfx_passthru, xen_set_igd_gfx_passthru, +- &error_abort); ++ xen_get_igd_gfx_passthru, xen_set_igd_gfx_passthru); + object_class_property_set_description(oc, "igd-passthru", + "Set on/off to enable/disable igd passthrou"); + } +diff --git a/include/qom/object.h b/include/qom/object.h +index 1f0386a231..990e28e408 100644 +--- a/include/qom/object.h ++++ b/include/qom/object.h +@@ -1036,7 +1036,6 @@ void object_unref(Object *obj); + * meant to allow a property to free its opaque upon object + * destruction. This may be NULL. + * @opaque: an opaque pointer to pass to the callbacks for the property +- * @errp: returns an error if this function fails + * + * Returns: The #ObjectProperty; this can be used to set the @resolve + * callback for child and link properties. +@@ -1046,7 +1045,7 @@ ObjectProperty *object_property_add(Object *obj, const char *name, + ObjectPropertyAccessor *get, + ObjectPropertyAccessor *set, + ObjectPropertyRelease *release, +- void *opaque, Error **errp); ++ void *opaque); + + void object_property_del(Object *obj, const char *name, Error **errp); + +@@ -1055,7 +1054,7 @@ ObjectProperty *object_class_property_add(ObjectClass *klass, const char *name, + ObjectPropertyAccessor *get, + ObjectPropertyAccessor *set, + ObjectPropertyRelease *release, +- void *opaque, Error **errp); ++ void *opaque); + + /** + * object_property_set_default_bool: +@@ -1480,7 +1479,6 @@ Object *object_resolve_path_component(Object *parent, const char *part); + * @obj: the object to add a property to + * @name: the name of the property + * @child: the child object +- * @errp: if an error occurs, a pointer to an area to store the error + * + * Child properties form the composition tree. All objects need to be a child + * of another object. Objects can only be a child of one object. +@@ -1495,7 +1493,7 @@ Object *object_resolve_path_component(Object *parent, const char *part); + * Returns: The newly added property on success, or %NULL on failure. + */ + ObjectProperty *object_property_add_child(Object *obj, const char *name, +- Object *child, Error **errp); ++ Object *child); + + typedef enum { + /* Unref the link pointer when the property is deleted */ +@@ -1524,7 +1522,6 @@ void object_property_allow_set_link(const Object *, const char *, + * @targetp: a pointer to where the link object reference is stored + * @check: callback to veto setting or NULL if the property is read-only + * @flags: additional options for the link +- * @errp: if an error occurs, a pointer to an area to store the error + * + * Links establish relationships between objects. Links are unidirectional + * although two links can be combined to form a bidirectional relationship +@@ -1551,16 +1548,14 @@ ObjectProperty *object_property_add_link(Object *obj, const char *name, + const char *type, Object **targetp, + void (*check)(const Object *obj, const char *name, + Object *val, Error **errp), +- ObjectPropertyLinkFlags flags, +- Error **errp); ++ ObjectPropertyLinkFlags flags); + + ObjectProperty *object_class_property_add_link(ObjectClass *oc, + const char *name, + const char *type, ptrdiff_t offset, + void (*check)(const Object *obj, const char *name, + Object *val, Error **errp), +- ObjectPropertyLinkFlags flags, +- Error **errp); ++ ObjectPropertyLinkFlags flags); + + /** + * object_property_add_str: +@@ -1569,7 +1564,6 @@ ObjectProperty *object_class_property_add_link(ObjectClass *oc, + * @get: the getter or NULL if the property is write-only. This function must + * return a string to be freed by g_free(). + * @set: the setter or NULL if the property is read-only +- * @errp: if an error occurs, a pointer to an area to store the error + * + * Add a string property using getters/setters. This function will add a + * property of type 'string'. +@@ -1578,15 +1572,13 @@ ObjectProperty *object_class_property_add_link(ObjectClass *oc, + */ + ObjectProperty *object_property_add_str(Object *obj, const char *name, + char *(*get)(Object *, Error **), +- void (*set)(Object *, const char *, Error **), +- Error **errp); ++ void (*set)(Object *, const char *, Error **)); + + ObjectProperty *object_class_property_add_str(ObjectClass *klass, + const char *name, + char *(*get)(Object *, Error **), + void (*set)(Object *, const char *, +- Error **), +- Error **errp); ++ Error **)); + + /** + * object_property_add_bool: +@@ -1594,7 +1586,6 @@ ObjectProperty *object_class_property_add_str(ObjectClass *klass, + * @name: the name of the property + * @get: the getter or NULL if the property is write-only. + * @set: the setter or NULL if the property is read-only +- * @errp: if an error occurs, a pointer to an area to store the error + * + * Add a bool property using getters/setters. This function will add a + * property of type 'bool'. +@@ -1603,14 +1594,12 @@ ObjectProperty *object_class_property_add_str(ObjectClass *klass, + */ + ObjectProperty *object_property_add_bool(Object *obj, const char *name, + bool (*get)(Object *, Error **), +- void (*set)(Object *, bool, Error **), +- Error **errp); ++ void (*set)(Object *, bool, Error **)); + + ObjectProperty *object_class_property_add_bool(ObjectClass *klass, + const char *name, + bool (*get)(Object *, Error **), +- void (*set)(Object *, bool, Error **), +- Error **errp); ++ void (*set)(Object *, bool, Error **)); + + /** + * object_property_add_enum: +@@ -1619,7 +1608,6 @@ ObjectProperty *object_class_property_add_bool(ObjectClass *klass, + * @typename: the name of the enum data type + * @get: the getter or %NULL if the property is write-only. + * @set: the setter or %NULL if the property is read-only +- * @errp: if an error occurs, a pointer to an area to store the error + * + * Add an enum property using getters/setters. This function will add a + * property of type '@typename'. +@@ -1630,23 +1618,20 @@ ObjectProperty *object_property_add_enum(Object *obj, const char *name, + const char *typename, + const QEnumLookup *lookup, + int (*get)(Object *, Error **), +- void (*set)(Object *, int, Error **), +- Error **errp); ++ void (*set)(Object *, int, Error **)); + + ObjectProperty *object_class_property_add_enum(ObjectClass *klass, + const char *name, + const char *typename, + const QEnumLookup *lookup, + int (*get)(Object *, Error **), +- void (*set)(Object *, int, Error **), +- Error **errp); ++ void (*set)(Object *, int, Error **)); + + /** + * object_property_add_tm: + * @obj: the object to add a property to + * @name: the name of the property + * @get: the getter or NULL if the property is write-only. +- * @errp: if an error occurs, a pointer to an area to store the error + * + * Add a read-only struct tm valued property using a getter function. + * This function will add a property of type 'struct tm'. +@@ -1654,13 +1639,11 @@ ObjectProperty *object_class_property_add_enum(ObjectClass *klass, + * Returns: The newly added property on success, or %NULL on failure. + */ + ObjectProperty *object_property_add_tm(Object *obj, const char *name, +- void (*get)(Object *, struct tm *, Error **), +- Error **errp); ++ void (*get)(Object *, struct tm *, Error **)); + + ObjectProperty *object_class_property_add_tm(ObjectClass *klass, +- const char *name, +- void (*get)(Object *, struct tm *, Error **), +- Error **errp); ++ const char *name, ++ void (*get)(Object *, struct tm *, Error **)); + + typedef enum { + /* Automatically add a getter to the property */ +@@ -1677,7 +1660,6 @@ typedef enum { + * @name: the name of the property + * @v: pointer to value + * @flags: bitwise-or'd ObjectPropertyFlags +- * @errp: if an error occurs, a pointer to an area to store the error + * + * Add an integer property in memory. This function will add a + * property of type 'uint8'. +@@ -1685,14 +1667,13 @@ typedef enum { + * Returns: The newly added property on success, or %NULL on failure. + */ + ObjectProperty *object_property_add_uint8_ptr(Object *obj, const char *name, +- const uint8_t *v, ObjectPropertyFlags flags, +- Error **errp); ++ const uint8_t *v, ++ ObjectPropertyFlags flags); + + ObjectProperty *object_class_property_add_uint8_ptr(ObjectClass *klass, + const char *name, + const uint8_t *v, +- ObjectPropertyFlags flags, +- Error **errp); ++ ObjectPropertyFlags flags); + + /** + * object_property_add_uint16_ptr: +@@ -1700,7 +1681,6 @@ ObjectProperty *object_class_property_add_uint8_ptr(ObjectClass *klass, + * @name: the name of the property + * @v: pointer to value + * @flags: bitwise-or'd ObjectPropertyFlags +- * @errp: if an error occurs, a pointer to an area to store the error + * + * Add an integer property in memory. This function will add a + * property of type 'uint16'. +@@ -1709,14 +1689,12 @@ ObjectProperty *object_class_property_add_uint8_ptr(ObjectClass *klass, + */ + ObjectProperty *object_property_add_uint16_ptr(Object *obj, const char *name, + const uint16_t *v, +- ObjectPropertyFlags flags, +- Error **errp); ++ ObjectPropertyFlags flags); + + ObjectProperty *object_class_property_add_uint16_ptr(ObjectClass *klass, + const char *name, + const uint16_t *v, +- ObjectPropertyFlags flags, +- Error **errp); ++ ObjectPropertyFlags flags); + + /** + * object_property_add_uint32_ptr: +@@ -1724,7 +1702,6 @@ ObjectProperty *object_class_property_add_uint16_ptr(ObjectClass *klass, + * @name: the name of the property + * @v: pointer to value + * @flags: bitwise-or'd ObjectPropertyFlags +- * @errp: if an error occurs, a pointer to an area to store the error + * + * Add an integer property in memory. This function will add a + * property of type 'uint32'. +@@ -1733,14 +1710,12 @@ ObjectProperty *object_class_property_add_uint16_ptr(ObjectClass *klass, + */ + ObjectProperty *object_property_add_uint32_ptr(Object *obj, const char *name, + const uint32_t *v, +- ObjectPropertyFlags flags, +- Error **errp); ++ ObjectPropertyFlags flags); + + ObjectProperty *object_class_property_add_uint32_ptr(ObjectClass *klass, + const char *name, + const uint32_t *v, +- ObjectPropertyFlags flags, +- Error **errp); ++ ObjectPropertyFlags flags); + + /** + * object_property_add_uint64_ptr: +@@ -1748,7 +1723,6 @@ ObjectProperty *object_class_property_add_uint32_ptr(ObjectClass *klass, + * @name: the name of the property + * @v: pointer to value + * @flags: bitwise-or'd ObjectPropertyFlags +- * @errp: if an error occurs, a pointer to an area to store the error + * + * Add an integer property in memory. This function will add a + * property of type 'uint64'. +@@ -1757,14 +1731,12 @@ ObjectProperty *object_class_property_add_uint32_ptr(ObjectClass *klass, + */ + ObjectProperty *object_property_add_uint64_ptr(Object *obj, const char *name, + const uint64_t *v, +- ObjectPropertyFlags flags, +- Error **Errp); ++ ObjectPropertyFlags flags); + + ObjectProperty *object_class_property_add_uint64_ptr(ObjectClass *klass, + const char *name, + const uint64_t *v, +- ObjectPropertyFlags flags, +- Error **Errp); ++ ObjectPropertyFlags flags); + + /** + * object_property_add_alias: +@@ -1772,7 +1744,6 @@ ObjectProperty *object_class_property_add_uint64_ptr(ObjectClass *klass, + * @name: the name of the property + * @target_obj: the object to forward property access to + * @target_name: the name of the property on the forwarded object +- * @errp: if an error occurs, a pointer to an area to store the error + * + * Add an alias for a property on an object. This function will add a property + * of the same type as the forwarded property. +@@ -1785,15 +1756,13 @@ ObjectProperty *object_class_property_add_uint64_ptr(ObjectClass *klass, + * Returns: The newly added property on success, or %NULL on failure. + */ + ObjectProperty *object_property_add_alias(Object *obj, const char *name, +- Object *target_obj, const char *target_name, +- Error **errp); ++ Object *target_obj, const char *target_name); + + /** + * object_property_add_const_link: + * @obj: the object to add a property to + * @name: the name of the property + * @target: the object to be referred by the link +- * @errp: if an error occurs, a pointer to an area to store the error + * + * Add an unmodifiable link for a property on an object. This function will + * add a property of type link where TYPE is the type of @target. +@@ -1806,7 +1775,7 @@ ObjectProperty *object_property_add_alias(Object *obj, const char *name, + * Returns: The newly added property on success, or %NULL on failure. + */ + ObjectProperty *object_property_add_const_link(Object *obj, const char *name, +- Object *target, Error **errp); ++ Object *target); + + /** + * object_property_set_description: +diff --git a/iothread.c b/iothread.c +index 7130be58e3..cb082b9b26 100644 +--- a/iothread.c ++++ b/iothread.c +@@ -276,15 +276,15 @@ static void iothread_class_init(ObjectClass *klass, void *class_data) + object_class_property_add(klass, "poll-max-ns", "int", + iothread_get_poll_param, + iothread_set_poll_param, +- NULL, &poll_max_ns_info, &error_abort); ++ NULL, &poll_max_ns_info); + object_class_property_add(klass, "poll-grow", "int", + iothread_get_poll_param, + iothread_set_poll_param, +- NULL, &poll_grow_info, &error_abort); ++ NULL, &poll_grow_info); + object_class_property_add(klass, "poll-shrink", "int", + iothread_get_poll_param, + iothread_set_poll_param, +- NULL, &poll_shrink_info, &error_abort); ++ NULL, &poll_shrink_info); + } + + static const TypeInfo iothread_info = { +diff --git a/memory.c b/memory.c +index 936c1b23d4..fd6f3d6aca 100644 +--- a/memory.c ++++ b/memory.c +@@ -1154,7 +1154,7 @@ static void memory_region_do_init(MemoryRegion *mr, + owner = container_get(qdev_get_machine(), "/unattached"); + } + +- object_property_add_child(owner, name_array, OBJECT(mr), &error_abort); ++ object_property_add_child(owner, name_array, OBJECT(mr)); + object_unref(OBJECT(mr)); + g_free(name_array); + g_free(escaped_name); +@@ -1230,19 +1230,19 @@ static void memory_region_initfn(Object *obj) + "link<" TYPE_MEMORY_REGION ">", + memory_region_get_container, + NULL, /* memory_region_set_container */ +- NULL, NULL, &error_abort); ++ NULL, NULL); + op->resolve = memory_region_resolve_container; + + object_property_add_uint64_ptr(OBJECT(mr), "addr", +- &mr->addr, OBJ_PROP_FLAG_READ, &error_abort); ++ &mr->addr, OBJ_PROP_FLAG_READ); + object_property_add(OBJECT(mr), "priority", "uint32", + memory_region_get_priority, + NULL, /* memory_region_set_priority */ +- NULL, NULL, &error_abort); ++ NULL, NULL); + object_property_add(OBJECT(mr), "size", "uint64", + memory_region_get_size, + NULL, /* memory_region_set_size, */ +- NULL, NULL, &error_abort); ++ NULL, NULL); + } + + static void iommu_memory_region_initfn(Object *obj) +diff --git a/net/can/can_host.c b/net/can/can_host.c +index 1dfaf0ced0..be4547d913 100644 +--- a/net/can/can_host.c ++++ b/net/can/can_host.c +@@ -79,8 +79,7 @@ static void can_host_instance_init(Object *obj) + object_property_add_link(obj, "canbus", TYPE_CAN_BUS, + (Object **)&ch->bus, + object_property_allow_set_link, +- OBJ_PROP_LINK_STRONG, +- &error_abort); ++ OBJ_PROP_LINK_STRONG); + } + + static void can_host_class_init(ObjectClass *klass, +diff --git a/net/can/can_socketcan.c b/net/can/can_socketcan.c +index 807f31fcde..b7ef63ec0e 100644 +--- a/net/can/can_socketcan.c ++++ b/net/can/can_socketcan.c +@@ -266,8 +266,7 @@ static void can_host_socketcan_class_init(ObjectClass *klass, + + object_class_property_add_str(klass, "if", + can_host_socketcan_get_if, +- can_host_socketcan_set_if, +- &error_abort); ++ can_host_socketcan_set_if); + chc->connect = can_host_socketcan_connect; + chc->disconnect = can_host_socketcan_disconnect; + } +diff --git a/net/colo-compare.c b/net/colo-compare.c +index 10c0239f9d..c07e7c1c09 100644 +--- a/net/colo-compare.c ++++ b/net/colo-compare.c +@@ -1245,34 +1245,30 @@ static void colo_compare_init(Object *obj) + CompareState *s = COLO_COMPARE(obj); + + object_property_add_str(obj, "primary_in", +- compare_get_pri_indev, compare_set_pri_indev, +- NULL); ++ compare_get_pri_indev, compare_set_pri_indev); + object_property_add_str(obj, "secondary_in", +- compare_get_sec_indev, compare_set_sec_indev, +- NULL); ++ compare_get_sec_indev, compare_set_sec_indev); + object_property_add_str(obj, "outdev", +- compare_get_outdev, compare_set_outdev, +- NULL); ++ compare_get_outdev, compare_set_outdev); + object_property_add_link(obj, "iothread", TYPE_IOTHREAD, + (Object **)&s->iothread, + object_property_allow_set_link, +- OBJ_PROP_LINK_STRONG, NULL); ++ OBJ_PROP_LINK_STRONG); + /* This parameter just for Xen COLO */ + object_property_add_str(obj, "notify_dev", +- compare_get_notify_dev, compare_set_notify_dev, +- NULL); ++ compare_get_notify_dev, compare_set_notify_dev); + + object_property_add(obj, "compare_timeout", "uint32", + compare_get_timeout, +- compare_set_timeout, NULL, NULL, NULL); ++ compare_set_timeout, NULL, NULL); + + object_property_add(obj, "expired_scan_cycle", "uint32", + compare_get_expired_scan_cycle, +- compare_set_expired_scan_cycle, NULL, NULL, NULL); ++ compare_set_expired_scan_cycle, NULL, NULL); + + s->vnet_hdr = false; + object_property_add_bool(obj, "vnet_hdr_support", compare_get_vnet_hdr, +- compare_set_vnet_hdr, NULL); ++ compare_set_vnet_hdr); + } + + static void colo_compare_finalize(Object *obj) +diff --git a/net/dump.c b/net/dump.c +index 23b3628dde..61389e7dad 100644 +--- a/net/dump.c ++++ b/net/dump.c +@@ -232,9 +232,9 @@ static void filter_dump_instance_init(Object *obj) + nfds->maxlen = 65536; + + object_property_add(obj, "maxlen", "uint32", filter_dump_get_maxlen, +- filter_dump_set_maxlen, NULL, NULL, NULL); ++ filter_dump_set_maxlen, NULL, NULL); + object_property_add_str(obj, "file", file_dump_get_filename, +- file_dump_set_filename, NULL); ++ file_dump_set_filename); + } + + static void filter_dump_instance_finalize(Object *obj) +diff --git a/net/filter-buffer.c b/net/filter-buffer.c +index 12e0254287..93050f86cf 100644 +--- a/net/filter-buffer.c ++++ b/net/filter-buffer.c +@@ -192,7 +192,7 @@ static void filter_buffer_init(Object *obj) + { + object_property_add(obj, "interval", "uint32", + filter_buffer_get_interval, +- filter_buffer_set_interval, NULL, NULL, NULL); ++ filter_buffer_set_interval, NULL, NULL); + } + + static const TypeInfo filter_buffer_info = { +diff --git a/net/filter-mirror.c b/net/filter-mirror.c +index d83e815545..e9379ce248 100644 +--- a/net/filter-mirror.c ++++ b/net/filter-mirror.c +@@ -392,12 +392,12 @@ static void filter_mirror_init(Object *obj) + MirrorState *s = FILTER_MIRROR(obj); + + object_property_add_str(obj, "outdev", filter_mirror_get_outdev, +- filter_mirror_set_outdev, NULL); ++ filter_mirror_set_outdev); + + s->vnet_hdr = false; + object_property_add_bool(obj, "vnet_hdr_support", + filter_mirror_get_vnet_hdr, +- filter_mirror_set_vnet_hdr, NULL); ++ filter_mirror_set_vnet_hdr); + } + + static void filter_redirector_init(Object *obj) +@@ -405,14 +405,14 @@ static void filter_redirector_init(Object *obj) + MirrorState *s = FILTER_REDIRECTOR(obj); + + object_property_add_str(obj, "indev", filter_redirector_get_indev, +- filter_redirector_set_indev, NULL); ++ filter_redirector_set_indev); + object_property_add_str(obj, "outdev", filter_redirector_get_outdev, +- filter_redirector_set_outdev, NULL); ++ filter_redirector_set_outdev); + + s->vnet_hdr = false; + object_property_add_bool(obj, "vnet_hdr_support", + filter_redirector_get_vnet_hdr, +- filter_redirector_set_vnet_hdr, NULL); ++ filter_redirector_set_vnet_hdr); + } + + static void filter_mirror_fini(Object *obj) +diff --git a/net/filter-rewriter.c b/net/filter-rewriter.c +index 31da08a2f4..1aaad101b6 100644 +--- a/net/filter-rewriter.c ++++ b/net/filter-rewriter.c +@@ -413,7 +413,7 @@ static void filter_rewriter_init(Object *obj) + s->failover_mode = FAILOVER_MODE_OFF; + object_property_add_bool(obj, "vnet_hdr_support", + filter_rewriter_get_vnet_hdr, +- filter_rewriter_set_vnet_hdr, NULL); ++ filter_rewriter_set_vnet_hdr); + } + + static void colo_rewriter_class_init(ObjectClass *oc, void *data) +diff --git a/net/filter.c b/net/filter.c +index 8221666263..caf6443655 100644 +--- a/net/filter.c ++++ b/net/filter.c +@@ -214,21 +214,16 @@ static void netfilter_init(Object *obj) + nf->position = g_strdup("tail"); + + object_property_add_str(obj, "netdev", +- netfilter_get_netdev_id, netfilter_set_netdev_id, +- NULL); ++ netfilter_get_netdev_id, netfilter_set_netdev_id); + object_property_add_enum(obj, "queue", "NetFilterDirection", + &NetFilterDirection_lookup, +- netfilter_get_direction, netfilter_set_direction, +- NULL); ++ netfilter_get_direction, netfilter_set_direction); + object_property_add_str(obj, "status", +- netfilter_get_status, netfilter_set_status, +- NULL); ++ netfilter_get_status, netfilter_set_status); + object_property_add_str(obj, "position", +- netfilter_get_position, netfilter_set_position, +- NULL); ++ netfilter_get_position, netfilter_set_position); + object_property_add_str(obj, "insert", +- netfilter_get_insert, netfilter_set_insert, +- NULL); ++ netfilter_get_insert, netfilter_set_insert); + } + + static void netfilter_complete(UserCreatable *uc, Error **errp) +diff --git a/qdev-monitor.c b/qdev-monitor.c +index 56cee1483f..a4735d3bb1 100644 +--- a/qdev-monitor.c ++++ b/qdev-monitor.c +@@ -562,12 +562,12 @@ void qdev_set_id(DeviceState *dev, const char *id) + + if (dev->id) { + object_property_add_child(qdev_get_peripheral(), dev->id, +- OBJECT(dev), NULL); ++ OBJECT(dev)); + } else { + static int anon_count; + gchar *name = g_strdup_printf("device[%d]", anon_count++); + object_property_add_child(qdev_get_peripheral_anon(), name, +- OBJECT(dev), NULL); ++ OBJECT(dev)); + g_free(name); + } + } +diff --git a/qom/container.c b/qom/container.c +index e635e8ee76..14e7ae485b 100644 +--- a/qom/container.c ++++ b/qom/container.c +@@ -39,7 +39,7 @@ Object *container_get(Object *root, const char *path) + child = object_resolve_path_component(obj, parts[i]); + if (!child) { + child = object_new("container"); +- object_property_add_child(obj, parts[i], child, NULL); ++ object_property_add_child(obj, parts[i], child); + object_unref(child); + } + } +diff --git a/qom/object.c b/qom/object.c +index 58a6ec9b1b..23f481ca46 100644 +--- a/qom/object.c ++++ b/qom/object.c +@@ -557,10 +557,7 @@ void object_initialize_childv(Object *parentobj, const char *propname, + goto out; + } + +- object_property_add_child(parentobj, propname, obj, &local_err); +- if (local_err) { +- goto out; +- } ++ object_property_add_child(parentobj, propname, obj); + + uc = (UserCreatable *)object_dynamic_cast(obj, TYPE_USER_CREATABLE); + if (uc) { +@@ -745,10 +742,7 @@ Object *object_new_with_propv(const char *typename, + } + + if (id != NULL) { +- object_property_add_child(parent, id, obj, &local_err); +- if (local_err) { +- goto error; +- } ++ object_property_add_child(parent, id, obj); + } + + uc = (UserCreatable *)object_dynamic_cast(obj, TYPE_USER_CREATABLE); +@@ -1129,12 +1123,12 @@ void object_unref(Object *obj) + } + } + +-ObjectProperty * +-object_property_add(Object *obj, const char *name, const char *type, +- ObjectPropertyAccessor *get, +- ObjectPropertyAccessor *set, +- ObjectPropertyRelease *release, +- void *opaque, Error **errp) ++static ObjectProperty * ++object_property_try_add(Object *obj, const char *name, const char *type, ++ ObjectPropertyAccessor *get, ++ ObjectPropertyAccessor *set, ++ ObjectPropertyRelease *release, ++ void *opaque, Error **errp) + { + ObjectProperty *prop; + size_t name_len = strlen(name); +@@ -1148,8 +1142,8 @@ object_property_add(Object *obj, const char *name, const char *type, + for (i = 0; ; ++i) { + char *full_name = g_strdup_printf("%s[%d]", name_no_array, i); + +- ret = object_property_add(obj, full_name, type, get, set, +- release, opaque, NULL); ++ ret = object_property_try_add(obj, full_name, type, get, set, ++ release, opaque, NULL); + g_free(full_name); + if (ret) { + break; +@@ -1179,6 +1173,17 @@ object_property_add(Object *obj, const char *name, const char *type, + return prop; + } + ++ObjectProperty * ++object_property_add(Object *obj, const char *name, const char *type, ++ ObjectPropertyAccessor *get, ++ ObjectPropertyAccessor *set, ++ ObjectPropertyRelease *release, ++ void *opaque) ++{ ++ return object_property_try_add(obj, name, type, get, set, release, ++ opaque, &error_abort); ++} ++ + ObjectProperty * + object_class_property_add(ObjectClass *klass, + const char *name, +@@ -1186,16 +1191,11 @@ object_class_property_add(ObjectClass *klass, + ObjectPropertyAccessor *get, + ObjectPropertyAccessor *set, + ObjectPropertyRelease *release, +- void *opaque, +- Error **errp) ++ void *opaque) + { + ObjectProperty *prop; + +- if (object_class_property_find(klass, name, NULL) != NULL) { +- error_setg(errp, "attempt to add duplicate property '%s' to class (type '%s')", +- name, object_class_get_name(klass)); +- return NULL; +- } ++ assert(!object_class_property_find(klass, name, NULL)); + + prop = g_malloc0(sizeof(*prop)); + +@@ -1648,24 +1648,17 @@ static void object_finalize_child_property(Object *obj, const char *name, + + ObjectProperty * + object_property_add_child(Object *obj, const char *name, +- Object *child, Error **errp) ++ Object *child) + { + g_autofree char *type = NULL; + ObjectProperty *op; + +- if (child->parent != NULL) { +- error_setg(errp, "child object is already parented"); +- return NULL; +- } ++ assert(!child->parent); + + type = g_strdup_printf("child<%s>", object_get_typename(OBJECT(child))); + + op = object_property_add(obj, name, type, object_get_child_property, NULL, +- object_finalize_child_property, child, errp); +- if (!op) { +- return NULL; +- } +- ++ object_finalize_child_property, child); + op->resolve = object_resolve_child_property; + object_ref(child); + child->parent = obj; +@@ -1821,8 +1814,7 @@ object_add_link_prop(Object *obj, const char *name, + const char *type, void *ptr, + void (*check)(const Object *, const char *, + Object *, Error **), +- ObjectPropertyLinkFlags flags, +- Error **errp) ++ ObjectPropertyLinkFlags flags) + { + LinkProperty *prop = g_malloc(sizeof(*prop)); + g_autofree char *full_type = NULL; +@@ -1842,13 +1834,7 @@ object_add_link_prop(Object *obj, const char *name, + object_get_link_property, + check ? object_set_link_property : NULL, + object_release_link_property, +- prop, +- errp); +- if (!op) { +- g_free(prop); +- return NULL; +- } +- ++ prop); + op->resolve = object_resolve_link_property; + return op; + } +@@ -1858,11 +1844,9 @@ object_property_add_link(Object *obj, const char *name, + const char *type, Object **targetp, + void (*check)(const Object *, const char *, + Object *, Error **), +- ObjectPropertyLinkFlags flags, +- Error **errp) ++ ObjectPropertyLinkFlags flags) + { +- return object_add_link_prop(obj, name, type, targetp, check, flags, +- errp); ++ return object_add_link_prop(obj, name, type, targetp, check, flags); + } + + ObjectProperty * +@@ -1871,10 +1855,8 @@ object_class_property_add_link(ObjectClass *oc, + const char *type, ptrdiff_t offset, + void (*check)(const Object *obj, const char *name, + Object *val, Error **errp), +- ObjectPropertyLinkFlags flags, +- Error **errp) ++ ObjectPropertyLinkFlags flags) + { +- Error *local_err = NULL; + LinkProperty *prop = g_new0(LinkProperty, 1); + char *full_type; + ObjectProperty *op; +@@ -1889,28 +1871,21 @@ object_class_property_add_link(ObjectClass *oc, + object_get_link_property, + check ? object_set_link_property : NULL, + object_release_link_property, +- prop, +- &local_err); +- if (local_err) { +- error_propagate(errp, local_err); +- g_free(prop); +- goto out; +- } ++ prop); + + op->resolve = object_resolve_link_property; + +-out: + g_free(full_type); + return op; + } + + ObjectProperty * + object_property_add_const_link(Object *obj, const char *name, +- Object *target, Error **errp) ++ Object *target) + { + return object_add_link_prop(obj, name, + object_get_typename(target), target, +- NULL, OBJ_PROP_LINK_DIRECT, errp); ++ NULL, OBJ_PROP_LINK_DIRECT); + } + + char *object_get_canonical_path_component(Object *obj) +@@ -2122,51 +2097,36 @@ static void property_release_str(Object *obj, const char *name, + ObjectProperty * + object_property_add_str(Object *obj, const char *name, + char *(*get)(Object *, Error **), +- void (*set)(Object *, const char *, Error **), +- Error **errp) ++ void (*set)(Object *, const char *, Error **)) + { + StringProperty *prop = g_malloc0(sizeof(*prop)); +- ObjectProperty *op; + + prop->get = get; + prop->set = set; + +- op = object_property_add(obj, name, "string", +- get ? property_get_str : NULL, +- set ? property_set_str : NULL, +- property_release_str, +- prop, errp); +- if (!op) { +- g_free(prop); +- } +- return op; ++ return object_property_add(obj, name, "string", ++ get ? property_get_str : NULL, ++ set ? property_set_str : NULL, ++ property_release_str, ++ prop); + } + + ObjectProperty * + object_class_property_add_str(ObjectClass *klass, const char *name, + char *(*get)(Object *, Error **), + void (*set)(Object *, const char *, +- Error **), +- Error **errp) ++ Error **)) + { +- Error *local_err = NULL; + StringProperty *prop = g_malloc0(sizeof(*prop)); +- ObjectProperty *rv; + + prop->get = get; + prop->set = set; + +- rv = object_class_property_add(klass, name, "string", +- get ? property_get_str : NULL, +- set ? property_set_str : NULL, +- NULL, +- prop, &local_err); +- if (local_err) { +- error_propagate(errp, local_err); +- g_free(prop); +- } +- +- return rv; ++ return object_class_property_add(klass, name, "string", ++ get ? property_get_str : NULL, ++ set ? property_set_str : NULL, ++ NULL, ++ prop); + } + + typedef struct BoolProperty +@@ -2217,50 +2177,35 @@ static void property_release_bool(Object *obj, const char *name, + ObjectProperty * + object_property_add_bool(Object *obj, const char *name, + bool (*get)(Object *, Error **), +- void (*set)(Object *, bool, Error **), +- Error **errp) ++ void (*set)(Object *, bool, Error **)) + { + BoolProperty *prop = g_malloc0(sizeof(*prop)); +- ObjectProperty *op; + + prop->get = get; + prop->set = set; + +- op = object_property_add(obj, name, "bool", +- get ? property_get_bool : NULL, +- set ? property_set_bool : NULL, +- property_release_bool, +- prop, errp); +- if (!op) { +- g_free(prop); +- } +- return op; ++ return object_property_add(obj, name, "bool", ++ get ? property_get_bool : NULL, ++ set ? property_set_bool : NULL, ++ property_release_bool, ++ prop); + } + + ObjectProperty * + object_class_property_add_bool(ObjectClass *klass, const char *name, + bool (*get)(Object *, Error **), +- void (*set)(Object *, bool, Error **), +- Error **errp) ++ void (*set)(Object *, bool, Error **)) + { +- Error *local_err = NULL; + BoolProperty *prop = g_malloc0(sizeof(*prop)); +- ObjectProperty *rv; + + prop->get = get; + prop->set = set; + +- rv = object_class_property_add(klass, name, "bool", +- get ? property_get_bool : NULL, +- set ? property_set_bool : NULL, +- NULL, +- prop, &local_err); +- if (local_err) { +- error_propagate(errp, local_err); +- g_free(prop); +- } +- +- return rv; ++ return object_class_property_add(klass, name, "bool", ++ get ? property_get_bool : NULL, ++ set ? property_set_bool : NULL, ++ NULL, ++ prop); + } + + static void property_get_enum(Object *obj, Visitor *v, const char *name, +@@ -2306,25 +2251,19 @@ object_property_add_enum(Object *obj, const char *name, + const char *typename, + const QEnumLookup *lookup, + int (*get)(Object *, Error **), +- void (*set)(Object *, int, Error **), +- Error **errp) ++ void (*set)(Object *, int, Error **)) + { + EnumProperty *prop = g_malloc(sizeof(*prop)); +- ObjectProperty *op; + + prop->lookup = lookup; + prop->get = get; + prop->set = set; + +- op = object_property_add(obj, name, typename, +- get ? property_get_enum : NULL, +- set ? property_set_enum : NULL, +- property_release_enum, +- prop, errp); +- if (!op) { +- g_free(prop); +- } +- return op; ++ return object_property_add(obj, name, typename, ++ get ? property_get_enum : NULL, ++ set ? property_set_enum : NULL, ++ property_release_enum, ++ prop); + } + + ObjectProperty * +@@ -2332,28 +2271,19 @@ object_class_property_add_enum(ObjectClass *klass, const char *name, + const char *typename, + const QEnumLookup *lookup, + int (*get)(Object *, Error **), +- void (*set)(Object *, int, Error **), +- Error **errp) ++ void (*set)(Object *, int, Error **)) + { +- Error *local_err = NULL; + EnumProperty *prop = g_malloc(sizeof(*prop)); +- ObjectProperty *rv; + + prop->lookup = lookup; + prop->get = get; + prop->set = set; + +- rv = object_class_property_add(klass, name, typename, +- get ? property_get_enum : NULL, +- set ? property_set_enum : NULL, +- NULL, +- prop, &local_err); +- if (local_err) { +- error_propagate(errp, local_err); +- g_free(prop); +- } +- +- return rv; ++ return object_class_property_add(klass, name, typename, ++ get ? property_get_enum : NULL, ++ set ? property_set_enum : NULL, ++ NULL, ++ prop); + } + + typedef struct TMProperty { +@@ -2417,45 +2347,29 @@ static void property_release_tm(Object *obj, const char *name, + + ObjectProperty * + object_property_add_tm(Object *obj, const char *name, +- void (*get)(Object *, struct tm *, Error **), +- Error **errp) ++ void (*get)(Object *, struct tm *, Error **)) + { + TMProperty *prop = g_malloc0(sizeof(*prop)); +- ObjectProperty *op; + + prop->get = get; + +- op = object_property_add(obj, name, "struct tm", +- get ? property_get_tm : NULL, NULL, +- property_release_tm, +- prop, errp); +- if (!op) { +- g_free(prop); +- } +- return op; ++ return object_property_add(obj, name, "struct tm", ++ get ? property_get_tm : NULL, NULL, ++ property_release_tm, ++ prop); + } + + ObjectProperty * + object_class_property_add_tm(ObjectClass *klass, const char *name, +- void (*get)(Object *, struct tm *, Error **), +- Error **errp) ++ void (*get)(Object *, struct tm *, Error **)) + { +- Error *local_err = NULL; + TMProperty *prop = g_malloc0(sizeof(*prop)); +- ObjectProperty *rv; + + prop->get = get; + +- rv = object_class_property_add(klass, name, "struct tm", +- get ? property_get_tm : NULL, NULL, +- NULL, +- prop, &local_err); +- if (local_err) { +- error_propagate(errp, local_err); +- g_free(prop); +- } +- +- return rv; ++ return object_class_property_add(klass, name, "struct tm", ++ get ? property_get_tm : NULL, ++ NULL, NULL, prop); + } + + static char *qdev_get_type(Object *obj, Error **errp) +@@ -2558,8 +2472,7 @@ static void property_set_uint64_ptr(Object *obj, Visitor *v, const char *name, + ObjectProperty * + object_property_add_uint8_ptr(Object *obj, const char *name, + const uint8_t *v, +- ObjectPropertyFlags flags, +- Error **errp) ++ ObjectPropertyFlags flags) + { + ObjectPropertyAccessor *getter = NULL; + ObjectPropertyAccessor *setter = NULL; +@@ -2573,14 +2486,13 @@ object_property_add_uint8_ptr(Object *obj, const char *name, + } + + return object_property_add(obj, name, "uint8", +- getter, setter, NULL, (void *)v, errp); ++ getter, setter, NULL, (void *)v); + } + + ObjectProperty * + object_class_property_add_uint8_ptr(ObjectClass *klass, const char *name, + const uint8_t *v, +- ObjectPropertyFlags flags, +- Error **errp) ++ ObjectPropertyFlags flags) + { + ObjectPropertyAccessor *getter = NULL; + ObjectPropertyAccessor *setter = NULL; +@@ -2594,14 +2506,13 @@ object_class_property_add_uint8_ptr(ObjectClass *klass, const char *name, + } + + return object_class_property_add(klass, name, "uint8", +- getter, setter, NULL, (void *)v, errp); ++ getter, setter, NULL, (void *)v); + } + + ObjectProperty * + object_property_add_uint16_ptr(Object *obj, const char *name, + const uint16_t *v, +- ObjectPropertyFlags flags, +- Error **errp) ++ ObjectPropertyFlags flags) + { + ObjectPropertyAccessor *getter = NULL; + ObjectPropertyAccessor *setter = NULL; +@@ -2615,14 +2526,13 @@ object_property_add_uint16_ptr(Object *obj, const char *name, + } + + return object_property_add(obj, name, "uint16", +- getter, setter, NULL, (void *)v, errp); ++ getter, setter, NULL, (void *)v); + } + + ObjectProperty * + object_class_property_add_uint16_ptr(ObjectClass *klass, const char *name, + const uint16_t *v, +- ObjectPropertyFlags flags, +- Error **errp) ++ ObjectPropertyFlags flags) + { + ObjectPropertyAccessor *getter = NULL; + ObjectPropertyAccessor *setter = NULL; +@@ -2636,14 +2546,13 @@ object_class_property_add_uint16_ptr(ObjectClass *klass, const char *name, + } + + return object_class_property_add(klass, name, "uint16", +- getter, setter, NULL, (void *)v, errp); ++ getter, setter, NULL, (void *)v); + } + + ObjectProperty * + object_property_add_uint32_ptr(Object *obj, const char *name, + const uint32_t *v, +- ObjectPropertyFlags flags, +- Error **errp) ++ ObjectPropertyFlags flags) + { + ObjectPropertyAccessor *getter = NULL; + ObjectPropertyAccessor *setter = NULL; +@@ -2657,14 +2566,13 @@ object_property_add_uint32_ptr(Object *obj, const char *name, + } + + return object_property_add(obj, name, "uint32", +- getter, setter, NULL, (void *)v, errp); ++ getter, setter, NULL, (void *)v); + } + + ObjectProperty * + object_class_property_add_uint32_ptr(ObjectClass *klass, const char *name, + const uint32_t *v, +- ObjectPropertyFlags flags, +- Error **errp) ++ ObjectPropertyFlags flags) + { + ObjectPropertyAccessor *getter = NULL; + ObjectPropertyAccessor *setter = NULL; +@@ -2678,14 +2586,13 @@ object_class_property_add_uint32_ptr(ObjectClass *klass, const char *name, + } + + return object_class_property_add(klass, name, "uint32", +- getter, setter, NULL, (void *)v, errp); ++ getter, setter, NULL, (void *)v); + } + + ObjectProperty * + object_property_add_uint64_ptr(Object *obj, const char *name, + const uint64_t *v, +- ObjectPropertyFlags flags, +- Error **errp) ++ ObjectPropertyFlags flags) + { + ObjectPropertyAccessor *getter = NULL; + ObjectPropertyAccessor *setter = NULL; +@@ -2699,14 +2606,13 @@ object_property_add_uint64_ptr(Object *obj, const char *name, + } + + return object_property_add(obj, name, "uint64", +- getter, setter, NULL, (void *)v, errp); ++ getter, setter, NULL, (void *)v); + } + + ObjectProperty * + object_class_property_add_uint64_ptr(ObjectClass *klass, const char *name, + const uint64_t *v, +- ObjectPropertyFlags flags, +- Error **errp) ++ ObjectPropertyFlags flags) + { + ObjectPropertyAccessor *getter = NULL; + ObjectPropertyAccessor *setter = NULL; +@@ -2720,7 +2626,7 @@ object_class_property_add_uint64_ptr(ObjectClass *klass, const char *name, + } + + return object_class_property_add(klass, name, "uint64", +- getter, setter, NULL, (void *)v, errp); ++ getter, setter, NULL, (void *)v); + } + + typedef struct { +@@ -2762,18 +2668,15 @@ static void property_release_alias(Object *obj, const char *name, void *opaque) + + ObjectProperty * + object_property_add_alias(Object *obj, const char *name, +- Object *target_obj, const char *target_name, +- Error **errp) ++ Object *target_obj, const char *target_name) + { + AliasProperty *prop; + ObjectProperty *op; + ObjectProperty *target_prop; + g_autofree char *prop_type = NULL; + +- target_prop = object_property_find(target_obj, target_name, errp); +- if (!target_prop) { +- return NULL; +- } ++ target_prop = object_property_find(target_obj, target_name, ++ &error_abort); + + if (object_property_is_child(target_prop)) { + prop_type = g_strdup_printf("link%s", +@@ -2790,12 +2693,7 @@ object_property_add_alias(Object *obj, const char *name, + property_get_alias, + property_set_alias, + property_release_alias, +- prop, errp); +- if (!op) { +- g_free(prop); +- return NULL; +- } +- ++ prop); + op->resolve = property_resolve_alias; + if (target_prop->defval) { + op->defval = qobject_ref(target_prop->defval); +@@ -2830,7 +2728,7 @@ void object_class_property_set_description(ObjectClass *klass, + static void object_class_init(ObjectClass *klass, void *data) + { + object_class_property_add_str(klass, "type", qdev_get_type, +- NULL, &error_abort); ++ NULL); + } + + static void register_types(void) +diff --git a/qom/object_interfaces.c b/qom/object_interfaces.c +index bc36f96e47..054e75043d 100644 +--- a/qom/object_interfaces.c ++++ b/qom/object_interfaces.c +@@ -83,10 +83,7 @@ Object *user_creatable_add_type(const char *type, const char *id, + + if (id != NULL) { + object_property_add_child(object_get_objects_root(), +- id, obj, &local_err); +- if (local_err) { +- goto out; +- } ++ id, obj); + } + + user_creatable_complete(USER_CREATABLE(obj), &local_err); +diff --git a/scsi/pr-manager-helper.c b/scsi/pr-manager-helper.c +index ca27c93283..bf62cbec11 100644 +--- a/scsi/pr-manager-helper.c ++++ b/scsi/pr-manager-helper.c +@@ -307,8 +307,7 @@ static void pr_manager_helper_class_init(ObjectClass *klass, + PRManagerClass *prmgr_klass = PR_MANAGER_CLASS(klass); + UserCreatableClass *uc_klass = USER_CREATABLE_CLASS(klass); + +- object_class_property_add_str(klass, "path", get_path, set_path, +- &error_abort); ++ object_class_property_add_str(klass, "path", get_path, set_path); + uc_klass->complete = pr_manager_helper_complete; + prmgr_klass->run = pr_manager_helper_run; + prmgr_klass->is_connected = pr_manager_helper_is_connected; +diff --git a/softmmu/vl.c b/softmmu/vl.c +index afd2615fb3..f84151acd3 100644 +--- a/softmmu/vl.c ++++ b/softmmu/vl.c +@@ -2802,7 +2802,7 @@ static void create_default_memdev(MachineState *ms, const char *path) + } + object_property_set_int(obj, ms->ram_size, "size", &error_fatal); + object_property_add_child(object_get_objects_root(), mc->default_ram_id, +- obj, &error_fatal); ++ obj); + /* Ensure backend's memory region name is equal to mc->default_ram_id */ + object_property_set_bool(obj, false, "x-use-canonical-path-for-ramblock-id", + &error_fatal); +@@ -3878,11 +3878,10 @@ void qemu_init(int argc, char **argv, char **envp) + exit(0); + } + object_property_add_child(object_get_root(), "machine", +- OBJECT(current_machine), &error_abort); ++ OBJECT(current_machine)); + object_property_add_child(container_get(OBJECT(current_machine), + "/unattached"), +- "sysbus", OBJECT(sysbus_get_default()), +- NULL); ++ "sysbus", OBJECT(sysbus_get_default())); + + if (machine_class->minimum_page_bits) { + if (!set_preferred_target_page_bits(machine_class->minimum_page_bits)) { +diff --git a/target/arm/cpu.c b/target/arm/cpu.c +index 3794f0dbc4..32bec156f2 100644 +--- a/target/arm/cpu.c ++++ b/target/arm/cpu.c +@@ -1179,8 +1179,7 @@ void arm_cpu_post_init(Object *obj) + TYPE_MEMORY_REGION, + (Object **)&cpu->secure_memory, + qdev_prop_allow_set_link_before_realize, +- OBJ_PROP_LINK_STRONG, +- &error_abort); ++ OBJ_PROP_LINK_STRONG); + } + + if (arm_feature(&cpu->env, ARM_FEATURE_EL2)) { +@@ -1190,8 +1189,7 @@ void arm_cpu_post_init(Object *obj) + + if (arm_feature(&cpu->env, ARM_FEATURE_PMU)) { + cpu->has_pmu = true; +- object_property_add_bool(obj, "pmu", arm_get_pmu, arm_set_pmu, +- &error_abort); ++ object_property_add_bool(obj, "pmu", arm_get_pmu, arm_set_pmu); + } + + /* +@@ -1231,8 +1229,7 @@ void arm_cpu_post_init(Object *obj) + if (arm_feature(&cpu->env, ARM_FEATURE_M_SECURITY)) { + object_property_add_link(obj, "idau", TYPE_IDAU_INTERFACE, &cpu->idau, + qdev_prop_allow_set_link_before_realize, +- OBJ_PROP_LINK_STRONG, +- &error_abort); ++ OBJ_PROP_LINK_STRONG); + /* + * M profile: initial value of the Secure VTOR. We can't just use + * a simple DEFINE_PROP_UINT32 for this because we want to permit +@@ -1240,7 +1237,7 @@ void arm_cpu_post_init(Object *obj) + */ + object_property_add_uint32_ptr(obj, "init-svtor", + &cpu->init_svtor, +- OBJ_PROP_FLAG_READWRITE, &error_abort); ++ OBJ_PROP_FLAG_READWRITE); + } + + qdev_property_add_static(DEVICE(obj), &arm_cpu_cfgend_property); +diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c +index 18a0af88e2..cbc5c3868f 100644 +--- a/target/arm/cpu64.c ++++ b/target/arm/cpu64.c +@@ -571,13 +571,13 @@ void aarch64_add_sve_properties(Object *obj) + uint32_t vq; + + object_property_add(obj, "sve", "bool", cpu_arm_get_sve, +- cpu_arm_set_sve, NULL, NULL, &error_fatal); ++ cpu_arm_set_sve, NULL, NULL); + + for (vq = 1; vq <= ARM_MAX_VQ; ++vq) { + char name[8]; + sprintf(name, "sve%d", vq * 128); + object_property_add(obj, name, "bool", cpu_arm_get_sve_vq, +- cpu_arm_set_sve_vq, NULL, NULL, &error_fatal); ++ cpu_arm_set_sve_vq, NULL, NULL); + } + } + +@@ -726,7 +726,7 @@ static void aarch64_max_initfn(Object *obj) + + aarch64_add_sve_properties(obj); + object_property_add(obj, "sve-max-vq", "uint32", cpu_max_get_sve_max_vq, +- cpu_max_set_sve_max_vq, NULL, NULL, &error_fatal); ++ cpu_max_set_sve_max_vq, NULL, NULL); + } + + static const ARMCPUInfo aarch64_cpus[] = { +@@ -767,7 +767,7 @@ static void aarch64_cpu_set_aarch64(Object *obj, bool value, Error **errp) + static void aarch64_cpu_initfn(Object *obj) + { + object_property_add_bool(obj, "aarch64", aarch64_cpu_get_aarch64, +- aarch64_cpu_set_aarch64, NULL); ++ aarch64_cpu_set_aarch64); + object_property_set_description(obj, "aarch64", + "Set on/off to enable/disable aarch64 " + "execution state "); +diff --git a/target/arm/kvm.c b/target/arm/kvm.c +index 1ea2d047e3..4bdbe6dcac 100644 +--- a/target/arm/kvm.c ++++ b/target/arm/kvm.c +@@ -200,7 +200,7 @@ void kvm_arm_add_vcpu_properties(Object *obj) + + ARM_CPU(obj)->kvm_adjvtime = true; + object_property_add_bool(obj, "kvm-no-adjvtime", kvm_no_adjvtime_get, +- kvm_no_adjvtime_set, &error_abort); ++ kvm_no_adjvtime_set); + object_property_set_description(obj, "kvm-no-adjvtime", + "Set on to disable the adjustment of " + "the virtual counter. VM stopped time " +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index 9c256ab159..6a64d2a5cd 100644 +--- a/target/i386/cpu.c ++++ b/target/i386/cpu.c +@@ -6110,7 +6110,7 @@ static void x86_cpu_apic_create(X86CPU *cpu, Error **errp) + cpu->apic_state = DEVICE(object_new_with_class(apic_class)); + + object_property_add_child(OBJECT(cpu), "lapic", +- OBJECT(cpu->apic_state), &error_abort); ++ OBJECT(cpu->apic_state)); + object_unref(OBJECT(cpu->apic_state)); + + qdev_prop_set_uint32(cpu->apic_state, "id", cpu->apic_id); +@@ -6822,7 +6822,7 @@ static void x86_cpu_register_bit_prop(X86CPU *cpu, + object_property_add(OBJECT(cpu), prop_name, "bool", + x86_cpu_get_bit_prop, + x86_cpu_set_bit_prop, +- x86_cpu_release_bit_prop, fp, &error_abort); ++ x86_cpu_release_bit_prop, fp); + } + } + +@@ -6905,28 +6905,28 @@ static void x86_cpu_initfn(Object *obj) + + object_property_add(obj, "family", "int", + x86_cpuid_version_get_family, +- x86_cpuid_version_set_family, NULL, NULL, NULL); ++ x86_cpuid_version_set_family, NULL, NULL); + object_property_add(obj, "model", "int", + x86_cpuid_version_get_model, +- x86_cpuid_version_set_model, NULL, NULL, NULL); ++ x86_cpuid_version_set_model, NULL, NULL); + object_property_add(obj, "stepping", "int", + x86_cpuid_version_get_stepping, +- x86_cpuid_version_set_stepping, NULL, NULL, NULL); ++ x86_cpuid_version_set_stepping, NULL, NULL); + object_property_add_str(obj, "vendor", + x86_cpuid_get_vendor, +- x86_cpuid_set_vendor, NULL); ++ x86_cpuid_set_vendor); + object_property_add_str(obj, "model-id", + x86_cpuid_get_model_id, +- x86_cpuid_set_model_id, NULL); ++ x86_cpuid_set_model_id); + object_property_add(obj, "tsc-frequency", "int", + x86_cpuid_get_tsc_freq, +- x86_cpuid_set_tsc_freq, NULL, NULL, NULL); ++ x86_cpuid_set_tsc_freq, NULL, NULL); + object_property_add(obj, "feature-words", "X86CPUFeatureWordInfo", + x86_cpu_get_feature_words, +- NULL, NULL, (void *)env->features, NULL); ++ NULL, NULL, (void *)env->features); + object_property_add(obj, "filtered-features", "X86CPUFeatureWordInfo", + x86_cpu_get_feature_words, +- NULL, NULL, (void *)cpu->filtered_features, NULL); ++ NULL, NULL, (void *)cpu->filtered_features); + /* + * The "unavailable-features" property has the same semantics as + * CpuDefinitionInfo.unavailable-features on the "query-cpu-definitions" +@@ -6935,10 +6935,10 @@ static void x86_cpu_initfn(Object *obj) + */ + object_property_add(obj, "unavailable-features", "strList", + x86_cpu_get_unavailable_features, +- NULL, NULL, NULL, &error_abort); ++ NULL, NULL, NULL); + + object_property_add(obj, "crash-information", "GuestPanicInformation", +- x86_cpu_get_crash_info_qom, NULL, NULL, NULL, NULL); ++ x86_cpu_get_crash_info_qom, NULL, NULL, NULL); + + for (w = 0; w < FEATURE_WORDS; w++) { + int bitnr; +@@ -6948,37 +6948,36 @@ static void x86_cpu_initfn(Object *obj) + } + } + +- object_property_add_alias(obj, "sse3", obj, "pni", &error_abort); +- object_property_add_alias(obj, "pclmuldq", obj, "pclmulqdq", &error_abort); +- object_property_add_alias(obj, "sse4-1", obj, "sse4.1", &error_abort); +- object_property_add_alias(obj, "sse4-2", obj, "sse4.2", &error_abort); +- object_property_add_alias(obj, "xd", obj, "nx", &error_abort); +- object_property_add_alias(obj, "ffxsr", obj, "fxsr-opt", &error_abort); +- object_property_add_alias(obj, "i64", obj, "lm", &error_abort); +- +- object_property_add_alias(obj, "ds_cpl", obj, "ds-cpl", &error_abort); +- object_property_add_alias(obj, "tsc_adjust", obj, "tsc-adjust", &error_abort); +- object_property_add_alias(obj, "fxsr_opt", obj, "fxsr-opt", &error_abort); +- object_property_add_alias(obj, "lahf_lm", obj, "lahf-lm", &error_abort); +- object_property_add_alias(obj, "cmp_legacy", obj, "cmp-legacy", &error_abort); +- object_property_add_alias(obj, "nodeid_msr", obj, "nodeid-msr", &error_abort); +- object_property_add_alias(obj, "perfctr_core", obj, "perfctr-core", &error_abort); +- object_property_add_alias(obj, "perfctr_nb", obj, "perfctr-nb", &error_abort); +- object_property_add_alias(obj, "kvm_nopiodelay", obj, "kvm-nopiodelay", &error_abort); +- object_property_add_alias(obj, "kvm_mmu", obj, "kvm-mmu", &error_abort); +- object_property_add_alias(obj, "kvm_asyncpf", obj, "kvm-asyncpf", &error_abort); +- object_property_add_alias(obj, "kvm_steal_time", obj, "kvm-steal-time", &error_abort); +- object_property_add_alias(obj, "kvm_pv_eoi", obj, "kvm-pv-eoi", &error_abort); +- object_property_add_alias(obj, "kvm_pv_unhalt", obj, "kvm-pv-unhalt", &error_abort); +- object_property_add_alias(obj, "kvm_poll_control", obj, "kvm-poll-control", +- &error_abort); +- object_property_add_alias(obj, "svm_lock", obj, "svm-lock", &error_abort); +- object_property_add_alias(obj, "nrip_save", obj, "nrip-save", &error_abort); +- object_property_add_alias(obj, "tsc_scale", obj, "tsc-scale", &error_abort); +- object_property_add_alias(obj, "vmcb_clean", obj, "vmcb-clean", &error_abort); +- object_property_add_alias(obj, "pause_filter", obj, "pause-filter", &error_abort); +- object_property_add_alias(obj, "sse4_1", obj, "sse4.1", &error_abort); +- object_property_add_alias(obj, "sse4_2", obj, "sse4.2", &error_abort); ++ object_property_add_alias(obj, "sse3", obj, "pni"); ++ object_property_add_alias(obj, "pclmuldq", obj, "pclmulqdq"); ++ object_property_add_alias(obj, "sse4-1", obj, "sse4.1"); ++ object_property_add_alias(obj, "sse4-2", obj, "sse4.2"); ++ object_property_add_alias(obj, "xd", obj, "nx"); ++ object_property_add_alias(obj, "ffxsr", obj, "fxsr-opt"); ++ object_property_add_alias(obj, "i64", obj, "lm"); ++ ++ object_property_add_alias(obj, "ds_cpl", obj, "ds-cpl"); ++ object_property_add_alias(obj, "tsc_adjust", obj, "tsc-adjust"); ++ object_property_add_alias(obj, "fxsr_opt", obj, "fxsr-opt"); ++ object_property_add_alias(obj, "lahf_lm", obj, "lahf-lm"); ++ object_property_add_alias(obj, "cmp_legacy", obj, "cmp-legacy"); ++ object_property_add_alias(obj, "nodeid_msr", obj, "nodeid-msr"); ++ object_property_add_alias(obj, "perfctr_core", obj, "perfctr-core"); ++ object_property_add_alias(obj, "perfctr_nb", obj, "perfctr-nb"); ++ object_property_add_alias(obj, "kvm_nopiodelay", obj, "kvm-nopiodelay"); ++ object_property_add_alias(obj, "kvm_mmu", obj, "kvm-mmu"); ++ object_property_add_alias(obj, "kvm_asyncpf", obj, "kvm-asyncpf"); ++ object_property_add_alias(obj, "kvm_steal_time", obj, "kvm-steal-time"); ++ object_property_add_alias(obj, "kvm_pv_eoi", obj, "kvm-pv-eoi"); ++ object_property_add_alias(obj, "kvm_pv_unhalt", obj, "kvm-pv-unhalt"); ++ object_property_add_alias(obj, "kvm_poll_control", obj, "kvm-poll-control"); ++ object_property_add_alias(obj, "svm_lock", obj, "svm-lock"); ++ object_property_add_alias(obj, "nrip_save", obj, "nrip-save"); ++ object_property_add_alias(obj, "tsc_scale", obj, "tsc-scale"); ++ object_property_add_alias(obj, "vmcb_clean", obj, "vmcb-clean"); ++ object_property_add_alias(obj, "pause_filter", obj, "pause-filter"); ++ object_property_add_alias(obj, "sse4_1", obj, "sse4.1"); ++ object_property_add_alias(obj, "sse4_2", obj, "sse4.2"); + + if (xcc->model) { + x86_cpu_load_model(cpu, xcc->model, &error_abort); +diff --git a/target/i386/sev.c b/target/i386/sev.c +index 6842cfc26d..51cdbe5496 100644 +--- a/target/i386/sev.c ++++ b/target/i386/sev.c +@@ -248,20 +248,17 @@ qsev_guest_class_init(ObjectClass *oc, void *data) + { + object_class_property_add_str(oc, "sev-device", + qsev_guest_get_sev_device, +- qsev_guest_set_sev_device, +- NULL); ++ qsev_guest_set_sev_device); + object_class_property_set_description(oc, "sev-device", + "SEV device to use"); + object_class_property_add_str(oc, "dh-cert-file", + qsev_guest_get_dh_cert_file, +- qsev_guest_set_dh_cert_file, +- NULL); ++ qsev_guest_set_dh_cert_file); + object_class_property_set_description(oc, "dh-cert-file", + "guest owners DH certificate (encoded with base64)"); + object_class_property_add_str(oc, "session-file", + qsev_guest_get_session_file, +- qsev_guest_set_session_file, +- NULL); ++ qsev_guest_set_session_file); + object_class_property_set_description(oc, "session-file", + "guest owners session parameters (encoded with base64)"); + } +@@ -274,14 +271,14 @@ qsev_guest_init(Object *obj) + sev->sev_device = g_strdup(DEFAULT_SEV_DEVICE); + sev->policy = DEFAULT_GUEST_POLICY; + object_property_add_uint32_ptr(obj, "policy", &sev->policy, +- OBJ_PROP_FLAG_READWRITE, NULL); ++ OBJ_PROP_FLAG_READWRITE); + object_property_add_uint32_ptr(obj, "handle", &sev->handle, +- OBJ_PROP_FLAG_READWRITE, NULL); ++ OBJ_PROP_FLAG_READWRITE); + object_property_add_uint32_ptr(obj, "cbitpos", &sev->cbitpos, +- OBJ_PROP_FLAG_READWRITE, NULL); ++ OBJ_PROP_FLAG_READWRITE); + object_property_add_uint32_ptr(obj, "reduced-phys-bits", + &sev->reduced_phys_bits, +- OBJ_PROP_FLAG_READWRITE, NULL); ++ OBJ_PROP_FLAG_READWRITE); + } + + /* sev guest info */ +diff --git a/target/ppc/compat.c b/target/ppc/compat.c +index 46ffb6da6d..7f144392f8 100644 +--- a/target/ppc/compat.c ++++ b/target/ppc/compat.c +@@ -301,17 +301,13 @@ void ppc_compat_add_property(Object *obj, const char *name, + uint32_t *compat_pvr, const char *basedesc, + Error **errp) + { +- Error *local_err = NULL; + gchar *namesv[ARRAY_SIZE(compat_table) + 1]; + gchar *names, *desc; + int i; + + object_property_add(obj, name, "string", + ppc_compat_prop_get, ppc_compat_prop_set, NULL, +- compat_pvr, &local_err); +- if (local_err) { +- goto out; +- } ++ compat_pvr); + + for (i = 0; i < ARRAY_SIZE(compat_table); i++) { + /* +@@ -328,7 +324,4 @@ void ppc_compat_add_property(Object *obj, const char *name, + + g_free(names); + g_free(desc); +- +-out: +- error_propagate(errp, local_err); + } +diff --git a/target/s390x/cpu.c b/target/s390x/cpu.c +index f2ccf0a06a..ca50b70451 100644 +--- a/target/s390x/cpu.c ++++ b/target/s390x/cpu.c +@@ -296,7 +296,7 @@ static void s390_cpu_initfn(Object *obj) + cs->halted = 1; + cs->exception_index = EXCP_HLT; + object_property_add(obj, "crash-information", "GuestPanicInformation", +- s390_cpu_get_crash_info_qom, NULL, NULL, NULL, NULL); ++ s390_cpu_get_crash_info_qom, NULL, NULL, NULL); + s390_cpu_model_register_props(obj); + #if !defined(CONFIG_USER_ONLY) + cpu->env.tod_timer = +diff --git a/target/s390x/cpu_models.c b/target/s390x/cpu_models.c +index aa7fc713ca..8efe6ed514 100644 +--- a/target/s390x/cpu_models.c ++++ b/target/s390x/cpu_models.c +@@ -1106,13 +1106,13 @@ void s390_cpu_model_register_props(Object *obj) + for (feat = 0; feat < S390_FEAT_MAX; feat++) { + const S390FeatDef *def = s390_feat_def(feat); + object_property_add(obj, def->name, "bool", get_feature, +- set_feature, NULL, (void *) feat, NULL); ++ set_feature, NULL, (void *) feat); + object_property_set_description(obj, def->name, def->desc); + } + for (group = 0; group < S390_FEAT_GROUP_MAX; group++) { + const S390FeatGroupDef *def = s390_feat_group_def(group); + object_property_add(obj, def->name, "bool", get_feature_group, +- set_feature_group, NULL, (void *) group, NULL); ++ set_feature_group, NULL, (void *) group); + object_property_set_description(obj, def->name, def->desc); + } + } +@@ -1225,11 +1225,10 @@ static char *get_description(Object *obj, Error **errp) + void s390_cpu_model_class_register_props(ObjectClass *oc) + { + object_class_property_add_bool(oc, "migration-safe", get_is_migration_safe, +- NULL, NULL); ++ NULL); + object_class_property_add_bool(oc, "static", get_is_static, +- NULL, NULL); +- object_class_property_add_str(oc, "description", get_description, NULL, +- NULL); ++ NULL); ++ object_class_property_add_str(oc, "description", get_description, NULL); + } + + #ifdef CONFIG_KVM +diff --git a/tests/check-qom-proplist.c b/tests/check-qom-proplist.c +index 140d56439a..84f48fe592 100644 +--- a/tests/check-qom-proplist.c ++++ b/tests/check-qom-proplist.c +@@ -125,18 +125,9 @@ static char *dummy_get_sv(Object *obj, + + static void dummy_init(Object *obj) + { +- Error *err = NULL; +- + object_property_add_bool(obj, "bv", + dummy_get_bv, +- dummy_set_bv, +- NULL); +- /* duplicate: */ +- object_property_add_str(obj, "sv", +- dummy_get_sv, +- dummy_set_sv, +- &err); +- error_free_or_abort(&err); ++ dummy_set_bv); + } + + +@@ -144,14 +135,12 @@ static void dummy_class_init(ObjectClass *cls, void *data) + { + object_class_property_add_str(cls, "sv", + dummy_get_sv, +- dummy_set_sv, +- NULL); ++ dummy_set_sv); + object_class_property_add_enum(cls, "av", + "DummyAnimal", + &dummy_animal_map, + dummy_get_av, +- dummy_set_av, +- NULL); ++ dummy_set_av); + } + + +@@ -256,13 +245,13 @@ static void dummy_dev_init(Object *obj) + DummyBus *bus = DUMMY_BUS(object_new(TYPE_DUMMY_BUS)); + DummyBackend *backend = DUMMY_BACKEND(object_new(TYPE_DUMMY_BACKEND)); + +- object_property_add_child(obj, "bus", OBJECT(bus), NULL); ++ object_property_add_child(obj, "bus", OBJECT(bus)); + dev->bus = bus; +- object_property_add_child(OBJECT(bus), "backend", OBJECT(backend), NULL); ++ object_property_add_child(OBJECT(bus), "backend", OBJECT(backend)); + bus->backend = backend; + + object_property_add_link(obj, "backend", TYPE_DUMMY_BACKEND, +- (Object **)&bus->backend, NULL, 0, NULL); ++ (Object **)&bus->backend, NULL, 0); + } + + static void dummy_dev_unparent(Object *obj) +@@ -603,11 +592,11 @@ static void test_qom_partial_path(void) + * /cont1/obj2 (obj2a) + * /obj2 (obj2b) + */ +- object_property_add_child(cont1, "obj1", obj1, &error_abort); ++ object_property_add_child(cont1, "obj1", obj1); + object_unref(obj1); +- object_property_add_child(cont1, "obj2", obj2a, &error_abort); ++ object_property_add_child(cont1, "obj2", obj2a); + object_unref(obj2a); +- object_property_add_child(root, "obj2", obj2b, &error_abort); ++ object_property_add_child(root, "obj2", obj2b); + object_unref(obj2b); + + ambiguous = false; +diff --git a/tests/test-qdev-global-props.c b/tests/test-qdev-global-props.c +index 270c690479..42d3dd7030 100644 +--- a/tests/test-qdev-global-props.c ++++ b/tests/test-qdev-global-props.c +@@ -151,9 +151,9 @@ static void prop2_accessor(Object *obj, Visitor *v, const char *name, + static void dynamic_instance_init(Object *obj) + { + object_property_add(obj, "prop1", "uint32", prop1_accessor, prop1_accessor, +- NULL, NULL, NULL); ++ NULL, NULL); + object_property_add(obj, "prop2", "uint32", prop2_accessor, prop2_accessor, +- NULL, NULL, NULL); ++ NULL, NULL); + } + + static void dynamic_class_init(ObjectClass *oc, void *data) +diff --git a/ui/console.c b/ui/console.c +index 184e173687..865fa32635 100644 +--- a/ui/console.c ++++ b/ui/console.c +@@ -1297,10 +1297,9 @@ static QemuConsole *new_console(DisplayState *ds, console_type_t console_type, + object_property_add_link(obj, "device", TYPE_DEVICE, + (Object **)&s->device, + object_property_allow_set_link, +- OBJ_PROP_LINK_STRONG, +- &error_abort); ++ OBJ_PROP_LINK_STRONG); + object_property_add_uint32_ptr(obj, "head", &s->head, +- OBJ_PROP_FLAG_READ, &error_abort); ++ OBJ_PROP_FLAG_READ); + + if (!active_console || ((active_console->console_type != GRAPHIC_CONSOLE) && + (console_type == GRAPHIC_CONSOLE))) { +@@ -1868,7 +1867,7 @@ DisplayState *init_displaystate(void) + * doesn't change any more */ + name = g_strdup_printf("console[%d]", con->index); + object_property_add_child(container_get(object_get_root(), "/backend"), +- name, OBJECT(con), &error_abort); ++ name, OBJECT(con)); + g_free(name); + } + +diff --git a/ui/input-barrier.c b/ui/input-barrier.c +index 527c75e130..1cdf0c5f82 100644 +--- a/ui/input-barrier.c ++++ b/ui/input-barrier.c +@@ -700,25 +700,25 @@ static void input_barrier_instance_init(Object *obj) + + object_property_add_str(obj, "name", + input_barrier_get_name, +- input_barrier_set_name, NULL); ++ input_barrier_set_name); + object_property_add_str(obj, "server", + input_barrier_get_server, +- input_barrier_set_server, NULL); ++ input_barrier_set_server); + object_property_add_str(obj, "port", + input_barrier_get_port, +- input_barrier_set_port, NULL); ++ input_barrier_set_port); + object_property_add_str(obj, "x-origin", + input_barrier_get_x_origin, +- input_barrier_set_x_origin, NULL); ++ input_barrier_set_x_origin); + object_property_add_str(obj, "y-origin", + input_barrier_get_y_origin, +- input_barrier_set_y_origin, NULL); ++ input_barrier_set_y_origin); + object_property_add_str(obj, "width", + input_barrier_get_width, +- input_barrier_set_width, NULL); ++ input_barrier_set_width); + object_property_add_str(obj, "height", + input_barrier_get_height, +- input_barrier_set_height, NULL); ++ input_barrier_set_height); + } + + static void input_barrier_class_init(ObjectClass *oc, void *data) +diff --git a/ui/input-linux.c b/ui/input-linux.c +index ef37b14d6f..4925ce1af1 100644 +--- a/ui/input-linux.c ++++ b/ui/input-linux.c +@@ -499,17 +499,17 @@ static void input_linux_instance_init(Object *obj) + { + object_property_add_str(obj, "evdev", + input_linux_get_evdev, +- input_linux_set_evdev, NULL); ++ input_linux_set_evdev); + object_property_add_bool(obj, "grab_all", + input_linux_get_grab_all, +- input_linux_set_grab_all, NULL); ++ input_linux_set_grab_all); + object_property_add_bool(obj, "repeat", + input_linux_get_repeat, +- input_linux_set_repeat, NULL); ++ input_linux_set_repeat); + object_property_add_enum(obj, "grab-toggle", "GrabToggleKeys", + &GrabToggleKeys_lookup, + input_linux_get_grab_toggle, +- input_linux_set_grab_toggle, NULL); ++ input_linux_set_grab_toggle); + } + + static void input_linux_class_init(ObjectClass *oc, void *data) +-- +2.23.0 + diff --git a/qom-Factor-out-user_creatable_add_dict.patch b/qom-Factor-out-user_creatable_add_dict.patch new file mode 100644 index 0000000000000000000000000000000000000000..29206ae2856e7a4f494d2b6a5c511e22b7b5b7fc --- /dev/null +++ b/qom-Factor-out-user_creatable_add_dict.patch @@ -0,0 +1,143 @@ +From d6a5beeb2bbf4f5ce6e6396051fb4c5fcced56a4 Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Thu, 16 Apr 2020 17:04:20 +0200 +Subject: [PATCH 137/709] qom: Factor out user_creatable_add_dict() + +The QMP handler qmp_object_add() and the implementation of --object in +qemu-storage-daemon can share most of the code. Currently, +qemu-storage-daemon calls qmp_object_add(), but this is not correct +because different visitors need to be used. + +As a first step towards a fix, make qmp_object_add() a wrapper around a +new function user_creatable_add_dict() that can get an additional +parameter. The handling of "props" is only required for compatibility +and not required for the qemu-storage-daemon command line, so it stays +in qmp_object_add(). + +Signed-off-by: Kevin Wolf +--- + include/qom/object_interfaces.h | 12 ++++++++++++ + qom/object_interfaces.c | 27 +++++++++++++++++++++++++++ + qom/qom-qmp-cmds.c | 24 +----------------------- + 3 files changed, 40 insertions(+), 23 deletions(-) + +diff --git a/include/qom/object_interfaces.h b/include/qom/object_interfaces.h +index 6f92f3cebb..a0037968a4 100644 +--- a/include/qom/object_interfaces.h ++++ b/include/qom/object_interfaces.h +@@ -87,6 +87,18 @@ Object *user_creatable_add_type(const char *type, const char *id, + const QDict *qdict, + Visitor *v, Error **errp); + ++/** ++ * user_creatable_add_dict: ++ * @qdict: the object definition ++ * @errp: if an error occurs, a pointer to an area to store the error ++ * ++ * Create an instance of the user creatable object that is defined by ++ * @qdict. The object type is taken from the QDict key 'qom-type', its ++ * ID from the key 'id'. The remaining entries in @qdict are used to ++ * initialize the object properties. ++ */ ++void user_creatable_add_dict(QDict *qdict, Error **errp); ++ + /** + * user_creatable_add_opts: + * @opts: the object definition +diff --git a/qom/object_interfaces.c b/qom/object_interfaces.c +index 72cb9e32a9..739e3e5172 100644 +--- a/qom/object_interfaces.c ++++ b/qom/object_interfaces.c +@@ -6,6 +6,7 @@ + #include "qapi/qmp/qerror.h" + #include "qapi/qmp/qjson.h" + #include "qapi/qmp/qstring.h" ++#include "qapi/qobject-input-visitor.h" + #include "qom/object_interfaces.h" + #include "qemu/help_option.h" + #include "qemu/module.h" +@@ -105,6 +106,32 @@ out: + return obj; + } + ++void user_creatable_add_dict(QDict *qdict, Error **errp) ++{ ++ Visitor *v; ++ Object *obj; ++ g_autofree char *type = NULL; ++ g_autofree char *id = NULL; ++ ++ type = g_strdup(qdict_get_try_str(qdict, "qom-type")); ++ if (!type) { ++ error_setg(errp, QERR_MISSING_PARAMETER, "qom-type"); ++ return; ++ } ++ qdict_del(qdict, "qom-type"); ++ ++ id = g_strdup(qdict_get_try_str(qdict, "id")); ++ if (!id) { ++ error_setg(errp, QERR_MISSING_PARAMETER, "id"); ++ return; ++ } ++ qdict_del(qdict, "id"); ++ ++ v = qobject_input_visitor_new(QOBJECT(qdict)); ++ obj = user_creatable_add_type(type, id, qdict, v, errp); ++ visit_free(v); ++ object_unref(obj); ++} + + Object *user_creatable_add_opts(QemuOpts *opts, Error **errp) + { +diff --git a/qom/qom-qmp-cmds.c b/qom/qom-qmp-cmds.c +index e47ebe8ed1..35db44b50e 100644 +--- a/qom/qom-qmp-cmds.c ++++ b/qom/qom-qmp-cmds.c +@@ -21,7 +21,6 @@ + #include "qapi/qapi-commands-qom.h" + #include "qapi/qmp/qdict.h" + #include "qapi/qmp/qerror.h" +-#include "qapi/qobject-input-visitor.h" + #include "qemu/cutils.h" + #include "qom/object_interfaces.h" + #include "qom/qom-qobject.h" +@@ -245,24 +244,6 @@ void qmp_object_add(QDict *qdict, QObject **ret_data, Error **errp) + { + QObject *props; + QDict *pdict; +- Visitor *v; +- Object *obj; +- g_autofree char *type = NULL; +- g_autofree char *id = NULL; +- +- type = g_strdup(qdict_get_try_str(qdict, "qom-type")); +- if (!type) { +- error_setg(errp, QERR_MISSING_PARAMETER, "qom-type"); +- return; +- } +- qdict_del(qdict, "qom-type"); +- +- id = g_strdup(qdict_get_try_str(qdict, "id")); +- if (!id) { +- error_setg(errp, QERR_MISSING_PARAMETER, "id"); +- return; +- } +- qdict_del(qdict, "id"); + + props = qdict_get(qdict, "props"); + if (props) { +@@ -282,10 +263,7 @@ void qmp_object_add(QDict *qdict, QObject **ret_data, Error **errp) + qobject_unref(pdict); + } + +- v = qobject_input_visitor_new(QOBJECT(qdict)); +- obj = user_creatable_add_type(type, id, qdict, v, errp); +- visit_free(v); +- object_unref(obj); ++ user_creatable_add_dict(qdict, errp); + } + + void qmp_object_del(const char *id, Error **errp) +-- +2.23.0 + diff --git a/qom-Make-all-the-object_property_add_FOO-return-the-.patch b/qom-Make-all-the-object_property_add_FOO-return-the-.patch new file mode 100644 index 0000000000000000000000000000000000000000..74de5d2d897a2e4664a72217e50b2ad92138e97a --- /dev/null +++ b/qom-Make-all-the-object_property_add_FOO-return-the-.patch @@ -0,0 +1,624 @@ +From 702518877220187a858da1a6ba08d53995dc6e2f Mon Sep 17 00:00:00 2001 +From: Markus Armbruster +Date: Tue, 5 May 2020 17:29:14 +0200 +Subject: [PATCH 468/709] qom: Make all the object_property_add_FOO() return + the property + +Some object_property_add_FOO() return the newly added property, some +don't. Clean that up. + +Signed-off-by: Markus Armbruster +Reviewed-by: Eric Blake +Reviewed-by: Paolo Bonzini +Message-Id: <20200505152926.18877-7-armbru@redhat.com> +--- + include/qom/object.h | 50 ++++++--- + qom/object.c | 250 ++++++++++++++++++++++--------------------- + 2 files changed, 164 insertions(+), 136 deletions(-) + +diff --git a/include/qom/object.h b/include/qom/object.h +index 4df9ecebad..0ea5808432 100644 +--- a/include/qom/object.h ++++ b/include/qom/object.h +@@ -1491,9 +1491,11 @@ Object *object_resolve_path_component(Object *parent, const char *part); + * The value of a child property as a C string will be the child object's + * canonical path. It can be retrieved using object_property_get_str(). + * The child object itself can be retrieved using object_property_get_link(). ++ * ++ * Returns: The newly added property on success, or %NULL on failure. + */ +-void object_property_add_child(Object *obj, const char *name, +- Object *child, Error **errp); ++ObjectProperty *object_property_add_child(Object *obj, const char *name, ++ Object *child, Error **errp); + + typedef enum { + /* Unref the link pointer when the property is deleted */ +@@ -1542,8 +1544,10 @@ void object_property_allow_set_link(const Object *, const char *, + * @flags OBJ_PROP_LINK_STRONG bit is set, + * the reference count is decremented when the property is deleted or + * modified. ++ * ++ * Returns: The newly added property on success, or %NULL on failure. + */ +-void object_property_add_link(Object *obj, const char *name, ++ObjectProperty *object_property_add_link(Object *obj, const char *name, + const char *type, Object **targetp, + void (*check)(const Object *obj, const char *name, + Object *val, Error **errp), +@@ -1569,8 +1573,10 @@ ObjectProperty *object_class_property_add_link(ObjectClass *oc, + * + * Add a string property using getters/setters. This function will add a + * property of type 'string'. ++ * ++ * Returns: The newly added property on success, or %NULL on failure. + */ +-void object_property_add_str(Object *obj, const char *name, ++ObjectProperty *object_property_add_str(Object *obj, const char *name, + char *(*get)(Object *, Error **), + void (*set)(Object *, const char *, Error **), + Error **errp); +@@ -1592,8 +1598,10 @@ ObjectProperty *object_class_property_add_str(ObjectClass *klass, + * + * Add a bool property using getters/setters. This function will add a + * property of type 'bool'. ++ * ++ * Returns: The newly added property on success, or %NULL on failure. + */ +-void object_property_add_bool(Object *obj, const char *name, ++ObjectProperty *object_property_add_bool(Object *obj, const char *name, + bool (*get)(Object *, Error **), + void (*set)(Object *, bool, Error **), + Error **errp); +@@ -1615,8 +1623,10 @@ ObjectProperty *object_class_property_add_bool(ObjectClass *klass, + * + * Add an enum property using getters/setters. This function will add a + * property of type '@typename'. ++ * ++ * Returns: The newly added property on success, or %NULL on failure. + */ +-void object_property_add_enum(Object *obj, const char *name, ++ObjectProperty *object_property_add_enum(Object *obj, const char *name, + const char *typename, + const QEnumLookup *lookup, + int (*get)(Object *, Error **), +@@ -1640,8 +1650,10 @@ ObjectProperty *object_class_property_add_enum(ObjectClass *klass, + * + * Add a read-only struct tm valued property using a getter function. + * This function will add a property of type 'struct tm'. ++ * ++ * Returns: The newly added property on success, or %NULL on failure. + */ +-void object_property_add_tm(Object *obj, const char *name, ++ObjectProperty *object_property_add_tm(Object *obj, const char *name, + void (*get)(Object *, struct tm *, Error **), + Error **errp); + +@@ -1669,8 +1681,10 @@ typedef enum { + * + * Add an integer property in memory. This function will add a + * property of type 'uint8'. ++ * ++ * Returns: The newly added property on success, or %NULL on failure. + */ +-void object_property_add_uint8_ptr(Object *obj, const char *name, ++ObjectProperty *object_property_add_uint8_ptr(Object *obj, const char *name, + const uint8_t *v, ObjectPropertyFlags flags, + Error **errp); + +@@ -1690,8 +1704,10 @@ ObjectProperty *object_class_property_add_uint8_ptr(ObjectClass *klass, + * + * Add an integer property in memory. This function will add a + * property of type 'uint16'. ++ * ++ * Returns: The newly added property on success, or %NULL on failure. + */ +-void object_property_add_uint16_ptr(Object *obj, const char *name, ++ObjectProperty *object_property_add_uint16_ptr(Object *obj, const char *name, + const uint16_t *v, + ObjectPropertyFlags flags, + Error **errp); +@@ -1712,8 +1728,10 @@ ObjectProperty *object_class_property_add_uint16_ptr(ObjectClass *klass, + * + * Add an integer property in memory. This function will add a + * property of type 'uint32'. ++ * ++ * Returns: The newly added property on success, or %NULL on failure. + */ +-void object_property_add_uint32_ptr(Object *obj, const char *name, ++ObjectProperty *object_property_add_uint32_ptr(Object *obj, const char *name, + const uint32_t *v, + ObjectPropertyFlags flags, + Error **errp); +@@ -1734,8 +1752,10 @@ ObjectProperty *object_class_property_add_uint32_ptr(ObjectClass *klass, + * + * Add an integer property in memory. This function will add a + * property of type 'uint64'. ++ * ++ * Returns: The newly added property on success, or %NULL on failure. + */ +-void object_property_add_uint64_ptr(Object *obj, const char *name, ++ObjectProperty *object_property_add_uint64_ptr(Object *obj, const char *name, + const uint64_t *v, + ObjectPropertyFlags flags, + Error **Errp); +@@ -1761,8 +1781,10 @@ ObjectProperty *object_class_property_add_uint64_ptr(ObjectClass *klass, + * this property exists. In the case of a child object or an alias on the same + * object this will be the case. For aliases to other objects the caller is + * responsible for taking a reference. ++ * ++ * Returns: The newly added property on success, or %NULL on failure. + */ +-void object_property_add_alias(Object *obj, const char *name, ++ObjectProperty *object_property_add_alias(Object *obj, const char *name, + Object *target_obj, const char *target_name, + Error **errp); + +@@ -1780,8 +1802,10 @@ void object_property_add_alias(Object *obj, const char *name, + * this property exists. In the case @target is a child of @obj, + * this will be the case. Otherwise, the caller is responsible for + * taking a reference. ++ * ++ * Returns: The newly added property on success, or %NULL on failure. + */ +-void object_property_add_const_link(Object *obj, const char *name, ++ObjectProperty *object_property_add_const_link(Object *obj, const char *name, + Object *target, Error **errp); + + /** +diff --git a/qom/object.c b/qom/object.c +index 54a26ed16a..4e5b2ecacd 100644 +--- a/qom/object.c ++++ b/qom/object.c +@@ -1646,33 +1646,30 @@ static void object_finalize_child_property(Object *obj, const char *name, + object_unref(child); + } + +-void object_property_add_child(Object *obj, const char *name, +- Object *child, Error **errp) ++ObjectProperty * ++object_property_add_child(Object *obj, const char *name, ++ Object *child, Error **errp) + { +- Error *local_err = NULL; +- char *type; ++ g_autofree char *type = NULL; + ObjectProperty *op; + + if (child->parent != NULL) { + error_setg(errp, "child object is already parented"); +- return; ++ return NULL; + } + + type = g_strdup_printf("child<%s>", object_get_typename(OBJECT(child))); + + op = object_property_add(obj, name, type, object_get_child_property, NULL, +- object_finalize_child_property, child, &local_err); +- if (local_err) { +- error_propagate(errp, local_err); +- goto out; ++ object_finalize_child_property, child, errp); ++ if (!op) { ++ return NULL; + } + + op->resolve = object_resolve_child_property; + object_ref(child); + child->parent = obj; +- +-out: +- g_free(type); ++ return op; + } + + void object_property_allow_set_link(const Object *obj, const char *name, +@@ -1819,16 +1816,16 @@ static void object_release_link_property(Object *obj, const char *name, + } + } + +-static void object_add_link_prop(Object *obj, const char *name, +- const char *type, void *ptr, +- void (*check)(const Object *, const char *, +- Object *, Error **), +- ObjectPropertyLinkFlags flags, +- Error **errp) ++static ObjectProperty * ++object_add_link_prop(Object *obj, const char *name, ++ const char *type, void *ptr, ++ void (*check)(const Object *, const char *, ++ Object *, Error **), ++ ObjectPropertyLinkFlags flags, ++ Error **errp) + { +- Error *local_err = NULL; + LinkProperty *prop = g_malloc(sizeof(*prop)); +- char *full_type; ++ g_autofree char *full_type = NULL; + ObjectProperty *op; + + if (flags & OBJ_PROP_LINK_DIRECT) { +@@ -1846,27 +1843,26 @@ static void object_add_link_prop(Object *obj, const char *name, + check ? object_set_link_property : NULL, + object_release_link_property, + prop, +- &local_err); +- if (local_err) { +- error_propagate(errp, local_err); ++ errp); ++ if (!op) { + g_free(prop); +- goto out; ++ return NULL; + } + + op->resolve = object_resolve_link_property; +- +-out: +- g_free(full_type); ++ return op; + } + +-void object_property_add_link(Object *obj, const char *name, +- const char *type, Object **targetp, +- void (*check)(const Object *, const char *, +- Object *, Error **), +- ObjectPropertyLinkFlags flags, +- Error **errp) ++ObjectProperty * ++object_property_add_link(Object *obj, const char *name, ++ const char *type, Object **targetp, ++ void (*check)(const Object *, const char *, ++ Object *, Error **), ++ ObjectPropertyLinkFlags flags, ++ Error **errp) + { +- object_add_link_prop(obj, name, type, targetp, check, flags, errp); ++ return object_add_link_prop(obj, name, type, targetp, check, flags, ++ errp); + } + + ObjectProperty * +@@ -1908,11 +1904,13 @@ out: + return op; + } + +-void object_property_add_const_link(Object *obj, const char *name, +- Object *target, Error **errp) ++ObjectProperty * ++object_property_add_const_link(Object *obj, const char *name, ++ Object *target, Error **errp) + { +- object_add_link_prop(obj, name, object_get_typename(target), target, +- NULL, OBJ_PROP_LINK_DIRECT, errp); ++ return object_add_link_prop(obj, name, ++ object_get_typename(target), target, ++ NULL, OBJ_PROP_LINK_DIRECT, errp); + } + + char *object_get_canonical_path_component(Object *obj) +@@ -2121,26 +2119,27 @@ static void property_release_str(Object *obj, const char *name, + g_free(prop); + } + +-void object_property_add_str(Object *obj, const char *name, +- char *(*get)(Object *, Error **), +- void (*set)(Object *, const char *, Error **), +- Error **errp) ++ObjectProperty * ++object_property_add_str(Object *obj, const char *name, ++ char *(*get)(Object *, Error **), ++ void (*set)(Object *, const char *, Error **), ++ Error **errp) + { +- Error *local_err = NULL; + StringProperty *prop = g_malloc0(sizeof(*prop)); ++ ObjectProperty *op; + + prop->get = get; + prop->set = set; + +- object_property_add(obj, name, "string", +- get ? property_get_str : NULL, +- set ? property_set_str : NULL, +- property_release_str, +- prop, &local_err); +- if (local_err) { +- error_propagate(errp, local_err); ++ op = object_property_add(obj, name, "string", ++ get ? property_get_str : NULL, ++ set ? property_set_str : NULL, ++ property_release_str, ++ prop, errp); ++ if (!op) { + g_free(prop); + } ++ return op; + } + + ObjectProperty * +@@ -2215,26 +2214,27 @@ static void property_release_bool(Object *obj, const char *name, + g_free(prop); + } + +-void object_property_add_bool(Object *obj, const char *name, +- bool (*get)(Object *, Error **), +- void (*set)(Object *, bool, Error **), +- Error **errp) ++ObjectProperty * ++object_property_add_bool(Object *obj, const char *name, ++ bool (*get)(Object *, Error **), ++ void (*set)(Object *, bool, Error **), ++ Error **errp) + { +- Error *local_err = NULL; + BoolProperty *prop = g_malloc0(sizeof(*prop)); ++ ObjectProperty *op; + + prop->get = get; + prop->set = set; + +- object_property_add(obj, name, "bool", +- get ? property_get_bool : NULL, +- set ? property_set_bool : NULL, +- property_release_bool, +- prop, &local_err); +- if (local_err) { +- error_propagate(errp, local_err); ++ op = object_property_add(obj, name, "bool", ++ get ? property_get_bool : NULL, ++ set ? property_set_bool : NULL, ++ property_release_bool, ++ prop, errp); ++ if (!op) { + g_free(prop); + } ++ return op; + } + + ObjectProperty * +@@ -2301,29 +2301,30 @@ static void property_release_enum(Object *obj, const char *name, + g_free(prop); + } + +-void object_property_add_enum(Object *obj, const char *name, +- const char *typename, +- const QEnumLookup *lookup, +- int (*get)(Object *, Error **), +- void (*set)(Object *, int, Error **), +- Error **errp) ++ObjectProperty * ++object_property_add_enum(Object *obj, const char *name, ++ const char *typename, ++ const QEnumLookup *lookup, ++ int (*get)(Object *, Error **), ++ void (*set)(Object *, int, Error **), ++ Error **errp) + { +- Error *local_err = NULL; + EnumProperty *prop = g_malloc(sizeof(*prop)); ++ ObjectProperty *op; + + prop->lookup = lookup; + prop->get = get; + prop->set = set; + +- object_property_add(obj, name, typename, +- get ? property_get_enum : NULL, +- set ? property_set_enum : NULL, +- property_release_enum, +- prop, &local_err); +- if (local_err) { +- error_propagate(errp, local_err); ++ op = object_property_add(obj, name, typename, ++ get ? property_get_enum : NULL, ++ set ? property_set_enum : NULL, ++ property_release_enum, ++ prop, errp); ++ if (!op) { + g_free(prop); + } ++ return op; + } + + ObjectProperty * +@@ -2414,23 +2415,24 @@ static void property_release_tm(Object *obj, const char *name, + g_free(prop); + } + +-void object_property_add_tm(Object *obj, const char *name, +- void (*get)(Object *, struct tm *, Error **), +- Error **errp) ++ObjectProperty * ++object_property_add_tm(Object *obj, const char *name, ++ void (*get)(Object *, struct tm *, Error **), ++ Error **errp) + { +- Error *local_err = NULL; + TMProperty *prop = g_malloc0(sizeof(*prop)); ++ ObjectProperty *op; + + prop->get = get; + +- object_property_add(obj, name, "struct tm", +- get ? property_get_tm : NULL, NULL, +- property_release_tm, +- prop, &local_err); +- if (local_err) { +- error_propagate(errp, local_err); ++ op = object_property_add(obj, name, "struct tm", ++ get ? property_get_tm : NULL, NULL, ++ property_release_tm, ++ prop, errp); ++ if (!op) { + g_free(prop); + } ++ return op; + } + + ObjectProperty * +@@ -2553,10 +2555,11 @@ static void property_set_uint64_ptr(Object *obj, Visitor *v, const char *name, + *field = value; + } + +-void object_property_add_uint8_ptr(Object *obj, const char *name, +- const uint8_t *v, +- ObjectPropertyFlags flags, +- Error **errp) ++ObjectProperty * ++object_property_add_uint8_ptr(Object *obj, const char *name, ++ const uint8_t *v, ++ ObjectPropertyFlags flags, ++ Error **errp) + { + ObjectPropertyAccessor *getter = NULL; + ObjectPropertyAccessor *setter = NULL; +@@ -2569,8 +2572,8 @@ void object_property_add_uint8_ptr(Object *obj, const char *name, + setter = property_set_uint8_ptr; + } + +- object_property_add(obj, name, "uint8", +- getter, setter, NULL, (void *)v, errp); ++ return object_property_add(obj, name, "uint8", ++ getter, setter, NULL, (void *)v, errp); + } + + ObjectProperty * +@@ -2594,10 +2597,11 @@ object_class_property_add_uint8_ptr(ObjectClass *klass, const char *name, + getter, setter, NULL, (void *)v, errp); + } + +-void object_property_add_uint16_ptr(Object *obj, const char *name, +- const uint16_t *v, +- ObjectPropertyFlags flags, +- Error **errp) ++ObjectProperty * ++object_property_add_uint16_ptr(Object *obj, const char *name, ++ const uint16_t *v, ++ ObjectPropertyFlags flags, ++ Error **errp) + { + ObjectPropertyAccessor *getter = NULL; + ObjectPropertyAccessor *setter = NULL; +@@ -2610,8 +2614,8 @@ void object_property_add_uint16_ptr(Object *obj, const char *name, + setter = property_set_uint16_ptr; + } + +- object_property_add(obj, name, "uint16", +- getter, setter, NULL, (void *)v, errp); ++ return object_property_add(obj, name, "uint16", ++ getter, setter, NULL, (void *)v, errp); + } + + ObjectProperty * +@@ -2635,10 +2639,11 @@ object_class_property_add_uint16_ptr(ObjectClass *klass, const char *name, + getter, setter, NULL, (void *)v, errp); + } + +-void object_property_add_uint32_ptr(Object *obj, const char *name, +- const uint32_t *v, +- ObjectPropertyFlags flags, +- Error **errp) ++ObjectProperty * ++object_property_add_uint32_ptr(Object *obj, const char *name, ++ const uint32_t *v, ++ ObjectPropertyFlags flags, ++ Error **errp) + { + ObjectPropertyAccessor *getter = NULL; + ObjectPropertyAccessor *setter = NULL; +@@ -2651,8 +2656,8 @@ void object_property_add_uint32_ptr(Object *obj, const char *name, + setter = property_set_uint32_ptr; + } + +- object_property_add(obj, name, "uint32", +- getter, setter, NULL, (void *)v, errp); ++ return object_property_add(obj, name, "uint32", ++ getter, setter, NULL, (void *)v, errp); + } + + ObjectProperty * +@@ -2676,10 +2681,11 @@ object_class_property_add_uint32_ptr(ObjectClass *klass, const char *name, + getter, setter, NULL, (void *)v, errp); + } + +-void object_property_add_uint64_ptr(Object *obj, const char *name, +- const uint64_t *v, +- ObjectPropertyFlags flags, +- Error **errp) ++ObjectProperty * ++object_property_add_uint64_ptr(Object *obj, const char *name, ++ const uint64_t *v, ++ ObjectPropertyFlags flags, ++ Error **errp) + { + ObjectPropertyAccessor *getter = NULL; + ObjectPropertyAccessor *setter = NULL; +@@ -2692,8 +2698,8 @@ void object_property_add_uint64_ptr(Object *obj, const char *name, + setter = property_set_uint64_ptr; + } + +- object_property_add(obj, name, "uint64", +- getter, setter, NULL, (void *)v, errp); ++ return object_property_add(obj, name, "uint64", ++ getter, setter, NULL, (void *)v, errp); + } + + ObjectProperty * +@@ -2754,19 +2760,19 @@ static void property_release_alias(Object *obj, const char *name, void *opaque) + g_free(prop); + } + +-void object_property_add_alias(Object *obj, const char *name, +- Object *target_obj, const char *target_name, +- Error **errp) ++ObjectProperty * ++object_property_add_alias(Object *obj, const char *name, ++ Object *target_obj, const char *target_name, ++ Error **errp) + { + AliasProperty *prop; + ObjectProperty *op; + ObjectProperty *target_prop; +- char *prop_type; +- Error *local_err = NULL; ++ g_autofree char *prop_type = NULL; + + target_prop = object_property_find(target_obj, target_name, errp); + if (!target_prop) { +- return; ++ return NULL; + } + + if (object_property_is_child(target_prop)) { +@@ -2784,12 +2790,12 @@ void object_property_add_alias(Object *obj, const char *name, + property_get_alias, + property_set_alias, + property_release_alias, +- prop, &local_err); +- if (local_err) { +- error_propagate(errp, local_err); ++ prop, errp); ++ if (!op) { + g_free(prop); +- goto out; ++ return NULL; + } ++ + op->resolve = property_resolve_alias; + if (target_prop->defval) { + op->defval = qobject_ref(target_prop->defval); +@@ -2798,9 +2804,7 @@ void object_property_add_alias(Object *obj, const char *name, + object_property_set_description(obj, op->name, + target_prop->description, + &error_abort); +- +-out: +- g_free(prop_type); ++ return op; + } + + void object_property_set_description(Object *obj, const char *name, +-- +2.23.0 + diff --git a/qom-Simplify-object_property_get_enum.patch b/qom-Simplify-object_property_get_enum.patch new file mode 100644 index 0000000000000000000000000000000000000000..dac5b97a93fe923b86d4e6d2e27f6802bea44640 --- /dev/null +++ b/qom-Simplify-object_property_get_enum.patch @@ -0,0 +1,32 @@ +From ea097dff0f011c07202ea7e52a421429e01ef351 Mon Sep 17 00:00:00 2001 +From: Markus Armbruster +Date: Fri, 24 Apr 2020 10:43:36 +0200 +Subject: [PATCH 085/709] qom: Simplify object_property_get_enum() + +Signed-off-by: Markus Armbruster +Reviewed-by: Eric Blake +Message-Id: <20200424084338.26803-14-armbru@redhat.com> +--- + qom/object.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +diff --git a/qom/object.c b/qom/object.c +index 1812f79224..be700e831f 100644 +--- a/qom/object.c ++++ b/qom/object.c +@@ -1550,11 +1550,9 @@ int object_property_get_enum(Object *obj, const char *name, + } + visit_complete(v, &str); + visit_free(v); +- v = string_input_visitor_new(str); +- visit_type_enum(v, name, &ret, enumprop->lookup, errp); + ++ ret = qapi_enum_parse(enumprop->lookup, str, -1, errp); + g_free(str); +- visit_free(v); + + return ret; + } +-- +2.23.0 + diff --git a/qom-Simplify-object_property_get_enum_get_str.patch b/qom-Simplify-object_property_get_enum_get_str.patch new file mode 100644 index 0000000000000000000000000000000000000000..43e618d875de258f622e11c9625653e07ae8cea9 --- /dev/null +++ b/qom-Simplify-object_property_get_enum_get_str.patch @@ -0,0 +1,49 @@ +From b555f89fcbdc797423f6d6a41b76ef5fa5272235 Mon Sep 17 00:00:00 2001 +From: Markus Armbruster +Date: Tue, 5 May 2020 17:29:12 +0200 +Subject: [PATCH 466/709] qom: Simplify object_property_get_enum() + +Reuse object_property_get_str(). Switches from the string to the +qobject visitor under the hood. + +Signed-off-by: Markus Armbruster +Message-Id: <20200505152926.18877-5-armbru@redhat.com> +Reviewed-by: Paolo Bonzini +--- + qom/object.c | 11 ++--------- + 1 file changed, 2 insertions(+), 9 deletions(-) + +diff --git a/qom/object.c b/qom/object.c +index 3d65658059..b374af302c 100644 +--- a/qom/object.c ++++ b/qom/object.c +@@ -1521,8 +1521,6 @@ typedef struct EnumProperty { + int object_property_get_enum(Object *obj, const char *name, + const char *typename, Error **errp) + { +- Error *err = NULL; +- Visitor *v; + char *str; + int ret; + ObjectProperty *prop = object_property_find(obj, name, errp); +@@ -1541,15 +1539,10 @@ int object_property_get_enum(Object *obj, const char *name, + + enumprop = prop->opaque; + +- v = string_output_visitor_new(false, &str); +- object_property_get(obj, v, name, &err); +- if (err) { +- error_propagate(errp, err); +- visit_free(v); ++ str = object_property_get_str(obj, name, errp); ++ if (!str) { + return 0; + } +- visit_complete(v, &str); +- visit_free(v); + + ret = qapi_enum_parse(enumprop->lookup, str, -1, errp); + g_free(str); +-- +2.23.0 + diff --git a/qtest-allow-DSDT-acpi-table-changes.patch b/qtest-allow-DSDT-acpi-table-changes.patch new file mode 100644 index 0000000000000000000000000000000000000000..43dc11a704970a35107e0234e0d1c3f5902d0d28 --- /dev/null +++ b/qtest-allow-DSDT-acpi-table-changes.patch @@ -0,0 +1,39 @@ +From 9604980303579ac351e1611d1b0ea8a89c3e9e6b Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann +Date: Wed, 29 Apr 2020 15:59:51 +0200 +Subject: [PATCH 208/709] qtest: allow DSDT acpi table changes + +Signed-off-by: Gerd Hoffmann +Message-Id: <20200429140003.7336-4-kraxel@redhat.com> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +--- + tests/qtest/bios-tables-test-allowed-diff.h | 17 +++++++++++++++++ + 1 file changed, 17 insertions(+) + +diff --git a/tests/qtest/bios-tables-test-allowed-diff.h b/tests/qtest/bios-tables-test-allowed-diff.h +index dfb8523c8b..6a052c5044 100644 +--- a/tests/qtest/bios-tables-test-allowed-diff.h ++++ b/tests/qtest/bios-tables-test-allowed-diff.h +@@ -1 +1,18 @@ + /* List of comma-separated changed AML files to ignore */ ++"tests/data/acpi/pc/DSDT", ++"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.ipmikcs", ++"tests/data/acpi/pc/DSDT.memhp", ++"tests/data/acpi/pc/DSDT.numamem", ++"tests/data/acpi/q35/DSDT", ++"tests/data/acpi/q35/DSDT.acpihmat", ++"tests/data/acpi/q35/DSDT.bridge", ++"tests/data/acpi/q35/DSDT.cphp", ++"tests/data/acpi/q35/DSDT.dimmpxm", ++"tests/data/acpi/q35/DSDT.ipmibt", ++"tests/data/acpi/q35/DSDT.memhp", ++"tests/data/acpi/q35/DSDT.mmio64", ++"tests/data/acpi/q35/DSDT.numamem", +-- +2.23.0 + diff --git a/qxl-check-release-info-object.patch b/qxl-check-release-info-object.patch deleted file mode 100644 index aeddbe467c34aa83a3c7b8bca6b98b44abf546a6..0000000000000000000000000000000000000000 --- a/qxl-check-release-info-object.patch +++ /dev/null @@ -1,36 +0,0 @@ -From cbed4e0108ca1403f1f47cde292330b87a0d8bf2 Mon Sep 17 00:00:00 2001 -From: Prasad J Pandit -Date: Thu, 25 Apr 2019 12:05:34 +0530 -Subject: [PATCH] qxl: check release info object - -When releasing spice resources in release_resource() routine, -if release info object 'ext.info' is null, it leads to null -pointer dereference. Add check to avoid it. - -(This is cherry-pick d52680fc932efb8a2f334cc6993e705ed1e31e99) - -Reported-by: Bugs SysSec -Signed-off-by: Prasad J Pandit -Message-id: 20190425063534.32747-1-ppandit@redhat.com -Signed-off-by: Gerd Hoffmann ---- - hw/display/qxl.c | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/hw/display/qxl.c b/hw/display/qxl.c -index c8ce578..632923a 100644 ---- a/hw/display/qxl.c -+++ b/hw/display/qxl.c -@@ -777,6 +777,9 @@ static void interface_release_resource(QXLInstance *sin, - QXLReleaseRing *ring; - uint64_t *item, id; - -+ if (!ext.info) { -+ return; -+ } - if (ext.group_id == MEMSLOT_GROUP_HOST) { - /* host group -> vga mode update request */ - QXLCommandExt *cmdext = (void *)(intptr_t)(ext.info->id); --- -1.8.3.1 - diff --git a/ramfb-add-sanity-checks-to-ramfb_create_display_surf.patch b/ramfb-add-sanity-checks-to-ramfb_create_display_surf.patch new file mode 100644 index 0000000000000000000000000000000000000000..115a2c2b887fb21be8130109b10ab9c284ecc665 --- /dev/null +++ b/ramfb-add-sanity-checks-to-ramfb_create_display_surf.patch @@ -0,0 +1,40 @@ +From 819c83e27895472befbfee67d3d7d089c61d7fbd Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann +Date: Wed, 29 Apr 2020 13:52:35 +0200 +Subject: [PATCH 513/709] ramfb: add sanity checks to + ramfb_create_display_surface + +Signed-off-by: Gerd Hoffmann +Reviewed-by: Laszlo Ersek +Message-id: 20200429115236.28709-6-kraxel@redhat.com +--- + hw/display/ramfb.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/hw/display/ramfb.c b/hw/display/ramfb.c +index 1a20bdec41..52dae78db4 100644 +--- a/hw/display/ramfb.c ++++ b/hw/display/ramfb.c +@@ -15,6 +15,7 @@ + #include "qapi/error.h" + #include "hw/loader.h" + #include "hw/display/ramfb.h" ++#include "hw/display/bochs-vbe.h" /* for limits */ + #include "ui/console.h" + #include "sysemu/reset.h" + +@@ -49,6 +50,11 @@ static DisplaySurface *ramfb_create_display_surface(int width, int height, + hwaddr size; + void *data; + ++ if (width < 16 || width > VBE_DISPI_MAX_XRES || ++ height < 16 || height > VBE_DISPI_MAX_YRES || ++ format == 0 /* unknown format */) ++ return NULL; ++ + if (linesize == 0) { + linesize = width * PIXMAN_FORMAT_BPP(format) / 8; + } +-- +2.23.0 + diff --git a/ramfb-don-t-update-RAMFBState-on-errors.patch b/ramfb-don-t-update-RAMFBState-on-errors.patch new file mode 100644 index 0000000000000000000000000000000000000000..41253b66039df73731ba192dce0d48fde6892cd7 --- /dev/null +++ b/ramfb-don-t-update-RAMFBState-on-errors.patch @@ -0,0 +1,63 @@ +From 19aaee2a65a26693fe0a30b5a0746f967774e278 Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann +Date: Wed, 29 Apr 2020 13:52:34 +0200 +Subject: [PATCH 512/709] ramfb: don't update RAMFBState on errors +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Store width & height & surface in local variables. Update RAMFBState +with the new values only in case the ramfb_create_display_surface() call +succeeds. + +Signed-off-by: Gerd Hoffmann +Reviewed-by: Philippe Mathieu-Daudé +Reviewed-by: Laszlo Ersek +Message-id: 20200429115236.28709-5-kraxel@redhat.com +--- + hw/display/ramfb.c | 26 +++++++++++++++++--------- + 1 file changed, 17 insertions(+), 9 deletions(-) + +diff --git a/hw/display/ramfb.c b/hw/display/ramfb.c +index 228defee56..1a20bdec41 100644 +--- a/hw/display/ramfb.c ++++ b/hw/display/ramfb.c +@@ -71,18 +71,26 @@ static DisplaySurface *ramfb_create_display_surface(int width, int height, + static void ramfb_fw_cfg_write(void *dev, off_t offset, size_t len) + { + RAMFBState *s = dev; +- uint32_t fourcc, format; ++ DisplaySurface *surface; ++ uint32_t fourcc, format, width, height; + hwaddr stride, addr; + +- s->width = be32_to_cpu(s->cfg.width); +- s->height = be32_to_cpu(s->cfg.height); +- stride = be32_to_cpu(s->cfg.stride); +- fourcc = be32_to_cpu(s->cfg.fourcc); +- addr = be64_to_cpu(s->cfg.addr); +- format = qemu_drm_format_to_pixman(fourcc); ++ width = be32_to_cpu(s->cfg.width); ++ height = be32_to_cpu(s->cfg.height); ++ stride = be32_to_cpu(s->cfg.stride); ++ fourcc = be32_to_cpu(s->cfg.fourcc); ++ addr = be64_to_cpu(s->cfg.addr); ++ format = qemu_drm_format_to_pixman(fourcc); ++ ++ surface = ramfb_create_display_surface(width, height, ++ format, stride, addr); ++ if (!surface) { ++ return; ++ } + +- s->ds = ramfb_create_display_surface(s->width, s->height, +- format, stride, addr); ++ s->width = width; ++ s->height = height; ++ s->ds = surface; + } + + void ramfb_display_update(QemuConsole *con, RAMFBState *s) +-- +2.23.0 + diff --git a/ramfb-drop-leftover-debug-message.patch b/ramfb-drop-leftover-debug-message.patch new file mode 100644 index 0000000000000000000000000000000000000000..88de5685509099d7c319c3fa5af571ac0672bc60 --- /dev/null +++ b/ramfb-drop-leftover-debug-message.patch @@ -0,0 +1,32 @@ +From 46a298d60271f03d4f85031827426fca67af2a20 Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann +Date: Wed, 29 Apr 2020 13:52:33 +0200 +Subject: [PATCH 511/709] ramfb: drop leftover debug message +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Gerd Hoffmann +Reviewed-by: Philippe Mathieu-Daudé +Reviewed-by: Laszlo Ersek +Message-id: 20200429115236.28709-4-kraxel@redhat.com +--- + hw/display/ramfb.c | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/hw/display/ramfb.c b/hw/display/ramfb.c +index 9d41c2ad28..228defee56 100644 +--- a/hw/display/ramfb.c ++++ b/hw/display/ramfb.c +@@ -81,8 +81,6 @@ static void ramfb_fw_cfg_write(void *dev, off_t offset, size_t len) + addr = be64_to_cpu(s->cfg.addr); + format = qemu_drm_format_to_pixman(fourcc); + +- fprintf(stderr, "%s: %dx%d @ 0x%" PRIx64 "\n", __func__, +- s->width, s->height, addr); + s->ds = ramfb_create_display_surface(s->width, s->height, + format, stride, addr); + } +-- +2.23.0 + diff --git a/ramfb-fix-size-calculation.patch b/ramfb-fix-size-calculation.patch new file mode 100644 index 0000000000000000000000000000000000000000..66c77c3cf3007de80b3e54a24225d4e0424a9429 --- /dev/null +++ b/ramfb-fix-size-calculation.patch @@ -0,0 +1,74 @@ +From 3fcf15df0073a76d37e2816597771d4c9763e413 Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann +Date: Wed, 29 Apr 2020 13:52:36 +0200 +Subject: [PATCH 514/709] ramfb: fix size calculation + +size calculation isn't correct with guest-supplied stride, the last +display line isn't accounted for correctly. + +For the typical case of stride > linesize (add padding) we error on the +safe side (calculated size is larger than actual size). + +With stride < linesize (scanlines overlap) the calculated size is +smaller than the actual size though so our guest memory mapping might +end up being too small. + +While being at it also fix ramfb_create_display_surface to use hwaddr +for the parameters. That way all calculation are done with hwaddr type +and we can't get funny effects from type castings. + +Signed-off-by: Gerd Hoffmann +Acked-by: Laszlo Ersek +Message-id: 20200429115236.28709-7-kraxel@redhat.com +--- + hw/display/ramfb.c | 19 ++++++++++--------- + 1 file changed, 10 insertions(+), 9 deletions(-) + +diff --git a/hw/display/ramfb.c b/hw/display/ramfb.c +index 52dae78db4..79b9754a58 100644 +--- a/hw/display/ramfb.c ++++ b/hw/display/ramfb.c +@@ -44,10 +44,10 @@ static void ramfb_unmap_display_surface(pixman_image_t *image, void *unused) + + static DisplaySurface *ramfb_create_display_surface(int width, int height, + pixman_format_code_t format, +- int linesize, uint64_t addr) ++ hwaddr stride, hwaddr addr) + { + DisplaySurface *surface; +- hwaddr size; ++ hwaddr size, mapsize, linesize; + void *data; + + if (width < 16 || width > VBE_DISPI_MAX_XRES || +@@ -55,19 +55,20 @@ static DisplaySurface *ramfb_create_display_surface(int width, int height, + format == 0 /* unknown format */) + return NULL; + +- if (linesize == 0) { +- linesize = width * PIXMAN_FORMAT_BPP(format) / 8; ++ linesize = width * PIXMAN_FORMAT_BPP(format) / 8; ++ if (stride == 0) { ++ stride = linesize; + } + +- size = (hwaddr)linesize * height; +- data = cpu_physical_memory_map(addr, &size, false); +- if (size != (hwaddr)linesize * height) { +- cpu_physical_memory_unmap(data, size, 0, 0); ++ mapsize = size = stride * (height - 1) + linesize; ++ data = cpu_physical_memory_map(addr, &mapsize, false); ++ if (size != mapsize) { ++ cpu_physical_memory_unmap(data, mapsize, 0, 0); + return NULL; + } + + surface = qemu_create_displaysurface_from(width, height, +- format, linesize, data); ++ format, stride, data); + pixman_image_set_destroy_function(surface->image, + ramfb_unmap_display_surface, NULL); + +-- +2.23.0 + diff --git a/raw-format-Split-raw_read_options.patch b/raw-format-Split-raw_read_options.patch new file mode 100644 index 0000000000000000000000000000000000000000..c88480c85e923cdd94ffb773e14f1a5fe9a8eade --- /dev/null +++ b/raw-format-Split-raw_read_options.patch @@ -0,0 +1,193 @@ +From 500e2434207dd3cff4f88e6d6c7b0b7b9c1a2caf Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Wed, 13 May 2020 13:05:30 +0200 +Subject: [PATCH 552/709] raw-format: Split raw_read_options() + +Split raw_read_options() into one function that actually just reads the +options, and another that applies them. This will allow us to detect +whether the user has specified any options before attaching the file +child (so we can decide on its role based on the options). + +Signed-off-by: Max Reitz +Reviewed-by: Eric Blake +Message-Id: <20200513110544.176672-21-mreitz@redhat.com> +Signed-off-by: Kevin Wolf +--- + block/raw-format.c | 110 ++++++++++++++++++++++++++------------------- + 1 file changed, 65 insertions(+), 45 deletions(-) + +diff --git a/block/raw-format.c b/block/raw-format.c +index 4b8d4ce8be..824fe70686 100644 +--- a/block/raw-format.c ++++ b/block/raw-format.c +@@ -71,20 +71,13 @@ static QemuOptsList raw_create_opts = { + } + }; + +-static int raw_read_options(QDict *options, BlockDriverState *bs, +- BDRVRawState *s, Error **errp) ++static int raw_read_options(QDict *options, uint64_t *offset, bool *has_size, ++ uint64_t *size, Error **errp) + { + Error *local_err = NULL; + QemuOpts *opts = NULL; +- int64_t real_size = 0; + int ret; + +- real_size = bdrv_getlength(bs->file->bs); +- if (real_size < 0) { +- error_setg_errno(errp, -real_size, "Could not get image size"); +- return real_size; +- } +- + opts = qemu_opts_create(&raw_runtime_opts, NULL, 0, &error_abort); + qemu_opts_absorb_qdict(opts, options, &local_err); + if (local_err) { +@@ -93,64 +86,84 @@ static int raw_read_options(QDict *options, BlockDriverState *bs, + goto end; + } + +- s->offset = qemu_opt_get_size(opts, "offset", 0); +- if (s->offset > real_size) { +- error_setg(errp, "Offset (%" PRIu64 ") cannot be greater than " +- "size of the containing file (%" PRId64 ")", +- s->offset, real_size); +- ret = -EINVAL; +- goto end; +- } ++ *offset = qemu_opt_get_size(opts, "offset", 0); ++ *has_size = qemu_opt_find(opts, "size"); ++ *size = qemu_opt_get_size(opts, "size", 0); + +- if (qemu_opt_find(opts, "size") != NULL) { +- s->size = qemu_opt_get_size(opts, "size", 0); +- s->has_size = true; +- } else { +- s->has_size = false; +- s->size = real_size - s->offset; ++ ret = 0; ++end: ++ qemu_opts_del(opts); ++ return ret; ++} ++ ++static int raw_apply_options(BlockDriverState *bs, BDRVRawState *s, ++ uint64_t offset, bool has_size, uint64_t size, ++ Error **errp) ++{ ++ int64_t real_size = 0; ++ ++ real_size = bdrv_getlength(bs->file->bs); ++ if (real_size < 0) { ++ error_setg_errno(errp, -real_size, "Could not get image size"); ++ return real_size; + } + + /* Check size and offset */ +- if ((real_size - s->offset) < s->size) { ++ if (offset > real_size) { ++ error_setg(errp, "Offset (%" PRIu64 ") cannot be greater than " ++ "size of the containing file (%" PRId64 ")", ++ s->offset, real_size); ++ return -EINVAL; ++ } ++ ++ if (has_size && (real_size - offset) < size) { + error_setg(errp, "The sum of offset (%" PRIu64 ") and size " +- "(%" PRIu64 ") has to be smaller or equal to the " +- " actual size of the containing file (%" PRId64 ")", +- s->offset, s->size, real_size); +- ret = -EINVAL; +- goto end; ++ "(%" PRIu64 ") has to be smaller or equal to the " ++ " actual size of the containing file (%" PRId64 ")", ++ s->offset, s->size, real_size); ++ return -EINVAL; + } + + /* Make sure size is multiple of BDRV_SECTOR_SIZE to prevent rounding + * up and leaking out of the specified area. */ +- if (s->has_size && !QEMU_IS_ALIGNED(s->size, BDRV_SECTOR_SIZE)) { ++ if (has_size && !QEMU_IS_ALIGNED(size, BDRV_SECTOR_SIZE)) { + error_setg(errp, "Specified size is not multiple of %llu", +- BDRV_SECTOR_SIZE); +- ret = -EINVAL; +- goto end; ++ BDRV_SECTOR_SIZE); ++ return -EINVAL; + } + +- ret = 0; +- +-end: ++ s->offset = offset; ++ s->has_size = has_size; ++ s->size = has_size ? size : real_size - offset; + +- qemu_opts_del(opts); +- +- return ret; ++ return 0; + } + + static int raw_reopen_prepare(BDRVReopenState *reopen_state, + BlockReopenQueue *queue, Error **errp) + { ++ bool has_size; ++ uint64_t offset, size; ++ int ret; ++ + assert(reopen_state != NULL); + assert(reopen_state->bs != NULL); + + reopen_state->opaque = g_new0(BDRVRawState, 1); + +- return raw_read_options( +- reopen_state->options, +- reopen_state->bs, +- reopen_state->opaque, +- errp); ++ ret = raw_read_options(reopen_state->options, &offset, &has_size, &size, ++ errp); ++ if (ret < 0) { ++ return ret; ++ } ++ ++ ret = raw_apply_options(reopen_state->bs, reopen_state->opaque, ++ offset, has_size, size, errp); ++ if (ret < 0) { ++ return ret; ++ } ++ ++ return 0; + } + + static void raw_reopen_commit(BDRVReopenState *state) +@@ -426,8 +439,15 @@ static int raw_open(BlockDriverState *bs, QDict *options, int flags, + Error **errp) + { + BDRVRawState *s = bs->opaque; ++ bool has_size; ++ uint64_t offset, size; + int ret; + ++ ret = raw_read_options(options, &offset, &has_size, &size, errp); ++ if (ret < 0) { ++ return ret; ++ } ++ + bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, 0, + false, errp); + if (!bs->file) { +@@ -455,7 +475,7 @@ static int raw_open(BlockDriverState *bs, QDict *options, int flags, + bs->file->bs->filename); + } + +- ret = raw_read_options(options, bs, s, errp); ++ ret = raw_apply_options(bs, s, offset, has_size, size, errp); + if (ret < 0) { + return ret; + } +-- +2.23.0 + diff --git a/raw-format-Support-BDRV_REQ_ZERO_WRITE-for-truncate.patch b/raw-format-Support-BDRV_REQ_ZERO_WRITE-for-truncate.patch new file mode 100644 index 0000000000000000000000000000000000000000..a8f5c2e09670cde2fa8685e55ecf4148db95c905 --- /dev/null +++ b/raw-format-Support-BDRV_REQ_ZERO_WRITE-for-truncate.patch @@ -0,0 +1,43 @@ +From 1ddaabaecb7eaeb6d8948a32340af95db44c54a1 Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Fri, 24 Apr 2020 14:54:43 +0200 +Subject: [PATCH 130/709] raw-format: Support BDRV_REQ_ZERO_WRITE for truncate + +The raw format driver can simply forward the flag and let its bs->file +child take care of actually providing the zeros. + +Signed-off-by: Kevin Wolf +Reviewed-by: Max Reitz +Reviewed-by: Eric Blake +Reviewed-by: Vladimir Sementsov-Ogievskiy +Message-Id: <20200424125448.63318-6-kwolf@redhat.com> +Signed-off-by: Kevin Wolf +--- + block/raw-format.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/block/raw-format.c b/block/raw-format.c +index 3465c9a865..351f2d91c6 100644 +--- a/block/raw-format.c ++++ b/block/raw-format.c +@@ -387,7 +387,7 @@ static int coroutine_fn raw_co_truncate(BlockDriverState *bs, int64_t offset, + + s->size = offset; + offset += s->offset; +- return bdrv_co_truncate(bs->file, offset, exact, prealloc, 0, errp); ++ return bdrv_co_truncate(bs->file, offset, exact, prealloc, flags, errp); + } + + static void raw_eject(BlockDriverState *bs, bool eject_flag) +@@ -445,6 +445,8 @@ static int raw_open(BlockDriverState *bs, QDict *options, int flags, + bs->supported_zero_flags = BDRV_REQ_WRITE_UNCHANGED | + ((BDRV_REQ_FUA | BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK) & + bs->file->bs->supported_zero_flags); ++ bs->supported_truncate_flags = bs->file->bs->supported_truncate_flags & ++ BDRV_REQ_ZERO_WRITE; + + if (bs->probed && !bdrv_is_read_only(bs)) { + bdrv_refresh_filename(bs->file->bs); +-- +2.23.0 + diff --git a/rbd-Support-BDRV_REQ_ZERO_WRITE-for-truncate.patch b/rbd-Support-BDRV_REQ_ZERO_WRITE-for-truncate.patch new file mode 100644 index 0000000000000000000000000000000000000000..1e77ddbdcf167f7f1f6a5643c354b9fa07fdcb05 --- /dev/null +++ b/rbd-Support-BDRV_REQ_ZERO_WRITE-for-truncate.patch @@ -0,0 +1,33 @@ +From 2f98910d5b89733b1a5df06c6d2a7056da32a7b7 Mon Sep 17 00:00:00 2001 +From: Eric Blake +Date: Tue, 28 Apr 2020 15:29:00 -0500 +Subject: [PATCH 352/709] rbd: Support BDRV_REQ_ZERO_WRITE for truncate + +Our .bdrv_has_zero_init_truncate always returns 1 because rbd always +0-fills; we can use that same knowledge to implement +BDRV_REQ_ZERO_WRITE by ignoring it. + +Signed-off-by: Eric Blake +Message-Id: <20200428202905.770727-5-eblake@redhat.com> +Signed-off-by: Kevin Wolf +--- + block/rbd.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/block/rbd.c b/block/rbd.c +index f2d52091c7..331c45adb2 100644 +--- a/block/rbd.c ++++ b/block/rbd.c +@@ -817,6 +817,9 @@ static int qemu_rbd_open(BlockDriverState *bs, QDict *options, int flags, + } + } + ++ /* When extending regular files, we get zeros from the OS */ ++ bs->supported_truncate_flags = BDRV_REQ_ZERO_WRITE; ++ + r = 0; + goto out; + +-- +2.23.0 + diff --git a/replication-Avoid-blk_make_empty-on-read-only-child.patch b/replication-Avoid-blk_make_empty-on-read-only-child.patch new file mode 100644 index 0000000000000000000000000000000000000000..55068950aae7c2e85042fd7641ae73ca8bb953b2 --- /dev/null +++ b/replication-Avoid-blk_make_empty-on-read-only-child.patch @@ -0,0 +1,48 @@ +From 6ecbc6c52672db5c13805735ca02784879ce8285 Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Fri, 15 May 2020 13:25:44 +0200 +Subject: [PATCH 531/709] replication: Avoid blk_make_empty() on read-only + child + +This is just a bandaid to keep tests/test-replication working after +bdrv_make_empty() starts to assert that we're not trying to call it on a +read-only child. + +For the real solution in the future, replication should not steal the +BdrvChild from its backing file (this is never correct to do!), but +instead have its own child node references, with the appropriate +permissions. + +Signed-off-by: Kevin Wolf +--- + block/replication.c | 13 +++++++++++-- + 1 file changed, 11 insertions(+), 2 deletions(-) + +diff --git a/block/replication.c b/block/replication.c +index c03980a192..eb480a8e08 100644 +--- a/block/replication.c ++++ b/block/replication.c +@@ -343,9 +343,18 @@ static void secondary_do_checkpoint(BDRVReplicationState *s, Error **errp) + return; + } + +- ret = s->hidden_disk->bs->drv->bdrv_make_empty(s->hidden_disk->bs); ++ BlockBackend *blk = blk_new(qemu_get_current_aio_context(), ++ BLK_PERM_WRITE, BLK_PERM_ALL); ++ blk_insert_bs(blk, s->hidden_disk->bs, &local_err); ++ if (local_err) { ++ error_propagate(errp, local_err); ++ blk_unref(blk); ++ return; ++ } ++ ++ ret = blk_make_empty(blk, errp); ++ blk_unref(blk); + if (ret < 0) { +- error_setg(errp, "Cannot make hidden disk empty"); + return; + } + } +-- +2.23.0 + diff --git a/riscv-AND-stage-1-and-stage-2-protection-flags.patch b/riscv-AND-stage-1-and-stage-2-protection-flags.patch new file mode 100644 index 0000000000000000000000000000000000000000..849ee26a63f7626341199b9490f723432a0c1be0 --- /dev/null +++ b/riscv-AND-stage-1-and-stage-2-protection-flags.patch @@ -0,0 +1,52 @@ +From 8f67cd6db7375f9133d900b13b300931fbc2e1d8 Mon Sep 17 00:00:00 2001 +From: Alistair Francis +Date: Thu, 26 Mar 2020 15:44:09 -0700 +Subject: [PATCH 058/709] riscv: AND stage-1 and stage-2 protection flags + +Take the result of stage-1 and stage-2 page table walks and AND the two +protection flags together. This way we require both to set permissions +instead of just stage-2. + +Signed-off-by: Alistair Francis +Reviewed-by: Richard Henderson +Tested-by: Anup Patel +Message-id: 846f1e18f5922d818bc464ec32c144ef314ec724.1585262586.git.alistair.francis@wdc.com +Message-Id: <846f1e18f5922d818bc464ec32c144ef314ec724.1585262586.git.alistair.francis@wdc.com> +--- + target/riscv/cpu_helper.c | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c +index f36d184b7b..50e13a064f 100644 +--- a/target/riscv/cpu_helper.c ++++ b/target/riscv/cpu_helper.c +@@ -707,7 +707,7 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size, + #ifndef CONFIG_USER_ONLY + vaddr im_address; + hwaddr pa = 0; +- int prot; ++ int prot, prot2; + bool pmp_violation = false; + bool m_mode_two_stage = false; + bool hs_mode_two_stage = false; +@@ -757,13 +757,15 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size, + /* Second stage lookup */ + im_address = pa; + +- ret = get_physical_address(env, &pa, &prot, im_address, ++ ret = get_physical_address(env, &pa, &prot2, im_address, + access_type, mmu_idx, false, true); + + qemu_log_mask(CPU_LOG_MMU, + "%s 2nd-stage address=%" VADDR_PRIx " ret %d physical " + TARGET_FMT_plx " prot %d\n", +- __func__, im_address, ret, pa, prot); ++ __func__, im_address, ret, pa, prot2); ++ ++ prot &= prot2; + + if (riscv_feature(env, RISCV_FEATURE_PMP) && + (ret == TRANSLATE_SUCCESS) && +-- +2.23.0 + diff --git a/riscv-Don-t-use-stage-2-PTE-lookup-protection-flags.patch b/riscv-Don-t-use-stage-2-PTE-lookup-protection-flags.patch new file mode 100644 index 0000000000000000000000000000000000000000..cb4b6fa5620df2877c8d56bd966ba75781d7cc8e --- /dev/null +++ b/riscv-Don-t-use-stage-2-PTE-lookup-protection-flags.patch @@ -0,0 +1,38 @@ +From 384728905441279e54fa3d714b11bf1b1bcbfd27 Mon Sep 17 00:00:00 2001 +From: Alistair Francis +Date: Thu, 26 Mar 2020 15:44:07 -0700 +Subject: [PATCH 057/709] riscv: Don't use stage-2 PTE lookup protection flags + +When doing the fist of a two stage lookup (Hypervisor extensions) don't +set the current protection flags from the second stage lookup of the +base address PTE. + +Signed-off-by: Alistair Francis +Reviewed-by: Richard Henderson +Tested-by: Anup Patel +Message-id: 931db85d6890ed4bc2b527fd1011197cd28299aa.1585262586.git.alistair.francis@wdc.com +Message-Id: <931db85d6890ed4bc2b527fd1011197cd28299aa.1585262586.git.alistair.francis@wdc.com> +--- + target/riscv/cpu_helper.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c +index d3ba9efb02..f36d184b7b 100644 +--- a/target/riscv/cpu_helper.c ++++ b/target/riscv/cpu_helper.c +@@ -452,10 +452,11 @@ restart: + hwaddr pte_addr; + + if (two_stage && first_stage) { ++ int vbase_prot; + hwaddr vbase; + + /* Do the second stage translation on the base PTE address. */ +- get_physical_address(env, &vbase, prot, base, access_type, ++ get_physical_address(env, &vbase, &vbase_prot, base, access_type, + mmu_idx, false, true); + + pte_addr = vbase + idx * ptesize; +-- +2.23.0 + diff --git a/riscv-Fix-Stage2-SV32-page-table-walk.patch b/riscv-Fix-Stage2-SV32-page-table-walk.patch new file mode 100644 index 0000000000000000000000000000000000000000..ff72eca4b99c6fc2a394c8530bbc1f399a37968b --- /dev/null +++ b/riscv-Fix-Stage2-SV32-page-table-walk.patch @@ -0,0 +1,52 @@ +From ee79e7cd47ef47074d7c20c221321c5d31d3683d Mon Sep 17 00:00:00 2001 +From: Anup Patel +Date: Mon, 30 Mar 2020 13:57:24 +0530 +Subject: [PATCH 059/709] riscv: Fix Stage2 SV32 page table walk + +As-per RISC-V H-Extension v0.5 draft, the Stage2 SV32 page table has +12bits of VPN[1] and 10bits of VPN[0]. The additional 2bits in VPN[1] +is required to handle the 34bit intermediate physical address coming +from Stage1 SV32 page table. The 12bits of VPN[1] implies that Stage2 +SV32 level-0 page table will be 16KB in size with total 4096 enteries +where each entry maps 4MB of memory (same as Stage1 SV32 page table). + +The get_physical_address() function is broken for Stage2 SV32 level-0 +page table because it incorrectly computes output physical address for +Stage2 SV32 level-0 page table entry. + +The root cause of the issue is that get_physical_address() uses the +"widened" variable to compute level-0 physical address mapping which +changes level-0 mapping size (instead of 4MB). We should use the +"widened" variable only for computing index of Stage2 SV32 level-0 +page table. + +Signed-off-by: Anup Patel +Reviewed-by: Alistair Francis +Message-id: 20200330082724.120444-1-anup.patel@wdc.com +Message-Id: <20200330082724.120444-1-anup.patel@wdc.com> +Signed-off-by: Alistair Francis +--- + target/riscv/cpu_helper.c | 7 +------ + 1 file changed, 1 insertion(+), 6 deletions(-) + +diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c +index 50e13a064f..bc80aa87cf 100644 +--- a/target/riscv/cpu_helper.c ++++ b/target/riscv/cpu_helper.c +@@ -559,12 +559,7 @@ restart: + /* for superpage mappings, make a fake leaf PTE for the TLB's + benefit. */ + target_ulong vpn = addr >> PGSHIFT; +- if (i == 0) { +- *physical = (ppn | (vpn & ((1L << (ptshift + widened)) - 1))) << +- PGSHIFT; +- } else { +- *physical = (ppn | (vpn & ((1L << ptshift) - 1))) << PGSHIFT; +- } ++ *physical = (ppn | (vpn & ((1L << ptshift) - 1))) << PGSHIFT; + + /* set permissions on the TLB entry */ + if ((pte & PTE_R) || ((pte & PTE_X) && mxr)) { +-- +2.23.0 + diff --git a/riscv-sifive_e-Support-changing-CPU-type.patch b/riscv-sifive_e-Support-changing-CPU-type.patch new file mode 100644 index 0000000000000000000000000000000000000000..59a823d1afdf796867e4012a809e764aa4553563 --- /dev/null +++ b/riscv-sifive_e-Support-changing-CPU-type.patch @@ -0,0 +1,58 @@ +From 74dbba9b734b3509dc3682715187339a91fcd3fb Mon Sep 17 00:00:00 2001 +From: Corey Wharton +Date: Fri, 13 Mar 2020 12:34:28 -0700 +Subject: [PATCH 061/709] riscv: sifive_e: Support changing CPU type +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Allows the CPU to be changed from the default via the -cpu command +line option. + +Signed-off-by: Corey Wharton +Reviewed-by: Bin Meng +Reviewed-by: Alistair Francis +Reviewed-by: Philippe Mathieu-Daudé +Message-id: 20200313193429.8035-2-coreyw7@fb.com +Message-Id: <20200313193429.8035-2-coreyw7@fb.com> +[ Changes by AF: + - Set "cpu-type" from the machine and not SoC +] +Signed-off-by: Alistair Francis +--- + hw/riscv/sifive_e.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/hw/riscv/sifive_e.c b/hw/riscv/sifive_e.c +index 646553a7c3..b53109521e 100644 +--- a/hw/riscv/sifive_e.c ++++ b/hw/riscv/sifive_e.c +@@ -123,8 +123,6 @@ static void riscv_sifive_e_soc_init(Object *obj) + object_initialize_child(obj, "cpus", &s->cpus, + sizeof(s->cpus), TYPE_RISCV_HART_ARRAY, + &error_abort, NULL); +- object_property_set_str(OBJECT(&s->cpus), SIFIVE_E_CPU, "cpu-type", +- &error_abort); + object_property_set_int(OBJECT(&s->cpus), ms->smp.cpus, "num-harts", + &error_abort); + sysbus_init_child_obj(obj, "riscv.sifive.e.gpio0", +@@ -141,6 +139,8 @@ static void riscv_sifive_e_soc_realize(DeviceState *dev, Error **errp) + SiFiveESoCState *s = RISCV_E_SOC(dev); + MemoryRegion *sys_mem = get_system_memory(); + ++ object_property_set_str(OBJECT(&s->cpus), ms->cpu_type, "cpu-type", ++ &error_abort); + object_property_set_bool(OBJECT(&s->cpus), true, "realized", + &error_abort); + +@@ -219,6 +219,7 @@ static void riscv_sifive_e_machine_init(MachineClass *mc) + mc->desc = "RISC-V Board compatible with SiFive E SDK"; + mc->init = riscv_sifive_e_init; + mc->max_cpus = 1; ++ mc->default_cpu_type = SIFIVE_E_CPU; + } + + DEFINE_MACHINE("sifive_e", riscv_sifive_e_machine_init) +-- +2.23.0 + diff --git a/riscv-sifive_u-Add-a-serial-property-to-the-sifive_u-m.patch b/riscv-sifive_u-Add-a-serial-property-to-the-sifive_u-m.patch new file mode 100644 index 0000000000000000000000000000000000000000..6fd750a1b4af15c9269984b528db1095b5cd7a3e --- /dev/null +++ b/riscv-sifive_u-Add-a-serial-property-to-the-sifive_u-m.patch @@ -0,0 +1,98 @@ +From 3ca109c3f8d6225efdfa801252d25f3e526b004a Mon Sep 17 00:00:00 2001 +From: Bin Meng +Date: Sat, 16 Nov 2019 07:08:50 -0800 +Subject: [PATCH 056/709] riscv/sifive_u: Add a serial property to the sifive_u + machine + +At present the board serial number is hard-coded to 1, and passed +to OTP model during initialization. Firmware (FSBL, U-Boot) uses +the serial number to generate a unique MAC address for the on-chip +ethernet controller. When multiple QEMU 'sifive_u' instances are +created and connected to the same subnet, they all have the same +MAC address hence it creates a unusable network. + +A new "serial" property is introduced to specify the board serial +number. When not given, the default serial number 1 is used. + +Signed-off-by: Bin Meng +Reviewed-by: Palmer Dabbelt +Reviewed-by: Alistair Francis +Message-Id: <1573916930-19068-1-git-send-email-bmeng.cn@gmail.com> +[ Changed by AF: + - Use the SoC's serial property to pass the info to the SoC + - Fixup commit title + - Rebase on file restructuring +] +Signed-off-by: Alistair Francis +--- + hw/riscv/sifive_u.c | 20 ++++++++++++++++++++ + include/hw/riscv/sifive_u.h | 1 + + 2 files changed, 21 insertions(+) + +diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c +index 6e659e986f..8d0ee8b9c4 100644 +--- a/hw/riscv/sifive_u.c ++++ b/hw/riscv/sifive_u.c +@@ -34,6 +34,7 @@ + #include "qemu/log.h" + #include "qemu/error-report.h" + #include "qapi/error.h" ++#include "qapi/visitor.h" + #include "hw/boards.h" + #include "hw/loader.h" + #include "hw/sysbus.h" +@@ -326,6 +327,8 @@ static void sifive_u_machine_init(MachineState *machine) + object_initialize_child(OBJECT(machine), "soc", &s->soc, + sizeof(s->soc), TYPE_RISCV_U_SOC, + &error_abort, NULL); ++ object_property_set_uint(OBJECT(&s->soc), s->serial, "serial", ++ &error_abort); + object_property_set_bool(OBJECT(&s->soc), true, "realized", + &error_abort); + +@@ -417,6 +420,18 @@ static void sifive_u_machine_set_start_in_flash(Object *obj, bool value, Error * + s->start_in_flash = value; + } + ++static void sifive_u_machine_get_serial(Object *obj, Visitor *v, const char *name, ++ void *opaque, Error **errp) ++{ ++ visit_type_uint32(v, name, (uint32_t *)opaque, errp); ++} ++ ++static void sifive_u_machine_set_serial(Object *obj, Visitor *v, const char *name, ++ void *opaque, Error **errp) ++{ ++ visit_type_uint32(v, name, (uint32_t *)opaque, errp); ++} ++ + static void sifive_u_machine_instance_init(Object *obj) + { + SiFiveUState *s = RISCV_U_MACHINE(obj); +@@ -428,6 +443,11 @@ static void sifive_u_machine_instance_init(Object *obj) + "Set on to tell QEMU's ROM to jump to " + "flash. Otherwise QEMU will jump to DRAM", + NULL); ++ ++ s->serial = OTP_SERIAL; ++ object_property_add(obj, "serial", "uint32", sifive_u_machine_get_serial, ++ sifive_u_machine_set_serial, NULL, &s->serial, NULL); ++ object_property_set_description(obj, "serial", "Board serial number", NULL); + } + + static void sifive_u_machine_class_init(ObjectClass *oc, void *data) +diff --git a/include/hw/riscv/sifive_u.h b/include/hw/riscv/sifive_u.h +index a2baa1de5f..16c297ec5f 100644 +--- a/include/hw/riscv/sifive_u.h ++++ b/include/hw/riscv/sifive_u.h +@@ -61,6 +61,7 @@ typedef struct SiFiveUState { + int fdt_size; + + bool start_in_flash; ++ uint32_t serial; + } SiFiveUState; + + enum { +-- +2.23.0 + diff --git a/riscv-sifive_u-Add-a-serial-property-to-the-sifive_u.patch b/riscv-sifive_u-Add-a-serial-property-to-the-sifive_u.patch new file mode 100644 index 0000000000000000000000000000000000000000..5072e253b5ee6ff8620a2882ee1f3f8fb1bcdcd1 --- /dev/null +++ b/riscv-sifive_u-Add-a-serial-property-to-the-sifive_u.patch @@ -0,0 +1,79 @@ +From fda5b000faf401cf595c4e87809eac3378ddbfd4 Mon Sep 17 00:00:00 2001 +From: Alistair Francis +Date: Mon, 2 Mar 2020 15:08:51 -0800 +Subject: [PATCH 055/709] riscv/sifive_u: Add a serial property to the sifive_u + SoC + +At present the board serial number is hard-coded to 1, and passed +to OTP model during initialization. Firmware (FSBL, U-Boot) uses +the serial number to generate a unique MAC address for the on-chip +ethernet controller. When multiple QEMU 'sifive_u' instances are +created and connected to the same subnet, they all have the same +MAC address hence it creates a unusable network. + +A new "serial" property is introduced to the sifive_u SoC to specify +the board serial number. When not given, the default serial number +1 is used. + +Suggested-by: Bin Meng +Signed-off-by: Alistair Francis +Reviewed-by: Bin Meng +Tested-by: Bin Meng +--- + hw/riscv/sifive_u.c | 8 +++++++- + include/hw/riscv/sifive_u.h | 2 ++ + 2 files changed, 9 insertions(+), 1 deletion(-) + +diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c +index 7f6a3c6c15..6e659e986f 100644 +--- a/hw/riscv/sifive_u.c ++++ b/hw/riscv/sifive_u.c +@@ -491,7 +491,6 @@ static void riscv_sifive_u_soc_init(Object *obj) + TYPE_SIFIVE_U_PRCI); + sysbus_init_child_obj(obj, "otp", &s->otp, sizeof(s->otp), + TYPE_SIFIVE_U_OTP); +- qdev_prop_set_uint32(DEVICE(&s->otp), "serial", OTP_SERIAL); + sysbus_init_child_obj(obj, "gem", &s->gem, sizeof(s->gem), + TYPE_CADENCE_GEM); + } +@@ -584,6 +583,7 @@ static void riscv_sifive_u_soc_realize(DeviceState *dev, Error **errp) + object_property_set_bool(OBJECT(&s->prci), true, "realized", &err); + sysbus_mmio_map(SYS_BUS_DEVICE(&s->prci), 0, memmap[SIFIVE_U_PRCI].base); + ++ qdev_prop_set_uint32(DEVICE(&s->otp), "serial", s->serial); + object_property_set_bool(OBJECT(&s->otp), true, "realized", &err); + sysbus_mmio_map(SYS_BUS_DEVICE(&s->otp), 0, memmap[SIFIVE_U_OTP].base); + +@@ -610,10 +610,16 @@ static void riscv_sifive_u_soc_realize(DeviceState *dev, Error **errp) + memmap[SIFIVE_U_GEM_MGMT].base, memmap[SIFIVE_U_GEM_MGMT].size); + } + ++static Property riscv_sifive_u_soc_props[] = { ++ DEFINE_PROP_UINT32("serial", SiFiveUSoCState, serial, OTP_SERIAL), ++ DEFINE_PROP_END_OF_LIST() ++}; ++ + static void riscv_sifive_u_soc_class_init(ObjectClass *oc, void *data) + { + DeviceClass *dc = DEVICE_CLASS(oc); + ++ device_class_set_props(dc, riscv_sifive_u_soc_props); + dc->realize = riscv_sifive_u_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/sifive_u.h b/include/hw/riscv/sifive_u.h +index 82667b5746..a2baa1de5f 100644 +--- a/include/hw/riscv/sifive_u.h ++++ b/include/hw/riscv/sifive_u.h +@@ -42,6 +42,8 @@ typedef struct SiFiveUSoCState { + SiFiveUPRCIState prci; + SiFiveUOTPState otp; + CadenceGEMState gem; ++ ++ uint32_t serial; + } SiFiveUSoCState; + + #define TYPE_RISCV_U_MACHINE MACHINE_TYPE_NAME("sifive_u") +-- +2.23.0 + diff --git a/riscv-sifive_u-Fix-up-file-ordering.patch b/riscv-sifive_u-Fix-up-file-ordering.patch new file mode 100644 index 0000000000000000000000000000000000000000..0d6b4292a9bf8a7e3ebe952d15915b9b473eb4d9 --- /dev/null +++ b/riscv-sifive_u-Fix-up-file-ordering.patch @@ -0,0 +1,153 @@ +From 523e34646788d877d16b422f43f23911eb0ea7cd Mon Sep 17 00:00:00 2001 +From: Alistair Francis +Date: Mon, 2 Mar 2020 14:57:22 -0800 +Subject: [PATCH 054/709] riscv/sifive_u: Fix up file ordering + +Split the file into clear machine and SoC sections. + +Signed-off-by: Alistair Francis +Reviewed-by: Bin Meng +--- + hw/riscv/sifive_u.c | 108 ++++++++++++++++++++++---------------------- + 1 file changed, 54 insertions(+), 54 deletions(-) + +diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c +index 998666c91f..7f6a3c6c15 100644 +--- a/hw/riscv/sifive_u.c ++++ b/hw/riscv/sifive_u.c +@@ -312,7 +312,7 @@ static void create_fdt(SiFiveUState *s, const struct MemmapEntry *memmap, + g_free(nodename); + } + +-static void riscv_sifive_u_init(MachineState *machine) ++static void sifive_u_machine_init(MachineState *machine) + { + const struct MemmapEntry *memmap = sifive_u_memmap; + SiFiveUState *s = RISCV_U_MACHINE(machine); +@@ -403,6 +403,59 @@ static void riscv_sifive_u_init(MachineState *machine) + &address_space_memory); + } + ++static bool sifive_u_machine_get_start_in_flash(Object *obj, Error **errp) ++{ ++ SiFiveUState *s = RISCV_U_MACHINE(obj); ++ ++ return s->start_in_flash; ++} ++ ++static void sifive_u_machine_set_start_in_flash(Object *obj, bool value, Error **errp) ++{ ++ SiFiveUState *s = RISCV_U_MACHINE(obj); ++ ++ s->start_in_flash = value; ++} ++ ++static void sifive_u_machine_instance_init(Object *obj) ++{ ++ SiFiveUState *s = RISCV_U_MACHINE(obj); ++ ++ s->start_in_flash = false; ++ object_property_add_bool(obj, "start-in-flash", sifive_u_machine_get_start_in_flash, ++ sifive_u_machine_set_start_in_flash, NULL); ++ object_property_set_description(obj, "start-in-flash", ++ "Set on to tell QEMU's ROM to jump to " ++ "flash. Otherwise QEMU will jump to DRAM", ++ NULL); ++} ++ ++static void sifive_u_machine_class_init(ObjectClass *oc, void *data) ++{ ++ MachineClass *mc = MACHINE_CLASS(oc); ++ ++ mc->desc = "RISC-V Board compatible with SiFive U SDK"; ++ mc->init = sifive_u_machine_init; ++ mc->max_cpus = SIFIVE_U_MANAGEMENT_CPU_COUNT + SIFIVE_U_COMPUTE_CPU_COUNT; ++ mc->min_cpus = SIFIVE_U_MANAGEMENT_CPU_COUNT + 1; ++ mc->default_cpus = mc->min_cpus; ++} ++ ++static const TypeInfo sifive_u_machine_typeinfo = { ++ .name = MACHINE_TYPE_NAME("sifive_u"), ++ .parent = TYPE_MACHINE, ++ .class_init = sifive_u_machine_class_init, ++ .instance_init = sifive_u_machine_instance_init, ++ .instance_size = sizeof(SiFiveUState), ++}; ++ ++static void sifive_u_machine_init_register_types(void) ++{ ++ type_register_static(&sifive_u_machine_typeinfo); ++} ++ ++type_init(sifive_u_machine_init_register_types) ++ + static void riscv_sifive_u_soc_init(Object *obj) + { + MachineState *ms = MACHINE(qdev_get_machine()); +@@ -443,33 +496,6 @@ static void riscv_sifive_u_soc_init(Object *obj) + TYPE_CADENCE_GEM); + } + +-static bool sifive_u_get_start_in_flash(Object *obj, Error **errp) +-{ +- SiFiveUState *s = RISCV_U_MACHINE(obj); +- +- return s->start_in_flash; +-} +- +-static void sifive_u_set_start_in_flash(Object *obj, bool value, Error **errp) +-{ +- SiFiveUState *s = RISCV_U_MACHINE(obj); +- +- s->start_in_flash = value; +-} +- +-static void riscv_sifive_u_machine_instance_init(Object *obj) +-{ +- SiFiveUState *s = RISCV_U_MACHINE(obj); +- +- s->start_in_flash = false; +- object_property_add_bool(obj, "start-in-flash", sifive_u_get_start_in_flash, +- sifive_u_set_start_in_flash, NULL); +- object_property_set_description(obj, "start-in-flash", +- "Set on to tell QEMU's ROM to jump to " +- "flash. Otherwise QEMU will jump to DRAM", +- NULL); +-} +- + static void riscv_sifive_u_soc_realize(DeviceState *dev, Error **errp) + { + MachineState *ms = MACHINE(qdev_get_machine()); +@@ -607,29 +633,3 @@ static void riscv_sifive_u_soc_register_types(void) + } + + type_init(riscv_sifive_u_soc_register_types) +- +-static void riscv_sifive_u_machine_class_init(ObjectClass *oc, void *data) +-{ +- MachineClass *mc = MACHINE_CLASS(oc); +- +- mc->desc = "RISC-V Board compatible with SiFive U SDK"; +- mc->init = riscv_sifive_u_init; +- mc->max_cpus = SIFIVE_U_MANAGEMENT_CPU_COUNT + SIFIVE_U_COMPUTE_CPU_COUNT; +- mc->min_cpus = SIFIVE_U_MANAGEMENT_CPU_COUNT + 1; +- mc->default_cpus = mc->min_cpus; +-} +- +-static const TypeInfo riscv_sifive_u_machine_typeinfo = { +- .name = MACHINE_TYPE_NAME("sifive_u"), +- .parent = TYPE_MACHINE, +- .class_init = riscv_sifive_u_machine_class_init, +- .instance_init = riscv_sifive_u_machine_instance_init, +- .instance_size = sizeof(SiFiveUState), +-}; +- +-static void riscv_sifive_u_machine_init_register_types(void) +-{ +- type_register_static(&riscv_sifive_u_machine_typeinfo); +-} +- +-type_init(riscv_sifive_u_machine_init_register_types) +-- +2.23.0 + diff --git a/rtc-add-RTC_ISA_BASE.patch b/rtc-add-RTC_ISA_BASE.patch new file mode 100644 index 0000000000000000000000000000000000000000..fbafd08f1879a7cf51ad1c5c6812dcb49d7f0e5c --- /dev/null +++ b/rtc-add-RTC_ISA_BASE.patch @@ -0,0 +1,66 @@ +From ba480fa6264b161697009448c3cbc0730485379e Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann +Date: Wed, 29 Apr 2020 15:59:54 +0200 +Subject: [PATCH 211/709] rtc: add RTC_ISA_BASE +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Add and use RTC_ISA_BASE define instead of hardcoding 0x70. + +Signed-off-by: Gerd Hoffmann +Message-Id: <20200429140003.7336-7-kraxel@redhat.com> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +Reviewed-by: Philippe Mathieu-Daudé +Reviewed-by: Igor Mammedov +--- + hw/rtc/mc146818rtc.c | 5 ++--- + include/hw/rtc/mc146818rtc.h | 1 + + 2 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/hw/rtc/mc146818rtc.c b/hw/rtc/mc146818rtc.c +index dc4269cc55..d18c09911b 100644 +--- a/hw/rtc/mc146818rtc.c ++++ b/hw/rtc/mc146818rtc.c +@@ -908,7 +908,6 @@ static void rtc_realizefn(DeviceState *dev, Error **errp) + { + ISADevice *isadev = ISA_DEVICE(dev); + RTCState *s = MC146818_RTC(dev); +- int base = 0x70; + + s->cmos_data[RTC_REG_A] = 0x26; + s->cmos_data[RTC_REG_B] = 0x02; +@@ -951,7 +950,7 @@ static void rtc_realizefn(DeviceState *dev, Error **errp) + qemu_register_suspend_notifier(&s->suspend_notifier); + + memory_region_init_io(&s->io, OBJECT(s), &cmos_ops, s, "rtc", 2); +- isa_register_ioport(isadev, &s->io, base); ++ isa_register_ioport(isadev, &s->io, RTC_ISA_BASE); + + /* register rtc 0x70 port for coalesced_pio */ + memory_region_set_flush_coalesced(&s->io); +@@ -960,7 +959,7 @@ static void rtc_realizefn(DeviceState *dev, Error **errp) + memory_region_add_subregion(&s->io, 0, &s->coalesced_io); + memory_region_add_coalescing(&s->coalesced_io, 0, 1); + +- qdev_set_legacy_instance_id(dev, base, 3); ++ qdev_set_legacy_instance_id(dev, RTC_ISA_BASE, 3); + qemu_register_reset(rtc_reset, s); + + object_property_add_tm(OBJECT(s), "date", rtc_get_date, NULL); +diff --git a/include/hw/rtc/mc146818rtc.h b/include/hw/rtc/mc146818rtc.h +index 10c93a096a..3713181b56 100644 +--- a/include/hw/rtc/mc146818rtc.h ++++ b/include/hw/rtc/mc146818rtc.h +@@ -47,6 +47,7 @@ typedef struct RTCState { + } RTCState; + + #define RTC_ISA_IRQ 8 ++#define RTC_ISA_BASE 0x70 + + ISADevice *mc146818_rtc_init(ISABus *bus, int base_year, + qemu_irq intercept_irq); +-- +2.23.0 + diff --git a/s390x-Add-SIDA-memory-ops.patch b/s390x-Add-SIDA-memory-ops.patch new file mode 100644 index 0000000000000000000000000000000000000000..2d3edfca6e940cb9a82d3e8fd9234370db9332f8 --- /dev/null +++ b/s390x-Add-SIDA-memory-ops.patch @@ -0,0 +1,137 @@ +From 1cca8265499d394d9ed4bfb75bd6e7265b529f89 Mon Sep 17 00:00:00 2001 +From: Janosch Frank +Date: Thu, 19 Mar 2020 09:19:12 -0400 +Subject: [PATCH 040/709] s390x: Add SIDA memory ops + +Protected guests save the instruction control blocks in the SIDA +instead of QEMU/KVM directly accessing the guest's memory. + +Let's introduce new functions to access the SIDA. + +The memops for doing so are available with KVM_CAP_S390_PROTECTED, so +let's check for that. + +Signed-off-by: Janosch Frank +Reviewed-by: David Hildenbrand +Reviewed-by: Christian Borntraeger +Reviewed-by: Claudio Imbrenda +Reviewed-by: Cornelia Huck +Message-Id: <20200319131921.2367-8-frankja@linux.ibm.com> +Signed-off-by: Cornelia Huck +--- + target/s390x/cpu.h | 7 ++++++- + target/s390x/kvm.c | 26 ++++++++++++++++++++++++++ + target/s390x/kvm_s390x.h | 2 ++ + target/s390x/mmu_helper.c | 14 ++++++++++++++ + 4 files changed, 48 insertions(+), 1 deletion(-) + +diff --git a/target/s390x/cpu.h b/target/s390x/cpu.h +index 1d17709d6e..035427521c 100644 +--- a/target/s390x/cpu.h ++++ b/target/s390x/cpu.h +@@ -823,7 +823,12 @@ int s390_cpu_virt_mem_rw(S390CPU *cpu, vaddr laddr, uint8_t ar, void *hostbuf, + #define s390_cpu_virt_mem_check_write(cpu, laddr, ar, len) \ + s390_cpu_virt_mem_rw(cpu, laddr, ar, NULL, len, true) + void s390_cpu_virt_mem_handle_exc(S390CPU *cpu, uintptr_t ra); +- ++int s390_cpu_pv_mem_rw(S390CPU *cpu, unsigned int offset, void *hostbuf, ++ int len, bool is_write); ++#define s390_cpu_pv_mem_read(cpu, offset, dest, len) \ ++ s390_cpu_pv_mem_rw(cpu, offset, dest, len, false) ++#define s390_cpu_pv_mem_write(cpu, offset, dest, len) \ ++ s390_cpu_pv_mem_rw(cpu, offset, dest, len, true) + + /* sigp.c */ + int s390_cpu_restart(S390CPU *cpu); +diff --git a/target/s390x/kvm.c b/target/s390x/kvm.c +index 1988809ec2..0e93778ed1 100644 +--- a/target/s390x/kvm.c ++++ b/target/s390x/kvm.c +@@ -154,6 +154,7 @@ static int cap_ri; + static int cap_gs; + static int cap_hpage_1m; + static int cap_vcpu_resets; ++static int cap_protected; + + static int active_cmma; + +@@ -351,6 +352,7 @@ int kvm_arch_init(MachineState *ms, KVMState *s) + cap_mem_op = kvm_check_extension(s, KVM_CAP_S390_MEM_OP); + 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); + + if (!kvm_check_extension(s, KVM_CAP_S390_GMAP) + || !kvm_check_extension(s, KVM_CAP_S390_COW)) { +@@ -851,6 +853,30 @@ int kvm_s390_mem_op(S390CPU *cpu, vaddr addr, uint8_t ar, void *hostbuf, + return ret; + } + ++int kvm_s390_mem_op_pv(S390CPU *cpu, uint64_t offset, void *hostbuf, ++ int len, bool is_write) ++{ ++ struct kvm_s390_mem_op mem_op = { ++ .sida_offset = offset, ++ .size = len, ++ .op = is_write ? KVM_S390_MEMOP_SIDA_WRITE ++ : KVM_S390_MEMOP_SIDA_READ, ++ .buf = (uint64_t)hostbuf, ++ }; ++ int ret; ++ ++ if (!cap_mem_op || !cap_protected) { ++ return -ENOSYS; ++ } ++ ++ ret = kvm_vcpu_ioctl(CPU(cpu), KVM_S390_MEM_OP, &mem_op); ++ if (ret < 0) { ++ error_report("KVM_S390_MEM_OP failed: %s", strerror(-ret)); ++ abort(); ++ } ++ return ret; ++} ++ + /* + * Legacy layout for s390: + * Older S390 KVM requires the topmost vma of the RAM to be +diff --git a/target/s390x/kvm_s390x.h b/target/s390x/kvm_s390x.h +index dea813f450..6ab17c81b7 100644 +--- a/target/s390x/kvm_s390x.h ++++ b/target/s390x/kvm_s390x.h +@@ -19,6 +19,8 @@ void kvm_s390_vcpu_interrupt(S390CPU *cpu, struct kvm_s390_irq *irq); + void kvm_s390_access_exception(S390CPU *cpu, uint16_t code, uint64_t te_code); + int kvm_s390_mem_op(S390CPU *cpu, vaddr addr, uint8_t ar, void *hostbuf, + int len, bool is_write); ++int kvm_s390_mem_op_pv(S390CPU *cpu, vaddr addr, void *hostbuf, int len, ++ bool is_write); + void kvm_s390_program_interrupt(S390CPU *cpu, uint16_t code); + int kvm_s390_set_cpu_state(S390CPU *cpu, uint8_t cpu_state); + void kvm_s390_vcpu_interrupt_pre_save(S390CPU *cpu); +diff --git a/target/s390x/mmu_helper.c b/target/s390x/mmu_helper.c +index 0be2f300bb..7d9f3059cd 100644 +--- a/target/s390x/mmu_helper.c ++++ b/target/s390x/mmu_helper.c +@@ -474,6 +474,20 @@ static int translate_pages(S390CPU *cpu, vaddr addr, int nr_pages, + return 0; + } + ++int s390_cpu_pv_mem_rw(S390CPU *cpu, unsigned int offset, void *hostbuf, ++ int len, bool is_write) ++{ ++ int ret; ++ ++ if (kvm_enabled()) { ++ ret = kvm_s390_mem_op_pv(cpu, offset, hostbuf, len, is_write); ++ } else { ++ /* Protected Virtualization is a KVM/Hardware only feature */ ++ g_assert_not_reached(); ++ } ++ return ret; ++} ++ + /** + * s390_cpu_virt_mem_rw: + * @laddr: the logical start address +-- +2.23.0 + diff --git a/s390x-Add-unpack-facility-feature-to-GA1.patch b/s390x-Add-unpack-facility-feature-to-GA1.patch new file mode 100644 index 0000000000000000000000000000000000000000..af5ace4fda49120d1a69bed205243de1b28955e7 --- /dev/null +++ b/s390x-Add-unpack-facility-feature-to-GA1.patch @@ -0,0 +1,63 @@ +From 572c0826615737f1c095b1b6d9e381ec40f72eb5 Mon Sep 17 00:00:00 2001 +From: Christian Borntraeger +Date: Thu, 19 Mar 2020 09:19:21 -0400 +Subject: [PATCH 049/709] s390x: Add unpack facility feature to GA1 + +The unpack facility is an indication that diagnose 308 subcodes 8-10 +are available to the guest. That means, that the guest can put itself +into protected mode. + +Once it is in protected mode, the hardware stops any attempt of VM +introspection by the hypervisor. + +Some features are currently not supported in protected mode: + * vfio devices + * Migration + * Huge page backings + +Signed-off-by: Christian Borntraeger +Signed-off-by: Janosch Frank +Reviewed-by: David Hildenbrand +Reviewed-by: Claudio Imbrenda +Reviewed-by: Cornelia Huck +Message-Id: <20200319131921.2367-17-frankja@linux.ibm.com> +Signed-off-by: Cornelia Huck +--- + target/s390x/gen-features.c | 1 + + target/s390x/kvm.c | 8 ++++++++ + 2 files changed, 9 insertions(+) + +diff --git a/target/s390x/gen-features.c b/target/s390x/gen-features.c +index 6278845b12..8ddeebc544 100644 +--- a/target/s390x/gen-features.c ++++ b/target/s390x/gen-features.c +@@ -562,6 +562,7 @@ static uint16_t full_GEN15_GA1[] = { + S390_FEAT_GROUP_MSA_EXT_9, + S390_FEAT_GROUP_MSA_EXT_9_PCKMO, + S390_FEAT_ETOKEN, ++ S390_FEAT_UNPACK, + }; + + /* Default features (in order of release) +diff --git a/target/s390x/kvm.c b/target/s390x/kvm.c +index 870dd1b52b..69881a0da0 100644 +--- a/target/s390x/kvm.c ++++ b/target/s390x/kvm.c +@@ -2425,6 +2425,14 @@ void kvm_s390_get_host_cpu_model(S390CPUModel *model, Error **errp) + clear_bit(S390_FEAT_BPB, model->features); + } + ++ /* ++ * If we have support for protected virtualization, indicate ++ * the protected virtualization IPL unpack facility. ++ */ ++ if (cap_protected) { ++ set_bit(S390_FEAT_UNPACK, model->features); ++ } ++ + /* We emulate a zPCI bus and AEN, therefore we don't need HW support */ + set_bit(S390_FEAT_ZPCI, model->features); + set_bit(S390_FEAT_ADAPTER_EVENT_NOTIFICATION, model->features); +-- +2.23.0 + diff --git a/s390x-Move-diagnose-308-subcodes-and-rcs-into-ipl.h.patch b/s390x-Move-diagnose-308-subcodes-and-rcs-into-ipl.h.patch new file mode 100644 index 0000000000000000000000000000000000000000..412a21336b05f25b607f9b92e2543268b859fb7d --- /dev/null +++ b/s390x-Move-diagnose-308-subcodes-and-rcs-into-ipl.h.patch @@ -0,0 +1,66 @@ +From 9b39d29470e9dbef24ee842a44ea56bd92b855ea Mon Sep 17 00:00:00 2001 +From: Janosch Frank +Date: Thu, 19 Mar 2020 09:19:06 -0400 +Subject: [PATCH 003/709] s390x: Move diagnose 308 subcodes and rcs into ipl.h + +They are part of the IPL process, so let's put them into the ipl +header. + +Signed-off-by: Janosch Frank +Reviewed-by: Cornelia Huck +Reviewed-by: Christian Borntraeger +Reviewed-by: David Hildenbrand +Message-Id: <20200319131921.2367-2-frankja@linux.ibm.com> +Signed-off-by: Cornelia Huck +--- + hw/s390x/ipl.h | 11 +++++++++++ + target/s390x/diag.c | 11 ----------- + 2 files changed, 11 insertions(+), 11 deletions(-) + +diff --git a/hw/s390x/ipl.h b/hw/s390x/ipl.h +index 3e44abe1c6..a5665e6bfd 100644 +--- a/hw/s390x/ipl.h ++++ b/hw/s390x/ipl.h +@@ -159,6 +159,17 @@ struct S390IPLState { + typedef struct S390IPLState S390IPLState; + QEMU_BUILD_BUG_MSG(offsetof(S390IPLState, iplb) & 3, "alignment of iplb wrong"); + ++#define DIAG_308_RC_OK 0x0001 ++#define DIAG_308_RC_NO_CONF 0x0102 ++#define DIAG_308_RC_INVALID 0x0402 ++ ++#define DIAG308_RESET_MOD_CLR 0 ++#define DIAG308_RESET_LOAD_NORM 1 ++#define DIAG308_LOAD_CLEAR 3 ++#define DIAG308_LOAD_NORMAL_DUMP 4 ++#define DIAG308_SET 5 ++#define DIAG308_STORE 6 ++ + #define S390_IPL_TYPE_FCP 0x00 + #define S390_IPL_TYPE_CCW 0x02 + #define S390_IPL_TYPE_QEMU_SCSI 0xff +diff --git a/target/s390x/diag.c b/target/s390x/diag.c +index 54e5670b3f..8aba6341f9 100644 +--- a/target/s390x/diag.c ++++ b/target/s390x/diag.c +@@ -49,17 +49,6 @@ int handle_diag_288(CPUS390XState *env, uint64_t r1, uint64_t r3) + return diag288_class->handle_timer(diag288, func, timeout); + } + +-#define DIAG_308_RC_OK 0x0001 +-#define DIAG_308_RC_NO_CONF 0x0102 +-#define DIAG_308_RC_INVALID 0x0402 +- +-#define DIAG308_RESET_MOD_CLR 0 +-#define DIAG308_RESET_LOAD_NORM 1 +-#define DIAG308_LOAD_CLEAR 3 +-#define DIAG308_LOAD_NORMAL_DUMP 4 +-#define DIAG308_SET 5 +-#define DIAG308_STORE 6 +- + static int diag308_parm_check(CPUS390XState *env, uint64_t r1, uint64_t addr, + uintptr_t ra, bool write) + { +-- +2.23.0 + diff --git a/s390x-cpumodel-Fix-UI-to-CPU-features-pcc-cmac-aes-e.patch b/s390x-cpumodel-Fix-UI-to-CPU-features-pcc-cmac-aes-e.patch new file mode 100644 index 0000000000000000000000000000000000000000..eea57580588b42c1a66affc1bb269ea96a4d1026 --- /dev/null +++ b/s390x-cpumodel-Fix-UI-to-CPU-features-pcc-cmac-aes-e.patch @@ -0,0 +1,67 @@ +From e274408cdc07b431ef6dfdbb5011c5ef434702e8 Mon Sep 17 00:00:00 2001 +From: Markus Armbruster +Date: Tue, 5 May 2020 17:29:17 +0200 +Subject: [PATCH 471/709] s390x/cpumodel: Fix UI to CPU features + pcc-cmac-{aes,eaes}-256 + +Both s390_features[S390_FEAT_PCC_CMAC_AES_256].name and +s390_features[S390_FEAT_PCC_CMAC_EAES_256].name is +"pcc-cmac-eaes-256". The former is obviously a pasto. + +Impact: + +* s390_feat_bitmap_to_ascii() misidentifies S390_FEAT_PCC_CMAC_AES_256 + as "pcc-cmac-eaes-256". Affects QMP commands query-cpu-definitions, + query-cpu-model-expansion, query-cpu-model-baseline, + query-cpu-model-comparison, and the error message when + s390_realize_cpu_model() fails in check_compatibility(). + +* s390_cpu_list() also misidentifies it. Affects -cpu help. + +* s390_cpu_model_register_props() creates CPU property + "pcc-cmac-eaes-256" twice. The second one fails, but the error is + ignored (a later commit will change that). Results in a single + property "pcc-cmac-eaes-256" with the description for + S390_FEAT_PCC_CMAC_AES_256, and no property for + S390_FEAT_PCC_CMAC_EAES_256. CPU properties are visible in CLI -cpu + and -device, QMP & HMP device_add, QMP device-list-properties, and + QOM introspection. + +The two features are almost always used via their group msa4. Such +use is not affected by this bug. + +Fix by deleting the wayward 'e'. + +Fixes: 782417446279 ("s390x/cpumodel: introduce CPU features") +Cc: Halil Pasic +Cc: Cornelia Huck +Cc: Christian Borntraeger +Cc: Richard Henderson +Cc: David Hildenbrand +Cc: qemu-s390x@nongnu.org +Signed-off-by: Markus Armbruster +Reviewed-by: David Hildenbrand +Tested-by: Christian Borntraeger +Message-Id: <20200505152926.18877-10-armbru@redhat.com> +Reviewed-by: Cornelia Huck +[Lost paragraph in commit message restored, Fixes: tweaked] +--- + target/s390x/cpu_features_def.inc.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/target/s390x/cpu_features_def.inc.h b/target/s390x/cpu_features_def.inc.h +index 60db28351d..5942f81f16 100644 +--- a/target/s390x/cpu_features_def.inc.h ++++ b/target/s390x/cpu_features_def.inc.h +@@ -311,7 +311,7 @@ DEF_FEAT(PCC_CMAC_ETDEA_192, "pcc-cmac-etdea-128", PCC, 10, "PCC Compute-Last-Bl + DEF_FEAT(PCC_CMAC_TDEA, "pcc-cmac-etdea-192", PCC, 11, "PCC Compute-Last-Block-CMAC-Using-EncryptedTDEA-192") + DEF_FEAT(PCC_CMAC_AES_128, "pcc-cmac-aes-128", PCC, 18, "PCC Compute-Last-Block-CMAC-Using-AES-128") + DEF_FEAT(PCC_CMAC_AES_192, "pcc-cmac-aes-192", PCC, 19, "PCC Compute-Last-Block-CMAC-Using-AES-192") +-DEF_FEAT(PCC_CMAC_AES_256, "pcc-cmac-eaes-256", PCC, 20, "PCC Compute-Last-Block-CMAC-Using-AES-256") ++DEF_FEAT(PCC_CMAC_AES_256, "pcc-cmac-aes-256", PCC, 20, "PCC Compute-Last-Block-CMAC-Using-AES-256") + DEF_FEAT(PCC_CMAC_EAES_128, "pcc-cmac-eaes-128", PCC, 26, "PCC Compute-Last-Block-CMAC-Using-Encrypted-AES-128") + DEF_FEAT(PCC_CMAC_EAES_192, "pcc-cmac-eaes-192", PCC, 27, "PCC Compute-Last-Block-CMAC-Using-Encrypted-AES-192") + DEF_FEAT(PCC_CMAC_EAES_256, "pcc-cmac-eaes-256", PCC, 28, "PCC Compute-Last-Block-CMAC-Using-Encrypted-AES-256") +-- +2.23.0 + diff --git a/s390x-protvirt-Add-migration-blocker.patch b/s390x-protvirt-Add-migration-blocker.patch new file mode 100644 index 0000000000000000000000000000000000000000..f3d8b1e0b9ec1f73ae8bb14c35dc761a1ddc4bed --- /dev/null +++ b/s390x-protvirt-Add-migration-blocker.patch @@ -0,0 +1,66 @@ +From 0141e1b47707d90f5bd9d252da064ebdaca698a6 Mon Sep 17 00:00:00 2001 +From: Janosch Frank +Date: Thu, 19 Mar 2020 09:19:09 -0400 +Subject: [PATCH 037/709] s390x: protvirt: Add migration blocker + +Migration is not yet supported. + +Signed-off-by: Janosch Frank +Reviewed-by: David Hildenbrand +Reviewed-by: Christian Borntraeger +Reviewed-by: Claudio Imbrenda +Reviewed-by: Cornelia Huck +Message-Id: <20200319131921.2367-5-frankja@linux.ibm.com> +Signed-off-by: Cornelia Huck +--- + hw/s390x/s390-virtio-ccw.c | 18 ++++++++++++++++++ + 1 file changed, 18 insertions(+) + +diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c +index b4d681da43..e00040a00b 100644 +--- a/hw/s390x/s390-virtio-ccw.c ++++ b/hw/s390x/s390-virtio-ccw.c +@@ -45,6 +45,9 @@ + #include "sysemu/sysemu.h" + #include "hw/s390x/pv.h" + #include ++#include "migration/blocker.h" ++ ++static Error *pv_mig_blocker; + + S390CPU *s390_cpu_addr2state(uint16_t cpu_addr) + { +@@ -324,15 +327,30 @@ static void s390_machine_unprotect(S390CcwMachineState *ms) + { + s390_pv_vm_disable(); + ms->pv = false; ++ migrate_del_blocker(pv_mig_blocker); ++ error_free_or_abort(&pv_mig_blocker); + } + + static int s390_machine_protect(S390CcwMachineState *ms) + { ++ Error *local_err = NULL; + int rc; + ++ error_setg(&pv_mig_blocker, ++ "protected VMs are currently not migrateable."); ++ rc = migrate_add_blocker(pv_mig_blocker, &local_err); ++ if (rc) { ++ error_report_err(local_err); ++ error_free_or_abort(&pv_mig_blocker); ++ return rc; ++ } ++ + /* Create SE VM */ + rc = s390_pv_vm_enable(); + if (rc) { ++ error_report_err(local_err); ++ migrate_del_blocker(pv_mig_blocker); ++ error_free_or_abort(&pv_mig_blocker); + return rc; + } + +-- +2.23.0 + diff --git a/s390x-protvirt-Disable-address-checks-for-PV-guest-I.patch b/s390x-protvirt-Disable-address-checks-for-PV-guest-I.patch new file mode 100644 index 0000000000000000000000000000000000000000..e99c1fbc3a7629b89616d23d06025f9f0c066b5f --- /dev/null +++ b/s390x-protvirt-Disable-address-checks-for-PV-guest-I.patch @@ -0,0 +1,122 @@ +From c10b708752e5264a85b5c3afa0a0ccfcf6503ddf Mon Sep 17 00:00:00 2001 +From: Janosch Frank +Date: Thu, 19 Mar 2020 09:19:17 -0400 +Subject: [PATCH 045/709] s390x: protvirt: Disable address checks for PV guest + IO emulation + +IO instruction data is routed through SIDAD for protected guests, so +adresses do not need to be checked, as this is kernel memory which is +always available. + +Also the instruction data always starts at offset 0 of the SIDAD. + +Signed-off-by: Janosch Frank +Reviewed-by: Thomas Huth +Reviewed-by: David Hildenbrand +Reviewed-by: Christian Borntraeger +Reviewed-by: Claudio Imbrenda +Reviewed-by: Cornelia Huck +Message-Id: <20200319131921.2367-13-frankja@linux.ibm.com> +Signed-off-by: Cornelia Huck +--- + target/s390x/ioinst.c | 35 ++++++++++++++++++++++++++++------- + 1 file changed, 28 insertions(+), 7 deletions(-) + +diff --git a/target/s390x/ioinst.c b/target/s390x/ioinst.c +index 0e840cc579..8828482eec 100644 +--- a/target/s390x/ioinst.c ++++ b/target/s390x/ioinst.c +@@ -16,6 +16,25 @@ + #include "hw/s390x/ioinst.h" + #include "trace.h" + #include "hw/s390x/s390-pci-bus.h" ++#include "hw/s390x/pv.h" ++ ++/* All I/O instructions but chsc use the s format */ ++static uint64_t get_address_from_regs(CPUS390XState *env, uint32_t ipb, ++ uint8_t *ar) ++{ ++ /* ++ * Addresses for protected guests are all offsets into the ++ * satellite block which holds the IO control structures. Those ++ * control structures are always starting at offset 0 and are ++ * always aligned and accessible. So we can return 0 here which ++ * will pass the following address checks. ++ */ ++ if (s390_is_pv()) { ++ *ar = 0; ++ return 0; ++ } ++ return decode_basedisp_s(env, ipb, ar); ++} + + int ioinst_disassemble_sch_ident(uint32_t value, int *m, int *cssid, int *ssid, + int *schid) +@@ -114,7 +133,7 @@ void ioinst_handle_msch(S390CPU *cpu, uint64_t reg1, uint32_t ipb, uintptr_t ra) + CPUS390XState *env = &cpu->env; + uint8_t ar; + +- addr = decode_basedisp_s(env, ipb, &ar); ++ addr = get_address_from_regs(env, ipb, &ar); + if (addr & 3) { + s390_program_interrupt(env, PGM_SPECIFICATION, ra); + return; +@@ -171,7 +190,7 @@ void ioinst_handle_ssch(S390CPU *cpu, uint64_t reg1, uint32_t ipb, uintptr_t ra) + CPUS390XState *env = &cpu->env; + uint8_t ar; + +- addr = decode_basedisp_s(env, ipb, &ar); ++ addr = get_address_from_regs(env, ipb, &ar); + if (addr & 3) { + s390_program_interrupt(env, PGM_SPECIFICATION, ra); + return; +@@ -203,7 +222,7 @@ void ioinst_handle_stcrw(S390CPU *cpu, uint32_t ipb, uintptr_t ra) + CPUS390XState *env = &cpu->env; + uint8_t ar; + +- addr = decode_basedisp_s(env, ipb, &ar); ++ addr = get_address_from_regs(env, ipb, &ar); + if (addr & 3) { + s390_program_interrupt(env, PGM_SPECIFICATION, ra); + return; +@@ -234,7 +253,7 @@ void ioinst_handle_stsch(S390CPU *cpu, uint64_t reg1, uint32_t ipb, + CPUS390XState *env = &cpu->env; + uint8_t ar; + +- addr = decode_basedisp_s(env, ipb, &ar); ++ addr = get_address_from_regs(env, ipb, &ar); + if (addr & 3) { + s390_program_interrupt(env, PGM_SPECIFICATION, ra); + return; +@@ -303,7 +322,7 @@ int ioinst_handle_tsch(S390CPU *cpu, uint64_t reg1, uint32_t ipb, uintptr_t ra) + return -EIO; + } + trace_ioinst_sch_id("tsch", cssid, ssid, schid); +- addr = decode_basedisp_s(env, ipb, &ar); ++ addr = get_address_from_regs(env, ipb, &ar); + if (addr & 3) { + s390_program_interrupt(env, PGM_SPECIFICATION, ra); + return -EIO; +@@ -601,7 +620,7 @@ void ioinst_handle_chsc(S390CPU *cpu, uint32_t ipb, uintptr_t ra) + { + ChscReq *req; + ChscResp *res; +- uint64_t addr; ++ uint64_t addr = 0; + int reg; + uint16_t len; + uint16_t command; +@@ -610,7 +629,9 @@ void ioinst_handle_chsc(S390CPU *cpu, uint32_t ipb, uintptr_t ra) + + trace_ioinst("chsc"); + reg = (ipb >> 20) & 0x00f; +- addr = env->regs[reg]; ++ if (!s390_is_pv()) { ++ addr = env->regs[reg]; ++ } + /* Page boundary? */ + if (addr & 0xfff) { + s390_program_interrupt(env, PGM_SPECIFICATION, ra); +-- +2.23.0 + diff --git a/s390x-protvirt-Fix-stray-error_report_err-in-s390_ma.patch b/s390x-protvirt-Fix-stray-error_report_err-in-s390_ma.patch new file mode 100644 index 0000000000000000000000000000000000000000..1fe2d25bacbc0311c1d51b3b9f21f142c41bb6ab --- /dev/null +++ b/s390x-protvirt-Fix-stray-error_report_err-in-s390_ma.patch @@ -0,0 +1,38 @@ +From 7152c9ecc6530ea145c122b0a58cc28802f630c6 Mon Sep 17 00:00:00 2001 +From: Janosch Frank +Date: Thu, 26 Mar 2020 10:05:05 -0400 +Subject: [PATCH 050/709] s390x: protvirt: Fix stray error_report_err in + s390_machine_protect + +In case the protection of the machine fails at s390_pv_vm_enable(), +we'll currently report the local_error variable. Problem is that +there's no migration blocker error that we can report at this point so +the pointer is always NULL which leads to a SEGFAULT. + +Let's remove the error report. + +Signed-off-by: Janosch Frank +Reported-by: Marc Hartmayer +Fixes: 0141e1b47707 ("s390x: protvirt: Add migration blocker") +Message-Id: <20200326140505.2432-1-frankja@linux.ibm.com> +Reviewed-by: David Hildenbrand +Signed-off-by: Cornelia Huck +--- + hw/s390x/s390-virtio-ccw.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c +index db45249320..b268907395 100644 +--- a/hw/s390x/s390-virtio-ccw.c ++++ b/hw/s390x/s390-virtio-ccw.c +@@ -359,7 +359,6 @@ static int s390_machine_protect(S390CcwMachineState *ms) + rc = s390_pv_vm_enable(); + if (rc) { + qemu_balloon_inhibit(false); +- error_report_err(local_err); + migrate_del_blocker(pv_mig_blocker); + error_free_or_abort(&pv_mig_blocker); + return rc; +-- +2.23.0 + diff --git a/s390x-protvirt-Handle-SIGP-store-status-correctly.patch b/s390x-protvirt-Handle-SIGP-store-status-correctly.patch new file mode 100644 index 0000000000000000000000000000000000000000..846eb6499763f25a6164f978b2ee314eb050d8e9 --- /dev/null +++ b/s390x-protvirt-Handle-SIGP-store-status-correctly.patch @@ -0,0 +1,46 @@ +From f2a2d9a2bae8f6fdc5e9a40c1241e9428f15b4df Mon Sep 17 00:00:00 2001 +From: Janosch Frank +Date: Thu, 19 Mar 2020 09:19:19 -0400 +Subject: [PATCH 047/709] s390x: protvirt: Handle SIGP store status correctly + +For protected VMs status storing is not done by QEMU anymore. + +Signed-off-by: Janosch Frank +Reviewed-by: Thomas Huth +Reviewed-by: David Hildenbrand +Reviewed-by: Christian Borntraeger +Reviewed-by: Claudio Imbrenda +Reviewed-by: Cornelia Huck +Message-Id: <20200319131921.2367-15-frankja@linux.ibm.com> +Signed-off-by: Cornelia Huck +--- + target/s390x/helper.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/target/s390x/helper.c b/target/s390x/helper.c +index ed72684911..09f60406aa 100644 +--- a/target/s390x/helper.c ++++ b/target/s390x/helper.c +@@ -25,6 +25,7 @@ + #include "qemu/timer.h" + #include "qemu/qemu-print.h" + #include "hw/s390x/ioinst.h" ++#include "hw/s390x/pv.h" + #include "sysemu/hw_accel.h" + #include "sysemu/runstate.h" + #ifndef CONFIG_USER_ONLY +@@ -246,6 +247,11 @@ int s390_store_status(S390CPU *cpu, hwaddr addr, bool store_arch) + hwaddr len = sizeof(*sa); + int i; + ++ /* For PVMs storing will occur when this cpu enters SIE again */ ++ if (s390_is_pv()) { ++ return 0; ++ } ++ + sa = cpu_physical_memory_map(addr, &len, true); + if (!sa) { + return -EFAULT; +-- +2.23.0 + diff --git a/s390x-protvirt-Inhibit-balloon-when-switching-to-pro.patch b/s390x-protvirt-Inhibit-balloon-when-switching-to-pro.patch new file mode 100644 index 0000000000000000000000000000000000000000..f02ed44e09c7eec4fd49a929d1f857c89157175f --- /dev/null +++ b/s390x-protvirt-Inhibit-balloon-when-switching-to-pro.patch @@ -0,0 +1,87 @@ +From b1697f63fd8f8201b1447bb55f595830b9cbde31 Mon Sep 17 00:00:00 2001 +From: Janosch Frank +Date: Thu, 19 Mar 2020 09:19:10 -0400 +Subject: [PATCH 038/709] s390x: protvirt: Inhibit balloon when switching to + protected mode + +Ballooning in protected VMs can only be done when the guest shares the +pages it gives to the host. If pages are not shared, the integrity +checks will fail once those pages have been altered and are given back +to the guest. + +As we currently do not yet have a solution for this we will continue +like this: + +1. We block ballooning now in QEMU (with this patch). + +2. Later we will provide a change to virtio that removes the blocker +and adds VIRTIO_F_IOMMU_PLATFORM automatically by QEMU when doing the +protvirt switch. This is OK, as the balloon driver in Linux (the only +supported guest) will refuse to work with the IOMMU_PLATFORM feature +bit set. + +3. Later, we can fix the guest balloon driver to accept the IOMMU +feature bit and correctly exercise sharing and unsharing of balloon +pages. + +Signed-off-by: Janosch Frank +Reviewed-by: David Hildenbrand +Reviewed-by: Christian Borntraeger +Reviewed-by: Claudio Imbrenda +Reviewed-by: Cornelia Huck +Message-Id: <20200319131921.2367-6-frankja@linux.ibm.com> +Signed-off-by: Cornelia Huck +--- + hw/s390x/s390-virtio-ccw.c | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c +index e00040a00b..db45249320 100644 +--- a/hw/s390x/s390-virtio-ccw.c ++++ b/hw/s390x/s390-virtio-ccw.c +@@ -43,6 +43,7 @@ + #include "hw/qdev-properties.h" + #include "hw/s390x/tod.h" + #include "sysemu/sysemu.h" ++#include "sysemu/balloon.h" + #include "hw/s390x/pv.h" + #include + #include "migration/blocker.h" +@@ -329,6 +330,7 @@ static void s390_machine_unprotect(S390CcwMachineState *ms) + ms->pv = false; + migrate_del_blocker(pv_mig_blocker); + error_free_or_abort(&pv_mig_blocker); ++ qemu_balloon_inhibit(false); + } + + static int s390_machine_protect(S390CcwMachineState *ms) +@@ -336,10 +338,18 @@ static int s390_machine_protect(S390CcwMachineState *ms) + Error *local_err = NULL; + int rc; + ++ /* ++ * Ballooning on protected VMs needs support in the guest for ++ * sharing and unsharing balloon pages. Block ballooning for ++ * now, until we have a solution to make at least Linux guests ++ * either support it or fail gracefully. ++ */ ++ qemu_balloon_inhibit(true); + error_setg(&pv_mig_blocker, + "protected VMs are currently not migrateable."); + rc = migrate_add_blocker(pv_mig_blocker, &local_err); + if (rc) { ++ qemu_balloon_inhibit(false); + error_report_err(local_err); + error_free_or_abort(&pv_mig_blocker); + return rc; +@@ -348,6 +358,7 @@ static int s390_machine_protect(S390CcwMachineState *ms) + /* Create SE VM */ + rc = s390_pv_vm_enable(); + if (rc) { ++ qemu_balloon_inhibit(false); + error_report_err(local_err); + migrate_del_blocker(pv_mig_blocker); + error_free_or_abort(&pv_mig_blocker); +-- +2.23.0 + diff --git a/s390x-protvirt-KVM-intercept-changes.patch b/s390x-protvirt-KVM-intercept-changes.patch new file mode 100644 index 0000000000000000000000000000000000000000..85fc56a873b5e9b337d1540772d53270fa54a0e8 --- /dev/null +++ b/s390x-protvirt-KVM-intercept-changes.patch @@ -0,0 +1,62 @@ +From 2585e507ffa1da01b57dbea26b1e1fe507d27198 Mon Sep 17 00:00:00 2001 +From: Janosch Frank +Date: Thu, 19 Mar 2020 09:19:11 -0400 +Subject: [PATCH 039/709] s390x: protvirt: KVM intercept changes + +Protected VMs no longer intercept with code 4 for an instruction +interception. Instead they have codes 104 and 108 for protected +instruction interception and protected instruction notification +respectively. + +The 104 mirrors the 4 interception. + +The 108 is a notification interception to let KVM and QEMU know that +something changed and we need to update tracking information or +perform specific tasks. It's currently taken for the following +instructions: + +* spx (To inform about the changed prefix location) +* sclp (On incorrect SCCB values, so we can inject a IRQ) +* sigp (All but "stop and store status") +* diag308 (Subcodes 0/1) + +Of these exits only sclp errors, state changing sigps and diag308 will +reach QEMU. QEMU will do its parts of the job, while the ultravisor +has done the instruction part of the job. + +Signed-off-by: Janosch Frank +Reviewed-by: David Hildenbrand +Reviewed-by: Christian Borntraeger +Reviewed-by: Claudio Imbrenda +Reviewed-by: Cornelia Huck +Message-Id: <20200319131921.2367-7-frankja@linux.ibm.com> +Signed-off-by: Cornelia Huck +--- + target/s390x/kvm.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/target/s390x/kvm.c b/target/s390x/kvm.c +index b2b14bde2b..1988809ec2 100644 +--- a/target/s390x/kvm.c ++++ b/target/s390x/kvm.c +@@ -115,6 +115,8 @@ + #define ICPT_CPU_STOP 0x28 + #define ICPT_OPEREXC 0x2c + #define ICPT_IO 0x40 ++#define ICPT_PV_INSTR 0x68 ++#define ICPT_PV_INSTR_NOTIFICATION 0x6c + + #define NR_LOCAL_IRQS 32 + /* +@@ -1698,6 +1700,8 @@ static int handle_intercept(S390CPU *cpu) + (long)cs->kvm_run->psw_addr); + switch (icpt_code) { + case ICPT_INSTRUCTION: ++ case ICPT_PV_INSTR: ++ case ICPT_PV_INSTR_NOTIFICATION: + r = handle_instruction(cpu, run); + break; + case ICPT_PROGRAM: +-- +2.23.0 + diff --git a/s390x-protvirt-Move-IO-control-structures-over-SIDA.patch b/s390x-protvirt-Move-IO-control-structures-over-SIDA.patch new file mode 100644 index 0000000000000000000000000000000000000000..317ca5eb0e3d403de8d48304e6b3f1e3894ae64d --- /dev/null +++ b/s390x-protvirt-Move-IO-control-structures-over-SIDA.patch @@ -0,0 +1,158 @@ +From fcc10c1470d6e9460ebcf4c30f5bbd37b921a041 Mon Sep 17 00:00:00 2001 +From: Janosch Frank +Date: Thu, 19 Mar 2020 09:19:18 -0400 +Subject: [PATCH 046/709] s390x: protvirt: Move IO control structures over SIDA + +For protected guests, we need to put the IO emulation results into the +SIDA, so SIE will write them into the guest at the next entry. + +Signed-off-by: Janosch Frank +Reviewed-by: David Hildenbrand +Reviewed-by: Cornelia Huck +Message-Id: <20200319131921.2367-14-frankja@linux.ibm.com> +Signed-off-by: Cornelia Huck +--- + target/s390x/ioinst.c | 61 +++++++++++++++++++++++++++++++------------ + 1 file changed, 45 insertions(+), 16 deletions(-) + +diff --git a/target/s390x/ioinst.c b/target/s390x/ioinst.c +index 8828482eec..7a14c52c12 100644 +--- a/target/s390x/ioinst.c ++++ b/target/s390x/ioinst.c +@@ -138,7 +138,9 @@ void ioinst_handle_msch(S390CPU *cpu, uint64_t reg1, uint32_t ipb, uintptr_t ra) + s390_program_interrupt(env, PGM_SPECIFICATION, ra); + return; + } +- if (s390_cpu_virt_mem_read(cpu, addr, ar, &schib, sizeof(schib))) { ++ if (s390_is_pv()) { ++ s390_cpu_pv_mem_read(cpu, addr, &schib, sizeof(schib)); ++ } else if (s390_cpu_virt_mem_read(cpu, addr, ar, &schib, sizeof(schib))) { + s390_cpu_virt_mem_handle_exc(cpu, ra); + return; + } +@@ -195,7 +197,9 @@ void ioinst_handle_ssch(S390CPU *cpu, uint64_t reg1, uint32_t ipb, uintptr_t ra) + s390_program_interrupt(env, PGM_SPECIFICATION, ra); + return; + } +- if (s390_cpu_virt_mem_read(cpu, addr, ar, &orig_orb, sizeof(orb))) { ++ if (s390_is_pv()) { ++ s390_cpu_pv_mem_read(cpu, addr, &orig_orb, sizeof(orb)); ++ } else if (s390_cpu_virt_mem_read(cpu, addr, ar, &orig_orb, sizeof(orb))) { + s390_cpu_virt_mem_handle_exc(cpu, ra); + return; + } +@@ -231,14 +235,19 @@ void ioinst_handle_stcrw(S390CPU *cpu, uint32_t ipb, uintptr_t ra) + cc = css_do_stcrw(&crw); + /* 0 - crw stored, 1 - zeroes stored */ + +- if (s390_cpu_virt_mem_write(cpu, addr, ar, &crw, sizeof(crw)) == 0) { ++ if (s390_is_pv()) { ++ s390_cpu_pv_mem_write(cpu, addr, &crw, sizeof(crw)); + setcc(cpu, cc); + } else { +- if (cc == 0) { +- /* Write failed: requeue CRW since STCRW is suppressing */ +- css_undo_stcrw(&crw); ++ if (s390_cpu_virt_mem_write(cpu, addr, ar, &crw, sizeof(crw)) == 0) { ++ setcc(cpu, cc); ++ } else { ++ if (cc == 0) { ++ /* Write failed: requeue CRW since STCRW is suppressing */ ++ css_undo_stcrw(&crw); ++ } ++ s390_cpu_virt_mem_handle_exc(cpu, ra); + } +- s390_cpu_virt_mem_handle_exc(cpu, ra); + } + } + +@@ -260,6 +269,13 @@ void ioinst_handle_stsch(S390CPU *cpu, uint64_t reg1, uint32_t ipb, + } + + if (ioinst_disassemble_sch_ident(reg1, &m, &cssid, &ssid, &schid)) { ++ /* ++ * The Ultravisor checks schid bit 16 to be one and bits 0-12 ++ * to be 0 and injects a operand exception itself. ++ * ++ * Hence we should never end up here. ++ */ ++ g_assert(!s390_is_pv()); + /* + * As operand exceptions have a lower priority than access exceptions, + * we check whether the memory area is writeable (injecting the +@@ -292,14 +308,17 @@ void ioinst_handle_stsch(S390CPU *cpu, uint64_t reg1, uint32_t ipb, + } + } + if (cc != 3) { +- if (s390_cpu_virt_mem_write(cpu, addr, ar, &schib, +- sizeof(schib)) != 0) { ++ if (s390_is_pv()) { ++ s390_cpu_pv_mem_write(cpu, addr, &schib, sizeof(schib)); ++ } else if (s390_cpu_virt_mem_write(cpu, addr, ar, &schib, ++ sizeof(schib)) != 0) { + s390_cpu_virt_mem_handle_exc(cpu, ra); + return; + } + } else { + /* Access exceptions have a higher priority than cc3 */ +- if (s390_cpu_virt_mem_check_write(cpu, addr, ar, sizeof(schib)) != 0) { ++ if (!s390_is_pv() && ++ s390_cpu_virt_mem_check_write(cpu, addr, ar, sizeof(schib)) != 0) { + s390_cpu_virt_mem_handle_exc(cpu, ra); + return; + } +@@ -336,7 +355,9 @@ int ioinst_handle_tsch(S390CPU *cpu, uint64_t reg1, uint32_t ipb, uintptr_t ra) + } + /* 0 - status pending, 1 - not status pending, 3 - not operational */ + if (cc != 3) { +- if (s390_cpu_virt_mem_write(cpu, addr, ar, &irb, irb_len) != 0) { ++ if (s390_is_pv()) { ++ s390_cpu_pv_mem_write(cpu, addr, &irb, irb_len); ++ } else if (s390_cpu_virt_mem_write(cpu, addr, ar, &irb, irb_len) != 0) { + s390_cpu_virt_mem_handle_exc(cpu, ra); + return -EFAULT; + } +@@ -344,7 +365,8 @@ int ioinst_handle_tsch(S390CPU *cpu, uint64_t reg1, uint32_t ipb, uintptr_t ra) + } else { + irb_len = sizeof(irb) - sizeof(irb.emw); + /* Access exceptions have a higher priority than cc3 */ +- if (s390_cpu_virt_mem_check_write(cpu, addr, ar, irb_len) != 0) { ++ if (!s390_is_pv() && ++ s390_cpu_virt_mem_check_write(cpu, addr, ar, irb_len) != 0) { + s390_cpu_virt_mem_handle_exc(cpu, ra); + return -EFAULT; + } +@@ -642,7 +664,9 @@ void ioinst_handle_chsc(S390CPU *cpu, uint32_t ipb, uintptr_t ra) + * present CHSC sub-handlers ... if we ever need more, we should take + * care of req->len here first. + */ +- if (s390_cpu_virt_mem_read(cpu, addr, reg, buf, sizeof(ChscReq))) { ++ if (s390_is_pv()) { ++ s390_cpu_pv_mem_read(cpu, addr, buf, sizeof(ChscReq)); ++ } else if (s390_cpu_virt_mem_read(cpu, addr, reg, buf, sizeof(ChscReq))) { + s390_cpu_virt_mem_handle_exc(cpu, ra); + return; + } +@@ -675,11 +699,16 @@ void ioinst_handle_chsc(S390CPU *cpu, uint32_t ipb, uintptr_t ra) + break; + } + +- if (!s390_cpu_virt_mem_write(cpu, addr + len, reg, res, +- be16_to_cpu(res->len))) { ++ if (s390_is_pv()) { ++ s390_cpu_pv_mem_write(cpu, addr + len, res, be16_to_cpu(res->len)); + setcc(cpu, 0); /* Command execution complete */ + } else { +- s390_cpu_virt_mem_handle_exc(cpu, ra); ++ if (!s390_cpu_virt_mem_write(cpu, addr + len, reg, res, ++ be16_to_cpu(res->len))) { ++ setcc(cpu, 0); /* Command execution complete */ ++ } else { ++ s390_cpu_virt_mem_handle_exc(cpu, ra); ++ } + } + } + +-- +2.23.0 + diff --git a/s390x-protvirt-Move-STSI-data-over-SIDAD.patch b/s390x-protvirt-Move-STSI-data-over-SIDAD.patch new file mode 100644 index 0000000000000000000000000000000000000000..a4a446fc9f839182e123656aeb90a38072a70e06 --- /dev/null +++ b/s390x-protvirt-Move-STSI-data-over-SIDAD.patch @@ -0,0 +1,57 @@ +From 7c713b8acb70fb61f9650f8a7702dec546752bb6 Mon Sep 17 00:00:00 2001 +From: Janosch Frank +Date: Thu, 19 Mar 2020 09:19:13 -0400 +Subject: [PATCH 041/709] s390x: protvirt: Move STSI data over SIDAD + +For protected guests, we need to put the STSI emulation results into +the SIDA, so SIE will write them into the guest at the next entry. + +Signed-off-by: Janosch Frank +Reviewed-by: David Hildenbrand +Reviewed-by: Claudio Imbrenda +Reviewed-by: Cornelia Huck +Message-Id: <20200319131921.2367-9-frankja@linux.ibm.com> +Signed-off-by: Cornelia Huck +--- + target/s390x/kvm.c | 11 +++++++++-- + 1 file changed, 9 insertions(+), 2 deletions(-) + +diff --git a/target/s390x/kvm.c b/target/s390x/kvm.c +index 0e93778ed1..e0b61680ab 100644 +--- a/target/s390x/kvm.c ++++ b/target/s390x/kvm.c +@@ -50,6 +50,7 @@ + #include "exec/memattrs.h" + #include "hw/s390x/s390-virtio-ccw.h" + #include "hw/s390x/s390-virtio-hcall.h" ++#include "hw/s390x/pv.h" + + #ifndef DEBUG_KVM + #define DEBUG_KVM 0 +@@ -1808,7 +1809,9 @@ static void insert_stsi_3_2_2(S390CPU *cpu, __u64 addr, uint8_t ar) + SysIB_322 sysib; + int del, i; + +- if (s390_cpu_virt_mem_read(cpu, addr, ar, &sysib, sizeof(sysib))) { ++ if (s390_is_pv()) { ++ s390_cpu_pv_mem_read(cpu, 0, &sysib, sizeof(sysib)); ++ } else if (s390_cpu_virt_mem_read(cpu, addr, ar, &sysib, sizeof(sysib))) { + return; + } + /* Shift the stack of Extended Names to prepare for our own data */ +@@ -1861,7 +1864,11 @@ static void insert_stsi_3_2_2(S390CPU *cpu, __u64 addr, uint8_t ar) + /* Insert UUID */ + memcpy(sysib.vm[0].uuid, &qemu_uuid, sizeof(sysib.vm[0].uuid)); + +- s390_cpu_virt_mem_write(cpu, addr, ar, &sysib, sizeof(sysib)); ++ if (s390_is_pv()) { ++ s390_cpu_pv_mem_write(cpu, 0, &sysib, sizeof(sysib)); ++ } else { ++ s390_cpu_virt_mem_write(cpu, addr, ar, &sysib, sizeof(sysib)); ++ } + } + + static int handle_stsi(S390CPU *cpu) +-- +2.23.0 + diff --git a/s390x-protvirt-Move-diag-308-data-over-SIDA.patch b/s390x-protvirt-Move-diag-308-data-over-SIDA.patch new file mode 100644 index 0000000000000000000000000000000000000000..c8d02832ff7d8763693d1c294fd1c6de139d02ca --- /dev/null +++ b/s390x-protvirt-Move-diag-308-data-over-SIDA.patch @@ -0,0 +1,80 @@ +From 9c61e11238cfa8f70e3eb90aac5d3e5646e5432f Mon Sep 17 00:00:00 2001 +From: Janosch Frank +Date: Thu, 19 Mar 2020 09:19:16 -0400 +Subject: [PATCH 044/709] s390x: protvirt: Move diag 308 data over SIDA + +For protected guests the IPIB is written/read to/from the SIDA, so we +need those accesses to go through s390_cpu_pv_mem_read/write(). + +Signed-off-by: Janosch Frank +Reviewed-by: David Hildenbrand +Reviewed-by: Christian Borntraeger +Reviewed-by: Claudio Imbrenda +Reviewed-by: Cornelia Huck +Message-Id: <20200319131921.2367-12-frankja@linux.ibm.com> +Signed-off-by: Cornelia Huck +--- + target/s390x/diag.c | 25 ++++++++++++++++++++----- + 1 file changed, 20 insertions(+), 5 deletions(-) + +diff --git a/target/s390x/diag.c b/target/s390x/diag.c +index b2cbefb8cf..1a48429564 100644 +--- a/target/s390x/diag.c ++++ b/target/s390x/diag.c +@@ -75,6 +75,7 @@ void handle_diag_308(CPUS390XState *env, uint64_t r1, uint64_t r3, uintptr_t ra) + { + bool valid; + CPUState *cs = env_cpu(env); ++ S390CPU *cpu = S390_CPU(cs); + uint64_t addr = env->regs[r1]; + uint64_t subcode = env->regs[r3]; + IplParameterBlock *iplb; +@@ -111,13 +112,22 @@ void handle_diag_308(CPUS390XState *env, uint64_t r1, uint64_t r3, uintptr_t ra) + return; + } + iplb = g_new0(IplParameterBlock, 1); +- cpu_physical_memory_read(addr, iplb, sizeof(iplb->len)); ++ if (!s390_is_pv()) { ++ cpu_physical_memory_read(addr, iplb, sizeof(iplb->len)); ++ } else { ++ s390_cpu_pv_mem_read(cpu, 0, iplb, sizeof(iplb->len)); ++ } ++ + if (!iplb_valid_len(iplb)) { + env->regs[r1 + 1] = DIAG_308_RC_INVALID; + goto out; + } + +- cpu_physical_memory_read(addr, iplb, be32_to_cpu(iplb->len)); ++ if (!s390_is_pv()) { ++ cpu_physical_memory_read(addr, iplb, be32_to_cpu(iplb->len)); ++ } else { ++ s390_cpu_pv_mem_read(cpu, 0, iplb, be32_to_cpu(iplb->len)); ++ } + + valid = subcode == DIAG308_PV_SET ? iplb_valid_pv(iplb) : iplb_valid(iplb); + if (!valid) { +@@ -140,12 +150,17 @@ out: + } else { + iplb = s390_ipl_get_iplb(); + } +- if (iplb) { ++ if (!iplb) { ++ env->regs[r1 + 1] = DIAG_308_RC_NO_CONF; ++ return; ++ } ++ ++ if (!s390_is_pv()) { + cpu_physical_memory_write(addr, iplb, be32_to_cpu(iplb->len)); +- env->regs[r1 + 1] = DIAG_308_RC_OK; + } else { +- env->regs[r1 + 1] = DIAG_308_RC_NO_CONF; ++ s390_cpu_pv_mem_write(cpu, 0, iplb, be32_to_cpu(iplb->len)); + } ++ env->regs[r1 + 1] = DIAG_308_RC_OK; + return; + case DIAG308_PV_START: + iplb = s390_ipl_get_iplb_pv(); +-- +2.23.0 + diff --git a/s390x-protvirt-SCLP-interpretation.patch b/s390x-protvirt-SCLP-interpretation.patch new file mode 100644 index 0000000000000000000000000000000000000000..752f5dc596d732d4d99bb6a30bd36bf985a494aa --- /dev/null +++ b/s390x-protvirt-SCLP-interpretation.patch @@ -0,0 +1,159 @@ +From 0f73c5b30b8ba6c0828608be496d2f59a5427539 Mon Sep 17 00:00:00 2001 +From: Janosch Frank +Date: Thu, 19 Mar 2020 09:19:14 -0400 +Subject: [PATCH 042/709] s390x: protvirt: SCLP interpretation + +SCLP for a protected guest is done over the SIDAD, so we need to use +the s390_cpu_pv_mem_* functions to access the SIDAD instead of guest +memory when reading/writing SCBs. + +To not confuse the sclp emulation, we set 0x4000 as the SCCB address, +since the function that injects the sclp external interrupt would +reject a zero sccb address. + +Signed-off-by: Janosch Frank +Reviewed-by: David Hildenbrand +Reviewed-by: Claudio Imbrenda +Reviewed-by: Cornelia Huck +Reviewed-by: Christian Borntraeger +Message-Id: <20200319131921.2367-10-frankja@linux.ibm.com> +Signed-off-by: Cornelia Huck +--- + hw/s390x/sclp.c | 56 +++++++++++++++++++++++++++++++++-------- + include/hw/s390x/sclp.h | 2 ++ + target/s390x/kvm.c | 25 ++++++++++++++---- + 3 files changed, 67 insertions(+), 16 deletions(-) + +diff --git a/hw/s390x/sclp.c b/hw/s390x/sclp.c +index f0c35aa57a..ede056b3ef 100644 +--- a/hw/s390x/sclp.c ++++ b/hw/s390x/sclp.c +@@ -33,6 +33,22 @@ static inline SCLPDevice *get_sclp_device(void) + return sclp; + } + ++static inline bool sclp_command_code_valid(uint32_t code) ++{ ++ switch (code & SCLP_CMD_CODE_MASK) { ++ case SCLP_CMDW_READ_SCP_INFO: ++ case SCLP_CMDW_READ_SCP_INFO_FORCED: ++ case SCLP_CMDW_READ_CPU_INFO: ++ case SCLP_CMDW_CONFIGURE_IOA: ++ case SCLP_CMDW_DECONFIGURE_IOA: ++ case SCLP_CMD_READ_EVENT_DATA: ++ case SCLP_CMD_WRITE_EVENT_DATA: ++ case SCLP_CMD_WRITE_EVENT_MASK: ++ return true; ++ } ++ return false; ++} ++ + static void prepare_cpu_entries(SCLPDevice *sclp, CPUEntry *entry, int *count) + { + MachineState *ms = MACHINE(qdev_get_machine()); +@@ -193,6 +209,34 @@ static void sclp_execute(SCLPDevice *sclp, SCCB *sccb, uint32_t code) + } + } + ++/* ++ * We only need the address to have something valid for the ++ * service_interrupt call. ++ */ ++#define SCLP_PV_DUMMY_ADDR 0x4000 ++int sclp_service_call_protected(CPUS390XState *env, uint64_t sccb, ++ uint32_t code) ++{ ++ SCLPDevice *sclp = get_sclp_device(); ++ SCLPDeviceClass *sclp_c = SCLP_GET_CLASS(sclp); ++ SCCB work_sccb; ++ hwaddr sccb_len = sizeof(SCCB); ++ ++ s390_cpu_pv_mem_read(env_archcpu(env), 0, &work_sccb, sccb_len); ++ ++ if (!sclp_command_code_valid(code)) { ++ work_sccb.h.response_code = cpu_to_be16(SCLP_RC_INVALID_SCLP_COMMAND); ++ goto out_write; ++ } ++ ++ sclp_c->execute(sclp, &work_sccb, code); ++out_write: ++ s390_cpu_pv_mem_write(env_archcpu(env), 0, &work_sccb, ++ be16_to_cpu(work_sccb.h.length)); ++ sclp_c->service_interrupt(sclp, SCLP_PV_DUMMY_ADDR); ++ return 0; ++} ++ + int sclp_service_call(CPUS390XState *env, uint64_t sccb, uint32_t code) + { + SCLPDevice *sclp = get_sclp_device(); +@@ -225,17 +269,7 @@ int sclp_service_call(CPUS390XState *env, uint64_t sccb, uint32_t code) + return -PGM_SPECIFICATION; + } + +- switch (code & SCLP_CMD_CODE_MASK) { +- case SCLP_CMDW_READ_SCP_INFO: +- case SCLP_CMDW_READ_SCP_INFO_FORCED: +- case SCLP_CMDW_READ_CPU_INFO: +- case SCLP_CMDW_CONFIGURE_IOA: +- case SCLP_CMDW_DECONFIGURE_IOA: +- case SCLP_CMD_READ_EVENT_DATA: +- case SCLP_CMD_WRITE_EVENT_DATA: +- case SCLP_CMD_WRITE_EVENT_MASK: +- break; +- default: ++ if (!sclp_command_code_valid(code)) { + work_sccb.h.response_code = cpu_to_be16(SCLP_RC_INVALID_SCLP_COMMAND); + goto out_write; + } +diff --git a/include/hw/s390x/sclp.h b/include/hw/s390x/sclp.h +index cd7b24359f..822eff4396 100644 +--- a/include/hw/s390x/sclp.h ++++ b/include/hw/s390x/sclp.h +@@ -217,5 +217,7 @@ void s390_sclp_init(void); + void sclp_service_interrupt(uint32_t sccb); + void raise_irq_cpu_hotplug(void); + int sclp_service_call(CPUS390XState *env, uint64_t sccb, uint32_t code); ++int sclp_service_call_protected(CPUS390XState *env, uint64_t sccb, ++ uint32_t code); + + #endif +diff --git a/target/s390x/kvm.c b/target/s390x/kvm.c +index e0b61680ab..870dd1b52b 100644 +--- a/target/s390x/kvm.c ++++ b/target/s390x/kvm.c +@@ -1233,12 +1233,27 @@ static void kvm_sclp_service_call(S390CPU *cpu, struct kvm_run *run, + sccb = env->regs[ipbh0 & 0xf]; + code = env->regs[(ipbh0 & 0xf0) >> 4]; + +- r = sclp_service_call(env, sccb, code); +- if (r < 0) { +- kvm_s390_program_interrupt(cpu, -r); +- return; ++ switch (run->s390_sieic.icptcode) { ++ case ICPT_PV_INSTR_NOTIFICATION: ++ g_assert(s390_is_pv()); ++ /* The notification intercepts are currently handled by KVM */ ++ error_report("unexpected SCLP PV notification"); ++ exit(1); ++ break; ++ case ICPT_PV_INSTR: ++ g_assert(s390_is_pv()); ++ sclp_service_call_protected(env, sccb, code); ++ /* Setting the CC is done by the Ultravisor. */ ++ break; ++ case ICPT_INSTRUCTION: ++ g_assert(!s390_is_pv()); ++ r = sclp_service_call(env, sccb, code); ++ if (r < 0) { ++ kvm_s390_program_interrupt(cpu, -r); ++ return; ++ } ++ setcc(cpu, r); + } +- setcc(cpu, r); + } + + static int handle_b2(S390CPU *cpu, struct kvm_run *run, uint8_t ipa1) +-- +2.23.0 + diff --git a/s390x-protvirt-Set-guest-IPL-PSW.patch b/s390x-protvirt-Set-guest-IPL-PSW.patch new file mode 100644 index 0000000000000000000000000000000000000000..fef3e13be3e86105ee6be3d28551b4d3ff2a3c6a --- /dev/null +++ b/s390x-protvirt-Set-guest-IPL-PSW.patch @@ -0,0 +1,62 @@ +From 59181010a2ff82c3a97e9b5768ee87c38e4815f1 Mon Sep 17 00:00:00 2001 +From: Janosch Frank +Date: Thu, 19 Mar 2020 09:19:15 -0400 +Subject: [PATCH 043/709] s390x: protvirt: Set guest IPL PSW + +Handling of CPU reset and setting of the IPL psw from guest storage at +offset 0 is done by a Ultravisor call. Let's only fetch it if +necessary. + +Signed-off-by: Janosch Frank +Reviewed-by: Thomas Huth +Reviewed-by: David Hildenbrand +Reviewed-by: Christian Borntraeger +Reviewed-by: Claudio Imbrenda +Reviewed-by: Cornelia Huck +Message-Id: <20200319131921.2367-11-frankja@linux.ibm.com> +Signed-off-by: Cornelia Huck +--- + target/s390x/cpu.c | 26 +++++++++++++++++--------- + 1 file changed, 17 insertions(+), 9 deletions(-) + +diff --git a/target/s390x/cpu.c b/target/s390x/cpu.c +index bb7a588e3b..f2ccf0a06a 100644 +--- a/target/s390x/cpu.c ++++ b/target/s390x/cpu.c +@@ -77,16 +77,24 @@ static bool s390_cpu_has_work(CPUState *cs) + static void s390_cpu_load_normal(CPUState *s) + { + S390CPU *cpu = S390_CPU(s); +- uint64_t spsw = ldq_phys(s->as, 0); +- +- cpu->env.psw.mask = spsw & PSW_MASK_SHORT_CTRL; +- /* +- * Invert short psw indication, so SIE will report a specification +- * exception if it was not set. +- */ +- cpu->env.psw.mask ^= PSW_MASK_SHORTPSW; +- cpu->env.psw.addr = spsw & PSW_MASK_SHORT_ADDR; ++ uint64_t spsw; + ++ if (!s390_is_pv()) { ++ spsw = ldq_phys(s->as, 0); ++ cpu->env.psw.mask = spsw & PSW_MASK_SHORT_CTRL; ++ /* ++ * Invert short psw indication, so SIE will report a specification ++ * exception if it was not set. ++ */ ++ cpu->env.psw.mask ^= PSW_MASK_SHORTPSW; ++ cpu->env.psw.addr = spsw & PSW_MASK_SHORT_ADDR; ++ } else { ++ /* ++ * Firmware requires us to set the load state before we set ++ * the cpu to operating on protected guests. ++ */ ++ s390_cpu_set_state(S390_CPU_STATE_LOAD, cpu); ++ } + s390_cpu_set_state(S390_CPU_STATE_OPERATING, cpu); + } + #endif +-- +2.23.0 + diff --git a/s390x-protvirt-Support-unpack-facility.patch b/s390x-protvirt-Support-unpack-facility.patch new file mode 100644 index 0000000000000000000000000000000000000000..f5f152c066eae9af7d93b62cf27478377dbf6fdb --- /dev/null +++ b/s390x-protvirt-Support-unpack-facility.patch @@ -0,0 +1,873 @@ +From c3347ed0d2ee42a7dcf7bfe7f9c3884a9596727a Mon Sep 17 00:00:00 2001 +From: Janosch Frank +Date: Mon, 23 Mar 2020 04:36:06 -0400 +Subject: [PATCH 036/709] s390x: protvirt: Support unpack facility + +The unpack facility provides the means to setup a protected guest. A +protected guest cannot be introspected by the hypervisor or any +user/administrator of the machine it is running on. + +Protected guests are encrypted at rest and need a special boot +mechanism via diag308 subcode 8 and 10. + +Code 8 sets the PV specific IPLB which is retained separately from +those set via code 5. + +Code 10 is used to unpack the VM into protected memory, verify its +integrity and start it. + +Signed-off-by: Janosch Frank +Co-developed-by: Christian Borntraeger [Changes +to machine] +Reviewed-by: David Hildenbrand +Reviewed-by: Claudio Imbrenda +Reviewed-by: Cornelia Huck +Message-Id: <20200323083606.24520-1-frankja@linux.ibm.com> +[CH: fixed up KVM_PV_VM_ -> KVM_PV_] +Signed-off-by: Cornelia Huck +--- + MAINTAINERS | 2 + + hw/s390x/Makefile.objs | 1 + + hw/s390x/ipl.c | 59 +++++++++++++- + hw/s390x/ipl.h | 91 ++++++++++++++++++++- + hw/s390x/pv.c | 98 +++++++++++++++++++++++ + hw/s390x/s390-virtio-ccw.c | 119 +++++++++++++++++++++++++++- + include/hw/s390x/pv.h | 55 +++++++++++++ + include/hw/s390x/s390-virtio-ccw.h | 1 + + target/s390x/cpu.c | 1 + + target/s390x/cpu_features_def.inc.h | 1 + + target/s390x/diag.c | 39 ++++++++- + target/s390x/kvm-stub.c | 5 ++ + target/s390x/kvm.c | 5 ++ + target/s390x/kvm_s390x.h | 1 + + 14 files changed, 468 insertions(+), 10 deletions(-) + create mode 100644 hw/s390x/pv.c + create mode 100644 include/hw/s390x/pv.h + +diff --git a/MAINTAINERS b/MAINTAINERS +index 8cbc1fac2b..831d4b014a 100644 +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -396,6 +396,8 @@ F: target/s390x/machine.c + F: target/s390x/sigp.c + F: target/s390x/cpu_features*.[ch] + F: target/s390x/cpu_models.[ch] ++F: hw/s390x/pv.c ++F: include/hw/s390x/pv.h + F: hw/intc/s390_flic.c + F: hw/intc/s390_flic_kvm.c + F: include/hw/s390x/s390_flic.h +diff --git a/hw/s390x/Makefile.objs b/hw/s390x/Makefile.objs +index e02ed80b68..a46a1c7894 100644 +--- a/hw/s390x/Makefile.objs ++++ b/hw/s390x/Makefile.objs +@@ -31,6 +31,7 @@ obj-y += tod-qemu.o + obj-$(CONFIG_KVM) += tod-kvm.o + obj-$(CONFIG_KVM) += s390-skeys-kvm.o + obj-$(CONFIG_KVM) += s390-stattrib-kvm.o ++obj-$(CONFIG_KVM) += pv.o + obj-y += s390-ccw.o + obj-y += ap-device.o + obj-y += ap-bridge.o +diff --git a/hw/s390x/ipl.c b/hw/s390x/ipl.c +index 8c3e019571..ce21494c08 100644 +--- a/hw/s390x/ipl.c ++++ b/hw/s390x/ipl.c +@@ -1,10 +1,11 @@ + /* + * bootloader support + * +- * Copyright IBM, Corp. 2012 ++ * Copyright IBM, Corp. 2012, 2020 + * + * Authors: + * Christian Borntraeger ++ * Janosch Frank + * + * 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. +@@ -27,6 +28,7 @@ + #include "hw/s390x/vfio-ccw.h" + #include "hw/s390x/css.h" + #include "hw/s390x/ebcdic.h" ++#include "hw/s390x/pv.h" + #include "ipl.h" + #include "qemu/error-report.h" + #include "qemu/config-file.h" +@@ -566,12 +568,31 @@ void s390_ipl_update_diag308(IplParameterBlock *iplb) + { + S390IPLState *ipl = get_ipl_device(); + +- ipl->iplb = *iplb; +- ipl->iplb_valid = true; ++ /* ++ * The IPLB set and retrieved by subcodes 8/9 is completely ++ * separate from the one managed via subcodes 5/6. ++ */ ++ if (iplb->pbt == S390_IPL_TYPE_PV) { ++ ipl->iplb_pv = *iplb; ++ ipl->iplb_valid_pv = true; ++ } else { ++ ipl->iplb = *iplb; ++ ipl->iplb_valid = true; ++ } + ipl->netboot = is_virtio_net_device(iplb); + update_machine_ipl_properties(iplb); + } + ++IplParameterBlock *s390_ipl_get_iplb_pv(void) ++{ ++ S390IPLState *ipl = get_ipl_device(); ++ ++ if (!ipl->iplb_valid_pv) { ++ return NULL; ++ } ++ return &ipl->iplb_pv; ++} ++ + IplParameterBlock *s390_ipl_get_iplb(void) + { + S390IPLState *ipl = get_ipl_device(); +@@ -660,6 +681,38 @@ static void s390_ipl_prepare_qipl(S390CPU *cpu) + cpu_physical_memory_unmap(addr, len, 1, len); + } + ++int s390_ipl_prepare_pv_header(void) ++{ ++ IplParameterBlock *ipib = s390_ipl_get_iplb_pv(); ++ IPLBlockPV *ipib_pv = &ipib->pv; ++ void *hdr = g_malloc(ipib_pv->pv_header_len); ++ int rc; ++ ++ cpu_physical_memory_read(ipib_pv->pv_header_addr, hdr, ++ ipib_pv->pv_header_len); ++ rc = s390_pv_set_sec_parms((uintptr_t)hdr, ++ ipib_pv->pv_header_len); ++ g_free(hdr); ++ return rc; ++} ++ ++int s390_ipl_pv_unpack(void) ++{ ++ IplParameterBlock *ipib = s390_ipl_get_iplb_pv(); ++ IPLBlockPV *ipib_pv = &ipib->pv; ++ int i, rc = 0; ++ ++ for (i = 0; i < ipib_pv->num_comp; i++) { ++ rc = s390_pv_unpack(ipib_pv->components[i].addr, ++ TARGET_PAGE_ALIGN(ipib_pv->components[i].size), ++ ipib_pv->components[i].tweak_pref); ++ if (rc) { ++ break; ++ } ++ } ++ return rc; ++} ++ + void s390_ipl_prepare_cpu(S390CPU *cpu) + { + S390IPLState *ipl = get_ipl_device(); +diff --git a/hw/s390x/ipl.h b/hw/s390x/ipl.h +index a5665e6bfd..89b3044d7a 100644 +--- a/hw/s390x/ipl.h ++++ b/hw/s390x/ipl.h +@@ -1,8 +1,9 @@ + /* + * s390 IPL device + * +- * Copyright 2015 IBM Corp. ++ * Copyright 2015, 2020 IBM Corp. + * Author(s): Zhang Fan ++ * Janosch Frank + * + * 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 +@@ -15,6 +16,24 @@ + #include "cpu.h" + #include "hw/qdev-core.h" + ++struct IPLBlockPVComp { ++ uint64_t tweak_pref; ++ uint64_t addr; ++ uint64_t size; ++} QEMU_PACKED; ++typedef struct IPLBlockPVComp IPLBlockPVComp; ++ ++struct IPLBlockPV { ++ uint8_t reserved18[87]; /* 0x18 */ ++ uint8_t version; /* 0x6f */ ++ uint32_t reserved70; /* 0x70 */ ++ uint32_t num_comp; /* 0x74 */ ++ uint64_t pv_header_addr; /* 0x78 */ ++ uint64_t pv_header_len; /* 0x80 */ ++ struct IPLBlockPVComp components[]; ++} QEMU_PACKED; ++typedef struct IPLBlockPV IPLBlockPV; ++ + struct IplBlockCcw { + uint8_t reserved0[85]; + uint8_t ssid; +@@ -71,6 +90,7 @@ union IplParameterBlock { + union { + IplBlockCcw ccw; + IplBlockFcp fcp; ++ IPLBlockPV pv; + IplBlockQemuScsi scsi; + }; + } QEMU_PACKED; +@@ -85,8 +105,11 @@ typedef union IplParameterBlock IplParameterBlock; + + int s390_ipl_set_loadparm(uint8_t *loadparm); + void s390_ipl_update_diag308(IplParameterBlock *iplb); ++int s390_ipl_prepare_pv_header(void); ++int s390_ipl_pv_unpack(void); + void s390_ipl_prepare_cpu(S390CPU *cpu); + IplParameterBlock *s390_ipl_get_iplb(void); ++IplParameterBlock *s390_ipl_get_iplb_pv(void); + + enum s390_reset { + /* default is a reset not triggered by a CPU e.g. issued by QMP */ +@@ -94,6 +117,7 @@ enum s390_reset { + S390_RESET_REIPL, + S390_RESET_MODIFIED_CLEAR, + S390_RESET_LOAD_NORMAL, ++ S390_RESET_PV, + }; + void s390_ipl_reset_request(CPUState *cs, enum s390_reset reset_type); + void s390_ipl_get_reset_request(CPUState **cs, enum s390_reset *reset_type); +@@ -133,6 +157,7 @@ struct S390IPLState { + /*< private >*/ + DeviceState parent_obj; + IplParameterBlock iplb; ++ IplParameterBlock iplb_pv; + QemuIplParameters qipl; + uint64_t start_addr; + uint64_t compat_start_addr; +@@ -140,6 +165,7 @@ struct S390IPLState { + uint64_t compat_bios_start_addr; + bool enforce_bios; + bool iplb_valid; ++ bool iplb_valid_pv; + bool netboot; + /* reset related properties don't have to be migrated or reset */ + enum s390_reset reset_type; +@@ -162,6 +188,8 @@ QEMU_BUILD_BUG_MSG(offsetof(S390IPLState, iplb) & 3, "alignment of iplb wrong"); + #define DIAG_308_RC_OK 0x0001 + #define DIAG_308_RC_NO_CONF 0x0102 + #define DIAG_308_RC_INVALID 0x0402 ++#define DIAG_308_RC_NO_PV_CONF 0x0902 ++#define DIAG_308_RC_INVAL_FOR_PV 0x0a02 + + #define DIAG308_RESET_MOD_CLR 0 + #define DIAG308_RESET_LOAD_NORM 1 +@@ -169,12 +197,17 @@ QEMU_BUILD_BUG_MSG(offsetof(S390IPLState, iplb) & 3, "alignment of iplb wrong"); + #define DIAG308_LOAD_NORMAL_DUMP 4 + #define DIAG308_SET 5 + #define DIAG308_STORE 6 ++#define DIAG308_PV_SET 8 ++#define DIAG308_PV_STORE 9 ++#define DIAG308_PV_START 10 + + #define S390_IPL_TYPE_FCP 0x00 + #define S390_IPL_TYPE_CCW 0x02 ++#define S390_IPL_TYPE_PV 0x05 + #define S390_IPL_TYPE_QEMU_SCSI 0xff + + #define S390_IPLB_HEADER_LEN 8 ++#define S390_IPLB_MIN_PV_LEN 148 + #define S390_IPLB_MIN_CCW_LEN 200 + #define S390_IPLB_MIN_FCP_LEN 384 + #define S390_IPLB_MIN_QEMU_SCSI_LEN 200 +@@ -184,6 +217,62 @@ static inline bool iplb_valid_len(IplParameterBlock *iplb) + return be32_to_cpu(iplb->len) <= sizeof(IplParameterBlock); + } + ++static inline bool ipl_valid_pv_components(IplParameterBlock *iplb) ++{ ++ IPLBlockPV *ipib_pv = &iplb->pv; ++ int i; ++ ++ if (ipib_pv->num_comp == 0) { ++ return false; ++ } ++ ++ for (i = 0; i < ipib_pv->num_comp; i++) { ++ /* Addr must be 4k aligned */ ++ if (ipib_pv->components[i].addr & ~TARGET_PAGE_MASK) { ++ return false; ++ } ++ ++ /* Tweak prefix is monotonically increasing with each component */ ++ if (i < ipib_pv->num_comp - 1 && ++ ipib_pv->components[i].tweak_pref >= ++ ipib_pv->components[i + 1].tweak_pref) { ++ return false; ++ } ++ } ++ return true; ++} ++ ++static inline bool ipl_valid_pv_header(IplParameterBlock *iplb) ++{ ++ IPLBlockPV *ipib_pv = &iplb->pv; ++ ++ if (ipib_pv->pv_header_len > 2 * TARGET_PAGE_SIZE) { ++ return false; ++ } ++ ++ if (!address_space_access_valid(&address_space_memory, ++ ipib_pv->pv_header_addr, ++ ipib_pv->pv_header_len, ++ false, ++ MEMTXATTRS_UNSPECIFIED)) { ++ return false; ++ } ++ ++ return true; ++} ++ ++static inline bool iplb_valid_pv(IplParameterBlock *iplb) ++{ ++ if (iplb->pbt != S390_IPL_TYPE_PV || ++ be32_to_cpu(iplb->len) < S390_IPLB_MIN_PV_LEN) { ++ return false; ++ } ++ if (!ipl_valid_pv_header(iplb)) { ++ return false; ++ } ++ return ipl_valid_pv_components(iplb); ++} ++ + static inline bool iplb_valid(IplParameterBlock *iplb) + { + switch (iplb->pbt) { +diff --git a/hw/s390x/pv.c b/hw/s390x/pv.c +new file mode 100644 +index 0000000000..a40a844806 +--- /dev/null ++++ b/hw/s390x/pv.c +@@ -0,0 +1,98 @@ ++/* ++ * Protected Virtualization functions ++ * ++ * Copyright IBM Corp. 2020 ++ * Author(s): ++ * Janosch Frank ++ * ++ * 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 ++ ++#include "qemu/error-report.h" ++#include "sysemu/kvm.h" ++#include "hw/s390x/pv.h" ++ ++static int __s390_pv_cmd(uint32_t cmd, const char *cmdname, void *data) ++{ ++ struct kvm_pv_cmd pv_cmd = { ++ .cmd = cmd, ++ .data = (uint64_t)data, ++ }; ++ int rc = kvm_vm_ioctl(kvm_state, KVM_S390_PV_COMMAND, &pv_cmd); ++ ++ if (rc) { ++ error_report("KVM PV command %d (%s) failed: header rc %x rrc %x " ++ "IOCTL rc: %d", cmd, cmdname, pv_cmd.rc, pv_cmd.rrc, ++ rc); ++ } ++ return rc; ++} ++ ++/* ++ * This macro lets us pass the command as a string to the function so ++ * we can print it on an error. ++ */ ++#define s390_pv_cmd(cmd, data) __s390_pv_cmd(cmd, #cmd, data); ++#define s390_pv_cmd_exit(cmd, data) \ ++{ \ ++ int rc; \ ++ \ ++ rc = __s390_pv_cmd(cmd, #cmd, data);\ ++ if (rc) { \ ++ exit(1); \ ++ } \ ++} ++ ++int s390_pv_vm_enable(void) ++{ ++ return s390_pv_cmd(KVM_PV_ENABLE, NULL); ++} ++ ++void s390_pv_vm_disable(void) ++{ ++ s390_pv_cmd_exit(KVM_PV_DISABLE, NULL); ++} ++ ++int s390_pv_set_sec_parms(uint64_t origin, uint64_t length) ++{ ++ struct kvm_s390_pv_sec_parm args = { ++ .origin = origin, ++ .length = length, ++ }; ++ ++ return s390_pv_cmd(KVM_PV_SET_SEC_PARMS, &args); ++} ++ ++/* ++ * Called for each component in the SE type IPL parameter block 0. ++ */ ++int s390_pv_unpack(uint64_t addr, uint64_t size, uint64_t tweak) ++{ ++ struct kvm_s390_pv_unp args = { ++ .addr = addr, ++ .size = size, ++ .tweak = tweak, ++ }; ++ ++ return s390_pv_cmd(KVM_PV_UNPACK, &args); ++} ++ ++void s390_pv_perf_clear_reset(void) ++{ ++ s390_pv_cmd_exit(KVM_PV_PREP_RESET, NULL); ++} ++ ++int s390_pv_verify(void) ++{ ++ return s390_pv_cmd(KVM_PV_VERIFY, NULL); ++} ++ ++void s390_pv_unshare(void) ++{ ++ s390_pv_cmd_exit(KVM_PV_UNSHARE_ALL, NULL); ++} +diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c +index 0fa00a9fff..b4d681da43 100644 +--- a/hw/s390x/s390-virtio-ccw.c ++++ b/hw/s390x/s390-virtio-ccw.c +@@ -1,9 +1,10 @@ + /* + * virtio ccw machine + * +- * Copyright 2012 IBM Corp. ++ * Copyright 2012, 2020 IBM Corp. + * Copyright (c) 2009 Alexander Graf + * Author(s): Cornelia Huck ++ * Janosch Frank + * + * 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 +@@ -42,6 +43,8 @@ + #include "hw/qdev-properties.h" + #include "hw/s390x/tod.h" + #include "sysemu/sysemu.h" ++#include "hw/s390x/pv.h" ++#include + + S390CPU *s390_cpu_addr2state(uint16_t cpu_addr) + { +@@ -317,10 +320,78 @@ static inline void s390_do_cpu_ipl(CPUState *cs, run_on_cpu_data arg) + s390_cpu_set_state(S390_CPU_STATE_OPERATING, cpu); + } + ++static void s390_machine_unprotect(S390CcwMachineState *ms) ++{ ++ s390_pv_vm_disable(); ++ ms->pv = false; ++} ++ ++static int s390_machine_protect(S390CcwMachineState *ms) ++{ ++ int rc; ++ ++ /* Create SE VM */ ++ rc = s390_pv_vm_enable(); ++ if (rc) { ++ return rc; ++ } ++ ++ ms->pv = true; ++ ++ /* Set SE header and unpack */ ++ rc = s390_ipl_prepare_pv_header(); ++ if (rc) { ++ goto out_err; ++ } ++ ++ /* Decrypt image */ ++ rc = s390_ipl_pv_unpack(); ++ if (rc) { ++ goto out_err; ++ } ++ ++ /* Verify integrity */ ++ rc = s390_pv_verify(); ++ if (rc) { ++ goto out_err; ++ } ++ return rc; ++ ++out_err: ++ s390_machine_unprotect(ms); ++ return rc; ++} ++ ++static void s390_machine_inject_pv_error(CPUState *cs) ++{ ++ int r1 = (cs->kvm_run->s390_sieic.ipa & 0x00f0) >> 4; ++ CPUS390XState *env = &S390_CPU(cs)->env; ++ ++ /* Report that we are unable to enter protected mode */ ++ env->regs[r1 + 1] = DIAG_308_RC_INVAL_FOR_PV; ++} ++ ++static void s390_pv_prepare_reset(S390CcwMachineState *ms) ++{ ++ CPUState *cs; ++ ++ if (!s390_is_pv()) { ++ return; ++ } ++ /* Unsharing requires all cpus to be stopped */ ++ CPU_FOREACH(cs) { ++ s390_cpu_set_state(S390_CPU_STATE_STOPPED, S390_CPU(cs)); ++ } ++ s390_pv_unshare(); ++ s390_pv_perf_clear_reset(); ++} ++ + static void s390_machine_reset(MachineState *machine) + { ++ S390CcwMachineState *ms = S390_CCW_MACHINE(machine); + enum s390_reset reset_type; + CPUState *cs, *t; ++ S390CPU *cpu; + + /* get the reset parameters, reset them once done */ + s390_ipl_get_reset_request(&cs, &reset_type); +@@ -328,9 +399,15 @@ static void s390_machine_reset(MachineState *machine) + /* all CPUs are paused and synchronized at this point */ + s390_cmma_reset(); + ++ cpu = S390_CPU(cs); ++ + switch (reset_type) { + case S390_RESET_EXTERNAL: + case S390_RESET_REIPL: ++ if (s390_is_pv()) { ++ s390_machine_unprotect(ms); ++ } ++ + qemu_devices_reset(); + s390_crypto_reset(); + +@@ -338,22 +415,56 @@ static void s390_machine_reset(MachineState *machine) + run_on_cpu(cs, s390_do_cpu_ipl, RUN_ON_CPU_NULL); + break; + case S390_RESET_MODIFIED_CLEAR: ++ /* ++ * Susbsystem reset needs to be done before we unshare memory ++ * and lose access to VIRTIO structures in guest memory. ++ */ ++ subsystem_reset(); ++ s390_crypto_reset(); ++ s390_pv_prepare_reset(ms); + CPU_FOREACH(t) { + run_on_cpu(t, s390_do_cpu_full_reset, RUN_ON_CPU_NULL); + } +- subsystem_reset(); +- s390_crypto_reset(); + run_on_cpu(cs, s390_do_cpu_load_normal, RUN_ON_CPU_NULL); + break; + case S390_RESET_LOAD_NORMAL: ++ /* ++ * Susbsystem reset needs to be done before we unshare memory ++ * and lose access to VIRTIO structures in guest memory. ++ */ ++ subsystem_reset(); ++ s390_pv_prepare_reset(ms); + CPU_FOREACH(t) { + if (t == cs) { + continue; + } + run_on_cpu(t, s390_do_cpu_reset, RUN_ON_CPU_NULL); + } +- subsystem_reset(); + run_on_cpu(cs, s390_do_cpu_initial_reset, RUN_ON_CPU_NULL); ++ run_on_cpu(cs, s390_do_cpu_load_normal, RUN_ON_CPU_NULL); ++ break; ++ case S390_RESET_PV: /* Subcode 10 */ ++ subsystem_reset(); ++ s390_crypto_reset(); ++ ++ CPU_FOREACH(t) { ++ if (t == cs) { ++ continue; ++ } ++ run_on_cpu(t, s390_do_cpu_full_reset, RUN_ON_CPU_NULL); ++ } ++ run_on_cpu(cs, s390_do_cpu_reset, RUN_ON_CPU_NULL); ++ ++ if (s390_machine_protect(ms)) { ++ s390_machine_inject_pv_error(cs); ++ /* ++ * Continue after the diag308 so the guest knows something ++ * went wrong. ++ */ ++ s390_cpu_set_state(S390_CPU_STATE_OPERATING, cpu); ++ return; ++ } ++ + run_on_cpu(cs, s390_do_cpu_load_normal, RUN_ON_CPU_NULL); + break; + default: +diff --git a/include/hw/s390x/pv.h b/include/hw/s390x/pv.h +new file mode 100644 +index 0000000000..c6cb360f2f +--- /dev/null ++++ b/include/hw/s390x/pv.h +@@ -0,0 +1,55 @@ ++/* ++ * Protected Virtualization header ++ * ++ * Copyright IBM Corp. 2020 ++ * Author(s): ++ * Janosch Frank ++ * ++ * 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_PV_H ++#define HW_S390_PV_H ++ ++#ifdef CONFIG_KVM ++#include "hw/s390x/s390-virtio-ccw.h" ++ ++static inline bool s390_is_pv(void) ++{ ++ static S390CcwMachineState *ccw; ++ Object *obj; ++ ++ if (ccw) { ++ return ccw->pv; ++ } ++ ++ /* we have to bail out for the "none" machine */ ++ obj = object_dynamic_cast(qdev_get_machine(), ++ TYPE_S390_CCW_MACHINE); ++ if (!obj) { ++ return false; ++ } ++ ccw = S390_CCW_MACHINE(obj); ++ return ccw->pv; ++} ++ ++int s390_pv_vm_enable(void); ++void s390_pv_vm_disable(void); ++int s390_pv_set_sec_parms(uint64_t origin, uint64_t length); ++int s390_pv_unpack(uint64_t addr, uint64_t size, uint64_t tweak); ++void s390_pv_perf_clear_reset(void); ++int s390_pv_verify(void); ++void s390_pv_unshare(void); ++#else /* CONFIG_KVM */ ++static inline bool s390_is_pv(void) { return false; } ++static inline int s390_pv_vm_enable(void) { return 0; } ++static inline void s390_pv_vm_disable(void) {} ++static inline int s390_pv_set_sec_parms(uint64_t origin, uint64_t length) { return 0; } ++static inline int s390_pv_unpack(uint64_t addr, uint64_t size, uint64_t tweak) { return 0; } ++static inline void s390_pv_perf_clear_reset(void) {} ++static inline int s390_pv_verify(void) { return 0; } ++static inline void s390_pv_unshare(void) {} ++#endif /* CONFIG_KVM */ ++ ++#endif /* HW_S390_PV_H */ +diff --git a/include/hw/s390x/s390-virtio-ccw.h b/include/hw/s390x/s390-virtio-ccw.h +index 8aa27199c9..cd1dccc6e3 100644 +--- a/include/hw/s390x/s390-virtio-ccw.h ++++ b/include/hw/s390x/s390-virtio-ccw.h +@@ -28,6 +28,7 @@ typedef struct S390CcwMachineState { + /*< public >*/ + bool aes_key_wrap; + bool dea_key_wrap; ++ bool pv; + uint8_t loadparm[8]; + } S390CcwMachineState; + +diff --git a/target/s390x/cpu.c b/target/s390x/cpu.c +index 427a46e3e1..bb7a588e3b 100644 +--- a/target/s390x/cpu.c ++++ b/target/s390x/cpu.c +@@ -37,6 +37,7 @@ + #include "sysemu/hw_accel.h" + #include "hw/qdev-properties.h" + #ifndef CONFIG_USER_ONLY ++#include "hw/s390x/pv.h" + #include "hw/boards.h" + #include "sysemu/arch_init.h" + #include "sysemu/sysemu.h" +diff --git a/target/s390x/cpu_features_def.inc.h b/target/s390x/cpu_features_def.inc.h +index 31dff0d84e..60db28351d 100644 +--- a/target/s390x/cpu_features_def.inc.h ++++ b/target/s390x/cpu_features_def.inc.h +@@ -107,6 +107,7 @@ DEF_FEAT(DEFLATE_BASE, "deflate-base", STFL, 151, "Deflate-conversion facility ( + DEF_FEAT(VECTOR_PACKED_DECIMAL_ENH, "vxpdeh", STFL, 152, "Vector-Packed-Decimal-Enhancement Facility") + DEF_FEAT(MSA_EXT_9, "msa9-base", STFL, 155, "Message-security-assist-extension-9 facility (excluding subfunctions)") + DEF_FEAT(ETOKEN, "etoken", STFL, 156, "Etoken facility") ++DEF_FEAT(UNPACK, "unpack", STFL, 161, "Unpack facility") + + /* 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/diag.c b/target/s390x/diag.c +index 8aba6341f9..b2cbefb8cf 100644 +--- a/target/s390x/diag.c ++++ b/target/s390x/diag.c +@@ -20,6 +20,8 @@ + #include "sysemu/cpus.h" + #include "hw/s390x/ipl.h" + #include "hw/s390x/s390-virtio-ccw.h" ++#include "hw/s390x/pv.h" ++#include "kvm_s390x.h" + + int handle_diag_288(CPUS390XState *env, uint64_t r1, uint64_t r3) + { +@@ -52,6 +54,10 @@ int handle_diag_288(CPUS390XState *env, uint64_t r1, uint64_t r3) + static int diag308_parm_check(CPUS390XState *env, uint64_t r1, uint64_t addr, + uintptr_t ra, bool write) + { ++ /* Handled by the Ultravisor */ ++ if (s390_is_pv()) { ++ return 0; ++ } + if ((r1 & 1) || (addr & ~TARGET_PAGE_MASK)) { + s390_program_interrupt(env, PGM_SPECIFICATION, ra); + return -1; +@@ -67,6 +73,7 @@ static int diag308_parm_check(CPUS390XState *env, uint64_t r1, uint64_t addr, + + void handle_diag_308(CPUS390XState *env, uint64_t r1, uint64_t r3, uintptr_t ra) + { ++ bool valid; + CPUState *cs = env_cpu(env); + uint64_t addr = env->regs[r1]; + uint64_t subcode = env->regs[r3]; +@@ -82,6 +89,11 @@ void handle_diag_308(CPUS390XState *env, uint64_t r1, uint64_t r3, uintptr_t ra) + return; + } + ++ if (subcode >= DIAG308_PV_SET && !s390_has_feat(S390_FEAT_UNPACK)) { ++ s390_program_interrupt(env, PGM_SPECIFICATION, ra); ++ return; ++ } ++ + switch (subcode) { + case DIAG308_RESET_MOD_CLR: + s390_ipl_reset_request(cs, S390_RESET_MODIFIED_CLEAR); +@@ -94,6 +106,7 @@ void handle_diag_308(CPUS390XState *env, uint64_t r1, uint64_t r3, uintptr_t ra) + s390_ipl_reset_request(cs, S390_RESET_REIPL); + break; + case DIAG308_SET: ++ case DIAG308_PV_SET: + if (diag308_parm_check(env, r1, addr, ra, false)) { + return; + } +@@ -106,7 +119,8 @@ void handle_diag_308(CPUS390XState *env, uint64_t r1, uint64_t r3, uintptr_t ra) + + cpu_physical_memory_read(addr, iplb, be32_to_cpu(iplb->len)); + +- if (!iplb_valid(iplb)) { ++ valid = subcode == DIAG308_PV_SET ? iplb_valid_pv(iplb) : iplb_valid(iplb); ++ if (!valid) { + env->regs[r1 + 1] = DIAG_308_RC_INVALID; + goto out; + } +@@ -117,10 +131,15 @@ out: + g_free(iplb); + return; + case DIAG308_STORE: ++ case DIAG308_PV_STORE: + if (diag308_parm_check(env, r1, addr, ra, true)) { + return; + } +- iplb = s390_ipl_get_iplb(); ++ if (subcode == DIAG308_PV_STORE) { ++ iplb = s390_ipl_get_iplb_pv(); ++ } else { ++ iplb = s390_ipl_get_iplb(); ++ } + if (iplb) { + cpu_physical_memory_write(addr, iplb, be32_to_cpu(iplb->len)); + env->regs[r1 + 1] = DIAG_308_RC_OK; +@@ -128,6 +147,22 @@ out: + env->regs[r1 + 1] = DIAG_308_RC_NO_CONF; + } + return; ++ case DIAG308_PV_START: ++ iplb = s390_ipl_get_iplb_pv(); ++ if (!iplb) { ++ env->regs[r1 + 1] = DIAG_308_RC_NO_PV_CONF; ++ return; ++ } ++ ++ if (kvm_s390_get_hpage_1m()) { ++ error_report("Protected VMs can currently not be backed with " ++ "huge pages"); ++ env->regs[r1 + 1] = DIAG_308_RC_INVAL_FOR_PV; ++ return; ++ } ++ ++ s390_ipl_reset_request(cs, S390_RESET_PV); ++ break; + default: + s390_program_interrupt(env, PGM_SPECIFICATION, ra); + break; +diff --git a/target/s390x/kvm-stub.c b/target/s390x/kvm-stub.c +index c4cd497f85..aa185017a2 100644 +--- a/target/s390x/kvm-stub.c ++++ b/target/s390x/kvm-stub.c +@@ -39,6 +39,11 @@ int kvm_s390_vcpu_interrupt_post_load(S390CPU *cpu) + return 0; + } + ++int kvm_s390_get_hpage_1m(void) ++{ ++ return 0; ++} ++ + int kvm_s390_get_ri(void) + { + return 0; +diff --git a/target/s390x/kvm.c b/target/s390x/kvm.c +index 7f7ebab842..b2b14bde2b 100644 +--- a/target/s390x/kvm.c ++++ b/target/s390x/kvm.c +@@ -321,6 +321,11 @@ void kvm_s390_set_max_pagesize(uint64_t pagesize, Error **errp) + cap_hpage_1m = 1; + } + ++int kvm_s390_get_hpage_1m(void) ++{ ++ return cap_hpage_1m; ++} ++ + static void ccw_machine_class_foreach(ObjectClass *oc, void *opaque) + { + MachineClass *mc = MACHINE_CLASS(oc); +diff --git a/target/s390x/kvm_s390x.h b/target/s390x/kvm_s390x.h +index 0b21789796..dea813f450 100644 +--- a/target/s390x/kvm_s390x.h ++++ b/target/s390x/kvm_s390x.h +@@ -23,6 +23,7 @@ void kvm_s390_program_interrupt(S390CPU *cpu, uint16_t code); + int kvm_s390_set_cpu_state(S390CPU *cpu, uint8_t cpu_state); + 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_gs(void); + int kvm_s390_get_clock(uint8_t *tod_high, uint64_t *tod_clock); +-- +2.23.0 + diff --git a/s390x-pv-Retry-ioctls-on-EINTR.patch b/s390x-pv-Retry-ioctls-on-EINTR.patch new file mode 100644 index 0000000000000000000000000000000000000000..887ef0c629e47b1a7979ba65aa0e95b7fa3eaf32 --- /dev/null +++ b/s390x-pv-Retry-ioctls-on-EINTR.patch @@ -0,0 +1,40 @@ +From e8d12a55f6d3e577455b02f15907c460578c689b Mon Sep 17 00:00:00 2001 +From: Christian Borntraeger +Date: Fri, 27 Mar 2020 08:46:16 -0400 +Subject: [PATCH 051/709] s390x/pv: Retry ioctls on -EINTR + +PV_ENABLE (and maybe others) might return -EINTR when a signal is +pending. See the Linux kernel patch "s390/gmap: return proper error code +on ksm unsharing" for details. Let us retry the ioctl in that case. + +Fixes: c3347ed0d2ee ("s390x: protvirt: Support unpack facility") +Reported-by: Marc Hartmayer +Acked-by: Janosch Frank +Tested-by: Marc Hartmayer +Signed-off-by: Christian Borntraeger +Message-Id: <20200327124616.34866-1-borntraeger@de.ibm.com> +Signed-off-by: Cornelia Huck +--- + hw/s390x/pv.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/hw/s390x/pv.c b/hw/s390x/pv.c +index a40a844806..cb0dce4a4f 100644 +--- a/hw/s390x/pv.c ++++ b/hw/s390x/pv.c +@@ -23,7 +23,11 @@ static int __s390_pv_cmd(uint32_t cmd, const char *cmdname, void *data) + .cmd = cmd, + .data = (uint64_t)data, + }; +- int rc = kvm_vm_ioctl(kvm_state, KVM_S390_PV_COMMAND, &pv_cmd); ++ int rc; ++ ++ do { ++ rc = kvm_vm_ioctl(kvm_state, KVM_S390_PV_COMMAND, &pv_cmd); ++ } while (rc == -EINTR); + + if (rc) { + error_report("KVM PV command %d (%s) failed: header rc %x rrc %x " +-- +2.23.0 + diff --git a/s390x-s390-virtio-ccw-Fix-build-on-systems-without-K.patch b/s390x-s390-virtio-ccw-Fix-build-on-systems-without-K.patch new file mode 100644 index 0000000000000000000000000000000000000000..f4daef19b2e227afe08a94c68ac26c1bca11b2b7 --- /dev/null +++ b/s390x-s390-virtio-ccw-Fix-build-on-systems-without-K.patch @@ -0,0 +1,134 @@ +From fbc1384ccd48fa7c0c38f950adf7992a4fb6042e Mon Sep 17 00:00:00 2001 +From: Christian Borntraeger +Date: Mon, 6 Apr 2020 06:01:58 -0400 +Subject: [PATCH 052/709] s390x/s390-virtio-ccw: Fix build on systems without + KVM + +linux/kvm.h is not available on all platforms. Let us move +s390_machine_inject_pv_error into pv.c as it uses KVM structures. +Also rename the function to s390_pv_inject_reset_error. + +While at it, ipl.h needs an include for "exec/address-spaces.h" +as it uses address_space_memory. + +Fixes: c3347ed0d2ee ("s390x: protvirt: Support unpack facility") +Reported-by: Bruce Rogers +Signed-off-by: Christian Borntraeger +Message-Id: <20200406100158.5940-2-borntraeger@de.ibm.com> +Reviewed-by: David Hildenbrand +Signed-off-by: Cornelia Huck +--- + hw/s390x/ipl.h | 1 + + hw/s390x/pv.c | 11 +++++++++++ + hw/s390x/s390-virtio-ccw.c | 12 +----------- + include/hw/s390x/pv.h | 3 +++ + 4 files changed, 16 insertions(+), 11 deletions(-) + +diff --git a/hw/s390x/ipl.h b/hw/s390x/ipl.h +index 89b3044d7a..53cc9eb5ac 100644 +--- a/hw/s390x/ipl.h ++++ b/hw/s390x/ipl.h +@@ -14,6 +14,7 @@ + #define HW_S390_IPL_H + + #include "cpu.h" ++#include "exec/address-spaces.h" + #include "hw/qdev-core.h" + + struct IPLBlockPVComp { +diff --git a/hw/s390x/pv.c b/hw/s390x/pv.c +index cb0dce4a4f..f11868e865 100644 +--- a/hw/s390x/pv.c ++++ b/hw/s390x/pv.c +@@ -13,8 +13,10 @@ + + #include + ++#include "cpu.h" + #include "qemu/error-report.h" + #include "sysemu/kvm.h" ++#include "hw/s390x/ipl.h" + #include "hw/s390x/pv.h" + + static int __s390_pv_cmd(uint32_t cmd, const char *cmdname, void *data) +@@ -100,3 +102,12 @@ void s390_pv_unshare(void) + { + s390_pv_cmd_exit(KVM_PV_UNSHARE_ALL, NULL); + } ++ ++void s390_pv_inject_reset_error(CPUState *cs) ++{ ++ int r1 = (cs->kvm_run->s390_sieic.ipa & 0x00f0) >> 4; ++ CPUS390XState *env = &S390_CPU(cs)->env; ++ ++ /* Report that we are unable to enter protected mode */ ++ env->regs[r1 + 1] = DIAG_308_RC_INVAL_FOR_PV; ++} +diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c +index b268907395..45292fb5a8 100644 +--- a/hw/s390x/s390-virtio-ccw.c ++++ b/hw/s390x/s390-virtio-ccw.c +@@ -45,7 +45,6 @@ + #include "sysemu/sysemu.h" + #include "sysemu/balloon.h" + #include "hw/s390x/pv.h" +-#include + #include "migration/blocker.h" + + static Error *pv_mig_blocker; +@@ -390,15 +389,6 @@ out_err: + return rc; + } + +-static void s390_machine_inject_pv_error(CPUState *cs) +-{ +- int r1 = (cs->kvm_run->s390_sieic.ipa & 0x00f0) >> 4; +- CPUS390XState *env = &S390_CPU(cs)->env; +- +- /* Report that we are unable to enter protected mode */ +- env->regs[r1 + 1] = DIAG_308_RC_INVAL_FOR_PV; +-} +- + static void s390_pv_prepare_reset(S390CcwMachineState *ms) + { + CPUState *cs; +@@ -484,7 +474,7 @@ static void s390_machine_reset(MachineState *machine) + run_on_cpu(cs, s390_do_cpu_reset, RUN_ON_CPU_NULL); + + if (s390_machine_protect(ms)) { +- s390_machine_inject_pv_error(cs); ++ s390_pv_inject_reset_error(cs); + /* + * Continue after the diag308 so the guest knows something + * went wrong. +diff --git a/include/hw/s390x/pv.h b/include/hw/s390x/pv.h +index c6cb360f2f..522ca6a04e 100644 +--- a/include/hw/s390x/pv.h ++++ b/include/hw/s390x/pv.h +@@ -13,6 +13,7 @@ + #define HW_S390_PV_H + + #ifdef CONFIG_KVM ++#include "cpu.h" + #include "hw/s390x/s390-virtio-ccw.h" + + static inline bool s390_is_pv(void) +@@ -41,6 +42,7 @@ int s390_pv_unpack(uint64_t addr, uint64_t size, uint64_t tweak); + void s390_pv_perf_clear_reset(void); + int s390_pv_verify(void); + void s390_pv_unshare(void); ++void s390_pv_inject_reset_error(CPUState *cs); + #else /* CONFIG_KVM */ + static inline bool s390_is_pv(void) { return false; } + static inline int s390_pv_vm_enable(void) { return 0; } +@@ -50,6 +52,7 @@ static inline int s390_pv_unpack(uint64_t addr, uint64_t size, uint64_t tweak) { + static inline void s390_pv_perf_clear_reset(void) {} + static inline int s390_pv_verify(void) { return 0; } + static inline void s390_pv_unshare(void) {} ++static inline void s390_pv_inject_reset_error(CPUState *cs) {}; + #endif /* CONFIG_KVM */ + + #endif /* HW_S390_PV_H */ +-- +2.23.0 + diff --git a/sam460ex-Suppress-useless-warning-on-m-32-and-m-64.patch b/sam460ex-Suppress-useless-warning-on-m-32-and-m-64.patch new file mode 100644 index 0000000000000000000000000000000000000000..073e58959f60bf609a99f6256102e68d2e198a83 --- /dev/null +++ b/sam460ex-Suppress-useless-warning-on-m-32-and-m-64.patch @@ -0,0 +1,46 @@ +From fc0cfc1decb5457058d7cbfeb7ae26ad5d6ecba4 Mon Sep 17 00:00:00 2001 +From: Markus Armbruster +Date: Wed, 22 Apr 2020 15:48:12 +0200 +Subject: [PATCH 028/709] sam460ex: Suppress useless warning on -m 32 and -m 64 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Requesting 32 or 64 MiB of RAM with the sam460ex machine type produces +a useless warning: + + qemu-system-ppc: warning: Memory size is too small for SDRAM type, adjusting type + +This is because sam460ex_init() asks spd_data_generate() for DDR2, +which is impossible, so spd_data_generate() corrects it to DDR. + +The warning goes back to commit 08fd99179a "sam460ex: Clean up SPD +EEPROM creation". + +Make sam460ex_init() pass the correct SDRAM type to get rid of the +warning. + +Signed-off-by: Markus Armbruster +Message-Id: <20200422134815.1584-2-armbru@redhat.com> +Reviewed-by: Philippe Mathieu-Daudé +--- + hw/ppc/sam460ex.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/hw/ppc/sam460ex.c b/hw/ppc/sam460ex.c +index 898453cf30..1e3eaac0db 100644 +--- a/hw/ppc/sam460ex.c ++++ b/hw/ppc/sam460ex.c +@@ -335,7 +335,8 @@ static void sam460ex_init(MachineState *machine) + dev = sysbus_create_simple(TYPE_PPC4xx_I2C, 0x4ef600700, uic[0][2]); + i2c = PPC4xx_I2C(dev)->bus; + /* SPD EEPROM on RAM module */ +- spd_data = spd_data_generate(DDR2, ram_sizes[0], &err); ++ spd_data = spd_data_generate(ram_sizes[0] < 128 * MiB ? DDR : DDR2, ++ ram_sizes[0], &err); + if (err) { + warn_report_err(err); + } +-- +2.23.0 + diff --git a/scsi-disk-define-props-in-scsi_block_disk-to-avoid-memleaks.patch b/scsi-disk-define-props-in-scsi_block_disk-to-avoid-memleaks.patch deleted file mode 100644 index a180aa1a08062f11cd313f5019d35933cd55747c..0000000000000000000000000000000000000000 --- a/scsi-disk-define-props-in-scsi_block_disk-to-avoid-memleaks.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 79da8e2e18610ae22a3bd640c117ba56b911038d Mon Sep 17 00:00:00 2001 -From: Pan Nengyuan -Date: Mon, 13 Jan 2020 15:53:32 +0800 -Subject: [PATCH] scsi-disk: define props in scsi_block_disk to avoid - memleaks - -scsi_block_realize() use scsi_realize() to init some props, but -these props is not defined in scsi_block_disk_properties, so they will -not be freed. - -This patch defines these prop in scsi_block_disk_properties to avoid memleaks. - -Signed-off-by: Pan Nengyuan ---- - hw/scsi/scsi-disk.c | 4 +--- - 1 file changed, 1 insertion(+), 3 deletions(-) - -diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c -index e7e865ab..233afb4a 100644 ---- a/hw/scsi/scsi-disk.c -+++ b/hw/scsi/scsi-disk.c -@@ -3026,9 +3026,7 @@ static const TypeInfo scsi_cd_info = { - - #ifdef __linux__ - static Property scsi_block_properties[] = { -- DEFINE_BLOCK_ERROR_PROPERTIES(SCSIDiskState, qdev.conf), \ -- DEFINE_PROP_DRIVE("drive", SCSIDiskState, qdev.conf.blk), -- DEFINE_PROP_BOOL("share-rw", SCSIDiskState, qdev.conf.share_rw, false), -+ DEFINE_SCSI_DISK_PROPERTIES(), - DEFINE_PROP_UINT16("rotation_rate", SCSIDiskState, rotation_rate, 0), - DEFINE_PROP_UINT64("max_unmap_size", SCSIDiskState, max_unmap_size, - DEFAULT_MAX_UNMAP_SIZE), --- -2.18.1 - - diff --git a/scsi-esp-pci-add-g_assert-for-fix-clang-analyzer-war.patch b/scsi-esp-pci-add-g_assert-for-fix-clang-analyzer-war.patch new file mode 100644 index 0000000000000000000000000000000000000000..7cb8e911d0804678d9bf4835d4045fb06f71e779 --- /dev/null +++ b/scsi-esp-pci-add-g_assert-for-fix-clang-analyzer-war.patch @@ -0,0 +1,35 @@ +From d58f8860ddba8a316bdcdc1010ca4d2ed0b41941 Mon Sep 17 00:00:00 2001 +From: Chen Qun +Date: Wed, 25 Mar 2020 10:59:17 +0800 +Subject: [PATCH 146/709] scsi/esp-pci: add g_assert() for fix clang analyzer + warning in esp_pci_io_write() + +Clang static code analyzer show warning: + hw/scsi/esp-pci.c:198:9: warning: Value stored to 'size' is never read + size = 4; + ^ ~ + +Reported-by: Euler Robot +Signed-off-by: Chen Qun +Reviewed-by: Laurent Vivier +Message-Id: <20200325025919.21316-2-kuhn.chenqun@huawei.com> +Signed-off-by: Laurent Vivier +--- + hw/scsi/esp-pci.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/hw/scsi/esp-pci.c b/hw/scsi/esp-pci.c +index d5a1f9e017..497a8d5901 100644 +--- a/hw/scsi/esp-pci.c ++++ b/hw/scsi/esp-pci.c +@@ -197,6 +197,7 @@ static void esp_pci_io_write(void *opaque, hwaddr addr, + addr &= ~3; + size = 4; + } ++ g_assert(size >= 4); + + if (addr < 0x40) { + /* SCSI core reg */ +-- +2.23.0 + diff --git a/scsi-lsi-exit-infinite-loop-while-executing-script.patch b/scsi-lsi-exit-infinite-loop-while-executing-script.patch deleted file mode 100644 index f78c28670b1bcff30d6e66dba17fe4b3ed18cddd..0000000000000000000000000000000000000000 --- a/scsi-lsi-exit-infinite-loop-while-executing-script.patch +++ /dev/null @@ -1,104 +0,0 @@ -From dee1c7242e6b11d502728840f36d021ceedce140 Mon Sep 17 00:00:00 2001 -From: Paolo Bonzini -Date: Wed, 14 Aug 2019 17:35:21 +0530 -Subject: [PATCH 3/5] scsi: lsi: exit infinite loop while executing script - (CVE-2019-12068) - -When executing script in lsi_execute_script(), the LSI scsi adapter -emulator advances 's->dsp' index to read next opcode. This can lead -to an infinite loop if the next opcode is empty. Move the existing -loop exit after 10k iterations so that it covers no-op opcodes as -well. - -Reported-by: Bugs SysSec -Signed-off-by: Paolo Bonzini -Signed-off-by: Prasad J Pandit -Signed-off-by: Paolo Bonzini -(cherry-picked from commit de594e47659029316bbf9391efb79da0a1a08e08) ---- - hw/scsi/lsi53c895a.c | 41 +++++++++++++++++++++++++++-------------- - 1 file changed, 27 insertions(+), 14 deletions(-) - -diff --git a/hw/scsi/lsi53c895a.c b/hw/scsi/lsi53c895a.c -index da7239d..d3380b6 100644 ---- a/hw/scsi/lsi53c895a.c -+++ b/hw/scsi/lsi53c895a.c -@@ -184,6 +184,9 @@ static const char *names[] = { - /* Flag set if this is a tagged command. */ - #define LSI_TAG_VALID (1 << 16) - -+/* Maximum instructions to process. */ -+#define LSI_MAX_INSN 10000 -+ - typedef struct lsi_request { - SCSIRequest *req; - uint32_t tag; -@@ -1131,7 +1134,21 @@ static void lsi_execute_script(LSIState *s) - - s->istat1 |= LSI_ISTAT1_SRUN; - again: -- insn_processed++; -+ if (++insn_processed > LSI_MAX_INSN) { -+ /* Some windows drivers make the device spin waiting for a memory -+ location to change. If we have been executed a lot of code then -+ assume this is the case and force an unexpected device disconnect. -+ This is apparently sufficient to beat the drivers into submission. -+ */ -+ if (!(s->sien0 & LSI_SIST0_UDC)) { -+ qemu_log_mask(LOG_GUEST_ERROR, -+ "lsi_scsi: inf. loop with UDC masked"); -+ } -+ lsi_script_scsi_interrupt(s, LSI_SIST0_UDC, 0); -+ lsi_disconnect(s); -+ trace_lsi_execute_script_stop(); -+ return; -+ } - insn = read_dword(s, s->dsp); - if (!insn) { - /* If we receive an empty opcode increment the DSP by 4 bytes -@@ -1568,19 +1585,7 @@ again: - } - } - } -- if (insn_processed > 10000 && s->waiting == LSI_NOWAIT) { -- /* Some windows drivers make the device spin waiting for a memory -- location to change. If we have been executed a lot of code then -- assume this is the case and force an unexpected device disconnect. -- This is apparently sufficient to beat the drivers into submission. -- */ -- if (!(s->sien0 & LSI_SIST0_UDC)) { -- qemu_log_mask(LOG_GUEST_ERROR, -- "lsi_scsi: inf. loop with UDC masked"); -- } -- lsi_script_scsi_interrupt(s, LSI_SIST0_UDC, 0); -- lsi_disconnect(s); -- } else if (s->istat1 & LSI_ISTAT1_SRUN && s->waiting == LSI_NOWAIT) { -+ if (s->istat1 & LSI_ISTAT1_SRUN && s->waiting == LSI_NOWAIT) { - if (s->dcntl & LSI_DCNTL_SSM) { - lsi_script_dma_interrupt(s, LSI_DSTAT_SSI); - } else { -@@ -1968,6 +1973,10 @@ static void lsi_reg_writeb(LSIState *s, int offset, uint8_t val) - case 0x2f: /* DSP[24:31] */ - s->dsp &= 0x00ffffff; - s->dsp |= val << 24; -+ /* -+ * FIXME: if s->waiting != LSI_NOWAIT, this will only execute one -+ * instruction. Is this correct? -+ */ - if ((s->dmode & LSI_DMODE_MAN) == 0 - && (s->istat1 & LSI_ISTAT1_SRUN) == 0) - lsi_execute_script(s); -@@ -1986,6 +1995,10 @@ static void lsi_reg_writeb(LSIState *s, int offset, uint8_t val) - break; - case 0x3b: /* DCNTL */ - s->dcntl = val & ~(LSI_DCNTL_PFF | LSI_DCNTL_STD); -+ /* -+ * FIXME: if s->waiting != LSI_NOWAIT, this will only execute one -+ * instruction. Is this correct? -+ */ - if ((val & LSI_DCNTL_STD) && (s->istat1 & LSI_ISTAT1_SRUN) == 0) - lsi_execute_script(s); - break; --- -1.8.3.1 - diff --git a/sheepdog-Support-BDRV_REQ_ZERO_WRITE-for-truncate.patch b/sheepdog-Support-BDRV_REQ_ZERO_WRITE-for-truncate.patch new file mode 100644 index 0000000000000000000000000000000000000000..3a6e618ec78d19a03292272caf2e99dda9e1b8cb --- /dev/null +++ b/sheepdog-Support-BDRV_REQ_ZERO_WRITE-for-truncate.patch @@ -0,0 +1,31 @@ +From fec00559e71c94749deac176f6c4bebf81fbe7b8 Mon Sep 17 00:00:00 2001 +From: Eric Blake +Date: Tue, 28 Apr 2020 15:29:01 -0500 +Subject: [PATCH 353/709] sheepdog: Support BDRV_REQ_ZERO_WRITE for truncate + +Our .bdrv_has_zero_init_truncate always returns 1 because sheepdog +always 0-fills; we can use that same knowledge to implement +BDRV_REQ_ZERO_WRITE by ignoring it. + +Signed-off-by: Eric Blake +Message-Id: <20200428202905.770727-6-eblake@redhat.com> +Signed-off-by: Kevin Wolf +--- + block/sheepdog.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/block/sheepdog.c b/block/sheepdog.c +index 2eb61938ff..739e6dee30 100644 +--- a/block/sheepdog.c ++++ b/block/sheepdog.c +@@ -1654,6 +1654,7 @@ static int sd_open(BlockDriverState *bs, QDict *options, int flags, + memcpy(&s->inode, buf, sizeof(s->inode)); + + bs->total_sectors = s->inode.vdi_size / BDRV_SECTOR_SIZE; ++ bs->supported_truncate_flags = BDRV_REQ_ZERO_WRITE; + pstrcpy(s->name, sizeof(s->name), vdi); + qemu_co_mutex_init(&s->lock); + qemu_co_mutex_init(&s->queue_lock); +-- +2.23.0 + diff --git a/slirp-Fix-heap-overflow-in-ip_reass-on-big-packet-input.patch b/slirp-Fix-heap-overflow-in-ip_reass-on-big-packet-input.patch deleted file mode 100644 index 3ebf0297748c77e23667cd1b641de192fb13d06e..0000000000000000000000000000000000000000 --- a/slirp-Fix-heap-overflow-in-ip_reass-on-big-packet-input.patch +++ /dev/null @@ -1,53 +0,0 @@ -From c2e03e2aa42d0f4f41deb08c2655503835840afa Mon Sep 17 00:00:00 2001 -From: Michael Roth -Date: Tue, 24 Sep 2019 15:57:59 -0500 -Subject: [PATCH] slirp: Fix heap overflow in ip_reass on big packet input - -When the first fragment does not fit in the preallocated buffer, q will -already be pointing to the ext buffer, so we mustn't try to update it. - -Signed-off-by: Samuel Thibault -(from libslirp.git commit 126c04acbabd7ad32c2b018fe10dfac2a3bc1210) -(from libslirp.git commit e0be80430c390bce181ea04dfcdd6ea3dfa97de1) -*squash in e0be80 (clarifying comments) -Fixes: CVE-2019-14378 -Signed-off-by: Michael Roth ---- - slirp/src/ip_input.c | 13 +++++++------ - 1 file changed, 7 insertions(+), 6 deletions(-) - -diff --git a/slirp/src/ip_input.c b/slirp/src/ip_input.c -index a714fecd58..68a99de5b5 100644 ---- a/slirp/src/ip_input.c -+++ b/slirp/src/ip_input.c -@@ -331,6 +331,8 @@ insert: - q = fp->frag_link.next; - m = dtom(slirp, q); - -+ int was_ext = m->m_flags & M_EXT; -+ - q = (struct ipasfrag *) q->ipf_next; - while (q != (struct ipasfrag*)&fp->frag_link) { - struct mbuf *t = dtom(slirp, q); -@@ -347,13 +349,12 @@ insert: - q = fp->frag_link.next; - - /* -- * If the fragments concatenated to an mbuf that's -- * bigger than the total size of the fragment, then and -- * m_ext buffer was alloced. But fp->ipq_next points to -- * the old buffer (in the mbuf), so we must point ip -- * into the new buffer. -+ * If the fragments concatenated to an mbuf that's bigger than the total -+ * size of the fragment and the mbuf was not already using an m_ext buffer, -+ * then an m_ext buffer was alloced. But fp->ipq_next points to the old -+ * buffer (in the mbuf), so we must point ip into the new buffer. - */ -- if (m->m_flags & M_EXT) { -+ if (!was_ext && m->m_flags & M_EXT) { - int delta = (char *)q - m->m_dat; - q = (struct ipasfrag *)(m->m_ext + delta); - } --- -2.19.1 - diff --git a/slirp-ip_reass-Fix-use-after-free.patch b/slirp-ip_reass-Fix-use-after-free.patch deleted file mode 100644 index b603379f8a8ae7854bb98d50bdfe48da47b9bd91..0000000000000000000000000000000000000000 --- a/slirp-ip_reass-Fix-use-after-free.patch +++ /dev/null @@ -1,47 +0,0 @@ -From b27192be13da3fb59f51185d9a1f944b3474b2fc Mon Sep 17 00:00:00 2001 -From: Michael Roth -Date: Tue, 24 Sep 2019 16:04:04 -0500 -Subject: [PATCH] slirp: ip_reass: Fix use after free - -Using ip_deq after m_free might read pointers from an allocation reuse. - -This would be difficult to exploit, but that is still related with -CVE-2019-14378 which generates fragmented IP packets that would trigger this -issue and at least produce a DoS. - -Signed-off-by: Samuel Thibault -(from libslirp.git commit c59279437eda91841b9d26079c70b8a540d41204) -Fixes: CVE-2019-15890 -Signed-off-by: Michael Roth ---- - slirp/src/ip_input.c | 6 ++++-- - 1 file changed, 4 insertions(+), 2 deletions(-) - -diff --git a/slirp/src/ip_input.c b/slirp/src/ip_input.c -index 68a99de5b5..89ae04e0c1 100644 ---- a/slirp/src/ip_input.c -+++ b/slirp/src/ip_input.c -@@ -297,6 +297,7 @@ ip_reass(Slirp *slirp, struct ip *ip, struct ipq *fp) - */ - while (q != (struct ipasfrag*)&fp->frag_link && - ip->ip_off + ip->ip_len > q->ipf_off) { -+ struct ipasfrag *prev; - i = (ip->ip_off + ip->ip_len) - q->ipf_off; - if (i < q->ipf_len) { - q->ipf_len -= i; -@@ -304,9 +305,10 @@ ip_reass(Slirp *slirp, struct ip *ip, struct ipq *fp) - m_adj(dtom(slirp, q), i); - break; - } -+ prev = q; - q = q->ipf_next; -- m_free(dtom(slirp, q->ipf_prev)); -- ip_deq(q->ipf_prev); -+ ip_deq(prev); -+ m_free(dtom(slirp, prev)); - } - - insert: --- -2.19.1 - diff --git a/smbios-Add-missing-member-of-type-4-for-smbios-3.0.patch b/smbios-Add-missing-member-of-type-4-for-smbios-3.0.patch deleted file mode 100644 index c45af3e6aa3ba4b5c58583f5605c7a6b9f90e508..0000000000000000000000000000000000000000 --- a/smbios-Add-missing-member-of-type-4-for-smbios-3.0.patch +++ /dev/null @@ -1,57 +0,0 @@ -From e52fdbd850b49304c5bbd5f19c9f518b80efef42 Mon Sep 17 00:00:00 2001 -From: zhanghailiang -Date: Wed, 31 Jul 2019 15:40:55 +0800 -Subject: [PATCH] smbios: Add missing member of type 4 for smbios 3.0 - -According to smbios 3.0 spec, for processor information (type 4), -it adds three new members (Core Count 2, Core enabled 2, thread count 2) for 3.0, - -Without this three members, we can not get correct cpu frequency from dmi, -Because it will failed to check the length of Processor Infomation in DMI. - -The corresponding codes in kernel is like: - if (dm->type == DMI_ENTRY_PROCESSOR && - dm->length >= DMI_ENTRY_PROCESSOR_MIN_LENGTH) { - u16 val = (u16)get_unaligned((const u16 *) - (dmi_data + DMI_PROCESSOR_MAX_SPEED)); - *mhz = val > *mhz ? val : *mhz; - } - -Signed-off-by: zhanghailiang ---- - hw/smbios/smbios.c | 4 +++- - include/hw/firmware/smbios.h | 3 +++ - 2 files changed, 6 insertions(+), 1 deletion(-) - -diff --git a/hw/smbios/smbios.c b/hw/smbios/smbios.c -index 47be9071..b11ec6e3 100644 ---- a/hw/smbios/smbios.c -+++ b/hw/smbios/smbios.c -@@ -600,7 +600,9 @@ static void smbios_build_type_4_table(unsigned instance) - t->thread_count = smp_threads; - t->processor_characteristics = cpu_to_le16(0x02); /* Unknown */ - t->processor_family2 = cpu_to_le16(0x01); /* Other */ -- -+ t->corecount2 = 0; -+ t->enabledcorecount2 = 0; -+ t->threadcount2 = 0; - SMBIOS_BUILD_TABLE_POST; - smbios_type4_count++; - } -diff --git a/include/hw/firmware/smbios.h b/include/hw/firmware/smbios.h -index 6fef32a3..70eb7304 100644 ---- a/include/hw/firmware/smbios.h -+++ b/include/hw/firmware/smbios.h -@@ -193,6 +193,9 @@ struct smbios_type_4 { - uint8_t thread_count; - uint16_t processor_characteristics; - uint16_t processor_family2; -+ uint16_t corecount2; -+ uint16_t enabledcorecount2; -+ uint16_t threadcount2; - } QEMU_PACKED; - - /* SMBIOS type 11 - OEM strings */ --- -2.19.1 - diff --git a/smbus-Fix-spd_data_generate-error-API-violation.patch b/smbus-Fix-spd_data_generate-error-API-violation.patch new file mode 100644 index 0000000000000000000000000000000000000000..f934ab7bcfb16cd75f0aeafa40c6e05192eccc07 --- /dev/null +++ b/smbus-Fix-spd_data_generate-error-API-violation.patch @@ -0,0 +1,172 @@ +From f26740c61a57f1a1556f79a49c6863479fe5aa6b Mon Sep 17 00:00:00 2001 +From: Markus Armbruster +Date: Wed, 22 Apr 2020 15:48:13 +0200 +Subject: [PATCH 029/709] smbus: Fix spd_data_generate() error API violation + +The Error ** argument must be NULL, &error_abort, &error_fatal, or a +pointer to a variable containing NULL. Passing an argument of the +latter kind twice without clearing it in between is wrong: if the +first call sets an error, it no longer points to NULL for the second +call. + +spd_data_generate() can pass @errp to error_setg() more than once when +it adjusts both memory size and type. Harmless, because no caller +passes anything that needs adjusting. Until the previous commit, +sam460ex passed types that needed adjusting, but not sizes. + +spd_data_generate()'s contract is rather awkward: + + If everything's fine, return non-null and don't set an error. + + Else, if memory size or type need adjusting, return non-null and + set an error describing the adjustment. + + Else, return null and set an error reporting why no data can be + generated. + +Its callers treat the error as a warning even when null is returned. +They don't create the "smbus-eeprom" device then. Suspicious. + +Since the previous commit, only "everything's fine" can actually +happen. Drop the unused code and simplify the callers. This gets rid +of the error API violation. + +Signed-off-by: Markus Armbruster +Message-Id: <20200422134815.1584-3-armbru@redhat.com> +--- + hw/i2c/smbus_eeprom.c | 30 ++++-------------------------- + hw/mips/mips_fulong2e.c | 10 ++-------- + hw/ppc/sam460ex.c | 12 +++--------- + include/hw/i2c/smbus_eeprom.h | 2 +- + 4 files changed, 10 insertions(+), 44 deletions(-) + +diff --git a/hw/i2c/smbus_eeprom.c b/hw/i2c/smbus_eeprom.c +index 5adf3b15b5..07fbbf87f1 100644 +--- a/hw/i2c/smbus_eeprom.c ++++ b/hw/i2c/smbus_eeprom.c +@@ -195,8 +195,7 @@ void smbus_eeprom_init(I2CBus *smbus, int nb_eeprom, + } + + /* Generate SDRAM SPD EEPROM data describing a module of type and size */ +-uint8_t *spd_data_generate(enum sdram_type type, ram_addr_t ram_size, +- Error **errp) ++uint8_t *spd_data_generate(enum sdram_type type, ram_addr_t ram_size) + { + uint8_t *spd; + uint8_t nbanks; +@@ -222,29 +221,10 @@ uint8_t *spd_data_generate(enum sdram_type type, ram_addr_t ram_size, + g_assert_not_reached(); + } + size = ram_size >> 20; /* work in terms of megabytes */ +- if (size < 4) { +- error_setg(errp, "SDRAM size is too small"); +- return NULL; +- } + sz_log2 = 31 - clz32(size); + size = 1U << sz_log2; +- if (ram_size > size * MiB) { +- error_setg(errp, "SDRAM size 0x"RAM_ADDR_FMT" is not a power of 2, " +- "truncating to %u MB", ram_size, size); +- } +- if (sz_log2 < min_log2) { +- error_setg(errp, +- "Memory size is too small for SDRAM type, adjusting type"); +- if (size >= 32) { +- type = DDR; +- min_log2 = 5; +- max_log2 = 12; +- } else { +- type = SDR; +- min_log2 = 2; +- max_log2 = 9; +- } +- } ++ assert(ram_size == size * MiB); ++ assert(sz_log2 >= min_log2); + + nbanks = 1; + while (sz_log2 > max_log2 && nbanks < 8) { +@@ -252,9 +232,7 @@ uint8_t *spd_data_generate(enum sdram_type type, ram_addr_t ram_size, + nbanks++; + } + +- if (size > (1ULL << sz_log2) * nbanks) { +- error_setg(errp, "Memory size is too big for SDRAM, truncating"); +- } ++ assert(size == (1ULL << sz_log2) * nbanks); + + /* split to 2 banks if possible to avoid a bug in MIPS Malta firmware */ + if (nbanks == 1 && sz_log2 > min_log2) { +diff --git a/hw/mips/mips_fulong2e.c b/hw/mips/mips_fulong2e.c +index 5040afd581..ef02d54b33 100644 +--- a/hw/mips/mips_fulong2e.c ++++ b/hw/mips/mips_fulong2e.c +@@ -297,7 +297,6 @@ static void mips_fulong2e_init(MachineState *machine) + MemoryRegion *bios = g_new(MemoryRegion, 1); + long bios_size; + uint8_t *spd_data; +- Error *err = NULL; + int64_t kernel_entry; + PCIBus *pci_bus; + ISABus *isa_bus; +@@ -377,13 +376,8 @@ static void mips_fulong2e_init(MachineState *machine) + } + + /* Populate SPD eeprom data */ +- spd_data = spd_data_generate(DDR, machine->ram_size, &err); +- if (err) { +- warn_report_err(err); +- } +- if (spd_data) { +- smbus_eeprom_init_one(smbus, 0x50, spd_data); +- } ++ spd_data = spd_data_generate(DDR, machine->ram_size); ++ smbus_eeprom_init_one(smbus, 0x50, spd_data); + + mc146818_rtc_init(isa_bus, 2000, NULL); + +diff --git a/hw/ppc/sam460ex.c b/hw/ppc/sam460ex.c +index 1e3eaac0db..42a8c9fb7f 100644 +--- a/hw/ppc/sam460ex.c ++++ b/hw/ppc/sam460ex.c +@@ -292,7 +292,6 @@ static void sam460ex_init(MachineState *machine) + SysBusDevice *sbdev; + struct boot_info *boot_info; + uint8_t *spd_data; +- Error *err = NULL; + int success; + + cpu = POWERPC_CPU(cpu_create(machine->cpu_type)); +@@ -336,14 +335,9 @@ static void sam460ex_init(MachineState *machine) + i2c = PPC4xx_I2C(dev)->bus; + /* SPD EEPROM on RAM module */ + spd_data = spd_data_generate(ram_sizes[0] < 128 * MiB ? DDR : DDR2, +- ram_sizes[0], &err); +- if (err) { +- warn_report_err(err); +- } +- if (spd_data) { +- spd_data[20] = 4; /* SO-DIMM module */ +- smbus_eeprom_init_one(i2c, 0x50, spd_data); +- } ++ ram_sizes[0]); ++ spd_data[20] = 4; /* SO-DIMM module */ ++ smbus_eeprom_init_one(i2c, 0x50, spd_data); + /* RTC */ + i2c_create_slave(i2c, "m41t80", 0x68); + +diff --git a/include/hw/i2c/smbus_eeprom.h b/include/hw/i2c/smbus_eeprom.h +index 15e2151b50..68b0063ab6 100644 +--- a/include/hw/i2c/smbus_eeprom.h ++++ b/include/hw/i2c/smbus_eeprom.h +@@ -31,6 +31,6 @@ void smbus_eeprom_init(I2CBus *bus, int nb_eeprom, + const uint8_t *eeprom_spd, int size); + + enum sdram_type { SDR = 0x4, DDR = 0x7, DDR2 = 0x8 }; +-uint8_t *spd_data_generate(enum sdram_type type, ram_addr_t size, Error **errp); ++uint8_t *spd_data_generate(enum sdram_type type, ram_addr_t size); + + #endif +-- +2.23.0 + diff --git a/smbus-Fix-spd_data_generate-for-number-of-banks-2.patch b/smbus-Fix-spd_data_generate-for-number-of-banks-2.patch new file mode 100644 index 0000000000000000000000000000000000000000..c161071e8a39a9a078b589168dacdfaabc546750 --- /dev/null +++ b/smbus-Fix-spd_data_generate-for-number-of-banks-2.patch @@ -0,0 +1,66 @@ +From 32c82f0eaf9919cb0268d18d86a94bfd7ff5d1b2 Mon Sep 17 00:00:00 2001 +From: Markus Armbruster +Date: Wed, 22 Apr 2020 15:48:15 +0200 +Subject: [PATCH 031/709] smbus: Fix spd_data_generate() for number of banks > + 2 + +spd_data_generate() splits @ram_size bytes into @nbanks RAM banks of +1 << sz_log2 MiB each, like this: + + size = ram_size >> 20; /* work in terms of megabytes */ + [...] + nbanks = 1; + while (sz_log2 > max_log2 && nbanks < 8) { + sz_log2--; + nbanks++; + } + +Each iteration halves the size of a bank, and increments the number of +banks. Wrong: it should double the number of banks. + +The bug goes back all the way to commit b296b664ab "smbus: Add a +helper to generate SPD EEPROM data". + +It can't bite because spd_data_generate()'s current users pass only +@ram_size that result in *zero* iterations: + + machine RAM size #banks type bank size + fulong2e 256 MiB 1 DDR 256 MiB + sam460ex 2048 MiB 1 DDR2 2048 MiB + 1024 MiB 1 DDR2 1024 MiB + 512 MiB 1 DDR2 512 MiB + 256 MiB 1 DDR2 256 MiB + 128 MiB 1 SDR 128 MiB + 64 MiB 1 SDR 64 MiB + 32 MiB 1 SDR 32 MiB + +Apply the obvious, minimal fix. I admit I'm tempted to rip out the +unused (and obviously untested) feature instead, because YAGNI. + +Note that this is not the final result, as spd_data_generate() next +increases #banks from 1 to 2 if possible. This is done "to avoid a +bug in MIPS Malta firmware". We don't even use this function with +machine type malta. *Shrug* + +Signed-off-by: Markus Armbruster +Message-Id: <20200422134815.1584-5-armbru@redhat.com> +--- + hw/i2c/smbus_eeprom.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/hw/i2c/smbus_eeprom.c b/hw/i2c/smbus_eeprom.c +index 07fbbf87f1..e199fc8678 100644 +--- a/hw/i2c/smbus_eeprom.c ++++ b/hw/i2c/smbus_eeprom.c +@@ -229,7 +229,7 @@ uint8_t *spd_data_generate(enum sdram_type type, ram_addr_t ram_size) + nbanks = 1; + while (sz_log2 > max_log2 && nbanks < 8) { + sz_log2--; +- nbanks++; ++ nbanks *= 2; + } + + assert(size == (1ULL << sz_log2) * nbanks); +-- +2.23.0 + diff --git a/softfloat-Change-tininess_before_rounding-to-bool.patch b/softfloat-Change-tininess_before_rounding-to-bool.patch new file mode 100644 index 0000000000000000000000000000000000000000..fb813faf5e143f034b66ba64894ff3eda18ec954 --- /dev/null +++ b/softfloat-Change-tininess_before_rounding-to-bool.patch @@ -0,0 +1,193 @@ +From a828b373bdabc7e53d1e218e3fc76f85b6674688 Mon Sep 17 00:00:00 2001 +From: Richard Henderson +Date: Mon, 4 May 2020 21:19:39 -0700 +Subject: [PATCH 594/709] softfloat: Change tininess_before_rounding to bool +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Slightly tidies the usage within softfloat.c and the +representation in float_status. + +Reviewed-by: Alex Bennée +Signed-off-by: Richard Henderson +--- + fpu/softfloat.c | 54 ++++++++++++--------------------- + include/fpu/softfloat-helpers.h | 8 ++--- + include/fpu/softfloat-types.h | 8 ++--- + tests/fp/fp-test.c | 2 +- + 4 files changed, 28 insertions(+), 44 deletions(-) + +diff --git a/fpu/softfloat.c b/fpu/softfloat.c +index b741cf5bc3..65d457a548 100644 +--- a/fpu/softfloat.c ++++ b/fpu/softfloat.c +@@ -744,8 +744,7 @@ static FloatParts round_canonical(FloatParts p, float_status *s, + p.cls = float_class_zero; + goto do_zero; + } else { +- bool is_tiny = (s->float_detect_tininess +- == float_tininess_before_rounding) ++ bool is_tiny = s->tininess_before_rounding + || (exp < 0) + || !((frac + inc) & DECOMPOSED_OVERFLOW_BIT); + +@@ -3579,11 +3578,9 @@ static float32 roundAndPackFloat32(bool zSign, int zExp, uint32_t zSig, + float_raise(float_flag_output_denormal, status); + return packFloat32(zSign, 0, 0); + } +- isTiny = +- (status->float_detect_tininess +- == float_tininess_before_rounding) +- || ( zExp < -1 ) +- || ( zSig + roundIncrement < 0x80000000 ); ++ isTiny = status->tininess_before_rounding ++ || (zExp < -1) ++ || (zSig + roundIncrement < 0x80000000); + shift32RightJamming( zSig, - zExp, &zSig ); + zExp = 0; + roundBits = zSig & 0x7F; +@@ -3735,11 +3732,9 @@ static float64 roundAndPackFloat64(bool zSign, int zExp, uint64_t zSig, + float_raise(float_flag_output_denormal, status); + return packFloat64(zSign, 0, 0); + } +- isTiny = +- (status->float_detect_tininess +- == float_tininess_before_rounding) +- || ( zExp < -1 ) +- || ( zSig + roundIncrement < UINT64_C(0x8000000000000000) ); ++ isTiny = status->tininess_before_rounding ++ || (zExp < -1) ++ || (zSig + roundIncrement < UINT64_C(0x8000000000000000)); + shift64RightJamming( zSig, - zExp, &zSig ); + zExp = 0; + roundBits = zSig & 0x3FF; +@@ -3878,11 +3873,9 @@ floatx80 roundAndPackFloatx80(int8_t roundingPrecision, bool zSign, + float_raise(float_flag_output_denormal, status); + return packFloatx80(zSign, 0, 0); + } +- isTiny = +- (status->float_detect_tininess +- == float_tininess_before_rounding) +- || ( zExp < 0 ) +- || ( zSig0 <= zSig0 + roundIncrement ); ++ isTiny = status->tininess_before_rounding ++ || (zExp < 0 ) ++ || (zSig0 <= zSig0 + roundIncrement); + shift64RightJamming( zSig0, 1 - zExp, &zSig0 ); + zExp = 0; + roundBits = zSig0 & roundMask; +@@ -3956,12 +3949,10 @@ floatx80 roundAndPackFloatx80(int8_t roundingPrecision, bool zSign, + floatx80_infinity_low); + } + if ( zExp <= 0 ) { +- isTiny = +- (status->float_detect_tininess +- == float_tininess_before_rounding) +- || ( zExp < 0 ) +- || ! increment +- || ( zSig0 < UINT64_C(0xFFFFFFFFFFFFFFFF) ); ++ isTiny = status->tininess_before_rounding ++ || (zExp < 0) ++ || !increment ++ || (zSig0 < UINT64_C(0xFFFFFFFFFFFFFFFF)); + shift64ExtraRightJamming( zSig0, zSig1, 1 - zExp, &zSig0, &zSig1 ); + zExp = 0; + if (isTiny && zSig1) { +@@ -4237,17 +4228,12 @@ static float128 roundAndPackFloat128(bool zSign, int32_t zExp, + float_raise(float_flag_output_denormal, status); + return packFloat128(zSign, 0, 0, 0); + } +- isTiny = +- (status->float_detect_tininess +- == float_tininess_before_rounding) +- || ( zExp < -1 ) +- || ! increment +- || lt128( +- zSig0, +- zSig1, +- UINT64_C(0x0001FFFFFFFFFFFF), +- UINT64_C(0xFFFFFFFFFFFFFFFF) +- ); ++ isTiny = status->tininess_before_rounding ++ || (zExp < -1) ++ || !increment ++ || lt128(zSig0, zSig1, ++ UINT64_C(0x0001FFFFFFFFFFFF), ++ UINT64_C(0xFFFFFFFFFFFFFFFF)); + shift128ExtraRightJamming( + zSig0, zSig1, zSig2, - zExp, &zSig0, &zSig1, &zSig2 ); + zExp = 0; +diff --git a/include/fpu/softfloat-helpers.h b/include/fpu/softfloat-helpers.h +index 528d7ebd9f..40d32a6d5d 100644 +--- a/include/fpu/softfloat-helpers.h ++++ b/include/fpu/softfloat-helpers.h +@@ -53,9 +53,9 @@ this code that are retained. + + #include "fpu/softfloat-types.h" + +-static inline void set_float_detect_tininess(int val, float_status *status) ++static inline void set_float_detect_tininess(bool val, float_status *status) + { +- status->float_detect_tininess = val; ++ status->tininess_before_rounding = val; + } + + static inline void set_float_rounding_mode(int val, float_status *status) +@@ -94,9 +94,9 @@ static inline void set_snan_bit_is_one(bool val, float_status *status) + status->snan_bit_is_one = val; + } + +-static inline int get_float_detect_tininess(float_status *status) ++static inline bool get_float_detect_tininess(float_status *status) + { +- return status->float_detect_tininess; ++ return status->tininess_before_rounding; + } + + static inline int get_float_rounding_mode(float_status *status) +diff --git a/include/fpu/softfloat-types.h b/include/fpu/softfloat-types.h +index 619b875df6..874ddd9f93 100644 +--- a/include/fpu/softfloat-types.h ++++ b/include/fpu/softfloat-types.h +@@ -116,10 +116,8 @@ typedef struct { + * Software IEC/IEEE floating-point underflow tininess-detection mode. + */ + +-enum { +- float_tininess_after_rounding = 0, +- float_tininess_before_rounding = 1 +-}; ++#define float_tininess_after_rounding false ++#define float_tininess_before_rounding true + + /* + *Software IEC/IEEE floating-point rounding mode. +@@ -158,10 +156,10 @@ enum { + */ + + typedef struct float_status { +- signed char float_detect_tininess; + signed char float_rounding_mode; + uint8_t float_exception_flags; + signed char floatx80_rounding_precision; ++ bool tininess_before_rounding; + /* should denormalised results go to zero and set the inexact flag? */ + bool flush_to_zero; + /* should denormalised inputs go to zero and set the input_denormal flag? */ +diff --git a/tests/fp/fp-test.c b/tests/fp/fp-test.c +index 7d0faf2b47..43ef9628c4 100644 +--- a/tests/fp/fp-test.c ++++ b/tests/fp/fp-test.c +@@ -989,7 +989,7 @@ static void QEMU_NORETURN run_test(void) + + verCases_tininessCode = 0; + slowfloat_detectTininess = tmode; +- qsf.float_detect_tininess = sf_tininess_to_qemu(tmode); ++ qsf.tininess_before_rounding = sf_tininess_to_qemu(tmode); + + if (attrs & FUNC_EFF_TININESSMODE || + ((attrs & FUNC_EFF_TININESSMODE_REDUCEDPREC) && +-- +2.23.0 + diff --git a/softfloat-Inline-float128-compare-specializations.patch b/softfloat-Inline-float128-compare-specializations.patch new file mode 100644 index 0000000000000000000000000000000000000000..df0f9e1ebb46cd210f80b21939f94b61b2e834c5 --- /dev/null +++ b/softfloat-Inline-float128-compare-specializations.patch @@ -0,0 +1,338 @@ +From b7b1ac684fea49c6bfe1ad8b706aed7b09116d15 Mon Sep 17 00:00:00 2001 +From: Richard Henderson +Date: Tue, 5 May 2020 10:50:32 -0700 +Subject: [PATCH 599/709] softfloat: Inline float128 compare specializations +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Replace the float128 compare specializations with inline functions +that call the standard float128_compare{,_quiet} functions. +Use bool as the return type. + +Reviewed-by: Alex Bennée +Signed-off-by: Richard Henderson +--- + fpu/softfloat.c | 238 ---------------------------------------- + include/fpu/softfloat.h | 49 +++++++-- + 2 files changed, 41 insertions(+), 246 deletions(-) + +diff --git a/fpu/softfloat.c b/fpu/softfloat.c +index 5d7fc2c17a..4567dda112 100644 +--- a/fpu/softfloat.c ++++ b/fpu/softfloat.c +@@ -7218,244 +7218,6 @@ float128 float128_sqrt(float128 a, float_status *status) + + } + +-/*---------------------------------------------------------------------------- +-| Returns 1 if the quadruple-precision floating-point value `a' is equal to +-| the corresponding value `b', and 0 otherwise. The invalid exception is +-| raised if either operand is a NaN. Otherwise, the comparison is performed +-| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. +-*----------------------------------------------------------------------------*/ +- +-int float128_eq(float128 a, float128 b, float_status *status) +-{ +- +- if ( ( ( extractFloat128Exp( a ) == 0x7FFF ) +- && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) ) +- || ( ( extractFloat128Exp( b ) == 0x7FFF ) +- && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) ) +- ) { +- float_raise(float_flag_invalid, status); +- return 0; +- } +- return +- ( a.low == b.low ) +- && ( ( a.high == b.high ) +- || ( ( a.low == 0 ) +- && ( (uint64_t) ( ( a.high | b.high )<<1 ) == 0 ) ) +- ); +- +-} +- +-/*---------------------------------------------------------------------------- +-| Returns 1 if the quadruple-precision floating-point value `a' is less than +-| or equal to the corresponding value `b', and 0 otherwise. The invalid +-| exception is raised if either operand is a NaN. The comparison is performed +-| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. +-*----------------------------------------------------------------------------*/ +- +-int float128_le(float128 a, float128 b, float_status *status) +-{ +- bool aSign, bSign; +- +- if ( ( ( extractFloat128Exp( a ) == 0x7FFF ) +- && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) ) +- || ( ( extractFloat128Exp( b ) == 0x7FFF ) +- && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) ) +- ) { +- float_raise(float_flag_invalid, status); +- return 0; +- } +- aSign = extractFloat128Sign( a ); +- bSign = extractFloat128Sign( b ); +- if ( aSign != bSign ) { +- return +- aSign +- || ( ( ( (uint64_t) ( ( a.high | b.high )<<1 ) ) | a.low | b.low ) +- == 0 ); +- } +- return +- aSign ? le128( b.high, b.low, a.high, a.low ) +- : le128( a.high, a.low, b.high, b.low ); +- +-} +- +-/*---------------------------------------------------------------------------- +-| Returns 1 if the quadruple-precision floating-point value `a' is less than +-| the corresponding value `b', and 0 otherwise. The invalid exception is +-| raised if either operand is a NaN. The comparison is performed according +-| to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. +-*----------------------------------------------------------------------------*/ +- +-int float128_lt(float128 a, float128 b, float_status *status) +-{ +- bool aSign, bSign; +- +- if ( ( ( extractFloat128Exp( a ) == 0x7FFF ) +- && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) ) +- || ( ( extractFloat128Exp( b ) == 0x7FFF ) +- && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) ) +- ) { +- float_raise(float_flag_invalid, status); +- return 0; +- } +- aSign = extractFloat128Sign( a ); +- bSign = extractFloat128Sign( b ); +- if ( aSign != bSign ) { +- return +- aSign +- && ( ( ( (uint64_t) ( ( a.high | b.high )<<1 ) ) | a.low | b.low ) +- != 0 ); +- } +- return +- aSign ? lt128( b.high, b.low, a.high, a.low ) +- : lt128( a.high, a.low, b.high, b.low ); +- +-} +- +-/*---------------------------------------------------------------------------- +-| Returns 1 if the quadruple-precision floating-point values `a' and `b' cannot +-| be compared, and 0 otherwise. The invalid exception is raised if either +-| operand is a NaN. The comparison is performed according to the IEC/IEEE +-| Standard for Binary Floating-Point Arithmetic. +-*----------------------------------------------------------------------------*/ +- +-int float128_unordered(float128 a, float128 b, float_status *status) +-{ +- if ( ( ( extractFloat128Exp( a ) == 0x7FFF ) +- && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) ) +- || ( ( extractFloat128Exp( b ) == 0x7FFF ) +- && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) ) +- ) { +- float_raise(float_flag_invalid, status); +- return 1; +- } +- return 0; +-} +- +-/*---------------------------------------------------------------------------- +-| Returns 1 if the quadruple-precision floating-point value `a' is equal to +-| the corresponding value `b', and 0 otherwise. Quiet NaNs do not cause an +-| exception. The comparison is performed according to the IEC/IEEE Standard +-| for Binary Floating-Point Arithmetic. +-*----------------------------------------------------------------------------*/ +- +-int float128_eq_quiet(float128 a, float128 b, float_status *status) +-{ +- +- if ( ( ( extractFloat128Exp( a ) == 0x7FFF ) +- && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) ) +- || ( ( extractFloat128Exp( b ) == 0x7FFF ) +- && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) ) +- ) { +- if (float128_is_signaling_nan(a, status) +- || float128_is_signaling_nan(b, status)) { +- float_raise(float_flag_invalid, status); +- } +- return 0; +- } +- return +- ( a.low == b.low ) +- && ( ( a.high == b.high ) +- || ( ( a.low == 0 ) +- && ( (uint64_t) ( ( a.high | b.high )<<1 ) == 0 ) ) +- ); +- +-} +- +-/*---------------------------------------------------------------------------- +-| Returns 1 if the quadruple-precision floating-point value `a' is less than +-| or equal to the corresponding value `b', and 0 otherwise. Quiet NaNs do not +-| cause an exception. Otherwise, the comparison is performed according to the +-| IEC/IEEE Standard for Binary Floating-Point Arithmetic. +-*----------------------------------------------------------------------------*/ +- +-int float128_le_quiet(float128 a, float128 b, float_status *status) +-{ +- bool aSign, bSign; +- +- if ( ( ( extractFloat128Exp( a ) == 0x7FFF ) +- && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) ) +- || ( ( extractFloat128Exp( b ) == 0x7FFF ) +- && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) ) +- ) { +- if (float128_is_signaling_nan(a, status) +- || float128_is_signaling_nan(b, status)) { +- float_raise(float_flag_invalid, status); +- } +- return 0; +- } +- aSign = extractFloat128Sign( a ); +- bSign = extractFloat128Sign( b ); +- if ( aSign != bSign ) { +- return +- aSign +- || ( ( ( (uint64_t) ( ( a.high | b.high )<<1 ) ) | a.low | b.low ) +- == 0 ); +- } +- return +- aSign ? le128( b.high, b.low, a.high, a.low ) +- : le128( a.high, a.low, b.high, b.low ); +- +-} +- +-/*---------------------------------------------------------------------------- +-| Returns 1 if the quadruple-precision floating-point value `a' is less than +-| the corresponding value `b', and 0 otherwise. Quiet NaNs do not cause an +-| exception. Otherwise, the comparison is performed according to the IEC/IEEE +-| Standard for Binary Floating-Point Arithmetic. +-*----------------------------------------------------------------------------*/ +- +-int float128_lt_quiet(float128 a, float128 b, float_status *status) +-{ +- bool aSign, bSign; +- +- if ( ( ( extractFloat128Exp( a ) == 0x7FFF ) +- && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) ) +- || ( ( extractFloat128Exp( b ) == 0x7FFF ) +- && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) ) +- ) { +- if (float128_is_signaling_nan(a, status) +- || float128_is_signaling_nan(b, status)) { +- float_raise(float_flag_invalid, status); +- } +- return 0; +- } +- aSign = extractFloat128Sign( a ); +- bSign = extractFloat128Sign( b ); +- if ( aSign != bSign ) { +- return +- aSign +- && ( ( ( (uint64_t) ( ( a.high | b.high )<<1 ) ) | a.low | b.low ) +- != 0 ); +- } +- return +- aSign ? lt128( b.high, b.low, a.high, a.low ) +- : lt128( a.high, a.low, b.high, b.low ); +- +-} +- +-/*---------------------------------------------------------------------------- +-| Returns 1 if the quadruple-precision floating-point values `a' and `b' cannot +-| be compared, and 0 otherwise. Quiet NaNs do not cause an exception. The +-| comparison is performed according to the IEC/IEEE Standard for Binary +-| Floating-Point Arithmetic. +-*----------------------------------------------------------------------------*/ +- +-int float128_unordered_quiet(float128 a, float128 b, float_status *status) +-{ +- if ( ( ( extractFloat128Exp( a ) == 0x7FFF ) +- && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) ) +- || ( ( extractFloat128Exp( b ) == 0x7FFF ) +- && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) ) +- ) { +- if (float128_is_signaling_nan(a, status) +- || float128_is_signaling_nan(b, status)) { +- float_raise(float_flag_invalid, status); +- } +- return 1; +- } +- return 0; +-} +- + static inline FloatRelation + floatx80_compare_internal(floatx80 a, floatx80 b, bool is_quiet, + float_status *status) +diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h +index 281f0fd971..cfb3cda46b 100644 +--- a/include/fpu/softfloat.h ++++ b/include/fpu/softfloat.h +@@ -901,14 +901,6 @@ float128 float128_mul(float128, float128, float_status *status); + float128 float128_div(float128, float128, float_status *status); + float128 float128_rem(float128, float128, float_status *status); + float128 float128_sqrt(float128, float_status *status); +-int float128_eq(float128, float128, float_status *status); +-int float128_le(float128, float128, float_status *status); +-int float128_lt(float128, float128, float_status *status); +-int float128_unordered(float128, float128, float_status *status); +-int float128_eq_quiet(float128, float128, float_status *status); +-int float128_le_quiet(float128, float128, float_status *status); +-int float128_lt_quiet(float128, float128, float_status *status); +-int float128_unordered_quiet(float128, float128, float_status *status); + FloatRelation float128_compare(float128, float128, float_status *status); + FloatRelation float128_compare_quiet(float128, float128, float_status *status); + int float128_is_quiet_nan(float128, float_status *status); +@@ -964,6 +956,47 @@ static inline int float128_is_any_nan(float128 a) + ((a.low != 0) || ((a.high & 0xffffffffffffLL) != 0)); + } + ++static inline bool float128_eq(float128 a, float128 b, float_status *s) ++{ ++ return float128_compare(a, b, s) == float_relation_equal; ++} ++ ++static inline bool float128_le(float128 a, float128 b, float_status *s) ++{ ++ return float128_compare(a, b, s) <= float_relation_equal; ++} ++ ++static inline bool float128_lt(float128 a, float128 b, float_status *s) ++{ ++ return float128_compare(a, b, s) < float_relation_equal; ++} ++ ++static inline bool float128_unordered(float128 a, float128 b, float_status *s) ++{ ++ return float128_compare(a, b, s) == float_relation_unordered; ++} ++ ++static inline bool float128_eq_quiet(float128 a, float128 b, float_status *s) ++{ ++ return float128_compare_quiet(a, b, s) == float_relation_equal; ++} ++ ++static inline bool float128_le_quiet(float128 a, float128 b, float_status *s) ++{ ++ return float128_compare_quiet(a, b, s) <= float_relation_equal; ++} ++ ++static inline bool float128_lt_quiet(float128 a, float128 b, float_status *s) ++{ ++ return float128_compare_quiet(a, b, s) < float_relation_equal; ++} ++ ++static inline bool float128_unordered_quiet(float128 a, float128 b, ++ float_status *s) ++{ ++ return float128_compare_quiet(a, b, s) == float_relation_unordered; ++} ++ + #define float128_zero make_float128(0, 0) + + /*---------------------------------------------------------------------------- +-- +2.23.0 + diff --git a/softfloat-Inline-float32-compare-specializations.patch b/softfloat-Inline-float32-compare-specializations.patch new file mode 100644 index 0000000000000000000000000000000000000000..a29f511ae44bf6323f65cea2ddf950b224544894 --- /dev/null +++ b/softfloat-Inline-float32-compare-specializations.patch @@ -0,0 +1,316 @@ +From 5da2d2d8e53d80e92a61720ea995c86b33cbf25d Mon Sep 17 00:00:00 2001 +From: Richard Henderson +Date: Tue, 5 May 2020 10:33:18 -0700 +Subject: [PATCH 597/709] softfloat: Inline float32 compare specializations +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Replace the float32 compare specializations with inline functions +that call the standard float32_compare{,_quiet} functions. +Use bool as the return type. + +Reviewed-by: Alex Bennée +Signed-off-by: Richard Henderson +--- + fpu/softfloat.c | 216 ---------------------------------------- + include/fpu/softfloat.h | 49 +++++++-- + 2 files changed, 41 insertions(+), 224 deletions(-) + +diff --git a/fpu/softfloat.c b/fpu/softfloat.c +index 60b9ae5f05..f6bfc40c97 100644 +--- a/fpu/softfloat.c ++++ b/fpu/softfloat.c +@@ -4733,222 +4733,6 @@ float32 float32_log2(float32 a, float_status *status) + return normalizeRoundAndPackFloat32(zSign, 0x85, zSig, status); + } + +-/*---------------------------------------------------------------------------- +-| Returns 1 if the single-precision floating-point value `a' is equal to +-| the corresponding value `b', and 0 otherwise. The invalid exception is +-| raised if either operand is a NaN. Otherwise, the comparison is performed +-| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. +-*----------------------------------------------------------------------------*/ +- +-int float32_eq(float32 a, float32 b, float_status *status) +-{ +- uint32_t av, bv; +- a = float32_squash_input_denormal(a, status); +- b = float32_squash_input_denormal(b, status); +- +- if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) ) +- || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) ) +- ) { +- float_raise(float_flag_invalid, status); +- return 0; +- } +- av = float32_val(a); +- bv = float32_val(b); +- return ( av == bv ) || ( (uint32_t) ( ( av | bv )<<1 ) == 0 ); +-} +- +-/*---------------------------------------------------------------------------- +-| Returns 1 if the single-precision floating-point value `a' is less than +-| or equal to the corresponding value `b', and 0 otherwise. The invalid +-| exception is raised if either operand is a NaN. The comparison is performed +-| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. +-*----------------------------------------------------------------------------*/ +- +-int float32_le(float32 a, float32 b, float_status *status) +-{ +- bool aSign, bSign; +- uint32_t av, bv; +- a = float32_squash_input_denormal(a, status); +- b = float32_squash_input_denormal(b, status); +- +- if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) ) +- || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) ) +- ) { +- float_raise(float_flag_invalid, status); +- return 0; +- } +- aSign = extractFloat32Sign( a ); +- bSign = extractFloat32Sign( b ); +- av = float32_val(a); +- bv = float32_val(b); +- if ( aSign != bSign ) return aSign || ( (uint32_t) ( ( av | bv )<<1 ) == 0 ); +- return ( av == bv ) || ( aSign ^ ( av < bv ) ); +- +-} +- +-/*---------------------------------------------------------------------------- +-| Returns 1 if the single-precision floating-point value `a' is less than +-| the corresponding value `b', and 0 otherwise. The invalid exception is +-| raised if either operand is a NaN. The comparison is performed according +-| to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. +-*----------------------------------------------------------------------------*/ +- +-int float32_lt(float32 a, float32 b, float_status *status) +-{ +- bool aSign, bSign; +- uint32_t av, bv; +- a = float32_squash_input_denormal(a, status); +- b = float32_squash_input_denormal(b, status); +- +- if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) ) +- || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) ) +- ) { +- float_raise(float_flag_invalid, status); +- return 0; +- } +- aSign = extractFloat32Sign( a ); +- bSign = extractFloat32Sign( b ); +- av = float32_val(a); +- bv = float32_val(b); +- if ( aSign != bSign ) return aSign && ( (uint32_t) ( ( av | bv )<<1 ) != 0 ); +- return ( av != bv ) && ( aSign ^ ( av < bv ) ); +- +-} +- +-/*---------------------------------------------------------------------------- +-| Returns 1 if the single-precision floating-point values `a' and `b' cannot +-| be compared, and 0 otherwise. The invalid exception is raised if either +-| operand is a NaN. The comparison is performed according to the IEC/IEEE +-| Standard for Binary Floating-Point Arithmetic. +-*----------------------------------------------------------------------------*/ +- +-int float32_unordered(float32 a, float32 b, float_status *status) +-{ +- a = float32_squash_input_denormal(a, status); +- b = float32_squash_input_denormal(b, status); +- +- if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) ) +- || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) ) +- ) { +- float_raise(float_flag_invalid, status); +- return 1; +- } +- return 0; +-} +- +-/*---------------------------------------------------------------------------- +-| Returns 1 if the single-precision floating-point value `a' is equal to +-| the corresponding value `b', and 0 otherwise. Quiet NaNs do not cause an +-| exception. The comparison is performed according to the IEC/IEEE Standard +-| for Binary Floating-Point Arithmetic. +-*----------------------------------------------------------------------------*/ +- +-int float32_eq_quiet(float32 a, float32 b, float_status *status) +-{ +- a = float32_squash_input_denormal(a, status); +- b = float32_squash_input_denormal(b, status); +- +- if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) ) +- || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) ) +- ) { +- if (float32_is_signaling_nan(a, status) +- || float32_is_signaling_nan(b, status)) { +- float_raise(float_flag_invalid, status); +- } +- return 0; +- } +- return ( float32_val(a) == float32_val(b) ) || +- ( (uint32_t) ( ( float32_val(a) | float32_val(b) )<<1 ) == 0 ); +-} +- +-/*---------------------------------------------------------------------------- +-| Returns 1 if the single-precision floating-point value `a' is less than or +-| equal to the corresponding value `b', and 0 otherwise. Quiet NaNs do not +-| cause an exception. Otherwise, the comparison is performed according to the +-| IEC/IEEE Standard for Binary Floating-Point Arithmetic. +-*----------------------------------------------------------------------------*/ +- +-int float32_le_quiet(float32 a, float32 b, float_status *status) +-{ +- bool aSign, bSign; +- uint32_t av, bv; +- a = float32_squash_input_denormal(a, status); +- b = float32_squash_input_denormal(b, status); +- +- if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) ) +- || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) ) +- ) { +- if (float32_is_signaling_nan(a, status) +- || float32_is_signaling_nan(b, status)) { +- float_raise(float_flag_invalid, status); +- } +- return 0; +- } +- aSign = extractFloat32Sign( a ); +- bSign = extractFloat32Sign( b ); +- av = float32_val(a); +- bv = float32_val(b); +- if ( aSign != bSign ) return aSign || ( (uint32_t) ( ( av | bv )<<1 ) == 0 ); +- return ( av == bv ) || ( aSign ^ ( av < bv ) ); +- +-} +- +-/*---------------------------------------------------------------------------- +-| Returns 1 if the single-precision floating-point value `a' is less than +-| the corresponding value `b', and 0 otherwise. Quiet NaNs do not cause an +-| exception. Otherwise, the comparison is performed according to the IEC/IEEE +-| Standard for Binary Floating-Point Arithmetic. +-*----------------------------------------------------------------------------*/ +- +-int float32_lt_quiet(float32 a, float32 b, float_status *status) +-{ +- bool aSign, bSign; +- uint32_t av, bv; +- a = float32_squash_input_denormal(a, status); +- b = float32_squash_input_denormal(b, status); +- +- if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) ) +- || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) ) +- ) { +- if (float32_is_signaling_nan(a, status) +- || float32_is_signaling_nan(b, status)) { +- float_raise(float_flag_invalid, status); +- } +- return 0; +- } +- aSign = extractFloat32Sign( a ); +- bSign = extractFloat32Sign( b ); +- av = float32_val(a); +- bv = float32_val(b); +- if ( aSign != bSign ) return aSign && ( (uint32_t) ( ( av | bv )<<1 ) != 0 ); +- return ( av != bv ) && ( aSign ^ ( av < bv ) ); +- +-} +- +-/*---------------------------------------------------------------------------- +-| Returns 1 if the single-precision floating-point values `a' and `b' cannot +-| be compared, and 0 otherwise. Quiet NaNs do not cause an exception. The +-| comparison is performed according to the IEC/IEEE Standard for Binary +-| Floating-Point Arithmetic. +-*----------------------------------------------------------------------------*/ +- +-int float32_unordered_quiet(float32 a, float32 b, float_status *status) +-{ +- a = float32_squash_input_denormal(a, status); +- b = float32_squash_input_denormal(b, status); +- +- if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) ) +- || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) ) +- ) { +- if (float32_is_signaling_nan(a, status) +- || float32_is_signaling_nan(b, status)) { +- float_raise(float_flag_invalid, status); +- } +- return 1; +- } +- return 0; +-} +- + /*---------------------------------------------------------------------------- + | Returns the result of converting the double-precision floating-point value + | `a' to the extended double-precision floating-point format. The conversion +diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h +index 7f84235122..4d1af6ab45 100644 +--- a/include/fpu/softfloat.h ++++ b/include/fpu/softfloat.h +@@ -343,14 +343,6 @@ float32 float32_muladd(float32, float32, float32, int, float_status *status); + float32 float32_sqrt(float32, float_status *status); + float32 float32_exp2(float32, float_status *status); + float32 float32_log2(float32, float_status *status); +-int float32_eq(float32, float32, float_status *status); +-int float32_le(float32, float32, float_status *status); +-int float32_lt(float32, float32, float_status *status); +-int float32_unordered(float32, float32, float_status *status); +-int float32_eq_quiet(float32, float32, float_status *status); +-int float32_le_quiet(float32, float32, float_status *status); +-int float32_lt_quiet(float32, float32, float_status *status); +-int float32_unordered_quiet(float32, float32, float_status *status); + FloatRelation float32_compare(float32, float32, float_status *status); + FloatRelation float32_compare_quiet(float32, float32, float_status *status); + float32 float32_min(float32, float32, float_status *status); +@@ -425,6 +417,47 @@ static inline float32 float32_set_sign(float32 a, int sign) + return make_float32((float32_val(a) & 0x7fffffff) | (sign << 31)); + } + ++static inline bool float32_eq(float32 a, float32 b, float_status *s) ++{ ++ return float32_compare(a, b, s) == float_relation_equal; ++} ++ ++static inline bool float32_le(float32 a, float32 b, float_status *s) ++{ ++ return float32_compare(a, b, s) <= float_relation_equal; ++} ++ ++static inline bool float32_lt(float32 a, float32 b, float_status *s) ++{ ++ return float32_compare(a, b, s) < float_relation_equal; ++} ++ ++static inline bool float32_unordered(float32 a, float32 b, float_status *s) ++{ ++ return float32_compare(a, b, s) == float_relation_unordered; ++} ++ ++static inline bool float32_eq_quiet(float32 a, float32 b, float_status *s) ++{ ++ return float32_compare_quiet(a, b, s) == float_relation_equal; ++} ++ ++static inline bool float32_le_quiet(float32 a, float32 b, float_status *s) ++{ ++ return float32_compare_quiet(a, b, s) <= float_relation_equal; ++} ++ ++static inline bool float32_lt_quiet(float32 a, float32 b, float_status *s) ++{ ++ return float32_compare_quiet(a, b, s) < float_relation_equal; ++} ++ ++static inline bool float32_unordered_quiet(float32 a, float32 b, ++ float_status *s) ++{ ++ return float32_compare_quiet(a, b, s) == float_relation_unordered; ++} ++ + #define float32_zero make_float32(0) + #define float32_half make_float32(0x3f000000) + #define float32_one make_float32(0x3f800000) +-- +2.23.0 + diff --git a/softfloat-Inline-float64-compare-specializations.patch b/softfloat-Inline-float64-compare-specializations.patch new file mode 100644 index 0000000000000000000000000000000000000000..fdbfa499b53615c15be4a1d0ef09430851b7a2e3 --- /dev/null +++ b/softfloat-Inline-float64-compare-specializations.patch @@ -0,0 +1,334 @@ +From 0673ecdf6cb2b1445a85283db8cbacb251c46516 Mon Sep 17 00:00:00 2001 +From: Richard Henderson +Date: Tue, 5 May 2020 10:40:23 -0700 +Subject: [PATCH 598/709] softfloat: Inline float64 compare specializations +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Replace the float64 compare specializations with inline functions +that call the standard float64_compare{,_quiet} functions. +Use bool as the return type. + +Reviewed-by: Alex Bennée +Signed-off-by: Richard Henderson +--- + fpu/softfloat.c | 220 ---------------------------------- + include/fpu/softfloat.h | 49 ++++++-- + target/s390x/vec_fpu_helper.c | 2 +- + 3 files changed, 42 insertions(+), 229 deletions(-) + +diff --git a/fpu/softfloat.c b/fpu/softfloat.c +index f6bfc40c97..5d7fc2c17a 100644 +--- a/fpu/softfloat.c ++++ b/fpu/softfloat.c +@@ -4941,226 +4941,6 @@ float64 float64_log2(float64 a, float_status *status) + return normalizeRoundAndPackFloat64(zSign, 0x408, zSig, status); + } + +-/*---------------------------------------------------------------------------- +-| Returns 1 if the double-precision floating-point value `a' is equal to the +-| corresponding value `b', and 0 otherwise. The invalid exception is raised +-| if either operand is a NaN. Otherwise, the comparison is performed +-| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. +-*----------------------------------------------------------------------------*/ +- +-int float64_eq(float64 a, float64 b, float_status *status) +-{ +- uint64_t av, bv; +- a = float64_squash_input_denormal(a, status); +- b = float64_squash_input_denormal(b, status); +- +- if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) ) +- || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) ) +- ) { +- float_raise(float_flag_invalid, status); +- return 0; +- } +- av = float64_val(a); +- bv = float64_val(b); +- return ( av == bv ) || ( (uint64_t) ( ( av | bv )<<1 ) == 0 ); +- +-} +- +-/*---------------------------------------------------------------------------- +-| Returns 1 if the double-precision floating-point value `a' is less than or +-| equal to the corresponding value `b', and 0 otherwise. The invalid +-| exception is raised if either operand is a NaN. The comparison is performed +-| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. +-*----------------------------------------------------------------------------*/ +- +-int float64_le(float64 a, float64 b, float_status *status) +-{ +- bool aSign, bSign; +- uint64_t av, bv; +- a = float64_squash_input_denormal(a, status); +- b = float64_squash_input_denormal(b, status); +- +- if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) ) +- || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) ) +- ) { +- float_raise(float_flag_invalid, status); +- return 0; +- } +- aSign = extractFloat64Sign( a ); +- bSign = extractFloat64Sign( b ); +- av = float64_val(a); +- bv = float64_val(b); +- if ( aSign != bSign ) return aSign || ( (uint64_t) ( ( av | bv )<<1 ) == 0 ); +- return ( av == bv ) || ( aSign ^ ( av < bv ) ); +- +-} +- +-/*---------------------------------------------------------------------------- +-| Returns 1 if the double-precision floating-point value `a' is less than +-| the corresponding value `b', and 0 otherwise. The invalid exception is +-| raised if either operand is a NaN. The comparison is performed according +-| to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. +-*----------------------------------------------------------------------------*/ +- +-int float64_lt(float64 a, float64 b, float_status *status) +-{ +- bool aSign, bSign; +- uint64_t av, bv; +- +- a = float64_squash_input_denormal(a, status); +- b = float64_squash_input_denormal(b, status); +- if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) ) +- || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) ) +- ) { +- float_raise(float_flag_invalid, status); +- return 0; +- } +- aSign = extractFloat64Sign( a ); +- bSign = extractFloat64Sign( b ); +- av = float64_val(a); +- bv = float64_val(b); +- if ( aSign != bSign ) return aSign && ( (uint64_t) ( ( av | bv )<<1 ) != 0 ); +- return ( av != bv ) && ( aSign ^ ( av < bv ) ); +- +-} +- +-/*---------------------------------------------------------------------------- +-| Returns 1 if the double-precision floating-point values `a' and `b' cannot +-| be compared, and 0 otherwise. The invalid exception is raised if either +-| operand is a NaN. The comparison is performed according to the IEC/IEEE +-| Standard for Binary Floating-Point Arithmetic. +-*----------------------------------------------------------------------------*/ +- +-int float64_unordered(float64 a, float64 b, float_status *status) +-{ +- a = float64_squash_input_denormal(a, status); +- b = float64_squash_input_denormal(b, status); +- +- if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) ) +- || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) ) +- ) { +- float_raise(float_flag_invalid, status); +- return 1; +- } +- return 0; +-} +- +-/*---------------------------------------------------------------------------- +-| Returns 1 if the double-precision floating-point value `a' is equal to the +-| corresponding value `b', and 0 otherwise. Quiet NaNs do not cause an +-| exception.The comparison is performed according to the IEC/IEEE Standard +-| for Binary Floating-Point Arithmetic. +-*----------------------------------------------------------------------------*/ +- +-int float64_eq_quiet(float64 a, float64 b, float_status *status) +-{ +- uint64_t av, bv; +- a = float64_squash_input_denormal(a, status); +- b = float64_squash_input_denormal(b, status); +- +- if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) ) +- || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) ) +- ) { +- if (float64_is_signaling_nan(a, status) +- || float64_is_signaling_nan(b, status)) { +- float_raise(float_flag_invalid, status); +- } +- return 0; +- } +- av = float64_val(a); +- bv = float64_val(b); +- return ( av == bv ) || ( (uint64_t) ( ( av | bv )<<1 ) == 0 ); +- +-} +- +-/*---------------------------------------------------------------------------- +-| Returns 1 if the double-precision floating-point value `a' is less than or +-| equal to the corresponding value `b', and 0 otherwise. Quiet NaNs do not +-| cause an exception. Otherwise, the comparison is performed according to the +-| IEC/IEEE Standard for Binary Floating-Point Arithmetic. +-*----------------------------------------------------------------------------*/ +- +-int float64_le_quiet(float64 a, float64 b, float_status *status) +-{ +- bool aSign, bSign; +- uint64_t av, bv; +- a = float64_squash_input_denormal(a, status); +- b = float64_squash_input_denormal(b, status); +- +- if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) ) +- || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) ) +- ) { +- if (float64_is_signaling_nan(a, status) +- || float64_is_signaling_nan(b, status)) { +- float_raise(float_flag_invalid, status); +- } +- return 0; +- } +- aSign = extractFloat64Sign( a ); +- bSign = extractFloat64Sign( b ); +- av = float64_val(a); +- bv = float64_val(b); +- if ( aSign != bSign ) return aSign || ( (uint64_t) ( ( av | bv )<<1 ) == 0 ); +- return ( av == bv ) || ( aSign ^ ( av < bv ) ); +- +-} +- +-/*---------------------------------------------------------------------------- +-| Returns 1 if the double-precision floating-point value `a' is less than +-| the corresponding value `b', and 0 otherwise. Quiet NaNs do not cause an +-| exception. Otherwise, the comparison is performed according to the IEC/IEEE +-| Standard for Binary Floating-Point Arithmetic. +-*----------------------------------------------------------------------------*/ +- +-int float64_lt_quiet(float64 a, float64 b, float_status *status) +-{ +- bool aSign, bSign; +- uint64_t av, bv; +- a = float64_squash_input_denormal(a, status); +- b = float64_squash_input_denormal(b, status); +- +- if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) ) +- || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) ) +- ) { +- if (float64_is_signaling_nan(a, status) +- || float64_is_signaling_nan(b, status)) { +- float_raise(float_flag_invalid, status); +- } +- return 0; +- } +- aSign = extractFloat64Sign( a ); +- bSign = extractFloat64Sign( b ); +- av = float64_val(a); +- bv = float64_val(b); +- if ( aSign != bSign ) return aSign && ( (uint64_t) ( ( av | bv )<<1 ) != 0 ); +- return ( av != bv ) && ( aSign ^ ( av < bv ) ); +- +-} +- +-/*---------------------------------------------------------------------------- +-| Returns 1 if the double-precision floating-point values `a' and `b' cannot +-| be compared, and 0 otherwise. Quiet NaNs do not cause an exception. The +-| comparison is performed according to the IEC/IEEE Standard for Binary +-| Floating-Point Arithmetic. +-*----------------------------------------------------------------------------*/ +- +-int float64_unordered_quiet(float64 a, float64 b, float_status *status) +-{ +- a = float64_squash_input_denormal(a, status); +- b = float64_squash_input_denormal(b, status); +- +- if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) ) +- || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) ) +- ) { +- if (float64_is_signaling_nan(a, status) +- || float64_is_signaling_nan(b, status)) { +- float_raise(float_flag_invalid, status); +- } +- return 1; +- } +- return 0; +-} +- + /*---------------------------------------------------------------------------- + | Returns the result of converting the extended double-precision floating- + | point value `a' to the 32-bit two's complement integer format. The +diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h +index 4d1af6ab45..281f0fd971 100644 +--- a/include/fpu/softfloat.h ++++ b/include/fpu/softfloat.h +@@ -532,14 +532,6 @@ float64 float64_rem(float64, float64, float_status *status); + float64 float64_muladd(float64, float64, float64, int, float_status *status); + float64 float64_sqrt(float64, float_status *status); + float64 float64_log2(float64, float_status *status); +-int float64_eq(float64, float64, float_status *status); +-int float64_le(float64, float64, float_status *status); +-int float64_lt(float64, float64, float_status *status); +-int float64_unordered(float64, float64, float_status *status); +-int float64_eq_quiet(float64, float64, float_status *status); +-int float64_le_quiet(float64, float64, float_status *status); +-int float64_lt_quiet(float64, float64, float_status *status); +-int float64_unordered_quiet(float64, float64, float_status *status); + FloatRelation float64_compare(float64, float64, float_status *status); + FloatRelation float64_compare_quiet(float64, float64, float_status *status); + float64 float64_min(float64, float64, float_status *status); +@@ -615,6 +607,47 @@ static inline float64 float64_set_sign(float64 a, int sign) + | ((int64_t)sign << 63)); + } + ++static inline bool float64_eq(float64 a, float64 b, float_status *s) ++{ ++ return float64_compare(a, b, s) == float_relation_equal; ++} ++ ++static inline bool float64_le(float64 a, float64 b, float_status *s) ++{ ++ return float64_compare(a, b, s) <= float_relation_equal; ++} ++ ++static inline bool float64_lt(float64 a, float64 b, float_status *s) ++{ ++ return float64_compare(a, b, s) < float_relation_equal; ++} ++ ++static inline bool float64_unordered(float64 a, float64 b, float_status *s) ++{ ++ return float64_compare(a, b, s) == float_relation_unordered; ++} ++ ++static inline bool float64_eq_quiet(float64 a, float64 b, float_status *s) ++{ ++ return float64_compare_quiet(a, b, s) == float_relation_equal; ++} ++ ++static inline bool float64_le_quiet(float64 a, float64 b, float_status *s) ++{ ++ return float64_compare_quiet(a, b, s) <= float_relation_equal; ++} ++ ++static inline bool float64_lt_quiet(float64 a, float64 b, float_status *s) ++{ ++ return float64_compare_quiet(a, b, s) < float_relation_equal; ++} ++ ++static inline bool float64_unordered_quiet(float64 a, float64 b, ++ float_status *s) ++{ ++ return float64_compare_quiet(a, b, s) == float_relation_unordered; ++} ++ + #define float64_zero make_float64(0) + #define float64_half make_float64(0x3fe0000000000000LL) + #define float64_one make_float64(0x3ff0000000000000LL) +diff --git a/target/s390x/vec_fpu_helper.c b/target/s390x/vec_fpu_helper.c +index a48bd704bc..c1564e819b 100644 +--- a/target/s390x/vec_fpu_helper.c ++++ b/target/s390x/vec_fpu_helper.c +@@ -174,7 +174,7 @@ void HELPER(gvec_wfk64)(const void *v1, const void *v2, CPUS390XState *env, + env->cc_op = wfc64(v1, v2, env, true, GETPC()); + } + +-typedef int (*vfc64_fn)(float64 a, float64 b, float_status *status); ++typedef bool (*vfc64_fn)(float64 a, float64 b, float_status *status); + static int vfc64(S390Vector *v1, const S390Vector *v2, const S390Vector *v3, + CPUS390XState *env, bool s, vfc64_fn fn, uintptr_t retaddr) + { +-- +2.23.0 + diff --git a/softfloat-Inline-floatx80-compare-specializations.patch b/softfloat-Inline-floatx80-compare-specializations.patch new file mode 100644 index 0000000000000000000000000000000000000000..834c593f744ff91a77a75f1643649df550da0f9b --- /dev/null +++ b/softfloat-Inline-floatx80-compare-specializations.patch @@ -0,0 +1,357 @@ +From c6baf65000f826a713e8d9b5b35e617b0ca9ab5d Mon Sep 17 00:00:00 2001 +From: Richard Henderson +Date: Tue, 5 May 2020 10:53:15 -0700 +Subject: [PATCH 600/709] softfloat: Inline floatx80 compare specializations +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Replace the floatx80 compare specializations with inline functions +that call the standard floatx80_compare{,_quiet} functions. +Use bool as the return type. + +Reviewed-by: Alex Bennée +Signed-off-by: Richard Henderson +--- + fpu/softfloat.c | 257 ---------------------------------------- + include/fpu/softfloat.h | 49 ++++++-- + 2 files changed, 41 insertions(+), 265 deletions(-) + +diff --git a/fpu/softfloat.c b/fpu/softfloat.c +index 4567dda112..6c8f2d597a 100644 +--- a/fpu/softfloat.c ++++ b/fpu/softfloat.c +@@ -5849,263 +5849,6 @@ floatx80 floatx80_sqrt(floatx80 a, float_status *status) + 0, zExp, zSig0, zSig1, status); + } + +-/*---------------------------------------------------------------------------- +-| Returns 1 if the extended double-precision floating-point value `a' is equal +-| to the corresponding value `b', and 0 otherwise. The invalid exception is +-| raised if either operand is a NaN. Otherwise, the comparison is performed +-| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. +-*----------------------------------------------------------------------------*/ +- +-int floatx80_eq(floatx80 a, floatx80 b, float_status *status) +-{ +- +- if (floatx80_invalid_encoding(a) || floatx80_invalid_encoding(b) +- || (extractFloatx80Exp(a) == 0x7FFF +- && (uint64_t) (extractFloatx80Frac(a) << 1)) +- || (extractFloatx80Exp(b) == 0x7FFF +- && (uint64_t) (extractFloatx80Frac(b) << 1)) +- ) { +- float_raise(float_flag_invalid, status); +- return 0; +- } +- return +- ( a.low == b.low ) +- && ( ( a.high == b.high ) +- || ( ( a.low == 0 ) +- && ( (uint16_t) ( ( a.high | b.high )<<1 ) == 0 ) ) +- ); +- +-} +- +-/*---------------------------------------------------------------------------- +-| Returns 1 if the extended double-precision floating-point value `a' is +-| less than or equal to the corresponding value `b', and 0 otherwise. The +-| invalid exception is raised if either operand is a NaN. The comparison is +-| performed according to the IEC/IEEE Standard for Binary Floating-Point +-| Arithmetic. +-*----------------------------------------------------------------------------*/ +- +-int floatx80_le(floatx80 a, floatx80 b, float_status *status) +-{ +- bool aSign, bSign; +- +- if (floatx80_invalid_encoding(a) || floatx80_invalid_encoding(b) +- || (extractFloatx80Exp(a) == 0x7FFF +- && (uint64_t) (extractFloatx80Frac(a) << 1)) +- || (extractFloatx80Exp(b) == 0x7FFF +- && (uint64_t) (extractFloatx80Frac(b) << 1)) +- ) { +- float_raise(float_flag_invalid, status); +- return 0; +- } +- aSign = extractFloatx80Sign( a ); +- bSign = extractFloatx80Sign( b ); +- if ( aSign != bSign ) { +- return +- aSign +- || ( ( ( (uint16_t) ( ( a.high | b.high )<<1 ) ) | a.low | b.low ) +- == 0 ); +- } +- return +- aSign ? le128( b.high, b.low, a.high, a.low ) +- : le128( a.high, a.low, b.high, b.low ); +- +-} +- +-/*---------------------------------------------------------------------------- +-| Returns 1 if the extended double-precision floating-point value `a' is +-| less than the corresponding value `b', and 0 otherwise. The invalid +-| exception is raised if either operand is a NaN. The comparison is performed +-| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. +-*----------------------------------------------------------------------------*/ +- +-int floatx80_lt(floatx80 a, floatx80 b, float_status *status) +-{ +- bool aSign, bSign; +- +- if (floatx80_invalid_encoding(a) || floatx80_invalid_encoding(b) +- || (extractFloatx80Exp(a) == 0x7FFF +- && (uint64_t) (extractFloatx80Frac(a) << 1)) +- || (extractFloatx80Exp(b) == 0x7FFF +- && (uint64_t) (extractFloatx80Frac(b) << 1)) +- ) { +- float_raise(float_flag_invalid, status); +- return 0; +- } +- aSign = extractFloatx80Sign( a ); +- bSign = extractFloatx80Sign( b ); +- if ( aSign != bSign ) { +- return +- aSign +- && ( ( ( (uint16_t) ( ( a.high | b.high )<<1 ) ) | a.low | b.low ) +- != 0 ); +- } +- return +- aSign ? lt128( b.high, b.low, a.high, a.low ) +- : lt128( a.high, a.low, b.high, b.low ); +- +-} +- +-/*---------------------------------------------------------------------------- +-| Returns 1 if the extended double-precision floating-point values `a' and `b' +-| cannot be compared, and 0 otherwise. The invalid exception is raised if +-| either operand is a NaN. The comparison is performed according to the +-| IEC/IEEE Standard for Binary Floating-Point Arithmetic. +-*----------------------------------------------------------------------------*/ +-int floatx80_unordered(floatx80 a, floatx80 b, float_status *status) +-{ +- if (floatx80_invalid_encoding(a) || floatx80_invalid_encoding(b) +- || (extractFloatx80Exp(a) == 0x7FFF +- && (uint64_t) (extractFloatx80Frac(a) << 1)) +- || (extractFloatx80Exp(b) == 0x7FFF +- && (uint64_t) (extractFloatx80Frac(b) << 1)) +- ) { +- float_raise(float_flag_invalid, status); +- return 1; +- } +- return 0; +-} +- +-/*---------------------------------------------------------------------------- +-| Returns 1 if the extended double-precision floating-point value `a' is +-| equal to the corresponding value `b', and 0 otherwise. Quiet NaNs do not +-| cause an exception. The comparison is performed according to the IEC/IEEE +-| Standard for Binary Floating-Point Arithmetic. +-*----------------------------------------------------------------------------*/ +- +-int floatx80_eq_quiet(floatx80 a, floatx80 b, float_status *status) +-{ +- +- if (floatx80_invalid_encoding(a) || floatx80_invalid_encoding(b)) { +- float_raise(float_flag_invalid, status); +- return 0; +- } +- if ( ( ( extractFloatx80Exp( a ) == 0x7FFF ) +- && (uint64_t) ( extractFloatx80Frac( a )<<1 ) ) +- || ( ( extractFloatx80Exp( b ) == 0x7FFF ) +- && (uint64_t) ( extractFloatx80Frac( b )<<1 ) ) +- ) { +- if (floatx80_is_signaling_nan(a, status) +- || floatx80_is_signaling_nan(b, status)) { +- float_raise(float_flag_invalid, status); +- } +- return 0; +- } +- return +- ( a.low == b.low ) +- && ( ( a.high == b.high ) +- || ( ( a.low == 0 ) +- && ( (uint16_t) ( ( a.high | b.high )<<1 ) == 0 ) ) +- ); +- +-} +- +-/*---------------------------------------------------------------------------- +-| Returns 1 if the extended double-precision floating-point value `a' is less +-| than or equal to the corresponding value `b', and 0 otherwise. Quiet NaNs +-| do not cause an exception. Otherwise, the comparison is performed according +-| to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. +-*----------------------------------------------------------------------------*/ +- +-int floatx80_le_quiet(floatx80 a, floatx80 b, float_status *status) +-{ +- bool aSign, bSign; +- +- if (floatx80_invalid_encoding(a) || floatx80_invalid_encoding(b)) { +- float_raise(float_flag_invalid, status); +- return 0; +- } +- if ( ( ( extractFloatx80Exp( a ) == 0x7FFF ) +- && (uint64_t) ( extractFloatx80Frac( a )<<1 ) ) +- || ( ( extractFloatx80Exp( b ) == 0x7FFF ) +- && (uint64_t) ( extractFloatx80Frac( b )<<1 ) ) +- ) { +- if (floatx80_is_signaling_nan(a, status) +- || floatx80_is_signaling_nan(b, status)) { +- float_raise(float_flag_invalid, status); +- } +- return 0; +- } +- aSign = extractFloatx80Sign( a ); +- bSign = extractFloatx80Sign( b ); +- if ( aSign != bSign ) { +- return +- aSign +- || ( ( ( (uint16_t) ( ( a.high | b.high )<<1 ) ) | a.low | b.low ) +- == 0 ); +- } +- return +- aSign ? le128( b.high, b.low, a.high, a.low ) +- : le128( a.high, a.low, b.high, b.low ); +- +-} +- +-/*---------------------------------------------------------------------------- +-| Returns 1 if the extended double-precision floating-point value `a' is less +-| than the corresponding value `b', and 0 otherwise. Quiet NaNs do not cause +-| an exception. Otherwise, the comparison is performed according to the +-| IEC/IEEE Standard for Binary Floating-Point Arithmetic. +-*----------------------------------------------------------------------------*/ +- +-int floatx80_lt_quiet(floatx80 a, floatx80 b, float_status *status) +-{ +- bool aSign, bSign; +- +- if (floatx80_invalid_encoding(a) || floatx80_invalid_encoding(b)) { +- float_raise(float_flag_invalid, status); +- return 0; +- } +- if ( ( ( extractFloatx80Exp( a ) == 0x7FFF ) +- && (uint64_t) ( extractFloatx80Frac( a )<<1 ) ) +- || ( ( extractFloatx80Exp( b ) == 0x7FFF ) +- && (uint64_t) ( extractFloatx80Frac( b )<<1 ) ) +- ) { +- if (floatx80_is_signaling_nan(a, status) +- || floatx80_is_signaling_nan(b, status)) { +- float_raise(float_flag_invalid, status); +- } +- return 0; +- } +- aSign = extractFloatx80Sign( a ); +- bSign = extractFloatx80Sign( b ); +- if ( aSign != bSign ) { +- return +- aSign +- && ( ( ( (uint16_t) ( ( a.high | b.high )<<1 ) ) | a.low | b.low ) +- != 0 ); +- } +- return +- aSign ? lt128( b.high, b.low, a.high, a.low ) +- : lt128( a.high, a.low, b.high, b.low ); +- +-} +- +-/*---------------------------------------------------------------------------- +-| Returns 1 if the extended double-precision floating-point values `a' and `b' +-| cannot be compared, and 0 otherwise. Quiet NaNs do not cause an exception. +-| The comparison is performed according to the IEC/IEEE Standard for Binary +-| Floating-Point Arithmetic. +-*----------------------------------------------------------------------------*/ +-int floatx80_unordered_quiet(floatx80 a, floatx80 b, float_status *status) +-{ +- if (floatx80_invalid_encoding(a) || floatx80_invalid_encoding(b)) { +- float_raise(float_flag_invalid, status); +- return 1; +- } +- if ( ( ( extractFloatx80Exp( a ) == 0x7FFF ) +- && (uint64_t) ( extractFloatx80Frac( a )<<1 ) ) +- || ( ( extractFloatx80Exp( b ) == 0x7FFF ) +- && (uint64_t) ( extractFloatx80Frac( b )<<1 ) ) +- ) { +- if (floatx80_is_signaling_nan(a, status) +- || floatx80_is_signaling_nan(b, status)) { +- float_raise(float_flag_invalid, status); +- } +- return 1; +- } +- return 0; +-} +- + /*---------------------------------------------------------------------------- + | Returns the result of converting the quadruple-precision floating-point + | value `a' to the 32-bit two's complement integer format. The conversion +diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h +index cfb3cda46b..37217d9b9b 100644 +--- a/include/fpu/softfloat.h ++++ b/include/fpu/softfloat.h +@@ -689,14 +689,6 @@ floatx80 floatx80_mul(floatx80, floatx80, float_status *status); + floatx80 floatx80_div(floatx80, floatx80, float_status *status); + floatx80 floatx80_rem(floatx80, floatx80, float_status *status); + floatx80 floatx80_sqrt(floatx80, float_status *status); +-int floatx80_eq(floatx80, floatx80, float_status *status); +-int floatx80_le(floatx80, floatx80, float_status *status); +-int floatx80_lt(floatx80, floatx80, float_status *status); +-int floatx80_unordered(floatx80, floatx80, float_status *status); +-int floatx80_eq_quiet(floatx80, floatx80, float_status *status); +-int floatx80_le_quiet(floatx80, floatx80, float_status *status); +-int floatx80_lt_quiet(floatx80, floatx80, float_status *status); +-int floatx80_unordered_quiet(floatx80, floatx80, float_status *status); + FloatRelation floatx80_compare(floatx80, floatx80, float_status *status); + FloatRelation floatx80_compare_quiet(floatx80, floatx80, float_status *status); + int floatx80_is_quiet_nan(floatx80, float_status *status); +@@ -746,6 +738,47 @@ static inline int floatx80_is_any_nan(floatx80 a) + return ((a.high & 0x7fff) == 0x7fff) && (a.low<<1); + } + ++static inline bool floatx80_eq(floatx80 a, floatx80 b, float_status *s) ++{ ++ return floatx80_compare(a, b, s) == float_relation_equal; ++} ++ ++static inline bool floatx80_le(floatx80 a, floatx80 b, float_status *s) ++{ ++ return floatx80_compare(a, b, s) <= float_relation_equal; ++} ++ ++static inline bool floatx80_lt(floatx80 a, floatx80 b, float_status *s) ++{ ++ return floatx80_compare(a, b, s) < float_relation_equal; ++} ++ ++static inline bool floatx80_unordered(floatx80 a, floatx80 b, float_status *s) ++{ ++ return floatx80_compare(a, b, s) == float_relation_unordered; ++} ++ ++static inline bool floatx80_eq_quiet(floatx80 a, floatx80 b, float_status *s) ++{ ++ return floatx80_compare_quiet(a, b, s) == float_relation_equal; ++} ++ ++static inline bool floatx80_le_quiet(floatx80 a, floatx80 b, float_status *s) ++{ ++ return floatx80_compare_quiet(a, b, s) <= float_relation_equal; ++} ++ ++static inline bool floatx80_lt_quiet(floatx80 a, floatx80 b, float_status *s) ++{ ++ return floatx80_compare_quiet(a, b, s) < float_relation_equal; ++} ++ ++static inline bool floatx80_unordered_quiet(floatx80 a, floatx80 b, ++ float_status *s) ++{ ++ return floatx80_compare_quiet(a, b, s) == float_relation_unordered; ++} ++ + /*---------------------------------------------------------------------------- + | Return whether the given value is an invalid floatx80 encoding. + | Invalid floatx80 encodings arise when the integer bit is not set, but +-- +2.23.0 + diff --git a/softfloat-Name-compare-relation-enum.patch b/softfloat-Name-compare-relation-enum.patch new file mode 100644 index 0000000000000000000000000000000000000000..9bbd0a0313d7c78f30b9956a6741948bb59a3578 --- /dev/null +++ b/softfloat-Name-compare-relation-enum.patch @@ -0,0 +1,565 @@ +From 71bfd65c5fcd72f8af2735905415c7ce4220f6dc Mon Sep 17 00:00:00 2001 +From: Richard Henderson +Date: Tue, 5 May 2020 10:22:05 -0700 +Subject: [PATCH 596/709] softfloat: Name compare relation enum +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Give the previously unnamed enum a typedef name. Use it in the +prototypes of compare functions. Use it to hold the results +of the compare functions. + +Reviewed-by: Alex Bennée +Reviewed-by: Philippe Mathieu-Daudé +Signed-off-by: Richard Henderson +--- + fpu/softfloat.c | 40 ++++++++++++++++++--------------- + include/fpu/softfloat.h | 25 +++++++++++---------- + target/arm/vfp_helper.c | 2 +- + target/hppa/op_helper.c | 7 +++--- + target/i386/fpu_helper.c | 8 +++---- + target/i386/ops_sse.h | 8 +++---- + target/openrisc/fpu_helper.c | 4 ++-- + target/ppc/int_helper.c | 13 ++++++----- + target/s390x/fpu_helper.c | 22 +++++++++--------- + target/sparc/fop_helper.c | 4 ++-- + target/unicore32/ucf64_helper.c | 6 ++--- + target/xtensa/fpu_helper.c | 6 ++--- + 12 files changed, 75 insertions(+), 70 deletions(-) + +diff --git a/fpu/softfloat.c b/fpu/softfloat.c +index 93d8a03de6..60b9ae5f05 100644 +--- a/fpu/softfloat.c ++++ b/fpu/softfloat.c +@@ -2848,8 +2848,8 @@ MINMAX(64, maxnummag, false, true, true) + #undef MINMAX + + /* Floating point compare */ +-static int compare_floats(FloatParts a, FloatParts b, bool is_quiet, +- float_status *s) ++static FloatRelation compare_floats(FloatParts a, FloatParts b, bool is_quiet, ++ float_status *s) + { + if (is_nan(a.cls) || is_nan(b.cls)) { + if (!is_quiet || +@@ -2920,17 +2920,17 @@ COMPARE(soft_f64_compare, QEMU_SOFTFLOAT_ATTR, 64) + + #undef COMPARE + +-int float16_compare(float16 a, float16 b, float_status *s) ++FloatRelation float16_compare(float16 a, float16 b, float_status *s) + { + return soft_f16_compare(a, b, false, s); + } + +-int float16_compare_quiet(float16 a, float16 b, float_status *s) ++FloatRelation float16_compare_quiet(float16 a, float16 b, float_status *s) + { + return soft_f16_compare(a, b, true, s); + } + +-static int QEMU_FLATTEN ++static FloatRelation QEMU_FLATTEN + f32_compare(float32 xa, float32 xb, bool is_quiet, float_status *s) + { + union_float32 ua, ub; +@@ -2959,17 +2959,17 @@ f32_compare(float32 xa, float32 xb, bool is_quiet, float_status *s) + return soft_f32_compare(ua.s, ub.s, is_quiet, s); + } + +-int float32_compare(float32 a, float32 b, float_status *s) ++FloatRelation float32_compare(float32 a, float32 b, float_status *s) + { + return f32_compare(a, b, false, s); + } + +-int float32_compare_quiet(float32 a, float32 b, float_status *s) ++FloatRelation float32_compare_quiet(float32 a, float32 b, float_status *s) + { + return f32_compare(a, b, true, s); + } + +-static int QEMU_FLATTEN ++static FloatRelation QEMU_FLATTEN + f64_compare(float64 xa, float64 xb, bool is_quiet, float_status *s) + { + union_float64 ua, ub; +@@ -2998,12 +2998,12 @@ f64_compare(float64 xa, float64 xb, bool is_quiet, float_status *s) + return soft_f64_compare(ua.s, ub.s, is_quiet, s); + } + +-int float64_compare(float64 a, float64 b, float_status *s) ++FloatRelation float64_compare(float64 a, float64 b, float_status *s) + { + return f64_compare(a, b, false, s); + } + +-int float64_compare_quiet(float64 a, float64 b, float_status *s) ++FloatRelation float64_compare_quiet(float64 a, float64 b, float_status *s) + { + return f64_compare(a, b, true, s); + } +@@ -7892,8 +7892,9 @@ int float128_unordered_quiet(float128 a, float128 b, float_status *status) + return 0; + } + +-static inline int floatx80_compare_internal(floatx80 a, floatx80 b, +- int is_quiet, float_status *status) ++static inline FloatRelation ++floatx80_compare_internal(floatx80 a, floatx80 b, bool is_quiet, ++ float_status *status) + { + bool aSign, bSign; + +@@ -7939,18 +7940,20 @@ static inline int floatx80_compare_internal(floatx80 a, floatx80 b, + } + } + +-int floatx80_compare(floatx80 a, floatx80 b, float_status *status) ++FloatRelation floatx80_compare(floatx80 a, floatx80 b, float_status *status) + { + return floatx80_compare_internal(a, b, 0, status); + } + +-int floatx80_compare_quiet(floatx80 a, floatx80 b, float_status *status) ++FloatRelation floatx80_compare_quiet(floatx80 a, floatx80 b, ++ float_status *status) + { + return floatx80_compare_internal(a, b, 1, status); + } + +-static inline int float128_compare_internal(float128 a, float128 b, +- int is_quiet, float_status *status) ++static inline FloatRelation ++float128_compare_internal(float128 a, float128 b, bool is_quiet, ++ float_status *status) + { + bool aSign, bSign; + +@@ -7983,12 +7986,13 @@ static inline int float128_compare_internal(float128 a, float128 b, + } + } + +-int float128_compare(float128 a, float128 b, float_status *status) ++FloatRelation float128_compare(float128 a, float128 b, float_status *status) + { + return float128_compare_internal(a, b, 0, status); + } + +-int float128_compare_quiet(float128 a, float128 b, float_status *status) ++FloatRelation float128_compare_quiet(float128 a, float128 b, ++ float_status *status) + { + return float128_compare_internal(a, b, 1, status); + } +diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h +index ca75f764aa..7f84235122 100644 +--- a/include/fpu/softfloat.h ++++ b/include/fpu/softfloat.h +@@ -85,12 +85,13 @@ this code that are retained. + /*---------------------------------------------------------------------------- + | Software IEC/IEEE floating-point ordering relations + *----------------------------------------------------------------------------*/ +-enum { ++ ++typedef enum { + float_relation_less = -1, + float_relation_equal = 0, + float_relation_greater = 1, + float_relation_unordered = 2 +-}; ++} FloatRelation; + + #include "fpu/softfloat-types.h" + #include "fpu/softfloat-helpers.h" +@@ -231,8 +232,8 @@ float16 float16_maxnum(float16, float16, float_status *status); + float16 float16_minnummag(float16, float16, float_status *status); + float16 float16_maxnummag(float16, float16, float_status *status); + float16 float16_sqrt(float16, float_status *status); +-int float16_compare(float16, float16, float_status *status); +-int float16_compare_quiet(float16, float16, float_status *status); ++FloatRelation float16_compare(float16, float16, float_status *status); ++FloatRelation float16_compare_quiet(float16, float16, float_status *status); + + int float16_is_quiet_nan(float16, float_status *status); + int float16_is_signaling_nan(float16, float_status *status); +@@ -350,8 +351,8 @@ int float32_eq_quiet(float32, float32, float_status *status); + int float32_le_quiet(float32, float32, float_status *status); + int float32_lt_quiet(float32, float32, float_status *status); + int float32_unordered_quiet(float32, float32, float_status *status); +-int float32_compare(float32, float32, float_status *status); +-int float32_compare_quiet(float32, float32, float_status *status); ++FloatRelation float32_compare(float32, float32, float_status *status); ++FloatRelation float32_compare_quiet(float32, float32, float_status *status); + float32 float32_min(float32, float32, float_status *status); + float32 float32_max(float32, float32, float_status *status); + float32 float32_minnum(float32, float32, float_status *status); +@@ -506,8 +507,8 @@ int float64_eq_quiet(float64, float64, float_status *status); + int float64_le_quiet(float64, float64, float_status *status); + int float64_lt_quiet(float64, float64, float_status *status); + int float64_unordered_quiet(float64, float64, float_status *status); +-int float64_compare(float64, float64, float_status *status); +-int float64_compare_quiet(float64, float64, float_status *status); ++FloatRelation float64_compare(float64, float64, float_status *status); ++FloatRelation float64_compare_quiet(float64, float64, float_status *status); + float64 float64_min(float64, float64, float_status *status); + float64 float64_max(float64, float64, float_status *status); + float64 float64_minnum(float64, float64, float_status *status); +@@ -630,8 +631,8 @@ int floatx80_eq_quiet(floatx80, floatx80, float_status *status); + int floatx80_le_quiet(floatx80, floatx80, float_status *status); + int floatx80_lt_quiet(floatx80, floatx80, float_status *status); + int floatx80_unordered_quiet(floatx80, floatx80, float_status *status); +-int floatx80_compare(floatx80, floatx80, float_status *status); +-int floatx80_compare_quiet(floatx80, floatx80, float_status *status); ++FloatRelation floatx80_compare(floatx80, floatx80, float_status *status); ++FloatRelation floatx80_compare_quiet(floatx80, floatx80, float_status *status); + int floatx80_is_quiet_nan(floatx80, float_status *status); + int floatx80_is_signaling_nan(floatx80, float_status *status); + floatx80 floatx80_silence_nan(floatx80, float_status *status); +@@ -842,8 +843,8 @@ int float128_eq_quiet(float128, float128, float_status *status); + int float128_le_quiet(float128, float128, float_status *status); + int float128_lt_quiet(float128, float128, float_status *status); + int float128_unordered_quiet(float128, float128, float_status *status); +-int float128_compare(float128, float128, float_status *status); +-int float128_compare_quiet(float128, float128, float_status *status); ++FloatRelation float128_compare(float128, float128, float_status *status); ++FloatRelation float128_compare_quiet(float128, float128, float_status *status); + int float128_is_quiet_nan(float128, float_status *status); + int float128_is_signaling_nan(float128, float_status *status); + float128 float128_silence_nan(float128, float_status *status); +diff --git a/target/arm/vfp_helper.c b/target/arm/vfp_helper.c +index 0920694764..60dcd4bf14 100644 +--- a/target/arm/vfp_helper.c ++++ b/target/arm/vfp_helper.c +@@ -281,7 +281,7 @@ float64 VFP_HELPER(sqrt, d)(float64 a, CPUARMState *env) + return float64_sqrt(a, &env->vfp.fp_status); + } + +-static void softfloat_to_vfp_compare(CPUARMState *env, int cmp) ++static void softfloat_to_vfp_compare(CPUARMState *env, FloatRelation cmp) + { + uint32_t flags; + switch (cmp) { +diff --git a/target/hppa/op_helper.c b/target/hppa/op_helper.c +index 7823706e9c..5685e303ab 100644 +--- a/target/hppa/op_helper.c ++++ b/target/hppa/op_helper.c +@@ -523,7 +523,8 @@ uint64_t HELPER(fcnv_t_d_udw)(CPUHPPAState *env, float64 arg) + return ret; + } + +-static void update_fr0_cmp(CPUHPPAState *env, uint32_t y, uint32_t c, int r) ++static void update_fr0_cmp(CPUHPPAState *env, uint32_t y, ++ uint32_t c, FloatRelation r) + { + uint32_t shadow = env->fr0_shadow; + +@@ -565,7 +566,7 @@ static void update_fr0_cmp(CPUHPPAState *env, uint32_t y, uint32_t c, int r) + void HELPER(fcmp_s)(CPUHPPAState *env, float32 a, float32 b, + uint32_t y, uint32_t c) + { +- int r; ++ FloatRelation r; + if (c & 1) { + r = float32_compare(a, b, &env->fp_status); + } else { +@@ -578,7 +579,7 @@ void HELPER(fcmp_s)(CPUHPPAState *env, float32 a, float32 b, + void HELPER(fcmp_d)(CPUHPPAState *env, float64 a, float64 b, + uint32_t y, uint32_t c) + { +- int r; ++ FloatRelation r; + if (c & 1) { + r = float64_compare(a, b, &env->fp_status); + } else { +diff --git a/target/i386/fpu_helper.c b/target/i386/fpu_helper.c +index 792a128a6d..b34fa784eb 100644 +--- a/target/i386/fpu_helper.c ++++ b/target/i386/fpu_helper.c +@@ -420,7 +420,7 @@ static const int fcom_ccval[4] = {0x0100, 0x4000, 0x0000, 0x4500}; + + void helper_fcom_ST0_FT0(CPUX86State *env) + { +- int ret; ++ FloatRelation ret; + + ret = floatx80_compare(ST0, FT0, &env->fp_status); + env->fpus = (env->fpus & ~0x4500) | fcom_ccval[ret + 1]; +@@ -428,7 +428,7 @@ void helper_fcom_ST0_FT0(CPUX86State *env) + + void helper_fucom_ST0_FT0(CPUX86State *env) + { +- int ret; ++ FloatRelation ret; + + ret = floatx80_compare_quiet(ST0, FT0, &env->fp_status); + env->fpus = (env->fpus & ~0x4500) | fcom_ccval[ret + 1]; +@@ -439,7 +439,7 @@ static const int fcomi_ccval[4] = {CC_C, CC_Z, 0, CC_Z | CC_P | CC_C}; + void helper_fcomi_ST0_FT0(CPUX86State *env) + { + int eflags; +- int ret; ++ FloatRelation ret; + + ret = floatx80_compare(ST0, FT0, &env->fp_status); + eflags = cpu_cc_compute_all(env, CC_OP); +@@ -450,7 +450,7 @@ void helper_fcomi_ST0_FT0(CPUX86State *env) + void helper_fucomi_ST0_FT0(CPUX86State *env) + { + int eflags; +- int ret; ++ FloatRelation ret; + + ret = floatx80_compare_quiet(ST0, FT0, &env->fp_status); + eflags = cpu_cc_compute_all(env, CC_OP); +diff --git a/target/i386/ops_sse.h b/target/i386/ops_sse.h +index ec1ec745d0..4658768de2 100644 +--- a/target/i386/ops_sse.h ++++ b/target/i386/ops_sse.h +@@ -1031,7 +1031,7 @@ 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) + { +- int ret; ++ FloatRelation ret; + float32 s0, s1; + + s0 = d->ZMM_S(0); +@@ -1042,7 +1042,7 @@ void helper_ucomiss(CPUX86State *env, Reg *d, Reg *s) + + void helper_comiss(CPUX86State *env, Reg *d, Reg *s) + { +- int ret; ++ FloatRelation ret; + float32 s0, s1; + + s0 = d->ZMM_S(0); +@@ -1053,7 +1053,7 @@ void helper_comiss(CPUX86State *env, Reg *d, Reg *s) + + void helper_ucomisd(CPUX86State *env, Reg *d, Reg *s) + { +- int ret; ++ FloatRelation ret; + float64 d0, d1; + + d0 = d->ZMM_D(0); +@@ -1064,7 +1064,7 @@ void helper_ucomisd(CPUX86State *env, Reg *d, Reg *s) + + void helper_comisd(CPUX86State *env, Reg *d, Reg *s) + { +- int ret; ++ FloatRelation ret; + float64 d0, d1; + + d0 = d->ZMM_D(0); +diff --git a/target/openrisc/fpu_helper.c b/target/openrisc/fpu_helper.c +index 6f75ea0505..f9e34fa2cc 100644 +--- a/target/openrisc/fpu_helper.c ++++ b/target/openrisc/fpu_helper.c +@@ -155,13 +155,13 @@ FLOAT_CMP(un, unordered_quiet) + target_ulong helper_float_ ## name ## _d(CPUOpenRISCState *env, \ + uint64_t fdt0, uint64_t fdt1) \ + { \ +- int r = float64_compare_quiet(fdt0, fdt1, &env->fp_status); \ ++ FloatRelation r = float64_compare_quiet(fdt0, fdt1, &env->fp_status); \ + return expr; \ + } \ + target_ulong helper_float_ ## name ## _s(CPUOpenRISCState *env, \ + uint32_t fdt0, uint32_t fdt1) \ + { \ +- int r = float32_compare_quiet(fdt0, fdt1, &env->fp_status); \ ++ FloatRelation r = float32_compare_quiet(fdt0, fdt1, &env->fp_status); \ + return expr; \ + } + +diff --git a/target/ppc/int_helper.c b/target/ppc/int_helper.c +index 6d238b989d..be53cd6f68 100644 +--- a/target/ppc/int_helper.c ++++ b/target/ppc/int_helper.c +@@ -770,8 +770,9 @@ VCMPNE(w, u32, uint32_t, 0) + \ + for (i = 0; i < ARRAY_SIZE(r->f32); i++) { \ + uint32_t result; \ +- int rel = float32_compare_quiet(a->f32[i], b->f32[i], \ +- &env->vec_status); \ ++ FloatRelation rel = \ ++ float32_compare_quiet(a->f32[i], b->f32[i], \ ++ &env->vec_status); \ + if (rel == float_relation_unordered) { \ + result = 0; \ + } else if (rel compare order) { \ +@@ -803,15 +804,15 @@ static inline void vcmpbfp_internal(CPUPPCState *env, ppc_avr_t *r, + int all_in = 0; + + for (i = 0; i < ARRAY_SIZE(r->f32); i++) { +- int le_rel = float32_compare_quiet(a->f32[i], b->f32[i], +- &env->vec_status); ++ FloatRelation le_rel = float32_compare_quiet(a->f32[i], b->f32[i], ++ &env->vec_status); + if (le_rel == float_relation_unordered) { + r->u32[i] = 0xc0000000; + all_in = 1; + } else { + float32 bneg = float32_chs(b->f32[i]); +- int ge_rel = float32_compare_quiet(a->f32[i], bneg, +- &env->vec_status); ++ FloatRelation ge_rel = float32_compare_quiet(a->f32[i], bneg, ++ &env->vec_status); + int le = le_rel != float_relation_greater; + int ge = ge_rel != float_relation_less; + +diff --git a/target/s390x/fpu_helper.c b/target/s390x/fpu_helper.c +index 8bb9f54fd0..f155bc048c 100644 +--- a/target/s390x/fpu_helper.c ++++ b/target/s390x/fpu_helper.c +@@ -112,7 +112,7 @@ static void handle_exceptions(CPUS390XState *env, bool XxC, uintptr_t retaddr) + } + } + +-int float_comp_to_cc(CPUS390XState *env, int float_compare) ++int float_comp_to_cc(CPUS390XState *env, FloatRelation float_compare) + { + switch (float_compare) { + case float_relation_equal: +@@ -368,7 +368,7 @@ uint64_t HELPER(lexb)(CPUS390XState *env, uint64_t ah, uint64_t al, + /* 32-bit FP compare */ + uint32_t HELPER(ceb)(CPUS390XState *env, uint64_t f1, uint64_t f2) + { +- int cmp = float32_compare_quiet(f1, f2, &env->fpu_status); ++ FloatRelation cmp = float32_compare_quiet(f1, f2, &env->fpu_status); + handle_exceptions(env, false, GETPC()); + return float_comp_to_cc(env, cmp); + } +@@ -376,7 +376,7 @@ uint32_t HELPER(ceb)(CPUS390XState *env, uint64_t f1, uint64_t f2) + /* 64-bit FP compare */ + uint32_t HELPER(cdb)(CPUS390XState *env, uint64_t f1, uint64_t f2) + { +- int cmp = float64_compare_quiet(f1, f2, &env->fpu_status); ++ FloatRelation cmp = float64_compare_quiet(f1, f2, &env->fpu_status); + handle_exceptions(env, false, GETPC()); + return float_comp_to_cc(env, cmp); + } +@@ -385,9 +385,9 @@ uint32_t HELPER(cdb)(CPUS390XState *env, uint64_t f1, uint64_t f2) + uint32_t HELPER(cxb)(CPUS390XState *env, uint64_t ah, uint64_t al, + uint64_t bh, uint64_t bl) + { +- int cmp = float128_compare_quiet(make_float128(ah, al), +- make_float128(bh, bl), +- &env->fpu_status); ++ FloatRelation cmp = float128_compare_quiet(make_float128(ah, al), ++ make_float128(bh, bl), ++ &env->fpu_status); + handle_exceptions(env, false, GETPC()); + return float_comp_to_cc(env, cmp); + } +@@ -675,7 +675,7 @@ uint64_t HELPER(fixb)(CPUS390XState *env, uint64_t ah, uint64_t al, + /* 32-bit FP compare and signal */ + uint32_t HELPER(keb)(CPUS390XState *env, uint64_t f1, uint64_t f2) + { +- int cmp = float32_compare(f1, f2, &env->fpu_status); ++ FloatRelation cmp = float32_compare(f1, f2, &env->fpu_status); + handle_exceptions(env, false, GETPC()); + return float_comp_to_cc(env, cmp); + } +@@ -683,7 +683,7 @@ uint32_t HELPER(keb)(CPUS390XState *env, uint64_t f1, uint64_t f2) + /* 64-bit FP compare and signal */ + uint32_t HELPER(kdb)(CPUS390XState *env, uint64_t f1, uint64_t f2) + { +- int cmp = float64_compare(f1, f2, &env->fpu_status); ++ FloatRelation cmp = float64_compare(f1, f2, &env->fpu_status); + handle_exceptions(env, false, GETPC()); + return float_comp_to_cc(env, cmp); + } +@@ -692,9 +692,9 @@ uint32_t HELPER(kdb)(CPUS390XState *env, uint64_t f1, uint64_t f2) + uint32_t HELPER(kxb)(CPUS390XState *env, uint64_t ah, uint64_t al, + uint64_t bh, uint64_t bl) + { +- int cmp = float128_compare(make_float128(ah, al), +- make_float128(bh, bl), +- &env->fpu_status); ++ FloatRelation cmp = float128_compare(make_float128(ah, al), ++ make_float128(bh, bl), ++ &env->fpu_status); + handle_exceptions(env, false, GETPC()); + return float_comp_to_cc(env, cmp); + } +diff --git a/target/sparc/fop_helper.c b/target/sparc/fop_helper.c +index 9eb9b75718..e6dd3fc313 100644 +--- a/target/sparc/fop_helper.c ++++ b/target/sparc/fop_helper.c +@@ -264,7 +264,7 @@ void helper_fsqrtq(CPUSPARCState *env) + #define GEN_FCMP(name, size, reg1, reg2, FS, E) \ + target_ulong glue(helper_, name) (CPUSPARCState *env) \ + { \ +- int ret; \ ++ FloatRelation ret; \ + target_ulong fsr; \ + if (E) { \ + ret = glue(size, _compare)(reg1, reg2, &env->fp_status); \ +@@ -295,7 +295,7 @@ void helper_fsqrtq(CPUSPARCState *env) + #define GEN_FCMP_T(name, size, FS, E) \ + target_ulong glue(helper_, name)(CPUSPARCState *env, size src1, size src2)\ + { \ +- int ret; \ ++ FloatRelation ret; \ + target_ulong fsr; \ + if (E) { \ + ret = glue(size, _compare)(src1, src2, &env->fp_status); \ +diff --git a/target/unicore32/ucf64_helper.c b/target/unicore32/ucf64_helper.c +index e078e84437..12a91900f6 100644 +--- a/target/unicore32/ucf64_helper.c ++++ b/target/unicore32/ucf64_helper.c +@@ -174,8 +174,7 @@ float64 HELPER(ucf64_absd)(float64 a) + void HELPER(ucf64_cmps)(float32 a, float32 b, uint32_t c, + CPUUniCore32State *env) + { +- int flag; +- flag = float32_compare_quiet(a, b, &env->ucf64.fp_status); ++ FloatRelation flag = float32_compare_quiet(a, b, &env->ucf64.fp_status); + env->CF = 0; + switch (c & 0x7) { + case 0: /* F */ +@@ -223,8 +222,7 @@ void HELPER(ucf64_cmps)(float32 a, float32 b, uint32_t c, + void HELPER(ucf64_cmpd)(float64 a, float64 b, uint32_t c, + CPUUniCore32State *env) + { +- int flag; +- flag = float64_compare_quiet(a, b, &env->ucf64.fp_status); ++ FloatRelation flag = float64_compare_quiet(a, b, &env->ucf64.fp_status); + env->CF = 0; + switch (c & 0x7) { + case 0: /* F */ +diff --git a/target/xtensa/fpu_helper.c b/target/xtensa/fpu_helper.c +index f8bbb6cdd8..87487293f9 100644 +--- a/target/xtensa/fpu_helper.c ++++ b/target/xtensa/fpu_helper.c +@@ -139,7 +139,7 @@ void HELPER(oeq_s)(CPUXtensaState *env, uint32_t br, float32 a, float32 b) + + void HELPER(ueq_s)(CPUXtensaState *env, uint32_t br, float32 a, float32 b) + { +- int v = float32_compare_quiet(a, b, &env->fp_status); ++ FloatRelation v = float32_compare_quiet(a, b, &env->fp_status); + set_br(env, v == float_relation_equal || v == float_relation_unordered, br); + } + +@@ -150,7 +150,7 @@ void HELPER(olt_s)(CPUXtensaState *env, uint32_t br, float32 a, float32 b) + + void HELPER(ult_s)(CPUXtensaState *env, uint32_t br, float32 a, float32 b) + { +- int v = float32_compare_quiet(a, b, &env->fp_status); ++ FloatRelation v = float32_compare_quiet(a, b, &env->fp_status); + set_br(env, v == float_relation_less || v == float_relation_unordered, br); + } + +@@ -161,6 +161,6 @@ void HELPER(ole_s)(CPUXtensaState *env, uint32_t br, float32 a, float32 b) + + void HELPER(ule_s)(CPUXtensaState *env, uint32_t br, float32 a, float32 b) + { +- int v = float32_compare_quiet(a, b, &env->fp_status); ++ FloatRelation v = float32_compare_quiet(a, b, &env->fp_status); + set_br(env, v != float_relation_greater, br); + } +-- +2.23.0 + diff --git a/softfloat-Name-rounding-mode-enum.patch b/softfloat-Name-rounding-mode-enum.patch new file mode 100644 index 0000000000000000000000000000000000000000..113f53e6e2d6e3ffd6e5720bb998ff0535a2c6d0 --- /dev/null +++ b/softfloat-Name-rounding-mode-enum.patch @@ -0,0 +1,428 @@ +From 3dede407cc61b64997f0c30f6dbf4df09949abc9 Mon Sep 17 00:00:00 2001 +From: Richard Henderson +Date: Tue, 5 May 2020 09:01:49 -0700 +Subject: [PATCH 595/709] softfloat: Name rounding mode enum +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Give the previously unnamed enum a typedef name. Use the packed +attribute so that we do not affect the layout of the float_status +struct. Use it in the prototypes of relevant functions. + +Adjust switch statements as necessary to avoid compiler warnings. + +Reviewed-by: Alex Bennée +Reviewed-by: Philippe Mathieu-Daudé +Signed-off-by: Richard Henderson +--- + fpu/softfloat.c | 57 ++++++++++++++++++++------------- + include/fpu/softfloat-helpers.h | 5 +-- + include/fpu/softfloat-types.h | 6 ++-- + include/fpu/softfloat.h | 39 +++++++++++----------- + target/arm/vfp_helper.c | 4 +-- + target/m68k/fpu_helper.c | 6 ++-- + 6 files changed, 66 insertions(+), 51 deletions(-) + +diff --git a/fpu/softfloat.c b/fpu/softfloat.c +index 65d457a548..93d8a03de6 100644 +--- a/fpu/softfloat.c ++++ b/fpu/softfloat.c +@@ -759,6 +759,8 @@ static FloatParts round_canonical(FloatParts p, float_status *s, + case float_round_to_odd: + inc = frac & frac_lsb ? 0 : round_mask; + break; ++ default: ++ break; + } + flags |= float_flag_inexact; + frac += inc; +@@ -1928,7 +1930,7 @@ float32 float64_to_float32(float64 a, float_status *s) + * Arithmetic. + */ + +-static FloatParts round_to_int(FloatParts a, int rmode, ++static FloatParts round_to_int(FloatParts a, FloatRoundMode rmode, + int scale, float_status *s) + { + switch (a.cls) { +@@ -2061,8 +2063,8 @@ float64 float64_round_to_int(float64 a, float_status *s) + * is returned. + */ + +-static int64_t round_to_int_and_pack(FloatParts in, int rmode, int scale, +- int64_t min, int64_t max, ++static int64_t round_to_int_and_pack(FloatParts in, FloatRoundMode rmode, ++ int scale, int64_t min, int64_t max, + float_status *s) + { + uint64_t r; +@@ -2107,63 +2109,63 @@ static int64_t round_to_int_and_pack(FloatParts in, int rmode, int scale, + } + } + +-int16_t float16_to_int16_scalbn(float16 a, int rmode, int scale, ++int16_t float16_to_int16_scalbn(float16 a, FloatRoundMode rmode, int scale, + float_status *s) + { + return round_to_int_and_pack(float16_unpack_canonical(a, s), + rmode, scale, INT16_MIN, INT16_MAX, s); + } + +-int32_t float16_to_int32_scalbn(float16 a, int rmode, int scale, ++int32_t float16_to_int32_scalbn(float16 a, FloatRoundMode rmode, int scale, + float_status *s) + { + return round_to_int_and_pack(float16_unpack_canonical(a, s), + rmode, scale, INT32_MIN, INT32_MAX, s); + } + +-int64_t float16_to_int64_scalbn(float16 a, int rmode, int scale, ++int64_t float16_to_int64_scalbn(float16 a, FloatRoundMode rmode, int scale, + float_status *s) + { + return round_to_int_and_pack(float16_unpack_canonical(a, s), + rmode, scale, INT64_MIN, INT64_MAX, s); + } + +-int16_t float32_to_int16_scalbn(float32 a, int rmode, int scale, ++int16_t float32_to_int16_scalbn(float32 a, FloatRoundMode rmode, int scale, + float_status *s) + { + return round_to_int_and_pack(float32_unpack_canonical(a, s), + rmode, scale, INT16_MIN, INT16_MAX, s); + } + +-int32_t float32_to_int32_scalbn(float32 a, int rmode, int scale, ++int32_t float32_to_int32_scalbn(float32 a, FloatRoundMode rmode, int scale, + float_status *s) + { + return round_to_int_and_pack(float32_unpack_canonical(a, s), + rmode, scale, INT32_MIN, INT32_MAX, s); + } + +-int64_t float32_to_int64_scalbn(float32 a, int rmode, int scale, ++int64_t float32_to_int64_scalbn(float32 a, FloatRoundMode rmode, int scale, + float_status *s) + { + return round_to_int_and_pack(float32_unpack_canonical(a, s), + rmode, scale, INT64_MIN, INT64_MAX, s); + } + +-int16_t float64_to_int16_scalbn(float64 a, int rmode, int scale, ++int16_t float64_to_int16_scalbn(float64 a, FloatRoundMode rmode, int scale, + float_status *s) + { + return round_to_int_and_pack(float64_unpack_canonical(a, s), + rmode, scale, INT16_MIN, INT16_MAX, s); + } + +-int32_t float64_to_int32_scalbn(float64 a, int rmode, int scale, ++int32_t float64_to_int32_scalbn(float64 a, FloatRoundMode rmode, int scale, + float_status *s) + { + return round_to_int_and_pack(float64_unpack_canonical(a, s), + rmode, scale, INT32_MIN, INT32_MAX, s); + } + +-int64_t float64_to_int64_scalbn(float64 a, int rmode, int scale, ++int64_t float64_to_int64_scalbn(float64 a, FloatRoundMode rmode, int scale, + float_status *s) + { + return round_to_int_and_pack(float64_unpack_canonical(a, s), +@@ -2273,8 +2275,9 @@ int64_t float64_to_int64_round_to_zero(float64 a, float_status *s) + * flag. + */ + +-static uint64_t round_to_uint_and_pack(FloatParts in, int rmode, int scale, +- uint64_t max, float_status *s) ++static uint64_t round_to_uint_and_pack(FloatParts in, FloatRoundMode rmode, ++ int scale, uint64_t max, ++ float_status *s) + { + int orig_flags = get_float_exception_flags(s); + FloatParts p = round_to_int(in, rmode, scale, s); +@@ -2319,63 +2322,63 @@ static uint64_t round_to_uint_and_pack(FloatParts in, int rmode, int scale, + } + } + +-uint16_t float16_to_uint16_scalbn(float16 a, int rmode, int scale, ++uint16_t float16_to_uint16_scalbn(float16 a, FloatRoundMode rmode, int scale, + float_status *s) + { + return round_to_uint_and_pack(float16_unpack_canonical(a, s), + rmode, scale, UINT16_MAX, s); + } + +-uint32_t float16_to_uint32_scalbn(float16 a, int rmode, int scale, ++uint32_t float16_to_uint32_scalbn(float16 a, FloatRoundMode rmode, int scale, + float_status *s) + { + return round_to_uint_and_pack(float16_unpack_canonical(a, s), + rmode, scale, UINT32_MAX, s); + } + +-uint64_t float16_to_uint64_scalbn(float16 a, int rmode, int scale, ++uint64_t float16_to_uint64_scalbn(float16 a, FloatRoundMode rmode, int scale, + float_status *s) + { + return round_to_uint_and_pack(float16_unpack_canonical(a, s), + rmode, scale, UINT64_MAX, s); + } + +-uint16_t float32_to_uint16_scalbn(float32 a, int rmode, int scale, ++uint16_t float32_to_uint16_scalbn(float32 a, FloatRoundMode rmode, int scale, + float_status *s) + { + return round_to_uint_and_pack(float32_unpack_canonical(a, s), + rmode, scale, UINT16_MAX, s); + } + +-uint32_t float32_to_uint32_scalbn(float32 a, int rmode, int scale, ++uint32_t float32_to_uint32_scalbn(float32 a, FloatRoundMode rmode, int scale, + float_status *s) + { + return round_to_uint_and_pack(float32_unpack_canonical(a, s), + rmode, scale, UINT32_MAX, s); + } + +-uint64_t float32_to_uint64_scalbn(float32 a, int rmode, int scale, ++uint64_t float32_to_uint64_scalbn(float32 a, FloatRoundMode rmode, int scale, + float_status *s) + { + return round_to_uint_and_pack(float32_unpack_canonical(a, s), + rmode, scale, UINT64_MAX, s); + } + +-uint16_t float64_to_uint16_scalbn(float64 a, int rmode, int scale, ++uint16_t float64_to_uint16_scalbn(float64 a, FloatRoundMode rmode, int scale, + float_status *s) + { + return round_to_uint_and_pack(float64_unpack_canonical(a, s), + rmode, scale, UINT16_MAX, s); + } + +-uint32_t float64_to_uint32_scalbn(float64 a, int rmode, int scale, ++uint32_t float64_to_uint32_scalbn(float64 a, FloatRoundMode rmode, int scale, + float_status *s) + { + return round_to_uint_and_pack(float64_unpack_canonical(a, s), + rmode, scale, UINT32_MAX, s); + } + +-uint64_t float64_to_uint64_scalbn(float64 a, int rmode, int scale, ++uint64_t float64_to_uint64_scalbn(float64 a, FloatRoundMode rmode, int scale, + float_status *s) + { + return round_to_uint_and_pack(float64_unpack_canonical(a, s), +@@ -5715,6 +5718,11 @@ floatx80 floatx80_round_to_int(floatx80 a, float_status *status) + return + aSign ? packFloatx80( 1, 0, 0 ) + : packFloatx80( 0, 0x3FFF, UINT64_C(0x8000000000000000)); ++ ++ case float_round_to_zero: ++ break; ++ default: ++ g_assert_not_reached(); + } + return packFloatx80( aSign, 0, 0 ); + } +@@ -7047,6 +7055,9 @@ float128 float128_round_to_int(float128 a, float_status *status) + + case float_round_to_odd: + return packFloat128(aSign, 0x3FFF, 0, 0); ++ ++ case float_round_to_zero: ++ break; + } + return packFloat128( aSign, 0, 0, 0 ); + } +diff --git a/include/fpu/softfloat-helpers.h b/include/fpu/softfloat-helpers.h +index 40d32a6d5d..735ed6b653 100644 +--- a/include/fpu/softfloat-helpers.h ++++ b/include/fpu/softfloat-helpers.h +@@ -58,7 +58,8 @@ static inline void set_float_detect_tininess(bool val, float_status *status) + status->tininess_before_rounding = val; + } + +-static inline void set_float_rounding_mode(int val, float_status *status) ++static inline void set_float_rounding_mode(FloatRoundMode val, ++ float_status *status) + { + status->float_rounding_mode = val; + } +@@ -99,7 +100,7 @@ static inline bool get_float_detect_tininess(float_status *status) + return status->tininess_before_rounding; + } + +-static inline int get_float_rounding_mode(float_status *status) ++static inline FloatRoundMode get_float_rounding_mode(float_status *status) + { + return status->float_rounding_mode; + } +diff --git a/include/fpu/softfloat-types.h b/include/fpu/softfloat-types.h +index 874ddd9f93..7680193ebc 100644 +--- a/include/fpu/softfloat-types.h ++++ b/include/fpu/softfloat-types.h +@@ -123,7 +123,7 @@ typedef struct { + *Software IEC/IEEE floating-point rounding mode. + */ + +-enum { ++typedef enum __attribute__((__packed__)) { + float_round_nearest_even = 0, + float_round_down = 1, + float_round_up = 2, +@@ -131,7 +131,7 @@ enum { + float_round_ties_away = 4, + /* Not an IEEE rounding mode: round to the closest odd mantissa value */ + float_round_to_odd = 5, +-}; ++} FloatRoundMode; + + /* + * Software IEC/IEEE floating-point exception flags. +@@ -156,7 +156,7 @@ enum { + */ + + typedef struct float_status { +- signed char float_rounding_mode; ++ FloatRoundMode float_rounding_mode; + uint8_t float_exception_flags; + signed char floatx80_rounding_precision; + bool tininess_before_rounding; +diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h +index 3f588da7c7..ca75f764aa 100644 +--- a/include/fpu/softfloat.h ++++ b/include/fpu/softfloat.h +@@ -186,9 +186,9 @@ float32 float16_to_float32(float16, bool ieee, float_status *status); + float16 float64_to_float16(float64 a, bool ieee, float_status *status); + float64 float16_to_float64(float16 a, bool ieee, float_status *status); + +-int16_t float16_to_int16_scalbn(float16, int, int, float_status *status); +-int32_t float16_to_int32_scalbn(float16, int, int, float_status *status); +-int64_t float16_to_int64_scalbn(float16, int, int, float_status *status); ++int16_t float16_to_int16_scalbn(float16, FloatRoundMode, int, float_status *); ++int32_t float16_to_int32_scalbn(float16, FloatRoundMode, int, float_status *); ++int64_t float16_to_int64_scalbn(float16, FloatRoundMode, int, float_status *); + + int16_t float16_to_int16(float16, float_status *status); + int32_t float16_to_int32(float16, float_status *status); +@@ -198,9 +198,12 @@ int16_t float16_to_int16_round_to_zero(float16, float_status *status); + int32_t float16_to_int32_round_to_zero(float16, float_status *status); + int64_t float16_to_int64_round_to_zero(float16, float_status *status); + +-uint16_t float16_to_uint16_scalbn(float16 a, int, int, float_status *status); +-uint32_t float16_to_uint32_scalbn(float16 a, int, int, float_status *status); +-uint64_t float16_to_uint64_scalbn(float16 a, int, int, float_status *status); ++uint16_t float16_to_uint16_scalbn(float16 a, FloatRoundMode, ++ int, float_status *status); ++uint32_t float16_to_uint32_scalbn(float16 a, FloatRoundMode, ++ int, float_status *status); ++uint64_t float16_to_uint64_scalbn(float16 a, FloatRoundMode, ++ int, float_status *status); + + uint16_t float16_to_uint16(float16 a, float_status *status); + uint32_t float16_to_uint32(float16 a, float_status *status); +@@ -298,9 +301,9 @@ float16 float16_default_nan(float_status *status); + | Software IEC/IEEE single-precision conversion routines. + *----------------------------------------------------------------------------*/ + +-int16_t float32_to_int16_scalbn(float32, int, int, float_status *status); +-int32_t float32_to_int32_scalbn(float32, int, int, float_status *status); +-int64_t float32_to_int64_scalbn(float32, int, int, float_status *status); ++int16_t float32_to_int16_scalbn(float32, FloatRoundMode, int, float_status *); ++int32_t float32_to_int32_scalbn(float32, FloatRoundMode, int, float_status *); ++int64_t float32_to_int64_scalbn(float32, FloatRoundMode, int, float_status *); + + int16_t float32_to_int16(float32, float_status *status); + int32_t float32_to_int32(float32, float_status *status); +@@ -310,9 +313,9 @@ int16_t float32_to_int16_round_to_zero(float32, float_status *status); + int32_t float32_to_int32_round_to_zero(float32, float_status *status); + int64_t float32_to_int64_round_to_zero(float32, float_status *status); + +-uint16_t float32_to_uint16_scalbn(float32, int, int, float_status *status); +-uint32_t float32_to_uint32_scalbn(float32, int, int, float_status *status); +-uint64_t float32_to_uint64_scalbn(float32, int, int, float_status *status); ++uint16_t float32_to_uint16_scalbn(float32, FloatRoundMode, int, float_status *); ++uint32_t float32_to_uint32_scalbn(float32, FloatRoundMode, int, float_status *); ++uint64_t float32_to_uint64_scalbn(float32, FloatRoundMode, int, float_status *); + + uint16_t float32_to_uint16(float32, float_status *status); + uint32_t float32_to_uint32(float32, float_status *status); +@@ -455,9 +458,9 @@ float32 float32_default_nan(float_status *status); + | Software IEC/IEEE double-precision conversion routines. + *----------------------------------------------------------------------------*/ + +-int16_t float64_to_int16_scalbn(float64, int, int, float_status *status); +-int32_t float64_to_int32_scalbn(float64, int, int, float_status *status); +-int64_t float64_to_int64_scalbn(float64, int, int, float_status *status); ++int16_t float64_to_int16_scalbn(float64, FloatRoundMode, int, float_status *); ++int32_t float64_to_int32_scalbn(float64, FloatRoundMode, int, float_status *); ++int64_t float64_to_int64_scalbn(float64, FloatRoundMode, int, float_status *); + + int16_t float64_to_int16(float64, float_status *status); + int32_t float64_to_int32(float64, float_status *status); +@@ -467,9 +470,9 @@ int16_t float64_to_int16_round_to_zero(float64, float_status *status); + int32_t float64_to_int32_round_to_zero(float64, float_status *status); + int64_t float64_to_int64_round_to_zero(float64, float_status *status); + +-uint16_t float64_to_uint16_scalbn(float64, int, int, float_status *status); +-uint32_t float64_to_uint32_scalbn(float64, int, int, float_status *status); +-uint64_t float64_to_uint64_scalbn(float64, int, int, float_status *status); ++uint16_t float64_to_uint16_scalbn(float64, FloatRoundMode, int, float_status *); ++uint32_t float64_to_uint32_scalbn(float64, FloatRoundMode, int, float_status *); ++uint64_t float64_to_uint64_scalbn(float64, FloatRoundMode, int, float_status *); + + uint16_t float64_to_uint16(float64, float_status *status); + uint32_t float64_to_uint32(float64, float_status *status); +diff --git a/target/arm/vfp_helper.c b/target/arm/vfp_helper.c +index 42625747d1..0920694764 100644 +--- a/target/arm/vfp_helper.c ++++ b/target/arm/vfp_helper.c +@@ -697,9 +697,9 @@ static bool round_to_inf(float_status *fpst, bool sign_bit) + return sign_bit; + case float_round_to_zero: /* Round to Zero */ + return false; ++ default: ++ g_assert_not_reached(); + } +- +- g_assert_not_reached(); + } + + uint32_t HELPER(recpe_f16)(uint32_t input, void *fpstp) +diff --git a/target/m68k/fpu_helper.c b/target/m68k/fpu_helper.c +index 4137542ec0..36e6c704d1 100644 +--- a/target/m68k/fpu_helper.c ++++ b/target/m68k/fpu_helper.c +@@ -149,7 +149,7 @@ void cpu_m68k_set_fpcr(CPUM68KState *env, uint32_t val) + + void HELPER(fitrunc)(CPUM68KState *env, FPReg *res, FPReg *val) + { +- int rounding_mode = get_float_rounding_mode(&env->fp_status); ++ FloatRoundMode rounding_mode = get_float_rounding_mode(&env->fp_status); + set_float_rounding_mode(float_round_to_zero, &env->fp_status); + res->d = floatx80_round_to_int(val->d, &env->fp_status); + set_float_rounding_mode(rounding_mode, &env->fp_status); +@@ -300,7 +300,7 @@ void HELPER(fdmul)(CPUM68KState *env, FPReg *res, FPReg *val0, FPReg *val1) + + void HELPER(fsglmul)(CPUM68KState *env, FPReg *res, FPReg *val0, FPReg *val1) + { +- int rounding_mode = get_float_rounding_mode(&env->fp_status); ++ FloatRoundMode rounding_mode = get_float_rounding_mode(&env->fp_status); + floatx80 a, b; + + PREC_BEGIN(32); +@@ -333,7 +333,7 @@ void HELPER(fddiv)(CPUM68KState *env, FPReg *res, FPReg *val0, FPReg *val1) + + void HELPER(fsgldiv)(CPUM68KState *env, FPReg *res, FPReg *val0, FPReg *val1) + { +- int rounding_mode = get_float_rounding_mode(&env->fp_status); ++ FloatRoundMode rounding_mode = get_float_rounding_mode(&env->fp_status); + floatx80 a, b; + + PREC_BEGIN(32); +-- +2.23.0 + diff --git a/softfloat-Replace-flag-with-bool.patch b/softfloat-Replace-flag-with-bool.patch new file mode 100644 index 0000000000000000000000000000000000000000..56a1478bef9fec30111d3f52687d462efe3de5d1 --- /dev/null +++ b/softfloat-Replace-flag-with-bool.patch @@ -0,0 +1,1531 @@ +From c120391c0090d9c40425c92cdb00f38ea8588ff6 Mon Sep 17 00:00:00 2001 +From: Richard Henderson +Date: Mon, 4 May 2020 19:54:57 -0700 +Subject: [PATCH 593/709] softfloat: Replace flag with bool +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +We have had this on the to-do list for quite some time. + +Reviewed-by: Alex Bennée +Reviewed-by: Philippe Mathieu-Daudé +Signed-off-by: Richard Henderson +--- + fpu/softfloat-specialize.inc.c | 16 +-- + fpu/softfloat.c | 190 ++++++++++++++++---------------- + include/fpu/softfloat-helpers.h | 14 +-- + include/fpu/softfloat-macros.h | 24 ++-- + include/fpu/softfloat-types.h | 14 +-- + include/fpu/softfloat.h | 10 +- + target/arm/sve_helper.c | 8 +- + target/arm/vfp_helper.c | 8 +- + target/m68k/softfloat.c | 70 ++++++------ + target/mips/msa_helper.c | 10 +- + 10 files changed, 174 insertions(+), 190 deletions(-) + +diff --git a/fpu/softfloat-specialize.inc.c b/fpu/softfloat-specialize.inc.c +index 5ab2fa1941..025ee4f991 100644 +--- a/fpu/softfloat-specialize.inc.c ++++ b/fpu/softfloat-specialize.inc.c +@@ -93,7 +93,7 @@ this code that are retained. + * 2008 revision and backward compatibility with their original choice. + * Thus for MIPS we must make the choice at runtime. + */ +-static inline flag snan_bit_is_one(float_status *status) ++static inline bool snan_bit_is_one(float_status *status) + { + #if defined(TARGET_MIPS) + return status->snan_bit_is_one; +@@ -114,7 +114,7 @@ static bool parts_is_snan_frac(uint64_t frac, float_status *status) + #ifdef NO_SIGNALING_NANS + return false; + #else +- flag msb = extract64(frac, DECOMPOSED_BINARY_POINT - 1, 1); ++ bool msb = extract64(frac, DECOMPOSED_BINARY_POINT - 1, 1); + return msb == snan_bit_is_one(status); + #endif + } +@@ -236,7 +236,7 @@ void float_raise(uint8_t flags, float_status *status) + | Internal canonical NaN format. + *----------------------------------------------------------------------------*/ + typedef struct { +- flag sign; ++ bool sign; + uint64_t high, low; + } commonNaNT; + +@@ -374,7 +374,7 @@ static float32 commonNaNToFloat32(commonNaNT a, float_status *status) + *----------------------------------------------------------------------------*/ + + static int pickNaN(FloatClass a_cls, FloatClass b_cls, +- flag aIsLargerSignificand) ++ bool aIsLargerSignificand) + { + #if defined(TARGET_ARM) || defined(TARGET_MIPS) || defined(TARGET_HPPA) + /* ARM mandated NaN propagation rules (see FPProcessNaNs()), take +@@ -584,7 +584,7 @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls, + + static float32 propagateFloat32NaN(float32 a, float32 b, float_status *status) + { +- flag aIsLargerSignificand; ++ bool aIsLargerSignificand; + uint32_t av, bv; + FloatClass a_cls, b_cls; + +@@ -722,7 +722,7 @@ static float64 commonNaNToFloat64(commonNaNT a, float_status *status) + + static float64 propagateFloat64NaN(float64 a, float64 b, float_status *status) + { +- flag aIsLargerSignificand; ++ bool aIsLargerSignificand; + uint64_t av, bv; + FloatClass a_cls, b_cls; + +@@ -890,7 +890,7 @@ static floatx80 commonNaNToFloatx80(commonNaNT a, float_status *status) + + floatx80 propagateFloatx80NaN(floatx80 a, floatx80 b, float_status *status) + { +- flag aIsLargerSignificand; ++ bool aIsLargerSignificand; + FloatClass a_cls, b_cls; + + /* This is not complete, but is good enough for pickNaN. */ +@@ -1038,7 +1038,7 @@ static float128 commonNaNToFloat128(commonNaNT a, float_status *status) + static float128 propagateFloat128NaN(float128 a, float128 b, + float_status *status) + { +- flag aIsLargerSignificand; ++ bool aIsLargerSignificand; + FloatClass a_cls, b_cls; + + /* This is not complete, but is good enough for pickNaN. */ +diff --git a/fpu/softfloat.c b/fpu/softfloat.c +index 5fb4ef75bb..b741cf5bc3 100644 +--- a/fpu/softfloat.c ++++ b/fpu/softfloat.c +@@ -423,7 +423,7 @@ static inline int extractFloat32Exp(float32 a) + | Returns the sign bit of the single-precision floating-point value `a'. + *----------------------------------------------------------------------------*/ + +-static inline flag extractFloat32Sign(float32 a) ++static inline bool extractFloat32Sign(float32 a) + { + return float32_val(a) >> 31; + } +@@ -450,7 +450,7 @@ static inline int extractFloat64Exp(float64 a) + | Returns the sign bit of the double-precision floating-point value `a'. + *----------------------------------------------------------------------------*/ + +-static inline flag extractFloat64Sign(float64 a) ++static inline bool extractFloat64Sign(float64 a) + { + return float64_val(a) >> 63; + } +@@ -3328,10 +3328,11 @@ float64 float64_squash_input_denormal(float64 a, float_status *status) + | positive or negative integer is returned. + *----------------------------------------------------------------------------*/ + +-static int32_t roundAndPackInt32(flag zSign, uint64_t absZ, float_status *status) ++static int32_t roundAndPackInt32(bool zSign, uint64_t absZ, ++ float_status *status) + { + int8_t roundingMode; +- flag roundNearestEven; ++ bool roundNearestEven; + int8_t roundIncrement, roundBits; + int32_t z; + +@@ -3385,11 +3386,11 @@ static int32_t roundAndPackInt32(flag zSign, uint64_t absZ, float_status *status + | returned. + *----------------------------------------------------------------------------*/ + +-static int64_t roundAndPackInt64(flag zSign, uint64_t absZ0, uint64_t absZ1, ++static int64_t roundAndPackInt64(bool zSign, uint64_t absZ0, uint64_t absZ1, + float_status *status) + { + int8_t roundingMode; +- flag roundNearestEven, increment; ++ bool roundNearestEven, increment; + int64_t z; + + roundingMode = status->float_rounding_mode; +@@ -3443,11 +3444,11 @@ static int64_t roundAndPackInt64(flag zSign, uint64_t absZ0, uint64_t absZ1, + | exception is raised and the largest unsigned integer is returned. + *----------------------------------------------------------------------------*/ + +-static int64_t roundAndPackUint64(flag zSign, uint64_t absZ0, ++static int64_t roundAndPackUint64(bool zSign, uint64_t absZ0, + uint64_t absZ1, float_status *status) + { + int8_t roundingMode; +- flag roundNearestEven, increment; ++ bool roundNearestEven, increment; + + roundingMode = status->float_rounding_mode; + roundNearestEven = (roundingMode == float_round_nearest_even); +@@ -3531,13 +3532,13 @@ static void + | Binary Floating-Point Arithmetic. + *----------------------------------------------------------------------------*/ + +-static float32 roundAndPackFloat32(flag zSign, int zExp, uint32_t zSig, ++static float32 roundAndPackFloat32(bool zSign, int zExp, uint32_t zSig, + float_status *status) + { + int8_t roundingMode; +- flag roundNearestEven; ++ bool roundNearestEven; + int8_t roundIncrement, roundBits; +- flag isTiny; ++ bool isTiny; + + roundingMode = status->float_rounding_mode; + roundNearestEven = ( roundingMode == float_round_nearest_even ); +@@ -3618,7 +3619,7 @@ static float32 roundAndPackFloat32(flag zSign, int zExp, uint32_t zSig, + *----------------------------------------------------------------------------*/ + + static float32 +- normalizeRoundAndPackFloat32(flag zSign, int zExp, uint32_t zSig, ++ normalizeRoundAndPackFloat32(bool zSign, int zExp, uint32_t zSig, + float_status *status) + { + int8_t shiftCount; +@@ -3658,7 +3659,7 @@ static void + | significand. + *----------------------------------------------------------------------------*/ + +-static inline float64 packFloat64(flag zSign, int zExp, uint64_t zSig) ++static inline float64 packFloat64(bool zSign, int zExp, uint64_t zSig) + { + + return make_float64( +@@ -3688,13 +3689,13 @@ static inline float64 packFloat64(flag zSign, int zExp, uint64_t zSig) + | Binary Floating-Point Arithmetic. + *----------------------------------------------------------------------------*/ + +-static float64 roundAndPackFloat64(flag zSign, int zExp, uint64_t zSig, ++static float64 roundAndPackFloat64(bool zSign, int zExp, uint64_t zSig, + float_status *status) + { + int8_t roundingMode; +- flag roundNearestEven; ++ bool roundNearestEven; + int roundIncrement, roundBits; +- flag isTiny; ++ bool isTiny; + + roundingMode = status->float_rounding_mode; + roundNearestEven = ( roundingMode == float_round_nearest_even ); +@@ -3774,7 +3775,7 @@ static float64 roundAndPackFloat64(flag zSign, int zExp, uint64_t zSig, + *----------------------------------------------------------------------------*/ + + static float64 +- normalizeRoundAndPackFloat64(flag zSign, int zExp, uint64_t zSig, ++ normalizeRoundAndPackFloat64(bool zSign, int zExp, uint64_t zSig, + float_status *status) + { + int8_t shiftCount; +@@ -3826,12 +3827,12 @@ void normalizeFloatx80Subnormal(uint64_t aSig, int32_t *zExpPtr, + | Floating-Point Arithmetic. + *----------------------------------------------------------------------------*/ + +-floatx80 roundAndPackFloatx80(int8_t roundingPrecision, flag zSign, ++floatx80 roundAndPackFloatx80(int8_t roundingPrecision, bool zSign, + int32_t zExp, uint64_t zSig0, uint64_t zSig1, + float_status *status) + { + int8_t roundingMode; +- flag roundNearestEven, increment, isTiny; ++ bool roundNearestEven, increment, isTiny; + int64_t roundIncrement, roundMask, roundBits; + + roundingMode = status->float_rounding_mode; +@@ -4025,7 +4026,7 @@ floatx80 roundAndPackFloatx80(int8_t roundingPrecision, flag zSign, + *----------------------------------------------------------------------------*/ + + floatx80 normalizeRoundAndPackFloatx80(int8_t roundingPrecision, +- flag zSign, int32_t zExp, ++ bool zSign, int32_t zExp, + uint64_t zSig0, uint64_t zSig1, + float_status *status) + { +@@ -4084,11 +4085,9 @@ static inline int32_t extractFloat128Exp( float128 a ) + | Returns the sign bit of the quadruple-precision floating-point value `a'. + *----------------------------------------------------------------------------*/ + +-static inline flag extractFloat128Sign( float128 a ) ++static inline bool extractFloat128Sign(float128 a) + { +- +- return a.high>>63; +- ++ return a.high >> 63; + } + + /*---------------------------------------------------------------------------- +@@ -4146,14 +4145,13 @@ static void + *----------------------------------------------------------------------------*/ + + static inline float128 +- packFloat128( flag zSign, int32_t zExp, uint64_t zSig0, uint64_t zSig1 ) ++packFloat128(bool zSign, int32_t zExp, uint64_t zSig0, uint64_t zSig1) + { + float128 z; + + z.low = zSig1; +- z.high = ( ( (uint64_t) zSign )<<63 ) + ( ( (uint64_t) zExp )<<48 ) + zSig0; ++ z.high = ((uint64_t)zSign << 63) + ((uint64_t)zExp << 48) + zSig0; + return z; +- + } + + /*---------------------------------------------------------------------------- +@@ -4177,12 +4175,12 @@ static inline float128 + | overflow follows the IEC/IEEE Standard for Binary Floating-Point Arithmetic. + *----------------------------------------------------------------------------*/ + +-static float128 roundAndPackFloat128(flag zSign, int32_t zExp, ++static float128 roundAndPackFloat128(bool zSign, int32_t zExp, + uint64_t zSig0, uint64_t zSig1, + uint64_t zSig2, float_status *status) + { + int8_t roundingMode; +- flag roundNearestEven, increment, isTiny; ++ bool roundNearestEven, increment, isTiny; + + roundingMode = status->float_rounding_mode; + roundNearestEven = ( roundingMode == float_round_nearest_even ); +@@ -4302,7 +4300,7 @@ static float128 roundAndPackFloat128(flag zSign, int32_t zExp, + | point exponent. + *----------------------------------------------------------------------------*/ + +-static float128 normalizeRoundAndPackFloat128(flag zSign, int32_t zExp, ++static float128 normalizeRoundAndPackFloat128(bool zSign, int32_t zExp, + uint64_t zSig0, uint64_t zSig1, + float_status *status) + { +@@ -4338,7 +4336,7 @@ static float128 normalizeRoundAndPackFloat128(flag zSign, int32_t zExp, + + floatx80 int32_to_floatx80(int32_t a, float_status *status) + { +- flag zSign; ++ bool zSign; + uint32_t absA; + int8_t shiftCount; + uint64_t zSig; +@@ -4360,7 +4358,7 @@ floatx80 int32_to_floatx80(int32_t a, float_status *status) + + float128 int32_to_float128(int32_t a, float_status *status) + { +- flag zSign; ++ bool zSign; + uint32_t absA; + int8_t shiftCount; + uint64_t zSig0; +@@ -4383,7 +4381,7 @@ float128 int32_to_float128(int32_t a, float_status *status) + + floatx80 int64_to_floatx80(int64_t a, float_status *status) + { +- flag zSign; ++ bool zSign; + uint64_t absA; + int8_t shiftCount; + +@@ -4403,7 +4401,7 @@ floatx80 int64_to_floatx80(int64_t a, float_status *status) + + float128 int64_to_float128(int64_t a, float_status *status) + { +- flag zSign; ++ bool zSign; + uint64_t absA; + int8_t shiftCount; + int32_t zExp; +@@ -4451,7 +4449,7 @@ float128 uint64_to_float128(uint64_t a, float_status *status) + + floatx80 float32_to_floatx80(float32 a, float_status *status) + { +- flag aSign; ++ bool aSign; + int aExp; + uint32_t aSig; + +@@ -4487,7 +4485,7 @@ floatx80 float32_to_floatx80(float32 a, float_status *status) + + float128 float32_to_float128(float32 a, float_status *status) + { +- flag aSign; ++ bool aSign; + int aExp; + uint32_t aSig; + +@@ -4518,7 +4516,7 @@ float128 float32_to_float128(float32 a, float_status *status) + + float32 float32_rem(float32 a, float32 b, float_status *status) + { +- flag aSign, zSign; ++ bool aSign, zSign; + int aExp, bExp, expDiff; + uint32_t aSig, bSig; + uint32_t q; +@@ -4653,7 +4651,7 @@ static const float64 float32_exp2_coefficients[15] = + + float32 float32_exp2(float32 a, float_status *status) + { +- flag aSign; ++ bool aSign; + int aExp; + uint32_t aSig; + float64 r, x, xn; +@@ -4703,7 +4701,7 @@ float32 float32_exp2(float32 a, float_status *status) + *----------------------------------------------------------------------------*/ + float32 float32_log2(float32 a, float_status *status) + { +- flag aSign, zSign; ++ bool aSign, zSign; + int aExp; + uint32_t aSig, zSig, i; + +@@ -4779,7 +4777,7 @@ int float32_eq(float32 a, float32 b, float_status *status) + + int float32_le(float32 a, float32 b, float_status *status) + { +- flag aSign, bSign; ++ bool aSign, bSign; + uint32_t av, bv; + a = float32_squash_input_denormal(a, status); + b = float32_squash_input_denormal(b, status); +@@ -4808,7 +4806,7 @@ int float32_le(float32 a, float32 b, float_status *status) + + int float32_lt(float32 a, float32 b, float_status *status) + { +- flag aSign, bSign; ++ bool aSign, bSign; + uint32_t av, bv; + a = float32_squash_input_denormal(a, status); + b = float32_squash_input_denormal(b, status); +@@ -4883,7 +4881,7 @@ int float32_eq_quiet(float32 a, float32 b, float_status *status) + + int float32_le_quiet(float32 a, float32 b, float_status *status) + { +- flag aSign, bSign; ++ bool aSign, bSign; + uint32_t av, bv; + a = float32_squash_input_denormal(a, status); + b = float32_squash_input_denormal(b, status); +@@ -4915,7 +4913,7 @@ int float32_le_quiet(float32 a, float32 b, float_status *status) + + int float32_lt_quiet(float32 a, float32 b, float_status *status) + { +- flag aSign, bSign; ++ bool aSign, bSign; + uint32_t av, bv; + a = float32_squash_input_denormal(a, status); + b = float32_squash_input_denormal(b, status); +@@ -4971,7 +4969,7 @@ int float32_unordered_quiet(float32 a, float32 b, float_status *status) + + floatx80 float64_to_floatx80(float64 a, float_status *status) + { +- flag aSign; ++ bool aSign; + int aExp; + uint64_t aSig; + +@@ -5008,7 +5006,7 @@ floatx80 float64_to_floatx80(float64 a, float_status *status) + + float128 float64_to_float128(float64 a, float_status *status) + { +- flag aSign; ++ bool aSign; + int aExp; + uint64_t aSig, zSig0, zSig1; + +@@ -5041,7 +5039,7 @@ float128 float64_to_float128(float64 a, float_status *status) + + float64 float64_rem(float64 a, float64 b, float_status *status) + { +- flag aSign, zSign; ++ bool aSign, zSign; + int aExp, bExp, expDiff; + uint64_t aSig, bSig; + uint64_t q, alternateASig; +@@ -5128,7 +5126,7 @@ float64 float64_rem(float64 a, float64 b, float_status *status) + *----------------------------------------------------------------------------*/ + float64 float64_log2(float64 a, float_status *status) + { +- flag aSign, zSign; ++ bool aSign, zSign; + int aExp; + uint64_t aSig, aSig0, aSig1, zSig, i; + a = float64_squash_input_denormal(a, status); +@@ -5204,7 +5202,7 @@ int float64_eq(float64 a, float64 b, float_status *status) + + int float64_le(float64 a, float64 b, float_status *status) + { +- flag aSign, bSign; ++ bool aSign, bSign; + uint64_t av, bv; + a = float64_squash_input_denormal(a, status); + b = float64_squash_input_denormal(b, status); +@@ -5233,7 +5231,7 @@ int float64_le(float64 a, float64 b, float_status *status) + + int float64_lt(float64 a, float64 b, float_status *status) + { +- flag aSign, bSign; ++ bool aSign, bSign; + uint64_t av, bv; + + a = float64_squash_input_denormal(a, status); +@@ -5311,7 +5309,7 @@ int float64_eq_quiet(float64 a, float64 b, float_status *status) + + int float64_le_quiet(float64 a, float64 b, float_status *status) + { +- flag aSign, bSign; ++ bool aSign, bSign; + uint64_t av, bv; + a = float64_squash_input_denormal(a, status); + b = float64_squash_input_denormal(b, status); +@@ -5343,7 +5341,7 @@ int float64_le_quiet(float64 a, float64 b, float_status *status) + + int float64_lt_quiet(float64 a, float64 b, float_status *status) + { +- flag aSign, bSign; ++ bool aSign, bSign; + uint64_t av, bv; + a = float64_squash_input_denormal(a, status); + b = float64_squash_input_denormal(b, status); +@@ -5402,7 +5400,7 @@ int float64_unordered_quiet(float64 a, float64 b, float_status *status) + + int32_t floatx80_to_int32(floatx80 a, float_status *status) + { +- flag aSign; ++ bool aSign; + int32_t aExp, shiftCount; + uint64_t aSig; + +@@ -5433,7 +5431,7 @@ int32_t floatx80_to_int32(floatx80 a, float_status *status) + + int32_t floatx80_to_int32_round_to_zero(floatx80 a, float_status *status) + { +- flag aSign; ++ bool aSign; + int32_t aExp, shiftCount; + uint64_t aSig, savedASig; + int32_t z; +@@ -5484,7 +5482,7 @@ int32_t floatx80_to_int32_round_to_zero(floatx80 a, float_status *status) + + int64_t floatx80_to_int64(floatx80 a, float_status *status) + { +- flag aSign; ++ bool aSign; + int32_t aExp, shiftCount; + uint64_t aSig, aSigExtra; + +@@ -5525,7 +5523,7 @@ int64_t floatx80_to_int64(floatx80 a, float_status *status) + + int64_t floatx80_to_int64_round_to_zero(floatx80 a, float_status *status) + { +- flag aSign; ++ bool aSign; + int32_t aExp, shiftCount; + uint64_t aSig; + int64_t z; +@@ -5572,7 +5570,7 @@ int64_t floatx80_to_int64_round_to_zero(floatx80 a, float_status *status) + + float32 floatx80_to_float32(floatx80 a, float_status *status) + { +- flag aSign; ++ bool aSign; + int32_t aExp; + uint64_t aSig; + +@@ -5606,7 +5604,7 @@ float32 floatx80_to_float32(floatx80 a, float_status *status) + + float64 floatx80_to_float64(floatx80 a, float_status *status) + { +- flag aSign; ++ bool aSign; + int32_t aExp; + uint64_t aSig, zSig; + +@@ -5640,7 +5638,7 @@ float64 floatx80_to_float64(floatx80 a, float_status *status) + + float128 floatx80_to_float128(floatx80 a, float_status *status) + { +- flag aSign; ++ bool aSign; + int aExp; + uint64_t aSig, zSig0, zSig1; + +@@ -5686,7 +5684,7 @@ floatx80 floatx80_round(floatx80 a, float_status *status) + + floatx80 floatx80_round_to_int(floatx80 a, float_status *status) + { +- flag aSign; ++ bool aSign; + int32_t aExp; + uint64_t lastBitMask, roundBitsMask; + floatx80 z; +@@ -5783,7 +5781,7 @@ floatx80 floatx80_round_to_int(floatx80 a, float_status *status) + | Floating-Point Arithmetic. + *----------------------------------------------------------------------------*/ + +-static floatx80 addFloatx80Sigs(floatx80 a, floatx80 b, flag zSign, ++static floatx80 addFloatx80Sigs(floatx80 a, floatx80 b, bool zSign, + float_status *status) + { + int32_t aExp, bExp, zExp; +@@ -5863,7 +5861,7 @@ static floatx80 addFloatx80Sigs(floatx80 a, floatx80 b, flag zSign, + | Standard for Binary Floating-Point Arithmetic. + *----------------------------------------------------------------------------*/ + +-static floatx80 subFloatx80Sigs(floatx80 a, floatx80 b, flag zSign, ++static floatx80 subFloatx80Sigs(floatx80 a, floatx80 b, bool zSign, + float_status *status) + { + int32_t aExp, bExp, zExp; +@@ -5932,7 +5930,7 @@ static floatx80 subFloatx80Sigs(floatx80 a, floatx80 b, flag zSign, + + floatx80 floatx80_add(floatx80 a, floatx80 b, float_status *status) + { +- flag aSign, bSign; ++ bool aSign, bSign; + + if (floatx80_invalid_encoding(a) || floatx80_invalid_encoding(b)) { + float_raise(float_flag_invalid, status); +@@ -5957,7 +5955,7 @@ floatx80 floatx80_add(floatx80 a, floatx80 b, float_status *status) + + floatx80 floatx80_sub(floatx80 a, floatx80 b, float_status *status) + { +- flag aSign, bSign; ++ bool aSign, bSign; + + if (floatx80_invalid_encoding(a) || floatx80_invalid_encoding(b)) { + float_raise(float_flag_invalid, status); +@@ -5982,7 +5980,7 @@ floatx80 floatx80_sub(floatx80 a, floatx80 b, float_status *status) + + floatx80 floatx80_mul(floatx80 a, floatx80 b, float_status *status) + { +- flag aSign, bSign, zSign; ++ bool aSign, bSign, zSign; + int32_t aExp, bExp, zExp; + uint64_t aSig, bSig, zSig0, zSig1; + +@@ -6044,7 +6042,7 @@ floatx80 floatx80_mul(floatx80 a, floatx80 b, float_status *status) + + floatx80 floatx80_div(floatx80 a, floatx80 b, float_status *status) + { +- flag aSign, bSign, zSign; ++ bool aSign, bSign, zSign; + int32_t aExp, bExp, zExp; + uint64_t aSig, bSig, zSig0, zSig1; + uint64_t rem0, rem1, rem2, term0, term1, term2; +@@ -6131,7 +6129,7 @@ floatx80 floatx80_div(floatx80 a, floatx80 b, float_status *status) + + floatx80 floatx80_rem(floatx80 a, floatx80 b, float_status *status) + { +- flag aSign, zSign; ++ bool aSign, zSign; + int32_t aExp, bExp, expDiff; + uint64_t aSig0, aSig1, bSig; + uint64_t q, term0, term1, alternateASig0, alternateASig1; +@@ -6230,7 +6228,7 @@ floatx80 floatx80_rem(floatx80 a, floatx80 b, float_status *status) + + floatx80 floatx80_sqrt(floatx80 a, float_status *status) + { +- flag aSign; ++ bool aSign; + int32_t aExp, zExp; + uint64_t aSig0, aSig1, zSig0, zSig1, doubleZSig0; + uint64_t rem0, rem1, rem2, rem3, term0, term1, term2, term3; +@@ -6331,7 +6329,7 @@ int floatx80_eq(floatx80 a, floatx80 b, float_status *status) + + int floatx80_le(floatx80 a, floatx80 b, float_status *status) + { +- flag aSign, bSign; ++ bool aSign, bSign; + + if (floatx80_invalid_encoding(a) || floatx80_invalid_encoding(b) + || (extractFloatx80Exp(a) == 0x7FFF +@@ -6365,7 +6363,7 @@ int floatx80_le(floatx80 a, floatx80 b, float_status *status) + + int floatx80_lt(floatx80 a, floatx80 b, float_status *status) + { +- flag aSign, bSign; ++ bool aSign, bSign; + + if (floatx80_invalid_encoding(a) || floatx80_invalid_encoding(b) + || (extractFloatx80Exp(a) == 0x7FFF +@@ -6453,7 +6451,7 @@ int floatx80_eq_quiet(floatx80 a, floatx80 b, float_status *status) + + int floatx80_le_quiet(floatx80 a, floatx80 b, float_status *status) + { +- flag aSign, bSign; ++ bool aSign, bSign; + + if (floatx80_invalid_encoding(a) || floatx80_invalid_encoding(b)) { + float_raise(float_flag_invalid, status); +@@ -6493,7 +6491,7 @@ int floatx80_le_quiet(floatx80 a, floatx80 b, float_status *status) + + int floatx80_lt_quiet(floatx80 a, floatx80 b, float_status *status) + { +- flag aSign, bSign; ++ bool aSign, bSign; + + if (floatx80_invalid_encoding(a) || floatx80_invalid_encoding(b)) { + float_raise(float_flag_invalid, status); +@@ -6562,7 +6560,7 @@ int floatx80_unordered_quiet(floatx80 a, floatx80 b, float_status *status) + + int32_t float128_to_int32(float128 a, float_status *status) + { +- flag aSign; ++ bool aSign; + int32_t aExp, shiftCount; + uint64_t aSig0, aSig1; + +@@ -6591,7 +6589,7 @@ int32_t float128_to_int32(float128 a, float_status *status) + + int32_t float128_to_int32_round_to_zero(float128 a, float_status *status) + { +- flag aSign; ++ bool aSign; + int32_t aExp, shiftCount; + uint64_t aSig0, aSig1, savedASig; + int32_t z; +@@ -6641,7 +6639,7 @@ int32_t float128_to_int32_round_to_zero(float128 a, float_status *status) + + int64_t float128_to_int64(float128 a, float_status *status) + { +- flag aSign; ++ bool aSign; + int32_t aExp, shiftCount; + uint64_t aSig0, aSig1; + +@@ -6684,7 +6682,7 @@ int64_t float128_to_int64(float128 a, float_status *status) + + int64_t float128_to_int64_round_to_zero(float128 a, float_status *status) + { +- flag aSign; ++ bool aSign; + int32_t aExp, shiftCount; + uint64_t aSig0, aSig1; + int64_t z; +@@ -6749,7 +6747,7 @@ int64_t float128_to_int64_round_to_zero(float128 a, float_status *status) + + uint64_t float128_to_uint64(float128 a, float_status *status) + { +- flag aSign; ++ bool aSign; + int aExp; + int shiftCount; + uint64_t aSig0, aSig1; +@@ -6860,7 +6858,7 @@ uint32_t float128_to_uint32(float128 a, float_status *status) + + float32 float128_to_float32(float128 a, float_status *status) + { +- flag aSign; ++ bool aSign; + int32_t aExp; + uint64_t aSig0, aSig1; + uint32_t zSig; +@@ -6895,7 +6893,7 @@ float32 float128_to_float32(float128 a, float_status *status) + + float64 float128_to_float64(float128 a, float_status *status) + { +- flag aSign; ++ bool aSign; + int32_t aExp; + uint64_t aSig0, aSig1; + +@@ -6928,7 +6926,7 @@ float64 float128_to_float64(float128 a, float_status *status) + + floatx80 float128_to_floatx80(float128 a, float_status *status) + { +- flag aSign; ++ bool aSign; + int32_t aExp; + uint64_t aSig0, aSig1; + +@@ -6966,7 +6964,7 @@ floatx80 float128_to_floatx80(float128 a, float_status *status) + + float128 float128_round_to_int(float128 a, float_status *status) + { +- flag aSign; ++ bool aSign; + int32_t aExp; + uint64_t lastBitMask, roundBitsMask; + float128 z; +@@ -7121,7 +7119,7 @@ float128 float128_round_to_int(float128 a, float_status *status) + | Floating-Point Arithmetic. + *----------------------------------------------------------------------------*/ + +-static float128 addFloat128Sigs(float128 a, float128 b, flag zSign, ++static float128 addFloat128Sigs(float128 a, float128 b, bool zSign, + float_status *status) + { + int32_t aExp, bExp, zExp; +@@ -7212,7 +7210,7 @@ static float128 addFloat128Sigs(float128 a, float128 b, flag zSign, + | Standard for Binary Floating-Point Arithmetic. + *----------------------------------------------------------------------------*/ + +-static float128 subFloat128Sigs(float128 a, float128 b, flag zSign, ++static float128 subFloat128Sigs(float128 a, float128 b, bool zSign, + float_status *status) + { + int32_t aExp, bExp, zExp; +@@ -7300,7 +7298,7 @@ static float128 subFloat128Sigs(float128 a, float128 b, flag zSign, + + float128 float128_add(float128 a, float128 b, float_status *status) + { +- flag aSign, bSign; ++ bool aSign, bSign; + + aSign = extractFloat128Sign( a ); + bSign = extractFloat128Sign( b ); +@@ -7321,7 +7319,7 @@ float128 float128_add(float128 a, float128 b, float_status *status) + + float128 float128_sub(float128 a, float128 b, float_status *status) + { +- flag aSign, bSign; ++ bool aSign, bSign; + + aSign = extractFloat128Sign( a ); + bSign = extractFloat128Sign( b ); +@@ -7342,7 +7340,7 @@ float128 float128_sub(float128 a, float128 b, float_status *status) + + float128 float128_mul(float128 a, float128 b, float_status *status) + { +- flag aSign, bSign, zSign; ++ bool aSign, bSign, zSign; + int32_t aExp, bExp, zExp; + uint64_t aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2, zSig3; + +@@ -7405,7 +7403,7 @@ float128 float128_mul(float128 a, float128 b, float_status *status) + + float128 float128_div(float128 a, float128 b, float_status *status) + { +- flag aSign, bSign, zSign; ++ bool aSign, bSign, zSign; + int32_t aExp, bExp, zExp; + uint64_t aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2; + uint64_t rem0, rem1, rem2, rem3, term0, term1, term2, term3; +@@ -7492,7 +7490,7 @@ float128 float128_div(float128 a, float128 b, float_status *status) + + float128 float128_rem(float128 a, float128 b, float_status *status) + { +- flag aSign, zSign; ++ bool aSign, zSign; + int32_t aExp, bExp, expDiff; + uint64_t aSig0, aSig1, bSig0, bSig1, q, term0, term1, term2; + uint64_t allZero, alternateASig0, alternateASig1, sigMean1; +@@ -7599,7 +7597,7 @@ float128 float128_rem(float128 a, float128 b, float_status *status) + + float128 float128_sqrt(float128 a, float_status *status) + { +- flag aSign; ++ bool aSign; + int32_t aExp, zExp; + uint64_t aSig0, aSig1, zSig0, zSig1, zSig2, doubleZSig0; + uint64_t rem0, rem1, rem2, rem3, term0, term1, term2, term3; +@@ -7695,7 +7693,7 @@ int float128_eq(float128 a, float128 b, float_status *status) + + int float128_le(float128 a, float128 b, float_status *status) + { +- flag aSign, bSign; ++ bool aSign, bSign; + + if ( ( ( extractFloat128Exp( a ) == 0x7FFF ) + && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) ) +@@ -7728,7 +7726,7 @@ int float128_le(float128 a, float128 b, float_status *status) + + int float128_lt(float128 a, float128 b, float_status *status) + { +- flag aSign, bSign; ++ bool aSign, bSign; + + if ( ( ( extractFloat128Exp( a ) == 0x7FFF ) + && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) ) +@@ -7811,7 +7809,7 @@ int float128_eq_quiet(float128 a, float128 b, float_status *status) + + int float128_le_quiet(float128 a, float128 b, float_status *status) + { +- flag aSign, bSign; ++ bool aSign, bSign; + + if ( ( ( extractFloat128Exp( a ) == 0x7FFF ) + && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) ) +@@ -7847,7 +7845,7 @@ int float128_le_quiet(float128 a, float128 b, float_status *status) + + int float128_lt_quiet(float128 a, float128 b, float_status *status) + { +- flag aSign, bSign; ++ bool aSign, bSign; + + if ( ( ( extractFloat128Exp( a ) == 0x7FFF ) + && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) ) +@@ -7900,7 +7898,7 @@ int float128_unordered_quiet(float128 a, float128 b, float_status *status) + static inline int floatx80_compare_internal(floatx80 a, floatx80 b, + int is_quiet, float_status *status) + { +- flag aSign, bSign; ++ bool aSign, bSign; + + if (floatx80_invalid_encoding(a) || floatx80_invalid_encoding(b)) { + float_raise(float_flag_invalid, status); +@@ -7957,7 +7955,7 @@ int floatx80_compare_quiet(floatx80 a, floatx80 b, float_status *status) + static inline int float128_compare_internal(float128 a, float128 b, + int is_quiet, float_status *status) + { +- flag aSign, bSign; ++ bool aSign, bSign; + + if (( ( extractFloat128Exp( a ) == 0x7fff ) && + ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) ) || +@@ -8000,7 +7998,7 @@ int float128_compare_quiet(float128 a, float128 b, float_status *status) + + floatx80 floatx80_scalbn(floatx80 a, int n, float_status *status) + { +- flag aSign; ++ bool aSign; + int32_t aExp; + uint64_t aSig; + +@@ -8039,7 +8037,7 @@ floatx80 floatx80_scalbn(floatx80 a, int n, float_status *status) + + float128 float128_scalbn(float128 a, int n, float_status *status) + { +- flag aSign; ++ bool aSign; + int32_t aExp; + uint64_t aSig0, aSig1; + +diff --git a/include/fpu/softfloat-helpers.h b/include/fpu/softfloat-helpers.h +index e0baf24c8f..528d7ebd9f 100644 +--- a/include/fpu/softfloat-helpers.h ++++ b/include/fpu/softfloat-helpers.h +@@ -74,22 +74,22 @@ static inline void set_floatx80_rounding_precision(int val, + status->floatx80_rounding_precision = val; + } + +-static inline void set_flush_to_zero(flag val, float_status *status) ++static inline void set_flush_to_zero(bool val, float_status *status) + { + status->flush_to_zero = val; + } + +-static inline void set_flush_inputs_to_zero(flag val, float_status *status) ++static inline void set_flush_inputs_to_zero(bool val, float_status *status) + { + status->flush_inputs_to_zero = val; + } + +-static inline void set_default_nan_mode(flag val, float_status *status) ++static inline void set_default_nan_mode(bool val, float_status *status) + { + status->default_nan_mode = val; + } + +-static inline void set_snan_bit_is_one(flag val, float_status *status) ++static inline void set_snan_bit_is_one(bool val, float_status *status) + { + status->snan_bit_is_one = val; + } +@@ -114,17 +114,17 @@ static inline int get_floatx80_rounding_precision(float_status *status) + return status->floatx80_rounding_precision; + } + +-static inline flag get_flush_to_zero(float_status *status) ++static inline bool get_flush_to_zero(float_status *status) + { + return status->flush_to_zero; + } + +-static inline flag get_flush_inputs_to_zero(float_status *status) ++static inline bool get_flush_inputs_to_zero(float_status *status) + { + return status->flush_inputs_to_zero; + } + +-static inline flag get_default_nan_mode(float_status *status) ++static inline bool get_default_nan_mode(float_status *status) + { + return status->default_nan_mode; + } +diff --git a/include/fpu/softfloat-macros.h b/include/fpu/softfloat-macros.h +index 605c4f4bc6..a35ec2893a 100644 +--- a/include/fpu/softfloat-macros.h ++++ b/include/fpu/softfloat-macros.h +@@ -756,11 +756,9 @@ static inline uint32_t estimateSqrt32(int aExp, uint32_t a) + | Otherwise, returns 0. + *----------------------------------------------------------------------------*/ + +-static inline flag eq128( uint64_t a0, uint64_t a1, uint64_t b0, uint64_t b1 ) ++static inline bool eq128(uint64_t a0, uint64_t a1, uint64_t b0, uint64_t b1) + { +- +- return ( a0 == b0 ) && ( a1 == b1 ); +- ++ return a0 == b0 && a1 == b1; + } + + /*---------------------------------------------------------------------------- +@@ -769,11 +767,9 @@ static inline flag eq128( uint64_t a0, uint64_t a1, uint64_t b0, uint64_t b1 ) + | Otherwise, returns 0. + *----------------------------------------------------------------------------*/ + +-static inline flag le128( uint64_t a0, uint64_t a1, uint64_t b0, uint64_t b1 ) ++static inline bool le128(uint64_t a0, uint64_t a1, uint64_t b0, uint64_t b1) + { +- +- return ( a0 < b0 ) || ( ( a0 == b0 ) && ( a1 <= b1 ) ); +- ++ return a0 < b0 || (a0 == b0 && a1 <= b1); + } + + /*---------------------------------------------------------------------------- +@@ -782,11 +778,9 @@ static inline flag le128( uint64_t a0, uint64_t a1, uint64_t b0, uint64_t b1 ) + | returns 0. + *----------------------------------------------------------------------------*/ + +-static inline flag lt128( uint64_t a0, uint64_t a1, uint64_t b0, uint64_t b1 ) ++static inline bool lt128(uint64_t a0, uint64_t a1, uint64_t b0, uint64_t b1) + { +- +- return ( a0 < b0 ) || ( ( a0 == b0 ) && ( a1 < b1 ) ); +- ++ return a0 < b0 || (a0 == b0 && a1 < b1); + } + + /*---------------------------------------------------------------------------- +@@ -795,11 +789,9 @@ static inline flag lt128( uint64_t a0, uint64_t a1, uint64_t b0, uint64_t b1 ) + | Otherwise, returns 0. + *----------------------------------------------------------------------------*/ + +-static inline flag ne128( uint64_t a0, uint64_t a1, uint64_t b0, uint64_t b1 ) ++static inline bool ne128(uint64_t a0, uint64_t a1, uint64_t b0, uint64_t b1) + { +- +- return ( a0 != b0 ) || ( a1 != b1 ); +- ++ return a0 != b0 || a1 != b1; + } + + #endif +diff --git a/include/fpu/softfloat-types.h b/include/fpu/softfloat-types.h +index 2aae6a89b1..619b875df6 100644 +--- a/include/fpu/softfloat-types.h ++++ b/include/fpu/softfloat-types.h +@@ -80,12 +80,6 @@ this code that are retained. + #ifndef SOFTFLOAT_TYPES_H + #define SOFTFLOAT_TYPES_H + +-/* This 'flag' type must be able to hold at least 0 and 1. It should +- * probably be replaced with 'bool' but the uses would need to be audited +- * to check that they weren't accidentally relying on it being a larger type. +- */ +-typedef uint8_t flag; +- + /* + * Software IEC/IEEE floating-point types. + */ +@@ -169,12 +163,12 @@ typedef struct float_status { + uint8_t float_exception_flags; + signed char floatx80_rounding_precision; + /* should denormalised results go to zero and set the inexact flag? */ +- flag flush_to_zero; ++ bool flush_to_zero; + /* should denormalised inputs go to zero and set the input_denormal flag? */ +- flag flush_inputs_to_zero; +- flag default_nan_mode; ++ bool flush_inputs_to_zero; ++ bool default_nan_mode; + /* not always used -- see snan_bit_is_one() in softfloat-specialize.h */ +- flag snan_bit_is_one; ++ bool snan_bit_is_one; + } float_status; + + #endif /* SOFTFLOAT_TYPES_H */ +diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h +index ecb8ba0114..3f588da7c7 100644 +--- a/include/fpu/softfloat.h ++++ b/include/fpu/softfloat.h +@@ -440,7 +440,7 @@ static inline float32 float32_set_sign(float32 a, int sign) + | significand. + *----------------------------------------------------------------------------*/ + +-static inline float32 packFloat32(flag zSign, int zExp, uint32_t zSig) ++static inline float32 packFloat32(bool zSign, int zExp, uint32_t zSig) + { + return make_float32( + (((uint32_t)zSign) << 31) + (((uint32_t)zExp) << 23) + zSig); +@@ -722,7 +722,7 @@ static inline int32_t extractFloatx80Exp(floatx80 a) + | `a'. + *----------------------------------------------------------------------------*/ + +-static inline flag extractFloatx80Sign(floatx80 a) ++static inline bool extractFloatx80Sign(floatx80 a) + { + return a.high >> 15; + } +@@ -732,7 +732,7 @@ static inline flag extractFloatx80Sign(floatx80 a) + | extended double-precision floating-point value, returning the result. + *----------------------------------------------------------------------------*/ + +-static inline floatx80 packFloatx80(flag zSign, int32_t zExp, uint64_t zSig) ++static inline floatx80 packFloatx80(bool zSign, int32_t zExp, uint64_t zSig) + { + floatx80 z; + +@@ -783,7 +783,7 @@ floatx80 propagateFloatx80NaN(floatx80 a, floatx80 b, float_status *status); + | Floating-Point Arithmetic. + *----------------------------------------------------------------------------*/ + +-floatx80 roundAndPackFloatx80(int8_t roundingPrecision, flag zSign, ++floatx80 roundAndPackFloatx80(int8_t roundingPrecision, bool zSign, + int32_t zExp, uint64_t zSig0, uint64_t zSig1, + float_status *status); + +@@ -797,7 +797,7 @@ floatx80 roundAndPackFloatx80(int8_t roundingPrecision, flag zSign, + *----------------------------------------------------------------------------*/ + + floatx80 normalizeRoundAndPackFloatx80(int8_t roundingPrecision, +- flag zSign, int32_t zExp, ++ bool zSign, int32_t zExp, + uint64_t zSig0, uint64_t zSig1, + float_status *status); + +diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c +index 0da254d402..e590db6637 100644 +--- a/target/arm/sve_helper.c ++++ b/target/arm/sve_helper.c +@@ -3201,7 +3201,7 @@ void HELPER(NAME)(void *vd, void *vn, void *vg, void *status, uint32_t desc) \ + */ + static inline float32 sve_f16_to_f32(float16 f, float_status *fpst) + { +- flag save = get_flush_inputs_to_zero(fpst); ++ bool save = get_flush_inputs_to_zero(fpst); + float32 ret; + + set_flush_inputs_to_zero(false, fpst); +@@ -3212,7 +3212,7 @@ static inline float32 sve_f16_to_f32(float16 f, float_status *fpst) + + static inline float64 sve_f16_to_f64(float16 f, float_status *fpst) + { +- flag save = get_flush_inputs_to_zero(fpst); ++ bool save = get_flush_inputs_to_zero(fpst); + float64 ret; + + set_flush_inputs_to_zero(false, fpst); +@@ -3223,7 +3223,7 @@ static inline float64 sve_f16_to_f64(float16 f, float_status *fpst) + + static inline float16 sve_f32_to_f16(float32 f, float_status *fpst) + { +- flag save = get_flush_to_zero(fpst); ++ bool save = get_flush_to_zero(fpst); + float16 ret; + + set_flush_to_zero(false, fpst); +@@ -3234,7 +3234,7 @@ static inline float16 sve_f32_to_f16(float32 f, float_status *fpst) + + static inline float16 sve_f64_to_f16(float64 f, float_status *fpst) + { +- flag save = get_flush_to_zero(fpst); ++ bool save = get_flush_to_zero(fpst); + float16 ret; + + set_flush_to_zero(false, fpst); +diff --git a/target/arm/vfp_helper.c b/target/arm/vfp_helper.c +index 88483d4066..42625747d1 100644 +--- a/target/arm/vfp_helper.c ++++ b/target/arm/vfp_helper.c +@@ -531,7 +531,7 @@ float32 HELPER(vfp_fcvt_f16_to_f32)(uint32_t a, void *fpstp, uint32_t ahp_mode) + * it would affect flushing input denormals. + */ + float_status *fpst = fpstp; +- flag save = get_flush_inputs_to_zero(fpst); ++ bool save = get_flush_inputs_to_zero(fpst); + set_flush_inputs_to_zero(false, fpst); + float32 r = float16_to_float32(a, !ahp_mode, fpst); + set_flush_inputs_to_zero(save, fpst); +@@ -544,7 +544,7 @@ uint32_t HELPER(vfp_fcvt_f32_to_f16)(float32 a, void *fpstp, uint32_t ahp_mode) + * it would affect flushing output denormals. + */ + float_status *fpst = fpstp; +- flag save = get_flush_to_zero(fpst); ++ bool save = get_flush_to_zero(fpst); + set_flush_to_zero(false, fpst); + float16 r = float32_to_float16(a, !ahp_mode, fpst); + set_flush_to_zero(save, fpst); +@@ -557,7 +557,7 @@ float64 HELPER(vfp_fcvt_f16_to_f64)(uint32_t a, void *fpstp, uint32_t ahp_mode) + * it would affect flushing input denormals. + */ + float_status *fpst = fpstp; +- flag save = get_flush_inputs_to_zero(fpst); ++ bool save = get_flush_inputs_to_zero(fpst); + set_flush_inputs_to_zero(false, fpst); + float64 r = float16_to_float64(a, !ahp_mode, fpst); + set_flush_inputs_to_zero(save, fpst); +@@ -570,7 +570,7 @@ uint32_t HELPER(vfp_fcvt_f64_to_f16)(float64 a, void *fpstp, uint32_t ahp_mode) + * it would affect flushing output denormals. + */ + float_status *fpst = fpstp; +- flag save = get_flush_to_zero(fpst); ++ bool save = get_flush_to_zero(fpst); + set_flush_to_zero(false, fpst); + float16 r = float64_to_float16(a, !ahp_mode, fpst); + set_flush_to_zero(save, fpst); +diff --git a/target/m68k/softfloat.c b/target/m68k/softfloat.c +index 24c313ed69..9f120cf15e 100644 +--- a/target/m68k/softfloat.c ++++ b/target/m68k/softfloat.c +@@ -49,7 +49,7 @@ static floatx80 propagateFloatx80NaNOneArg(floatx80 a, float_status *status) + + floatx80 floatx80_mod(floatx80 a, floatx80 b, float_status *status) + { +- flag aSign, zSign; ++ bool aSign, zSign; + int32_t aExp, bExp, expDiff; + uint64_t aSig0, aSig1, bSig; + uint64_t qTemp, term0, term1; +@@ -132,7 +132,7 @@ floatx80 floatx80_mod(floatx80 a, floatx80 b, float_status *status) + + floatx80 floatx80_getman(floatx80 a, float_status *status) + { +- flag aSign; ++ bool aSign; + int32_t aExp; + uint64_t aSig; + +@@ -166,7 +166,7 @@ floatx80 floatx80_getman(floatx80 a, float_status *status) + + floatx80 floatx80_getexp(floatx80 a, float_status *status) + { +- flag aSign; ++ bool aSign; + int32_t aExp; + uint64_t aSig; + +@@ -202,7 +202,7 @@ floatx80 floatx80_getexp(floatx80 a, float_status *status) + + floatx80 floatx80_scale(floatx80 a, floatx80 b, float_status *status) + { +- flag aSign, bSign; ++ bool aSign, bSign; + int32_t aExp, bExp, shiftCount; + uint64_t aSig, bSig; + +@@ -258,7 +258,7 @@ floatx80 floatx80_scale(floatx80 a, floatx80 b, float_status *status) + + floatx80 floatx80_move(floatx80 a, float_status *status) + { +- flag aSign; ++ bool aSign; + int32_t aExp; + uint64_t aSig; + +@@ -306,7 +306,7 @@ static int32_t floatx80_make_compact(int32_t aExp, uint64_t aSig) + + floatx80 floatx80_lognp1(floatx80 a, float_status *status) + { +- flag aSign; ++ bool aSign; + int32_t aExp; + uint64_t aSig, fSig; + +@@ -505,7 +505,7 @@ floatx80 floatx80_lognp1(floatx80 a, float_status *status) + + floatx80 floatx80_logn(floatx80 a, float_status *status) + { +- flag aSign; ++ bool aSign; + int32_t aExp; + uint64_t aSig, fSig; + +@@ -673,7 +673,7 @@ floatx80 floatx80_logn(floatx80 a, float_status *status) + + floatx80 floatx80_log10(floatx80 a, float_status *status) + { +- flag aSign; ++ bool aSign; + int32_t aExp; + uint64_t aSig; + +@@ -730,7 +730,7 @@ floatx80 floatx80_log10(floatx80 a, float_status *status) + + floatx80 floatx80_log2(floatx80 a, float_status *status) + { +- flag aSign; ++ bool aSign; + int32_t aExp; + uint64_t aSig; + +@@ -797,7 +797,7 @@ floatx80 floatx80_log2(floatx80 a, float_status *status) + + floatx80 floatx80_etox(floatx80 a, float_status *status) + { +- flag aSign; ++ bool aSign; + int32_t aExp; + uint64_t aSig; + +@@ -805,7 +805,7 @@ floatx80 floatx80_etox(floatx80 a, float_status *status) + + int32_t compact, n, j, k, m, m1; + floatx80 fp0, fp1, fp2, fp3, l2, scale, adjscale; +- flag adjflag; ++ bool adjflag; + + aSig = extractFloatx80Frac(a); + aExp = extractFloatx80Exp(a); +@@ -981,7 +981,7 @@ floatx80 floatx80_etox(floatx80 a, float_status *status) + + floatx80 floatx80_twotox(floatx80 a, float_status *status) + { +- flag aSign; ++ bool aSign; + int32_t aExp; + uint64_t aSig; + +@@ -1131,7 +1131,7 @@ floatx80 floatx80_twotox(floatx80 a, float_status *status) + + floatx80 floatx80_tentox(floatx80 a, float_status *status) + { +- flag aSign; ++ bool aSign; + int32_t aExp; + uint64_t aSig; + +@@ -1286,7 +1286,7 @@ floatx80 floatx80_tentox(floatx80 a, float_status *status) + + floatx80 floatx80_tan(floatx80 a, float_status *status) + { +- flag aSign, xSign; ++ bool aSign, xSign; + int32_t aExp, xExp; + uint64_t aSig, xSig; + +@@ -1295,7 +1295,7 @@ floatx80 floatx80_tan(floatx80 a, float_status *status) + int32_t compact, l, n, j; + floatx80 fp0, fp1, fp2, fp3, fp4, fp5, invtwopi, twopi1, twopi2; + float32 twoto63; +- flag endflag; ++ bool endflag; + + aSig = extractFloatx80Frac(a); + aExp = extractFloatx80Exp(a); +@@ -1344,10 +1344,10 @@ floatx80 floatx80_tan(floatx80 a, float_status *status) + xExp -= 0x3FFF; + if (xExp <= 28) { + l = 0; +- endflag = 1; ++ endflag = true; + } else { + l = xExp - 27; +- endflag = 0; ++ endflag = false; + } + invtwopi = packFloatx80(0, 0x3FFE - l, + UINT64_C(0xA2F9836E4E44152A)); /* INVTWOPI */ +@@ -1372,7 +1372,7 @@ floatx80 floatx80_tan(floatx80 a, float_status *status) + fp1 = floatx80_sub(fp1, fp4, status); /* FP1 is a := r - p */ + fp0 = floatx80_add(fp0, fp1, status); /* FP0 is R := A+a */ + +- if (endflag > 0) { ++ if (endflag) { + n = floatx80_to_int32(fp2, status); + goto tancont; + } +@@ -1496,7 +1496,7 @@ floatx80 floatx80_tan(floatx80 a, float_status *status) + + floatx80 floatx80_sin(floatx80 a, float_status *status) + { +- flag aSign, xSign; ++ bool aSign, xSign; + int32_t aExp, xExp; + uint64_t aSig, xSig; + +@@ -1505,7 +1505,7 @@ floatx80 floatx80_sin(floatx80 a, float_status *status) + int32_t compact, l, n, j; + floatx80 fp0, fp1, fp2, fp3, fp4, fp5, x, invtwopi, twopi1, twopi2; + float32 posneg1, twoto63; +- flag endflag; ++ bool endflag; + + aSig = extractFloatx80Frac(a); + aExp = extractFloatx80Exp(a); +@@ -1554,10 +1554,10 @@ floatx80 floatx80_sin(floatx80 a, float_status *status) + xExp -= 0x3FFF; + if (xExp <= 28) { + l = 0; +- endflag = 1; ++ endflag = true; + } else { + l = xExp - 27; +- endflag = 0; ++ endflag = false; + } + invtwopi = packFloatx80(0, 0x3FFE - l, + UINT64_C(0xA2F9836E4E44152A)); /* INVTWOPI */ +@@ -1582,7 +1582,7 @@ floatx80 floatx80_sin(floatx80 a, float_status *status) + fp1 = floatx80_sub(fp1, fp4, status); /* FP1 is a := r - p */ + fp0 = floatx80_add(fp0, fp1, status); /* FP0 is R := A+a */ + +- if (endflag > 0) { ++ if (endflag) { + n = floatx80_to_int32(fp2, status); + goto sincont; + } +@@ -1735,7 +1735,7 @@ floatx80 floatx80_sin(floatx80 a, float_status *status) + + floatx80 floatx80_cos(floatx80 a, float_status *status) + { +- flag aSign, xSign; ++ bool aSign, xSign; + int32_t aExp, xExp; + uint64_t aSig, xSig; + +@@ -1744,7 +1744,7 @@ floatx80 floatx80_cos(floatx80 a, float_status *status) + int32_t compact, l, n, j; + floatx80 fp0, fp1, fp2, fp3, fp4, fp5, x, invtwopi, twopi1, twopi2; + float32 posneg1, twoto63; +- flag endflag; ++ bool endflag; + + aSig = extractFloatx80Frac(a); + aExp = extractFloatx80Exp(a); +@@ -1793,10 +1793,10 @@ floatx80 floatx80_cos(floatx80 a, float_status *status) + xExp -= 0x3FFF; + if (xExp <= 28) { + l = 0; +- endflag = 1; ++ endflag = true; + } else { + l = xExp - 27; +- endflag = 0; ++ endflag = false; + } + invtwopi = packFloatx80(0, 0x3FFE - l, + UINT64_C(0xA2F9836E4E44152A)); /* INVTWOPI */ +@@ -1821,7 +1821,7 @@ floatx80 floatx80_cos(floatx80 a, float_status *status) + fp1 = floatx80_sub(fp1, fp4, status); /* FP1 is a := r - p */ + fp0 = floatx80_add(fp0, fp1, status); /* FP0 is R := A+a */ + +- if (endflag > 0) { ++ if (endflag) { + n = floatx80_to_int32(fp2, status); + goto sincont; + } +@@ -1972,7 +1972,7 @@ floatx80 floatx80_cos(floatx80 a, float_status *status) + + floatx80 floatx80_atan(floatx80 a, float_status *status) + { +- flag aSign; ++ bool aSign; + int32_t aExp; + uint64_t aSig; + +@@ -2169,7 +2169,7 @@ floatx80 floatx80_atan(floatx80 a, float_status *status) + + floatx80 floatx80_asin(floatx80 a, float_status *status) + { +- flag aSign; ++ bool aSign; + int32_t aExp; + uint64_t aSig; + +@@ -2234,7 +2234,7 @@ floatx80 floatx80_asin(floatx80 a, float_status *status) + + floatx80 floatx80_acos(floatx80 a, float_status *status) + { +- flag aSign; ++ bool aSign; + int32_t aExp; + uint64_t aSig; + +@@ -2303,7 +2303,7 @@ floatx80 floatx80_acos(floatx80 a, float_status *status) + + floatx80 floatx80_atanh(floatx80 a, float_status *status) + { +- flag aSign; ++ bool aSign; + int32_t aExp; + uint64_t aSig; + +@@ -2368,7 +2368,7 @@ floatx80 floatx80_atanh(floatx80 a, float_status *status) + + floatx80 floatx80_etoxm1(floatx80 a, float_status *status) + { +- flag aSign; ++ bool aSign; + int32_t aExp; + uint64_t aSig; + +@@ -2620,7 +2620,7 @@ floatx80 floatx80_etoxm1(floatx80 a, float_status *status) + + floatx80 floatx80_tanh(floatx80 a, float_status *status) + { +- flag aSign, vSign; ++ bool aSign, vSign; + int32_t aExp, vExp; + uint64_t aSig, vSig; + +@@ -2735,7 +2735,7 @@ floatx80 floatx80_tanh(floatx80 a, float_status *status) + + floatx80 floatx80_sinh(floatx80 a, float_status *status) + { +- flag aSign; ++ bool aSign; + int32_t aExp; + uint64_t aSig; + +diff --git a/target/mips/msa_helper.c b/target/mips/msa_helper.c +index 4065cfe4f7..3c7012c0b8 100644 +--- a/target/mips/msa_helper.c ++++ b/target/mips/msa_helper.c +@@ -5508,7 +5508,7 @@ static inline int get_enabled_exceptions(const CPUMIPSState *env, int c) + return c & enable; + } + +-static inline float16 float16_from_float32(int32_t a, flag ieee, ++static inline float16 float16_from_float32(int32_t a, bool ieee, + float_status *status) + { + float16 f_val; +@@ -5527,7 +5527,7 @@ static inline float32 float32_from_float64(int64_t a, float_status *status) + return a < 0 ? (f_val | (1 << 31)) : f_val; + } + +-static inline float32 float32_from_float16(int16_t a, flag ieee, ++static inline float32 float32_from_float16(int16_t a, bool ieee, + float_status *status) + { + float32 f_val; +@@ -6564,7 +6564,7 @@ void helper_msa_fexdo_df(CPUMIPSState *env, uint32_t df, uint32_t wd, + * IEEE and "ARM" format. The latter gains extra exponent + * range by omitting the NaN/Inf encodings. + */ +- flag ieee = 1; ++ bool ieee = true; + + MSA_FLOAT_BINOP(Lh(pwx, i), from_float32, pws->w[i], ieee, 16); + MSA_FLOAT_BINOP(Rh(pwx, i), from_float32, pwt->w[i], ieee, 16); +@@ -7178,7 +7178,7 @@ void helper_msa_fexupl_df(CPUMIPSState *env, uint32_t df, uint32_t wd, + * IEEE and "ARM" format. The latter gains extra exponent + * range by omitting the NaN/Inf encodings. + */ +- flag ieee = 1; ++ bool ieee = true; + + MSA_FLOAT_BINOP(pwx->w[i], from_float16, Lh(pws, i), ieee, 32); + } +@@ -7214,7 +7214,7 @@ void helper_msa_fexupr_df(CPUMIPSState *env, uint32_t df, uint32_t wd, + * IEEE and "ARM" format. The latter gains extra exponent + * range by omitting the NaN/Inf encodings. + */ +- flag ieee = 1; ++ bool ieee = true; + + MSA_FLOAT_BINOP(pwx->w[i], from_float16, Rh(pws, i), ieee, 32); + } +-- +2.23.0 + diff --git a/softfloat-Return-bool-from-all-classification-predic.patch b/softfloat-Return-bool-from-all-classification-predic.patch new file mode 100644 index 0000000000000000000000000000000000000000..b55967ff2520aba5888b7adbfbf45f84aae7c8ed --- /dev/null +++ b/softfloat-Return-bool-from-all-classification-predic.patch @@ -0,0 +1,312 @@ +From 150c7a91ce7862bcaf7422f6038dcf0ba4a7eee3 Mon Sep 17 00:00:00 2001 +From: Richard Henderson +Date: Tue, 5 May 2020 12:16:24 -0700 +Subject: [PATCH 601/709] softfloat: Return bool from all classification + predicates +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This includes *_is_any_nan, *_is_neg, *_is_inf, etc. + +Reviewed-by: Alex Bennée +Reviewed-by: Philippe Mathieu-Daudé +Signed-off-by: Richard Henderson +--- + fpu/softfloat-specialize.inc.c | 16 ++++----- + include/fpu/softfloat.h | 66 +++++++++++++++++----------------- + 2 files changed, 41 insertions(+), 41 deletions(-) + +diff --git a/fpu/softfloat-specialize.inc.c b/fpu/softfloat-specialize.inc.c +index 025ee4f991..44f5b661f8 100644 +--- a/fpu/softfloat-specialize.inc.c ++++ b/fpu/softfloat-specialize.inc.c +@@ -245,7 +245,7 @@ typedef struct { + | NaN; otherwise returns 0. + *----------------------------------------------------------------------------*/ + +-int float16_is_quiet_nan(float16 a_, float_status *status) ++bool float16_is_quiet_nan(float16 a_, float_status *status) + { + #ifdef NO_SIGNALING_NANS + return float16_is_any_nan(a_); +@@ -264,7 +264,7 @@ int float16_is_quiet_nan(float16 a_, float_status *status) + | NaN; otherwise returns 0. + *----------------------------------------------------------------------------*/ + +-int float16_is_signaling_nan(float16 a_, float_status *status) ++bool float16_is_signaling_nan(float16 a_, float_status *status) + { + #ifdef NO_SIGNALING_NANS + return 0; +@@ -283,7 +283,7 @@ int float16_is_signaling_nan(float16 a_, float_status *status) + | NaN; otherwise returns 0. + *----------------------------------------------------------------------------*/ + +-int float32_is_quiet_nan(float32 a_, float_status *status) ++bool float32_is_quiet_nan(float32 a_, float_status *status) + { + #ifdef NO_SIGNALING_NANS + return float32_is_any_nan(a_); +@@ -302,7 +302,7 @@ int float32_is_quiet_nan(float32 a_, float_status *status) + | NaN; otherwise returns 0. + *----------------------------------------------------------------------------*/ + +-int float32_is_signaling_nan(float32 a_, float_status *status) ++bool float32_is_signaling_nan(float32 a_, float_status *status) + { + #ifdef NO_SIGNALING_NANS + return 0; +@@ -637,7 +637,7 @@ static float32 propagateFloat32NaN(float32 a, float32 b, float_status *status) + | NaN; otherwise returns 0. + *----------------------------------------------------------------------------*/ + +-int float64_is_quiet_nan(float64 a_, float_status *status) ++bool float64_is_quiet_nan(float64 a_, float_status *status) + { + #ifdef NO_SIGNALING_NANS + return float64_is_any_nan(a_); +@@ -657,7 +657,7 @@ int float64_is_quiet_nan(float64 a_, float_status *status) + | NaN; otherwise returns 0. + *----------------------------------------------------------------------------*/ + +-int float64_is_signaling_nan(float64 a_, float_status *status) ++bool float64_is_signaling_nan(float64 a_, float_status *status) + { + #ifdef NO_SIGNALING_NANS + return 0; +@@ -939,7 +939,7 @@ floatx80 propagateFloatx80NaN(floatx80 a, floatx80 b, float_status *status) + | NaN; otherwise returns 0. + *----------------------------------------------------------------------------*/ + +-int float128_is_quiet_nan(float128 a, float_status *status) ++bool float128_is_quiet_nan(float128 a, float_status *status) + { + #ifdef NO_SIGNALING_NANS + return float128_is_any_nan(a); +@@ -959,7 +959,7 @@ int float128_is_quiet_nan(float128 a, float_status *status) + | signaling NaN; otherwise returns 0. + *----------------------------------------------------------------------------*/ + +-int float128_is_signaling_nan(float128 a, float_status *status) ++bool float128_is_signaling_nan(float128 a, float_status *status) + { + #ifdef NO_SIGNALING_NANS + return 0; +diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h +index 37217d9b9b..16ca697a73 100644 +--- a/include/fpu/softfloat.h ++++ b/include/fpu/softfloat.h +@@ -235,31 +235,31 @@ float16 float16_sqrt(float16, float_status *status); + FloatRelation float16_compare(float16, float16, float_status *status); + FloatRelation float16_compare_quiet(float16, float16, float_status *status); + +-int float16_is_quiet_nan(float16, float_status *status); +-int float16_is_signaling_nan(float16, float_status *status); ++bool float16_is_quiet_nan(float16, float_status *status); ++bool float16_is_signaling_nan(float16, float_status *status); + float16 float16_silence_nan(float16, float_status *status); + +-static inline int float16_is_any_nan(float16 a) ++static inline bool float16_is_any_nan(float16 a) + { + return ((float16_val(a) & ~0x8000) > 0x7c00); + } + +-static inline int float16_is_neg(float16 a) ++static inline bool float16_is_neg(float16 a) + { + return float16_val(a) >> 15; + } + +-static inline int float16_is_infinity(float16 a) ++static inline bool float16_is_infinity(float16 a) + { + return (float16_val(a) & 0x7fff) == 0x7c00; + } + +-static inline int float16_is_zero(float16 a) ++static inline bool float16_is_zero(float16 a) + { + return (float16_val(a) & 0x7fff) == 0; + } + +-static inline int float16_is_zero_or_denormal(float16 a) ++static inline bool float16_is_zero_or_denormal(float16 a) + { + return (float16_val(a) & 0x7c00) == 0; + } +@@ -351,8 +351,8 @@ float32 float32_minnum(float32, float32, float_status *status); + float32 float32_maxnum(float32, float32, float_status *status); + float32 float32_minnummag(float32, float32, float_status *status); + float32 float32_maxnummag(float32, float32, float_status *status); +-int float32_is_quiet_nan(float32, float_status *status); +-int float32_is_signaling_nan(float32, float_status *status); ++bool float32_is_quiet_nan(float32, float_status *status); ++bool float32_is_signaling_nan(float32, float_status *status); + float32 float32_silence_nan(float32, float_status *status); + float32 float32_scalbn(float32, int, float_status *status); + +@@ -372,27 +372,27 @@ static inline float32 float32_chs(float32 a) + return make_float32(float32_val(a) ^ 0x80000000); + } + +-static inline int float32_is_infinity(float32 a) ++static inline bool float32_is_infinity(float32 a) + { + return (float32_val(a) & 0x7fffffff) == 0x7f800000; + } + +-static inline int float32_is_neg(float32 a) ++static inline bool float32_is_neg(float32 a) + { + return float32_val(a) >> 31; + } + +-static inline int float32_is_zero(float32 a) ++static inline bool float32_is_zero(float32 a) + { + return (float32_val(a) & 0x7fffffff) == 0; + } + +-static inline int float32_is_any_nan(float32 a) ++static inline bool float32_is_any_nan(float32 a) + { + return ((float32_val(a) & ~(1 << 31)) > 0x7f800000UL); + } + +-static inline int float32_is_zero_or_denormal(float32 a) ++static inline bool float32_is_zero_or_denormal(float32 a) + { + return (float32_val(a) & 0x7f800000) == 0; + } +@@ -540,8 +540,8 @@ float64 float64_minnum(float64, float64, float_status *status); + float64 float64_maxnum(float64, float64, float_status *status); + float64 float64_minnummag(float64, float64, float_status *status); + float64 float64_maxnummag(float64, float64, float_status *status); +-int float64_is_quiet_nan(float64 a, float_status *status); +-int float64_is_signaling_nan(float64, float_status *status); ++bool float64_is_quiet_nan(float64 a, float_status *status); ++bool float64_is_signaling_nan(float64, float_status *status); + float64 float64_silence_nan(float64, float_status *status); + float64 float64_scalbn(float64, int, float_status *status); + +@@ -561,27 +561,27 @@ static inline float64 float64_chs(float64 a) + return make_float64(float64_val(a) ^ 0x8000000000000000LL); + } + +-static inline int float64_is_infinity(float64 a) ++static inline bool float64_is_infinity(float64 a) + { + return (float64_val(a) & 0x7fffffffffffffffLL ) == 0x7ff0000000000000LL; + } + +-static inline int float64_is_neg(float64 a) ++static inline bool float64_is_neg(float64 a) + { + return float64_val(a) >> 63; + } + +-static inline int float64_is_zero(float64 a) ++static inline bool float64_is_zero(float64 a) + { + return (float64_val(a) & 0x7fffffffffffffffLL) == 0; + } + +-static inline int float64_is_any_nan(float64 a) ++static inline bool float64_is_any_nan(float64 a) + { + return ((float64_val(a) & ~(1ULL << 63)) > 0x7ff0000000000000ULL); + } + +-static inline int float64_is_zero_or_denormal(float64 a) ++static inline bool float64_is_zero_or_denormal(float64 a) + { + return (float64_val(a) & 0x7ff0000000000000LL) == 0; + } +@@ -708,7 +708,7 @@ static inline floatx80 floatx80_chs(floatx80 a) + return a; + } + +-static inline int floatx80_is_infinity(floatx80 a) ++static inline bool floatx80_is_infinity(floatx80 a) + { + #if defined(TARGET_M68K) + return (a.high & 0x7fff) == floatx80_infinity.high && !(a.low << 1); +@@ -718,22 +718,22 @@ static inline int floatx80_is_infinity(floatx80 a) + #endif + } + +-static inline int floatx80_is_neg(floatx80 a) ++static inline bool floatx80_is_neg(floatx80 a) + { + return a.high >> 15; + } + +-static inline int floatx80_is_zero(floatx80 a) ++static inline bool floatx80_is_zero(floatx80 a) + { + return (a.high & 0x7fff) == 0 && a.low == 0; + } + +-static inline int floatx80_is_zero_or_denormal(floatx80 a) ++static inline bool floatx80_is_zero_or_denormal(floatx80 a) + { + return (a.high & 0x7fff) == 0; + } + +-static inline int floatx80_is_any_nan(floatx80 a) ++static inline bool floatx80_is_any_nan(floatx80 a) + { + return ((a.high & 0x7fff) == 0x7fff) && (a.low<<1); + } +@@ -936,8 +936,8 @@ float128 float128_rem(float128, float128, float_status *status); + float128 float128_sqrt(float128, float_status *status); + FloatRelation float128_compare(float128, float128, float_status *status); + FloatRelation float128_compare_quiet(float128, float128, float_status *status); +-int float128_is_quiet_nan(float128, float_status *status); +-int float128_is_signaling_nan(float128, float_status *status); ++bool float128_is_quiet_nan(float128, float_status *status); ++bool float128_is_signaling_nan(float128, float_status *status); + float128 float128_silence_nan(float128, float_status *status); + float128 float128_scalbn(float128, int, float_status *status); + +@@ -953,22 +953,22 @@ static inline float128 float128_chs(float128 a) + return a; + } + +-static inline int float128_is_infinity(float128 a) ++static inline bool float128_is_infinity(float128 a) + { + return (a.high & 0x7fffffffffffffffLL) == 0x7fff000000000000LL && a.low == 0; + } + +-static inline int float128_is_neg(float128 a) ++static inline bool float128_is_neg(float128 a) + { + return a.high >> 63; + } + +-static inline int float128_is_zero(float128 a) ++static inline bool float128_is_zero(float128 a) + { + return (a.high & 0x7fffffffffffffffLL) == 0 && a.low == 0; + } + +-static inline int float128_is_zero_or_denormal(float128 a) ++static inline bool float128_is_zero_or_denormal(float128 a) + { + return (a.high & 0x7fff000000000000LL) == 0; + } +@@ -983,7 +983,7 @@ static inline bool float128_is_denormal(float128 a) + return float128_is_zero_or_denormal(a) && !float128_is_zero(a); + } + +-static inline int float128_is_any_nan(float128 a) ++static inline bool float128_is_any_nan(float128 a) + { + return ((a.high >> 48) & 0x7fff) == 0x7fff && + ((a.low != 0) || ((a.high & 0xffffffffffffLL) != 0)); +-- +2.23.0 + diff --git a/softfloat-Use-post-test-for-floatN_mul.patch b/softfloat-Use-post-test-for-floatN_mul.patch new file mode 100644 index 0000000000000000000000000000000000000000..92051cab70c16fc5455a3bc939b18f7a95f52ff1 --- /dev/null +++ b/softfloat-Use-post-test-for-floatN_mul.patch @@ -0,0 +1,190 @@ +From b240c9c497b9880ac0ba29465907d5ebecd48083 Mon Sep 17 00:00:00 2001 +From: Richard Henderson +Date: Mon, 4 May 2020 16:57:21 -0700 +Subject: [PATCH 592/709] softfloat: Use post test for floatN_mul +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The existing f{32,64}_addsub_post test, which checks for zero +inputs, is identical to f{32,64}_mul_fast_test. Which means +we can eliminate the fast_test/fast_op hooks in favor of +reusing the same post hook. + +This means we have one fewer test along the fast path for multiply. + +Tested-by: Alex Bennée +Reviewed-by: Alex Bennée +Signed-off-by: Richard Henderson +--- + fpu/softfloat.c | 65 +++++++++++-------------------------------------- + 1 file changed, 14 insertions(+), 51 deletions(-) + +diff --git a/fpu/softfloat.c b/fpu/softfloat.c +index a362bf89ca..5fb4ef75bb 100644 +--- a/fpu/softfloat.c ++++ b/fpu/softfloat.c +@@ -339,12 +339,10 @@ static inline bool f64_is_inf(union_float64 a) + return float64_is_infinity(a.s); + } + +-/* Note: @fast_test and @post can be NULL */ + static inline float32 + float32_gen2(float32 xa, float32 xb, float_status *s, + hard_f32_op2_fn hard, soft_f32_op2_fn soft, +- f32_check_fn pre, f32_check_fn post, +- f32_check_fn fast_test, soft_f32_op2_fn fast_op) ++ f32_check_fn pre, f32_check_fn post) + { + union_float32 ua, ub, ur; + +@@ -359,17 +357,12 @@ float32_gen2(float32 xa, float32 xb, float_status *s, + if (unlikely(!pre(ua, ub))) { + goto soft; + } +- if (fast_test && fast_test(ua, ub)) { +- return fast_op(ua.s, ub.s, s); +- } + + ur.h = hard(ua.h, ub.h); + if (unlikely(f32_is_inf(ur))) { + s->float_exception_flags |= float_flag_overflow; +- } else if (unlikely(fabsf(ur.h) <= FLT_MIN)) { +- if (post == NULL || post(ua, ub)) { +- goto soft; +- } ++ } else if (unlikely(fabsf(ur.h) <= FLT_MIN) && post(ua, ub)) { ++ goto soft; + } + return ur.s; + +@@ -380,8 +373,7 @@ float32_gen2(float32 xa, float32 xb, float_status *s, + static inline float64 + float64_gen2(float64 xa, float64 xb, float_status *s, + hard_f64_op2_fn hard, soft_f64_op2_fn soft, +- f64_check_fn pre, f64_check_fn post, +- f64_check_fn fast_test, soft_f64_op2_fn fast_op) ++ f64_check_fn pre, f64_check_fn post) + { + union_float64 ua, ub, ur; + +@@ -396,17 +388,12 @@ float64_gen2(float64 xa, float64 xb, float_status *s, + if (unlikely(!pre(ua, ub))) { + goto soft; + } +- if (fast_test && fast_test(ua, ub)) { +- return fast_op(ua.s, ub.s, s); +- } + + ur.h = hard(ua.h, ub.h); + if (unlikely(f64_is_inf(ur))) { + s->float_exception_flags |= float_flag_overflow; +- } else if (unlikely(fabs(ur.h) <= DBL_MIN)) { +- if (post == NULL || post(ua, ub)) { +- goto soft; +- } ++ } else if (unlikely(fabs(ur.h) <= DBL_MIN) && post(ua, ub)) { ++ goto soft; + } + return ur.s; + +@@ -1115,7 +1102,7 @@ static double hard_f64_sub(double a, double b) + return a - b; + } + +-static bool f32_addsub_post(union_float32 a, union_float32 b) ++static bool f32_addsubmul_post(union_float32 a, union_float32 b) + { + if (QEMU_HARDFLOAT_2F32_USE_FP) { + return !(fpclassify(a.h) == FP_ZERO && fpclassify(b.h) == FP_ZERO); +@@ -1123,7 +1110,7 @@ static bool f32_addsub_post(union_float32 a, union_float32 b) + return !(float32_is_zero(a.s) && float32_is_zero(b.s)); + } + +-static bool f64_addsub_post(union_float64 a, union_float64 b) ++static bool f64_addsubmul_post(union_float64 a, union_float64 b) + { + if (QEMU_HARDFLOAT_2F64_USE_FP) { + return !(fpclassify(a.h) == FP_ZERO && fpclassify(b.h) == FP_ZERO); +@@ -1136,14 +1123,14 @@ static float32 float32_addsub(float32 a, float32 b, float_status *s, + hard_f32_op2_fn hard, soft_f32_op2_fn soft) + { + return float32_gen2(a, b, s, hard, soft, +- f32_is_zon2, f32_addsub_post, NULL, NULL); ++ f32_is_zon2, f32_addsubmul_post); + } + + static float64 float64_addsub(float64 a, float64 b, float_status *s, + hard_f64_op2_fn hard, soft_f64_op2_fn soft) + { + return float64_gen2(a, b, s, hard, soft, +- f64_is_zon2, f64_addsub_post, NULL, NULL); ++ f64_is_zon2, f64_addsubmul_post); + } + + float32 QEMU_FLATTEN +@@ -1258,42 +1245,18 @@ static double hard_f64_mul(double a, double b) + return a * b; + } + +-static bool f32_mul_fast_test(union_float32 a, union_float32 b) +-{ +- return float32_is_zero(a.s) || float32_is_zero(b.s); +-} +- +-static bool f64_mul_fast_test(union_float64 a, union_float64 b) +-{ +- return float64_is_zero(a.s) || float64_is_zero(b.s); +-} +- +-static float32 f32_mul_fast_op(float32 a, float32 b, float_status *s) +-{ +- bool signbit = float32_is_neg(a) ^ float32_is_neg(b); +- +- return float32_set_sign(float32_zero, signbit); +-} +- +-static float64 f64_mul_fast_op(float64 a, float64 b, float_status *s) +-{ +- bool signbit = float64_is_neg(a) ^ float64_is_neg(b); +- +- return float64_set_sign(float64_zero, signbit); +-} +- + float32 QEMU_FLATTEN + float32_mul(float32 a, float32 b, float_status *s) + { + return float32_gen2(a, b, s, hard_f32_mul, soft_f32_mul, +- f32_is_zon2, NULL, f32_mul_fast_test, f32_mul_fast_op); ++ f32_is_zon2, f32_addsubmul_post); + } + + float64 QEMU_FLATTEN + float64_mul(float64 a, float64 b, float_status *s) + { + return float64_gen2(a, b, s, hard_f64_mul, soft_f64_mul, +- f64_is_zon2, NULL, f64_mul_fast_test, f64_mul_fast_op); ++ f64_is_zon2, f64_addsubmul_post); + } + + /* +@@ -1834,14 +1797,14 @@ float32 QEMU_FLATTEN + float32_div(float32 a, float32 b, float_status *s) + { + return float32_gen2(a, b, s, hard_f32_div, soft_f32_div, +- f32_div_pre, f32_div_post, NULL, NULL); ++ f32_div_pre, f32_div_post); + } + + float64 QEMU_FLATTEN + float64_div(float64 a, float64 b, float_status *s) + { + return float64_gen2(a, b, s, hard_f64_div, soft_f64_div, +- f64_div_pre, f64_div_post, NULL, NULL); ++ f64_div_pre, f64_div_post); + } + + /* +-- +2.23.0 + diff --git a/softfloat-fix-floatx80-pseudo-denormal-addition-subt.patch b/softfloat-fix-floatx80-pseudo-denormal-addition-subt.patch new file mode 100644 index 0000000000000000000000000000000000000000..6e169bae91f51835f09468469922b6832e321588 --- /dev/null +++ b/softfloat-fix-floatx80-pseudo-denormal-addition-subt.patch @@ -0,0 +1,73 @@ +From 41602807766e253ccb6fb761f3ff12767f786e2c Mon Sep 17 00:00:00 2001 +From: Joseph Myers +Date: Mon, 4 May 2020 23:38:44 +0000 +Subject: [PATCH 504/709] softfloat: fix floatx80 pseudo-denormal addition / + subtraction + +The softfloat function addFloatx80Sigs, used for addition of values +with the same sign and subtraction of values with opposite sign, fails +to handle the case where the two values both have biased exponent zero +and there is a carry resulting from adding the significands, which can +occur if one or both values are pseudo-denormals (biased exponent +zero, explicit integer bit 1). Add a check for that case, so making +the results match those seen on x86 hardware for pseudo-denormals. + +Signed-off-by: Joseph Myers +Message-Id: +Signed-off-by: Richard Henderson +--- + fpu/softfloat.c | 6 ++++++ + tests/tcg/i386/test-i386-pseudo-denormal.c | 24 ++++++++++++++++++++++ + 2 files changed, 30 insertions(+) + create mode 100644 tests/tcg/i386/test-i386-pseudo-denormal.c + +diff --git a/fpu/softfloat.c b/fpu/softfloat.c +index ac116c70b8..6094d267b5 100644 +--- a/fpu/softfloat.c ++++ b/fpu/softfloat.c +@@ -5866,6 +5866,12 @@ static floatx80 addFloatx80Sigs(floatx80 a, floatx80 b, flag zSign, + zSig1 = 0; + zSig0 = aSig + bSig; + if ( aExp == 0 ) { ++ if ((aSig | bSig) & UINT64_C(0x8000000000000000) && zSig0 < aSig) { ++ /* At least one of the values is a pseudo-denormal, ++ * and there is a carry out of the result. */ ++ zExp = 1; ++ goto shiftRight1; ++ } + if (zSig0 == 0) { + return packFloatx80(zSign, 0, 0); + } +diff --git a/tests/tcg/i386/test-i386-pseudo-denormal.c b/tests/tcg/i386/test-i386-pseudo-denormal.c +new file mode 100644 +index 0000000000..cfa2a500b0 +--- /dev/null ++++ b/tests/tcg/i386/test-i386-pseudo-denormal.c +@@ -0,0 +1,24 @@ ++/* Test pseudo-denormal operations. */ ++ ++#include ++#include ++ ++union u { ++ struct { uint64_t sig; uint16_t sign_exp; } s; ++ long double ld; ++}; ++ ++volatile union u ld_pseudo_m16382 = { .s = { UINT64_C(1) << 63, 0 } }; ++ ++volatile long double ld_res; ++ ++int main(void) ++{ ++ int ret = 0; ++ ld_res = ld_pseudo_m16382.ld + ld_pseudo_m16382.ld; ++ if (ld_res != 0x1p-16381L) { ++ printf("FAIL: pseudo-denormal add\n"); ++ ret = 1; ++ } ++ return ret; ++} +-- +2.23.0 + diff --git a/softfloat-fix-floatx80-pseudo-denormal-comparisons.patch b/softfloat-fix-floatx80-pseudo-denormal-comparisons.patch new file mode 100644 index 0000000000000000000000000000000000000000..6a8f472a2b2499491a1c7333732a1591cbb077b9 --- /dev/null +++ b/softfloat-fix-floatx80-pseudo-denormal-comparisons.patch @@ -0,0 +1,53 @@ +From be53fa785ab766d2722628403edee75b3e6ab599 Mon Sep 17 00:00:00 2001 +From: Joseph Myers +Date: Mon, 4 May 2020 23:39:39 +0000 +Subject: [PATCH 505/709] softfloat: fix floatx80 pseudo-denormal comparisons + +The softfloat floatx80 comparisons fail to allow for pseudo-denormals, +which should compare equal to corresponding values with biased +exponent 1 rather than 0. Add an adjustment for that case when +comparing numbers with the same sign. + +Signed-off-by: Joseph Myers +Message-Id: +Signed-off-by: Richard Henderson +--- + fpu/softfloat.c | 7 +++++++ + tests/tcg/i386/test-i386-pseudo-denormal.c | 4 ++++ + 2 files changed, 11 insertions(+) + +diff --git a/fpu/softfloat.c b/fpu/softfloat.c +index 6094d267b5..c57f72e3a6 100644 +--- a/fpu/softfloat.c ++++ b/fpu/softfloat.c +@@ -7966,6 +7966,13 @@ static inline int floatx80_compare_internal(floatx80 a, floatx80 b, + return 1 - (2 * aSign); + } + } else { ++ /* Normalize pseudo-denormals before comparison. */ ++ if ((a.high & 0x7fff) == 0 && a.low & UINT64_C(0x8000000000000000)) { ++ ++a.high; ++ } ++ if ((b.high & 0x7fff) == 0 && b.low & UINT64_C(0x8000000000000000)) { ++ ++b.high; ++ } + if (a.low == b.low && a.high == b.high) { + return float_relation_equal; + } else { +diff --git a/tests/tcg/i386/test-i386-pseudo-denormal.c b/tests/tcg/i386/test-i386-pseudo-denormal.c +index cfa2a500b0..acf2b9cf03 100644 +--- a/tests/tcg/i386/test-i386-pseudo-denormal.c ++++ b/tests/tcg/i386/test-i386-pseudo-denormal.c +@@ -20,5 +20,9 @@ int main(void) + printf("FAIL: pseudo-denormal add\n"); + ret = 1; + } ++ if (ld_pseudo_m16382.ld != 0x1p-16382L) { ++ printf("FAIL: pseudo-denormal compare\n"); ++ ret = 1; ++ } + return ret; + } +-- +2.23.0 + diff --git a/softfloat-fix-floatx80-pseudo-denormal-round-to-inte.patch b/softfloat-fix-floatx80-pseudo-denormal-round-to-inte.patch new file mode 100644 index 0000000000000000000000000000000000000000..f9a0f88aaff9851907eb4389d8858561e0609b3a --- /dev/null +++ b/softfloat-fix-floatx80-pseudo-denormal-round-to-inte.patch @@ -0,0 +1,65 @@ +From 9ecaf5ccec13ff2e8fe1e72f6e0f3367d2169c1c Mon Sep 17 00:00:00 2001 +From: Joseph Myers +Date: Mon, 4 May 2020 23:40:20 +0000 +Subject: [PATCH 506/709] softfloat: fix floatx80 pseudo-denormal round to + integer + +The softfloat function floatx80_round_to_int incorrectly handles the +case of a pseudo-denormal where only the high bit of the significand +is set, ignoring that bit (treating the number as an exact zero) +rather than treating the number as an alternative representation of ++/- 2^-16382 (which may round to +/- 1 depending on the rounding mode) +as hardware does. Fix this check (simplifying the code in the +process). + +Signed-off-by: Joseph Myers +Message-Id: +Signed-off-by: Richard Henderson +--- + fpu/softfloat.c | 2 +- + tests/tcg/i386/test-i386-pseudo-denormal.c | 10 ++++++++++ + 2 files changed, 11 insertions(+), 1 deletion(-) + +diff --git a/fpu/softfloat.c b/fpu/softfloat.c +index c57f72e3a6..a362bf89ca 100644 +--- a/fpu/softfloat.c ++++ b/fpu/softfloat.c +@@ -5741,7 +5741,7 @@ floatx80 floatx80_round_to_int(floatx80 a, float_status *status) + } + if ( aExp < 0x3FFF ) { + if ( ( aExp == 0 ) +- && ( (uint64_t) ( extractFloatx80Frac( a )<<1 ) == 0 ) ) { ++ && ( (uint64_t) ( extractFloatx80Frac( a ) ) == 0 ) ) { + return a; + } + status->float_exception_flags |= float_flag_inexact; +diff --git a/tests/tcg/i386/test-i386-pseudo-denormal.c b/tests/tcg/i386/test-i386-pseudo-denormal.c +index acf2b9cf03..00d510cf4a 100644 +--- a/tests/tcg/i386/test-i386-pseudo-denormal.c ++++ b/tests/tcg/i386/test-i386-pseudo-denormal.c +@@ -14,6 +14,7 @@ volatile long double ld_res; + + int main(void) + { ++ short cw; + int ret = 0; + ld_res = ld_pseudo_m16382.ld + ld_pseudo_m16382.ld; + if (ld_res != 0x1p-16381L) { +@@ -24,5 +25,14 @@ int main(void) + printf("FAIL: pseudo-denormal compare\n"); + ret = 1; + } ++ /* Set round-upward. */ ++ __asm__ volatile ("fnstcw %0" : "=m" (cw)); ++ cw = (cw & ~0xc00) | 0x800; ++ __asm__ volatile ("fldcw %0" : : "m" (cw)); ++ __asm__ ("frndint" : "=t" (ld_res) : "0" (ld_pseudo_m16382.ld)); ++ if (ld_res != 1.0L) { ++ printf("FAIL: pseudo-denormal round-to-integer\n"); ++ ret = 1; ++ } + return ret; + } +-- +2.23.0 + diff --git a/softfloat-silence-sNaN-for-conversions-to-from-float.patch b/softfloat-silence-sNaN-for-conversions-to-from-float.patch new file mode 100644 index 0000000000000000000000000000000000000000..b6aafe36b7e3fcce072cb22f410c29f2616f4993 --- /dev/null +++ b/softfloat-silence-sNaN-for-conversions-to-from-float.patch @@ -0,0 +1,162 @@ +From 7537c2b4a363237534c96d089a02b0712b49d890 Mon Sep 17 00:00:00 2001 +From: Joseph Myers +Date: Mon, 4 May 2020 23:37:54 +0000 +Subject: [PATCH 503/709] softfloat: silence sNaN for conversions to/from + floatx80 + +Conversions between IEEE floating-point formats should convert +signaling NaNs to quiet NaNs. Most of those in QEMU's softfloat code +do so, but those for floatx80 fail to. Fix those conversions to +silence signaling NaNs as well. + +Signed-off-by: Joseph Myers +Message-Id: +Signed-off-by: Richard Henderson +--- + fpu/softfloat.c | 24 +++++++--- + tests/tcg/i386/test-i386-snan-convert.c | 63 +++++++++++++++++++++++++ + 2 files changed, 81 insertions(+), 6 deletions(-) + create mode 100644 tests/tcg/i386/test-i386-snan-convert.c + +diff --git a/fpu/softfloat.c b/fpu/softfloat.c +index ae6ba71854..ac116c70b8 100644 +--- a/fpu/softfloat.c ++++ b/fpu/softfloat.c +@@ -4498,7 +4498,9 @@ floatx80 float32_to_floatx80(float32 a, float_status *status) + aSign = extractFloat32Sign( a ); + if ( aExp == 0xFF ) { + if (aSig) { +- return commonNaNToFloatx80(float32ToCommonNaN(a, status), status); ++ floatx80 res = commonNaNToFloatx80(float32ToCommonNaN(a, status), ++ status); ++ return floatx80_silence_nan(res, status); + } + return packFloatx80(aSign, + floatx80_infinity_high, +@@ -5016,7 +5018,9 @@ floatx80 float64_to_floatx80(float64 a, float_status *status) + aSign = extractFloat64Sign( a ); + if ( aExp == 0x7FF ) { + if (aSig) { +- return commonNaNToFloatx80(float64ToCommonNaN(a, status), status); ++ floatx80 res = commonNaNToFloatx80(float64ToCommonNaN(a, status), ++ status); ++ return floatx80_silence_nan(res, status); + } + return packFloatx80(aSign, + floatx80_infinity_high, +@@ -5618,7 +5622,9 @@ float32 floatx80_to_float32(floatx80 a, float_status *status) + aSign = extractFloatx80Sign( a ); + if ( aExp == 0x7FFF ) { + if ( (uint64_t) ( aSig<<1 ) ) { +- return commonNaNToFloat32(floatx80ToCommonNaN(a, status), status); ++ float32 res = commonNaNToFloat32(floatx80ToCommonNaN(a, status), ++ status); ++ return float32_silence_nan(res, status); + } + return packFloat32( aSign, 0xFF, 0 ); + } +@@ -5650,7 +5656,9 @@ float64 floatx80_to_float64(floatx80 a, float_status *status) + aSign = extractFloatx80Sign( a ); + if ( aExp == 0x7FFF ) { + if ( (uint64_t) ( aSig<<1 ) ) { +- return commonNaNToFloat64(floatx80ToCommonNaN(a, status), status); ++ float64 res = commonNaNToFloat64(floatx80ToCommonNaN(a, status), ++ status); ++ return float64_silence_nan(res, status); + } + return packFloat64( aSign, 0x7FF, 0 ); + } +@@ -5681,7 +5689,9 @@ float128 floatx80_to_float128(floatx80 a, float_status *status) + aExp = extractFloatx80Exp( a ); + aSign = extractFloatx80Sign( a ); + if ( ( aExp == 0x7FFF ) && (uint64_t) ( aSig<<1 ) ) { +- return commonNaNToFloat128(floatx80ToCommonNaN(a, status), status); ++ float128 res = commonNaNToFloat128(floatx80ToCommonNaN(a, status), ++ status); ++ return float128_silence_nan(res, status); + } + shift128Right( aSig<<1, 0, 16, &zSig0, &zSig1 ); + return packFloat128( aSign, aExp, zSig0, zSig1 ); +@@ -6959,7 +6969,9 @@ floatx80 float128_to_floatx80(float128 a, float_status *status) + aSign = extractFloat128Sign( a ); + if ( aExp == 0x7FFF ) { + if ( aSig0 | aSig1 ) { +- return commonNaNToFloatx80(float128ToCommonNaN(a, status), status); ++ floatx80 res = commonNaNToFloatx80(float128ToCommonNaN(a, status), ++ status); ++ return floatx80_silence_nan(res, status); + } + return packFloatx80(aSign, floatx80_infinity_high, + floatx80_infinity_low); +diff --git a/tests/tcg/i386/test-i386-snan-convert.c b/tests/tcg/i386/test-i386-snan-convert.c +new file mode 100644 +index 0000000000..ed6d535ce2 +--- /dev/null ++++ b/tests/tcg/i386/test-i386-snan-convert.c +@@ -0,0 +1,63 @@ ++/* Test conversions of signaling NaNs to and from long double. */ ++ ++#include ++#include ++ ++volatile float f_res; ++volatile double d_res; ++volatile long double ld_res; ++ ++volatile float f_snan = __builtin_nansf(""); ++volatile double d_snan = __builtin_nans(""); ++volatile long double ld_snan = __builtin_nansl(""); ++ ++int issignaling_f(float x) ++{ ++ union { float f; uint32_t u; } u = { .f = x }; ++ return (u.u & 0x7fffffff) > 0x7f800000 && (u.u & 0x400000) == 0; ++} ++ ++int issignaling_d(double x) ++{ ++ union { double d; uint64_t u; } u = { .d = x }; ++ return (((u.u & UINT64_C(0x7fffffffffffffff)) > ++ UINT64_C(0x7ff0000000000000)) && ++ (u.u & UINT64_C(0x8000000000000)) == 0); ++} ++ ++int issignaling_ld(long double x) ++{ ++ union { ++ long double ld; ++ struct { uint64_t sig; uint16_t sign_exp; } s; ++ } u = { .ld = x }; ++ return ((u.s.sign_exp & 0x7fff) == 0x7fff && ++ (u.s.sig >> 63) != 0 && ++ (u.s.sig & UINT64_C(0x4000000000000000)) == 0); ++} ++ ++int main(void) ++{ ++ int ret = 0; ++ ld_res = f_snan; ++ if (issignaling_ld(ld_res)) { ++ printf("FAIL: float -> long double\n"); ++ ret = 1; ++ } ++ ld_res = d_snan; ++ if (issignaling_ld(ld_res)) { ++ printf("FAIL: double -> long double\n"); ++ ret = 1; ++ } ++ f_res = ld_snan; ++ if (issignaling_d(f_res)) { ++ printf("FAIL: long double -> float\n"); ++ ret = 1; ++ } ++ d_res = ld_snan; ++ if (issignaling_d(d_res)) { ++ printf("FAIL: long double -> double\n"); ++ ret = 1; ++ } ++ return ret; ++} +-- +2.23.0 + diff --git a/spapr-Don-t-allow-unplug-of-NVLink2-devices.patch b/spapr-Don-t-allow-unplug-of-NVLink2-devices.patch new file mode 100644 index 0000000000000000000000000000000000000000..a0d587225d52fece0bc43339c5f3c7bb4cbf4507 --- /dev/null +++ b/spapr-Don-t-allow-unplug-of-NVLink2-devices.patch @@ -0,0 +1,37 @@ +From 05af7c77f5f24ef2bec25f2cab22170c29edaf37 Mon Sep 17 00:00:00 2001 +From: David Gibson +Date: Thu, 26 Mar 2020 16:27:37 +1100 +Subject: [PATCH 303/709] spapr: Don't allow unplug of NVLink2 devices + +Currently, we can't properly handle unplug of NVLink2 devices, because we +don't have code to tear down their special memory resources. There's not +a lot of impetus to implement that: since hardware NVLink2 devices can't +be hot unplugged, the guest side drivers don't usually support unplug +anyway. + +Therefore, simply prevent unplug of NVLink2 devices. + +Signed-off-by: David Gibson +Reviewed-by: Alexey Kardashevskiy +--- + hw/ppc/spapr_pci.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c +index 55ca9dee1e..61b84a392d 100644 +--- a/hw/ppc/spapr_pci.c ++++ b/hw/ppc/spapr_pci.c +@@ -1665,6 +1665,10 @@ static void spapr_pci_unplug_request(HotplugHandler *plug_handler, + error_setg(errp, "PCI: Hot unplug of PCI bridges not supported"); + return; + } ++ if (object_property_get_uint(OBJECT(pdev), "nvlink2-tgt", NULL)) { ++ error_setg(errp, "PCI: Cannot unplug NVLink2 devices"); ++ return; ++ } + + /* ensure any other present functions are pending unplug */ + if (PCI_FUNC(pdev->devfn) == 0) { +-- +2.23.0 + diff --git a/spapr-Don-t-check-capabilities-removed-between-CAS-c.patch b/spapr-Don-t-check-capabilities-removed-between-CAS-c.patch new file mode 100644 index 0000000000000000000000000000000000000000..61cf3d317a0797882bb9fce3e740130f328451ef --- /dev/null +++ b/spapr-Don-t-check-capabilities-removed-between-CAS-c.patch @@ -0,0 +1,68 @@ +From 86962462f89b2abbba18e5c2243d59bd408f04d4 Mon Sep 17 00:00:00 2001 +From: Greg Kurz +Date: Wed, 25 Mar 2020 16:25:30 +0100 +Subject: [PATCH 294/709] spapr: Don't check capabilities removed between CAS + calls + +We currently check if some capability in OV5 was removed by the guest +since the previous CAS, and we trigger a CAS reboot in that case. This +was required because it could call for a device-tree property or node +removal, that we didn't support until recently (see commit 6787d27b04a7 +"spapr: add option vector handling in CAS-generated resets" for details). + +Now that we render a full FDT at CAS and that SLOF is able to handle +node removal, we don't need to do a CAS reset in this case anymore. +Also, this check can only return true if the guest has already called +CAS since the last full system reset (otherwise spapr->ov5_cas is +empty). Linux doesn't do that so this can be considered as dead code +for the vast majority of existing setups. + +Drop the check. Since the only use of the ov5_cas_old variable is +precisely the check itself, drop the variable as well. + +Signed-off-by: Greg Kurz +Message-Id: <158514993021.478799.10928618293640651819.stgit@bahia.lan> +Signed-off-by: David Gibson +--- + hw/ppc/spapr_hcall.c | 14 +------------- + 1 file changed, 1 insertion(+), 13 deletions(-) + +diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c +index 0d50fc9117..e8ee447537 100644 +--- a/hw/ppc/spapr_hcall.c ++++ b/hw/ppc/spapr_hcall.c +@@ -1676,7 +1676,7 @@ static target_ulong h_client_architecture_support(PowerPCCPU *cpu, + target_ulong fdt_bufsize = args[2]; + target_ulong ov_table; + uint32_t cas_pvr; +- SpaprOptionVector *ov1_guest, *ov5_guest, *ov5_cas_old; ++ SpaprOptionVector *ov1_guest, *ov5_guest; + bool guest_radix; + Error *local_err = NULL; + bool raw_mode_supported = false; +@@ -1782,22 +1782,10 @@ static target_ulong h_client_architecture_support(PowerPCCPU *cpu, + * by LoPAPR 1.1, 14.5.4.8, which QEMU doesn't implement, we don't need + * to worry about this for now. + */ +- ov5_cas_old = spapr_ovec_clone(spapr->ov5_cas); +- +- /* also clear the radix/hash bit from the current ov5_cas bits to +- * be in sync with the newly ov5 bits. Else the radix bit will be +- * seen as being removed and this will generate a reset loop +- */ +- spapr_ovec_clear(ov5_cas_old, OV5_MMU_RADIX_300); + + /* full range of negotiated ov5 capabilities */ + spapr_ovec_intersect(spapr->ov5_cas, spapr->ov5, ov5_guest); + spapr_ovec_cleanup(ov5_guest); +- /* capabilities that have been added since CAS-generated guest reset. +- * if capabilities have since been removed, generate another reset +- */ +- spapr->cas_reboot = !spapr_ovec_subset(ov5_cas_old, spapr->ov5_cas); +- spapr_ovec_cleanup(ov5_cas_old); + /* Now that processing is finished, set the radix/hash bit for the + * guest if it requested a valid mode; otherwise terminate the boot. */ + if (guest_radix) { +-- +2.23.0 + diff --git a/spapr-Drop-CAS-reboot-flag.patch b/spapr-Drop-CAS-reboot-flag.patch new file mode 100644 index 0000000000000000000000000000000000000000..20958ec8f6bdec9d7572f38998851c3c7f468f90 --- /dev/null +++ b/spapr-Drop-CAS-reboot-flag.patch @@ -0,0 +1,134 @@ +From 087820e37f05c391c1ea77b1761ed489c928872e Mon Sep 17 00:00:00 2001 +From: Greg Kurz +Date: Wed, 25 Mar 2020 16:25:49 +0100 +Subject: [PATCH 299/709] spapr: Drop CAS reboot flag + +The CAS reboot flag is false by default and all the locations that +could set it to true have been dropped. This means that all code +blocks depending on the flag being set is dead code and the other +code blocks should be executed always. + +Just do that and drop the now uneeded CAS reboot flag. Fix a +comment on the way to make checkpatch happy. + +Signed-off-by: Greg Kurz +Message-Id: <158514994893.478799.11772512888322840990.stgit@bahia.lan> +Signed-off-by: David Gibson +--- + hw/ppc/spapr.c | 18 ++++-------------- + hw/ppc/spapr_hcall.c | 33 ++++++++++++++------------------- + include/hw/ppc/spapr.h | 1 - + 3 files changed, 18 insertions(+), 34 deletions(-) + +diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c +index f52488d397..841b5ec59b 100644 +--- a/hw/ppc/spapr.c ++++ b/hw/ppc/spapr.c +@@ -1579,9 +1579,7 @@ void spapr_setup_hpt(SpaprMachineState *spapr) + { + int hpt_shift; + +- if ((spapr->resize_hpt == SPAPR_RESIZE_HPT_DISABLED) +- || (spapr->cas_reboot +- && !spapr_ovec_test(spapr->ov5_cas, OV5_HPT_RESIZE))) { ++ if (spapr->resize_hpt == SPAPR_RESIZE_HPT_DISABLED) { + hpt_shift = spapr_hpt_shift_for_ramsize(MACHINE(spapr)->maxram_size); + } else { + uint64_t current_ram_size; +@@ -1645,16 +1643,10 @@ static void spapr_machine_reset(MachineState *machine) + + qemu_devices_reset(); + +- /* +- * If this reset wasn't generated by CAS, we should reset our +- * negotiated options and start from scratch +- */ +- if (!spapr->cas_reboot) { +- spapr_ovec_cleanup(spapr->ov5_cas); +- spapr->ov5_cas = spapr_ovec_new(); ++ spapr_ovec_cleanup(spapr->ov5_cas); ++ spapr->ov5_cas = spapr_ovec_new(); + +- ppc_set_compat_all(spapr->max_compat_pvr, &error_fatal); +- } ++ ppc_set_compat_all(spapr->max_compat_pvr, &error_fatal); + + /* + * This is fixing some of the default configuration of the XIVE +@@ -1707,8 +1699,6 @@ static void spapr_machine_reset(MachineState *machine) + spapr_cpu_set_entry_state(first_ppc_cpu, SPAPR_ENTRY_POINT, 0, fdt_addr, 0); + first_ppc_cpu->env.gpr[5] = 0; + +- spapr->cas_reboot = false; +- + spapr->fwnmi_system_reset_addr = -1; + spapr->fwnmi_machine_check_addr = -1; + spapr->fwnmi_machine_check_interlock = -1; +diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c +index 48a8745514..0f54988f2e 100644 +--- a/hw/ppc/spapr_hcall.c ++++ b/hw/ppc/spapr_hcall.c +@@ -1678,6 +1678,7 @@ target_ulong do_client_architecture_support(PowerPCCPU *cpu, + bool raw_mode_supported = false; + bool guest_xive; + CPUState *cs; ++ void *fdt; + + /* CAS is supposed to be called early when only the boot vCPU is active. */ + CPU_FOREACH(cs) { +@@ -1818,27 +1819,21 @@ target_ulong do_client_architecture_support(PowerPCCPU *cpu, + + spapr_handle_transient_dev_before_cas(spapr); + +- if (!spapr->cas_reboot) { +- void *fdt; +- +- /* If spapr_machine_reset() did not set up a HPT but one is necessary +- * (because the guest isn't going to use radix) then set it up here. */ +- if ((spapr->patb_entry & PATE1_GR) && !guest_radix) { +- /* legacy hash or new hash: */ +- spapr_setup_hpt(spapr); +- } +- +- fdt = spapr_build_fdt(spapr, false, fdt_bufsize); +- +- g_free(spapr->fdt_blob); +- spapr->fdt_size = fdt_totalsize(fdt); +- spapr->fdt_initial_size = spapr->fdt_size; +- spapr->fdt_blob = fdt; ++ /* ++ * If spapr_machine_reset() did not set up a HPT but one is necessary ++ * (because the guest isn't going to use radix) then set it up here. ++ */ ++ if ((spapr->patb_entry & PATE1_GR) && !guest_radix) { ++ /* legacy hash or new hash: */ ++ spapr_setup_hpt(spapr); + } + +- if (spapr->cas_reboot) { +- qemu_system_reset_request(SHUTDOWN_CAUSE_SUBSYSTEM_RESET); +- } ++ fdt = spapr_build_fdt(spapr, false, fdt_bufsize); ++ ++ g_free(spapr->fdt_blob); ++ spapr->fdt_size = fdt_totalsize(fdt); ++ spapr->fdt_initial_size = spapr->fdt_size; ++ spapr->fdt_blob = fdt; + + return H_SUCCESS; + } +diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h +index b7e13e5aaf..e579eaf28c 100644 +--- a/include/hw/ppc/spapr.h ++++ b/include/hw/ppc/spapr.h +@@ -178,7 +178,6 @@ struct SpaprMachineState { + SpaprEventSource *event_sources; + + /* ibm,client-architecture-support option negotiation */ +- bool cas_reboot; + bool cas_pre_isa3_guest; + SpaprOptionVector *ov5; /* QEMU-supported option vectors */ + SpaprOptionVector *ov5_cas; /* negotiated (via CAS) option vectors */ +-- +2.23.0 + diff --git a/spapr-Simplify-selection-of-radix-hash-during-CAS.patch b/spapr-Simplify-selection-of-radix-hash-during-CAS.patch new file mode 100644 index 0000000000000000000000000000000000000000..c0560c7eb30f5e6675256b7910f873121f70f37e --- /dev/null +++ b/spapr-Simplify-selection-of-radix-hash-during-CAS.patch @@ -0,0 +1,80 @@ +From b4b83312e72461540ee155006f0d49e33bf0c58d Mon Sep 17 00:00:00 2001 +From: Greg Kurz +Date: Wed, 25 Mar 2020 16:25:36 +0100 +Subject: [PATCH 297/709] spapr: Simplify selection of radix/hash during CAS + +The guest can select the MMU mode by setting bits 0-1 of byte 24 +in OV5 to to 0b00 for hash or 0b01 for radix. As required by the +architecture, we terminate the boot process if any other value +is found there. + +The usual way to negotiate features in OV5 is basically ANDing +the bitfield provided by the guest and the bitfield of features +supported by QEMU, previously populated at machine init. + +For some not documented reason, MMU is treated differently : bit 1 +of byte 24 (the radix/hash bit) is cleared from the guest OV5 and +explicitely set in the final negotiated OV5 if radix was requested. + +Since the only expected input from the guest is the radix/hash bit +being set or not, it seems more appropriate to handle this like we +do for XIVE. + +Set the radix bit in spapr->ov5 at machine init if it has a chance +to work (ie. power9, either TCG or a radix capable KVM) and rely +exclusively on spapr_ovec_intersect() to set the radix bit in +spapr->ov5_cas. + +Signed-off-by: Greg Kurz +Message-Id: <158514993621.478799.4204740354545734293.stgit@bahia.lan> +Signed-off-by: David Gibson +--- + hw/ppc/spapr.c | 1 + + hw/ppc/spapr_hcall.c | 6 +----- + 2 files changed, 2 insertions(+), 5 deletions(-) + +diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c +index 785c41d205..167b1216ba 100644 +--- a/hw/ppc/spapr.c ++++ b/hw/ppc/spapr.c +@@ -2837,6 +2837,7 @@ static void spapr_machine_init(MachineState *machine) + if ((!kvm_enabled() || kvmppc_has_cap_mmu_radix()) && + ppc_type_check_compat(machine->cpu_type, CPU_POWERPC_LOGICAL_3_00, 0, + spapr->max_compat_pvr)) { ++ spapr_ovec_set(spapr->ov5, OV5_MMU_RADIX_300); + /* KVM and TCG always allow GTSE with radix... */ + spapr_ovec_set(spapr->ov5, OV5_MMU_RADIX_GTSE); + } +diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c +index e8ee447537..fb4fdd4a0c 100644 +--- a/hw/ppc/spapr_hcall.c ++++ b/hw/ppc/spapr_hcall.c +@@ -1739,9 +1739,7 @@ static target_ulong h_client_architecture_support(PowerPCCPU *cpu, + exit(EXIT_FAILURE); + } + +- /* The radix/hash bit in byte 24 requires special handling: */ + guest_radix = spapr_ovec_test(ov5_guest, OV5_MMU_RADIX_300); +- spapr_ovec_clear(ov5_guest, OV5_MMU_RADIX_300); + + guest_xive = spapr_ovec_test(ov5_guest, OV5_XIVE_EXPLOIT); + +@@ -1786,14 +1784,12 @@ static target_ulong h_client_architecture_support(PowerPCCPU *cpu, + /* full range of negotiated ov5 capabilities */ + spapr_ovec_intersect(spapr->ov5_cas, spapr->ov5, ov5_guest); + spapr_ovec_cleanup(ov5_guest); +- /* Now that processing is finished, set the radix/hash bit for the +- * guest if it requested a valid mode; otherwise terminate the boot. */ ++ + if (guest_radix) { + if (kvm_enabled() && !kvmppc_has_cap_mmu_radix()) { + error_report("Guest requested unavailable MMU mode (radix)."); + exit(EXIT_FAILURE); + } +- spapr_ovec_set(spapr->ov5_cas, OV5_MMU_RADIX_300); + } else { + if (kvm_enabled() && kvmppc_has_cap_mmu_radix() + && !kvmppc_has_cap_mmu_hash_v3()) { +-- +2.23.0 + diff --git a/spapr-cas-Separate-CAS-handling-from-rebuilding-the-.patch b/spapr-cas-Separate-CAS-handling-from-rebuilding-the-.patch new file mode 100644 index 0000000000000000000000000000000000000000..5e9906c2f418f477ecc929ac412ae36aa6357c47 --- /dev/null +++ b/spapr-cas-Separate-CAS-handling-from-rebuilding-the-.patch @@ -0,0 +1,187 @@ +From 91067db1abcdc6caf951494b8d7e4bfaaa0cb61d Mon Sep 17 00:00:00 2001 +From: Alexey Kardashevskiy +Date: Wed, 25 Mar 2020 16:25:42 +0100 +Subject: [PATCH 298/709] spapr/cas: Separate CAS handling from rebuilding the + FDT + +At the moment "ibm,client-architecture-support" ("CAS") is implemented +in SLOF and QEMU assists via the custom H_CAS hypercall which copies +an updated flatten device tree (FDT) blob to the SLOF memory which +it then uses to update its internal tree. + +When we enable the OpenFirmware client interface in QEMU, we won't need +to copy the FDT to the guest as the client is expected to fetch +the device tree using the client interface. + +This moves FDT rebuild out to a separate helper which is going to be +called from the "ibm,client-architecture-support" handler and leaves +writing FDT to the guest in the H_CAS handler. + +This should not cause any behavioral change. + +Signed-off-by: Alexey Kardashevskiy +Message-Id: <20200310050733.29805-3-aik@ozlabs.ru> +Signed-off-by: Greg Kurz +Message-Id: <158514994229.478799.2178881312094922324.stgit@bahia.lan> +Signed-off-by: David Gibson +--- + hw/ppc/spapr.c | 1 - + hw/ppc/spapr_hcall.c | 67 ++++++++++++++++++++++++++---------------- + include/hw/ppc/spapr.h | 7 +++++ + 3 files changed, 48 insertions(+), 27 deletions(-) + +diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c +index 167b1216ba..f52488d397 100644 +--- a/hw/ppc/spapr.c ++++ b/hw/ppc/spapr.c +@@ -96,7 +96,6 @@ + * + * We load our kernel at 4M, leaving space for SLOF initial image + */ +-#define FDT_MAX_SIZE 0x100000 + #define RTAS_MAX_ADDR 0x80000000 /* RTAS must stay below that */ + #define FW_MAX_SIZE 0x400000 + #define FW_FILE_NAME "slof.bin" +diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c +index fb4fdd4a0c..48a8745514 100644 +--- a/hw/ppc/spapr_hcall.c ++++ b/hw/ppc/spapr_hcall.c +@@ -1665,16 +1665,12 @@ static void spapr_handle_transient_dev_before_cas(SpaprMachineState *spapr) + spapr_clear_pending_hotplug_events(spapr); + } + +-static target_ulong h_client_architecture_support(PowerPCCPU *cpu, +- SpaprMachineState *spapr, +- target_ulong opcode, +- target_ulong *args) ++target_ulong do_client_architecture_support(PowerPCCPU *cpu, ++ SpaprMachineState *spapr, ++ target_ulong vec, ++ target_ulong fdt_bufsize) + { +- /* Working address in data buffer */ +- target_ulong addr = ppc64_phys_to_real(args[0]); +- target_ulong fdt_buf = args[1]; +- target_ulong fdt_bufsize = args[2]; +- target_ulong ov_table; ++ target_ulong ov_table; /* Working address in data buffer */ + uint32_t cas_pvr; + SpaprOptionVector *ov1_guest, *ov5_guest; + bool guest_radix; +@@ -1694,7 +1690,7 @@ static target_ulong h_client_architecture_support(PowerPCCPU *cpu, + } + } + +- cas_pvr = cas_check_pvr(spapr, cpu, &addr, &raw_mode_supported, &local_err); ++ cas_pvr = cas_check_pvr(spapr, cpu, &vec, &raw_mode_supported, &local_err); + if (local_err) { + error_report_err(local_err); + return H_HARDWARE; +@@ -1717,7 +1713,7 @@ static target_ulong h_client_architecture_support(PowerPCCPU *cpu, + } + + /* For the future use: here @ov_table points to the first option vector */ +- ov_table = addr; ++ ov_table = vec; + + ov1_guest = spapr_ovec_parse_vector(ov_table, 1); + if (!ov1_guest) { +@@ -1824,7 +1820,6 @@ static target_ulong h_client_architecture_support(PowerPCCPU *cpu, + + if (!spapr->cas_reboot) { + void *fdt; +- SpaprDeviceTreeUpdateHeader hdr = { .version_id = 1 }; + + /* If spapr_machine_reset() did not set up a HPT but one is necessary + * (because the guest isn't going to use radix) then set it up here. */ +@@ -1833,21 +1828,7 @@ static target_ulong h_client_architecture_support(PowerPCCPU *cpu, + spapr_setup_hpt(spapr); + } + +- if (fdt_bufsize < sizeof(hdr)) { +- error_report("SLOF provided insufficient CAS buffer " +- TARGET_FMT_lu " (min: %zu)", fdt_bufsize, sizeof(hdr)); +- exit(EXIT_FAILURE); +- } +- +- fdt_bufsize -= sizeof(hdr); +- + fdt = spapr_build_fdt(spapr, false, fdt_bufsize); +- _FDT((fdt_pack(fdt))); +- +- cpu_physical_memory_write(fdt_buf, &hdr, sizeof(hdr)); +- cpu_physical_memory_write(fdt_buf + sizeof(hdr), fdt, +- fdt_totalsize(fdt)); +- trace_spapr_cas_continue(fdt_totalsize(fdt) + sizeof(hdr)); + + g_free(spapr->fdt_blob); + spapr->fdt_size = fdt_totalsize(fdt); +@@ -1862,6 +1843,40 @@ static target_ulong h_client_architecture_support(PowerPCCPU *cpu, + return H_SUCCESS; + } + ++static target_ulong h_client_architecture_support(PowerPCCPU *cpu, ++ SpaprMachineState *spapr, ++ target_ulong opcode, ++ target_ulong *args) ++{ ++ target_ulong vec = ppc64_phys_to_real(args[0]); ++ target_ulong fdt_buf = args[1]; ++ target_ulong fdt_bufsize = args[2]; ++ target_ulong ret; ++ SpaprDeviceTreeUpdateHeader hdr = { .version_id = 1 }; ++ ++ if (fdt_bufsize < sizeof(hdr)) { ++ error_report("SLOF provided insufficient CAS buffer " ++ TARGET_FMT_lu " (min: %zu)", fdt_bufsize, sizeof(hdr)); ++ exit(EXIT_FAILURE); ++ } ++ ++ fdt_bufsize -= sizeof(hdr); ++ ++ ret = do_client_architecture_support(cpu, spapr, vec, fdt_bufsize); ++ if (ret == H_SUCCESS) { ++ _FDT((fdt_pack(spapr->fdt_blob))); ++ spapr->fdt_size = fdt_totalsize(spapr->fdt_blob); ++ spapr->fdt_initial_size = spapr->fdt_size; ++ ++ cpu_physical_memory_write(fdt_buf, &hdr, sizeof(hdr)); ++ cpu_physical_memory_write(fdt_buf + sizeof(hdr), spapr->fdt_blob, ++ spapr->fdt_size); ++ trace_spapr_cas_continue(spapr->fdt_size + sizeof(hdr)); ++ } ++ ++ return ret; ++} ++ + static target_ulong h_home_node_associativity(PowerPCCPU *cpu, + SpaprMachineState *spapr, + target_ulong opcode, +diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h +index 42d64a0368..b7e13e5aaf 100644 +--- a/include/hw/ppc/spapr.h ++++ b/include/hw/ppc/spapr.h +@@ -102,6 +102,8 @@ typedef enum { + #define SPAPR_CAP_FIXED_CCD 0x03 + #define SPAPR_CAP_FIXED_NA 0x10 /* Lets leave a bit of a gap... */ + ++#define FDT_MAX_SIZE 0x100000 ++ + typedef struct SpaprCapabilities SpaprCapabilities; + struct SpaprCapabilities { + uint8_t caps[SPAPR_CAP_NUM]; +@@ -566,6 +568,11 @@ void spapr_register_hypercall(target_ulong opcode, spapr_hcall_fn fn); + target_ulong spapr_hypercall(PowerPCCPU *cpu, target_ulong opcode, + target_ulong *args); + ++target_ulong do_client_architecture_support(PowerPCCPU *cpu, ++ SpaprMachineState *spapr, ++ target_ulong addr, ++ target_ulong fdt_bufsize); ++ + /* Virtual Processor Area structure constants */ + #define VPA_MIN_SIZE 640 + #define VPA_SIZE_OFFSET 0x4 +-- +2.23.0 + diff --git a/spapr_nvdimm-Tweak-error-messages.patch b/spapr_nvdimm-Tweak-error-messages.patch new file mode 100644 index 0000000000000000000000000000000000000000..efa7528f216fc8c51402bcf811efe46d1e51a4f9 --- /dev/null +++ b/spapr_nvdimm-Tweak-error-messages.patch @@ -0,0 +1,38 @@ +From 6c0f0cb319bd9f906d461a2e12a2b5d1eb588fa2 Mon Sep 17 00:00:00 2001 +From: David Gibson +Date: Fri, 24 Apr 2020 11:56:17 +1000 +Subject: [PATCH 309/709] spapr_nvdimm: Tweak error messages + +The restrictions here (which are checked at pre-plug time) are PAPR +specific, rather than being inherent to the NVDIMM devices. Adjust the +error messages to be clearer about this. + +Signed-off-by: David Gibson +--- + hw/ppc/spapr_nvdimm.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/hw/ppc/spapr_nvdimm.c b/hw/ppc/spapr_nvdimm.c +index 9abcdcc26b..81410aa63f 100644 +--- a/hw/ppc/spapr_nvdimm.c ++++ b/hw/ppc/spapr_nvdimm.c +@@ -39,13 +39,13 @@ void spapr_nvdimm_validate_opts(NVDIMMDevice *nvdimm, uint64_t size, + + if (object_property_get_int(OBJECT(nvdimm), NVDIMM_LABEL_SIZE_PROP, + &error_abort) == 0) { +- error_setg(errp, "NVDIMM device requires label-size to be set"); ++ error_setg(errp, "PAPR requires NVDIMM devices to have label-size set"); + return; + } + + if (size % SPAPR_MINIMUM_SCM_BLOCK_SIZE) { +- error_setg(errp, "NVDIMM memory size excluding the label area" +- " must be a multiple of %" PRIu64 "MB", ++ error_setg(errp, "PAPR requires NVDIMM memory size (excluding label)" ++ " to be a multiple of %" PRIu64 "MB", + SPAPR_MINIMUM_SCM_BLOCK_SIZE / MiB); + return; + } +-- +2.23.0 + diff --git a/spapr_nvdimm.c-make-label-size-mandatory.patch b/spapr_nvdimm.c-make-label-size-mandatory.patch new file mode 100644 index 0000000000000000000000000000000000000000..4b6e0d0154859f73578f60ea110f9dfd159c5a55 --- /dev/null +++ b/spapr_nvdimm.c-make-label-size-mandatory.patch @@ -0,0 +1,44 @@ +From 70fc9cb0920fce3c2c0a090e69bf06d39f4b2362 Mon Sep 17 00:00:00 2001 +From: Daniel Henrique Barboza +Date: Mon, 13 Apr 2020 17:36:28 -0300 +Subject: [PATCH 308/709] spapr_nvdimm.c: make 'label-size' mandatory + +The pseries machine does not support NVDIMM modules without label. +Attempting to do so, even if the overall block size is aligned with +256MB, will seg fault the guest kernel during NVDIMM probe. This +can be avoided by forcing 'label-size' to always be present for +sPAPR NVDIMMs. + +The verification was put before the alignment check because the +presence of label-size affects the alignment calculation, so +it's not optimal to warn the user about an alignment error, +then about the lack of label-size, then about a new alignment +error when the user sets a label-size. + +Signed-off-by: Daniel Henrique Barboza +Message-Id: <20200413203628.31636-1-danielhb413@gmail.com> +Signed-off-by: David Gibson +--- + hw/ppc/spapr_nvdimm.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/hw/ppc/spapr_nvdimm.c b/hw/ppc/spapr_nvdimm.c +index 25be8082d7..9abcdcc26b 100644 +--- a/hw/ppc/spapr_nvdimm.c ++++ b/hw/ppc/spapr_nvdimm.c +@@ -37,6 +37,12 @@ void spapr_nvdimm_validate_opts(NVDIMMDevice *nvdimm, uint64_t size, + QemuUUID uuid; + int ret; + ++ if (object_property_get_int(OBJECT(nvdimm), NVDIMM_LABEL_SIZE_PROP, ++ &error_abort) == 0) { ++ error_setg(errp, "NVDIMM device requires label-size to be set"); ++ return; ++ } ++ + if (size % SPAPR_MINIMUM_SCM_BLOCK_SIZE) { + error_setg(errp, "NVDIMM memory size excluding the label area" + " must be a multiple of %" PRIu64 "MB", +-- +2.23.0 + diff --git a/spapr_pci-Drop-some-dead-error-handling.patch b/spapr_pci-Drop-some-dead-error-handling.patch new file mode 100644 index 0000000000000000000000000000000000000000..01364060a174ca20f4683a124532013ba1bac879 --- /dev/null +++ b/spapr_pci-Drop-some-dead-error-handling.patch @@ -0,0 +1,225 @@ +From 7ef1553dac8ef8dbe547b58d7420461a16be0eeb Mon Sep 17 00:00:00 2001 +From: Markus Armbruster +Date: Tue, 5 May 2020 17:29:25 +0200 +Subject: [PATCH 479/709] spapr_pci: Drop some dead error handling +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +chassis_from_bus() uses object_property_get_uint() to get property +"chassis_nr" of the bridge device. Failure would be a programming +error. Pass &error_abort, and simplify its callers. + +Cc: David Gibson +Cc: qemu-ppc@nongnu.org +Signed-off-by: Markus Armbruster +Acked-by: David Gibson +Reviewed-by: Greg Kurz +Reviewed-by: Philippe Mathieu-Daudé +Reviewed-by: Paolo Bonzini +Message-Id: <20200505152926.18877-18-armbru@redhat.com> +--- + hw/ppc/spapr_pci.c | 86 ++++++++++------------------------------------ + 1 file changed, 18 insertions(+), 68 deletions(-) + +diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c +index 616034222d..83f1453096 100644 +--- a/hw/ppc/spapr_pci.c ++++ b/hw/ppc/spapr_pci.c +@@ -1203,46 +1203,36 @@ static SpaprDrc *drc_from_devfn(SpaprPhbState *phb, + drc_id_from_devfn(phb, chassis, devfn)); + } + +-static uint8_t chassis_from_bus(PCIBus *bus, Error **errp) ++static uint8_t chassis_from_bus(PCIBus *bus) + { + if (pci_bus_is_root(bus)) { + return 0; + } else { + PCIDevice *bridge = pci_bridge_get_device(bus); + +- return object_property_get_uint(OBJECT(bridge), "chassis_nr", errp); ++ return object_property_get_uint(OBJECT(bridge), "chassis_nr", ++ &error_abort); + } + } + + static SpaprDrc *drc_from_dev(SpaprPhbState *phb, PCIDevice *dev) + { +- Error *local_err = NULL; +- uint8_t chassis = chassis_from_bus(pci_get_bus(dev), &local_err); +- +- if (local_err) { +- error_report_err(local_err); +- return NULL; +- } ++ uint8_t chassis = chassis_from_bus(pci_get_bus(dev)); + + return drc_from_devfn(phb, chassis, dev->devfn); + } + +-static void add_drcs(SpaprPhbState *phb, PCIBus *bus, Error **errp) ++static void add_drcs(SpaprPhbState *phb, PCIBus *bus) + { + Object *owner; + int i; + uint8_t chassis; +- Error *local_err = NULL; + + if (!phb->dr_enabled) { + return; + } + +- chassis = chassis_from_bus(bus, &local_err); +- if (local_err) { +- error_propagate(errp, local_err); +- return; +- } ++ chassis = chassis_from_bus(bus); + + if (pci_bus_is_root(bus)) { + owner = OBJECT(phb); +@@ -1256,21 +1246,16 @@ static void add_drcs(SpaprPhbState *phb, PCIBus *bus, Error **errp) + } + } + +-static void remove_drcs(SpaprPhbState *phb, PCIBus *bus, Error **errp) ++static void remove_drcs(SpaprPhbState *phb, PCIBus *bus) + { + int i; + uint8_t chassis; +- Error *local_err = NULL; + + if (!phb->dr_enabled) { + return; + } + +- chassis = chassis_from_bus(bus, &local_err); +- if (local_err) { +- error_propagate(errp, local_err); +- return; +- } ++ chassis = chassis_from_bus(bus); + + for (i = PCI_SLOT_MAX * PCI_FUNC_MAX - 1; i >= 0; i--) { + SpaprDrc *drc = drc_from_devfn(phb, chassis, i); +@@ -1488,17 +1473,11 @@ int spapr_pci_dt_populate(SpaprDrc *drc, SpaprMachineState *spapr, + } + + static void spapr_pci_bridge_plug(SpaprPhbState *phb, +- PCIBridge *bridge, +- Error **errp) ++ PCIBridge *bridge) + { +- Error *local_err = NULL; + PCIBus *bus = pci_bridge_get_sec_bus(bridge); + +- add_drcs(phb, bus, &local_err); +- if (local_err) { +- error_propagate(errp, local_err); +- return; +- } ++ add_drcs(phb, bus); + } + + static void spapr_pci_plug(HotplugHandler *plug_handler, +@@ -1529,11 +1508,7 @@ static void spapr_pci_plug(HotplugHandler *plug_handler, + g_assert(drc); + + if (pc->is_bridge) { +- spapr_pci_bridge_plug(phb, PCI_BRIDGE(plugged_dev), &local_err); +- if (local_err) { +- error_propagate(errp, local_err); +- return; +- } ++ spapr_pci_bridge_plug(phb, PCI_BRIDGE(plugged_dev)); + } + + /* Following the QEMU convention used for PCIe multifunction +@@ -1560,12 +1535,7 @@ static void spapr_pci_plug(HotplugHandler *plug_handler, + spapr_drc_reset(drc); + } else if (PCI_FUNC(pdev->devfn) == 0) { + int i; +- uint8_t chassis = chassis_from_bus(pci_get_bus(pdev), &local_err); +- +- if (local_err) { +- error_propagate(errp, local_err); +- return; +- } ++ uint8_t chassis = chassis_from_bus(pci_get_bus(pdev)); + + for (i = 0; i < 8; i++) { + SpaprDrc *func_drc; +@@ -1587,17 +1557,11 @@ out: + } + + static void spapr_pci_bridge_unplug(SpaprPhbState *phb, +- PCIBridge *bridge, +- Error **errp) ++ PCIBridge *bridge) + { +- Error *local_err = NULL; + PCIBus *bus = pci_bridge_get_sec_bus(bridge); + +- remove_drcs(phb, bus, &local_err); +- if (local_err) { +- error_propagate(errp, local_err); +- return; +- } ++ remove_drcs(phb, bus); + } + + static void spapr_pci_unplug(HotplugHandler *plug_handler, +@@ -1619,11 +1583,7 @@ static void spapr_pci_unplug(HotplugHandler *plug_handler, + pci_device_reset(PCI_DEVICE(plugged_dev)); + + if (pc->is_bridge) { +- Error *local_err = NULL; +- spapr_pci_bridge_unplug(phb, PCI_BRIDGE(plugged_dev), &local_err); +- if (local_err) { +- error_propagate(errp, local_err); +- } ++ spapr_pci_bridge_unplug(phb, PCI_BRIDGE(plugged_dev)); + return; + } + +@@ -1654,13 +1614,7 @@ static void spapr_pci_unplug_request(HotplugHandler *plug_handler, + SpaprDrcClass *func_drck; + SpaprDREntitySense state; + int i; +- Error *local_err = NULL; +- uint8_t chassis = chassis_from_bus(pci_get_bus(pdev), &local_err); +- +- if (local_err) { +- error_propagate(errp, local_err); +- return; +- } ++ uint8_t chassis = chassis_from_bus(pci_get_bus(pdev)); + + if (pc->is_bridge) { + error_setg(errp, "PCI: Hot unplug of PCI bridges not supported"); +@@ -1745,7 +1699,7 @@ static void spapr_phb_unrealize(DeviceState *dev) + } + } + +- remove_drcs(sphb, phb->bus, &error_abort); ++ remove_drcs(sphb, phb->bus); + + for (i = PCI_NUM_PINS - 1; i >= 0; i--) { + if (sphb->lsi_table[i].irq) { +@@ -1984,11 +1938,7 @@ static void spapr_phb_realize(DeviceState *dev, Error **errp) + } + + /* allocate connectors for child PCI devices */ +- add_drcs(sphb, phb->bus, &local_err); +- if (local_err) { +- error_propagate(errp, local_err); +- goto unrealize; +- } ++ add_drcs(sphb, phb->bus); + + /* DMA setup */ + for (i = 0; i < windows_supported; ++i) { +-- +2.23.0 + diff --git a/ssh-Support-BDRV_REQ_ZERO_WRITE-for-truncate.patch b/ssh-Support-BDRV_REQ_ZERO_WRITE-for-truncate.patch new file mode 100644 index 0000000000000000000000000000000000000000..6310759e8533e453bd46b21076055c347b003421 --- /dev/null +++ b/ssh-Support-BDRV_REQ_ZERO_WRITE-for-truncate.patch @@ -0,0 +1,36 @@ +From be9c9404db7e6992946fa55c75ca61dfb20926eb Mon Sep 17 00:00:00 2001 +From: Eric Blake +Date: Tue, 28 Apr 2020 15:29:02 -0500 +Subject: [PATCH 354/709] ssh: Support BDRV_REQ_ZERO_WRITE for truncate + +Our .bdrv_has_zero_init_truncate can detect when the remote side +always zero fills; we can reuse that same knowledge to implement +BDRV_REQ_ZERO_WRITE by ignoring it when the server gives it to us for +free. + +Signed-off-by: Eric Blake +Message-Id: <20200428202905.770727-7-eblake@redhat.com> +Reviewed-by: Richard W.M. Jones +Signed-off-by: Kevin Wolf +--- + block/ssh.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/block/ssh.c b/block/ssh.c +index 9eb33df859..f9e08a4900 100644 +--- a/block/ssh.c ++++ b/block/ssh.c +@@ -883,6 +883,10 @@ static int ssh_file_open(BlockDriverState *bs, QDict *options, int bdrv_flags, + /* Go non-blocking. */ + ssh_set_blocking(s->session, 0); + ++ if (s->attrs->type == SSH_FILEXFER_TYPE_REGULAR) { ++ bs->supported_truncate_flags = BDRV_REQ_ZERO_WRITE; ++ } ++ + qapi_free_BlockdevOptionsSsh(opts); + + return 0; +-- +2.23.0 + diff --git a/target-Remove-unnecessary-CPU-cast.patch b/target-Remove-unnecessary-CPU-cast.patch new file mode 100644 index 0000000000000000000000000000000000000000..fdb897d168bffcaed7a551936c1d0d1813cac9a7 --- /dev/null +++ b/target-Remove-unnecessary-CPU-cast.patch @@ -0,0 +1,58 @@ +From 96449e4a30a56e3303d6d0407aca130c71671754 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Tue, 12 May 2020 09:00:18 +0200 +Subject: [PATCH 481/709] target: Remove unnecessary CPU() cast +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The CPU() macro is defined as: + + #define CPU(obj) ((CPUState *)(obj)) + +which expands to: + + ((CPUState *)object_dynamic_cast_assert((Object *)(obj), (name), + __FILE__, __LINE__, __func__)) + +This assertion can only fail when @obj points to something other +than its stated type, i.e. when we're in undefined behavior country. + +Remove the unnecessary CPU() casts when we already know the pointer +is of CPUState type. + +Patch created mechanically using spatch with this script: + + @@ + typedef CPUState; + CPUState *s; + @@ + - CPU(s) + + s + +Acked-by: David Gibson +Reviewed-by: Cédric Le Goater +Reviewed-by: Richard Henderson +Reviewed-by: Markus Armbruster +Signed-off-by: Philippe Mathieu-Daudé +Message-Id: <20200512070020.22782-2-f4bug@amsat.org> +--- + target/ppc/mmu_helper.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/target/ppc/mmu_helper.c b/target/ppc/mmu_helper.c +index 86c667b094..8972714775 100644 +--- a/target/ppc/mmu_helper.c ++++ b/target/ppc/mmu_helper.c +@@ -1820,7 +1820,7 @@ static inline void do_invalidate_BAT(CPUPPCState *env, target_ulong BATu, + if (((end - base) >> TARGET_PAGE_BITS) > 1024) { + /* Flushing 1024 4K pages is slower than a complete flush */ + LOG_BATS("Flush all BATs\n"); +- tlb_flush(CPU(cs)); ++ tlb_flush(cs); + LOG_BATS("Flush done\n"); + return; + } +-- +2.23.0 + diff --git a/target-arm-Add-new-s1_is_el0-argument-to-get_phys_ad.patch b/target-arm-Add-new-s1_is_el0-argument-to-get_phys_ad.patch new file mode 100644 index 0000000000000000000000000000000000000000..f4a6a1ecdc5dd88ee299832d5e90a2a1d37fe795 --- /dev/null +++ b/target-arm-Add-new-s1_is_el0-argument-to-get_phys_ad.patch @@ -0,0 +1,97 @@ +From ff7de2fc2c994030bfb83af9ddc9a3cd70ce3e88 Mon Sep 17 00:00:00 2001 +From: Peter Maydell +Date: Mon, 30 Mar 2020 22:03:59 +0100 +Subject: [PATCH 153/709] target/arm: Add new 's1_is_el0' argument to + get_phys_addr_lpae() + +For ARMv8.2-TTS2UXN, the stage 2 page table walk wants to know +whether the stage 1 access is for EL0 or not, because whether +exec permission is given can depend on whether this is an EL0 +or EL1 access. Add a new argument to get_phys_addr_lpae() so +the call sites can pass this information in. + +Since get_phys_addr_lpae() doesn't already have a doc comment, +add one so we have a place to put the documentation of the +semantics of the new s1_is_el0 argument. + +Signed-off-by: Peter Maydell +Reviewed-by: Edgar E. Iglesias +Reviewed-by: Richard Henderson +Message-id: 20200330210400.11724-4-peter.maydell@linaro.org +--- + target/arm/helper.c | 29 ++++++++++++++++++++++++++++- + 1 file changed, 28 insertions(+), 1 deletion(-) + +diff --git a/target/arm/helper.c b/target/arm/helper.c +index f17841ec24..b26f580194 100644 +--- a/target/arm/helper.c ++++ b/target/arm/helper.c +@@ -41,6 +41,7 @@ + + static bool get_phys_addr_lpae(CPUARMState *env, target_ulong 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); +@@ -10053,6 +10054,7 @@ static hwaddr S1_ptw_translate(CPUARMState *env, ARMMMUIdx mmu_idx, + } + + ret = get_phys_addr_lpae(env, addr, MMU_DATA_LOAD, ARMMMUIdx_Stage2, ++ false, + &s2pa, &txattrs, &s2prot, &s2size, fi, + pcacheattrs); + if (ret) { +@@ -10655,8 +10657,32 @@ static ARMVAParameters aa32_va_parameters(CPUARMState *env, uint32_t va, + }; + } + ++/** ++ * get_phys_addr_lpae: perform one stage of page table walk, LPAE format ++ * ++ * 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 long-format ++ * DFSR/IFSR fault register, with the following caveats: ++ * * the WnR bit is never set (the caller must do this). ++ * ++ * @env: CPUARMState ++ * @address: virtual address to get physical address for ++ * @access_type: MMU_DATA_LOAD, MMU_DATA_STORE or MMU_INST_FETCH ++ * @mmu_idx: MMU index indicating required translation regime ++ * @s1_is_el0: if @mmu_idx is ARMMMUIdx_Stage2 (so this is a stage 2 page 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 ++ * @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, target_ulong 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) +@@ -11748,6 +11774,7 @@ bool get_phys_addr(CPUARMState *env, target_ulong address, + + /* S1 is done. Now do S2 translation. */ + ret = get_phys_addr_lpae(env, ipa, access_type, ARMMMUIdx_Stage2, ++ mmu_idx == ARMMMUIdx_E10_0, + phys_ptr, attrs, &s2_prot, + page_size, fi, + cacheattrs != NULL ? &cacheattrs2 : NULL); +@@ -11872,7 +11899,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, ++ return get_phys_addr_lpae(env, address, access_type, mmu_idx, false, + phys_ptr, attrs, prot, page_size, + fi, cacheattrs); + } else if (regime_sctlr(env, mmu_idx) & SCTLR_XP) { +-- +2.23.0 + diff --git a/target-arm-Add-stubs-for-AArch32-Neon-decodetree.patch b/target-arm-Add-stubs-for-AArch32-Neon-decodetree.patch new file mode 100644 index 0000000000000000000000000000000000000000..9359318b5187797efd96c2d32d8c92df853d76bc --- /dev/null +++ b/target-arm-Add-stubs-for-AArch32-Neon-decodetree.patch @@ -0,0 +1,290 @@ +From 625e3dd44a15dfbe9532daa6454df3f86cf04d3e Mon Sep 17 00:00:00 2001 +From: Peter Maydell +Date: Thu, 30 Apr 2020 19:09:30 +0100 +Subject: [PATCH 170/709] target/arm: Add stubs for AArch32 Neon decodetree + +Add the infrastructure for building and invoking a decodetree decoder +for the AArch32 Neon encodings. At the moment the new decoder covers +nothing, so we always fall back to the existing hand-written decode. + +We follow the same pattern we did for the VFP decodetree conversion +(commit 78e138bc1f672c145ef6ace74617d and following): code that deals +with Neon will be moving gradually out to translate-neon.vfp.inc, +which we #include into translate.c. + +In order to share the decode files between A32 and T32, we +split Neon into 3 parts: + * data-processing + * load-store + * 'shared' encodings + +The first two groups of instructions have similar but not identical +A32 and T32 encodings, so we need to manually transform the T32 +encoding into the A32 one before calling the decoder; the third group +covers the Neon instructions which are identical in A32 and T32. + +Signed-off-by: Peter Maydell +Reviewed-by: Richard Henderson +Message-id: 20200430181003.21682-4-peter.maydell@linaro.org +--- + target/arm/Makefile.objs | 18 +++++++++++++++++ + target/arm/neon-dp.decode | 29 ++++++++++++++++++++++++++ + target/arm/neon-ls.decode | 29 ++++++++++++++++++++++++++ + target/arm/neon-shared.decode | 27 +++++++++++++++++++++++++ + target/arm/translate-neon.inc.c | 32 +++++++++++++++++++++++++++++ + target/arm/translate.c | 36 +++++++++++++++++++++++++++++++-- + 6 files changed, 169 insertions(+), 2 deletions(-) + create mode 100644 target/arm/neon-dp.decode + create mode 100644 target/arm/neon-ls.decode + create mode 100644 target/arm/neon-shared.decode + create mode 100644 target/arm/translate-neon.inc.c + +diff --git a/target/arm/Makefile.objs b/target/arm/Makefile.objs +index cf26c16f5f..775b3e24f2 100644 +--- a/target/arm/Makefile.objs ++++ b/target/arm/Makefile.objs +@@ -18,6 +18,21 @@ target/arm/decode-sve.inc.c: $(SRC_PATH)/target/arm/sve.decode $(DECODETREE) + $(PYTHON) $(DECODETREE) --decode disas_sve -o $@ $<,\ + "GEN", $(TARGET_DIR)$@) + ++target/arm/decode-neon-shared.inc.c: $(SRC_PATH)/target/arm/neon-shared.decode $(DECODETREE) ++ $(call quiet-command,\ ++ $(PYTHON) $(DECODETREE) --static-decode disas_neon_shared -o $@ $<,\ ++ "GEN", $(TARGET_DIR)$@) ++ ++target/arm/decode-neon-dp.inc.c: $(SRC_PATH)/target/arm/neon-dp.decode $(DECODETREE) ++ $(call quiet-command,\ ++ $(PYTHON) $(DECODETREE) --static-decode disas_neon_dp -o $@ $<,\ ++ "GEN", $(TARGET_DIR)$@) ++ ++target/arm/decode-neon-ls.inc.c: $(SRC_PATH)/target/arm/neon-ls.decode $(DECODETREE) ++ $(call quiet-command,\ ++ $(PYTHON) $(DECODETREE) --static-decode disas_neon_ls -o $@ $<,\ ++ "GEN", $(TARGET_DIR)$@) ++ + target/arm/decode-vfp.inc.c: $(SRC_PATH)/target/arm/vfp.decode $(DECODETREE) + $(call quiet-command,\ + $(PYTHON) $(DECODETREE) --static-decode disas_vfp -o $@ $<,\ +@@ -49,6 +64,9 @@ target/arm/decode-t16.inc.c: $(SRC_PATH)/target/arm/t16.decode $(DECODETREE) + "GEN", $(TARGET_DIR)$@) + + target/arm/translate-sve.o: target/arm/decode-sve.inc.c ++target/arm/translate.o: target/arm/decode-neon-shared.inc.c ++target/arm/translate.o: target/arm/decode-neon-dp.inc.c ++target/arm/translate.o: target/arm/decode-neon-ls.inc.c + target/arm/translate.o: target/arm/decode-vfp.inc.c + target/arm/translate.o: target/arm/decode-vfp-uncond.inc.c + target/arm/translate.o: target/arm/decode-a32.inc.c +diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode +new file mode 100644 +index 0000000000..c89a1a5859 +--- /dev/null ++++ b/target/arm/neon-dp.decode +@@ -0,0 +1,29 @@ ++# AArch32 Neon data-processing instruction descriptions ++# ++# Copyright (c) 2020 Linaro, Ltd ++# ++# 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 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 . ++ ++# ++# This file is processed by scripts/decodetree.py ++# ++ ++# Encodings for Neon data processing instructions where the T32 encoding ++# is a simple transformation of the A32 encoding. ++# More specifically, this file covers instructions where the A32 encoding is ++# 0b1111_001p_qqqq_qqqq_qqqq_qqqq_qqqq_qqqq ++# and the T32 encoding is ++# 0b111p_1111_qqqq_qqqq_qqqq_qqqq_qqqq_qqqq ++# This file works on the A32 encoding only; calling code for T32 has to ++# transform the insn into the A32 version first. +diff --git a/target/arm/neon-ls.decode b/target/arm/neon-ls.decode +new file mode 100644 +index 0000000000..2b16c9256d +--- /dev/null ++++ b/target/arm/neon-ls.decode +@@ -0,0 +1,29 @@ ++# AArch32 Neon load/store instruction descriptions ++# ++# Copyright (c) 2020 Linaro, Ltd ++# ++# 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 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 . ++ ++# ++# This file is processed by scripts/decodetree.py ++# ++ ++# Encodings for Neon load/store instructions where the T32 encoding ++# is a simple transformation of the A32 encoding. ++# More specifically, this file covers instructions where the A32 encoding is ++# 0b1111_0100_xxx0_xxxx_xxxx_xxxx_xxxx_xxxx ++# and the T32 encoding is ++# 0b1111_1001_xxx0_xxxx_xxxx_xxxx_xxxx_xxxx ++# This file works on the A32 encoding only; calling code for T32 has to ++# transform the insn into the A32 version first. +diff --git a/target/arm/neon-shared.decode b/target/arm/neon-shared.decode +new file mode 100644 +index 0000000000..3aea7c5e18 +--- /dev/null ++++ b/target/arm/neon-shared.decode +@@ -0,0 +1,27 @@ ++# AArch32 Neon instruction descriptions ++# ++# Copyright (c) 2020 Linaro, Ltd ++# ++# 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 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 . ++ ++# ++# This file is processed by scripts/decodetree.py ++# ++ ++# Encodings for Neon instructions whose encoding is the same for ++# both A32 and T32. ++ ++# More specifically, this covers: ++# 2reg scalar ext: 0b1111_1110_xxxx_xxxx_xxxx_1x0x_xxxx_xxxx ++# 3same ext: 0b1111_110x_xxxx_xxxx_xxxx_1x0x_xxxx_xxxx +diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c +new file mode 100644 +index 0000000000..a33e81ba3a +--- /dev/null ++++ b/target/arm/translate-neon.inc.c +@@ -0,0 +1,32 @@ ++/* ++ * ARM translation: AArch32 Neon instructions ++ * ++ * Copyright (c) 2003 Fabrice Bellard ++ * Copyright (c) 2005-2007 CodeSourcery ++ * Copyright (c) 2007 OpenedHand, Ltd. ++ * Copyright (c) 2020 Linaro, Ltd. ++ * ++ * 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 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 . ++ */ ++ ++/* ++ * This file is intended to be included from translate.c; it uses ++ * some macros and definitions provided by that file. ++ * It might be possible to convert it to a standalone .c file eventually. ++ */ ++ ++/* Include the generated Neon decoder */ ++#include "decode-neon-dp.inc.c" ++#include "decode-neon-ls.inc.c" ++#include "decode-neon-shared.inc.c" +diff --git a/target/arm/translate.c b/target/arm/translate.c +index 4cf5267be0..5a82a56e8e 100644 +--- a/target/arm/translate.c ++++ b/target/arm/translate.c +@@ -1313,8 +1313,9 @@ static TCGv_ptr vfp_reg_ptr(bool dp, int reg) + + #define ARM_CP_RW_BIT (1 << 20) + +-/* Include the VFP decoder */ ++/* Include the VFP and Neon decoders */ + #include "translate-vfp.inc.c" ++#include "translate-neon.inc.c" + + static inline void iwmmxt_load_reg(TCGv_i64 var, int reg) + { +@@ -10949,7 +10950,10 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn) + /* Unconditional instructions. */ + /* TODO: Perhaps merge these into one decodetree output file. */ + if (disas_a32_uncond(s, insn) || +- disas_vfp_uncond(s, insn)) { ++ disas_vfp_uncond(s, insn) || ++ disas_neon_dp(s, insn) || ++ disas_neon_ls(s, insn) || ++ disas_neon_shared(s, insn)) { + return; + } + /* fall back to legacy decoder */ +@@ -11102,6 +11106,33 @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn) + ARCH(6T2); + } + ++ if ((insn & 0xef000000) == 0xef000000) { ++ /* ++ * T32 encodings 0b111p_1111_qqqq_qqqq_qqqq_qqqq_qqqq_qqqq ++ * transform into ++ * A32 encodings 0b1111_001p_qqqq_qqqq_qqqq_qqqq_qqqq_qqqq ++ */ ++ uint32_t a32_insn = (insn & 0xe2ffffff) | ++ ((insn & (1 << 28)) >> 4) | (1 << 28); ++ ++ if (disas_neon_dp(s, a32_insn)) { ++ return; ++ } ++ } ++ ++ if ((insn & 0xff100000) == 0xf9000000) { ++ /* ++ * T32 encodings 0b1111_1001_ppp0_qqqq_qqqq_qqqq_qqqq_qqqq ++ * transform into ++ * A32 encodings 0b1111_0100_ppp0_qqqq_qqqq_qqqq_qqqq_qqqq ++ */ ++ uint32_t a32_insn = (insn & 0x00ffffff) | 0xf4000000; ++ ++ if (disas_neon_ls(s, a32_insn)) { ++ return; ++ } ++ } ++ + /* + * TODO: Perhaps merge these into one decodetree output file. + * Note disas_vfp is written for a32 with cond field in the +@@ -11109,6 +11140,7 @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn) + */ + if (disas_t32(s, insn) || + disas_vfp_uncond(s, insn) || ++ disas_neon_shared(s, insn) || + ((insn >> 28) == 0xe && disas_vfp(s, insn))) { + return; + } +-- +2.23.0 + diff --git a/target-arm-Add-sve-infrastructure-for-page-lookup.patch b/target-arm-Add-sve-infrastructure-for-page-lookup.patch new file mode 100644 index 0000000000000000000000000000000000000000..a9db313afa3f57ac22350b8b6c7014bc7225583e --- /dev/null +++ b/target-arm-Add-sve-infrastructure-for-page-lookup.patch @@ -0,0 +1,316 @@ +From b4cd95d2f4c7197b844f51b29871d888063ea3e7 Mon Sep 17 00:00:00 2001 +From: Richard Henderson +Date: Fri, 8 May 2020 08:43:49 -0700 +Subject: [PATCH 373/709] target/arm: Add sve infrastructure for page lookup + +For contiguous predicated memory operations, we want to +minimize the number of tlb lookups performed. We have +open-coded this for sve_ld1_r, but for correctness with +MTE we will need this for all of the memory operations. + +Create a structure that holds the bounds of active elements, +and metadata for two pages. Add routines to find those +active elements, lookup the pages, and run watchpoints +for those pages. + +Temporarily mark the functions unused to avoid Werror. + +Reviewed-by: Peter Maydell +Signed-off-by: Richard Henderson +Message-id: 20200508154359.7494-10-richard.henderson@linaro.org +Signed-off-by: Peter Maydell +--- + target/arm/sve_helper.c | 263 +++++++++++++++++++++++++++++++++++++++- + 1 file changed, 261 insertions(+), 2 deletions(-) + +diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c +index aad2c8c237..2f053a9152 100644 +--- a/target/arm/sve_helper.c ++++ b/target/arm/sve_helper.c +@@ -1630,7 +1630,7 @@ void HELPER(sve_cpy_z_d)(void *vd, void *vg, uint64_t val, uint32_t desc) + } + } + +-/* Big-endian hosts need to frob the byte indicies. If the copy ++/* Big-endian hosts need to frob the byte indices. If the copy + * happens to be 8-byte aligned, then no frobbing necessary. + */ + static void swap_memmove(void *vd, void *vs, size_t n) +@@ -3974,7 +3974,7 @@ void HELPER(sve_fcmla_zpzzz_d)(CPUARMState *env, void *vg, uint32_t desc) + /* + * Load elements into @vd, controlled by @vg, from @host + @mem_ofs. + * Memory is valid through @host + @mem_max. The register element +- * indicies are inferred from @mem_ofs, as modified by the types for ++ * indices are inferred from @mem_ofs, as modified by the types for + * which the helper is built. Return the @mem_ofs of the first element + * not loaded (which is @mem_max if they are all loaded). + * +@@ -4133,6 +4133,265 @@ static intptr_t max_for_page(target_ulong base, intptr_t mem_off, + return MIN(split, mem_max - mem_off) + mem_off; + } + ++/* ++ * Resolve the guest virtual address to info->host and info->flags. ++ * If @nofault, return false if the page is invalid, otherwise ++ * exit via page fault exception. ++ */ ++ ++typedef struct { ++ void *host; ++ int flags; ++ MemTxAttrs attrs; ++} SVEHostPage; ++ ++static bool sve_probe_page(SVEHostPage *info, bool nofault, ++ CPUARMState *env, target_ulong addr, ++ int mem_off, MMUAccessType access_type, ++ int mmu_idx, uintptr_t retaddr) ++{ ++ int flags; ++ ++ addr += mem_off; ++ flags = probe_access_flags(env, addr, access_type, mmu_idx, nofault, ++ &info->host, retaddr); ++ info->flags = flags; ++ ++ if (flags & TLB_INVALID_MASK) { ++ g_assert(nofault); ++ return false; ++ } ++ ++ /* Ensure that info->host[] is relative to addr, not addr + mem_off. */ ++ info->host -= mem_off; ++ ++#ifdef CONFIG_USER_ONLY ++ memset(&info->attrs, 0, sizeof(info->attrs)); ++#else ++ /* ++ * Find the iotlbentry for addr and return the transaction attributes. ++ * This *must* be present in the TLB because we just found the mapping. ++ */ ++ { ++ uintptr_t index = tlb_index(env, mmu_idx, addr); ++ ++# ifdef CONFIG_DEBUG_TCG ++ CPUTLBEntry *entry = tlb_entry(env, mmu_idx, addr); ++ target_ulong comparator = (access_type == MMU_DATA_LOAD ++ ? entry->addr_read ++ : tlb_addr_write(entry)); ++ g_assert(tlb_hit(comparator, addr)); ++# endif ++ ++ CPUIOTLBEntry *iotlbentry = &env_tlb(env)->d[mmu_idx].iotlb[index]; ++ info->attrs = iotlbentry->attrs; ++ } ++#endif ++ ++ return true; ++} ++ ++ ++/* ++ * Analyse contiguous data, protected by a governing predicate. ++ */ ++ ++typedef enum { ++ FAULT_NO, ++ FAULT_FIRST, ++ FAULT_ALL, ++} SVEContFault; ++ ++typedef struct { ++ /* ++ * First and last element wholly contained within the two pages. ++ * mem_off_first[0] and reg_off_first[0] are always set >= 0. ++ * reg_off_last[0] may be < 0 if the first element crosses pages. ++ * All of mem_off_first[1], reg_off_first[1] and reg_off_last[1] ++ * are set >= 0 only if there are complete elements on a second page. ++ * ++ * The reg_off_* offsets are relative to the internal vector register. ++ * The mem_off_first offset is relative to the memory address; the ++ * two offsets are different when a load operation extends, a store ++ * operation truncates, or for multi-register operations. ++ */ ++ int16_t mem_off_first[2]; ++ int16_t reg_off_first[2]; ++ int16_t reg_off_last[2]; ++ ++ /* ++ * One element that is misaligned and spans both pages, ++ * or -1 if there is no such active element. ++ */ ++ int16_t mem_off_split; ++ int16_t reg_off_split; ++ ++ /* ++ * The byte offset at which the entire operation crosses a page boundary. ++ * Set >= 0 if and only if the entire operation spans two pages. ++ */ ++ int16_t page_split; ++ ++ /* TLB data for the two pages. */ ++ SVEHostPage page[2]; ++} SVEContLdSt; ++ ++/* ++ * Find first active element on each page, and a loose bound for the ++ * final element on each page. Identify any single element that spans ++ * the page boundary. Return true if there are any active elements. ++ */ ++static bool __attribute__((unused)) ++sve_cont_ldst_elements(SVEContLdSt *info, target_ulong addr, uint64_t *vg, ++ intptr_t reg_max, int esz, int msize) ++{ ++ const int esize = 1 << esz; ++ const uint64_t pg_mask = pred_esz_masks[esz]; ++ intptr_t reg_off_first = -1, reg_off_last = -1, reg_off_split; ++ intptr_t mem_off_last, mem_off_split; ++ intptr_t page_split, elt_split; ++ intptr_t i; ++ ++ /* Set all of the element indices to -1, and the TLB data to 0. */ ++ memset(info, -1, offsetof(SVEContLdSt, page)); ++ memset(info->page, 0, sizeof(info->page)); ++ ++ /* Gross scan over the entire predicate to find bounds. */ ++ i = 0; ++ do { ++ uint64_t pg = vg[i] & pg_mask; ++ if (pg) { ++ reg_off_last = i * 64 + 63 - clz64(pg); ++ if (reg_off_first < 0) { ++ reg_off_first = i * 64 + ctz64(pg); ++ } ++ } ++ } while (++i * 64 < reg_max); ++ ++ if (unlikely(reg_off_first < 0)) { ++ /* No active elements, no pages touched. */ ++ return false; ++ } ++ tcg_debug_assert(reg_off_last >= 0 && reg_off_last < reg_max); ++ ++ info->reg_off_first[0] = reg_off_first; ++ info->mem_off_first[0] = (reg_off_first >> esz) * msize; ++ mem_off_last = (reg_off_last >> esz) * msize; ++ ++ page_split = -(addr | TARGET_PAGE_MASK); ++ if (likely(mem_off_last + msize <= page_split)) { ++ /* The entire operation fits within a single page. */ ++ info->reg_off_last[0] = reg_off_last; ++ return true; ++ } ++ ++ info->page_split = page_split; ++ elt_split = page_split / msize; ++ reg_off_split = elt_split << esz; ++ mem_off_split = elt_split * msize; ++ ++ /* ++ * This is the last full element on the first page, but it is not ++ * necessarily active. If there is no full element, i.e. the first ++ * active element is the one that's split, this value remains -1. ++ * It is useful as iteration bounds. ++ */ ++ if (elt_split != 0) { ++ info->reg_off_last[0] = reg_off_split - esize; ++ } ++ ++ /* Determine if an unaligned element spans the pages. */ ++ if (page_split % msize != 0) { ++ /* It is helpful to know if the split element is active. */ ++ if ((vg[reg_off_split >> 6] >> (reg_off_split & 63)) & 1) { ++ info->reg_off_split = reg_off_split; ++ info->mem_off_split = mem_off_split; ++ ++ if (reg_off_split == reg_off_last) { ++ /* The page crossing element is last. */ ++ return true; ++ } ++ } ++ reg_off_split += esize; ++ mem_off_split += msize; ++ } ++ ++ /* ++ * We do want the first active element on the second page, because ++ * this may affect the address reported in an exception. ++ */ ++ reg_off_split = find_next_active(vg, reg_off_split, reg_max, esz); ++ tcg_debug_assert(reg_off_split <= reg_off_last); ++ info->reg_off_first[1] = reg_off_split; ++ info->mem_off_first[1] = (reg_off_split >> esz) * msize; ++ info->reg_off_last[1] = reg_off_last; ++ return true; ++} ++ ++/* ++ * Resolve the guest virtual addresses to info->page[]. ++ * Control the generation of page faults with @fault. Return false if ++ * there is no work to do, which can only happen with @fault == FAULT_NO. ++ */ ++static bool __attribute__((unused)) ++sve_cont_ldst_pages(SVEContLdSt *info, SVEContFault fault, CPUARMState *env, ++ target_ulong addr, MMUAccessType access_type, ++ uintptr_t retaddr) ++{ ++ int mmu_idx = cpu_mmu_index(env, false); ++ int mem_off = info->mem_off_first[0]; ++ bool nofault = fault == FAULT_NO; ++ bool have_work = true; ++ ++ if (!sve_probe_page(&info->page[0], nofault, env, addr, mem_off, ++ access_type, mmu_idx, retaddr)) { ++ /* No work to be done. */ ++ return false; ++ } ++ ++ if (likely(info->page_split < 0)) { ++ /* The entire operation was on the one page. */ ++ return true; ++ } ++ ++ /* ++ * If the second page is invalid, then we want the fault address to be ++ * the first byte on that page which is accessed. ++ */ ++ if (info->mem_off_split >= 0) { ++ /* ++ * There is an element split across the pages. The fault address ++ * should be the first byte of the second page. ++ */ ++ mem_off = info->page_split; ++ /* ++ * If the split element is also the first active element ++ * of the vector, then: For first-fault we should continue ++ * to generate faults for the second page. For no-fault, ++ * we have work only if the second page is valid. ++ */ ++ if (info->mem_off_first[0] < info->mem_off_split) { ++ nofault = FAULT_FIRST; ++ have_work = false; ++ } ++ } else { ++ /* ++ * There is no element split across the pages. The fault address ++ * should be the first active element on the second page. ++ */ ++ mem_off = info->mem_off_first[1]; ++ /* ++ * There must have been one active element on the first page, ++ * so we're out of first-fault territory. ++ */ ++ nofault = fault != FAULT_ALL; ++ } ++ ++ have_work |= sve_probe_page(&info->page[1], nofault, env, addr, mem_off, ++ access_type, mmu_idx, retaddr); ++ return have_work; ++} ++ + /* + * The result of tlb_vaddr_to_host for user-only is just g2h(x), + * which is always non-null. Elide the useless test. +-- +2.23.0 + diff --git a/target-arm-Adjust-interface-of-sve_ld1_host_fn.patch b/target-arm-Adjust-interface-of-sve_ld1_host_fn.patch new file mode 100644 index 0000000000000000000000000000000000000000..b099711d358f9bd5f3c3a95503347fa625922c32 --- /dev/null +++ b/target-arm-Adjust-interface-of-sve_ld1_host_fn.patch @@ -0,0 +1,258 @@ +From cf4a49b71b1712142d7122025a8ca7ea5b59d73f Mon Sep 17 00:00:00 2001 +From: Richard Henderson +Date: Fri, 8 May 2020 08:43:50 -0700 +Subject: [PATCH 374/709] target/arm: Adjust interface of sve_ld1_host_fn + +The current interface includes a loop; change it to load a +single element. We will then be able to use the function +for ld{2,3,4} where individual vector elements are not adjacent. + +Replace each call with the simplest possible loop over active +elements. + +Reviewed-by: Peter Maydell +Signed-off-by: Richard Henderson +Message-id: 20200508154359.7494-11-richard.henderson@linaro.org +Signed-off-by: Peter Maydell +--- + target/arm/sve_helper.c | 124 ++++++++++++++++++++-------------------- + 1 file changed, 63 insertions(+), 61 deletions(-) + +diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c +index 2f053a9152..d007137735 100644 +--- a/target/arm/sve_helper.c ++++ b/target/arm/sve_helper.c +@@ -3972,20 +3972,10 @@ void HELPER(sve_fcmla_zpzzz_d)(CPUARMState *env, void *vg, uint32_t desc) + */ + + /* +- * Load elements into @vd, controlled by @vg, from @host + @mem_ofs. +- * Memory is valid through @host + @mem_max. The register element +- * indices are inferred from @mem_ofs, as modified by the types for +- * which the helper is built. Return the @mem_ofs of the first element +- * not loaded (which is @mem_max if they are all loaded). +- * +- * For softmmu, we have fully validated the guest page. For user-only, +- * we cannot fully validate without taking the mmap lock, but since we +- * know the access is within one host page, if any access is valid they +- * all must be valid. However, when @vg is all false, it may be that +- * no access is valid. ++ * Load one element into @vd + @reg_off from @host. ++ * The controlling predicate is known to be true. + */ +-typedef intptr_t sve_ld1_host_fn(void *vd, void *vg, void *host, +- intptr_t mem_ofs, intptr_t mem_max); ++typedef void sve_ldst1_host_fn(void *vd, intptr_t reg_off, void *host); + + /* + * Load one element into @vd + @reg_off from (@env, @vaddr, @ra). +@@ -3999,20 +3989,10 @@ typedef void sve_ldst1_tlb_fn(CPUARMState *env, void *vd, intptr_t reg_off, + */ + + #define DO_LD_HOST(NAME, H, TYPEE, TYPEM, HOST) \ +-static intptr_t sve_##NAME##_host(void *vd, void *vg, void *host, \ +- intptr_t mem_off, const intptr_t mem_max) \ +-{ \ +- intptr_t reg_off = mem_off * (sizeof(TYPEE) / sizeof(TYPEM)); \ +- uint64_t *pg = vg; \ +- while (mem_off + sizeof(TYPEM) <= mem_max) { \ +- TYPEM val = 0; \ +- if (likely((pg[reg_off >> 6] >> (reg_off & 63)) & 1)) { \ +- val = HOST(host + mem_off); \ +- } \ +- *(TYPEE *)(vd + H(reg_off)) = val; \ +- mem_off += sizeof(TYPEM), reg_off += sizeof(TYPEE); \ +- } \ +- return mem_off; \ ++static void sve_##NAME##_host(void *vd, intptr_t reg_off, void *host) \ ++{ \ ++ TYPEM val = HOST(host); \ ++ *(TYPEE *)(vd + H(reg_off)) = val; \ + } + + #define DO_LD_TLB(NAME, H, TYPEE, TYPEM, TLB) \ +@@ -4411,7 +4391,7 @@ static inline bool test_host_page(void *host) + static void sve_ld1_r(CPUARMState *env, void *vg, const target_ulong addr, + uint32_t desc, const uintptr_t retaddr, + const int esz, const int msz, +- sve_ld1_host_fn *host_fn, ++ sve_ldst1_host_fn *host_fn, + sve_ldst1_tlb_fn *tlb_fn) + { + const TCGMemOpIdx oi = extract32(desc, SIMD_DATA_SHIFT, MEMOPIDX_SHIFT); +@@ -4445,8 +4425,12 @@ static void sve_ld1_r(CPUARMState *env, void *vg, const target_ulong addr, + if (likely(split == mem_max)) { + host = tlb_vaddr_to_host(env, addr + mem_off, MMU_DATA_LOAD, mmu_idx); + if (test_host_page(host)) { +- mem_off = host_fn(vd, vg, host - mem_off, mem_off, mem_max); +- tcg_debug_assert(mem_off == mem_max); ++ intptr_t i = reg_off; ++ host -= mem_off; ++ do { ++ host_fn(vd, i, host + (i >> diffsz)); ++ i = find_next_active(vg, i + (1 << esz), reg_max, esz); ++ } while (i < reg_max); + /* After having taken any fault, zero leading inactive elements. */ + swap_memzero(vd, reg_off); + return; +@@ -4459,7 +4443,12 @@ static void sve_ld1_r(CPUARMState *env, void *vg, const target_ulong addr, + */ + #ifdef CONFIG_USER_ONLY + swap_memzero(&scratch, reg_off); +- host_fn(&scratch, vg, g2h(addr), mem_off, mem_max); ++ host = g2h(addr); ++ do { ++ host_fn(&scratch, reg_off, host + (reg_off >> diffsz)); ++ reg_off += 1 << esz; ++ reg_off = find_next_active(vg, reg_off, reg_max, esz); ++ } while (reg_off < reg_max); + #else + memset(&scratch, 0, reg_max); + goto start; +@@ -4477,9 +4466,13 @@ static void sve_ld1_r(CPUARMState *env, void *vg, const target_ulong addr, + host = tlb_vaddr_to_host(env, addr + mem_off, + MMU_DATA_LOAD, mmu_idx); + if (host) { +- mem_off = host_fn(&scratch, vg, host - mem_off, +- mem_off, split); +- reg_off = mem_off << diffsz; ++ host -= mem_off; ++ do { ++ host_fn(&scratch, reg_off, host + mem_off); ++ reg_off += 1 << esz; ++ reg_off = find_next_active(vg, reg_off, reg_max, esz); ++ mem_off = reg_off >> diffsz; ++ } while (split - mem_off >= (1 << msz)); + continue; + } + } +@@ -4706,7 +4699,7 @@ static void record_fault(CPUARMState *env, uintptr_t i, uintptr_t oprsz) + static void sve_ldff1_r(CPUARMState *env, void *vg, const target_ulong addr, + uint32_t desc, const uintptr_t retaddr, + const int esz, const int msz, +- sve_ld1_host_fn *host_fn, ++ sve_ldst1_host_fn *host_fn, + sve_ldst1_tlb_fn *tlb_fn) + { + const TCGMemOpIdx oi = extract32(desc, SIMD_DATA_SHIFT, MEMOPIDX_SHIFT); +@@ -4716,7 +4709,7 @@ static void sve_ldff1_r(CPUARMState *env, void *vg, const target_ulong addr, + const int diffsz = esz - msz; + const intptr_t reg_max = simd_oprsz(desc); + const intptr_t mem_max = reg_max >> diffsz; +- intptr_t split, reg_off, mem_off; ++ intptr_t split, reg_off, mem_off, i; + void *host; + + /* Skip to the first active element. */ +@@ -4739,28 +4732,18 @@ static void sve_ldff1_r(CPUARMState *env, void *vg, const target_ulong addr, + if (likely(split == mem_max)) { + host = tlb_vaddr_to_host(env, addr + mem_off, MMU_DATA_LOAD, mmu_idx); + if (test_host_page(host)) { +- mem_off = host_fn(vd, vg, host - mem_off, mem_off, mem_max); +- tcg_debug_assert(mem_off == mem_max); ++ i = reg_off; ++ host -= mem_off; ++ do { ++ host_fn(vd, i, host + (i >> diffsz)); ++ i = find_next_active(vg, i + (1 << esz), reg_max, esz); ++ } while (i < reg_max); + /* After any fault, zero any leading inactive elements. */ + swap_memzero(vd, reg_off); + return; + } + } + +-#ifdef CONFIG_USER_ONLY +- /* +- * The page(s) containing this first element at ADDR+MEM_OFF must +- * be valid. Considering that this first element may be misaligned +- * and cross a page boundary itself, take the rest of the page from +- * the last byte of the element. +- */ +- split = max_for_page(addr, mem_off + (1 << msz) - 1, mem_max); +- mem_off = host_fn(vd, vg, g2h(addr), mem_off, split); +- +- /* After any fault, zero any leading inactive elements. */ +- swap_memzero(vd, reg_off); +- reg_off = mem_off << diffsz; +-#else + /* + * Perform one normal read, which will fault or not. + * But it is likely to bring the page into the tlb. +@@ -4777,11 +4760,15 @@ static void sve_ldff1_r(CPUARMState *env, void *vg, const target_ulong addr, + if (split >= (1 << msz)) { + host = tlb_vaddr_to_host(env, addr + mem_off, MMU_DATA_LOAD, mmu_idx); + if (host) { +- mem_off = host_fn(vd, vg, host - mem_off, mem_off, split); +- reg_off = mem_off << diffsz; ++ host -= mem_off; ++ do { ++ host_fn(vd, reg_off, host + mem_off); ++ reg_off += 1 << esz; ++ reg_off = find_next_active(vg, reg_off, reg_max, esz); ++ mem_off = reg_off >> diffsz; ++ } while (split - mem_off >= (1 << msz)); + } + } +-#endif + + record_fault(env, reg_off, reg_max); + } +@@ -4791,7 +4778,7 @@ static void sve_ldff1_r(CPUARMState *env, void *vg, const target_ulong addr, + */ + static void sve_ldnf1_r(CPUARMState *env, void *vg, const target_ulong addr, + uint32_t desc, const int esz, const int msz, +- sve_ld1_host_fn *host_fn) ++ sve_ldst1_host_fn *host_fn) + { + const unsigned rd = extract32(desc, SIMD_DATA_SHIFT + MEMOPIDX_SHIFT, 5); + void *vd = &env->vfp.zregs[rd]; +@@ -4806,7 +4793,13 @@ static void sve_ldnf1_r(CPUARMState *env, void *vg, const target_ulong addr, + host = tlb_vaddr_to_host(env, addr, MMU_DATA_LOAD, mmu_idx); + if (likely(page_check_range(addr, mem_max, PAGE_READ) == 0)) { + /* The entire operation is valid and will not fault. */ +- host_fn(vd, vg, host, 0, mem_max); ++ reg_off = 0; ++ do { ++ mem_off = reg_off >> diffsz; ++ host_fn(vd, reg_off, host + mem_off); ++ reg_off += 1 << esz; ++ reg_off = find_next_active(vg, reg_off, reg_max, esz); ++ } while (reg_off < reg_max); + return; + } + #endif +@@ -4826,8 +4819,12 @@ static void sve_ldnf1_r(CPUARMState *env, void *vg, const target_ulong addr, + if (page_check_range(addr + mem_off, 1 << msz, PAGE_READ) == 0) { + /* At least one load is valid; take the rest of the page. */ + split = max_for_page(addr, mem_off + (1 << msz) - 1, mem_max); +- mem_off = host_fn(vd, vg, host, mem_off, split); +- reg_off = mem_off << diffsz; ++ do { ++ host_fn(vd, reg_off, host + mem_off); ++ reg_off += 1 << esz; ++ reg_off = find_next_active(vg, reg_off, reg_max, esz); ++ mem_off = reg_off >> diffsz; ++ } while (split - mem_off >= (1 << msz)); + } + #else + /* +@@ -4848,8 +4845,13 @@ static void sve_ldnf1_r(CPUARMState *env, void *vg, const target_ulong addr, + host = tlb_vaddr_to_host(env, addr + mem_off, MMU_DATA_LOAD, mmu_idx); + split = max_for_page(addr, mem_off, mem_max); + if (host && split >= (1 << msz)) { +- mem_off = host_fn(vd, vg, host - mem_off, mem_off, split); +- reg_off = mem_off << diffsz; ++ host -= mem_off; ++ do { ++ host_fn(vd, reg_off, host + mem_off); ++ reg_off += 1 << esz; ++ reg_off = find_next_active(vg, reg_off, reg_max, esz); ++ mem_off = reg_off >> diffsz; ++ } while (split - mem_off >= (1 << msz)); + } + #endif + +-- +2.23.0 + diff --git a/target-arm-Allow-user-mode-code-to-write-CPSR.E-via-.patch b/target-arm-Allow-user-mode-code-to-write-CPSR.E-via-.patch new file mode 100644 index 0000000000000000000000000000000000000000..5730023e4a436b60807d74c3954786c08cd534af --- /dev/null +++ b/target-arm-Allow-user-mode-code-to-write-CPSR.E-via-.patch @@ -0,0 +1,67 @@ +From 268b1b3dfbb92a9348406f728a33f39e3d8dcd8a Mon Sep 17 00:00:00 2001 +From: Peter Maydell +Date: Mon, 18 May 2020 15:28:01 +0100 +Subject: [PATCH 633/709] target/arm: Allow user-mode code to write CPSR.E via + MSR + +Using the MSR instruction to write to CPSR.E is deprecated, but it is +required to work from any mode including unprivileged code. We were +incorrectly forbidding usermode code from writing it because +CPSR_USER did not include the CPSR_E bit. + +We use CPSR_USER in only three places: + * as the mask of what to allow userspace MSR to write to CPSR + * when deciding what bits a linux-user signal-return should be + able to write from the sigcontext structure + * in target_user_copy_regs() when we set up the initial + registers for the linux-user process + +In the first two cases not being able to update CPSR.E is a bug, and +in the third case it doesn't matter because CPSR.E is always 0 there. +So we can fix both bugs by adding CPSR_E to CPSR_USER. + +Because the cpsr_write() in restore_sigcontext() is now changing +a CPSR bit which is cached in hflags, we need to add an +arm_rebuild_hflags() call there; the callsite in +target_user_copy_regs() was already rebuilding hflags for other +reasons. + +(The recommended way to change CPSR.E is to use the 'SETEND' +instruction, which we do correctly allow from usermode code.) + +Signed-off-by: Peter Maydell +Reviewed-by: Richard Henderson +Message-id: 20200518142801.20503-1-peter.maydell@linaro.org +--- + linux-user/arm/signal.c | 1 + + target/arm/cpu.h | 2 +- + 2 files changed, 2 insertions(+), 1 deletion(-) + +diff --git a/linux-user/arm/signal.c b/linux-user/arm/signal.c +index d96fc27ce1..8020c80acb 100644 +--- a/linux-user/arm/signal.c ++++ b/linux-user/arm/signal.c +@@ -546,6 +546,7 @@ restore_sigcontext(CPUARMState *env, struct target_sigcontext *sc) + #ifdef TARGET_CONFIG_CPU_32 + __get_user(cpsr, &sc->arm_cpsr); + cpsr_write(env, cpsr, CPSR_USER | CPSR_EXEC, CPSRWriteByInstr); ++ arm_rebuild_hflags(env); + #endif + + err |= !valid_user_regs(env); +diff --git a/target/arm/cpu.h b/target/arm/cpu.h +index 5d995368d4..677584e5da 100644 +--- a/target/arm/cpu.h ++++ b/target/arm/cpu.h +@@ -1230,7 +1230,7 @@ void pmu_init(ARMCPU *cpu); + #define CACHED_CPSR_BITS (CPSR_T | CPSR_AIF | CPSR_GE | CPSR_IT | CPSR_Q \ + | CPSR_NZCV) + /* Bits writable in user mode. */ +-#define CPSR_USER (CPSR_NZCV | CPSR_Q | CPSR_GE) ++#define CPSR_USER (CPSR_NZCV | CPSR_Q | CPSR_GE | CPSR_E) + /* Execution state bits. MRS read as zero, MSR writes ignored. */ + #define CPSR_EXEC (CPSR_T | CPSR_IT | CPSR_J | CPSR_IL) + +-- +2.23.0 + diff --git a/target-arm-Clear-tail-in-gvec_fmul_idx_-gvec_fmla_id.patch b/target-arm-Clear-tail-in-gvec_fmul_idx_-gvec_fmla_id.patch new file mode 100644 index 0000000000000000000000000000000000000000..46689114fb336792ec895fdc0d63f0d75a4988b9 --- /dev/null +++ b/target-arm-Clear-tail-in-gvec_fmul_idx_-gvec_fmla_id.patch @@ -0,0 +1,41 @@ +From 525d9b6d42844e187211d25b69be8b378785bc24 Mon Sep 17 00:00:00 2001 +From: Richard Henderson +Date: Wed, 13 May 2020 09:32:43 -0700 +Subject: [PATCH 432/709] target/arm: Clear tail in gvec_fmul_idx_*, + gvec_fmla_idx_* + +Must clear the tail for AdvSIMD when SVE is enabled. + +Fixes: ca40a6e6e39 +Cc: qemu-stable@nongnu.org +Reviewed-by: Peter Maydell +Signed-off-by: Richard Henderson +Message-id: 20200513163245.17915-15-richard.henderson@linaro.org +Signed-off-by: Peter Maydell +--- + target/arm/vec_helper.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c +index 6aa2ca0827..a483841add 100644 +--- a/target/arm/vec_helper.c ++++ b/target/arm/vec_helper.c +@@ -747,6 +747,7 @@ void HELPER(NAME)(void *vd, void *vn, void *vm, void *stat, uint32_t desc) \ + d[i + j] = TYPE##_mul(n[i + j], mm, stat); \ + } \ + } \ ++ clear_tail(d, oprsz, simd_maxsz(desc)); \ + } + + DO_MUL_IDX(gvec_fmul_idx_h, float16, H2) +@@ -771,6 +772,7 @@ void HELPER(NAME)(void *vd, void *vn, void *vm, void *va, \ + mm, a[i + j], 0, stat); \ + } \ + } \ ++ clear_tail(d, oprsz, simd_maxsz(desc)); \ + } + + DO_FMLA_IDX(gvec_fmla_idx_h, float16, H2) +-- +2.23.0 + diff --git a/target-arm-Convert-NEON-VFMA-VFMS-3-reg-same-insns-t.patch b/target-arm-Convert-NEON-VFMA-VFMS-3-reg-same-insns-t.patch new file mode 100644 index 0000000000000000000000000000000000000000..ea4062deab3eb954570debaf2ecb360f8f8d884a --- /dev/null +++ b/target-arm-Convert-NEON-VFMA-VFMS-3-reg-same-insns-t.patch @@ -0,0 +1,282 @@ +From e95485f85657be21135c17a9226e297c21e73360 Mon Sep 17 00:00:00 2001 +From: Peter Maydell +Date: Tue, 12 May 2020 17:39:04 +0100 +Subject: [PATCH 462/709] target/arm: Convert NEON VFMA, VFMS 3-reg-same insns + to decodetree + +Convert the Neon floating point VFMA and VFMS insn to decodetree. +These are the last insns in the 3-reg-same group so we can +remove all the support/loop code from the old decoder. + +Signed-off-by: Peter Maydell +Reviewed-by: Richard Henderson +Message-id: 20200512163904.10918-18-peter.maydell@linaro.org +--- + target/arm/neon-dp.decode | 3 + + target/arm/translate-neon.inc.c | 41 ++++++++ + target/arm/translate.c | 176 +------------------------------- + 3 files changed, 46 insertions(+), 174 deletions(-) + +diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode +index 9c28886507..8beb1db768 100644 +--- a/target/arm/neon-dp.decode ++++ b/target/arm/neon-dp.decode +@@ -174,6 +174,9 @@ SHA256H2_3s 1111 001 1 0 . 01 .... .... 1100 . 1 . 0 .... \ + SHA256SU1_3s 1111 001 1 0 . 10 .... .... 1100 . 1 . 0 .... \ + vm=%vm_dp vn=%vn_dp vd=%vd_dp + ++VFMA_fp_3s 1111 001 0 0 . 0 . .... .... 1100 ... 1 .... @3same_fp ++VFMS_fp_3s 1111 001 0 0 . 1 . .... .... 1100 ... 1 .... @3same_fp ++ + VQRDMLSH_3s 1111 001 1 0 . .. .... .... 1100 ... 1 .... @3same + + VADD_fp_3s 1111 001 0 0 . 0 . .... .... 1101 ... 0 .... @3same_fp +diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c +index 5e9e53c5c3..3fe65a0b08 100644 +--- a/target/arm/translate-neon.inc.c ++++ b/target/arm/translate-neon.inc.c +@@ -1207,6 +1207,47 @@ static bool trans_VRSQRTS_fp_3s(DisasContext *s, arg_3same *a) + return do_3same(s, a, gen_VRSQRTS_fp_3s); + } + ++static void gen_VFMA_fp_3s(TCGv_i32 vd, TCGv_i32 vn, TCGv_i32 vm, ++ TCGv_ptr fpstatus) ++{ ++ gen_helper_vfp_muladds(vd, vn, vm, vd, fpstatus); ++} ++ ++static bool trans_VFMA_fp_3s(DisasContext *s, arg_3same *a) ++{ ++ if (!dc_isar_feature(aa32_simdfmac, s)) { ++ return false; ++ } ++ ++ if (a->size != 0) { ++ /* TODO fp16 support */ ++ return false; ++ } ++ ++ return do_3same_fp(s, a, gen_VFMA_fp_3s, true); ++} ++ ++static void gen_VFMS_fp_3s(TCGv_i32 vd, TCGv_i32 vn, TCGv_i32 vm, ++ TCGv_ptr fpstatus) ++{ ++ gen_helper_vfp_negs(vn, vn); ++ gen_helper_vfp_muladds(vd, vn, vm, vd, fpstatus); ++} ++ ++static bool trans_VFMS_fp_3s(DisasContext *s, arg_3same *a) ++{ ++ if (!dc_isar_feature(aa32_simdfmac, s)) { ++ return false; ++ } ++ ++ if (a->size != 0) { ++ /* TODO fp16 support */ ++ return false; ++ } ++ ++ return do_3same_fp(s, a, gen_VFMS_fp_3s, true); ++} ++ + static bool do_3same_fp_pair(DisasContext *s, arg_3same *a, VFPGen3OpSPFn *fn) + { + /* FP operations handled pairwise 32 bits at a time */ +diff --git a/target/arm/translate.c b/target/arm/translate.c +index c1d4fab8e8..4c9bb8b5ac 100644 +--- a/target/arm/translate.c ++++ b/target/arm/translate.c +@@ -3391,78 +3391,6 @@ static void gen_neon_narrow_op(int op, int u, int size, + } + } + +-/* Symbolic constants for op fields for Neon 3-register same-length. +- * The values correspond to bits [11:8,4]; see the ARM ARM DDI0406B +- * table A7-9. +- */ +-#define NEON_3R_VHADD 0 +-#define NEON_3R_VQADD 1 +-#define NEON_3R_VRHADD 2 +-#define NEON_3R_LOGIC 3 /* VAND,VBIC,VORR,VMOV,VORN,VEOR,VBIF,VBIT,VBSL */ +-#define NEON_3R_VHSUB 4 +-#define NEON_3R_VQSUB 5 +-#define NEON_3R_VCGT 6 +-#define NEON_3R_VCGE 7 +-#define NEON_3R_VSHL 8 +-#define NEON_3R_VQSHL 9 +-#define NEON_3R_VRSHL 10 +-#define NEON_3R_VQRSHL 11 +-#define NEON_3R_VMAX 12 +-#define NEON_3R_VMIN 13 +-#define NEON_3R_VABD 14 +-#define NEON_3R_VABA 15 +-#define NEON_3R_VADD_VSUB 16 +-#define NEON_3R_VTST_VCEQ 17 +-#define NEON_3R_VML 18 /* VMLA, VMLS */ +-#define NEON_3R_VMUL 19 +-#define NEON_3R_VPMAX 20 +-#define NEON_3R_VPMIN 21 +-#define NEON_3R_VQDMULH_VQRDMULH 22 +-#define NEON_3R_VPADD_VQRDMLAH 23 +-#define NEON_3R_SHA 24 /* SHA1C,SHA1P,SHA1M,SHA1SU0,SHA256H{2},SHA256SU1 */ +-#define NEON_3R_VFM_VQRDMLSH 25 /* VFMA, VFMS, VQRDMLSH */ +-#define NEON_3R_FLOAT_ARITH 26 /* float VADD, VSUB, VPADD, VABD */ +-#define NEON_3R_FLOAT_MULTIPLY 27 /* float VMLA, VMLS, VMUL */ +-#define NEON_3R_FLOAT_CMP 28 /* float VCEQ, VCGE, VCGT */ +-#define NEON_3R_FLOAT_ACMP 29 /* float VACGE, VACGT, VACLE, VACLT */ +-#define NEON_3R_FLOAT_MINMAX 30 /* float VMIN, VMAX */ +-#define NEON_3R_FLOAT_MISC 31 /* float VRECPS, VRSQRTS, VMAXNM/MINNM */ +- +-static const uint8_t neon_3r_sizes[] = { +- [NEON_3R_VHADD] = 0x7, +- [NEON_3R_VQADD] = 0xf, +- [NEON_3R_VRHADD] = 0x7, +- [NEON_3R_LOGIC] = 0xf, /* size field encodes op type */ +- [NEON_3R_VHSUB] = 0x7, +- [NEON_3R_VQSUB] = 0xf, +- [NEON_3R_VCGT] = 0x7, +- [NEON_3R_VCGE] = 0x7, +- [NEON_3R_VSHL] = 0xf, +- [NEON_3R_VQSHL] = 0xf, +- [NEON_3R_VRSHL] = 0xf, +- [NEON_3R_VQRSHL] = 0xf, +- [NEON_3R_VMAX] = 0x7, +- [NEON_3R_VMIN] = 0x7, +- [NEON_3R_VABD] = 0x7, +- [NEON_3R_VABA] = 0x7, +- [NEON_3R_VADD_VSUB] = 0xf, +- [NEON_3R_VTST_VCEQ] = 0x7, +- [NEON_3R_VML] = 0x7, +- [NEON_3R_VMUL] = 0x7, +- [NEON_3R_VPMAX] = 0x7, +- [NEON_3R_VPMIN] = 0x7, +- [NEON_3R_VQDMULH_VQRDMULH] = 0x6, +- [NEON_3R_VPADD_VQRDMLAH] = 0x7, +- [NEON_3R_SHA] = 0xf, /* size field encodes op type */ +- [NEON_3R_VFM_VQRDMLSH] = 0x7, /* For VFM, size bit 1 encodes op */ +- [NEON_3R_FLOAT_ARITH] = 0x5, /* size bit 1 encodes op */ +- [NEON_3R_FLOAT_MULTIPLY] = 0x5, /* size bit 1 encodes op */ +- [NEON_3R_FLOAT_CMP] = 0x5, /* size bit 1 encodes op */ +- [NEON_3R_FLOAT_ACMP] = 0x5, /* size bit 1 encodes op */ +- [NEON_3R_FLOAT_MINMAX] = 0x5, /* size bit 1 encodes op */ +- [NEON_3R_FLOAT_MISC] = 0x5, /* size bit 1 encodes op */ +-}; +- + /* Symbolic constants for op fields for Neon 2-register miscellaneous. + * The values correspond to bits [17:16,10:7]; see the ARM ARM DDI0406B + * table A7-13. +@@ -5383,108 +5311,8 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn) + rm_ofs = neon_reg_offset(rm, 0); + + if ((insn & (1 << 23)) == 0) { +- /* Three register same length. */ +- op = ((insn >> 7) & 0x1e) | ((insn >> 4) & 1); +- /* Catch invalid op and bad size combinations: UNDEF */ +- if ((neon_3r_sizes[op] & (1 << size)) == 0) { +- return 1; +- } +- /* All insns of this form UNDEF for either this condition or the +- * superset of cases "Q==1"; we catch the latter later. +- */ +- if (q && ((rd | rn | rm) & 1)) { +- return 1; +- } +- switch (op) { +- case NEON_3R_VFM_VQRDMLSH: +- if (!u) { +- /* VFM, VFMS */ +- if (size == 1) { +- return 1; +- } +- break; +- } +- /* VQRDMLSH : handled by decodetree */ +- return 1; +- +- case NEON_3R_VADD_VSUB: +- case NEON_3R_LOGIC: +- case NEON_3R_VMAX: +- case NEON_3R_VMIN: +- case NEON_3R_VTST_VCEQ: +- case NEON_3R_VCGT: +- case NEON_3R_VCGE: +- case NEON_3R_VQADD: +- case NEON_3R_VQSUB: +- case NEON_3R_VMUL: +- case NEON_3R_VML: +- case NEON_3R_VSHL: +- case NEON_3R_SHA: +- case NEON_3R_VHADD: +- case NEON_3R_VRHADD: +- case NEON_3R_VHSUB: +- case NEON_3R_VABD: +- case NEON_3R_VABA: +- case NEON_3R_VQSHL: +- case NEON_3R_VRSHL: +- case NEON_3R_VQRSHL: +- case NEON_3R_VPMAX: +- case NEON_3R_VPMIN: +- case NEON_3R_VPADD_VQRDMLAH: +- case NEON_3R_VQDMULH_VQRDMULH: +- case NEON_3R_FLOAT_ARITH: +- case NEON_3R_FLOAT_MULTIPLY: +- case NEON_3R_FLOAT_CMP: +- case NEON_3R_FLOAT_ACMP: +- case NEON_3R_FLOAT_MINMAX: +- case NEON_3R_FLOAT_MISC: +- /* Already handled by decodetree */ +- return 1; +- } +- +- if (size == 3) { +- /* 64-bit element instructions: handled by decodetree */ +- return 1; +- } +- switch (op) { +- case NEON_3R_VFM_VQRDMLSH: +- if (!dc_isar_feature(aa32_simdfmac, s)) { +- return 1; +- } +- break; +- default: +- break; +- } +- +- for (pass = 0; pass < (q ? 4 : 2); pass++) { +- +- /* Elementwise. */ +- tmp = neon_load_reg(rn, pass); +- tmp2 = neon_load_reg(rm, pass); +- switch (op) { +- case NEON_3R_VFM_VQRDMLSH: +- { +- /* VFMA, VFMS: fused multiply-add */ +- TCGv_ptr fpstatus = get_fpstatus_ptr(1); +- TCGv_i32 tmp3 = neon_load_reg(rd, pass); +- if (size) { +- /* VFMS */ +- gen_helper_vfp_negs(tmp, tmp); +- } +- gen_helper_vfp_muladds(tmp, tmp, tmp2, tmp3, fpstatus); +- tcg_temp_free_i32(tmp3); +- tcg_temp_free_ptr(fpstatus); +- break; +- } +- default: +- abort(); +- } +- tcg_temp_free_i32(tmp2); +- +- neon_store_reg(rd, pass, tmp); +- +- } /* for pass */ +- /* End of 3 register same size operations. */ ++ /* Three register same length: handled by decodetree */ ++ return 1; + } else if (insn & (1 << 4)) { + if ((insn & 0x00380080) != 0) { + /* Two registers and shift. */ +-- +2.23.0 + diff --git a/target-arm-Convert-Neon-3-reg-same-SHA-to-decodetree.patch b/target-arm-Convert-Neon-3-reg-same-SHA-to-decodetree.patch new file mode 100644 index 0000000000000000000000000000000000000000..2deeccda9f5dca2a4c97ec0f5920639521a9a498 --- /dev/null +++ b/target-arm-Convert-Neon-3-reg-same-SHA-to-decodetree.patch @@ -0,0 +1,257 @@ +From 21290edfc29d8929741c0ed043733c23c69bc3b9 Mon Sep 17 00:00:00 2001 +From: Peter Maydell +Date: Tue, 12 May 2020 17:38:49 +0100 +Subject: [PATCH 447/709] target/arm: Convert Neon 3-reg-same SHA to decodetree + +Convert the Neon SHA instructions in the 3-reg-same group +to decodetree. + +Signed-off-by: Peter Maydell +Reviewed-by: Richard Henderson +Message-id: 20200512163904.10918-3-peter.maydell@linaro.org +--- + target/arm/neon-dp.decode | 10 +++ + target/arm/translate-neon.inc.c | 139 ++++++++++++++++++++++++++++++++ + target/arm/translate.c | 46 +---------- + 3 files changed, 151 insertions(+), 44 deletions(-) + +diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode +index 82503c582e..72eae12b26 100644 +--- a/target/arm/neon-dp.decode ++++ b/target/arm/neon-dp.decode +@@ -99,4 +99,14 @@ VMUL_3s 1111 001 0 0 . .. .... .... 1001 . . . 1 .... @3same + VMUL_p_3s 1111 001 1 0 . .. .... .... 1001 . . . 1 .... @3same + + VQRDMLAH_3s 1111 001 1 0 . .. .... .... 1011 ... 1 .... @3same ++ ++SHA1_3s 1111 001 0 0 . optype:2 .... .... 1100 . 1 . 0 .... \ ++ vm=%vm_dp vn=%vn_dp vd=%vd_dp ++SHA256H_3s 1111 001 1 0 . 00 .... .... 1100 . 1 . 0 .... \ ++ vm=%vm_dp vn=%vn_dp vd=%vd_dp ++SHA256H2_3s 1111 001 1 0 . 01 .... .... 1100 . 1 . 0 .... \ ++ vm=%vm_dp vn=%vn_dp vd=%vd_dp ++SHA256SU1_3s 1111 001 1 0 . 10 .... .... 1100 . 1 . 0 .... \ ++ vm=%vm_dp vn=%vn_dp vd=%vd_dp ++ + VQRDMLSH_3s 1111 001 1 0 . .. .... .... 1100 ... 1 .... @3same +diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c +index 661b5fc4cf..03b3337e46 100644 +--- a/target/arm/translate-neon.inc.c ++++ b/target/arm/translate-neon.inc.c +@@ -686,3 +686,142 @@ static bool trans_VMUL_p_3s(DisasContext *s, arg_3same *a) + + DO_VQRDMLAH(VQRDMLAH, gen_gvec_sqrdmlah_qc) + DO_VQRDMLAH(VQRDMLSH, gen_gvec_sqrdmlsh_qc) ++ ++static bool trans_SHA1_3s(DisasContext *s, arg_SHA1_3s *a) ++{ ++ TCGv_ptr ptr1, ptr2, ptr3; ++ TCGv_i32 tmp; ++ ++ if (!arm_dc_feature(s, ARM_FEATURE_NEON) || ++ !dc_isar_feature(aa32_sha1, s)) { ++ return false; ++ } ++ ++ /* UNDEF accesses to D16-D31 if they don't exist. */ ++ if (!dc_isar_feature(aa32_simd_r32, s) && ++ ((a->vd | a->vn | a->vm) & 0x10)) { ++ return false; ++ } ++ ++ if ((a->vn | a->vm | a->vd) & 1) { ++ return false; ++ } ++ ++ if (!vfp_access_check(s)) { ++ return true; ++ } ++ ++ ptr1 = vfp_reg_ptr(true, a->vd); ++ ptr2 = vfp_reg_ptr(true, a->vn); ++ ptr3 = vfp_reg_ptr(true, a->vm); ++ tmp = tcg_const_i32(a->optype); ++ gen_helper_crypto_sha1_3reg(ptr1, ptr2, ptr3, tmp); ++ tcg_temp_free_i32(tmp); ++ tcg_temp_free_ptr(ptr1); ++ tcg_temp_free_ptr(ptr2); ++ tcg_temp_free_ptr(ptr3); ++ ++ return true; ++} ++ ++static bool trans_SHA256H_3s(DisasContext *s, arg_SHA256H_3s *a) ++{ ++ TCGv_ptr ptr1, ptr2, ptr3; ++ ++ if (!arm_dc_feature(s, ARM_FEATURE_NEON) || ++ !dc_isar_feature(aa32_sha2, s)) { ++ return false; ++ } ++ ++ /* UNDEF accesses to D16-D31 if they don't exist. */ ++ if (!dc_isar_feature(aa32_simd_r32, s) && ++ ((a->vd | a->vn | a->vm) & 0x10)) { ++ return false; ++ } ++ ++ if ((a->vn | a->vm | a->vd) & 1) { ++ return false; ++ } ++ ++ if (!vfp_access_check(s)) { ++ return true; ++ } ++ ++ ptr1 = vfp_reg_ptr(true, a->vd); ++ ptr2 = vfp_reg_ptr(true, a->vn); ++ ptr3 = vfp_reg_ptr(true, a->vm); ++ gen_helper_crypto_sha256h(ptr1, ptr2, ptr3); ++ tcg_temp_free_ptr(ptr1); ++ tcg_temp_free_ptr(ptr2); ++ tcg_temp_free_ptr(ptr3); ++ ++ return true; ++} ++ ++static bool trans_SHA256H2_3s(DisasContext *s, arg_SHA256H2_3s *a) ++{ ++ TCGv_ptr ptr1, ptr2, ptr3; ++ ++ if (!arm_dc_feature(s, ARM_FEATURE_NEON) || ++ !dc_isar_feature(aa32_sha2, s)) { ++ return false; ++ } ++ ++ /* UNDEF accesses to D16-D31 if they don't exist. */ ++ if (!dc_isar_feature(aa32_simd_r32, s) && ++ ((a->vd | a->vn | a->vm) & 0x10)) { ++ return false; ++ } ++ ++ if ((a->vn | a->vm | a->vd) & 1) { ++ return false; ++ } ++ ++ if (!vfp_access_check(s)) { ++ return true; ++ } ++ ++ ptr1 = vfp_reg_ptr(true, a->vd); ++ ptr2 = vfp_reg_ptr(true, a->vn); ++ ptr3 = vfp_reg_ptr(true, a->vm); ++ gen_helper_crypto_sha256h2(ptr1, ptr2, ptr3); ++ tcg_temp_free_ptr(ptr1); ++ tcg_temp_free_ptr(ptr2); ++ tcg_temp_free_ptr(ptr3); ++ ++ return true; ++} ++ ++static bool trans_SHA256SU1_3s(DisasContext *s, arg_SHA256SU1_3s *a) ++{ ++ TCGv_ptr ptr1, ptr2, ptr3; ++ ++ if (!arm_dc_feature(s, ARM_FEATURE_NEON) || ++ !dc_isar_feature(aa32_sha2, s)) { ++ return false; ++ } ++ ++ /* UNDEF accesses to D16-D31 if they don't exist. */ ++ if (!dc_isar_feature(aa32_simd_r32, s) && ++ ((a->vd | a->vn | a->vm) & 0x10)) { ++ return false; ++ } ++ ++ if ((a->vn | a->vm | a->vd) & 1) { ++ return false; ++ } ++ ++ if (!vfp_access_check(s)) { ++ return true; ++ } ++ ++ ptr1 = vfp_reg_ptr(true, a->vd); ++ ptr2 = vfp_reg_ptr(true, a->vn); ++ ptr3 = vfp_reg_ptr(true, a->vm); ++ gen_helper_crypto_sha256su1(ptr1, ptr2, ptr3); ++ tcg_temp_free_ptr(ptr1); ++ tcg_temp_free_ptr(ptr2); ++ tcg_temp_free_ptr(ptr3); ++ ++ return true; ++} +diff --git a/target/arm/translate.c b/target/arm/translate.c +index 1f06cb5a87..ee2b8d6f6e 100644 +--- a/target/arm/translate.c ++++ b/target/arm/translate.c +@@ -5359,7 +5359,7 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn) + int vec_size; + uint32_t imm; + TCGv_i32 tmp, tmp2, tmp3, tmp4, tmp5; +- TCGv_ptr ptr1, ptr2, ptr3; ++ TCGv_ptr ptr1, ptr2; + TCGv_i64 tmp64; + + if (!arm_dc_feature(s, ARM_FEATURE_NEON)) { +@@ -5403,49 +5403,6 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn) + return 1; + } + switch (op) { +- case NEON_3R_SHA: +- /* The SHA-1/SHA-256 3-register instructions require special +- * treatment here, as their size field is overloaded as an +- * op type selector, and they all consume their input in a +- * single pass. +- */ +- if (!q) { +- return 1; +- } +- if (!u) { /* SHA-1 */ +- if (!dc_isar_feature(aa32_sha1, s)) { +- return 1; +- } +- ptr1 = vfp_reg_ptr(true, rd); +- ptr2 = vfp_reg_ptr(true, rn); +- ptr3 = vfp_reg_ptr(true, rm); +- tmp4 = tcg_const_i32(size); +- gen_helper_crypto_sha1_3reg(ptr1, ptr2, ptr3, tmp4); +- tcg_temp_free_i32(tmp4); +- } else { /* SHA-256 */ +- if (!dc_isar_feature(aa32_sha2, s) || size == 3) { +- return 1; +- } +- ptr1 = vfp_reg_ptr(true, rd); +- ptr2 = vfp_reg_ptr(true, rn); +- ptr3 = vfp_reg_ptr(true, rm); +- switch (size) { +- case 0: +- gen_helper_crypto_sha256h(ptr1, ptr2, ptr3); +- break; +- case 1: +- gen_helper_crypto_sha256h2(ptr1, ptr2, ptr3); +- break; +- case 2: +- gen_helper_crypto_sha256su1(ptr1, ptr2, ptr3); +- break; +- } +- } +- tcg_temp_free_ptr(ptr1); +- tcg_temp_free_ptr(ptr2); +- tcg_temp_free_ptr(ptr3); +- return 0; +- + case NEON_3R_VPADD_VQRDMLAH: + if (!u) { + break; /* VPADD */ +@@ -5496,6 +5453,7 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn) + case NEON_3R_VMUL: + case NEON_3R_VML: + case NEON_3R_VSHL: ++ case NEON_3R_SHA: + /* Already handled by decodetree */ + return 1; + } +-- +2.23.0 + diff --git a/target-arm-Convert-Neon-3-reg-same-VADD-VSUB-to-deco.patch b/target-arm-Convert-Neon-3-reg-same-VADD-VSUB-to-deco.patch new file mode 100644 index 0000000000000000000000000000000000000000..04a00e280d9bbb691bab6fe2826b7641ee466cc4 --- /dev/null +++ b/target-arm-Convert-Neon-3-reg-same-VADD-VSUB-to-deco.patch @@ -0,0 +1,176 @@ +From a4e143ac5b9185f670d2f17ee9cc1a430047cb65 Mon Sep 17 00:00:00 2001 +From: Peter Maydell +Date: Thu, 30 Apr 2020 19:09:41 +0100 +Subject: [PATCH 181/709] target/arm: Convert Neon 3-reg-same VADD/VSUB to + decodetree + +Convert the Neon 3-reg-same VADD and VSUB insns to decodetree. + +Note that we don't need the neon_3r_sizes[op] check here because all +size values are OK for VADD and VSUB; we'll add this when we convert +the first insn that has size restrictions. + +For this we need one of the GVecGen*Fn typedefs currently in +translate-a64.h; move them all to translate.h as a block so they +are visible to the 32-bit decoder. + +Signed-off-by: Peter Maydell +Reviewed-by: Richard Henderson +Message-id: 20200430181003.21682-15-peter.maydell@linaro.org +--- + target/arm/neon-dp.decode | 17 +++++++++++++++ + target/arm/translate-a64.h | 9 -------- + target/arm/translate-neon.inc.c | 38 +++++++++++++++++++++++++++++++++ + target/arm/translate.c | 14 ++++-------- + target/arm/translate.h | 9 ++++++++ + 5 files changed, 68 insertions(+), 19 deletions(-) + +diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode +index c89a1a5859..a61b1e8847 100644 +--- a/target/arm/neon-dp.decode ++++ b/target/arm/neon-dp.decode +@@ -18,6 +18,10 @@ + # + # This file is processed by scripts/decodetree.py + # ++# VFP/Neon register fields; same as vfp.decode ++%vm_dp 5:1 0:4 ++%vn_dp 7:1 16:4 ++%vd_dp 22:1 12:4 + + # Encodings for Neon data processing instructions where the T32 encoding + # is a simple transformation of the A32 encoding. +@@ -27,3 +31,16 @@ + # 0b111p_1111_qqqq_qqqq_qqqq_qqqq_qqqq_qqqq + # This file works on the A32 encoding only; calling code for T32 has to + # transform the insn into the A32 version first. ++ ++###################################################################### ++# 3-reg-same grouping: ++# 1111 001 U 0 D sz:2 Vn:4 Vd:4 opc:4 N Q M op Vm:4 ++###################################################################### ++ ++&3same vm vn vd q size ++ ++@3same .... ... . . . size:2 .... .... .... . q:1 . . .... \ ++ &3same vm=%vm_dp vn=%vn_dp vd=%vd_dp ++ ++VADD_3s 1111 001 0 0 . .. .... .... 1000 . . . 0 .... @3same ++VSUB_3s 1111 001 1 0 . .. .... .... 1000 . . . 0 .... @3same +diff --git a/target/arm/translate-a64.h b/target/arm/translate-a64.h +index 4c2c91ae1b..f02fbb63a4 100644 +--- a/target/arm/translate-a64.h ++++ b/target/arm/translate-a64.h +@@ -115,13 +115,4 @@ static inline int vec_full_reg_size(DisasContext *s) + + bool disas_sve(DisasContext *, uint32_t); + +-/* Note that the gvec expanders operate on offsets + sizes. */ +-typedef void GVecGen2Fn(unsigned, uint32_t, uint32_t, uint32_t, uint32_t); +-typedef void GVecGen2iFn(unsigned, uint32_t, uint32_t, int64_t, +- uint32_t, uint32_t); +-typedef void GVecGen3Fn(unsigned, uint32_t, uint32_t, +- uint32_t, uint32_t, uint32_t); +-typedef void GVecGen4Fn(unsigned, uint32_t, uint32_t, uint32_t, +- uint32_t, uint32_t, uint32_t); +- + #endif /* TARGET_ARM_TRANSLATE_A64_H */ +diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c +index c881d1cf60..bd9e697b3e 100644 +--- a/target/arm/translate-neon.inc.c ++++ b/target/arm/translate-neon.inc.c +@@ -560,3 +560,41 @@ static bool trans_VLDST_single(DisasContext *s, arg_VLDST_single *a) + + return true; + } ++ ++static bool do_3same(DisasContext *s, arg_3same *a, GVecGen3Fn fn) ++{ ++ int vec_size = a->q ? 16 : 8; ++ int rd_ofs = neon_reg_offset(a->vd, 0); ++ int rn_ofs = neon_reg_offset(a->vn, 0); ++ int rm_ofs = neon_reg_offset(a->vm, 0); ++ ++ if (!arm_dc_feature(s, ARM_FEATURE_NEON)) { ++ return false; ++ } ++ ++ /* UNDEF accesses to D16-D31 if they don't exist. */ ++ if (!dc_isar_feature(aa32_simd_r32, s) && ++ ((a->vd | a->vn | a->vm) & 0x10)) { ++ return false; ++ } ++ ++ if ((a->vn | a->vm | a->vd) & a->q) { ++ return false; ++ } ++ ++ if (!vfp_access_check(s)) { ++ return true; ++ } ++ ++ fn(a->size, rd_ofs, rn_ofs, rm_ofs, vec_size, vec_size); ++ return true; ++} ++ ++#define DO_3SAME(INSN, FUNC) \ ++ static bool trans_##INSN##_3s(DisasContext *s, arg_3same *a) \ ++ { \ ++ return do_3same(s, a, FUNC); \ ++ } ++ ++DO_3SAME(VADD, tcg_gen_gvec_add) ++DO_3SAME(VSUB, tcg_gen_gvec_sub) +diff --git a/target/arm/translate.c b/target/arm/translate.c +index 613be39ef3..061bc7c31c 100644 +--- a/target/arm/translate.c ++++ b/target/arm/translate.c +@@ -4885,16 +4885,6 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn) + } + return 0; + +- case NEON_3R_VADD_VSUB: +- if (u) { +- tcg_gen_gvec_sub(size, rd_ofs, rn_ofs, rm_ofs, +- vec_size, vec_size); +- } else { +- tcg_gen_gvec_add(size, rd_ofs, rn_ofs, rm_ofs, +- vec_size, vec_size); +- } +- return 0; +- + case NEON_3R_VQADD: + tcg_gen_gvec_4(rd_ofs, offsetof(CPUARMState, vfp.qc), + rn_ofs, rm_ofs, vec_size, vec_size, +@@ -4970,6 +4960,10 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn) + tcg_gen_gvec_3(rd_ofs, rm_ofs, rn_ofs, vec_size, vec_size, + u ? &ushl_op[size] : &sshl_op[size]); + return 0; ++ ++ case NEON_3R_VADD_VSUB: ++ /* Already handled by decodetree */ ++ return 1; + } + + if (size == 3) { +diff --git a/target/arm/translate.h b/target/arm/translate.h +index 98b319f3f6..95b43e7ab6 100644 +--- a/target/arm/translate.h ++++ b/target/arm/translate.h +@@ -305,4 +305,13 @@ void gen_sshl_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b); + #define dc_isar_feature(name, ctx) \ + ({ DisasContext *ctx_ = (ctx); isar_feature_##name(ctx_->isar); }) + ++/* Note that the gvec expanders operate on offsets + sizes. */ ++typedef void GVecGen2Fn(unsigned, uint32_t, uint32_t, uint32_t, uint32_t); ++typedef void GVecGen2iFn(unsigned, uint32_t, uint32_t, int64_t, ++ uint32_t, uint32_t); ++typedef void GVecGen3Fn(unsigned, uint32_t, uint32_t, ++ uint32_t, uint32_t, uint32_t); ++typedef void GVecGen4Fn(unsigned, uint32_t, uint32_t, uint32_t, ++ uint32_t, uint32_t, uint32_t); ++ + #endif /* TARGET_ARM_TRANSLATE_H */ +-- +2.23.0 + diff --git a/target-arm-Convert-Neon-3-reg-same-VMAX-VMIN-to-deco.patch b/target-arm-Convert-Neon-3-reg-same-VMAX-VMIN-to-deco.patch new file mode 100644 index 0000000000000000000000000000000000000000..0bf62c456308d1fa24639591cfd35c3cb4f4a93e --- /dev/null +++ b/target-arm-Convert-Neon-3-reg-same-VMAX-VMIN-to-deco.patch @@ -0,0 +1,96 @@ +From 36b59310c38d45213bf860affa90618aa5eeca93 Mon Sep 17 00:00:00 2001 +From: Peter Maydell +Date: Thu, 30 Apr 2020 19:09:43 +0100 +Subject: [PATCH 183/709] target/arm: Convert Neon 3-reg-same VMAX/VMIN to + decodetree + +Convert the Neon 3-reg-same VMAX and VMIN insns to decodetree. + +Signed-off-by: Peter Maydell +Reviewed-by: Richard Henderson +Message-id: 20200430181003.21682-17-peter.maydell@linaro.org +--- + target/arm/neon-dp.decode | 5 +++++ + target/arm/translate-neon.inc.c | 14 ++++++++++++++ + target/arm/translate.c | 21 ++------------------- + 3 files changed, 21 insertions(+), 19 deletions(-) + +diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode +index f62dbaa72d..b721d39c7b 100644 +--- a/target/arm/neon-dp.decode ++++ b/target/arm/neon-dp.decode +@@ -54,5 +54,10 @@ VBSL_3s 1111 001 1 0 . 01 .... .... 0001 ... 1 .... @3same_logic + VBIT_3s 1111 001 1 0 . 10 .... .... 0001 ... 1 .... @3same_logic + VBIF_3s 1111 001 1 0 . 11 .... .... 0001 ... 1 .... @3same_logic + ++VMAX_S_3s 1111 001 0 0 . .. .... .... 0110 . . . 0 .... @3same ++VMAX_U_3s 1111 001 1 0 . .. .... .... 0110 . . . 0 .... @3same ++VMIN_S_3s 1111 001 0 0 . .. .... .... 0110 . . . 1 .... @3same ++VMIN_U_3s 1111 001 1 0 . .. .... .... 0110 . . . 1 .... @3same ++ + VADD_3s 1111 001 0 0 . .. .... .... 1000 . . . 0 .... @3same + VSUB_3s 1111 001 1 0 . .. .... .... 1000 . . . 0 .... @3same +diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c +index 507f0abe80..ab1740201c 100644 +--- a/target/arm/translate-neon.inc.c ++++ b/target/arm/translate-neon.inc.c +@@ -617,3 +617,17 @@ DO_3SAME(VEOR, tcg_gen_gvec_xor) + DO_3SAME_BITSEL(VBSL, rd_ofs, rn_ofs, rm_ofs) + DO_3SAME_BITSEL(VBIT, rm_ofs, rn_ofs, rd_ofs) + DO_3SAME_BITSEL(VBIF, rm_ofs, rd_ofs, rn_ofs) ++ ++#define DO_3SAME_NO_SZ_3(INSN, FUNC) \ ++ static bool trans_##INSN##_3s(DisasContext *s, arg_3same *a) \ ++ { \ ++ if (a->size == 3) { \ ++ return false; \ ++ } \ ++ return do_3same(s, a, FUNC); \ ++ } ++ ++DO_3SAME_NO_SZ_3(VMAX_S, tcg_gen_gvec_smax) ++DO_3SAME_NO_SZ_3(VMAX_U, tcg_gen_gvec_umax) ++DO_3SAME_NO_SZ_3(VMIN_S, tcg_gen_gvec_smin) ++DO_3SAME_NO_SZ_3(VMIN_U, tcg_gen_gvec_umin) +diff --git a/target/arm/translate.c b/target/arm/translate.c +index 9affa92cbe..2f054cfa78 100644 +--- a/target/arm/translate.c ++++ b/target/arm/translate.c +@@ -4899,25 +4899,6 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn) + rd_ofs, rn_ofs, rm_ofs, vec_size, vec_size); + return 0; + +- case NEON_3R_VMAX: +- if (u) { +- tcg_gen_gvec_umax(size, rd_ofs, rn_ofs, rm_ofs, +- vec_size, vec_size); +- } else { +- tcg_gen_gvec_smax(size, rd_ofs, rn_ofs, rm_ofs, +- vec_size, vec_size); +- } +- return 0; +- case NEON_3R_VMIN: +- if (u) { +- tcg_gen_gvec_umin(size, rd_ofs, rn_ofs, rm_ofs, +- vec_size, vec_size); +- } else { +- tcg_gen_gvec_smin(size, rd_ofs, rn_ofs, rm_ofs, +- vec_size, vec_size); +- } +- return 0; +- + case NEON_3R_VSHL: + /* Note the operation is vshl vd,vm,vn */ + tcg_gen_gvec_3(rd_ofs, rm_ofs, rn_ofs, vec_size, vec_size, +@@ -4926,6 +4907,8 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn) + + case NEON_3R_VADD_VSUB: + case NEON_3R_LOGIC: ++ case NEON_3R_VMAX: ++ case NEON_3R_VMIN: + /* Already handled by decodetree */ + return 1; + } +-- +2.23.0 + diff --git a/target-arm-Convert-Neon-3-reg-same-VMUL-VMLA-VMLS-VS.patch b/target-arm-Convert-Neon-3-reg-same-VMUL-VMLA-VMLS-VS.patch new file mode 100644 index 0000000000000000000000000000000000000000..afae5002e8ff5bdc416d6d96dacc3e188f887566 --- /dev/null +++ b/target-arm-Convert-Neon-3-reg-same-VMUL-VMLA-VMLS-VS.patch @@ -0,0 +1,150 @@ +From 0de34fd48ad4e44bf5caa2330657ebefa93cea7d Mon Sep 17 00:00:00 2001 +From: Peter Maydell +Date: Thu, 30 Apr 2020 19:09:46 +0100 +Subject: [PATCH 186/709] target/arm: Convert Neon 3-reg-same VMUL, VMLA, VMLS, + VSHL to decodetree + +Convert the Neon VMUL, VMLA, VMLS and VSHL insns in the +3-reg-same grouping to decodetree. + +Signed-off-by: Peter Maydell +Reviewed-by: Richard Henderson +Message-id: 20200430181003.21682-20-peter.maydell@linaro.org +--- + target/arm/neon-dp.decode | 9 +++++++ + target/arm/translate-neon.inc.c | 44 +++++++++++++++++++++++++++++++++ + target/arm/translate.c | 28 +++------------------ + 3 files changed, 56 insertions(+), 25 deletions(-) + +diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode +index ab59b349aa..ec3a92fe75 100644 +--- a/target/arm/neon-dp.decode ++++ b/target/arm/neon-dp.decode +@@ -65,6 +65,9 @@ VCGT_U_3s 1111 001 1 0 . .. .... .... 0011 . . . 0 .... @3same + VCGE_S_3s 1111 001 0 0 . .. .... .... 0011 . . . 1 .... @3same + VCGE_U_3s 1111 001 1 0 . .. .... .... 0011 . . . 1 .... @3same + ++VSHL_S_3s 1111 001 0 0 . .. .... .... 0100 . . . 0 .... @3same ++VSHL_U_3s 1111 001 1 0 . .. .... .... 0100 . . . 0 .... @3same ++ + VMAX_S_3s 1111 001 0 0 . .. .... .... 0110 . . . 0 .... @3same + VMAX_U_3s 1111 001 1 0 . .. .... .... 0110 . . . 0 .... @3same + VMIN_S_3s 1111 001 0 0 . .. .... .... 0110 . . . 1 .... @3same +@@ -75,3 +78,9 @@ VSUB_3s 1111 001 1 0 . .. .... .... 1000 . . . 0 .... @3same + + VTST_3s 1111 001 0 0 . .. .... .... 1000 . . . 1 .... @3same + VCEQ_3s 1111 001 1 0 . .. .... .... 1000 . . . 1 .... @3same ++ ++VMLA_3s 1111 001 0 0 . .. .... .... 1001 . . . 0 .... @3same ++VMLS_3s 1111 001 1 0 . .. .... .... 1001 . . . 0 .... @3same ++ ++VMUL_3s 1111 001 0 0 . .. .... .... 1001 . . . 1 .... @3same ++VMUL_p_3s 1111 001 1 0 . .. .... .... 1001 . . . 1 .... @3same +diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c +index 854ab70cd7..50b77b6d71 100644 +--- a/target/arm/translate-neon.inc.c ++++ b/target/arm/translate-neon.inc.c +@@ -631,6 +631,7 @@ DO_3SAME_NO_SZ_3(VMAX_S, tcg_gen_gvec_smax) + DO_3SAME_NO_SZ_3(VMAX_U, tcg_gen_gvec_umax) + DO_3SAME_NO_SZ_3(VMIN_S, tcg_gen_gvec_smin) + DO_3SAME_NO_SZ_3(VMIN_U, tcg_gen_gvec_umin) ++DO_3SAME_NO_SZ_3(VMUL, tcg_gen_gvec_mul) + + #define DO_3SAME_CMP(INSN, COND) \ + static void gen_##INSN##_3s(unsigned vece, uint32_t rd_ofs, \ +@@ -668,3 +669,46 @@ DO_3SAME_GVEC4(VQADD_S, sqadd_op) + DO_3SAME_GVEC4(VQADD_U, uqadd_op) + DO_3SAME_GVEC4(VQSUB_S, sqsub_op) + DO_3SAME_GVEC4(VQSUB_U, uqsub_op) ++ ++static void gen_VMUL_p_3s(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs, ++ uint32_t rm_ofs, uint32_t oprsz, uint32_t maxsz) ++{ ++ tcg_gen_gvec_3_ool(rd_ofs, rn_ofs, rm_ofs, oprsz, maxsz, ++ 0, gen_helper_gvec_pmul_b); ++} ++ ++static bool trans_VMUL_p_3s(DisasContext *s, arg_3same *a) ++{ ++ if (a->size != 0) { ++ return false; ++ } ++ return do_3same(s, a, gen_VMUL_p_3s); ++} ++ ++#define DO_3SAME_GVEC3_NO_SZ_3(INSN, OPARRAY) \ ++ static void gen_##INSN##_3s(unsigned vece, uint32_t rd_ofs, \ ++ uint32_t rn_ofs, uint32_t rm_ofs, \ ++ uint32_t oprsz, uint32_t maxsz) \ ++ { \ ++ tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, \ ++ oprsz, maxsz, &OPARRAY[vece]); \ ++ } \ ++ DO_3SAME_NO_SZ_3(INSN, gen_##INSN##_3s) ++ ++ ++DO_3SAME_GVEC3_NO_SZ_3(VMLA, mla_op) ++DO_3SAME_GVEC3_NO_SZ_3(VMLS, mls_op) ++ ++#define DO_3SAME_GVEC3_SHIFT(INSN, OPARRAY) \ ++ static void gen_##INSN##_3s(unsigned vece, uint32_t rd_ofs, \ ++ uint32_t rn_ofs, uint32_t rm_ofs, \ ++ uint32_t oprsz, uint32_t maxsz) \ ++ { \ ++ /* Note the operation is vshl vd,vm,vn */ \ ++ tcg_gen_gvec_3(rd_ofs, rm_ofs, rn_ofs, \ ++ oprsz, maxsz, &OPARRAY[vece]); \ ++ } \ ++ DO_3SAME(INSN, gen_##INSN##_3s) ++ ++DO_3SAME_GVEC3_SHIFT(VSHL_S, sshl_op) ++DO_3SAME_GVEC3_SHIFT(VSHL_U, ushl_op) +diff --git a/target/arm/translate.c b/target/arm/translate.c +index 13ce1a5fc1..025747c0bd 100644 +--- a/target/arm/translate.c ++++ b/target/arm/translate.c +@@ -4848,31 +4848,6 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn) + } + return 1; + +- case NEON_3R_VMUL: /* VMUL */ +- if (u) { +- /* Polynomial case allows only P8. */ +- if (size != 0) { +- return 1; +- } +- tcg_gen_gvec_3_ool(rd_ofs, rn_ofs, rm_ofs, vec_size, vec_size, +- 0, gen_helper_gvec_pmul_b); +- } else { +- tcg_gen_gvec_mul(size, rd_ofs, rn_ofs, rm_ofs, +- vec_size, vec_size); +- } +- return 0; +- +- case NEON_3R_VML: /* VMLA, VMLS */ +- tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, vec_size, vec_size, +- u ? &mls_op[size] : &mla_op[size]); +- return 0; +- +- case NEON_3R_VSHL: +- /* Note the operation is vshl vd,vm,vn */ +- tcg_gen_gvec_3(rd_ofs, rm_ofs, rn_ofs, vec_size, vec_size, +- u ? &ushl_op[size] : &sshl_op[size]); +- return 0; +- + case NEON_3R_VADD_VSUB: + case NEON_3R_LOGIC: + case NEON_3R_VMAX: +@@ -4882,6 +4857,9 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn) + case NEON_3R_VCGE: + case NEON_3R_VQADD: + case NEON_3R_VQSUB: ++ case NEON_3R_VMUL: ++ case NEON_3R_VML: ++ case NEON_3R_VSHL: + /* Already handled by decodetree */ + return 1; + } +-- +2.23.0 + diff --git a/target-arm-Convert-Neon-3-reg-same-VQADD-VQSUB-to-de.patch b/target-arm-Convert-Neon-3-reg-same-VQADD-VQSUB-to-de.patch new file mode 100644 index 0000000000000000000000000000000000000000..99c69b6c39f4283c1ec3eaca481f7642cb305ba5 --- /dev/null +++ b/target-arm-Convert-Neon-3-reg-same-VQADD-VQSUB-to-de.patch @@ -0,0 +1,100 @@ +From 7a9497f1cf73667a4744d09673b808c20e067915 Mon Sep 17 00:00:00 2001 +From: Peter Maydell +Date: Thu, 30 Apr 2020 19:09:45 +0100 +Subject: [PATCH 185/709] target/arm: Convert Neon 3-reg-same VQADD/VQSUB to + decodetree + +Convert the Neon VQADD/VQSUB insns in the 3-reg-same grouping +to decodetree. + +Signed-off-by: Peter Maydell +Reviewed-by: Richard Henderson +Message-id: 20200430181003.21682-19-peter.maydell@linaro.org +--- + target/arm/neon-dp.decode | 6 ++++++ + target/arm/translate-neon.inc.c | 15 +++++++++++++++ + target/arm/translate.c | 14 ++------------ + 3 files changed, 23 insertions(+), 12 deletions(-) + +diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode +index b89ea6819a..ab59b349aa 100644 +--- a/target/arm/neon-dp.decode ++++ b/target/arm/neon-dp.decode +@@ -42,6 +42,9 @@ + @3same .... ... . . . size:2 .... .... .... . q:1 . . .... \ + &3same vm=%vm_dp vn=%vn_dp vd=%vd_dp + ++VQADD_S_3s 1111 001 0 0 . .. .... .... 0000 . . . 1 .... @3same ++VQADD_U_3s 1111 001 1 0 . .. .... .... 0000 . . . 1 .... @3same ++ + @3same_logic .... ... . . . .. .... .... .... . q:1 .. .... \ + &3same vm=%vm_dp vn=%vn_dp vd=%vd_dp size=0 + +@@ -54,6 +57,9 @@ VBSL_3s 1111 001 1 0 . 01 .... .... 0001 ... 1 .... @3same_logic + VBIT_3s 1111 001 1 0 . 10 .... .... 0001 ... 1 .... @3same_logic + VBIF_3s 1111 001 1 0 . 11 .... .... 0001 ... 1 .... @3same_logic + ++VQSUB_S_3s 1111 001 0 0 . .. .... .... 0010 . . . 1 .... @3same ++VQSUB_U_3s 1111 001 1 0 . .. .... .... 0010 . . . 1 .... @3same ++ + VCGT_S_3s 1111 001 0 0 . .. .... .... 0011 . . . 0 .... @3same + VCGT_U_3s 1111 001 1 0 . .. .... .... 0011 . . . 0 .... @3same + VCGE_S_3s 1111 001 0 0 . .. .... .... 0011 . . . 1 .... @3same +diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c +index 952e4456f5..854ab70cd7 100644 +--- a/target/arm/translate-neon.inc.c ++++ b/target/arm/translate-neon.inc.c +@@ -653,3 +653,18 @@ static void gen_VTST_3s(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs, + tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, oprsz, maxsz, &cmtst_op[vece]); + } + DO_3SAME_NO_SZ_3(VTST, gen_VTST_3s) ++ ++#define DO_3SAME_GVEC4(INSN, OPARRAY) \ ++ static void gen_##INSN##_3s(unsigned vece, uint32_t rd_ofs, \ ++ uint32_t rn_ofs, uint32_t rm_ofs, \ ++ uint32_t oprsz, uint32_t maxsz) \ ++ { \ ++ tcg_gen_gvec_4(rd_ofs, offsetof(CPUARMState, vfp.qc), \ ++ rn_ofs, rm_ofs, oprsz, maxsz, &OPARRAY[vece]); \ ++ } \ ++ DO_3SAME(INSN, gen_##INSN##_3s) ++ ++DO_3SAME_GVEC4(VQADD_S, sqadd_op) ++DO_3SAME_GVEC4(VQADD_U, uqadd_op) ++DO_3SAME_GVEC4(VQSUB_S, sqsub_op) ++DO_3SAME_GVEC4(VQSUB_U, uqsub_op) +diff --git a/target/arm/translate.c b/target/arm/translate.c +index 0e6ecc0969..13ce1a5fc1 100644 +--- a/target/arm/translate.c ++++ b/target/arm/translate.c +@@ -4848,18 +4848,6 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn) + } + return 1; + +- case NEON_3R_VQADD: +- tcg_gen_gvec_4(rd_ofs, offsetof(CPUARMState, vfp.qc), +- rn_ofs, rm_ofs, vec_size, vec_size, +- (u ? uqadd_op : sqadd_op) + size); +- return 0; +- +- case NEON_3R_VQSUB: +- tcg_gen_gvec_4(rd_ofs, offsetof(CPUARMState, vfp.qc), +- rn_ofs, rm_ofs, vec_size, vec_size, +- (u ? uqsub_op : sqsub_op) + size); +- return 0; +- + case NEON_3R_VMUL: /* VMUL */ + if (u) { + /* Polynomial case allows only P8. */ +@@ -4892,6 +4880,8 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn) + case NEON_3R_VTST_VCEQ: + case NEON_3R_VCGT: + case NEON_3R_VCGE: ++ case NEON_3R_VQADD: ++ case NEON_3R_VQSUB: + /* Already handled by decodetree */ + return 1; + } +-- +2.23.0 + diff --git a/target-arm-Convert-Neon-3-reg-same-VQRDMLAH-VQRDMLSH.patch b/target-arm-Convert-Neon-3-reg-same-VQRDMLAH-VQRDMLSH.patch new file mode 100644 index 0000000000000000000000000000000000000000..98ea3926c2a7233d6024352905ae39881f70dda3 --- /dev/null +++ b/target-arm-Convert-Neon-3-reg-same-VQRDMLAH-VQRDMLSH.patch @@ -0,0 +1,89 @@ +From a063569508af8295cf6271e06700e5b956bb402d Mon Sep 17 00:00:00 2001 +From: Peter Maydell +Date: Tue, 12 May 2020 17:38:48 +0100 +Subject: [PATCH 446/709] target/arm: Convert Neon 3-reg-same VQRDMLAH/VQRDMLSH + to decodetree + +Convert the Neon VQRDMLAH and VQRDMLSH insns in the 3-reg-same group +to decodetree. These don't use do_3same() because they want to +operate on VFP double registers, whose offsets are different from the +neon_reg_offset() calculations do_3same does. + +Signed-off-by: Peter Maydell +Reviewed-by: Richard Henderson +Message-id: 20200512163904.10918-2-peter.maydell@linaro.org +--- + target/arm/neon-dp.decode | 3 +++ + target/arm/translate-neon.inc.c | 15 +++++++++++++++ + target/arm/translate.c | 14 ++------------ + 3 files changed, 20 insertions(+), 12 deletions(-) + +diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode +index 593f7fff03..82503c582e 100644 +--- a/target/arm/neon-dp.decode ++++ b/target/arm/neon-dp.decode +@@ -97,3 +97,6 @@ VMLS_3s 1111 001 1 0 . .. .... .... 1001 . . . 0 .... @3same + + VMUL_3s 1111 001 0 0 . .. .... .... 1001 . . . 1 .... @3same + VMUL_p_3s 1111 001 1 0 . .. .... .... 1001 . . . 1 .... @3same ++ ++VQRDMLAH_3s 1111 001 1 0 . .. .... .... 1011 ... 1 .... @3same ++VQRDMLSH_3s 1111 001 1 0 . .. .... .... 1100 ... 1 .... @3same +diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c +index 099491b16f..661b5fc4cf 100644 +--- a/target/arm/translate-neon.inc.c ++++ b/target/arm/translate-neon.inc.c +@@ -671,3 +671,18 @@ static bool trans_VMUL_p_3s(DisasContext *s, arg_3same *a) + } + return do_3same(s, a, gen_VMUL_p_3s); + } ++ ++#define DO_VQRDMLAH(INSN, FUNC) \ ++ static bool trans_##INSN##_3s(DisasContext *s, arg_3same *a) \ ++ { \ ++ if (!dc_isar_feature(aa32_rdm, s)) { \ ++ return false; \ ++ } \ ++ if (a->size != 1 && a->size != 2) { \ ++ return false; \ ++ } \ ++ return do_3same(s, a, FUNC); \ ++ } ++ ++DO_VQRDMLAH(VQRDMLAH, gen_gvec_sqrdmlah_qc) ++DO_VQRDMLAH(VQRDMLSH, gen_gvec_sqrdmlsh_qc) +diff --git a/target/arm/translate.c b/target/arm/translate.c +index e3d37ef2e9..1f06cb5a87 100644 +--- a/target/arm/translate.c ++++ b/target/arm/translate.c +@@ -5450,12 +5450,7 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn) + if (!u) { + break; /* VPADD */ + } +- /* VQRDMLAH */ +- if (dc_isar_feature(aa32_rdm, s) && (size == 1 || size == 2)) { +- gen_gvec_sqrdmlah_qc(size, rd_ofs, rn_ofs, rm_ofs, +- vec_size, vec_size); +- return 0; +- } ++ /* VQRDMLAH : handled by decodetree */ + return 1; + + case NEON_3R_VFM_VQRDMLSH: +@@ -5466,12 +5461,7 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn) + } + break; + } +- /* VQRDMLSH */ +- if (dc_isar_feature(aa32_rdm, s) && (size == 1 || size == 2)) { +- gen_gvec_sqrdmlsh_qc(size, rd_ofs, rn_ofs, rm_ofs, +- vec_size, vec_size); +- return 0; +- } ++ /* VQRDMLSH : handled by decodetree */ + return 1; + + case NEON_3R_VABD: +-- +2.23.0 + diff --git a/target-arm-Convert-Neon-3-reg-same-compare-insns-to-.patch b/target-arm-Convert-Neon-3-reg-same-compare-insns-to-.patch new file mode 100644 index 0000000000000000000000000000000000000000..7a36d1fabab4979ed3fb9cca5aeae4954aad4d0b --- /dev/null +++ b/target-arm-Convert-Neon-3-reg-same-compare-insns-to-.patch @@ -0,0 +1,117 @@ +From 727ff1d63213e6666e511956903b9e97a339ec7e Mon Sep 17 00:00:00 2001 +From: Peter Maydell +Date: Tue, 12 May 2020 17:39:01 +0100 +Subject: [PATCH 459/709] target/arm: Convert Neon 3-reg-same compare insns to + decodetree + +Convert the Neon integer 3-reg-same compare insns VCGE, VCGT, +VCEQ, VACGE and VACGT to decodetree. + +Signed-off-by: Peter Maydell +Reviewed-by: Richard Henderson +Message-id: 20200512163904.10918-15-peter.maydell@linaro.org +--- + target/arm/neon-dp.decode | 5 +++++ + target/arm/translate-neon.inc.c | 6 +++++ + target/arm/translate.c | 39 ++------------------------------- + 3 files changed, 13 insertions(+), 37 deletions(-) + +diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode +index 4c2f8c770d..29cf54c217 100644 +--- a/target/arm/neon-dp.decode ++++ b/target/arm/neon-dp.decode +@@ -183,5 +183,10 @@ VABD_fp_3s 1111 001 1 0 . 1 . .... .... 1101 ... 0 .... @3same_fp + VMLA_fp_3s 1111 001 0 0 . 0 . .... .... 1101 ... 1 .... @3same_fp + VMLS_fp_3s 1111 001 0 0 . 1 . .... .... 1101 ... 1 .... @3same_fp + VMUL_fp_3s 1111 001 1 0 . 0 . .... .... 1101 ... 1 .... @3same_fp ++VCEQ_fp_3s 1111 001 0 0 . 0 . .... .... 1110 ... 0 .... @3same_fp ++VCGE_fp_3s 1111 001 1 0 . 0 . .... .... 1110 ... 0 .... @3same_fp ++VACGE_fp_3s 1111 001 1 0 . 0 . .... .... 1110 ... 1 .... @3same_fp ++VCGT_fp_3s 1111 001 1 0 . 1 . .... .... 1110 ... 0 .... @3same_fp ++VACGT_fp_3s 1111 001 1 0 . 1 . .... .... 1110 ... 1 .... @3same_fp + VPMAX_fp_3s 1111 001 1 0 . 0 . .... .... 1111 ... 0 .... @3same_fp_q0 + VPMIN_fp_3s 1111 001 1 0 . 1 . .... .... 1111 ... 0 .... @3same_fp_q0 +diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c +index 18896598bb..eeea71e3be 100644 +--- a/target/arm/translate-neon.inc.c ++++ b/target/arm/translate-neon.inc.c +@@ -1114,6 +1114,12 @@ DO_3S_FP_GVEC(VMUL, gen_helper_gvec_fmul_s) + return do_3same_fp(s, a, FUNC, READS_VD); \ + } + ++DO_3S_FP(VCEQ, gen_helper_neon_ceq_f32, false) ++DO_3S_FP(VCGE, gen_helper_neon_cge_f32, false) ++DO_3S_FP(VCGT, gen_helper_neon_cgt_f32, false) ++DO_3S_FP(VACGE, gen_helper_neon_acge_f32, false) ++DO_3S_FP(VACGT, gen_helper_neon_acgt_f32, false) ++ + static void gen_VMLA_fp_3s(TCGv_i32 vd, TCGv_i32 vn, TCGv_i32 vm, + TCGv_ptr fpstatus) + { +diff --git a/target/arm/translate.c b/target/arm/translate.c +index 06b6925d31..b9fcbbcbcb 100644 +--- a/target/arm/translate.c ++++ b/target/arm/translate.c +@@ -5434,6 +5434,8 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn) + case NEON_3R_VQDMULH_VQRDMULH: + case NEON_3R_FLOAT_ARITH: + case NEON_3R_FLOAT_MULTIPLY: ++ case NEON_3R_FLOAT_CMP: ++ case NEON_3R_FLOAT_ACMP: + /* Already handled by decodetree */ + return 1; + } +@@ -5448,17 +5450,6 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn) + return 1; /* VPMIN/VPMAX handled by decodetree */ + } + break; +- case NEON_3R_FLOAT_CMP: +- if (!u && size) { +- /* no encoding for U=0 C=1x */ +- return 1; +- } +- break; +- case NEON_3R_FLOAT_ACMP: +- if (!u) { +- return 1; +- } +- break; + case NEON_3R_FLOAT_MISC: + /* VMAXNM/VMINNM in ARMv8 */ + if (u && !arm_dc_feature(s, ARM_FEATURE_V8)) { +@@ -5480,32 +5471,6 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn) + tmp = neon_load_reg(rn, pass); + tmp2 = neon_load_reg(rm, pass); + switch (op) { +- case NEON_3R_FLOAT_CMP: +- { +- TCGv_ptr fpstatus = get_fpstatus_ptr(1); +- if (!u) { +- gen_helper_neon_ceq_f32(tmp, tmp, tmp2, fpstatus); +- } else { +- if (size == 0) { +- gen_helper_neon_cge_f32(tmp, tmp, tmp2, fpstatus); +- } else { +- gen_helper_neon_cgt_f32(tmp, tmp, tmp2, fpstatus); +- } +- } +- tcg_temp_free_ptr(fpstatus); +- break; +- } +- case NEON_3R_FLOAT_ACMP: +- { +- TCGv_ptr fpstatus = get_fpstatus_ptr(1); +- if (size == 0) { +- gen_helper_neon_acge_f32(tmp, tmp, tmp2, fpstatus); +- } else { +- gen_helper_neon_acgt_f32(tmp, tmp, tmp2, fpstatus); +- } +- tcg_temp_free_ptr(fpstatus); +- break; +- } + case NEON_3R_FLOAT_MINMAX: + { + TCGv_ptr fpstatus = get_fpstatus_ptr(1); +-- +2.23.0 + diff --git a/target-arm-Convert-Neon-3-reg-same-comparisons-to-de.patch b/target-arm-Convert-Neon-3-reg-same-comparisons-to-de.patch new file mode 100644 index 0000000000000000000000000000000000000000..d3f19bd7099e824154c8ffdcabb6be8c41145722 --- /dev/null +++ b/target-arm-Convert-Neon-3-reg-same-comparisons-to-de.patch @@ -0,0 +1,115 @@ +From 02bd0cdb64b3e79419ba3a8746cb86430883b3ae Mon Sep 17 00:00:00 2001 +From: Peter Maydell +Date: Thu, 30 Apr 2020 19:09:44 +0100 +Subject: [PATCH 184/709] target/arm: Convert Neon 3-reg-same comparisons to + decodetree + +Convert the Neon comparison ops in the 3-reg-same grouping +to decodetree. + +Signed-off-by: Peter Maydell +Reviewed-by: Richard Henderson +Message-id: 20200430181003.21682-18-peter.maydell@linaro.org +--- + target/arm/neon-dp.decode | 8 ++++++++ + target/arm/translate-neon.inc.c | 22 ++++++++++++++++++++++ + target/arm/translate.c | 23 +++-------------------- + 3 files changed, 33 insertions(+), 20 deletions(-) + +diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode +index b721d39c7b..b89ea6819a 100644 +--- a/target/arm/neon-dp.decode ++++ b/target/arm/neon-dp.decode +@@ -54,6 +54,11 @@ VBSL_3s 1111 001 1 0 . 01 .... .... 0001 ... 1 .... @3same_logic + VBIT_3s 1111 001 1 0 . 10 .... .... 0001 ... 1 .... @3same_logic + VBIF_3s 1111 001 1 0 . 11 .... .... 0001 ... 1 .... @3same_logic + ++VCGT_S_3s 1111 001 0 0 . .. .... .... 0011 . . . 0 .... @3same ++VCGT_U_3s 1111 001 1 0 . .. .... .... 0011 . . . 0 .... @3same ++VCGE_S_3s 1111 001 0 0 . .. .... .... 0011 . . . 1 .... @3same ++VCGE_U_3s 1111 001 1 0 . .. .... .... 0011 . . . 1 .... @3same ++ + VMAX_S_3s 1111 001 0 0 . .. .... .... 0110 . . . 0 .... @3same + VMAX_U_3s 1111 001 1 0 . .. .... .... 0110 . . . 0 .... @3same + VMIN_S_3s 1111 001 0 0 . .. .... .... 0110 . . . 1 .... @3same +@@ -61,3 +66,6 @@ VMIN_U_3s 1111 001 1 0 . .. .... .... 0110 . . . 1 .... @3same + + VADD_3s 1111 001 0 0 . .. .... .... 1000 . . . 0 .... @3same + VSUB_3s 1111 001 1 0 . .. .... .... 1000 . . . 0 .... @3same ++ ++VTST_3s 1111 001 0 0 . .. .... .... 1000 . . . 1 .... @3same ++VCEQ_3s 1111 001 1 0 . .. .... .... 1000 . . . 1 .... @3same +diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c +index ab1740201c..952e4456f5 100644 +--- a/target/arm/translate-neon.inc.c ++++ b/target/arm/translate-neon.inc.c +@@ -631,3 +631,25 @@ DO_3SAME_NO_SZ_3(VMAX_S, tcg_gen_gvec_smax) + DO_3SAME_NO_SZ_3(VMAX_U, tcg_gen_gvec_umax) + DO_3SAME_NO_SZ_3(VMIN_S, tcg_gen_gvec_smin) + DO_3SAME_NO_SZ_3(VMIN_U, tcg_gen_gvec_umin) ++ ++#define DO_3SAME_CMP(INSN, COND) \ ++ static void gen_##INSN##_3s(unsigned vece, uint32_t rd_ofs, \ ++ uint32_t rn_ofs, uint32_t rm_ofs, \ ++ uint32_t oprsz, uint32_t maxsz) \ ++ { \ ++ tcg_gen_gvec_cmp(COND, vece, rd_ofs, rn_ofs, rm_ofs, oprsz, maxsz); \ ++ } \ ++ DO_3SAME_NO_SZ_3(INSN, gen_##INSN##_3s) ++ ++DO_3SAME_CMP(VCGT_S, TCG_COND_GT) ++DO_3SAME_CMP(VCGT_U, TCG_COND_GTU) ++DO_3SAME_CMP(VCGE_S, TCG_COND_GE) ++DO_3SAME_CMP(VCGE_U, TCG_COND_GEU) ++DO_3SAME_CMP(VCEQ, TCG_COND_EQ) ++ ++static void gen_VTST_3s(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs, ++ uint32_t rm_ofs, uint32_t oprsz, uint32_t maxsz) ++{ ++ tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, oprsz, maxsz, &cmtst_op[vece]); ++} ++DO_3SAME_NO_SZ_3(VTST, gen_VTST_3s) +diff --git a/target/arm/translate.c b/target/arm/translate.c +index 2f054cfa78..0e6ecc0969 100644 +--- a/target/arm/translate.c ++++ b/target/arm/translate.c +@@ -4879,26 +4879,6 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn) + u ? &mls_op[size] : &mla_op[size]); + return 0; + +- case NEON_3R_VTST_VCEQ: +- if (u) { /* VCEQ */ +- tcg_gen_gvec_cmp(TCG_COND_EQ, size, rd_ofs, rn_ofs, rm_ofs, +- vec_size, vec_size); +- } else { /* VTST */ +- tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, +- vec_size, vec_size, &cmtst_op[size]); +- } +- return 0; +- +- case NEON_3R_VCGT: +- tcg_gen_gvec_cmp(u ? TCG_COND_GTU : TCG_COND_GT, size, +- rd_ofs, rn_ofs, rm_ofs, vec_size, vec_size); +- return 0; +- +- case NEON_3R_VCGE: +- tcg_gen_gvec_cmp(u ? TCG_COND_GEU : TCG_COND_GE, size, +- rd_ofs, rn_ofs, rm_ofs, vec_size, vec_size); +- return 0; +- + case NEON_3R_VSHL: + /* Note the operation is vshl vd,vm,vn */ + tcg_gen_gvec_3(rd_ofs, rm_ofs, rn_ofs, vec_size, vec_size, +@@ -4909,6 +4889,9 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn) + case NEON_3R_LOGIC: + case NEON_3R_VMAX: + case NEON_3R_VMIN: ++ case NEON_3R_VTST_VCEQ: ++ case NEON_3R_VCGT: ++ case NEON_3R_VCGE: + /* Already handled by decodetree */ + return 1; + } +-- +2.23.0 + diff --git a/target-arm-Convert-Neon-3-reg-same-logic-ops-to-deco.patch b/target-arm-Convert-Neon-3-reg-same-logic-ops-to-deco.patch new file mode 100644 index 0000000000000000000000000000000000000000..bfa0ea6e8a4692d973d4e4670a70522b81cf5c6e --- /dev/null +++ b/target-arm-Convert-Neon-3-reg-same-logic-ops-to-deco.patch @@ -0,0 +1,127 @@ +From 35a548edb6f5043386183b9f6b4139d99d1f130a Mon Sep 17 00:00:00 2001 +From: Peter Maydell +Date: Thu, 30 Apr 2020 19:09:42 +0100 +Subject: [PATCH 182/709] target/arm: Convert Neon 3-reg-same logic ops to + decodetree + +Convert the Neon logic ops in the 3-reg-same grouping to decodetree. +Note that for the logic ops the 'size' field forms part of their +decode and the actual operations are always bitwise. + +Signed-off-by: Peter Maydell +Reviewed-by: Richard Henderson +Message-id: 20200430181003.21682-16-peter.maydell@linaro.org +--- + target/arm/neon-dp.decode | 12 +++++++++++ + target/arm/translate-neon.inc.c | 19 +++++++++++++++++ + target/arm/translate.c | 38 +-------------------------------- + 3 files changed, 32 insertions(+), 37 deletions(-) + +diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode +index a61b1e8847..f62dbaa72d 100644 +--- a/target/arm/neon-dp.decode ++++ b/target/arm/neon-dp.decode +@@ -42,5 +42,17 @@ + @3same .... ... . . . size:2 .... .... .... . q:1 . . .... \ + &3same vm=%vm_dp vn=%vn_dp vd=%vd_dp + ++@3same_logic .... ... . . . .. .... .... .... . q:1 .. .... \ ++ &3same vm=%vm_dp vn=%vn_dp vd=%vd_dp size=0 ++ ++VAND_3s 1111 001 0 0 . 00 .... .... 0001 ... 1 .... @3same_logic ++VBIC_3s 1111 001 0 0 . 01 .... .... 0001 ... 1 .... @3same_logic ++VORR_3s 1111 001 0 0 . 10 .... .... 0001 ... 1 .... @3same_logic ++VORN_3s 1111 001 0 0 . 11 .... .... 0001 ... 1 .... @3same_logic ++VEOR_3s 1111 001 1 0 . 00 .... .... 0001 ... 1 .... @3same_logic ++VBSL_3s 1111 001 1 0 . 01 .... .... 0001 ... 1 .... @3same_logic ++VBIT_3s 1111 001 1 0 . 10 .... .... 0001 ... 1 .... @3same_logic ++VBIF_3s 1111 001 1 0 . 11 .... .... 0001 ... 1 .... @3same_logic ++ + VADD_3s 1111 001 0 0 . .. .... .... 1000 . . . 0 .... @3same + VSUB_3s 1111 001 1 0 . .. .... .... 1000 . . . 0 .... @3same +diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c +index bd9e697b3e..507f0abe80 100644 +--- a/target/arm/translate-neon.inc.c ++++ b/target/arm/translate-neon.inc.c +@@ -598,3 +598,22 @@ static bool do_3same(DisasContext *s, arg_3same *a, GVecGen3Fn fn) + + DO_3SAME(VADD, tcg_gen_gvec_add) + DO_3SAME(VSUB, tcg_gen_gvec_sub) ++DO_3SAME(VAND, tcg_gen_gvec_and) ++DO_3SAME(VBIC, tcg_gen_gvec_andc) ++DO_3SAME(VORR, tcg_gen_gvec_or) ++DO_3SAME(VORN, tcg_gen_gvec_orc) ++DO_3SAME(VEOR, tcg_gen_gvec_xor) ++ ++/* These insns are all gvec_bitsel but with the inputs in various orders. */ ++#define DO_3SAME_BITSEL(INSN, O1, O2, O3) \ ++ static void gen_##INSN##_3s(unsigned vece, uint32_t rd_ofs, \ ++ uint32_t rn_ofs, uint32_t rm_ofs, \ ++ uint32_t oprsz, uint32_t maxsz) \ ++ { \ ++ tcg_gen_gvec_bitsel(vece, rd_ofs, O1, O2, O3, oprsz, maxsz); \ ++ } \ ++ DO_3SAME(INSN, gen_##INSN##_3s) ++ ++DO_3SAME_BITSEL(VBSL, rd_ofs, rn_ofs, rm_ofs) ++DO_3SAME_BITSEL(VBIT, rm_ofs, rn_ofs, rd_ofs) ++DO_3SAME_BITSEL(VBIF, rm_ofs, rd_ofs, rn_ofs) +diff --git a/target/arm/translate.c b/target/arm/translate.c +index 061bc7c31c..9affa92cbe 100644 +--- a/target/arm/translate.c ++++ b/target/arm/translate.c +@@ -4848,43 +4848,6 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn) + } + return 1; + +- case NEON_3R_LOGIC: /* Logic ops. */ +- switch ((u << 2) | size) { +- case 0: /* VAND */ +- tcg_gen_gvec_and(0, rd_ofs, rn_ofs, rm_ofs, +- vec_size, vec_size); +- break; +- case 1: /* VBIC */ +- tcg_gen_gvec_andc(0, rd_ofs, rn_ofs, rm_ofs, +- vec_size, vec_size); +- break; +- case 2: /* VORR */ +- tcg_gen_gvec_or(0, rd_ofs, rn_ofs, rm_ofs, +- vec_size, vec_size); +- break; +- case 3: /* VORN */ +- tcg_gen_gvec_orc(0, rd_ofs, rn_ofs, rm_ofs, +- vec_size, vec_size); +- break; +- case 4: /* VEOR */ +- tcg_gen_gvec_xor(0, rd_ofs, rn_ofs, rm_ofs, +- vec_size, vec_size); +- break; +- case 5: /* VBSL */ +- tcg_gen_gvec_bitsel(MO_8, rd_ofs, rd_ofs, rn_ofs, rm_ofs, +- vec_size, vec_size); +- break; +- case 6: /* VBIT */ +- tcg_gen_gvec_bitsel(MO_8, rd_ofs, rm_ofs, rn_ofs, rd_ofs, +- vec_size, vec_size); +- break; +- case 7: /* VBIF */ +- tcg_gen_gvec_bitsel(MO_8, rd_ofs, rm_ofs, rd_ofs, rn_ofs, +- vec_size, vec_size); +- break; +- } +- return 0; +- + case NEON_3R_VQADD: + tcg_gen_gvec_4(rd_ofs, offsetof(CPUARMState, vfp.qc), + rn_ofs, rm_ofs, vec_size, vec_size, +@@ -4962,6 +4925,7 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn) + return 0; + + case NEON_3R_VADD_VSUB: ++ case NEON_3R_LOGIC: + /* Already handled by decodetree */ + return 1; + } +-- +2.23.0 + diff --git a/target-arm-Convert-Neon-64-bit-element-3-reg-same-in.patch b/target-arm-Convert-Neon-64-bit-element-3-reg-same-in.patch new file mode 100644 index 0000000000000000000000000000000000000000..9c975463cccd1fd70840eb39d17cd3e3ec345cbb --- /dev/null +++ b/target-arm-Convert-Neon-64-bit-element-3-reg-same-in.patch @@ -0,0 +1,127 @@ +From 35d4352fa9e94b35bf17f58181cb16c184b98d56 Mon Sep 17 00:00:00 2001 +From: Peter Maydell +Date: Tue, 12 May 2020 17:38:50 +0100 +Subject: [PATCH 448/709] target/arm: Convert Neon 64-bit element 3-reg-same + insns + +Convert the 64-bit element insns in the 3-reg-same group +to decodetree. This covers VQSHL, VRSHL and VQRSHL where +size==0b11. + +Signed-off-by: Peter Maydell +Reviewed-by: Richard Henderson +Message-id: 20200512163904.10918-4-peter.maydell@linaro.org +--- + target/arm/neon-dp.decode | 13 +++++++++++ + target/arm/translate-neon.inc.c | 24 +++++++++++++++++++++ + target/arm/translate.c | 38 ++------------------------------- + 3 files changed, 39 insertions(+), 36 deletions(-) + +diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode +index 72eae12b26..fa52b998e8 100644 +--- a/target/arm/neon-dp.decode ++++ b/target/arm/neon-dp.decode +@@ -81,6 +81,19 @@ VCGE_U_3s 1111 001 1 0 . .. .... .... 0011 . . . 1 .... @3same + VSHL_S_3s 1111 001 0 0 . .. .... .... 0100 . . . 0 .... @3same_rev + VSHL_U_3s 1111 001 1 0 . .. .... .... 0100 . . . 0 .... @3same_rev + ++# Insns operating on 64-bit elements (size!=0b11 handled elsewhere) ++# The _rev suffix indicates that Vn and Vm are reversed (as explained ++# by the comment for the @3same_rev format). ++@3same_64_rev .... ... . . . 11 .... .... .... . q:1 . . .... \ ++ &3same vm=%vn_dp vn=%vm_dp vd=%vd_dp size=3 ++ ++VQSHL_S64_3s 1111 001 0 0 . .. .... .... 0100 . . . 1 .... @3same_64_rev ++VQSHL_U64_3s 1111 001 1 0 . .. .... .... 0100 . . . 1 .... @3same_64_rev ++VRSHL_S64_3s 1111 001 0 0 . .. .... .... 0101 . . . 0 .... @3same_64_rev ++VRSHL_U64_3s 1111 001 1 0 . .. .... .... 0101 . . . 0 .... @3same_64_rev ++VQRSHL_S64_3s 1111 001 0 0 . .. .... .... 0101 . . . 1 .... @3same_64_rev ++VQRSHL_U64_3s 1111 001 1 0 . .. .... .... 0101 . . . 1 .... @3same_64_rev ++ + VMAX_S_3s 1111 001 0 0 . .. .... .... 0110 . . . 0 .... @3same + VMAX_U_3s 1111 001 1 0 . .. .... .... 0110 . . . 0 .... @3same + VMIN_S_3s 1111 001 0 0 . .. .... .... 0110 . . . 1 .... @3same +diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c +index 03b3337e46..05c6dcdc9b 100644 +--- a/target/arm/translate-neon.inc.c ++++ b/target/arm/translate-neon.inc.c +@@ -825,3 +825,27 @@ static bool trans_SHA256SU1_3s(DisasContext *s, arg_SHA256SU1_3s *a) + + return true; + } ++ ++#define DO_3SAME_64(INSN, FUNC) \ ++ static void gen_##INSN##_3s(unsigned vece, uint32_t rd_ofs, \ ++ uint32_t rn_ofs, uint32_t rm_ofs, \ ++ uint32_t oprsz, uint32_t maxsz) \ ++ { \ ++ static const GVecGen3 op = { .fni8 = FUNC }; \ ++ tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, oprsz, maxsz, &op); \ ++ } \ ++ DO_3SAME(INSN, gen_##INSN##_3s) ++ ++#define DO_3SAME_64_ENV(INSN, FUNC) \ ++ static void gen_##INSN##_elt(TCGv_i64 d, TCGv_i64 n, TCGv_i64 m) \ ++ { \ ++ FUNC(d, cpu_env, n, m); \ ++ } \ ++ DO_3SAME_64(INSN, gen_##INSN##_elt) ++ ++DO_3SAME_64(VRSHL_S64, gen_helper_neon_rshl_s64) ++DO_3SAME_64(VRSHL_U64, gen_helper_neon_rshl_u64) ++DO_3SAME_64_ENV(VQSHL_S64, gen_helper_neon_qshl_s64) ++DO_3SAME_64_ENV(VQSHL_U64, gen_helper_neon_qshl_u64) ++DO_3SAME_64_ENV(VQRSHL_S64, gen_helper_neon_qrshl_s64) ++DO_3SAME_64_ENV(VQRSHL_U64, gen_helper_neon_qrshl_u64) +diff --git a/target/arm/translate.c b/target/arm/translate.c +index ee2b8d6f6e..1ce3e18286 100644 +--- a/target/arm/translate.c ++++ b/target/arm/translate.c +@@ -5459,42 +5459,8 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn) + } + + if (size == 3) { +- /* 64-bit element instructions. */ +- for (pass = 0; pass < (q ? 2 : 1); pass++) { +- neon_load_reg64(cpu_V0, rn + pass); +- neon_load_reg64(cpu_V1, rm + pass); +- switch (op) { +- case NEON_3R_VQSHL: +- if (u) { +- gen_helper_neon_qshl_u64(cpu_V0, cpu_env, +- cpu_V1, cpu_V0); +- } else { +- gen_helper_neon_qshl_s64(cpu_V0, cpu_env, +- cpu_V1, cpu_V0); +- } +- break; +- case NEON_3R_VRSHL: +- if (u) { +- gen_helper_neon_rshl_u64(cpu_V0, cpu_V1, cpu_V0); +- } else { +- gen_helper_neon_rshl_s64(cpu_V0, cpu_V1, cpu_V0); +- } +- break; +- case NEON_3R_VQRSHL: +- if (u) { +- gen_helper_neon_qrshl_u64(cpu_V0, cpu_env, +- cpu_V1, cpu_V0); +- } else { +- gen_helper_neon_qrshl_s64(cpu_V0, cpu_env, +- cpu_V1, cpu_V0); +- } +- break; +- default: +- abort(); +- } +- neon_store_reg64(cpu_V0, rd + pass); +- } +- return 0; ++ /* 64-bit element instructions: handled by decodetree */ ++ return 1; + } + pairwise = 0; + switch (op) { +-- +2.23.0 + diff --git a/target-arm-Convert-Neon-VABA-VABD-3-reg-same-to-deco.patch b/target-arm-Convert-Neon-VABA-VABD-3-reg-same-to-deco.patch new file mode 100644 index 0000000000000000000000000000000000000000..9f8bc2f6b463ba87bd49637d5d16abec84126b1e --- /dev/null +++ b/target-arm-Convert-Neon-VABA-VABD-3-reg-same-to-deco.patch @@ -0,0 +1,93 @@ +From 7715098f93ff5205334edf161e5fe156346122b0 Mon Sep 17 00:00:00 2001 +From: Peter Maydell +Date: Tue, 12 May 2020 17:38:52 +0100 +Subject: [PATCH 450/709] target/arm: Convert Neon VABA/VABD 3-reg-same to + decodetree + +Convert the Neon VABA and VABD insns in the 3-reg-same group to +decodetree. + +Signed-off-by: Peter Maydell +Reviewed-by: Richard Henderson +Message-id: 20200512163904.10918-6-peter.maydell@linaro.org +--- + target/arm/neon-dp.decode | 6 ++++++ + target/arm/translate-neon.inc.c | 4 ++++ + target/arm/translate.c | 22 ++-------------------- + 3 files changed, 12 insertions(+), 20 deletions(-) + +diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode +index 8120d8d5f2..00a909a888 100644 +--- a/target/arm/neon-dp.decode ++++ b/target/arm/neon-dp.decode +@@ -101,6 +101,12 @@ VMAX_U_3s 1111 001 1 0 . .. .... .... 0110 . . . 0 .... @3same + VMIN_S_3s 1111 001 0 0 . .. .... .... 0110 . . . 1 .... @3same + VMIN_U_3s 1111 001 1 0 . .. .... .... 0110 . . . 1 .... @3same + ++VABD_S_3s 1111 001 0 0 . .. .... .... 0111 . . . 0 .... @3same ++VABD_U_3s 1111 001 1 0 . .. .... .... 0111 . . . 0 .... @3same ++ ++VABA_S_3s 1111 001 0 0 . .. .... .... 0111 . . . 1 .... @3same ++VABA_U_3s 1111 001 1 0 . .. .... .... 0111 . . . 1 .... @3same ++ + VADD_3s 1111 001 0 0 . .. .... .... 1000 . . . 0 .... @3same + VSUB_3s 1111 001 1 0 . .. .... .... 1000 . . . 0 .... @3same + +diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c +index 0418a84a7d..20f0f2c8d8 100644 +--- a/target/arm/translate-neon.inc.c ++++ b/target/arm/translate-neon.inc.c +@@ -641,6 +641,10 @@ DO_3SAME_NO_SZ_3(VMUL, tcg_gen_gvec_mul) + DO_3SAME_NO_SZ_3(VMLA, gen_gvec_mla) + DO_3SAME_NO_SZ_3(VMLS, gen_gvec_mls) + DO_3SAME_NO_SZ_3(VTST, gen_gvec_cmtst) ++DO_3SAME_NO_SZ_3(VABD_S, gen_gvec_sabd) ++DO_3SAME_NO_SZ_3(VABA_S, gen_gvec_saba) ++DO_3SAME_NO_SZ_3(VABD_U, gen_gvec_uabd) ++DO_3SAME_NO_SZ_3(VABA_U, gen_gvec_uaba) + + #define DO_3SAME_CMP(INSN, COND) \ + static void gen_##INSN##_3s(unsigned vece, uint32_t rd_ofs, \ +diff --git a/target/arm/translate.c b/target/arm/translate.c +index 8d856ccfe9..2c842df445 100644 +--- a/target/arm/translate.c ++++ b/target/arm/translate.c +@@ -5421,26 +5421,6 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn) + /* VQRDMLSH : handled by decodetree */ + return 1; + +- case NEON_3R_VABD: +- if (u) { +- gen_gvec_uabd(size, rd_ofs, rn_ofs, rm_ofs, +- vec_size, vec_size); +- } else { +- gen_gvec_sabd(size, rd_ofs, rn_ofs, rm_ofs, +- vec_size, vec_size); +- } +- return 0; +- +- case NEON_3R_VABA: +- if (u) { +- gen_gvec_uaba(size, rd_ofs, rn_ofs, rm_ofs, +- vec_size, vec_size); +- } else { +- gen_gvec_saba(size, rd_ofs, rn_ofs, rm_ofs, +- vec_size, vec_size); +- } +- return 0; +- + case NEON_3R_VADD_VSUB: + case NEON_3R_LOGIC: + case NEON_3R_VMAX: +@@ -5455,6 +5435,8 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn) + case NEON_3R_VSHL: + case NEON_3R_SHA: + case NEON_3R_VHADD: ++ case NEON_3R_VABD: ++ case NEON_3R_VABA: + /* Already handled by decodetree */ + return 1; + } +-- +2.23.0 + diff --git a/target-arm-Convert-Neon-VADD-VSUB-VABD-3-reg-same-in.patch b/target-arm-Convert-Neon-VADD-VSUB-VABD-3-reg-same-in.patch new file mode 100644 index 0000000000000000000000000000000000000000..6bdf8b4234e47835200cb98bf94615ebf18f63c1 --- /dev/null +++ b/target-arm-Convert-Neon-VADD-VSUB-VABD-3-reg-same-in.patch @@ -0,0 +1,179 @@ +From a26a352bb498662cd0c205cb433a352f86fac7d2 Mon Sep 17 00:00:00 2001 +From: Peter Maydell +Date: Tue, 12 May 2020 17:38:58 +0100 +Subject: [PATCH 456/709] target/arm: Convert Neon VADD, VSUB, VABD 3-reg-same + insns to decodetree + +Convert the Neon VADD, VSUB, VABD 3-reg-same insns to decodetree. +We already have gvec helpers for addition and subtraction, but must +add one for fabd. + +Signed-off-by: Peter Maydell +Reviewed-by: Richard Henderson +Message-id: 20200512163904.10918-12-peter.maydell@linaro.org +--- + target/arm/helper.h | 3 ++- + target/arm/neon-dp.decode | 8 ++++++++ + target/arm/neon_helper.c | 7 ------- + target/arm/translate-neon.inc.c | 28 ++++++++++++++++++++++++++++ + target/arm/translate.c | 10 +++------- + target/arm/vec_helper.c | 7 +++++++ + 6 files changed, 48 insertions(+), 15 deletions(-) + +diff --git a/target/arm/helper.h b/target/arm/helper.h +index 1857f4ee46..6e9629c87b 100644 +--- a/target/arm/helper.h ++++ b/target/arm/helper.h +@@ -396,7 +396,6 @@ DEF_HELPER_FLAGS_2(neon_qneg_s16, TCG_CALL_NO_RWG, i32, env, i32) + DEF_HELPER_FLAGS_2(neon_qneg_s32, TCG_CALL_NO_RWG, i32, env, i32) + DEF_HELPER_FLAGS_2(neon_qneg_s64, TCG_CALL_NO_RWG, i64, env, i64) + +-DEF_HELPER_3(neon_abd_f32, i32, i32, i32, ptr) + DEF_HELPER_3(neon_ceq_f32, i32, i32, i32, ptr) + DEF_HELPER_3(neon_cge_f32, i32, i32, i32, ptr) + DEF_HELPER_3(neon_cgt_f32, i32, i32, i32, ptr) +@@ -595,6 +594,8 @@ DEF_HELPER_FLAGS_5(gvec_fmul_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32) + DEF_HELPER_FLAGS_5(gvec_fmul_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32) + DEF_HELPER_FLAGS_5(gvec_fmul_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32) + ++DEF_HELPER_FLAGS_5(gvec_fabd_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32) ++ + DEF_HELPER_FLAGS_5(gvec_ftsmul_h, TCG_CALL_NO_RWG, + void, ptr, ptr, ptr, ptr, i32) + DEF_HELPER_FLAGS_5(gvec_ftsmul_s, TCG_CALL_NO_RWG, +diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode +index fd32837fb1..0dd02f3b72 100644 +--- a/target/arm/neon-dp.decode ++++ b/target/arm/neon-dp.decode +@@ -45,6 +45,10 @@ + @3same_q0 .... ... . . . size:2 .... .... .... . 0 . . .... \ + &3same vm=%vm_dp vn=%vn_dp vd=%vd_dp q=0 + ++# For FP insns the high bit of 'size' is used as part of opcode decode ++@3same_fp .... ... . . . . size:1 .... .... .... . q:1 . . .... \ ++ &3same vm=%vm_dp vn=%vn_dp vd=%vd_dp ++ + VHADD_S_3s 1111 001 0 0 . .. .... .... 0000 . . . 0 .... @3same + VHADD_U_3s 1111 001 1 0 . .. .... .... 0000 . . . 0 .... @3same + VQADD_S_3s 1111 001 0 0 . .. .... .... 0000 . . . 1 .... @3same +@@ -169,3 +173,7 @@ SHA256SU1_3s 1111 001 1 0 . 10 .... .... 1100 . 1 . 0 .... \ + vm=%vm_dp vn=%vn_dp vd=%vd_dp + + VQRDMLSH_3s 1111 001 1 0 . .. .... .... 1100 ... 1 .... @3same ++ ++VADD_fp_3s 1111 001 0 0 . 0 . .... .... 1101 ... 0 .... @3same_fp ++VSUB_fp_3s 1111 001 0 0 . 1 . .... .... 1101 ... 0 .... @3same_fp ++VABD_fp_3s 1111 001 1 0 . 1 . .... .... 1101 ... 0 .... @3same_fp +diff --git a/target/arm/neon_helper.c b/target/arm/neon_helper.c +index 2ef75e04c8..b637265691 100644 +--- a/target/arm/neon_helper.c ++++ b/target/arm/neon_helper.c +@@ -1825,13 +1825,6 @@ uint64_t HELPER(neon_qneg_s64)(CPUARMState *env, uint64_t x) + } + + /* NEON Float helpers. */ +-uint32_t HELPER(neon_abd_f32)(uint32_t a, uint32_t b, void *fpstp) +-{ +- float_status *fpst = fpstp; +- float32 f0 = make_float32(a); +- float32 f1 = make_float32(b); +- return float32_val(float32_abs(float32_sub(f0, f1, fpst))); +-} + + /* Floating point comparisons produce an integer result. + * Note that EQ doesn't signal InvalidOp for QNaNs but GE and GT do. +diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c +index f52302f42b..540720f5e0 100644 +--- a/target/arm/translate-neon.inc.c ++++ b/target/arm/translate-neon.inc.c +@@ -1021,3 +1021,31 @@ DO_3SAME_PAIR(VPADD, padd_u) + + DO_3SAME_VQDMULH(VQDMULH, qdmulh) + DO_3SAME_VQDMULH(VQRDMULH, qrdmulh) ++ ++/* ++ * For all the functions using this macro, size == 1 means fp16, ++ * which is an architecture extension we don't implement yet. ++ */ ++#define DO_3S_FP_GVEC(INSN,FUNC) \ ++ static void gen_##INSN##_3s(unsigned vece, uint32_t rd_ofs, \ ++ uint32_t rn_ofs, uint32_t rm_ofs, \ ++ uint32_t oprsz, uint32_t maxsz) \ ++ { \ ++ TCGv_ptr fpst = get_fpstatus_ptr(1); \ ++ tcg_gen_gvec_3_ptr(rd_ofs, rn_ofs, rm_ofs, fpst, \ ++ oprsz, maxsz, 0, FUNC); \ ++ tcg_temp_free_ptr(fpst); \ ++ } \ ++ static bool trans_##INSN##_fp_3s(DisasContext *s, arg_3same *a) \ ++ { \ ++ if (a->size != 0) { \ ++ /* TODO fp16 support */ \ ++ return false; \ ++ } \ ++ return do_3same(s, a, gen_##INSN##_3s); \ ++ } ++ ++ ++DO_3S_FP_GVEC(VADD, gen_helper_gvec_fadd_s) ++DO_3S_FP_GVEC(VSUB, gen_helper_gvec_fsub_s) ++DO_3S_FP_GVEC(VABD, gen_helper_gvec_fabd_s) +diff --git a/target/arm/translate.c b/target/arm/translate.c +index 561cb67286..8a94856cd2 100644 +--- a/target/arm/translate.c ++++ b/target/arm/translate.c +@@ -5445,6 +5445,9 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn) + switch (op) { + case NEON_3R_FLOAT_ARITH: + pairwise = (u && size < 2); /* if VPADD (float) */ ++ if (!pairwise) { ++ return 1; /* handled by decodetree */ ++ } + break; + case NEON_3R_FLOAT_MINMAX: + pairwise = u; /* if VPMIN/VPMAX (float) */ +@@ -5501,16 +5504,9 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn) + { + TCGv_ptr fpstatus = get_fpstatus_ptr(1); + switch ((u << 2) | size) { +- case 0: /* VADD */ + case 4: /* VPADD */ + gen_helper_vfp_adds(tmp, tmp, tmp2, fpstatus); + break; +- case 2: /* VSUB */ +- gen_helper_vfp_subs(tmp, tmp, tmp2, fpstatus); +- break; +- case 6: /* VABD */ +- gen_helper_neon_abd_f32(tmp, tmp, tmp2, fpstatus); +- break; + default: + abort(); + } +diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c +index fa33df859e..50a499299f 100644 +--- a/target/arm/vec_helper.c ++++ b/target/arm/vec_helper.c +@@ -691,6 +691,11 @@ static float64 float64_ftsmul(float64 op1, uint64_t op2, float_status *stat) + return result; + } + ++static float32 float32_abd(float32 op1, float32 op2, float_status *stat) ++{ ++ return float32_abs(float32_sub(op1, op2, stat)); ++} ++ + #define DO_3OP(NAME, FUNC, TYPE) \ + void HELPER(NAME)(void *vd, void *vn, void *vm, void *stat, uint32_t desc) \ + { \ +@@ -718,6 +723,8 @@ DO_3OP(gvec_ftsmul_h, float16_ftsmul, float16) + DO_3OP(gvec_ftsmul_s, float32_ftsmul, float32) + DO_3OP(gvec_ftsmul_d, float64_ftsmul, float64) + ++DO_3OP(gvec_fabd_s, float32_abd, float32) ++ + #ifdef TARGET_AARCH64 + + DO_3OP(gvec_recps_h, helper_recpsf_f16, float16) +-- +2.23.0 + diff --git a/target-arm-Convert-Neon-VHADD-3-reg-same-insns.patch b/target-arm-Convert-Neon-VHADD-3-reg-same-insns.patch new file mode 100644 index 0000000000000000000000000000000000000000..4a70f46cc4eb7857078e69dbd6860cb42d617833 --- /dev/null +++ b/target-arm-Convert-Neon-VHADD-3-reg-same-insns.patch @@ -0,0 +1,86 @@ +From cb294bca866f1cd776e44e03e5e432942bc676e8 Mon Sep 17 00:00:00 2001 +From: Peter Maydell +Date: Tue, 12 May 2020 17:38:51 +0100 +Subject: [PATCH 449/709] target/arm: Convert Neon VHADD 3-reg-same insns + +Convert the Neon VHADD insns in the 3-reg-same group to decodetree. + +Signed-off-by: Peter Maydell +Reviewed-by: Richard Henderson +Message-id: 20200512163904.10918-5-peter.maydell@linaro.org +--- + target/arm/neon-dp.decode | 2 ++ + target/arm/translate-neon.inc.c | 24 ++++++++++++++++++++++++ + target/arm/translate.c | 4 +--- + 3 files changed, 27 insertions(+), 3 deletions(-) + +diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode +index fa52b998e8..8120d8d5f2 100644 +--- a/target/arm/neon-dp.decode ++++ b/target/arm/neon-dp.decode +@@ -42,6 +42,8 @@ + @3same .... ... . . . size:2 .... .... .... . q:1 . . .... \ + &3same vm=%vm_dp vn=%vn_dp vd=%vd_dp + ++VHADD_S_3s 1111 001 0 0 . .. .... .... 0000 . . . 0 .... @3same ++VHADD_U_3s 1111 001 1 0 . .. .... .... 0000 . . . 0 .... @3same + VQADD_S_3s 1111 001 0 0 . .. .... .... 0000 . . . 1 .... @3same + VQADD_U_3s 1111 001 1 0 . .. .... .... 0000 . . . 1 .... @3same + +diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c +index 05c6dcdc9b..0418a84a7d 100644 +--- a/target/arm/translate-neon.inc.c ++++ b/target/arm/translate-neon.inc.c +@@ -849,3 +849,27 @@ DO_3SAME_64_ENV(VQSHL_S64, gen_helper_neon_qshl_s64) + DO_3SAME_64_ENV(VQSHL_U64, gen_helper_neon_qshl_u64) + DO_3SAME_64_ENV(VQRSHL_S64, gen_helper_neon_qrshl_s64) + DO_3SAME_64_ENV(VQRSHL_U64, gen_helper_neon_qrshl_u64) ++ ++#define DO_3SAME_32(INSN, FUNC) \ ++ static void gen_##INSN##_3s(unsigned vece, uint32_t rd_ofs, \ ++ uint32_t rn_ofs, uint32_t rm_ofs, \ ++ uint32_t oprsz, uint32_t maxsz) \ ++ { \ ++ static const GVecGen3 ops[4] = { \ ++ { .fni4 = gen_helper_neon_##FUNC##8 }, \ ++ { .fni4 = gen_helper_neon_##FUNC##16 }, \ ++ { .fni4 = gen_helper_neon_##FUNC##32 }, \ ++ { 0 }, \ ++ }; \ ++ tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, oprsz, maxsz, &ops[vece]); \ ++ } \ ++ static bool trans_##INSN##_3s(DisasContext *s, arg_3same *a) \ ++ { \ ++ if (a->size > 2) { \ ++ return false; \ ++ } \ ++ return do_3same(s, a, gen_##INSN##_3s); \ ++ } ++ ++DO_3SAME_32(VHADD_S, hadd_s) ++DO_3SAME_32(VHADD_U, hadd_u) +diff --git a/target/arm/translate.c b/target/arm/translate.c +index 1ce3e18286..8d856ccfe9 100644 +--- a/target/arm/translate.c ++++ b/target/arm/translate.c +@@ -5454,6 +5454,7 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn) + case NEON_3R_VML: + case NEON_3R_VSHL: + case NEON_3R_SHA: ++ case NEON_3R_VHADD: + /* Already handled by decodetree */ + return 1; + } +@@ -5534,9 +5535,6 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn) + tmp2 = neon_load_reg(rm, pass); + } + switch (op) { +- case NEON_3R_VHADD: +- GEN_NEON_INTEGER_OP(hadd); +- break; + case NEON_3R_VRHADD: + GEN_NEON_INTEGER_OP(rhadd); + break; +-- +2.23.0 + diff --git a/target-arm-Convert-Neon-VPADD-3-reg-same-insns-to-de.patch b/target-arm-Convert-Neon-VPADD-3-reg-same-insns-to-de.patch new file mode 100644 index 0000000000000000000000000000000000000000..ae93bd4b388e569d8cbfedbbd148cfc4a1309d41 --- /dev/null +++ b/target-arm-Convert-Neon-VPADD-3-reg-same-insns-to-de.patch @@ -0,0 +1,101 @@ +From fa22827d4eb078b6c58cd3d19af0b50ed951e832 Mon Sep 17 00:00:00 2001 +From: Peter Maydell +Date: Tue, 12 May 2020 17:38:56 +0100 +Subject: [PATCH 454/709] target/arm: Convert Neon VPADD 3-reg-same insns to + decodetree + +Convert the Neon integer VPADD 3-reg-same insns to decodetree. These +are 'pairwise' operations. (Note that VQRDMLAH, which shares the +same primary opcode but has U=1, has already been converted.) + +Signed-off-by: Peter Maydell +Reviewed-by: Richard Henderson +Message-id: 20200512163904.10918-10-peter.maydell@linaro.org +--- + target/arm/neon-dp.decode | 2 ++ + target/arm/translate-neon.inc.c | 2 ++ + target/arm/translate.c | 19 +------------------ + 3 files changed, 5 insertions(+), 18 deletions(-) + +diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode +index 2edcaba9f8..3659fb036c 100644 +--- a/target/arm/neon-dp.decode ++++ b/target/arm/neon-dp.decode +@@ -152,6 +152,8 @@ VPMAX_U_3s 1111 001 1 0 . .. .... .... 1010 . . . 0 .... @3same_q0 + VPMIN_S_3s 1111 001 0 0 . .. .... .... 1010 . . . 1 .... @3same_q0 + VPMIN_U_3s 1111 001 1 0 . .. .... .... 1010 . . . 1 .... @3same_q0 + ++VPADD_3s 1111 001 0 0 . .. .... .... 1011 . . . 1 .... @3same_q0 ++ + VQRDMLAH_3s 1111 001 1 0 . .. .... .... 1011 ... 1 .... @3same + + SHA1_3s 1111 001 0 0 . optype:2 .... .... 1100 . 1 . 0 .... \ +diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c +index 7db6b85659..e013736407 100644 +--- a/target/arm/translate-neon.inc.c ++++ b/target/arm/translate-neon.inc.c +@@ -990,8 +990,10 @@ static bool do_3same_pair(DisasContext *s, arg_3same *a, NeonGenTwoOpFn *fn) + #define gen_helper_neon_pmax_u32 tcg_gen_umax_i32 + #define gen_helper_neon_pmin_s32 tcg_gen_smin_i32 + #define gen_helper_neon_pmin_u32 tcg_gen_umin_i32 ++#define gen_helper_neon_padd_u32 tcg_gen_add_i32 + + DO_3SAME_PAIR(VPMAX_S, pmax_s) + DO_3SAME_PAIR(VPMIN_S, pmin_s) + DO_3SAME_PAIR(VPMAX_U, pmax_u) + DO_3SAME_PAIR(VPMIN_U, pmin_u) ++DO_3SAME_PAIR(VPADD, padd_u) +diff --git a/target/arm/translate.c b/target/arm/translate.c +index 82be4d4028..ce30417014 100644 +--- a/target/arm/translate.c ++++ b/target/arm/translate.c +@@ -5397,13 +5397,6 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn) + return 1; + } + switch (op) { +- case NEON_3R_VPADD_VQRDMLAH: +- if (!u) { +- break; /* VPADD */ +- } +- /* VQRDMLAH : handled by decodetree */ +- return 1; +- + case NEON_3R_VFM_VQRDMLSH: + if (!u) { + /* VFM, VFMS */ +@@ -5438,6 +5431,7 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn) + case NEON_3R_VQRSHL: + case NEON_3R_VPMAX: + case NEON_3R_VPMIN: ++ case NEON_3R_VPADD_VQRDMLAH: + /* Already handled by decodetree */ + return 1; + } +@@ -5448,9 +5442,6 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn) + } + pairwise = 0; + switch (op) { +- case NEON_3R_VPADD_VQRDMLAH: +- pairwise = 1; +- break; + case NEON_3R_FLOAT_ARITH: + pairwise = (u && size < 2); /* if VPADD (float) */ + break; +@@ -5528,14 +5519,6 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn) + } + } + break; +- case NEON_3R_VPADD_VQRDMLAH: +- switch (size) { +- case 0: gen_helper_neon_padd_u8(tmp, tmp, tmp2); break; +- case 1: gen_helper_neon_padd_u16(tmp, tmp, tmp2); break; +- case 2: tcg_gen_add_i32(tmp, tmp, tmp2); break; +- default: abort(); +- } +- break; + case NEON_3R_FLOAT_ARITH: /* Floating point arithmetic. */ + { + TCGv_ptr fpstatus = get_fpstatus_ptr(1); +-- +2.23.0 + diff --git a/target-arm-Convert-Neon-VPMAX-VPMIN-3-reg-same-insns.patch b/target-arm-Convert-Neon-VPMAX-VPMIN-3-reg-same-insns.patch new file mode 100644 index 0000000000000000000000000000000000000000..d62c95e9b66d865fa66dfffa68161fe8e023c22f --- /dev/null +++ b/target-arm-Convert-Neon-VPMAX-VPMIN-3-reg-same-insns.patch @@ -0,0 +1,176 @@ +From 059c2398a2b1ae86c6722c45e79fb0d0f4d95b1d Mon Sep 17 00:00:00 2001 +From: Peter Maydell +Date: Tue, 12 May 2020 17:38:55 +0100 +Subject: [PATCH 453/709] target/arm: Convert Neon VPMAX/VPMIN 3-reg-same insns + to decodetree + +Convert the Neon integer VPMAX and VPMIN 3-reg-same insns to +decodetree. These are 'pairwise' operations. + +Signed-off-by: Peter Maydell +Reviewed-by: Richard Henderson +Message-id: 20200512163904.10918-9-peter.maydell@linaro.org +--- + target/arm/neon-dp.decode | 9 +++++ + target/arm/translate-neon.inc.c | 71 +++++++++++++++++++++++++++++++++ + target/arm/translate.c | 17 +------- + 3 files changed, 82 insertions(+), 15 deletions(-) + +diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode +index 34bce81c43..2edcaba9f8 100644 +--- a/target/arm/neon-dp.decode ++++ b/target/arm/neon-dp.decode +@@ -42,6 +42,9 @@ + @3same .... ... . . . size:2 .... .... .... . q:1 . . .... \ + &3same vm=%vm_dp vn=%vn_dp vd=%vd_dp + ++@3same_q0 .... ... . . . size:2 .... .... .... . 0 . . .... \ ++ &3same vm=%vm_dp vn=%vn_dp vd=%vd_dp q=0 ++ + VHADD_S_3s 1111 001 0 0 . .. .... .... 0000 . . . 0 .... @3same + VHADD_U_3s 1111 001 1 0 . .. .... .... 0000 . . . 0 .... @3same + VQADD_S_3s 1111 001 0 0 . .. .... .... 0000 . . . 1 .... @3same +@@ -143,6 +146,12 @@ VMLS_3s 1111 001 1 0 . .. .... .... 1001 . . . 0 .... @3same + VMUL_3s 1111 001 0 0 . .. .... .... 1001 . . . 1 .... @3same + VMUL_p_3s 1111 001 1 0 . .. .... .... 1001 . . . 1 .... @3same + ++VPMAX_S_3s 1111 001 0 0 . .. .... .... 1010 . . . 0 .... @3same_q0 ++VPMAX_U_3s 1111 001 1 0 . .. .... .... 1010 . . . 0 .... @3same_q0 ++ ++VPMIN_S_3s 1111 001 0 0 . .. .... .... 1010 . . . 1 .... @3same_q0 ++VPMIN_U_3s 1111 001 1 0 . .. .... .... 1010 . . . 1 .... @3same_q0 ++ + VQRDMLAH_3s 1111 001 1 0 . .. .... .... 1011 ... 1 .... @3same + + SHA1_3s 1111 001 0 0 . optype:2 .... .... 1100 . 1 . 0 .... \ +diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c +index 7097c18f33..7db6b85659 100644 +--- a/target/arm/translate-neon.inc.c ++++ b/target/arm/translate-neon.inc.c +@@ -924,3 +924,74 @@ DO_3SAME_32_ENV(VQSHL_S, qshl_s) + DO_3SAME_32_ENV(VQSHL_U, qshl_u) + DO_3SAME_32_ENV(VQRSHL_S, qrshl_s) + DO_3SAME_32_ENV(VQRSHL_U, qrshl_u) ++ ++static bool do_3same_pair(DisasContext *s, arg_3same *a, NeonGenTwoOpFn *fn) ++{ ++ /* Operations handled pairwise 32 bits at a time */ ++ TCGv_i32 tmp, tmp2, tmp3; ++ ++ if (!arm_dc_feature(s, ARM_FEATURE_NEON)) { ++ return false; ++ } ++ ++ /* UNDEF accesses to D16-D31 if they don't exist. */ ++ if (!dc_isar_feature(aa32_simd_r32, s) && ++ ((a->vd | a->vn | a->vm) & 0x10)) { ++ return false; ++ } ++ ++ if (a->size == 3) { ++ return false; ++ } ++ ++ if (!vfp_access_check(s)) { ++ return true; ++ } ++ ++ assert(a->q == 0); /* enforced by decode patterns */ ++ ++ /* ++ * Note that we have to be careful not to clobber the source operands ++ * in the "vm == vd" case by storing the result of the first pass too ++ * early. Since Q is 0 there are always just two passes, so instead ++ * of a complicated loop over each pass we just unroll. ++ */ ++ tmp = neon_load_reg(a->vn, 0); ++ tmp2 = neon_load_reg(a->vn, 1); ++ fn(tmp, tmp, tmp2); ++ tcg_temp_free_i32(tmp2); ++ ++ tmp3 = neon_load_reg(a->vm, 0); ++ tmp2 = neon_load_reg(a->vm, 1); ++ fn(tmp3, tmp3, tmp2); ++ tcg_temp_free_i32(tmp2); ++ ++ neon_store_reg(a->vd, 0, tmp); ++ neon_store_reg(a->vd, 1, tmp3); ++ return true; ++} ++ ++#define DO_3SAME_PAIR(INSN, func) \ ++ static bool trans_##INSN##_3s(DisasContext *s, arg_3same *a) \ ++ { \ ++ static NeonGenTwoOpFn * const fns[] = { \ ++ gen_helper_neon_##func##8, \ ++ gen_helper_neon_##func##16, \ ++ gen_helper_neon_##func##32, \ ++ }; \ ++ if (a->size > 2) { \ ++ return false; \ ++ } \ ++ return do_3same_pair(s, a, fns[a->size]); \ ++ } ++ ++/* 32-bit pairwise ops end up the same as the elementwise versions. */ ++#define gen_helper_neon_pmax_s32 tcg_gen_smax_i32 ++#define gen_helper_neon_pmax_u32 tcg_gen_umax_i32 ++#define gen_helper_neon_pmin_s32 tcg_gen_smin_i32 ++#define gen_helper_neon_pmin_u32 tcg_gen_umin_i32 ++ ++DO_3SAME_PAIR(VPMAX_S, pmax_s) ++DO_3SAME_PAIR(VPMIN_S, pmin_s) ++DO_3SAME_PAIR(VPMAX_U, pmax_u) ++DO_3SAME_PAIR(VPMIN_U, pmin_u) +diff --git a/target/arm/translate.c b/target/arm/translate.c +index 3aabb18720..82be4d4028 100644 +--- a/target/arm/translate.c ++++ b/target/arm/translate.c +@@ -3011,12 +3011,6 @@ static inline void gen_neon_rsb(int size, TCGv_i32 t0, TCGv_i32 t1) + } + } + +-/* 32-bit pairwise ops end up the same as the elementwise versions. */ +-#define gen_helper_neon_pmax_s32 tcg_gen_smax_i32 +-#define gen_helper_neon_pmax_u32 tcg_gen_umax_i32 +-#define gen_helper_neon_pmin_s32 tcg_gen_smin_i32 +-#define gen_helper_neon_pmin_u32 tcg_gen_umin_i32 +- + #define GEN_NEON_INTEGER_OP_ENV(name) do { \ + switch ((size << 1) | u) { \ + case 0: \ +@@ -5442,6 +5436,8 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn) + case NEON_3R_VQSHL: + case NEON_3R_VRSHL: + case NEON_3R_VQRSHL: ++ case NEON_3R_VPMAX: ++ case NEON_3R_VPMIN: + /* Already handled by decodetree */ + return 1; + } +@@ -5453,8 +5449,6 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn) + pairwise = 0; + switch (op) { + case NEON_3R_VPADD_VQRDMLAH: +- case NEON_3R_VPMAX: +- case NEON_3R_VPMIN: + pairwise = 1; + break; + case NEON_3R_FLOAT_ARITH: +@@ -5511,13 +5505,6 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn) + tmp2 = neon_load_reg(rm, pass); + } + switch (op) { +- break; +- case NEON_3R_VPMAX: +- GEN_NEON_INTEGER_OP(pmax); +- break; +- case NEON_3R_VPMIN: +- GEN_NEON_INTEGER_OP(pmin); +- break; + case NEON_3R_VQDMULH_VQRDMULH: /* Multiply high. */ + if (!u) { /* VQDMULH */ + switch (size) { +-- +2.23.0 + diff --git a/target-arm-Convert-Neon-VPMIN-VPMAX-VPADD-float-3-re.patch b/target-arm-Convert-Neon-VPMIN-VPMAX-VPADD-float-3-re.patch new file mode 100644 index 0000000000000000000000000000000000000000..773bda0062cf65998c124c20d370e0e46b5f46f3 --- /dev/null +++ b/target-arm-Convert-Neon-VPMIN-VPMAX-VPADD-float-3-re.patch @@ -0,0 +1,224 @@ +From ab978335a56e3618212868fdce3a54217c6e71e6 Mon Sep 17 00:00:00 2001 +From: Peter Maydell +Date: Tue, 12 May 2020 17:38:59 +0100 +Subject: [PATCH 457/709] target/arm: Convert Neon VPMIN/VPMAX/VPADD float + 3-reg-same insns to decodetree + +Convert the Neon float VPMIN, VPMAX and VPADD 3-reg-same insns to +decodetree. These are the only remaining 'pairwise' operations, +so we can delete the pairwise-specific bits of the old decoder's +for-each-element loop now. + +Signed-off-by: Peter Maydell +Reviewed-by: Richard Henderson +Message-id: 20200512163904.10918-13-peter.maydell@linaro.org +--- + target/arm/neon-dp.decode | 5 +++ + target/arm/translate-neon.inc.c | 63 +++++++++++++++++++++++++++++++++ + target/arm/translate.c | 63 +++++---------------------------- + 3 files changed, 76 insertions(+), 55 deletions(-) + +diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode +index 0dd02f3b72..d66c67ca58 100644 +--- a/target/arm/neon-dp.decode ++++ b/target/arm/neon-dp.decode +@@ -48,6 +48,8 @@ + # For FP insns the high bit of 'size' is used as part of opcode decode + @3same_fp .... ... . . . . size:1 .... .... .... . q:1 . . .... \ + &3same vm=%vm_dp vn=%vn_dp vd=%vd_dp ++@3same_fp_q0 .... ... . . . . size:1 .... .... .... . 0 . . .... \ ++ &3same vm=%vm_dp vn=%vn_dp vd=%vd_dp q=0 + + VHADD_S_3s 1111 001 0 0 . .. .... .... 0000 . . . 0 .... @3same + VHADD_U_3s 1111 001 1 0 . .. .... .... 0000 . . . 0 .... @3same +@@ -176,4 +178,7 @@ VQRDMLSH_3s 1111 001 1 0 . .. .... .... 1100 ... 1 .... @3same + + VADD_fp_3s 1111 001 0 0 . 0 . .... .... 1101 ... 0 .... @3same_fp + VSUB_fp_3s 1111 001 0 0 . 1 . .... .... 1101 ... 0 .... @3same_fp ++VPADD_fp_3s 1111 001 1 0 . 0 . .... .... 1101 ... 0 .... @3same_fp_q0 + VABD_fp_3s 1111 001 1 0 . 1 . .... .... 1101 ... 0 .... @3same_fp ++VPMAX_fp_3s 1111 001 1 0 . 0 . .... .... 1111 ... 0 .... @3same_fp_q0 ++VPMIN_fp_3s 1111 001 1 0 . 1 . .... .... 1111 ... 0 .... @3same_fp_q0 +diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c +index 540720f5e0..7bdf1e3fee 100644 +--- a/target/arm/translate-neon.inc.c ++++ b/target/arm/translate-neon.inc.c +@@ -1049,3 +1049,66 @@ DO_3SAME_VQDMULH(VQRDMULH, qrdmulh) + DO_3S_FP_GVEC(VADD, gen_helper_gvec_fadd_s) + DO_3S_FP_GVEC(VSUB, gen_helper_gvec_fsub_s) + DO_3S_FP_GVEC(VABD, gen_helper_gvec_fabd_s) ++ ++static bool do_3same_fp_pair(DisasContext *s, arg_3same *a, VFPGen3OpSPFn *fn) ++{ ++ /* FP operations handled pairwise 32 bits at a time */ ++ TCGv_i32 tmp, tmp2, tmp3; ++ TCGv_ptr fpstatus; ++ ++ if (!arm_dc_feature(s, ARM_FEATURE_NEON)) { ++ return false; ++ } ++ ++ /* UNDEF accesses to D16-D31 if they don't exist. */ ++ if (!dc_isar_feature(aa32_simd_r32, s) && ++ ((a->vd | a->vn | a->vm) & 0x10)) { ++ return false; ++ } ++ ++ if (!vfp_access_check(s)) { ++ return true; ++ } ++ ++ assert(a->q == 0); /* enforced by decode patterns */ ++ ++ /* ++ * Note that we have to be careful not to clobber the source operands ++ * in the "vm == vd" case by storing the result of the first pass too ++ * early. Since Q is 0 there are always just two passes, so instead ++ * of a complicated loop over each pass we just unroll. ++ */ ++ fpstatus = get_fpstatus_ptr(1); ++ tmp = neon_load_reg(a->vn, 0); ++ tmp2 = neon_load_reg(a->vn, 1); ++ fn(tmp, tmp, tmp2, fpstatus); ++ tcg_temp_free_i32(tmp2); ++ ++ tmp3 = neon_load_reg(a->vm, 0); ++ tmp2 = neon_load_reg(a->vm, 1); ++ fn(tmp3, tmp3, tmp2, fpstatus); ++ tcg_temp_free_i32(tmp2); ++ tcg_temp_free_ptr(fpstatus); ++ ++ neon_store_reg(a->vd, 0, tmp); ++ neon_store_reg(a->vd, 1, tmp3); ++ return true; ++} ++ ++/* ++ * For all the functions using this macro, size == 1 means fp16, ++ * which is an architecture extension we don't implement yet. ++ */ ++#define DO_3S_FP_PAIR(INSN,FUNC) \ ++ static bool trans_##INSN##_fp_3s(DisasContext *s, arg_3same *a) \ ++ { \ ++ if (a->size != 0) { \ ++ /* TODO fp16 support */ \ ++ return false; \ ++ } \ ++ return do_3same_fp_pair(s, a, FUNC); \ ++ } ++ ++DO_3S_FP_PAIR(VPADD, gen_helper_vfp_adds) ++DO_3S_FP_PAIR(VPMAX, gen_helper_vfp_maxs) ++DO_3S_FP_PAIR(VPMIN, gen_helper_vfp_mins) +diff --git a/target/arm/translate.c b/target/arm/translate.c +index 8a94856cd2..ca6ed09ec3 100644 +--- a/target/arm/translate.c ++++ b/target/arm/translate.c +@@ -5348,7 +5348,6 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn) + int shift; + int pass; + int count; +- int pairwise; + int u; + int vec_size; + uint32_t imm; +@@ -5433,6 +5432,7 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn) + case NEON_3R_VPMIN: + case NEON_3R_VPADD_VQRDMLAH: + case NEON_3R_VQDMULH_VQRDMULH: ++ case NEON_3R_FLOAT_ARITH: + /* Already handled by decodetree */ + return 1; + } +@@ -5441,16 +5441,11 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn) + /* 64-bit element instructions: handled by decodetree */ + return 1; + } +- pairwise = 0; + switch (op) { +- case NEON_3R_FLOAT_ARITH: +- pairwise = (u && size < 2); /* if VPADD (float) */ +- if (!pairwise) { +- return 1; /* handled by decodetree */ +- } +- break; + case NEON_3R_FLOAT_MINMAX: +- pairwise = u; /* if VPMIN/VPMAX (float) */ ++ if (u) { ++ return 1; /* VPMIN/VPMAX handled by decodetree */ ++ } + break; + case NEON_3R_FLOAT_CMP: + if (!u && size) { +@@ -5478,41 +5473,12 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn) + break; + } + +- if (pairwise && q) { +- /* All the pairwise insns UNDEF if Q is set */ +- return 1; +- } +- + for (pass = 0; pass < (q ? 4 : 2); pass++) { + +- if (pairwise) { +- /* Pairwise. */ +- if (pass < 1) { +- tmp = neon_load_reg(rn, 0); +- tmp2 = neon_load_reg(rn, 1); +- } else { +- tmp = neon_load_reg(rm, 0); +- tmp2 = neon_load_reg(rm, 1); +- } +- } else { +- /* Elementwise. */ +- tmp = neon_load_reg(rn, pass); +- tmp2 = neon_load_reg(rm, pass); +- } ++ /* Elementwise. */ ++ tmp = neon_load_reg(rn, pass); ++ tmp2 = neon_load_reg(rm, pass); + switch (op) { +- case NEON_3R_FLOAT_ARITH: /* Floating point arithmetic. */ +- { +- TCGv_ptr fpstatus = get_fpstatus_ptr(1); +- switch ((u << 2) | size) { +- case 4: /* VPADD */ +- gen_helper_vfp_adds(tmp, tmp, tmp2, fpstatus); +- break; +- default: +- abort(); +- } +- tcg_temp_free_ptr(fpstatus); +- break; +- } + case NEON_3R_FLOAT_MULTIPLY: + { + TCGv_ptr fpstatus = get_fpstatus_ptr(1); +@@ -5603,22 +5569,9 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn) + } + tcg_temp_free_i32(tmp2); + +- /* Save the result. For elementwise operations we can put it +- straight into the destination register. For pairwise operations +- we have to be careful to avoid clobbering the source operands. */ +- if (pairwise && rd == rm) { +- neon_store_scratch(pass, tmp); +- } else { +- neon_store_reg(rd, pass, tmp); +- } ++ neon_store_reg(rd, pass, tmp); + + } /* for pass */ +- if (pairwise && rd == rm) { +- for (pass = 0; pass < (q ? 4 : 2); pass++) { +- tmp = neon_load_scratch(pass); +- neon_store_reg(rd, pass, tmp); +- } +- } + /* End of 3 register same size operations. */ + } else if (insn & (1 << 4)) { + if ((insn & 0x00380080) != 0) { +-- +2.23.0 + diff --git a/target-arm-Convert-Neon-VQDMULH-VQRDMULH-3-reg-same-.patch b/target-arm-Convert-Neon-VQDMULH-VQRDMULH-3-reg-same-.patch new file mode 100644 index 0000000000000000000000000000000000000000..79440a60039e30708d226cd5b6c89485c203daa5 --- /dev/null +++ b/target-arm-Convert-Neon-VQDMULH-VQRDMULH-3-reg-same-.patch @@ -0,0 +1,110 @@ +From 7ecc28bc72b8033cf4e0c6332135ec20d4125dfb Mon Sep 17 00:00:00 2001 +From: Peter Maydell +Date: Tue, 12 May 2020 17:38:57 +0100 +Subject: [PATCH 455/709] target/arm: Convert Neon VQDMULH/VQRDMULH 3-reg-same + to decodetree + +Convert the Neon VQDMULH and VQRDMULH 3-reg-same insns to +decodetree. These are the last integer operations in the +3-reg-same group. + +Signed-off-by: Peter Maydell +Reviewed-by: Richard Henderson +Message-id: 20200512163904.10918-11-peter.maydell@linaro.org +--- + target/arm/neon-dp.decode | 3 +++ + target/arm/translate-neon.inc.c | 24 ++++++++++++++++++++++++ + target/arm/translate.c | 24 +----------------------- + 3 files changed, 28 insertions(+), 23 deletions(-) + +diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode +index 3659fb036c..fd32837fb1 100644 +--- a/target/arm/neon-dp.decode ++++ b/target/arm/neon-dp.decode +@@ -152,6 +152,9 @@ VPMAX_U_3s 1111 001 1 0 . .. .... .... 1010 . . . 0 .... @3same_q0 + VPMIN_S_3s 1111 001 0 0 . .. .... .... 1010 . . . 1 .... @3same_q0 + VPMIN_U_3s 1111 001 1 0 . .. .... .... 1010 . . . 1 .... @3same_q0 + ++VQDMULH_3s 1111 001 0 0 . .. .... .... 1011 . . . 0 .... @3same ++VQRDMULH_3s 1111 001 1 0 . .. .... .... 1011 . . . 0 .... @3same ++ + VPADD_3s 1111 001 0 0 . .. .... .... 1011 . . . 1 .... @3same_q0 + + VQRDMLAH_3s 1111 001 1 0 . .. .... .... 1011 ... 1 .... @3same +diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c +index e013736407..f52302f42b 100644 +--- a/target/arm/translate-neon.inc.c ++++ b/target/arm/translate-neon.inc.c +@@ -997,3 +997,27 @@ DO_3SAME_PAIR(VPMIN_S, pmin_s) + DO_3SAME_PAIR(VPMAX_U, pmax_u) + DO_3SAME_PAIR(VPMIN_U, pmin_u) + DO_3SAME_PAIR(VPADD, padd_u) ++ ++#define DO_3SAME_VQDMULH(INSN, FUNC) \ ++ WRAP_ENV_FN(gen_##INSN##_tramp16, gen_helper_neon_##FUNC##_s16); \ ++ WRAP_ENV_FN(gen_##INSN##_tramp32, gen_helper_neon_##FUNC##_s32); \ ++ static void gen_##INSN##_3s(unsigned vece, uint32_t rd_ofs, \ ++ uint32_t rn_ofs, uint32_t rm_ofs, \ ++ uint32_t oprsz, uint32_t maxsz) \ ++ { \ ++ static const GVecGen3 ops[2] = { \ ++ { .fni4 = gen_##INSN##_tramp16 }, \ ++ { .fni4 = gen_##INSN##_tramp32 }, \ ++ }; \ ++ tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, oprsz, maxsz, &ops[vece - 1]); \ ++ } \ ++ static bool trans_##INSN##_3s(DisasContext *s, arg_3same *a) \ ++ { \ ++ if (a->size != 1 && a->size != 2) { \ ++ return false; \ ++ } \ ++ return do_3same(s, a, gen_##INSN##_3s); \ ++ } ++ ++DO_3SAME_VQDMULH(VQDMULH, qdmulh) ++DO_3SAME_VQDMULH(VQRDMULH, qrdmulh) +diff --git a/target/arm/translate.c b/target/arm/translate.c +index ce30417014..561cb67286 100644 +--- a/target/arm/translate.c ++++ b/target/arm/translate.c +@@ -5432,6 +5432,7 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn) + case NEON_3R_VPMAX: + case NEON_3R_VPMIN: + case NEON_3R_VPADD_VQRDMLAH: ++ case NEON_3R_VQDMULH_VQRDMULH: + /* Already handled by decodetree */ + return 1; + } +@@ -5496,29 +5497,6 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn) + tmp2 = neon_load_reg(rm, pass); + } + switch (op) { +- case NEON_3R_VQDMULH_VQRDMULH: /* Multiply high. */ +- if (!u) { /* VQDMULH */ +- switch (size) { +- case 1: +- gen_helper_neon_qdmulh_s16(tmp, cpu_env, tmp, tmp2); +- break; +- case 2: +- gen_helper_neon_qdmulh_s32(tmp, cpu_env, tmp, tmp2); +- break; +- default: abort(); +- } +- } else { /* VQRDMULH */ +- switch (size) { +- case 1: +- gen_helper_neon_qrdmulh_s16(tmp, cpu_env, tmp, tmp2); +- break; +- case 2: +- gen_helper_neon_qrdmulh_s32(tmp, cpu_env, tmp, tmp2); +- break; +- default: abort(); +- } +- } +- break; + case NEON_3R_FLOAT_ARITH: /* Floating point arithmetic. */ + { + TCGv_ptr fpstatus = get_fpstatus_ptr(1); +-- +2.23.0 + diff --git a/target-arm-Convert-Neon-VQSHL-VRSHL-VQRSHL-3-reg-sam.patch b/target-arm-Convert-Neon-VQSHL-VRSHL-VQRSHL-3-reg-sam.patch new file mode 100644 index 0000000000000000000000000000000000000000..0084990ed098f643f4dfe8010d843d98b7f5af3b --- /dev/null +++ b/target-arm-Convert-Neon-VQSHL-VRSHL-VQRSHL-3-reg-sam.patch @@ -0,0 +1,167 @@ +From 6812dfdc6b0286730d6f903ebfbdc4f81b80c29b Mon Sep 17 00:00:00 2001 +From: Peter Maydell +Date: Tue, 12 May 2020 17:38:54 +0100 +Subject: [PATCH 452/709] target/arm: Convert Neon VQSHL, VRSHL, VQRSHL + 3-reg-same insns to decodetree + +Convert the VQSHL, VRSHL and VQRSHL insns in the 3-reg-same +group to decodetree. We have already implemented the size==0b11 +case of these insns; this commit handles the remaining sizes. + +Signed-off-by: Peter Maydell +Reviewed-by: Richard Henderson +Message-id: 20200512163904.10918-8-peter.maydell@linaro.org +--- + target/arm/neon-dp.decode | 30 ++++++++++++++++++----- + target/arm/translate-neon.inc.c | 43 +++++++++++++++++++++++++++++++++ + target/arm/translate.c | 22 +++-------------- + 3 files changed, 70 insertions(+), 25 deletions(-) + +diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode +index 4984a5d4e1..34bce81c43 100644 +--- a/target/arm/neon-dp.decode ++++ b/target/arm/neon-dp.decode +@@ -95,12 +95,30 @@ VSHL_U_3s 1111 001 1 0 . .. .... .... 0100 . . . 0 .... @3same_rev + @3same_64_rev .... ... . . . 11 .... .... .... . q:1 . . .... \ + &3same vm=%vn_dp vn=%vm_dp vd=%vd_dp size=3 + +-VQSHL_S64_3s 1111 001 0 0 . .. .... .... 0100 . . . 1 .... @3same_64_rev +-VQSHL_U64_3s 1111 001 1 0 . .. .... .... 0100 . . . 1 .... @3same_64_rev +-VRSHL_S64_3s 1111 001 0 0 . .. .... .... 0101 . . . 0 .... @3same_64_rev +-VRSHL_U64_3s 1111 001 1 0 . .. .... .... 0101 . . . 0 .... @3same_64_rev +-VQRSHL_S64_3s 1111 001 0 0 . .. .... .... 0101 . . . 1 .... @3same_64_rev +-VQRSHL_U64_3s 1111 001 1 0 . .. .... .... 0101 . . . 1 .... @3same_64_rev ++{ ++ VQSHL_S64_3s 1111 001 0 0 . .. .... .... 0100 . . . 1 .... @3same_64_rev ++ VQSHL_S_3s 1111 001 0 0 . .. .... .... 0100 . . . 1 .... @3same_rev ++} ++{ ++ VQSHL_U64_3s 1111 001 1 0 . .. .... .... 0100 . . . 1 .... @3same_64_rev ++ VQSHL_U_3s 1111 001 1 0 . .. .... .... 0100 . . . 1 .... @3same_rev ++} ++{ ++ VRSHL_S64_3s 1111 001 0 0 . .. .... .... 0101 . . . 0 .... @3same_64_rev ++ VRSHL_S_3s 1111 001 0 0 . .. .... .... 0101 . . . 0 .... @3same_rev ++} ++{ ++ VRSHL_U64_3s 1111 001 1 0 . .. .... .... 0101 . . . 0 .... @3same_64_rev ++ VRSHL_U_3s 1111 001 1 0 . .. .... .... 0101 . . . 0 .... @3same_rev ++} ++{ ++ VQRSHL_S64_3s 1111 001 0 0 . .. .... .... 0101 . . . 1 .... @3same_64_rev ++ VQRSHL_S_3s 1111 001 0 0 . .. .... .... 0101 . . . 1 .... @3same_rev ++} ++{ ++ VQRSHL_U64_3s 1111 001 1 0 . .. .... .... 0101 . . . 1 .... @3same_64_rev ++ VQRSHL_U_3s 1111 001 1 0 . .. .... .... 0101 . . . 1 .... @3same_rev ++} + + VMAX_S_3s 1111 001 0 0 . .. .... .... 0110 . . . 0 .... @3same + VMAX_U_3s 1111 001 1 0 . .. .... .... 0110 . . . 0 .... @3same +diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c +index e9da47171c..7097c18f33 100644 +--- a/target/arm/translate-neon.inc.c ++++ b/target/arm/translate-neon.inc.c +@@ -875,9 +875,52 @@ DO_3SAME_64_ENV(VQRSHL_U64, gen_helper_neon_qrshl_u64) + return do_3same(s, a, gen_##INSN##_3s); \ + } + ++/* ++ * Some helper functions need to be passed the cpu_env. In order ++ * to use those with the gvec APIs like tcg_gen_gvec_3() we need ++ * to create wrapper functions whose prototype is a NeonGenTwoOpFn() ++ * and which call a NeonGenTwoOpEnvFn(). ++ */ ++#define WRAP_ENV_FN(WRAPNAME, FUNC) \ ++ static void WRAPNAME(TCGv_i32 d, TCGv_i32 n, TCGv_i32 m) \ ++ { \ ++ FUNC(d, cpu_env, n, m); \ ++ } ++ ++#define DO_3SAME_32_ENV(INSN, FUNC) \ ++ WRAP_ENV_FN(gen_##INSN##_tramp8, gen_helper_neon_##FUNC##8); \ ++ WRAP_ENV_FN(gen_##INSN##_tramp16, gen_helper_neon_##FUNC##16); \ ++ WRAP_ENV_FN(gen_##INSN##_tramp32, gen_helper_neon_##FUNC##32); \ ++ static void gen_##INSN##_3s(unsigned vece, uint32_t rd_ofs, \ ++ uint32_t rn_ofs, uint32_t rm_ofs, \ ++ uint32_t oprsz, uint32_t maxsz) \ ++ { \ ++ static const GVecGen3 ops[4] = { \ ++ { .fni4 = gen_##INSN##_tramp8 }, \ ++ { .fni4 = gen_##INSN##_tramp16 }, \ ++ { .fni4 = gen_##INSN##_tramp32 }, \ ++ { 0 }, \ ++ }; \ ++ tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, oprsz, maxsz, &ops[vece]); \ ++ } \ ++ static bool trans_##INSN##_3s(DisasContext *s, arg_3same *a) \ ++ { \ ++ if (a->size > 2) { \ ++ return false; \ ++ } \ ++ return do_3same(s, a, gen_##INSN##_3s); \ ++ } ++ + DO_3SAME_32(VHADD_S, hadd_s) + DO_3SAME_32(VHADD_U, hadd_u) + DO_3SAME_32(VHSUB_S, hsub_s) + DO_3SAME_32(VHSUB_U, hsub_u) + DO_3SAME_32(VRHADD_S, rhadd_s) + DO_3SAME_32(VRHADD_U, rhadd_u) ++DO_3SAME_32(VRSHL_S, rshl_s) ++DO_3SAME_32(VRSHL_U, rshl_u) ++ ++DO_3SAME_32_ENV(VQSHL_S, qshl_s) ++DO_3SAME_32_ENV(VQSHL_U, qshl_u) ++DO_3SAME_32_ENV(VQRSHL_S, qrshl_s) ++DO_3SAME_32_ENV(VQRSHL_U, qrshl_u) +diff --git a/target/arm/translate.c b/target/arm/translate.c +index ebb899d846..3aabb18720 100644 +--- a/target/arm/translate.c ++++ b/target/arm/translate.c +@@ -5439,6 +5439,9 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn) + case NEON_3R_VHSUB: + case NEON_3R_VABD: + case NEON_3R_VABA: ++ case NEON_3R_VQSHL: ++ case NEON_3R_VRSHL: ++ case NEON_3R_VQRSHL: + /* Already handled by decodetree */ + return 1; + } +@@ -5449,17 +5452,6 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn) + } + pairwise = 0; + switch (op) { +- case NEON_3R_VQSHL: +- case NEON_3R_VRSHL: +- case NEON_3R_VQRSHL: +- { +- int rtmp; +- /* Shift instruction operands are reversed. */ +- rtmp = rn; +- rn = rm; +- rm = rtmp; +- } +- break; + case NEON_3R_VPADD_VQRDMLAH: + case NEON_3R_VPMAX: + case NEON_3R_VPMIN: +@@ -5519,14 +5511,6 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn) + tmp2 = neon_load_reg(rm, pass); + } + switch (op) { +- case NEON_3R_VQSHL: +- GEN_NEON_INTEGER_OP_ENV(qshl); +- break; +- case NEON_3R_VRSHL: +- GEN_NEON_INTEGER_OP(rshl); +- break; +- case NEON_3R_VQRSHL: +- GEN_NEON_INTEGER_OP_ENV(qrshl); + break; + case NEON_3R_VPMAX: + GEN_NEON_INTEGER_OP(pmax); +-- +2.23.0 + diff --git a/target-arm-Convert-Neon-VRHADD-VHSUB-3-reg-same-insn.patch b/target-arm-Convert-Neon-VRHADD-VHSUB-3-reg-same-insn.patch new file mode 100644 index 0000000000000000000000000000000000000000..fdeb209ecc0f347a6bdb9ee6855b6bbd9216e899 --- /dev/null +++ b/target-arm-Convert-Neon-VRHADD-VHSUB-3-reg-same-insn.patch @@ -0,0 +1,85 @@ +From 8e44d03f4b5590e19a4f7910ca1c327609933dd7 Mon Sep 17 00:00:00 2001 +From: Peter Maydell +Date: Tue, 12 May 2020 17:38:53 +0100 +Subject: [PATCH 451/709] target/arm: Convert Neon VRHADD, VHSUB 3-reg-same + insns to decodetree + +Convert the Neon VRHADD and VHSUB 3-reg-same insns to decodetree. +(These are all the other insns in 3-reg-same which were using +GEN_NEON_INTEGER_OP() and which are not pairwise or +reversed-operands.) + +Signed-off-by: Peter Maydell +Reviewed-by: Richard Henderson +Message-id: 20200512163904.10918-7-peter.maydell@linaro.org +--- + target/arm/neon-dp.decode | 6 ++++++ + target/arm/translate-neon.inc.c | 4 ++++ + target/arm/translate.c | 8 ++------ + 3 files changed, 12 insertions(+), 6 deletions(-) + +diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode +index 00a909a888..4984a5d4e1 100644 +--- a/target/arm/neon-dp.decode ++++ b/target/arm/neon-dp.decode +@@ -47,6 +47,9 @@ VHADD_U_3s 1111 001 1 0 . .. .... .... 0000 . . . 0 .... @3same + VQADD_S_3s 1111 001 0 0 . .. .... .... 0000 . . . 1 .... @3same + VQADD_U_3s 1111 001 1 0 . .. .... .... 0000 . . . 1 .... @3same + ++VRHADD_S_3s 1111 001 0 0 . .. .... .... 0001 . . . 0 .... @3same ++VRHADD_U_3s 1111 001 1 0 . .. .... .... 0001 . . . 0 .... @3same ++ + @3same_logic .... ... . . . .. .... .... .... . q:1 .. .... \ + &3same vm=%vm_dp vn=%vn_dp vd=%vd_dp size=0 + +@@ -59,6 +62,9 @@ VBSL_3s 1111 001 1 0 . 01 .... .... 0001 ... 1 .... @3same_logic + VBIT_3s 1111 001 1 0 . 10 .... .... 0001 ... 1 .... @3same_logic + VBIF_3s 1111 001 1 0 . 11 .... .... 0001 ... 1 .... @3same_logic + ++VHSUB_S_3s 1111 001 0 0 . .. .... .... 0010 . . . 0 .... @3same ++VHSUB_U_3s 1111 001 1 0 . .. .... .... 0010 . . . 0 .... @3same ++ + VQSUB_S_3s 1111 001 0 0 . .. .... .... 0010 . . . 1 .... @3same + VQSUB_U_3s 1111 001 1 0 . .. .... .... 0010 . . . 1 .... @3same + +diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c +index 20f0f2c8d8..e9da47171c 100644 +--- a/target/arm/translate-neon.inc.c ++++ b/target/arm/translate-neon.inc.c +@@ -877,3 +877,7 @@ DO_3SAME_64_ENV(VQRSHL_U64, gen_helper_neon_qrshl_u64) + + DO_3SAME_32(VHADD_S, hadd_s) + DO_3SAME_32(VHADD_U, hadd_u) ++DO_3SAME_32(VHSUB_S, hsub_s) ++DO_3SAME_32(VHSUB_U, hsub_u) ++DO_3SAME_32(VRHADD_S, rhadd_s) ++DO_3SAME_32(VRHADD_U, rhadd_u) +diff --git a/target/arm/translate.c b/target/arm/translate.c +index 2c842df445..ebb899d846 100644 +--- a/target/arm/translate.c ++++ b/target/arm/translate.c +@@ -5435,6 +5435,8 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn) + case NEON_3R_VSHL: + case NEON_3R_SHA: + case NEON_3R_VHADD: ++ case NEON_3R_VRHADD: ++ case NEON_3R_VHSUB: + case NEON_3R_VABD: + case NEON_3R_VABA: + /* Already handled by decodetree */ +@@ -5517,12 +5519,6 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn) + tmp2 = neon_load_reg(rm, pass); + } + switch (op) { +- case NEON_3R_VRHADD: +- GEN_NEON_INTEGER_OP(rhadd); +- break; +- case NEON_3R_VHSUB: +- GEN_NEON_INTEGER_OP(hsub); +- break; + case NEON_3R_VQSHL: + GEN_NEON_INTEGER_OP_ENV(qshl); + break; +-- +2.23.0 + diff --git a/target-arm-Convert-Neon-fp-VMAX-VMIN-VMAXNM-VMINNM-V.patch b/target-arm-Convert-Neon-fp-VMAX-VMIN-VMAXNM-VMINNM-V.patch new file mode 100644 index 0000000000000000000000000000000000000000..690da1629ef2862699ca634d317e6131a3576573 --- /dev/null +++ b/target-arm-Convert-Neon-fp-VMAX-VMIN-VMAXNM-VMINNM-V.patch @@ -0,0 +1,193 @@ +From d5fdf9e9e1c6f2bbb0a4bcaafd85d344cce9c298 Mon Sep 17 00:00:00 2001 +From: Peter Maydell +Date: Tue, 12 May 2020 17:39:03 +0100 +Subject: [PATCH 461/709] target/arm: Convert Neon fp + VMAX/VMIN/VMAXNM/VMINNM/VRECPS/VRSQRTS to decodetree + +Convert the Neon fp VMAX/VMIN/VMAXNM/VMINNM/VRECPS/VRSQRTS 3-reg-same +insns to decodetree. (These are all the remaining non-accumulation +instructions in this group.) + +Signed-off-by: Peter Maydell +Reviewed-by: Richard Henderson +Message-id: 20200512163904.10918-17-peter.maydell@linaro.org +--- + target/arm/neon-dp.decode | 6 +++ + target/arm/translate-neon.inc.c | 70 +++++++++++++++++++++++++++++++++ + target/arm/translate.c | 42 +------------------- + 3 files changed, 78 insertions(+), 40 deletions(-) + +diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode +index 29cf54c217..9c28886507 100644 +--- a/target/arm/neon-dp.decode ++++ b/target/arm/neon-dp.decode +@@ -188,5 +188,11 @@ VCGE_fp_3s 1111 001 1 0 . 0 . .... .... 1110 ... 0 .... @3same_fp + VACGE_fp_3s 1111 001 1 0 . 0 . .... .... 1110 ... 1 .... @3same_fp + VCGT_fp_3s 1111 001 1 0 . 1 . .... .... 1110 ... 0 .... @3same_fp + VACGT_fp_3s 1111 001 1 0 . 1 . .... .... 1110 ... 1 .... @3same_fp ++VMAX_fp_3s 1111 001 0 0 . 0 . .... .... 1111 ... 0 .... @3same_fp ++VMIN_fp_3s 1111 001 0 0 . 1 . .... .... 1111 ... 0 .... @3same_fp + VPMAX_fp_3s 1111 001 1 0 . 0 . .... .... 1111 ... 0 .... @3same_fp_q0 + VPMIN_fp_3s 1111 001 1 0 . 1 . .... .... 1111 ... 0 .... @3same_fp_q0 ++VRECPS_fp_3s 1111 001 0 0 . 0 . .... .... 1111 ... 1 .... @3same_fp ++VRSQRTS_fp_3s 1111 001 0 0 . 1 . .... .... 1111 ... 1 .... @3same_fp ++VMAXNM_fp_3s 1111 001 1 0 . 0 . .... .... 1111 ... 1 .... @3same_fp ++VMINNM_fp_3s 1111 001 1 0 . 1 . .... .... 1111 ... 1 .... @3same_fp +diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c +index eeea71e3be..5e9e53c5c3 100644 +--- a/target/arm/translate-neon.inc.c ++++ b/target/arm/translate-neon.inc.c +@@ -1119,6 +1119,8 @@ DO_3S_FP(VCGE, gen_helper_neon_cge_f32, false) + DO_3S_FP(VCGT, gen_helper_neon_cgt_f32, false) + DO_3S_FP(VACGE, gen_helper_neon_acge_f32, false) + DO_3S_FP(VACGT, gen_helper_neon_acgt_f32, false) ++DO_3S_FP(VMAX, gen_helper_vfp_maxs, false) ++DO_3S_FP(VMIN, gen_helper_vfp_mins, false) + + static void gen_VMLA_fp_3s(TCGv_i32 vd, TCGv_i32 vn, TCGv_i32 vm, + TCGv_ptr fpstatus) +@@ -1137,6 +1139,74 @@ static void gen_VMLS_fp_3s(TCGv_i32 vd, TCGv_i32 vn, TCGv_i32 vm, + DO_3S_FP(VMLA, gen_VMLA_fp_3s, true) + DO_3S_FP(VMLS, gen_VMLS_fp_3s, true) + ++static bool trans_VMAXNM_fp_3s(DisasContext *s, arg_3same *a) ++{ ++ if (!arm_dc_feature(s, ARM_FEATURE_V8)) { ++ return false; ++ } ++ ++ if (a->size != 0) { ++ /* TODO fp16 support */ ++ return false; ++ } ++ ++ return do_3same_fp(s, a, gen_helper_vfp_maxnums, false); ++} ++ ++static bool trans_VMINNM_fp_3s(DisasContext *s, arg_3same *a) ++{ ++ if (!arm_dc_feature(s, ARM_FEATURE_V8)) { ++ return false; ++ } ++ ++ if (a->size != 0) { ++ /* TODO fp16 support */ ++ return false; ++ } ++ ++ return do_3same_fp(s, a, gen_helper_vfp_minnums, false); ++} ++ ++WRAP_ENV_FN(gen_VRECPS_tramp, gen_helper_recps_f32) ++ ++static void gen_VRECPS_fp_3s(unsigned vece, uint32_t rd_ofs, ++ uint32_t rn_ofs, uint32_t rm_ofs, ++ uint32_t oprsz, uint32_t maxsz) ++{ ++ static const GVecGen3 ops = { .fni4 = gen_VRECPS_tramp }; ++ tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, oprsz, maxsz, &ops); ++} ++ ++static bool trans_VRECPS_fp_3s(DisasContext *s, arg_3same *a) ++{ ++ if (a->size != 0) { ++ /* TODO fp16 support */ ++ return false; ++ } ++ ++ return do_3same(s, a, gen_VRECPS_fp_3s); ++} ++ ++WRAP_ENV_FN(gen_VRSQRTS_tramp, gen_helper_rsqrts_f32) ++ ++static void gen_VRSQRTS_fp_3s(unsigned vece, uint32_t rd_ofs, ++ uint32_t rn_ofs, uint32_t rm_ofs, ++ uint32_t oprsz, uint32_t maxsz) ++{ ++ static const GVecGen3 ops = { .fni4 = gen_VRSQRTS_tramp }; ++ tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, oprsz, maxsz, &ops); ++} ++ ++static bool trans_VRSQRTS_fp_3s(DisasContext *s, arg_3same *a) ++{ ++ if (a->size != 0) { ++ /* TODO fp16 support */ ++ return false; ++ } ++ ++ return do_3same(s, a, gen_VRSQRTS_fp_3s); ++} ++ + static bool do_3same_fp_pair(DisasContext *s, arg_3same *a, VFPGen3OpSPFn *fn) + { + /* FP operations handled pairwise 32 bits at a time */ +diff --git a/target/arm/translate.c b/target/arm/translate.c +index 23e3705172..c1d4fab8e8 100644 +--- a/target/arm/translate.c ++++ b/target/arm/translate.c +@@ -5436,6 +5436,8 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn) + case NEON_3R_FLOAT_MULTIPLY: + case NEON_3R_FLOAT_CMP: + case NEON_3R_FLOAT_ACMP: ++ case NEON_3R_FLOAT_MINMAX: ++ case NEON_3R_FLOAT_MISC: + /* Already handled by decodetree */ + return 1; + } +@@ -5445,17 +5447,6 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn) + return 1; + } + switch (op) { +- case NEON_3R_FLOAT_MINMAX: +- if (u) { +- return 1; /* VPMIN/VPMAX handled by decodetree */ +- } +- break; +- case NEON_3R_FLOAT_MISC: +- /* VMAXNM/VMINNM in ARMv8 */ +- if (u && !arm_dc_feature(s, ARM_FEATURE_V8)) { +- return 1; +- } +- break; + case NEON_3R_VFM_VQRDMLSH: + if (!dc_isar_feature(aa32_simdfmac, s)) { + return 1; +@@ -5471,35 +5462,6 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn) + tmp = neon_load_reg(rn, pass); + tmp2 = neon_load_reg(rm, pass); + switch (op) { +- case NEON_3R_FLOAT_MINMAX: +- { +- TCGv_ptr fpstatus = get_fpstatus_ptr(1); +- if (size == 0) { +- gen_helper_vfp_maxs(tmp, tmp, tmp2, fpstatus); +- } else { +- gen_helper_vfp_mins(tmp, tmp, tmp2, fpstatus); +- } +- tcg_temp_free_ptr(fpstatus); +- break; +- } +- case NEON_3R_FLOAT_MISC: +- if (u) { +- /* VMAXNM/VMINNM */ +- TCGv_ptr fpstatus = get_fpstatus_ptr(1); +- if (size == 0) { +- gen_helper_vfp_maxnums(tmp, tmp, tmp2, fpstatus); +- } else { +- gen_helper_vfp_minnums(tmp, tmp, tmp2, fpstatus); +- } +- tcg_temp_free_ptr(fpstatus); +- } else { +- if (size == 0) { +- gen_helper_recps_f32(tmp, cpu_env, tmp, tmp2); +- } else { +- gen_helper_rsqrts_f32(tmp, cpu_env, tmp, tmp2); +- } +- } +- break; + case NEON_3R_VFM_VQRDMLSH: + { + /* VFMA, VFMS: fused multiply-add */ +-- +2.23.0 + diff --git a/target-arm-Convert-Neon-fp-VMUL-VMLA-VMLS-3-reg-same.patch b/target-arm-Convert-Neon-fp-VMUL-VMLA-VMLS-3-reg-same.patch new file mode 100644 index 0000000000000000000000000000000000000000..a39735e8c48ecb0a0c69d46b4cd096c76185c3ab --- /dev/null +++ b/target-arm-Convert-Neon-fp-VMUL-VMLA-VMLS-3-reg-same.patch @@ -0,0 +1,188 @@ +From 8aa71ead912ca0a9c0d29b74e0976f91952f950a Mon Sep 17 00:00:00 2001 +From: Peter Maydell +Date: Tue, 12 May 2020 17:39:00 +0100 +Subject: [PATCH 458/709] target/arm: Convert Neon fp VMUL, VMLA, VMLS + 3-reg-same insns to decodetree + +Convert the Neon integer VMUL, VMLA, and VMLS 3-reg-same inssn to +decodetree. + +We don't have a gvec helper for multiply-accumulate, so VMLA and VMLS +need a loop function do_3same_fp(). This takes a reads_vd parameter +to do_3same_fp() which tells it to load the old value into vd before +calling the callback function, in the same way that the do_vfp_3op_sp() +and do_vfp_3op_dp() functions in translate-vfp.inc.c work. (The +only uses in this patch pass reads_vd == true, but later commits +will use reads_vd == false.) + +This conversion fixes in passing an underdecoding for VMUL +(originally reported by Fredrik Strupe ): bit 1 +of the 'size' field must be 0. The old decoder didn't enforce this, +but the decodetree pattern does. + +The gen_VMLA_fp_reg() function performs the addition operation +with the operands in the opposite order to the old decoder: +since Neon sets 'default NaN mode' float32_add operations are +commutative so there is no behaviour difference, but putting +them this way around matches the Arm ARM pseudocode and the +required operation order for the subtraction in gen_VMLS_fp_reg(). + +Signed-off-by: Peter Maydell +Reviewed-by: Richard Henderson +Message-id: 20200512163904.10918-14-peter.maydell@linaro.org +--- + target/arm/neon-dp.decode | 3 ++ + target/arm/translate-neon.inc.c | 81 +++++++++++++++++++++++++++++++++ + target/arm/translate.c | 17 +------ + 3 files changed, 85 insertions(+), 16 deletions(-) + +diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode +index d66c67ca58..4c2f8c770d 100644 +--- a/target/arm/neon-dp.decode ++++ b/target/arm/neon-dp.decode +@@ -180,5 +180,8 @@ VADD_fp_3s 1111 001 0 0 . 0 . .... .... 1101 ... 0 .... @3same_fp + VSUB_fp_3s 1111 001 0 0 . 1 . .... .... 1101 ... 0 .... @3same_fp + VPADD_fp_3s 1111 001 1 0 . 0 . .... .... 1101 ... 0 .... @3same_fp_q0 + VABD_fp_3s 1111 001 1 0 . 1 . .... .... 1101 ... 0 .... @3same_fp ++VMLA_fp_3s 1111 001 0 0 . 0 . .... .... 1101 ... 1 .... @3same_fp ++VMLS_fp_3s 1111 001 0 0 . 1 . .... .... 1101 ... 1 .... @3same_fp ++VMUL_fp_3s 1111 001 1 0 . 0 . .... .... 1101 ... 1 .... @3same_fp + VPMAX_fp_3s 1111 001 1 0 . 0 . .... .... 1111 ... 0 .... @3same_fp_q0 + VPMIN_fp_3s 1111 001 1 0 . 1 . .... .... 1111 ... 0 .... @3same_fp_q0 +diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c +index 7bdf1e3fee..18896598bb 100644 +--- a/target/arm/translate-neon.inc.c ++++ b/target/arm/translate-neon.inc.c +@@ -1022,6 +1022,55 @@ DO_3SAME_PAIR(VPADD, padd_u) + DO_3SAME_VQDMULH(VQDMULH, qdmulh) + DO_3SAME_VQDMULH(VQRDMULH, qrdmulh) + ++static bool do_3same_fp(DisasContext *s, arg_3same *a, VFPGen3OpSPFn *fn, ++ bool reads_vd) ++{ ++ /* ++ * FP operations handled elementwise 32 bits at a time. ++ * If reads_vd is true then the old value of Vd will be ++ * loaded before calling the callback function. This is ++ * used for multiply-accumulate type operations. ++ */ ++ TCGv_i32 tmp, tmp2; ++ int pass; ++ ++ if (!arm_dc_feature(s, ARM_FEATURE_NEON)) { ++ return false; ++ } ++ ++ /* UNDEF accesses to D16-D31 if they don't exist. */ ++ if (!dc_isar_feature(aa32_simd_r32, s) && ++ ((a->vd | a->vn | a->vm) & 0x10)) { ++ return false; ++ } ++ ++ if ((a->vn | a->vm | a->vd) & a->q) { ++ return false; ++ } ++ ++ if (!vfp_access_check(s)) { ++ return true; ++ } ++ ++ TCGv_ptr fpstatus = get_fpstatus_ptr(1); ++ for (pass = 0; pass < (a->q ? 4 : 2); pass++) { ++ tmp = neon_load_reg(a->vn, pass); ++ tmp2 = neon_load_reg(a->vm, pass); ++ if (reads_vd) { ++ TCGv_i32 tmp_rd = neon_load_reg(a->vd, pass); ++ fn(tmp_rd, tmp, tmp2, fpstatus); ++ neon_store_reg(a->vd, pass, tmp_rd); ++ tcg_temp_free_i32(tmp); ++ } else { ++ fn(tmp, tmp, tmp2, fpstatus); ++ neon_store_reg(a->vd, pass, tmp); ++ } ++ tcg_temp_free_i32(tmp2); ++ } ++ tcg_temp_free_ptr(fpstatus); ++ return true; ++} ++ + /* + * For all the functions using this macro, size == 1 means fp16, + * which is an architecture extension we don't implement yet. +@@ -1049,6 +1098,38 @@ DO_3SAME_VQDMULH(VQRDMULH, qrdmulh) + DO_3S_FP_GVEC(VADD, gen_helper_gvec_fadd_s) + DO_3S_FP_GVEC(VSUB, gen_helper_gvec_fsub_s) + DO_3S_FP_GVEC(VABD, gen_helper_gvec_fabd_s) ++DO_3S_FP_GVEC(VMUL, gen_helper_gvec_fmul_s) ++ ++/* ++ * For all the functions using this macro, size == 1 means fp16, ++ * which is an architecture extension we don't implement yet. ++ */ ++#define DO_3S_FP(INSN,FUNC,READS_VD) \ ++ static bool trans_##INSN##_fp_3s(DisasContext *s, arg_3same *a) \ ++ { \ ++ if (a->size != 0) { \ ++ /* TODO fp16 support */ \ ++ return false; \ ++ } \ ++ return do_3same_fp(s, a, FUNC, READS_VD); \ ++ } ++ ++static void gen_VMLA_fp_3s(TCGv_i32 vd, TCGv_i32 vn, TCGv_i32 vm, ++ TCGv_ptr fpstatus) ++{ ++ gen_helper_vfp_muls(vn, vn, vm, fpstatus); ++ gen_helper_vfp_adds(vd, vd, vn, fpstatus); ++} ++ ++static void gen_VMLS_fp_3s(TCGv_i32 vd, TCGv_i32 vn, TCGv_i32 vm, ++ TCGv_ptr fpstatus) ++{ ++ gen_helper_vfp_muls(vn, vn, vm, fpstatus); ++ gen_helper_vfp_subs(vd, vd, vn, fpstatus); ++} ++ ++DO_3S_FP(VMLA, gen_VMLA_fp_3s, true) ++DO_3S_FP(VMLS, gen_VMLS_fp_3s, true) + + static bool do_3same_fp_pair(DisasContext *s, arg_3same *a, VFPGen3OpSPFn *fn) + { +diff --git a/target/arm/translate.c b/target/arm/translate.c +index ca6ed09ec3..06b6925d31 100644 +--- a/target/arm/translate.c ++++ b/target/arm/translate.c +@@ -5433,6 +5433,7 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn) + case NEON_3R_VPADD_VQRDMLAH: + case NEON_3R_VQDMULH_VQRDMULH: + case NEON_3R_FLOAT_ARITH: ++ case NEON_3R_FLOAT_MULTIPLY: + /* Already handled by decodetree */ + return 1; + } +@@ -5479,22 +5480,6 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn) + tmp = neon_load_reg(rn, pass); + tmp2 = neon_load_reg(rm, pass); + switch (op) { +- case NEON_3R_FLOAT_MULTIPLY: +- { +- TCGv_ptr fpstatus = get_fpstatus_ptr(1); +- gen_helper_vfp_muls(tmp, tmp, tmp2, fpstatus); +- if (!u) { +- tcg_temp_free_i32(tmp2); +- tmp2 = neon_load_reg(rd, pass); +- if (size == 0) { +- gen_helper_vfp_adds(tmp, tmp, tmp2, fpstatus); +- } else { +- gen_helper_vfp_subs(tmp, tmp2, tmp, fpstatus); +- } +- } +- tcg_temp_free_ptr(fpstatus); +- break; +- } + case NEON_3R_FLOAT_CMP: + { + TCGv_ptr fpstatus = get_fpstatus_ptr(1); +-- +2.23.0 + diff --git a/target-arm-Convert-Neon-load-single-structure-to-all.patch b/target-arm-Convert-Neon-load-single-structure-to-all.patch new file mode 100644 index 0000000000000000000000000000000000000000..dec20077594e4a6a22a732956179c8e633d9a80d --- /dev/null +++ b/target-arm-Convert-Neon-load-single-structure-to-all.patch @@ -0,0 +1,188 @@ +From 3698747c48db871d876a398592c5a23d7580ed4a Mon Sep 17 00:00:00 2001 +From: Peter Maydell +Date: Thu, 30 Apr 2020 19:09:39 +0100 +Subject: [PATCH 179/709] target/arm: Convert Neon 'load single structure to + all lanes' to decodetree + +Convert the Neon "load single structure to all lanes" insns to +decodetree. + +Signed-off-by: Peter Maydell +Reviewed-by: Richard Henderson +Message-id: 20200430181003.21682-13-peter.maydell@linaro.org +--- + target/arm/neon-ls.decode | 5 +++ + target/arm/translate-neon.inc.c | 73 +++++++++++++++++++++++++++++++++ + target/arm/translate.c | 55 +------------------------ + 3 files changed, 80 insertions(+), 53 deletions(-) + +diff --git a/target/arm/neon-ls.decode b/target/arm/neon-ls.decode +index dd03d5a37b..f0ab6d2c98 100644 +--- a/target/arm/neon-ls.decode ++++ b/target/arm/neon-ls.decode +@@ -34,3 +34,8 @@ + + VLDST_multiple 1111 0100 0 . l:1 0 rn:4 .... itype:4 size:2 align:2 rm:4 \ + vd=%vd_dp ++ ++# Neon load single element to all lanes ++ ++VLD_all_lanes 1111 0100 1 . 1 0 rn:4 .... 11 n:2 size:2 t:1 a:1 rm:4 \ ++ vd=%vd_dp +diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c +index 966c0d9201..e60e9559ba 100644 +--- a/target/arm/translate-neon.inc.c ++++ b/target/arm/translate-neon.inc.c +@@ -398,3 +398,76 @@ static bool trans_VLDST_multiple(DisasContext *s, arg_VLDST_multiple *a) + gen_neon_ldst_base_update(s, a->rm, a->rn, nregs * interleave * 8); + return true; + } ++ ++static bool trans_VLD_all_lanes(DisasContext *s, arg_VLD_all_lanes *a) ++{ ++ /* Neon load single structure to all lanes */ ++ int reg, stride, vec_size; ++ int vd = a->vd; ++ int size = a->size; ++ int nregs = a->n + 1; ++ TCGv_i32 addr, tmp; ++ ++ if (!arm_dc_feature(s, ARM_FEATURE_NEON)) { ++ return false; ++ } ++ ++ /* UNDEF accesses to D16-D31 if they don't exist */ ++ if (!dc_isar_feature(aa32_simd_r32, s) && (a->vd & 0x10)) { ++ return false; ++ } ++ ++ if (size == 3) { ++ if (nregs != 4 || a->a == 0) { ++ return false; ++ } ++ /* For VLD4 size == 3 a == 1 means 32 bits at 16 byte alignment */ ++ size = 2; ++ } ++ if (nregs == 1 && a->a == 1 && size == 0) { ++ return false; ++ } ++ if (nregs == 3 && a->a == 1) { ++ return false; ++ } ++ ++ if (!vfp_access_check(s)) { ++ return true; ++ } ++ ++ /* ++ * VLD1 to all lanes: T bit indicates how many Dregs to write. ++ * VLD2/3/4 to all lanes: T bit indicates register stride. ++ */ ++ stride = a->t ? 2 : 1; ++ vec_size = nregs == 1 ? stride * 8 : 8; ++ ++ tmp = tcg_temp_new_i32(); ++ addr = tcg_temp_new_i32(); ++ load_reg_var(s, addr, a->rn); ++ for (reg = 0; reg < nregs; reg++) { ++ gen_aa32_ld_i32(s, tmp, addr, get_mem_index(s), ++ s->be_data | size); ++ if ((vd & 1) && vec_size == 16) { ++ /* ++ * We cannot write 16 bytes at once because the ++ * destination is unaligned. ++ */ ++ tcg_gen_gvec_dup_i32(size, neon_reg_offset(vd, 0), ++ 8, 8, tmp); ++ tcg_gen_gvec_mov(0, neon_reg_offset(vd + 1, 0), ++ neon_reg_offset(vd, 0), 8, 8); ++ } else { ++ tcg_gen_gvec_dup_i32(size, neon_reg_offset(vd, 0), ++ vec_size, vec_size, tmp); ++ } ++ tcg_gen_addi_i32(addr, addr, 1 << size); ++ vd += stride; ++ } ++ tcg_temp_free_i32(tmp); ++ tcg_temp_free_i32(addr); ++ ++ gen_neon_ldst_base_update(s, a->rm, a->rn, (1 << size) * nregs); ++ ++ return true; ++} +diff --git a/target/arm/translate.c b/target/arm/translate.c +index be56cbb061..7099274c92 100644 +--- a/target/arm/translate.c ++++ b/target/arm/translate.c +@@ -3224,7 +3224,6 @@ static int disas_neon_ls_insn(DisasContext *s, uint32_t insn) + int size; + int reg; + int load; +- int vec_size; + TCGv_i32 addr; + TCGv_i32 tmp; + +@@ -3254,58 +3253,8 @@ static int disas_neon_ls_insn(DisasContext *s, uint32_t insn) + } else { + size = (insn >> 10) & 3; + if (size == 3) { +- /* Load single element to all lanes. */ +- int a = (insn >> 4) & 1; +- if (!load) { +- return 1; +- } +- size = (insn >> 6) & 3; +- nregs = ((insn >> 8) & 3) + 1; +- +- if (size == 3) { +- if (nregs != 4 || a == 0) { +- return 1; +- } +- /* For VLD4 size==3 a == 1 means 32 bits at 16 byte alignment */ +- size = 2; +- } +- if (nregs == 1 && a == 1 && size == 0) { +- return 1; +- } +- if (nregs == 3 && a == 1) { +- return 1; +- } +- addr = tcg_temp_new_i32(); +- load_reg_var(s, addr, rn); +- +- /* VLD1 to all lanes: bit 5 indicates how many Dregs to write. +- * VLD2/3/4 to all lanes: bit 5 indicates register stride. +- */ +- stride = (insn & (1 << 5)) ? 2 : 1; +- vec_size = nregs == 1 ? stride * 8 : 8; +- +- tmp = tcg_temp_new_i32(); +- for (reg = 0; reg < nregs; reg++) { +- gen_aa32_ld_i32(s, tmp, addr, get_mem_index(s), +- s->be_data | size); +- if ((rd & 1) && vec_size == 16) { +- /* We cannot write 16 bytes at once because the +- * destination is unaligned. +- */ +- tcg_gen_gvec_dup_i32(size, neon_reg_offset(rd, 0), +- 8, 8, tmp); +- tcg_gen_gvec_mov(0, neon_reg_offset(rd + 1, 0), +- neon_reg_offset(rd, 0), 8, 8); +- } else { +- tcg_gen_gvec_dup_i32(size, neon_reg_offset(rd, 0), +- vec_size, vec_size, tmp); +- } +- tcg_gen_addi_i32(addr, addr, 1 << size); +- rd += stride; +- } +- tcg_temp_free_i32(tmp); +- tcg_temp_free_i32(addr); +- stride = (1 << size) * nregs; ++ /* Load single element to all lanes -- handled by decodetree */ ++ return 1; + } else { + /* Single element. */ + int idx = (insn >> 4) & 0xf; +-- +2.23.0 + diff --git a/target-arm-Convert-Neon-load-store-multiple-structur.patch b/target-arm-Convert-Neon-load-store-multiple-structur.patch new file mode 100644 index 0000000000000000000000000000000000000000..52689030caa0e56642fd43e95bcb5831d1af20c8 --- /dev/null +++ b/target-arm-Convert-Neon-load-store-multiple-structur.patch @@ -0,0 +1,290 @@ +From a27b46304352a0eced45e560e96515dbe3cc174f Mon Sep 17 00:00:00 2001 +From: Peter Maydell +Date: Thu, 30 Apr 2020 19:09:38 +0100 +Subject: [PATCH 178/709] target/arm: Convert Neon load/store multiple + structures to decodetree + +Convert the Neon "load/store multiple structures" insns to decodetree. + +Signed-off-by: Peter Maydell +Reviewed-by: Richard Henderson +Message-id: 20200430181003.21682-12-peter.maydell@linaro.org +--- + target/arm/neon-ls.decode | 7 ++ + target/arm/translate-neon.inc.c | 124 ++++++++++++++++++++++++++++++++ + target/arm/translate.c | 91 +---------------------- + 3 files changed, 133 insertions(+), 89 deletions(-) + +diff --git a/target/arm/neon-ls.decode b/target/arm/neon-ls.decode +index 2b16c9256d..dd03d5a37b 100644 +--- a/target/arm/neon-ls.decode ++++ b/target/arm/neon-ls.decode +@@ -27,3 +27,10 @@ + # 0b1111_1001_xxx0_xxxx_xxxx_xxxx_xxxx_xxxx + # This file works on the A32 encoding only; calling code for T32 has to + # transform the insn into the A32 version first. ++ ++%vd_dp 22:1 12:4 ++ ++# Neon load/store multiple structures ++ ++VLDST_multiple 1111 0100 0 . l:1 0 rn:4 .... itype:4 size:2 align:2 rm:4 \ ++ vd=%vd_dp +diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c +index b06542b8b8..966c0d9201 100644 +--- a/target/arm/translate-neon.inc.c ++++ b/target/arm/translate-neon.inc.c +@@ -274,3 +274,127 @@ static bool trans_VFML_scalar(DisasContext *s, arg_VFML_scalar *a) + gen_helper_gvec_fmlal_idx_a32); + return true; + } ++ ++static struct { ++ int nregs; ++ int interleave; ++ int spacing; ++} const neon_ls_element_type[11] = { ++ {1, 4, 1}, ++ {1, 4, 2}, ++ {4, 1, 1}, ++ {2, 2, 2}, ++ {1, 3, 1}, ++ {1, 3, 2}, ++ {3, 1, 1}, ++ {1, 1, 1}, ++ {1, 2, 1}, ++ {1, 2, 2}, ++ {2, 1, 1} ++}; ++ ++static void gen_neon_ldst_base_update(DisasContext *s, int rm, int rn, ++ int stride) ++{ ++ if (rm != 15) { ++ TCGv_i32 base; ++ ++ base = load_reg(s, rn); ++ if (rm == 13) { ++ tcg_gen_addi_i32(base, base, stride); ++ } else { ++ TCGv_i32 index; ++ index = load_reg(s, rm); ++ tcg_gen_add_i32(base, base, index); ++ tcg_temp_free_i32(index); ++ } ++ store_reg(s, rn, base); ++ } ++} ++ ++static bool trans_VLDST_multiple(DisasContext *s, arg_VLDST_multiple *a) ++{ ++ /* Neon load/store multiple structures */ ++ int nregs, interleave, spacing, reg, n; ++ MemOp endian = s->be_data; ++ int mmu_idx = get_mem_index(s); ++ int size = a->size; ++ TCGv_i64 tmp64; ++ TCGv_i32 addr, tmp; ++ ++ if (!arm_dc_feature(s, ARM_FEATURE_NEON)) { ++ return false; ++ } ++ ++ /* UNDEF accesses to D16-D31 if they don't exist */ ++ if (!dc_isar_feature(aa32_simd_r32, s) && (a->vd & 0x10)) { ++ return false; ++ } ++ if (a->itype > 10) { ++ return false; ++ } ++ /* Catch UNDEF cases for bad values of align field */ ++ switch (a->itype & 0xc) { ++ case 4: ++ if (a->align >= 2) { ++ return false; ++ } ++ break; ++ case 8: ++ if (a->align == 3) { ++ return false; ++ } ++ break; ++ default: ++ break; ++ } ++ nregs = neon_ls_element_type[a->itype].nregs; ++ interleave = neon_ls_element_type[a->itype].interleave; ++ spacing = neon_ls_element_type[a->itype].spacing; ++ if (size == 3 && (interleave | spacing) != 1) { ++ return false; ++ } ++ ++ if (!vfp_access_check(s)) { ++ return true; ++ } ++ ++ /* For our purposes, bytes are always little-endian. */ ++ if (size == 0) { ++ endian = MO_LE; ++ } ++ /* ++ * Consecutive little-endian elements from a single register ++ * can be promoted to a larger little-endian operation. ++ */ ++ if (interleave == 1 && endian == MO_LE) { ++ size = 3; ++ } ++ tmp64 = tcg_temp_new_i64(); ++ addr = tcg_temp_new_i32(); ++ tmp = tcg_const_i32(1 << size); ++ load_reg_var(s, addr, a->rn); ++ for (reg = 0; reg < nregs; reg++) { ++ for (n = 0; n < 8 >> size; n++) { ++ int xs; ++ for (xs = 0; xs < interleave; xs++) { ++ int tt = a->vd + reg + spacing * xs; ++ ++ if (a->l) { ++ gen_aa32_ld_i64(s, tmp64, addr, mmu_idx, endian | size); ++ neon_store_element64(tt, n, size, tmp64); ++ } else { ++ neon_load_element64(tmp64, tt, n, size); ++ gen_aa32_st_i64(s, tmp64, addr, mmu_idx, endian | size); ++ } ++ tcg_gen_add_i32(addr, addr, tmp); ++ } ++ } ++ } ++ tcg_temp_free_i32(addr); ++ tcg_temp_free_i32(tmp); ++ tcg_temp_free_i64(tmp64); ++ ++ gen_neon_ldst_base_update(s, a->rm, a->rn, nregs * interleave * 8); ++ return true; ++} +diff --git a/target/arm/translate.c b/target/arm/translate.c +index e269642a48..be56cbb061 100644 +--- a/target/arm/translate.c ++++ b/target/arm/translate.c +@@ -3214,45 +3214,19 @@ static void gen_neon_trn_u16(TCGv_i32 t0, TCGv_i32 t1) + } + + +-static struct { +- int nregs; +- int interleave; +- int spacing; +-} const neon_ls_element_type[11] = { +- {1, 4, 1}, +- {1, 4, 2}, +- {4, 1, 1}, +- {2, 2, 2}, +- {1, 3, 1}, +- {1, 3, 2}, +- {3, 1, 1}, +- {1, 1, 1}, +- {1, 2, 1}, +- {1, 2, 2}, +- {2, 1, 1} +-}; +- + /* Translate a NEON load/store element instruction. Return nonzero if the + instruction is invalid. */ + static int disas_neon_ls_insn(DisasContext *s, uint32_t insn) + { + int rd, rn, rm; +- int op; + int nregs; +- int interleave; +- int spacing; + int stride; + int size; + int reg; + int load; +- int n; + int vec_size; +- int mmu_idx; +- MemOp endian; + TCGv_i32 addr; + TCGv_i32 tmp; +- TCGv_i32 tmp2; +- TCGv_i64 tmp64; + + if (!arm_dc_feature(s, ARM_FEATURE_NEON)) { + return 1; +@@ -3274,70 +3248,9 @@ static int disas_neon_ls_insn(DisasContext *s, uint32_t insn) + rn = (insn >> 16) & 0xf; + rm = insn & 0xf; + load = (insn & (1 << 21)) != 0; +- endian = s->be_data; +- mmu_idx = get_mem_index(s); + if ((insn & (1 << 23)) == 0) { +- /* Load store all elements. */ +- op = (insn >> 8) & 0xf; +- size = (insn >> 6) & 3; +- if (op > 10) +- return 1; +- /* Catch UNDEF cases for bad values of align field */ +- switch (op & 0xc) { +- case 4: +- if (((insn >> 5) & 1) == 1) { +- return 1; +- } +- break; +- case 8: +- if (((insn >> 4) & 3) == 3) { +- return 1; +- } +- break; +- default: +- break; +- } +- nregs = neon_ls_element_type[op].nregs; +- interleave = neon_ls_element_type[op].interleave; +- spacing = neon_ls_element_type[op].spacing; +- if (size == 3 && (interleave | spacing) != 1) { +- return 1; +- } +- /* For our purposes, bytes are always little-endian. */ +- if (size == 0) { +- endian = MO_LE; +- } +- /* Consecutive little-endian elements from a single register +- * can be promoted to a larger little-endian operation. +- */ +- if (interleave == 1 && endian == MO_LE) { +- size = 3; +- } +- tmp64 = tcg_temp_new_i64(); +- addr = tcg_temp_new_i32(); +- tmp2 = tcg_const_i32(1 << size); +- load_reg_var(s, addr, rn); +- for (reg = 0; reg < nregs; reg++) { +- for (n = 0; n < 8 >> size; n++) { +- int xs; +- for (xs = 0; xs < interleave; xs++) { +- int tt = rd + reg + spacing * xs; +- +- if (load) { +- gen_aa32_ld_i64(s, tmp64, addr, mmu_idx, endian | size); +- neon_store_element64(tt, n, size, tmp64); +- } else { +- neon_load_element64(tmp64, tt, n, size); +- gen_aa32_st_i64(s, tmp64, addr, mmu_idx, endian | size); +- } +- tcg_gen_add_i32(addr, addr, tmp2); +- } +- } +- } +- tcg_temp_free_i32(addr); +- tcg_temp_free_i32(tmp2); +- tcg_temp_free_i64(tmp64); +- stride = nregs * interleave * 8; ++ /* Load store all elements -- handled already by decodetree */ ++ return 1; + } else { + size = (insn >> 10) & 3; + if (size == 3) { +-- +2.23.0 + diff --git a/target-arm-Convert-Neon-load-store-single-structure-.patch b/target-arm-Convert-Neon-load-store-single-structure-.patch new file mode 100644 index 0000000000000000000000000000000000000000..1838cc9e6a594fdeb70cda9b2edce74b230ca708 --- /dev/null +++ b/target-arm-Convert-Neon-load-store-single-structure-.patch @@ -0,0 +1,319 @@ +From 123ce4e3daba26b760b472687e1fb1ad82cf1993 Mon Sep 17 00:00:00 2001 +From: Peter Maydell +Date: Thu, 30 Apr 2020 19:09:40 +0100 +Subject: [PATCH 180/709] target/arm: Convert Neon 'load/store single + structure' to decodetree + +Convert the Neon "load/store single structure to one lane" insns to +decodetree. + +As this is the last set of insns in the neon load/store group, +we can remove the whole disas_neon_ls_insn() function. + +Signed-off-by: Peter Maydell +Reviewed-by: Richard Henderson +Message-id: 20200430181003.21682-14-peter.maydell@linaro.org +--- + target/arm/neon-ls.decode | 11 +++ + target/arm/translate-neon.inc.c | 89 +++++++++++++++++++ + target/arm/translate.c | 147 -------------------------------- + 3 files changed, 100 insertions(+), 147 deletions(-) + +diff --git a/target/arm/neon-ls.decode b/target/arm/neon-ls.decode +index f0ab6d2c98..c7b03a72e8 100644 +--- a/target/arm/neon-ls.decode ++++ b/target/arm/neon-ls.decode +@@ -39,3 +39,14 @@ VLDST_multiple 1111 0100 0 . l:1 0 rn:4 .... itype:4 size:2 align:2 rm:4 \ + + VLD_all_lanes 1111 0100 1 . 1 0 rn:4 .... 11 n:2 size:2 t:1 a:1 rm:4 \ + vd=%vd_dp ++ ++# Neon load/store single structure to one lane ++%imm1_5_p1 5:1 !function=plus1 ++%imm1_6_p1 6:1 !function=plus1 ++ ++VLDST_single 1111 0100 1 . l:1 0 rn:4 .... 00 n:2 reg_idx:3 align:1 rm:4 \ ++ vd=%vd_dp size=0 stride=1 ++VLDST_single 1111 0100 1 . l:1 0 rn:4 .... 01 n:2 reg_idx:2 align:2 rm:4 \ ++ vd=%vd_dp size=1 stride=%imm1_5_p1 ++VLDST_single 1111 0100 1 . l:1 0 rn:4 .... 10 n:2 reg_idx:1 align:3 rm:4 \ ++ vd=%vd_dp size=2 stride=%imm1_6_p1 +diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c +index e60e9559ba..c881d1cf60 100644 +--- a/target/arm/translate-neon.inc.c ++++ b/target/arm/translate-neon.inc.c +@@ -26,6 +26,11 @@ + * It might be possible to convert it to a standalone .c file eventually. + */ + ++static inline int plus1(DisasContext *s, int x) ++{ ++ return x + 1; ++} ++ + /* Include the generated Neon decoder */ + #include "decode-neon-dp.inc.c" + #include "decode-neon-ls.inc.c" +@@ -471,3 +476,87 @@ static bool trans_VLD_all_lanes(DisasContext *s, arg_VLD_all_lanes *a) + + return true; + } ++ ++static bool trans_VLDST_single(DisasContext *s, arg_VLDST_single *a) ++{ ++ /* Neon load/store single structure to one lane */ ++ int reg; ++ int nregs = a->n + 1; ++ int vd = a->vd; ++ TCGv_i32 addr, tmp; ++ ++ if (!arm_dc_feature(s, ARM_FEATURE_NEON)) { ++ return false; ++ } ++ ++ /* UNDEF accesses to D16-D31 if they don't exist */ ++ if (!dc_isar_feature(aa32_simd_r32, s) && (a->vd & 0x10)) { ++ return false; ++ } ++ ++ /* Catch the UNDEF cases. This is unavoidably a bit messy. */ ++ switch (nregs) { ++ case 1: ++ if (((a->align & (1 << a->size)) != 0) || ++ (a->size == 2 && ((a->align & 3) == 1 || (a->align & 3) == 2))) { ++ return false; ++ } ++ break; ++ case 3: ++ if ((a->align & 1) != 0) { ++ return false; ++ } ++ /* fall through */ ++ case 2: ++ if (a->size == 2 && (a->align & 2) != 0) { ++ return false; ++ } ++ break; ++ case 4: ++ if ((a->size == 2) && ((a->align & 3) == 3)) { ++ return false; ++ } ++ break; ++ default: ++ abort(); ++ } ++ if ((vd + a->stride * (nregs - 1)) > 31) { ++ /* ++ * Attempts to write off the end of the register file are ++ * UNPREDICTABLE; we choose to UNDEF because otherwise we would ++ * access off the end of the array that holds the register data. ++ */ ++ return false; ++ } ++ ++ if (!vfp_access_check(s)) { ++ return true; ++ } ++ ++ tmp = tcg_temp_new_i32(); ++ addr = tcg_temp_new_i32(); ++ load_reg_var(s, addr, a->rn); ++ /* ++ * TODO: if we implemented alignment exceptions, we should check ++ * addr against the alignment encoded in a->align here. ++ */ ++ for (reg = 0; reg < nregs; reg++) { ++ if (a->l) { ++ gen_aa32_ld_i32(s, tmp, addr, get_mem_index(s), ++ s->be_data | a->size); ++ neon_store_element(vd, a->reg_idx, a->size, tmp); ++ } else { /* Store */ ++ neon_load_element(tmp, vd, a->reg_idx, a->size); ++ gen_aa32_st_i32(s, tmp, addr, get_mem_index(s), ++ s->be_data | a->size); ++ } ++ vd += a->stride; ++ tcg_gen_addi_i32(addr, addr, 1 << a->size); ++ } ++ tcg_temp_free_i32(addr); ++ tcg_temp_free_i32(tmp); ++ ++ gen_neon_ldst_base_update(s, a->rm, a->rn, (1 << a->size) * nregs); ++ ++ return true; ++} +diff --git a/target/arm/translate.c b/target/arm/translate.c +index 7099274c92..613be39ef3 100644 +--- a/target/arm/translate.c ++++ b/target/arm/translate.c +@@ -3213,140 +3213,6 @@ static void gen_neon_trn_u16(TCGv_i32 t0, TCGv_i32 t1) + tcg_temp_free_i32(rd); + } + +- +-/* Translate a NEON load/store element instruction. Return nonzero if the +- instruction is invalid. */ +-static int disas_neon_ls_insn(DisasContext *s, uint32_t insn) +-{ +- int rd, rn, rm; +- int nregs; +- int stride; +- int size; +- int reg; +- int load; +- TCGv_i32 addr; +- TCGv_i32 tmp; +- +- if (!arm_dc_feature(s, ARM_FEATURE_NEON)) { +- return 1; +- } +- +- /* FIXME: this access check should not take precedence over UNDEF +- * for invalid encodings; we will generate incorrect syndrome information +- * for attempts to execute invalid vfp/neon encodings with FP disabled. +- */ +- if (s->fp_excp_el) { +- gen_exception_insn(s, s->pc_curr, EXCP_UDEF, +- syn_simd_access_trap(1, 0xe, false), s->fp_excp_el); +- return 0; +- } +- +- if (!s->vfp_enabled) +- return 1; +- VFP_DREG_D(rd, insn); +- rn = (insn >> 16) & 0xf; +- rm = insn & 0xf; +- load = (insn & (1 << 21)) != 0; +- if ((insn & (1 << 23)) == 0) { +- /* Load store all elements -- handled already by decodetree */ +- return 1; +- } else { +- size = (insn >> 10) & 3; +- if (size == 3) { +- /* Load single element to all lanes -- handled by decodetree */ +- return 1; +- } else { +- /* Single element. */ +- int idx = (insn >> 4) & 0xf; +- int reg_idx; +- switch (size) { +- case 0: +- reg_idx = (insn >> 5) & 7; +- stride = 1; +- break; +- case 1: +- reg_idx = (insn >> 6) & 3; +- stride = (insn & (1 << 5)) ? 2 : 1; +- break; +- case 2: +- reg_idx = (insn >> 7) & 1; +- stride = (insn & (1 << 6)) ? 2 : 1; +- break; +- default: +- abort(); +- } +- nregs = ((insn >> 8) & 3) + 1; +- /* Catch the UNDEF cases. This is unavoidably a bit messy. */ +- switch (nregs) { +- case 1: +- if (((idx & (1 << size)) != 0) || +- (size == 2 && ((idx & 3) == 1 || (idx & 3) == 2))) { +- return 1; +- } +- break; +- case 3: +- if ((idx & 1) != 0) { +- return 1; +- } +- /* fall through */ +- case 2: +- if (size == 2 && (idx & 2) != 0) { +- return 1; +- } +- break; +- case 4: +- if ((size == 2) && ((idx & 3) == 3)) { +- return 1; +- } +- break; +- default: +- abort(); +- } +- if ((rd + stride * (nregs - 1)) > 31) { +- /* Attempts to write off the end of the register file +- * are UNPREDICTABLE; we choose to UNDEF because otherwise +- * the neon_load_reg() would write off the end of the array. +- */ +- return 1; +- } +- tmp = tcg_temp_new_i32(); +- addr = tcg_temp_new_i32(); +- load_reg_var(s, addr, rn); +- for (reg = 0; reg < nregs; reg++) { +- if (load) { +- gen_aa32_ld_i32(s, tmp, addr, get_mem_index(s), +- s->be_data | size); +- neon_store_element(rd, reg_idx, size, tmp); +- } else { /* Store */ +- neon_load_element(tmp, rd, reg_idx, size); +- gen_aa32_st_i32(s, tmp, addr, get_mem_index(s), +- s->be_data | size); +- } +- rd += stride; +- tcg_gen_addi_i32(addr, addr, 1 << size); +- } +- tcg_temp_free_i32(addr); +- tcg_temp_free_i32(tmp); +- stride = nregs * (1 << size); +- } +- } +- if (rm != 15) { +- TCGv_i32 base; +- +- base = load_reg(s, rn); +- if (rm == 13) { +- tcg_gen_addi_i32(base, base, stride); +- } else { +- TCGv_i32 index; +- index = load_reg(s, rm); +- tcg_gen_add_i32(base, base, index); +- tcg_temp_free_i32(index); +- } +- store_reg(s, rn, base); +- } +- return 0; +-} +- + static inline void gen_neon_narrow(int size, TCGv_i32 dest, TCGv_i64 src) + { + switch (size) { +@@ -10596,13 +10462,6 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn) + } + return; + } +- if ((insn & 0x0f100000) == 0x04000000) { +- /* NEON load/store. */ +- if (disas_neon_ls_insn(s, insn)) { +- goto illegal_op; +- } +- return; +- } + if ((insn & 0x0e000f00) == 0x0c000100) { + if (arm_dc_feature(s, ARM_FEATURE_IWMMXT)) { + /* iWMMXt register transfer. */ +@@ -10807,12 +10666,6 @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn) + } + break; + case 12: +- if ((insn & 0x01100000) == 0x01000000) { +- if (disas_neon_ls_insn(s, insn)) { +- goto illegal_op; +- } +- break; +- } + goto illegal_op; + default: + illegal_op: +-- +2.23.0 + diff --git a/target-arm-Convert-V-US-DOT-scalar-to-decodetree.patch b/target-arm-Convert-V-US-DOT-scalar-to-decodetree.patch new file mode 100644 index 0000000000000000000000000000000000000000..b11c0a5820d5a41fc63c0072aff419893397ee11 --- /dev/null +++ b/target-arm-Convert-V-US-DOT-scalar-to-decodetree.patch @@ -0,0 +1,98 @@ +From 35f5d4d1747558c6af2d914bcd848dcc30c3b531 Mon Sep 17 00:00:00 2001 +From: Peter Maydell +Date: Thu, 30 Apr 2020 19:09:36 +0100 +Subject: [PATCH 176/709] target/arm: Convert V[US]DOT (scalar) to decodetree + +Convert the V[US]DOT (scalar) insns in the 2reg-scalar-ext group +to decodetree. + +Signed-off-by: Peter Maydell +Reviewed-by: Richard Henderson +Message-id: 20200430181003.21682-10-peter.maydell@linaro.org +--- + target/arm/neon-shared.decode | 3 +++ + target/arm/translate-neon.inc.c | 35 +++++++++++++++++++++++++++++++++ + target/arm/translate.c | 13 +----------- + 3 files changed, 39 insertions(+), 12 deletions(-) + +diff --git a/target/arm/neon-shared.decode b/target/arm/neon-shared.decode +index c11d755ed1..63a46c63c0 100644 +--- a/target/arm/neon-shared.decode ++++ b/target/arm/neon-shared.decode +@@ -54,3 +54,6 @@ VCMLA_scalar 1111 1110 0 . rot:2 .... .... 1000 . q:1 index:1 0 vm:4 \ + vn=%vn_dp vd=%vd_dp size=0 + VCMLA_scalar 1111 1110 1 . rot:2 .... .... 1000 . q:1 . 0 .... \ + vm=%vm_dp vn=%vn_dp vd=%vd_dp size=1 index=0 ++ ++VDOT_scalar 1111 1110 0 . 10 .... .... 1101 . q:1 index:1 u:1 rm:4 \ ++ vm=%vm_dp vn=%vn_dp vd=%vd_dp +diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c +index 92eccbf823..7cc6ccb069 100644 +--- a/target/arm/translate-neon.inc.c ++++ b/target/arm/translate-neon.inc.c +@@ -207,3 +207,38 @@ static bool trans_VCMLA_scalar(DisasContext *s, arg_VCMLA_scalar *a) + tcg_temp_free_ptr(fpst); + return true; + } ++ ++static bool trans_VDOT_scalar(DisasContext *s, arg_VDOT_scalar *a) ++{ ++ gen_helper_gvec_3 *fn_gvec; ++ int opr_sz; ++ TCGv_ptr fpst; ++ ++ if (!dc_isar_feature(aa32_dp, s)) { ++ return false; ++ } ++ ++ /* UNDEF accesses to D16-D31 if they don't exist. */ ++ if (!dc_isar_feature(aa32_simd_r32, s) && ++ ((a->vd | a->vn) & 0x10)) { ++ return false; ++ } ++ ++ if ((a->vd | a->vn) & a->q) { ++ return false; ++ } ++ ++ if (!vfp_access_check(s)) { ++ return true; ++ } ++ ++ fn_gvec = a->u ? gen_helper_gvec_udot_idx_b : gen_helper_gvec_sdot_idx_b; ++ opr_sz = (1 + a->q) * 8; ++ fpst = get_fpstatus_ptr(1); ++ tcg_gen_gvec_3_ool(vfp_reg_offset(1, a->vd), ++ vfp_reg_offset(1, a->vn), ++ vfp_reg_offset(1, a->rm), ++ opr_sz, opr_sz, a->index, fn_gvec); ++ tcg_temp_free_ptr(fpst); ++ return true; ++} +diff --git a/target/arm/translate.c b/target/arm/translate.c +index 4cb8c6d55b..8574d0964f 100644 +--- a/target/arm/translate.c ++++ b/target/arm/translate.c +@@ -7049,18 +7049,7 @@ static int disas_neon_insn_2reg_scalar_ext(DisasContext *s, uint32_t insn) + bool is_long = false, q = extract32(insn, 6, 1); + bool ptr_is_env = false; + +- if ((insn & 0xffb00f00) == 0xfe200d00) { +- /* V[US]DOT -- 1111 1110 0.10 .... .... 1101 .Q.U .... */ +- int u = extract32(insn, 4, 1); +- +- if (!dc_isar_feature(aa32_dp, s)) { +- return 1; +- } +- fn_gvec = u ? gen_helper_gvec_udot_idx_b : gen_helper_gvec_sdot_idx_b; +- /* rm is just Vm, and index is M. */ +- data = extract32(insn, 5, 1); /* index */ +- rm = extract32(insn, 0, 4); +- } else if ((insn & 0xffa00f10) == 0xfe000810) { ++ if ((insn & 0xffa00f10) == 0xfe000810) { + /* VFM[AS]L -- 1111 1110 0.0S .... .... 1000 .Q.1 .... */ + int is_s = extract32(insn, 20, 1); + int vm20 = extract32(insn, 0, 3); +-- +2.23.0 + diff --git a/target-arm-Convert-V-US-DOT-vector-to-decodetree.patch b/target-arm-Convert-V-US-DOT-vector-to-decodetree.patch new file mode 100644 index 0000000000000000000000000000000000000000..ebaff171477db061d3cdd70a1d3d309d5b0dc32a --- /dev/null +++ b/target-arm-Convert-V-US-DOT-vector-to-decodetree.patch @@ -0,0 +1,91 @@ +From 32da0e330d3e5218b669079826496751fb52c1ca Mon Sep 17 00:00:00 2001 +From: Peter Maydell +Date: Thu, 30 Apr 2020 19:09:33 +0100 +Subject: [PATCH 173/709] target/arm: Convert V[US]DOT (vector) to decodetree + +Convert the V[US]DOT (vector) insns to decodetree. + +Signed-off-by: Peter Maydell +Reviewed-by: Richard Henderson +Message-id: 20200430181003.21682-7-peter.maydell@linaro.org +--- + target/arm/neon-shared.decode | 4 ++++ + target/arm/translate-neon.inc.c | 32 ++++++++++++++++++++++++++++++++ + target/arm/translate.c | 9 +-------- + 3 files changed, 37 insertions(+), 8 deletions(-) + +diff --git a/target/arm/neon-shared.decode b/target/arm/neon-shared.decode +index ed65dae180..c9c641905d 100644 +--- a/target/arm/neon-shared.decode ++++ b/target/arm/neon-shared.decode +@@ -39,3 +39,7 @@ VCMLA 1111 110 rot:2 . 1 size:1 .... .... 1000 . q:1 . 0 .... \ + + VCADD 1111 110 rot:1 1 . 0 size:1 .... .... 1000 . q:1 . 0 .... \ + vm=%vm_dp vn=%vn_dp vd=%vd_dp ++ ++# VUDOT and VSDOT ++VDOT 1111 110 00 . 10 .... .... 1101 . q:1 . u:1 .... \ ++ vm=%vm_dp vn=%vn_dp vd=%vd_dp +diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c +index 28011e88d9..6537506c5b 100644 +--- a/target/arm/translate-neon.inc.c ++++ b/target/arm/translate-neon.inc.c +@@ -104,3 +104,35 @@ static bool trans_VCADD(DisasContext *s, arg_VCADD *a) + tcg_temp_free_ptr(fpst); + return true; + } ++ ++static bool trans_VDOT(DisasContext *s, arg_VDOT *a) ++{ ++ int opr_sz; ++ gen_helper_gvec_3 *fn_gvec; ++ ++ if (!dc_isar_feature(aa32_dp, s)) { ++ return false; ++ } ++ ++ /* UNDEF accesses to D16-D31 if they don't exist. */ ++ if (!dc_isar_feature(aa32_simd_r32, s) && ++ ((a->vd | a->vn | a->vm) & 0x10)) { ++ return false; ++ } ++ ++ if ((a->vn | a->vm | a->vd) & a->q) { ++ return false; ++ } ++ ++ if (!vfp_access_check(s)) { ++ return true; ++ } ++ ++ opr_sz = (1 + a->q) * 8; ++ fn_gvec = a->u ? gen_helper_gvec_udot_b : gen_helper_gvec_sdot_b; ++ tcg_gen_gvec_3_ool(vfp_reg_offset(1, a->vd), ++ vfp_reg_offset(1, a->vn), ++ vfp_reg_offset(1, a->vm), ++ opr_sz, opr_sz, 0, fn_gvec); ++ return true; ++} +diff --git a/target/arm/translate.c b/target/arm/translate.c +index 993bead82f..7d3aea8c98 100644 +--- a/target/arm/translate.c ++++ b/target/arm/translate.c +@@ -7048,14 +7048,7 @@ static int disas_neon_insn_3same_ext(DisasContext *s, uint32_t insn) + bool is_long = false, q = extract32(insn, 6, 1); + bool ptr_is_env = false; + +- if ((insn & 0xfeb00f00) == 0xfc200d00) { +- /* V[US]DOT -- 1111 1100 0.10 .... .... 1101 .Q.U .... */ +- bool u = extract32(insn, 4, 1); +- if (!dc_isar_feature(aa32_dp, s)) { +- return 1; +- } +- fn_gvec = u ? gen_helper_gvec_udot_b : gen_helper_gvec_sdot_b; +- } else if ((insn & 0xff300f10) == 0xfc200810) { ++ if ((insn & 0xff300f10) == 0xfc200810) { + /* VFM[AS]L -- 1111 1100 S.10 .... .... 1000 .Q.1 .... */ + int is_s = extract32(insn, 23, 1); + if (!dc_isar_feature(aa32_fhm, s)) { +-- +2.23.0 + diff --git a/target-arm-Convert-VCADD-vector-to-decodetree.patch b/target-arm-Convert-VCADD-vector-to-decodetree.patch new file mode 100644 index 0000000000000000000000000000000000000000..6653b8f5416b8ade185bc42e1d55595130f76f2e --- /dev/null +++ b/target-arm-Convert-VCADD-vector-to-decodetree.patch @@ -0,0 +1,97 @@ +From 94d5eb7b3f72fbbdee55d7908e9cb6de95949f4b Mon Sep 17 00:00:00 2001 +From: Peter Maydell +Date: Thu, 30 Apr 2020 19:09:32 +0100 +Subject: [PATCH 172/709] target/arm: Convert VCADD (vector) to decodetree + +Convert the VCADD (vector) insns to decodetree. + +Signed-off-by: Peter Maydell +Reviewed-by: Richard Henderson +Message-id: 20200430181003.21682-6-peter.maydell@linaro.org +--- + target/arm/neon-shared.decode | 3 +++ + target/arm/translate-neon.inc.c | 37 +++++++++++++++++++++++++++++++++ + target/arm/translate.c | 11 +--------- + 3 files changed, 41 insertions(+), 10 deletions(-) + +diff --git a/target/arm/neon-shared.decode b/target/arm/neon-shared.decode +index d1d707a56d..ed65dae180 100644 +--- a/target/arm/neon-shared.decode ++++ b/target/arm/neon-shared.decode +@@ -36,3 +36,6 @@ + + VCMLA 1111 110 rot:2 . 1 size:1 .... .... 1000 . q:1 . 0 .... \ + vm=%vm_dp vn=%vn_dp vd=%vd_dp ++ ++VCADD 1111 110 rot:1 1 . 0 size:1 .... .... 1000 . q:1 . 0 .... \ ++ vm=%vm_dp vn=%vn_dp vd=%vd_dp +diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c +index 0baae1338a..28011e88d9 100644 +--- a/target/arm/translate-neon.inc.c ++++ b/target/arm/translate-neon.inc.c +@@ -67,3 +67,40 @@ static bool trans_VCMLA(DisasContext *s, arg_VCMLA *a) + tcg_temp_free_ptr(fpst); + return true; + } ++ ++static bool trans_VCADD(DisasContext *s, arg_VCADD *a) ++{ ++ int opr_sz; ++ TCGv_ptr fpst; ++ gen_helper_gvec_3_ptr *fn_gvec_ptr; ++ ++ if (!dc_isar_feature(aa32_vcma, s) ++ || (!a->size && !dc_isar_feature(aa32_fp16_arith, s))) { ++ return false; ++ } ++ ++ /* UNDEF accesses to D16-D31 if they don't exist. */ ++ if (!dc_isar_feature(aa32_simd_r32, s) && ++ ((a->vd | a->vn | a->vm) & 0x10)) { ++ return false; ++ } ++ ++ if ((a->vn | a->vm | a->vd) & a->q) { ++ return false; ++ } ++ ++ if (!vfp_access_check(s)) { ++ return true; ++ } ++ ++ opr_sz = (1 + a->q) * 8; ++ fpst = get_fpstatus_ptr(1); ++ fn_gvec_ptr = a->size ? gen_helper_gvec_fcadds : gen_helper_gvec_fcaddh; ++ tcg_gen_gvec_3_ptr(vfp_reg_offset(1, a->vd), ++ vfp_reg_offset(1, a->vn), ++ vfp_reg_offset(1, a->vm), ++ fpst, opr_sz, opr_sz, a->rot, ++ fn_gvec_ptr); ++ tcg_temp_free_ptr(fpst); ++ return true; ++} +diff --git a/target/arm/translate.c b/target/arm/translate.c +index ae6799c6ae..993bead82f 100644 +--- a/target/arm/translate.c ++++ b/target/arm/translate.c +@@ -7048,16 +7048,7 @@ static int disas_neon_insn_3same_ext(DisasContext *s, uint32_t insn) + bool is_long = false, q = extract32(insn, 6, 1); + bool ptr_is_env = false; + +- if ((insn & 0xfea00f10) == 0xfc800800) { +- /* VCADD -- 1111 110R 1.0S .... .... 1000 ...0 .... */ +- int size = extract32(insn, 20, 1); +- data = extract32(insn, 24, 1); /* rot */ +- if (!dc_isar_feature(aa32_vcma, s) +- || (!size && !dc_isar_feature(aa32_fp16_arith, s))) { +- return 1; +- } +- fn_gvec_ptr = size ? gen_helper_gvec_fcadds : gen_helper_gvec_fcaddh; +- } else if ((insn & 0xfeb00f00) == 0xfc200d00) { ++ if ((insn & 0xfeb00f00) == 0xfc200d00) { + /* V[US]DOT -- 1111 1100 0.10 .... .... 1101 .Q.U .... */ + bool u = extract32(insn, 4, 1); + if (!dc_isar_feature(aa32_dp, s)) { +-- +2.23.0 + diff --git a/target-arm-Convert-VCMLA-scalar-to-decodetree.patch b/target-arm-Convert-VCMLA-scalar-to-decodetree.patch new file mode 100644 index 0000000000000000000000000000000000000000..f81b54e78cc48d0ba9980a0c0627e7881dc728e9 --- /dev/null +++ b/target-arm-Convert-VCMLA-scalar-to-decodetree.patch @@ -0,0 +1,117 @@ +From 7e1b5d615361bb0038cda0e08af41e350e42d081 Mon Sep 17 00:00:00 2001 +From: Peter Maydell +Date: Thu, 30 Apr 2020 19:09:35 +0100 +Subject: [PATCH 175/709] target/arm: Convert VCMLA (scalar) to decodetree + +Convert VCMLA (scalar) in the 2reg-scalar-ext group to decodetree. + +Signed-off-by: Peter Maydell +Reviewed-by: Richard Henderson +Message-id: 20200430181003.21682-9-peter.maydell@linaro.org +--- + target/arm/neon-shared.decode | 5 +++++ + target/arm/translate-neon.inc.c | 40 +++++++++++++++++++++++++++++++++ + target/arm/translate.c | 26 +-------------------- + 3 files changed, 46 insertions(+), 25 deletions(-) + +diff --git a/target/arm/neon-shared.decode b/target/arm/neon-shared.decode +index 90cd5c871e..c11d755ed1 100644 +--- a/target/arm/neon-shared.decode ++++ b/target/arm/neon-shared.decode +@@ -49,3 +49,8 @@ VFML 1111 110 0 s:1 . 10 .... .... 1000 . 0 . 1 .... \ + vm=%vm_sp vn=%vn_sp vd=%vd_dp q=0 + VFML 1111 110 0 s:1 . 10 .... .... 1000 . 1 . 1 .... \ + vm=%vm_dp vn=%vn_dp vd=%vd_dp q=1 ++ ++VCMLA_scalar 1111 1110 0 . rot:2 .... .... 1000 . q:1 index:1 0 vm:4 \ ++ vn=%vn_dp vd=%vd_dp size=0 ++VCMLA_scalar 1111 1110 1 . rot:2 .... .... 1000 . q:1 . 0 .... \ ++ vm=%vm_dp vn=%vn_dp vd=%vd_dp size=1 index=0 +diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c +index 6c58abc54b..92eccbf823 100644 +--- a/target/arm/translate-neon.inc.c ++++ b/target/arm/translate-neon.inc.c +@@ -167,3 +167,43 @@ static bool trans_VFML(DisasContext *s, arg_VFML *a) + gen_helper_gvec_fmlal_a32); + return true; + } ++ ++static bool trans_VCMLA_scalar(DisasContext *s, arg_VCMLA_scalar *a) ++{ ++ gen_helper_gvec_3_ptr *fn_gvec_ptr; ++ int opr_sz; ++ TCGv_ptr fpst; ++ ++ if (!dc_isar_feature(aa32_vcma, s)) { ++ return false; ++ } ++ if (a->size == 0 && !dc_isar_feature(aa32_fp16_arith, s)) { ++ return false; ++ } ++ ++ /* UNDEF accesses to D16-D31 if they don't exist. */ ++ if (!dc_isar_feature(aa32_simd_r32, s) && ++ ((a->vd | a->vn | a->vm) & 0x10)) { ++ return false; ++ } ++ ++ if ((a->vd | a->vn) & a->q) { ++ return false; ++ } ++ ++ if (!vfp_access_check(s)) { ++ return true; ++ } ++ ++ fn_gvec_ptr = (a->size ? gen_helper_gvec_fcmlas_idx ++ : gen_helper_gvec_fcmlah_idx); ++ opr_sz = (1 + a->q) * 8; ++ fpst = get_fpstatus_ptr(1); ++ tcg_gen_gvec_3_ptr(vfp_reg_offset(1, a->vd), ++ vfp_reg_offset(1, a->vn), ++ vfp_reg_offset(1, a->vm), ++ fpst, opr_sz, opr_sz, ++ (a->index << 2) | a->rot, fn_gvec_ptr); ++ tcg_temp_free_ptr(fpst); ++ return true; ++} +diff --git a/target/arm/translate.c b/target/arm/translate.c +index 79cd9138fe..4cb8c6d55b 100644 +--- a/target/arm/translate.c ++++ b/target/arm/translate.c +@@ -7049,31 +7049,7 @@ static int disas_neon_insn_2reg_scalar_ext(DisasContext *s, uint32_t insn) + bool is_long = false, q = extract32(insn, 6, 1); + bool ptr_is_env = false; + +- if ((insn & 0xff000f10) == 0xfe000800) { +- /* VCMLA (indexed) -- 1111 1110 S.RR .... .... 1000 ...0 .... */ +- int rot = extract32(insn, 20, 2); +- int size = extract32(insn, 23, 1); +- int index; +- +- if (!dc_isar_feature(aa32_vcma, s)) { +- return 1; +- } +- if (size == 0) { +- if (!dc_isar_feature(aa32_fp16_arith, s)) { +- return 1; +- } +- /* For fp16, rm is just Vm, and index is M. */ +- rm = extract32(insn, 0, 4); +- index = extract32(insn, 5, 1); +- } else { +- /* For fp32, rm is the usual M:Vm, and index is 0. */ +- VFP_DREG_M(rm, insn); +- index = 0; +- } +- data = (index << 2) | rot; +- fn_gvec_ptr = (size ? gen_helper_gvec_fcmlas_idx +- : gen_helper_gvec_fcmlah_idx); +- } else if ((insn & 0xffb00f00) == 0xfe200d00) { ++ if ((insn & 0xffb00f00) == 0xfe200d00) { + /* V[US]DOT -- 1111 1110 0.10 .... .... 1101 .Q.U .... */ + int u = extract32(insn, 4, 1); + +-- +2.23.0 + diff --git a/target-arm-Convert-VCMLA-vector-to-decodetree.patch b/target-arm-Convert-VCMLA-vector-to-decodetree.patch new file mode 100644 index 0000000000000000000000000000000000000000..899cb1ef3c4e3b255f54c924b1776e9518b7536c --- /dev/null +++ b/target-arm-Convert-VCMLA-vector-to-decodetree.patch @@ -0,0 +1,106 @@ +From afff8de0d4d55b4ce7c36eb9cdfafe477a35dd75 Mon Sep 17 00:00:00 2001 +From: Peter Maydell +Date: Thu, 30 Apr 2020 19:09:31 +0100 +Subject: [PATCH 171/709] target/arm: Convert VCMLA (vector) to decodetree + +Convert the VCMLA (vector) insns in the 3same extension group to +decodetree. + +Signed-off-by: Peter Maydell +Reviewed-by: Richard Henderson +Message-id: 20200430181003.21682-5-peter.maydell@linaro.org +--- + target/arm/neon-shared.decode | 11 ++++++++++ + target/arm/translate-neon.inc.c | 37 +++++++++++++++++++++++++++++++++ + target/arm/translate.c | 11 +--------- + 3 files changed, 49 insertions(+), 10 deletions(-) + +diff --git a/target/arm/neon-shared.decode b/target/arm/neon-shared.decode +index 3aea7c5e18..d1d707a56d 100644 +--- a/target/arm/neon-shared.decode ++++ b/target/arm/neon-shared.decode +@@ -25,3 +25,14 @@ + # More specifically, this covers: + # 2reg scalar ext: 0b1111_1110_xxxx_xxxx_xxxx_1x0x_xxxx_xxxx + # 3same ext: 0b1111_110x_xxxx_xxxx_xxxx_1x0x_xxxx_xxxx ++ ++# VFP/Neon register fields; same as vfp.decode ++%vm_dp 5:1 0:4 ++%vm_sp 0:4 5:1 ++%vn_dp 7:1 16:4 ++%vn_sp 16:4 7:1 ++%vd_dp 22:1 12:4 ++%vd_sp 12:4 22:1 ++ ++VCMLA 1111 110 rot:2 . 1 size:1 .... .... 1000 . q:1 . 0 .... \ ++ vm=%vm_dp vn=%vn_dp vd=%vd_dp +diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c +index a33e81ba3a..0baae1338a 100644 +--- a/target/arm/translate-neon.inc.c ++++ b/target/arm/translate-neon.inc.c +@@ -30,3 +30,40 @@ + #include "decode-neon-dp.inc.c" + #include "decode-neon-ls.inc.c" + #include "decode-neon-shared.inc.c" ++ ++static bool trans_VCMLA(DisasContext *s, arg_VCMLA *a) ++{ ++ int opr_sz; ++ TCGv_ptr fpst; ++ gen_helper_gvec_3_ptr *fn_gvec_ptr; ++ ++ if (!dc_isar_feature(aa32_vcma, s) ++ || (!a->size && !dc_isar_feature(aa32_fp16_arith, s))) { ++ return false; ++ } ++ ++ /* UNDEF accesses to D16-D31 if they don't exist. */ ++ if (!dc_isar_feature(aa32_simd_r32, s) && ++ ((a->vd | a->vn | a->vm) & 0x10)) { ++ return false; ++ } ++ ++ if ((a->vn | a->vm | a->vd) & a->q) { ++ return false; ++ } ++ ++ if (!vfp_access_check(s)) { ++ return true; ++ } ++ ++ opr_sz = (1 + a->q) * 8; ++ fpst = get_fpstatus_ptr(1); ++ fn_gvec_ptr = a->size ? gen_helper_gvec_fcmlas : gen_helper_gvec_fcmlah; ++ tcg_gen_gvec_3_ptr(vfp_reg_offset(1, a->vd), ++ vfp_reg_offset(1, a->vn), ++ vfp_reg_offset(1, a->vm), ++ fpst, opr_sz, opr_sz, a->rot, ++ fn_gvec_ptr); ++ tcg_temp_free_ptr(fpst); ++ return true; ++} +diff --git a/target/arm/translate.c b/target/arm/translate.c +index 5a82a56e8e..ae6799c6ae 100644 +--- a/target/arm/translate.c ++++ b/target/arm/translate.c +@@ -7048,16 +7048,7 @@ static int disas_neon_insn_3same_ext(DisasContext *s, uint32_t insn) + bool is_long = false, q = extract32(insn, 6, 1); + bool ptr_is_env = false; + +- if ((insn & 0xfe200f10) == 0xfc200800) { +- /* VCMLA -- 1111 110R R.1S .... .... 1000 ...0 .... */ +- int size = extract32(insn, 20, 1); +- data = extract32(insn, 23, 2); /* rot */ +- if (!dc_isar_feature(aa32_vcma, s) +- || (!size && !dc_isar_feature(aa32_fp16_arith, s))) { +- return 1; +- } +- fn_gvec_ptr = size ? gen_helper_gvec_fcmlas : gen_helper_gvec_fcmlah; +- } else if ((insn & 0xfea00f10) == 0xfc800800) { ++ if ((insn & 0xfea00f10) == 0xfc800800) { + /* VCADD -- 1111 110R 1.0S .... .... 1000 ...0 .... */ + int size = extract32(insn, 20, 1); + data = extract32(insn, 24, 1); /* rot */ +-- +2.23.0 + diff --git a/target-arm-Convert-VFM-AS-L-scalar-to-decodetree.patch b/target-arm-Convert-VFM-AS-L-scalar-to-decodetree.patch new file mode 100644 index 0000000000000000000000000000000000000000..4fca7a1c6a0a531e8dc3bbe36de0d1efd95d4fcd --- /dev/null +++ b/target-arm-Convert-VFM-AS-L-scalar-to-decodetree.patch @@ -0,0 +1,229 @@ +From d27e82f7d02f35e5919bd9cbbcb157f3537069a0 Mon Sep 17 00:00:00 2001 +From: Peter Maydell +Date: Thu, 30 Apr 2020 19:09:37 +0100 +Subject: [PATCH 177/709] target/arm: Convert VFM[AS]L (scalar) to decodetree + +Convert the VFM[AS]L (scalar) insns in the 2reg-scalar-ext group +to decodetree. These are the last ones in the group so we can remove +all the legacy decode for the group. + +Note that in disas_thumb2_insn() the parts of this encoding space +where the decodetree decoder returns false will correctly be directed +to illegal_op by the "(insn & (1 << 28))" check so they won't fall +into disas_coproc_insn() by mistake. + +Signed-off-by: Peter Maydell +Reviewed-by: Richard Henderson +Message-id: 20200430181003.21682-11-peter.maydell@linaro.org +--- + target/arm/neon-shared.decode | 7 +++ + target/arm/translate-neon.inc.c | 32 ++++++++++ + target/arm/translate.c | 107 +------------------------------- + 3 files changed, 40 insertions(+), 106 deletions(-) + +diff --git a/target/arm/neon-shared.decode b/target/arm/neon-shared.decode +index 63a46c63c0..f297ba8cdf 100644 +--- a/target/arm/neon-shared.decode ++++ b/target/arm/neon-shared.decode +@@ -57,3 +57,10 @@ VCMLA_scalar 1111 1110 1 . rot:2 .... .... 1000 . q:1 . 0 .... \ + + VDOT_scalar 1111 1110 0 . 10 .... .... 1101 . q:1 index:1 u:1 rm:4 \ + vm=%vm_dp vn=%vn_dp vd=%vd_dp ++ ++%vfml_scalar_q0_rm 0:3 5:1 ++%vfml_scalar_q1_index 5:1 3:1 ++VFML_scalar 1111 1110 0 . 0 s:1 .... .... 1000 . 0 . 1 index:1 ... \ ++ rm=%vfml_scalar_q0_rm vn=%vn_sp vd=%vd_dp q=0 ++VFML_scalar 1111 1110 0 . 0 s:1 .... .... 1000 . 1 . 1 . rm:3 \ ++ index=%vfml_scalar_q1_index vn=%vn_dp vd=%vd_dp q=1 +diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c +index 7cc6ccb069..b06542b8b8 100644 +--- a/target/arm/translate-neon.inc.c ++++ b/target/arm/translate-neon.inc.c +@@ -242,3 +242,35 @@ static bool trans_VDOT_scalar(DisasContext *s, arg_VDOT_scalar *a) + tcg_temp_free_ptr(fpst); + return true; + } ++ ++static bool trans_VFML_scalar(DisasContext *s, arg_VFML_scalar *a) ++{ ++ int opr_sz; ++ ++ if (!dc_isar_feature(aa32_fhm, s)) { ++ return false; ++ } ++ ++ /* UNDEF accesses to D16-D31 if they don't exist. */ ++ if (!dc_isar_feature(aa32_simd_r32, s) && ++ ((a->vd & 0x10) || (a->q && (a->vn & 0x10)))) { ++ return false; ++ } ++ ++ if (a->vd & a->q) { ++ return false; ++ } ++ ++ if (!vfp_access_check(s)) { ++ return true; ++ } ++ ++ opr_sz = (1 + a->q) * 8; ++ tcg_gen_gvec_3_ptr(vfp_reg_offset(1, a->vd), ++ vfp_reg_offset(a->q, a->vn), ++ vfp_reg_offset(a->q, a->rm), ++ cpu_env, opr_sz, opr_sz, ++ (a->index << 2) | a->s, /* is_2 == 0 */ ++ gen_helper_gvec_fmlal_idx_a32); ++ return true; ++} +diff --git a/target/arm/translate.c b/target/arm/translate.c +index 8574d0964f..e269642a48 100644 +--- a/target/arm/translate.c ++++ b/target/arm/translate.c +@@ -2610,8 +2610,6 @@ static int disas_dsp_insn(DisasContext *s, uint32_t insn) + } + + #define VFP_REG_SHR(x, n) (((n) > 0) ? (x) >> (n) : (x) << -(n)) +-#define VFP_SREG(insn, bigbit, smallbit) \ +- ((VFP_REG_SHR(insn, bigbit - 1) & 0x1e) | (((insn) >> (smallbit)) & 1)) + #define VFP_DREG(reg, insn, bigbit, smallbit) do { \ + if (dc_isar_feature(aa32_simd_r32, s)) { \ + reg = (((insn) >> (bigbit)) & 0x0f) \ +@@ -2622,11 +2620,8 @@ static int disas_dsp_insn(DisasContext *s, uint32_t insn) + reg = ((insn) >> (bigbit)) & 0x0f; \ + }} while (0) + +-#define VFP_SREG_D(insn) VFP_SREG(insn, 12, 22) + #define VFP_DREG_D(reg, insn) VFP_DREG(reg, insn, 12, 22) +-#define VFP_SREG_N(insn) VFP_SREG(insn, 16, 7) + #define VFP_DREG_N(reg, insn) VFP_DREG(reg, insn, 16, 7) +-#define VFP_SREG_M(insn) VFP_SREG(insn, 0, 5) + #define VFP_DREG_M(reg, insn) VFP_DREG(reg, insn, 0, 5) + + static void gen_neon_dup_low16(TCGv_i32 var) +@@ -7032,94 +7027,6 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn) + return 0; + } + +-/* Advanced SIMD two registers and a scalar extension. +- * 31 24 23 22 20 16 12 11 10 9 8 3 0 +- * +-----------------+----+---+----+----+----+---+----+---+----+---------+----+ +- * | 1 1 1 1 1 1 1 0 | o1 | D | o2 | Vn | Vd | 1 | o3 | 0 | o4 | N Q M U | Vm | +- * +-----------------+----+---+----+----+----+---+----+---+----+---------+----+ +- * +- */ +- +-static int disas_neon_insn_2reg_scalar_ext(DisasContext *s, uint32_t insn) +-{ +- gen_helper_gvec_3 *fn_gvec = NULL; +- gen_helper_gvec_3_ptr *fn_gvec_ptr = NULL; +- int rd, rn, rm, opr_sz, data; +- int off_rn, off_rm; +- bool is_long = false, q = extract32(insn, 6, 1); +- bool ptr_is_env = false; +- +- if ((insn & 0xffa00f10) == 0xfe000810) { +- /* VFM[AS]L -- 1111 1110 0.0S .... .... 1000 .Q.1 .... */ +- int is_s = extract32(insn, 20, 1); +- int vm20 = extract32(insn, 0, 3); +- int vm3 = extract32(insn, 3, 1); +- int m = extract32(insn, 5, 1); +- int index; +- +- if (!dc_isar_feature(aa32_fhm, s)) { +- return 1; +- } +- if (q) { +- rm = vm20; +- index = m * 2 + vm3; +- } else { +- rm = vm20 * 2 + m; +- index = vm3; +- } +- is_long = true; +- data = (index << 2) | is_s; /* is_2 == 0 */ +- fn_gvec_ptr = gen_helper_gvec_fmlal_idx_a32; +- ptr_is_env = true; +- } else { +- return 1; +- } +- +- VFP_DREG_D(rd, insn); +- if (rd & q) { +- return 1; +- } +- if (q || !is_long) { +- VFP_DREG_N(rn, insn); +- if (rn & q & !is_long) { +- return 1; +- } +- off_rn = vfp_reg_offset(1, rn); +- off_rm = vfp_reg_offset(1, rm); +- } else { +- rn = VFP_SREG_N(insn); +- off_rn = vfp_reg_offset(0, rn); +- off_rm = vfp_reg_offset(0, rm); +- } +- if (s->fp_excp_el) { +- gen_exception_insn(s, s->pc_curr, EXCP_UDEF, +- syn_simd_access_trap(1, 0xe, false), s->fp_excp_el); +- return 0; +- } +- if (!s->vfp_enabled) { +- return 1; +- } +- +- opr_sz = (1 + q) * 8; +- if (fn_gvec_ptr) { +- TCGv_ptr ptr; +- if (ptr_is_env) { +- ptr = cpu_env; +- } else { +- ptr = get_fpstatus_ptr(1); +- } +- tcg_gen_gvec_3_ptr(vfp_reg_offset(1, rd), off_rn, off_rm, ptr, +- opr_sz, opr_sz, data, fn_gvec_ptr); +- if (!ptr_is_env) { +- tcg_temp_free_ptr(ptr); +- } +- } else { +- tcg_gen_gvec_3_ool(vfp_reg_offset(1, rd), off_rn, off_rm, +- opr_sz, opr_sz, data, fn_gvec); +- } +- return 0; +-} +- + static int disas_coproc_insn(DisasContext *s, uint32_t insn) + { + int cpnum, is64, crn, crm, opc1, opc2, isread, rt, rt2; +@@ -10843,12 +10750,6 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn) + } + } + } +- } else if ((insn & 0x0f000a00) == 0x0e000800 +- && arm_dc_feature(s, ARM_FEATURE_V8)) { +- if (disas_neon_insn_2reg_scalar_ext(s, insn)) { +- goto illegal_op; +- } +- return; + } + goto illegal_op; + } +@@ -11026,13 +10927,7 @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn) + } + break; + } +- if ((insn & 0xff000a00) == 0xfe000800 +- && arm_dc_feature(s, ARM_FEATURE_V8)) { +- /* The Thumb2 and ARM encodings are identical. */ +- if (disas_neon_insn_2reg_scalar_ext(s, insn)) { +- goto illegal_op; +- } +- } else if (((insn >> 24) & 3) == 3) { ++ if (((insn >> 24) & 3) == 3) { + /* Translate into the equivalent ARM encoding. */ + insn = (insn & 0xe2ffffff) | ((insn & (1 << 28)) >> 4) | (1 << 28); + if (disas_neon_data_insn(s, insn)) { +-- +2.23.0 + diff --git a/target-arm-Convert-VFM-AS-L-vector-to-decodetree.patch b/target-arm-Convert-VFM-AS-L-vector-to-decodetree.patch new file mode 100644 index 0000000000000000000000000000000000000000..beebc6b569a1c8b083fcb4f26f35c8402f899ca6 --- /dev/null +++ b/target-arm-Convert-VFM-AS-L-vector-to-decodetree.patch @@ -0,0 +1,198 @@ +From 9a107e7b8a3c87ab63ec830d3d60f319fc577ff7 Mon Sep 17 00:00:00 2001 +From: Peter Maydell +Date: Thu, 30 Apr 2020 19:09:34 +0100 +Subject: [PATCH 174/709] target/arm: Convert VFM[AS]L (vector) to decodetree + +Convert the VFM[AS]L (vector) insns to decodetree. This is the last +insn in the legacy decoder for the 3same_ext group, so we can +delete the legacy decoder function for the group entirely. + +Note that in disas_thumb2_insn() the parts of this encoding space +where the decodetree decoder returns false will correctly be directed +to illegal_op by the "(insn & (1 << 28))" check so they won't fall +into disas_coproc_insn() by mistake. + +Signed-off-by: Peter Maydell +Reviewed-by: Richard Henderson +Message-id: 20200430181003.21682-8-peter.maydell@linaro.org +--- + target/arm/neon-shared.decode | 6 +++ + target/arm/translate-neon.inc.c | 31 +++++++++++ + target/arm/translate.c | 92 +-------------------------------- + 3 files changed, 38 insertions(+), 91 deletions(-) + +diff --git a/target/arm/neon-shared.decode b/target/arm/neon-shared.decode +index c9c641905d..90cd5c871e 100644 +--- a/target/arm/neon-shared.decode ++++ b/target/arm/neon-shared.decode +@@ -43,3 +43,9 @@ VCADD 1111 110 rot:1 1 . 0 size:1 .... .... 1000 . q:1 . 0 .... \ + # VUDOT and VSDOT + VDOT 1111 110 00 . 10 .... .... 1101 . q:1 . u:1 .... \ + vm=%vm_dp vn=%vn_dp vd=%vd_dp ++ ++# VFM[AS]L ++VFML 1111 110 0 s:1 . 10 .... .... 1000 . 0 . 1 .... \ ++ vm=%vm_sp vn=%vn_sp vd=%vd_dp q=0 ++VFML 1111 110 0 s:1 . 10 .... .... 1000 . 1 . 1 .... \ ++ vm=%vm_dp vn=%vn_dp vd=%vd_dp q=1 +diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c +index 6537506c5b..6c58abc54b 100644 +--- a/target/arm/translate-neon.inc.c ++++ b/target/arm/translate-neon.inc.c +@@ -136,3 +136,34 @@ static bool trans_VDOT(DisasContext *s, arg_VDOT *a) + opr_sz, opr_sz, 0, fn_gvec); + return true; + } ++ ++static bool trans_VFML(DisasContext *s, arg_VFML *a) ++{ ++ int opr_sz; ++ ++ if (!dc_isar_feature(aa32_fhm, s)) { ++ return false; ++ } ++ ++ /* UNDEF accesses to D16-D31 if they don't exist. */ ++ if (!dc_isar_feature(aa32_simd_r32, s) && ++ (a->vd & 0x10)) { ++ return false; ++ } ++ ++ if (a->vd & a->q) { ++ return false; ++ } ++ ++ if (!vfp_access_check(s)) { ++ return true; ++ } ++ ++ opr_sz = (1 + a->q) * 8; ++ tcg_gen_gvec_3_ptr(vfp_reg_offset(1, a->vd), ++ vfp_reg_offset(a->q, a->vn), ++ vfp_reg_offset(a->q, a->vm), ++ cpu_env, opr_sz, opr_sz, a->s, /* is_2 == 0 */ ++ gen_helper_gvec_fmlal_a32); ++ return true; ++} +diff --git a/target/arm/translate.c b/target/arm/translate.c +index 7d3aea8c98..79cd9138fe 100644 +--- a/target/arm/translate.c ++++ b/target/arm/translate.c +@@ -7032,84 +7032,6 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn) + return 0; + } + +-/* Advanced SIMD three registers of the same length extension. +- * 31 25 23 22 20 16 12 11 10 9 8 3 0 +- * +---------------+-----+---+-----+----+----+---+----+---+----+---------+----+ +- * | 1 1 1 1 1 1 0 | op1 | D | op2 | Vn | Vd | 1 | o3 | 0 | o4 | N Q M U | Vm | +- * +---------------+-----+---+-----+----+----+---+----+---+----+---------+----+ +- */ +-static int disas_neon_insn_3same_ext(DisasContext *s, uint32_t insn) +-{ +- gen_helper_gvec_3 *fn_gvec = NULL; +- gen_helper_gvec_3_ptr *fn_gvec_ptr = NULL; +- int rd, rn, rm, opr_sz; +- int data = 0; +- int off_rn, off_rm; +- bool is_long = false, q = extract32(insn, 6, 1); +- bool ptr_is_env = false; +- +- if ((insn & 0xff300f10) == 0xfc200810) { +- /* VFM[AS]L -- 1111 1100 S.10 .... .... 1000 .Q.1 .... */ +- int is_s = extract32(insn, 23, 1); +- if (!dc_isar_feature(aa32_fhm, s)) { +- return 1; +- } +- is_long = true; +- data = is_s; /* is_2 == 0 */ +- fn_gvec_ptr = gen_helper_gvec_fmlal_a32; +- ptr_is_env = true; +- } else { +- return 1; +- } +- +- VFP_DREG_D(rd, insn); +- if (rd & q) { +- return 1; +- } +- if (q || !is_long) { +- VFP_DREG_N(rn, insn); +- VFP_DREG_M(rm, insn); +- if ((rn | rm) & q & !is_long) { +- return 1; +- } +- off_rn = vfp_reg_offset(1, rn); +- off_rm = vfp_reg_offset(1, rm); +- } else { +- rn = VFP_SREG_N(insn); +- rm = VFP_SREG_M(insn); +- off_rn = vfp_reg_offset(0, rn); +- off_rm = vfp_reg_offset(0, rm); +- } +- +- if (s->fp_excp_el) { +- gen_exception_insn(s, s->pc_curr, EXCP_UDEF, +- syn_simd_access_trap(1, 0xe, false), s->fp_excp_el); +- return 0; +- } +- if (!s->vfp_enabled) { +- return 1; +- } +- +- opr_sz = (1 + q) * 8; +- if (fn_gvec_ptr) { +- TCGv_ptr ptr; +- if (ptr_is_env) { +- ptr = cpu_env; +- } else { +- ptr = get_fpstatus_ptr(1); +- } +- tcg_gen_gvec_3_ptr(vfp_reg_offset(1, rd), off_rn, off_rm, ptr, +- opr_sz, opr_sz, data, fn_gvec_ptr); +- if (!ptr_is_env) { +- tcg_temp_free_ptr(ptr); +- } +- } else { +- tcg_gen_gvec_3_ool(vfp_reg_offset(1, rd), off_rn, off_rm, +- opr_sz, opr_sz, data, fn_gvec); +- } +- return 0; +-} +- + /* Advanced SIMD two registers and a scalar extension. + * 31 24 23 22 20 16 12 11 10 9 8 3 0 + * +-----------------+----+---+----+----+----+---+----+---+----+---------+----+ +@@ -10956,12 +10878,6 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn) + } + } + } +- } else if ((insn & 0x0e000a00) == 0x0c000800 +- && arm_dc_feature(s, ARM_FEATURE_V8)) { +- if (disas_neon_insn_3same_ext(s, insn)) { +- goto illegal_op; +- } +- return; + } else if ((insn & 0x0f000a00) == 0x0e000800 + && arm_dc_feature(s, ARM_FEATURE_V8)) { + if (disas_neon_insn_2reg_scalar_ext(s, insn)) { +@@ -11145,15 +11061,9 @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn) + } + break; + } +- if ((insn & 0xfe000a00) == 0xfc000800 ++ if ((insn & 0xff000a00) == 0xfe000800 + && arm_dc_feature(s, ARM_FEATURE_V8)) { + /* The Thumb2 and ARM encodings are identical. */ +- if (disas_neon_insn_3same_ext(s, insn)) { +- goto illegal_op; +- } +- } else if ((insn & 0xff000a00) == 0xfe000800 +- && arm_dc_feature(s, ARM_FEATURE_V8)) { +- /* The Thumb2 and ARM encodings are identical. */ + if (disas_neon_insn_2reg_scalar_ext(s, insn)) { + goto illegal_op; + } +-- +2.23.0 + diff --git a/target-arm-Create-gen_gvec_-ceq-clt-cle-cgt-cge-0.patch b/target-arm-Create-gen_gvec_-ceq-clt-cle-cgt-cge-0.patch new file mode 100644 index 0000000000000000000000000000000000000000..51c3b3e2e2503efb585f05a3c18a6d8c60310529 --- /dev/null +++ b/target-arm-Create-gen_gvec_-ceq-clt-cle-cgt-cge-0.patch @@ -0,0 +1,381 @@ +From 69d5e2bf8c3cefedbfa1c1670137e636dbd7faa5 Mon Sep 17 00:00:00 2001 +From: Richard Henderson +Date: Wed, 13 May 2020 09:32:35 -0700 +Subject: [PATCH 424/709] target/arm: Create gen_gvec_{ceq,clt,cle,cgt,cge}0 + +Provide a functional interface for the vector expansion. +This fits better with the existing set of helpers that +we provide for other operations. + +Macro-ize the 5 nearly identical comparisons. + +Reviewed-by: Peter Maydell +Signed-off-by: Richard Henderson +Message-id: 20200513163245.17915-7-richard.henderson@linaro.org +Signed-off-by: Peter Maydell +--- + target/arm/translate-a64.c | 22 ++-- + target/arm/translate.c | 254 ++++++++----------------------------- + target/arm/translate.h | 16 ++- + 3 files changed, 74 insertions(+), 218 deletions(-) + +diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c +index d5e77f34a7..fef93dc27a 100644 +--- a/target/arm/translate-a64.c ++++ b/target/arm/translate-a64.c +@@ -577,14 +577,6 @@ static void gen_gvec_fn4(DisasContext *s, bool is_q, int rd, int rn, int rm, + is_q ? 16 : 8, vec_full_reg_size(s)); + } + +-/* Expand a 2-operand AdvSIMD vector operation using an op descriptor. */ +-static void gen_gvec_op2(DisasContext *s, bool is_q, int rd, +- int rn, const GVecGen2 *gvec_op) +-{ +- tcg_gen_gvec_2(vec_full_reg_offset(s, rd), vec_full_reg_offset(s, rn), +- is_q ? 16 : 8, vec_full_reg_size(s), gvec_op); +-} +- + /* Expand a 3-operand AdvSIMD vector operation using an op descriptor. */ + static void gen_gvec_op3(DisasContext *s, bool is_q, int rd, + int rn, int rm, const GVecGen3 *gvec_op) +@@ -12310,13 +12302,21 @@ static void disas_simd_two_reg_misc(DisasContext *s, uint32_t insn) + } + break; + case 0x8: /* CMGT, CMGE */ +- gen_gvec_op2(s, is_q, rd, rn, u ? &cge0_op[size] : &cgt0_op[size]); ++ if (u) { ++ gen_gvec_fn2(s, is_q, rd, rn, gen_gvec_cge0, size); ++ } else { ++ gen_gvec_fn2(s, is_q, rd, rn, gen_gvec_cgt0, size); ++ } + return; + case 0x9: /* CMEQ, CMLE */ +- gen_gvec_op2(s, is_q, rd, rn, u ? &cle0_op[size] : &ceq0_op[size]); ++ if (u) { ++ gen_gvec_fn2(s, is_q, rd, rn, gen_gvec_cle0, size); ++ } else { ++ gen_gvec_fn2(s, is_q, rd, rn, gen_gvec_ceq0, size); ++ } + return; + case 0xa: /* CMLT */ +- gen_gvec_op2(s, is_q, rd, rn, &clt0_op[size]); ++ gen_gvec_fn2(s, is_q, rd, rn, gen_gvec_clt0, size); + return; + case 0xb: + if (u) { /* ABS, NEG */ +diff --git a/target/arm/translate.c b/target/arm/translate.c +index 2eec689c5e..010a158e63 100644 +--- a/target/arm/translate.c ++++ b/target/arm/translate.c +@@ -3645,204 +3645,59 @@ static int do_v81_helper(DisasContext *s, gen_helper_gvec_3_ptr *fn, + return 1; + } + +-static void gen_ceq0_i32(TCGv_i32 d, TCGv_i32 a) +-{ +- tcg_gen_setcondi_i32(TCG_COND_EQ, d, a, 0); +- tcg_gen_neg_i32(d, d); +-} +- +-static void gen_ceq0_i64(TCGv_i64 d, TCGv_i64 a) +-{ +- tcg_gen_setcondi_i64(TCG_COND_EQ, d, a, 0); +- tcg_gen_neg_i64(d, d); +-} +- +-static void gen_ceq0_vec(unsigned vece, TCGv_vec d, TCGv_vec a) +-{ +- TCGv_vec zero = tcg_const_zeros_vec_matching(d); +- tcg_gen_cmp_vec(TCG_COND_EQ, vece, d, a, zero); +- tcg_temp_free_vec(zero); +-} ++#define GEN_CMP0(NAME, COND) \ ++ static void gen_##NAME##0_i32(TCGv_i32 d, TCGv_i32 a) \ ++ { \ ++ tcg_gen_setcondi_i32(COND, d, a, 0); \ ++ tcg_gen_neg_i32(d, d); \ ++ } \ ++ static void gen_##NAME##0_i64(TCGv_i64 d, TCGv_i64 a) \ ++ { \ ++ tcg_gen_setcondi_i64(COND, d, a, 0); \ ++ tcg_gen_neg_i64(d, d); \ ++ } \ ++ static void gen_##NAME##0_vec(unsigned vece, TCGv_vec d, TCGv_vec a) \ ++ { \ ++ TCGv_vec zero = tcg_const_zeros_vec_matching(d); \ ++ tcg_gen_cmp_vec(COND, vece, d, a, zero); \ ++ tcg_temp_free_vec(zero); \ ++ } \ ++ void gen_gvec_##NAME##0(unsigned vece, uint32_t d, uint32_t m, \ ++ uint32_t opr_sz, uint32_t max_sz) \ ++ { \ ++ const GVecGen2 op[4] = { \ ++ { .fno = gen_helper_gvec_##NAME##0_b, \ ++ .fniv = gen_##NAME##0_vec, \ ++ .opt_opc = vecop_list_cmp, \ ++ .vece = MO_8 }, \ ++ { .fno = gen_helper_gvec_##NAME##0_h, \ ++ .fniv = gen_##NAME##0_vec, \ ++ .opt_opc = vecop_list_cmp, \ ++ .vece = MO_16 }, \ ++ { .fni4 = gen_##NAME##0_i32, \ ++ .fniv = gen_##NAME##0_vec, \ ++ .opt_opc = vecop_list_cmp, \ ++ .vece = MO_32 }, \ ++ { .fni8 = gen_##NAME##0_i64, \ ++ .fniv = gen_##NAME##0_vec, \ ++ .opt_opc = vecop_list_cmp, \ ++ .prefer_i64 = TCG_TARGET_REG_BITS == 64, \ ++ .vece = MO_64 }, \ ++ }; \ ++ tcg_gen_gvec_2(d, m, opr_sz, max_sz, &op[vece]); \ ++ } + + static const TCGOpcode vecop_list_cmp[] = { + INDEX_op_cmp_vec, 0 + }; + +-const GVecGen2 ceq0_op[4] = { +- { .fno = gen_helper_gvec_ceq0_b, +- .fniv = gen_ceq0_vec, +- .opt_opc = vecop_list_cmp, +- .vece = MO_8 }, +- { .fno = gen_helper_gvec_ceq0_h, +- .fniv = gen_ceq0_vec, +- .opt_opc = vecop_list_cmp, +- .vece = MO_16 }, +- { .fni4 = gen_ceq0_i32, +- .fniv = gen_ceq0_vec, +- .opt_opc = vecop_list_cmp, +- .vece = MO_32 }, +- { .fni8 = gen_ceq0_i64, +- .fniv = gen_ceq0_vec, +- .opt_opc = vecop_list_cmp, +- .prefer_i64 = TCG_TARGET_REG_BITS == 64, +- .vece = MO_64 }, +-}; +- +-static void gen_cle0_i32(TCGv_i32 d, TCGv_i32 a) +-{ +- tcg_gen_setcondi_i32(TCG_COND_LE, d, a, 0); +- tcg_gen_neg_i32(d, d); +-} +- +-static void gen_cle0_i64(TCGv_i64 d, TCGv_i64 a) +-{ +- tcg_gen_setcondi_i64(TCG_COND_LE, d, a, 0); +- tcg_gen_neg_i64(d, d); +-} +- +-static void gen_cle0_vec(unsigned vece, TCGv_vec d, TCGv_vec a) +-{ +- TCGv_vec zero = tcg_const_zeros_vec_matching(d); +- tcg_gen_cmp_vec(TCG_COND_LE, vece, d, a, zero); +- tcg_temp_free_vec(zero); +-} +- +-const GVecGen2 cle0_op[4] = { +- { .fno = gen_helper_gvec_cle0_b, +- .fniv = gen_cle0_vec, +- .opt_opc = vecop_list_cmp, +- .vece = MO_8 }, +- { .fno = gen_helper_gvec_cle0_h, +- .fniv = gen_cle0_vec, +- .opt_opc = vecop_list_cmp, +- .vece = MO_16 }, +- { .fni4 = gen_cle0_i32, +- .fniv = gen_cle0_vec, +- .opt_opc = vecop_list_cmp, +- .vece = MO_32 }, +- { .fni8 = gen_cle0_i64, +- .fniv = gen_cle0_vec, +- .opt_opc = vecop_list_cmp, +- .prefer_i64 = TCG_TARGET_REG_BITS == 64, +- .vece = MO_64 }, +-}; +- +-static void gen_cge0_i32(TCGv_i32 d, TCGv_i32 a) +-{ +- tcg_gen_setcondi_i32(TCG_COND_GE, d, a, 0); +- tcg_gen_neg_i32(d, d); +-} +- +-static void gen_cge0_i64(TCGv_i64 d, TCGv_i64 a) +-{ +- tcg_gen_setcondi_i64(TCG_COND_GE, d, a, 0); +- tcg_gen_neg_i64(d, d); +-} +- +-static void gen_cge0_vec(unsigned vece, TCGv_vec d, TCGv_vec a) +-{ +- TCGv_vec zero = tcg_const_zeros_vec_matching(d); +- tcg_gen_cmp_vec(TCG_COND_GE, vece, d, a, zero); +- tcg_temp_free_vec(zero); +-} +- +-const GVecGen2 cge0_op[4] = { +- { .fno = gen_helper_gvec_cge0_b, +- .fniv = gen_cge0_vec, +- .opt_opc = vecop_list_cmp, +- .vece = MO_8 }, +- { .fno = gen_helper_gvec_cge0_h, +- .fniv = gen_cge0_vec, +- .opt_opc = vecop_list_cmp, +- .vece = MO_16 }, +- { .fni4 = gen_cge0_i32, +- .fniv = gen_cge0_vec, +- .opt_opc = vecop_list_cmp, +- .vece = MO_32 }, +- { .fni8 = gen_cge0_i64, +- .fniv = gen_cge0_vec, +- .opt_opc = vecop_list_cmp, +- .prefer_i64 = TCG_TARGET_REG_BITS == 64, +- .vece = MO_64 }, +-}; +- +-static void gen_clt0_i32(TCGv_i32 d, TCGv_i32 a) +-{ +- tcg_gen_setcondi_i32(TCG_COND_LT, d, a, 0); +- tcg_gen_neg_i32(d, d); +-} +- +-static void gen_clt0_i64(TCGv_i64 d, TCGv_i64 a) +-{ +- tcg_gen_setcondi_i64(TCG_COND_LT, d, a, 0); +- tcg_gen_neg_i64(d, d); +-} +- +-static void gen_clt0_vec(unsigned vece, TCGv_vec d, TCGv_vec a) +-{ +- TCGv_vec zero = tcg_const_zeros_vec_matching(d); +- tcg_gen_cmp_vec(TCG_COND_LT, vece, d, a, zero); +- tcg_temp_free_vec(zero); +-} +- +-const GVecGen2 clt0_op[4] = { +- { .fno = gen_helper_gvec_clt0_b, +- .fniv = gen_clt0_vec, +- .opt_opc = vecop_list_cmp, +- .vece = MO_8 }, +- { .fno = gen_helper_gvec_clt0_h, +- .fniv = gen_clt0_vec, +- .opt_opc = vecop_list_cmp, +- .vece = MO_16 }, +- { .fni4 = gen_clt0_i32, +- .fniv = gen_clt0_vec, +- .opt_opc = vecop_list_cmp, +- .vece = MO_32 }, +- { .fni8 = gen_clt0_i64, +- .fniv = gen_clt0_vec, +- .opt_opc = vecop_list_cmp, +- .prefer_i64 = TCG_TARGET_REG_BITS == 64, +- .vece = MO_64 }, +-}; +- +-static void gen_cgt0_i32(TCGv_i32 d, TCGv_i32 a) +-{ +- tcg_gen_setcondi_i32(TCG_COND_GT, d, a, 0); +- tcg_gen_neg_i32(d, d); +-} +- +-static void gen_cgt0_i64(TCGv_i64 d, TCGv_i64 a) +-{ +- tcg_gen_setcondi_i64(TCG_COND_GT, d, a, 0); +- tcg_gen_neg_i64(d, d); +-} +- +-static void gen_cgt0_vec(unsigned vece, TCGv_vec d, TCGv_vec a) +-{ +- TCGv_vec zero = tcg_const_zeros_vec_matching(d); +- tcg_gen_cmp_vec(TCG_COND_GT, vece, d, a, zero); +- tcg_temp_free_vec(zero); +-} ++GEN_CMP0(ceq, TCG_COND_EQ) ++GEN_CMP0(cle, TCG_COND_LE) ++GEN_CMP0(cge, TCG_COND_GE) ++GEN_CMP0(clt, TCG_COND_LT) ++GEN_CMP0(cgt, TCG_COND_GT) + +-const GVecGen2 cgt0_op[4] = { +- { .fno = gen_helper_gvec_cgt0_b, +- .fniv = gen_cgt0_vec, +- .opt_opc = vecop_list_cmp, +- .vece = MO_8 }, +- { .fno = gen_helper_gvec_cgt0_h, +- .fniv = gen_cgt0_vec, +- .opt_opc = vecop_list_cmp, +- .vece = MO_16 }, +- { .fni4 = gen_cgt0_i32, +- .fniv = gen_cgt0_vec, +- .opt_opc = vecop_list_cmp, +- .vece = MO_32 }, +- { .fni8 = gen_cgt0_i64, +- .fniv = gen_cgt0_vec, +- .opt_opc = vecop_list_cmp, +- .prefer_i64 = TCG_TARGET_REG_BITS == 64, +- .vece = MO_64 }, +-}; ++#undef GEN_CMP0 + + static void gen_ssra8_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift) + { +@@ -6772,24 +6627,19 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn) + break; + + case NEON_2RM_VCEQ0: +- tcg_gen_gvec_2(rd_ofs, rm_ofs, vec_size, +- vec_size, &ceq0_op[size]); ++ gen_gvec_ceq0(size, rd_ofs, rm_ofs, vec_size, vec_size); + break; + case NEON_2RM_VCGT0: +- tcg_gen_gvec_2(rd_ofs, rm_ofs, vec_size, +- vec_size, &cgt0_op[size]); ++ gen_gvec_cgt0(size, rd_ofs, rm_ofs, vec_size, vec_size); + break; + case NEON_2RM_VCLE0: +- tcg_gen_gvec_2(rd_ofs, rm_ofs, vec_size, +- vec_size, &cle0_op[size]); ++ gen_gvec_cle0(size, rd_ofs, rm_ofs, vec_size, vec_size); + break; + case NEON_2RM_VCGE0: +- tcg_gen_gvec_2(rd_ofs, rm_ofs, vec_size, +- vec_size, &cge0_op[size]); ++ gen_gvec_cge0(size, rd_ofs, rm_ofs, vec_size, vec_size); + break; + case NEON_2RM_VCLT0: +- tcg_gen_gvec_2(rd_ofs, rm_ofs, vec_size, +- vec_size, &clt0_op[size]); ++ gen_gvec_clt0(size, rd_ofs, rm_ofs, vec_size, vec_size); + break; + + default: +diff --git a/target/arm/translate.h b/target/arm/translate.h +index fa5c3f12b9..e35c812cc5 100644 +--- a/target/arm/translate.h ++++ b/target/arm/translate.h +@@ -275,11 +275,17 @@ static inline void gen_swstep_exception(DisasContext *s, int isv, int ex) + uint64_t vfp_expand_imm(int size, uint8_t imm8); + + /* Vector operations shared between ARM and AArch64. */ +-extern const GVecGen2 ceq0_op[4]; +-extern const GVecGen2 clt0_op[4]; +-extern const GVecGen2 cgt0_op[4]; +-extern const GVecGen2 cle0_op[4]; +-extern const GVecGen2 cge0_op[4]; ++void gen_gvec_ceq0(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs, ++ uint32_t opr_sz, uint32_t max_sz); ++void gen_gvec_clt0(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs, ++ uint32_t opr_sz, uint32_t max_sz); ++void gen_gvec_cgt0(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs, ++ uint32_t opr_sz, uint32_t max_sz); ++void gen_gvec_cle0(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs, ++ uint32_t opr_sz, uint32_t max_sz); ++void gen_gvec_cge0(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs, ++ uint32_t opr_sz, uint32_t max_sz); ++ + extern const GVecGen3 mla_op[4]; + extern const GVecGen3 mls_op[4]; + extern const GVecGen3 cmtst_op[4]; +-- +2.23.0 + diff --git a/target-arm-Create-gen_gvec_-cmtst-ushl-sshl.patch b/target-arm-Create-gen_gvec_-cmtst-ushl-sshl.patch new file mode 100644 index 0000000000000000000000000000000000000000..379ce36268b743eec4943fab6ba54418d8bcd15d --- /dev/null +++ b/target-arm-Create-gen_gvec_-cmtst-ushl-sshl.patch @@ -0,0 +1,310 @@ +From 8161b75357095fef54c76b1a6ed1e54d0e8655e0 Mon Sep 17 00:00:00 2001 +From: Richard Henderson +Date: Wed, 13 May 2020 09:32:38 -0700 +Subject: [PATCH 427/709] target/arm: Create gen_gvec_{cmtst,ushl,sshl} + +Provide a functional interface for the vector expansion. +This fits better with the existing set of helpers that +we provide for other operations. + +Reviewed-by: Peter Maydell +Signed-off-by: Richard Henderson +Message-id: 20200513163245.17915-10-richard.henderson@linaro.org +Signed-off-by: Peter Maydell +--- + target/arm/translate-a64.c | 18 ++-- + target/arm/translate-neon.inc.c | 23 +---- + target/arm/translate.c | 146 +++++++++++++++++--------------- + target/arm/translate.h | 10 ++- + 4 files changed, 95 insertions(+), 102 deletions(-) + +diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c +index ab9df12e44..3956c19ed8 100644 +--- a/target/arm/translate-a64.c ++++ b/target/arm/translate-a64.c +@@ -577,15 +577,6 @@ static void gen_gvec_fn4(DisasContext *s, bool is_q, int rd, int rn, int rm, + is_q ? 16 : 8, vec_full_reg_size(s)); + } + +-/* Expand a 3-operand AdvSIMD vector operation using an op descriptor. */ +-static void gen_gvec_op3(DisasContext *s, bool is_q, int rd, +- int rn, int rm, const GVecGen3 *gvec_op) +-{ +- tcg_gen_gvec_3(vec_full_reg_offset(s, rd), vec_full_reg_offset(s, rn), +- vec_full_reg_offset(s, rm), is_q ? 16 : 8, +- vec_full_reg_size(s), gvec_op); +-} +- + /* Expand a 3-operand operation using an out-of-line helper. */ + static void gen_gvec_op3_ool(DisasContext *s, bool is_q, int rd, + int rn, int rm, int data, gen_helper_gvec_3 *fn) +@@ -11193,8 +11184,11 @@ static void disas_simd_3same_int(DisasContext *s, uint32_t insn) + (u ? uqsub_op : sqsub_op) + size); + return; + case 0x08: /* SSHL, USHL */ +- gen_gvec_op3(s, is_q, rd, rn, rm, +- u ? &ushl_op[size] : &sshl_op[size]); ++ if (u) { ++ gen_gvec_fn3(s, is_q, rd, rn, rm, gen_gvec_ushl, size); ++ } else { ++ gen_gvec_fn3(s, is_q, rd, rn, rm, gen_gvec_sshl, size); ++ } + return; + case 0x0c: /* SMAX, UMAX */ + if (u) { +@@ -11233,7 +11227,7 @@ static void disas_simd_3same_int(DisasContext *s, uint32_t insn) + return; + case 0x11: + if (!u) { /* CMTST */ +- gen_gvec_op3(s, is_q, rd, rn, rm, &cmtst_op[size]); ++ gen_gvec_fn3(s, is_q, rd, rn, rm, gen_gvec_cmtst, size); + return; + } + /* else CMEQ */ +diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c +index 416302bcc7..e16475c212 100644 +--- a/target/arm/translate-neon.inc.c ++++ b/target/arm/translate-neon.inc.c +@@ -603,6 +603,8 @@ DO_3SAME(VBIC, tcg_gen_gvec_andc) + DO_3SAME(VORR, tcg_gen_gvec_or) + DO_3SAME(VORN, tcg_gen_gvec_orc) + DO_3SAME(VEOR, tcg_gen_gvec_xor) ++DO_3SAME(VSHL_S, gen_gvec_sshl) ++DO_3SAME(VSHL_U, gen_gvec_ushl) + + /* These insns are all gvec_bitsel but with the inputs in various orders. */ + #define DO_3SAME_BITSEL(INSN, O1, O2, O3) \ +@@ -634,6 +636,7 @@ DO_3SAME_NO_SZ_3(VMIN_U, tcg_gen_gvec_umin) + DO_3SAME_NO_SZ_3(VMUL, tcg_gen_gvec_mul) + DO_3SAME_NO_SZ_3(VMLA, gen_gvec_mla) + DO_3SAME_NO_SZ_3(VMLS, gen_gvec_mls) ++DO_3SAME_NO_SZ_3(VTST, gen_gvec_cmtst) + + #define DO_3SAME_CMP(INSN, COND) \ + static void gen_##INSN##_3s(unsigned vece, uint32_t rd_ofs, \ +@@ -650,13 +653,6 @@ DO_3SAME_CMP(VCGE_S, TCG_COND_GE) + DO_3SAME_CMP(VCGE_U, TCG_COND_GEU) + DO_3SAME_CMP(VCEQ, TCG_COND_EQ) + +-static void gen_VTST_3s(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs, +- uint32_t rm_ofs, uint32_t oprsz, uint32_t maxsz) +-{ +- tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, oprsz, maxsz, &cmtst_op[vece]); +-} +-DO_3SAME_NO_SZ_3(VTST, gen_VTST_3s) +- + #define DO_3SAME_GVEC4(INSN, OPARRAY) \ + static void gen_##INSN##_3s(unsigned vece, uint32_t rd_ofs, \ + uint32_t rn_ofs, uint32_t rm_ofs, \ +@@ -686,16 +682,3 @@ static bool trans_VMUL_p_3s(DisasContext *s, arg_3same *a) + } + return do_3same(s, a, gen_VMUL_p_3s); + } +- +-#define DO_3SAME_GVEC3_SHIFT(INSN, OPARRAY) \ +- static void gen_##INSN##_3s(unsigned vece, uint32_t rd_ofs, \ +- uint32_t rn_ofs, uint32_t rm_ofs, \ +- uint32_t oprsz, uint32_t maxsz) \ +- { \ +- tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, \ +- oprsz, maxsz, &OPARRAY[vece]); \ +- } \ +- DO_3SAME(INSN, gen_##INSN##_3s) +- +-DO_3SAME_GVEC3_SHIFT(VSHL_S, sshl_op) +-DO_3SAME_GVEC3_SHIFT(VSHL_U, ushl_op) +diff --git a/target/arm/translate.c b/target/arm/translate.c +index face89a1f7..df91ff73e3 100644 +--- a/target/arm/translate.c ++++ b/target/arm/translate.c +@@ -4606,27 +4606,31 @@ static void gen_cmtst_vec(unsigned vece, TCGv_vec d, TCGv_vec a, TCGv_vec b) + tcg_gen_cmp_vec(TCG_COND_NE, vece, d, d, a); + } + +-static const TCGOpcode vecop_list_cmtst[] = { INDEX_op_cmp_vec, 0 }; +- +-const GVecGen3 cmtst_op[4] = { +- { .fni4 = gen_helper_neon_tst_u8, +- .fniv = gen_cmtst_vec, +- .opt_opc = vecop_list_cmtst, +- .vece = MO_8 }, +- { .fni4 = gen_helper_neon_tst_u16, +- .fniv = gen_cmtst_vec, +- .opt_opc = vecop_list_cmtst, +- .vece = MO_16 }, +- { .fni4 = gen_cmtst_i32, +- .fniv = gen_cmtst_vec, +- .opt_opc = vecop_list_cmtst, +- .vece = MO_32 }, +- { .fni8 = gen_cmtst_i64, +- .fniv = gen_cmtst_vec, +- .prefer_i64 = TCG_TARGET_REG_BITS == 64, +- .opt_opc = vecop_list_cmtst, +- .vece = MO_64 }, +-}; ++void gen_gvec_cmtst(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs, ++ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz) ++{ ++ static const TCGOpcode vecop_list[] = { INDEX_op_cmp_vec, 0 }; ++ static const GVecGen3 ops[4] = { ++ { .fni4 = gen_helper_neon_tst_u8, ++ .fniv = gen_cmtst_vec, ++ .opt_opc = vecop_list, ++ .vece = MO_8 }, ++ { .fni4 = gen_helper_neon_tst_u16, ++ .fniv = gen_cmtst_vec, ++ .opt_opc = vecop_list, ++ .vece = MO_16 }, ++ { .fni4 = gen_cmtst_i32, ++ .fniv = gen_cmtst_vec, ++ .opt_opc = vecop_list, ++ .vece = MO_32 }, ++ { .fni8 = gen_cmtst_i64, ++ .fniv = gen_cmtst_vec, ++ .prefer_i64 = TCG_TARGET_REG_BITS == 64, ++ .opt_opc = vecop_list, ++ .vece = MO_64 }, ++ }; ++ tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]); ++} + + void gen_ushl_i32(TCGv_i32 dst, TCGv_i32 src, TCGv_i32 shift) + { +@@ -4744,29 +4748,33 @@ static void gen_ushl_vec(unsigned vece, TCGv_vec dst, + tcg_temp_free_vec(rsh); + } + +-static const TCGOpcode ushl_list[] = { +- INDEX_op_neg_vec, INDEX_op_shlv_vec, +- INDEX_op_shrv_vec, INDEX_op_cmp_vec, 0 +-}; +- +-const GVecGen3 ushl_op[4] = { +- { .fniv = gen_ushl_vec, +- .fno = gen_helper_gvec_ushl_b, +- .opt_opc = ushl_list, +- .vece = MO_8 }, +- { .fniv = gen_ushl_vec, +- .fno = gen_helper_gvec_ushl_h, +- .opt_opc = ushl_list, +- .vece = MO_16 }, +- { .fni4 = gen_ushl_i32, +- .fniv = gen_ushl_vec, +- .opt_opc = ushl_list, +- .vece = MO_32 }, +- { .fni8 = gen_ushl_i64, +- .fniv = gen_ushl_vec, +- .opt_opc = ushl_list, +- .vece = MO_64 }, +-}; ++void gen_gvec_ushl(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs, ++ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz) ++{ ++ static const TCGOpcode vecop_list[] = { ++ INDEX_op_neg_vec, INDEX_op_shlv_vec, ++ INDEX_op_shrv_vec, INDEX_op_cmp_vec, 0 ++ }; ++ static const GVecGen3 ops[4] = { ++ { .fniv = gen_ushl_vec, ++ .fno = gen_helper_gvec_ushl_b, ++ .opt_opc = vecop_list, ++ .vece = MO_8 }, ++ { .fniv = gen_ushl_vec, ++ .fno = gen_helper_gvec_ushl_h, ++ .opt_opc = vecop_list, ++ .vece = MO_16 }, ++ { .fni4 = gen_ushl_i32, ++ .fniv = gen_ushl_vec, ++ .opt_opc = vecop_list, ++ .vece = MO_32 }, ++ { .fni8 = gen_ushl_i64, ++ .fniv = gen_ushl_vec, ++ .opt_opc = vecop_list, ++ .vece = MO_64 }, ++ }; ++ tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]); ++} + + void gen_sshl_i32(TCGv_i32 dst, TCGv_i32 src, TCGv_i32 shift) + { +@@ -4878,29 +4886,33 @@ static void gen_sshl_vec(unsigned vece, TCGv_vec dst, + tcg_temp_free_vec(tmp); + } + +-static const TCGOpcode sshl_list[] = { +- INDEX_op_neg_vec, INDEX_op_umin_vec, INDEX_op_shlv_vec, +- INDEX_op_sarv_vec, INDEX_op_cmp_vec, INDEX_op_cmpsel_vec, 0 +-}; +- +-const GVecGen3 sshl_op[4] = { +- { .fniv = gen_sshl_vec, +- .fno = gen_helper_gvec_sshl_b, +- .opt_opc = sshl_list, +- .vece = MO_8 }, +- { .fniv = gen_sshl_vec, +- .fno = gen_helper_gvec_sshl_h, +- .opt_opc = sshl_list, +- .vece = MO_16 }, +- { .fni4 = gen_sshl_i32, +- .fniv = gen_sshl_vec, +- .opt_opc = sshl_list, +- .vece = MO_32 }, +- { .fni8 = gen_sshl_i64, +- .fniv = gen_sshl_vec, +- .opt_opc = sshl_list, +- .vece = MO_64 }, +-}; ++void gen_gvec_sshl(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs, ++ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz) ++{ ++ static const TCGOpcode vecop_list[] = { ++ INDEX_op_neg_vec, INDEX_op_umin_vec, INDEX_op_shlv_vec, ++ INDEX_op_sarv_vec, INDEX_op_cmp_vec, INDEX_op_cmpsel_vec, 0 ++ }; ++ static const GVecGen3 ops[4] = { ++ { .fniv = gen_sshl_vec, ++ .fno = gen_helper_gvec_sshl_b, ++ .opt_opc = vecop_list, ++ .vece = MO_8 }, ++ { .fniv = gen_sshl_vec, ++ .fno = gen_helper_gvec_sshl_h, ++ .opt_opc = vecop_list, ++ .vece = MO_16 }, ++ { .fni4 = gen_sshl_i32, ++ .fniv = gen_sshl_vec, ++ .opt_opc = vecop_list, ++ .vece = MO_32 }, ++ { .fni8 = gen_sshl_i64, ++ .fniv = gen_sshl_vec, ++ .opt_opc = vecop_list, ++ .vece = MO_64 }, ++ }; ++ tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]); ++} + + static void gen_uqadd_vec(unsigned vece, TCGv_vec t, TCGv_vec sat, + TCGv_vec a, TCGv_vec b) +diff --git a/target/arm/translate.h b/target/arm/translate.h +index 9354ceba35..a02a54cabf 100644 +--- a/target/arm/translate.h ++++ b/target/arm/translate.h +@@ -291,9 +291,13 @@ void gen_gvec_mla(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs, + void gen_gvec_mls(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs, + uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz); + +-extern const GVecGen3 cmtst_op[4]; +-extern const GVecGen3 sshl_op[4]; +-extern const GVecGen3 ushl_op[4]; ++void gen_gvec_cmtst(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs, ++ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz); ++void gen_gvec_sshl(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs, ++ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz); ++void gen_gvec_ushl(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs, ++ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz); ++ + extern const GVecGen4 uqadd_op[4]; + extern const GVecGen4 sqadd_op[4]; + extern const GVecGen4 uqsub_op[4]; +-- +2.23.0 + diff --git a/target-arm-Create-gen_gvec_-mla-mls.patch b/target-arm-Create-gen_gvec_-mla-mls.patch new file mode 100644 index 0000000000000000000000000000000000000000..86200749acd78dcfc157bebdfb8ef76d665cb7d7 --- /dev/null +++ b/target-arm-Create-gen_gvec_-mla-mls.patch @@ -0,0 +1,220 @@ +From 271063206a46062a45fc6bab8dabe45f0b88159d Mon Sep 17 00:00:00 2001 +From: Richard Henderson +Date: Wed, 13 May 2020 09:32:36 -0700 +Subject: [PATCH 425/709] target/arm: Create gen_gvec_{mla,mls} + +Provide a functional interface for the vector expansion. +This fits better with the existing set of helpers that +we provide for other operations. + +Reviewed-by: Peter Maydell +Signed-off-by: Richard Henderson +Message-id: 20200513163245.17915-8-richard.henderson@linaro.org +Signed-off-by: Peter Maydell +--- + target/arm/translate-a64.c | 4 +- + target/arm/translate-neon.inc.c | 16 +---- + target/arm/translate.c | 117 +++++++++++++++++--------------- + target/arm/translate.h | 7 +- + 4 files changed, 71 insertions(+), 73 deletions(-) + +diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c +index fef93dc27a..ab9df12e44 100644 +--- a/target/arm/translate-a64.c ++++ b/target/arm/translate-a64.c +@@ -11226,9 +11226,9 @@ static void disas_simd_3same_int(DisasContext *s, uint32_t insn) + return; + case 0x12: /* MLA, MLS */ + if (u) { +- gen_gvec_op3(s, is_q, rd, rn, rm, &mls_op[size]); ++ gen_gvec_fn3(s, is_q, rd, rn, rm, gen_gvec_mls, size); + } else { +- gen_gvec_op3(s, is_q, rd, rn, rm, &mla_op[size]); ++ gen_gvec_fn3(s, is_q, rd, rn, rm, gen_gvec_mla, size); + } + return; + case 0x11: +diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c +index 50b77b6d71..aefeff498a 100644 +--- a/target/arm/translate-neon.inc.c ++++ b/target/arm/translate-neon.inc.c +@@ -632,6 +632,8 @@ DO_3SAME_NO_SZ_3(VMAX_U, tcg_gen_gvec_umax) + DO_3SAME_NO_SZ_3(VMIN_S, tcg_gen_gvec_smin) + DO_3SAME_NO_SZ_3(VMIN_U, tcg_gen_gvec_umin) + DO_3SAME_NO_SZ_3(VMUL, tcg_gen_gvec_mul) ++DO_3SAME_NO_SZ_3(VMLA, gen_gvec_mla) ++DO_3SAME_NO_SZ_3(VMLS, gen_gvec_mls) + + #define DO_3SAME_CMP(INSN, COND) \ + static void gen_##INSN##_3s(unsigned vece, uint32_t rd_ofs, \ +@@ -685,20 +687,6 @@ static bool trans_VMUL_p_3s(DisasContext *s, arg_3same *a) + return do_3same(s, a, gen_VMUL_p_3s); + } + +-#define DO_3SAME_GVEC3_NO_SZ_3(INSN, OPARRAY) \ +- static void gen_##INSN##_3s(unsigned vece, uint32_t rd_ofs, \ +- uint32_t rn_ofs, uint32_t rm_ofs, \ +- uint32_t oprsz, uint32_t maxsz) \ +- { \ +- tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, \ +- oprsz, maxsz, &OPARRAY[vece]); \ +- } \ +- DO_3SAME_NO_SZ_3(INSN, gen_##INSN##_3s) +- +- +-DO_3SAME_GVEC3_NO_SZ_3(VMLA, mla_op) +-DO_3SAME_GVEC3_NO_SZ_3(VMLS, mls_op) +- + #define DO_3SAME_GVEC3_SHIFT(INSN, OPARRAY) \ + static void gen_##INSN##_3s(unsigned vece, uint32_t rd_ofs, \ + uint32_t rn_ofs, uint32_t rm_ofs, \ +diff --git a/target/arm/translate.c b/target/arm/translate.c +index 010a158e63..face89a1f7 100644 +--- a/target/arm/translate.c ++++ b/target/arm/translate.c +@@ -4520,62 +4520,69 @@ static void gen_mls_vec(unsigned vece, TCGv_vec d, TCGv_vec a, TCGv_vec b) + /* Note that while NEON does not support VMLA and VMLS as 64-bit ops, + * these tables are shared with AArch64 which does support them. + */ ++void gen_gvec_mla(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs, ++ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz) ++{ ++ static const TCGOpcode vecop_list[] = { ++ INDEX_op_mul_vec, INDEX_op_add_vec, 0 ++ }; ++ static const GVecGen3 ops[4] = { ++ { .fni4 = gen_mla8_i32, ++ .fniv = gen_mla_vec, ++ .load_dest = true, ++ .opt_opc = vecop_list, ++ .vece = MO_8 }, ++ { .fni4 = gen_mla16_i32, ++ .fniv = gen_mla_vec, ++ .load_dest = true, ++ .opt_opc = vecop_list, ++ .vece = MO_16 }, ++ { .fni4 = gen_mla32_i32, ++ .fniv = gen_mla_vec, ++ .load_dest = true, ++ .opt_opc = vecop_list, ++ .vece = MO_32 }, ++ { .fni8 = gen_mla64_i64, ++ .fniv = gen_mla_vec, ++ .prefer_i64 = TCG_TARGET_REG_BITS == 64, ++ .load_dest = true, ++ .opt_opc = vecop_list, ++ .vece = MO_64 }, ++ }; ++ tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]); ++} + +-static const TCGOpcode vecop_list_mla[] = { +- INDEX_op_mul_vec, INDEX_op_add_vec, 0 +-}; +- +-static const TCGOpcode vecop_list_mls[] = { +- INDEX_op_mul_vec, INDEX_op_sub_vec, 0 +-}; +- +-const GVecGen3 mla_op[4] = { +- { .fni4 = gen_mla8_i32, +- .fniv = gen_mla_vec, +- .load_dest = true, +- .opt_opc = vecop_list_mla, +- .vece = MO_8 }, +- { .fni4 = gen_mla16_i32, +- .fniv = gen_mla_vec, +- .load_dest = true, +- .opt_opc = vecop_list_mla, +- .vece = MO_16 }, +- { .fni4 = gen_mla32_i32, +- .fniv = gen_mla_vec, +- .load_dest = true, +- .opt_opc = vecop_list_mla, +- .vece = MO_32 }, +- { .fni8 = gen_mla64_i64, +- .fniv = gen_mla_vec, +- .prefer_i64 = TCG_TARGET_REG_BITS == 64, +- .load_dest = true, +- .opt_opc = vecop_list_mla, +- .vece = MO_64 }, +-}; +- +-const GVecGen3 mls_op[4] = { +- { .fni4 = gen_mls8_i32, +- .fniv = gen_mls_vec, +- .load_dest = true, +- .opt_opc = vecop_list_mls, +- .vece = MO_8 }, +- { .fni4 = gen_mls16_i32, +- .fniv = gen_mls_vec, +- .load_dest = true, +- .opt_opc = vecop_list_mls, +- .vece = MO_16 }, +- { .fni4 = gen_mls32_i32, +- .fniv = gen_mls_vec, +- .load_dest = true, +- .opt_opc = vecop_list_mls, +- .vece = MO_32 }, +- { .fni8 = gen_mls64_i64, +- .fniv = gen_mls_vec, +- .prefer_i64 = TCG_TARGET_REG_BITS == 64, +- .load_dest = true, +- .opt_opc = vecop_list_mls, +- .vece = MO_64 }, +-}; ++void gen_gvec_mls(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs, ++ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz) ++{ ++ static const TCGOpcode vecop_list[] = { ++ INDEX_op_mul_vec, INDEX_op_sub_vec, 0 ++ }; ++ static const GVecGen3 ops[4] = { ++ { .fni4 = gen_mls8_i32, ++ .fniv = gen_mls_vec, ++ .load_dest = true, ++ .opt_opc = vecop_list, ++ .vece = MO_8 }, ++ { .fni4 = gen_mls16_i32, ++ .fniv = gen_mls_vec, ++ .load_dest = true, ++ .opt_opc = vecop_list, ++ .vece = MO_16 }, ++ { .fni4 = gen_mls32_i32, ++ .fniv = gen_mls_vec, ++ .load_dest = true, ++ .opt_opc = vecop_list, ++ .vece = MO_32 }, ++ { .fni8 = gen_mls64_i64, ++ .fniv = gen_mls_vec, ++ .prefer_i64 = TCG_TARGET_REG_BITS == 64, ++ .load_dest = true, ++ .opt_opc = vecop_list, ++ .vece = MO_64 }, ++ }; ++ tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]); ++} + + /* CMTST : test is "if (X & Y != 0)". */ + static void gen_cmtst_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b) +diff --git a/target/arm/translate.h b/target/arm/translate.h +index e35c812cc5..9354ceba35 100644 +--- a/target/arm/translate.h ++++ b/target/arm/translate.h +@@ -286,8 +286,11 @@ void gen_gvec_cle0(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs, + void gen_gvec_cge0(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs, + uint32_t opr_sz, uint32_t max_sz); + +-extern const GVecGen3 mla_op[4]; +-extern const GVecGen3 mls_op[4]; ++void gen_gvec_mla(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs, ++ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz); ++void gen_gvec_mls(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs, ++ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz); ++ + extern const GVecGen3 cmtst_op[4]; + extern const GVecGen3 sshl_op[4]; + extern const GVecGen3 ushl_op[4]; +-- +2.23.0 + diff --git a/target-arm-Create-gen_gvec_-qrdmla-qrdmls.patch b/target-arm-Create-gen_gvec_-qrdmla-qrdmls.patch new file mode 100644 index 0000000000000000000000000000000000000000..01d634a5b93d81bcc6dc905a2aa7110651ea5e80 --- /dev/null +++ b/target-arm-Create-gen_gvec_-qrdmla-qrdmls.patch @@ -0,0 +1,172 @@ +From 146aa66ce58b686b8037d0eb3921c1125942dbde Mon Sep 17 00:00:00 2001 +From: Richard Henderson +Date: Wed, 13 May 2020 09:32:41 -0700 +Subject: [PATCH 430/709] target/arm: Create gen_gvec_{qrdmla,qrdmls} + +Provide a functional interface for the vector expansion. +This fits better with the existing set of helpers that +we provide for other operations. + +Reviewed-by: Peter Maydell +Signed-off-by: Richard Henderson +Message-id: 20200513163245.17915-13-richard.henderson@linaro.org +Signed-off-by: Peter Maydell +--- + target/arm/translate-a64.c | 34 ++----------------------- + target/arm/translate.c | 52 +++++++++++++++++++------------------- + target/arm/translate.h | 5 ++++ + 3 files changed, 33 insertions(+), 58 deletions(-) + +diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c +index 367fa403ae..4577df3cf4 100644 +--- a/target/arm/translate-a64.c ++++ b/target/arm/translate-a64.c +@@ -587,18 +587,6 @@ static void gen_gvec_op3_ool(DisasContext *s, bool is_q, int rd, + is_q ? 16 : 8, vec_full_reg_size(s), data, fn); + } + +-/* Expand a 3-operand + env pointer operation using +- * an out-of-line helper. +- */ +-static void gen_gvec_op3_env(DisasContext *s, bool is_q, int rd, +- int rn, int rm, gen_helper_gvec_3_ptr *fn) +-{ +- tcg_gen_gvec_3_ptr(vec_full_reg_offset(s, rd), +- vec_full_reg_offset(s, rn), +- vec_full_reg_offset(s, rm), cpu_env, +- is_q ? 16 : 8, vec_full_reg_size(s), 0, fn); +-} +- + /* Expand a 3-operand + fpstatus pointer + simd data value operation using + * an out-of-line helper. + */ +@@ -11693,29 +11681,11 @@ static void disas_simd_three_reg_same_extra(DisasContext *s, uint32_t insn) + + switch (opcode) { + case 0x0: /* SQRDMLAH (vector) */ +- switch (size) { +- case 1: +- gen_gvec_op3_env(s, is_q, rd, rn, rm, gen_helper_gvec_qrdmlah_s16); +- break; +- case 2: +- gen_gvec_op3_env(s, is_q, rd, rn, rm, gen_helper_gvec_qrdmlah_s32); +- break; +- default: +- g_assert_not_reached(); +- } ++ gen_gvec_fn3(s, is_q, rd, rn, rm, gen_gvec_sqrdmlah_qc, size); + return; + + case 0x1: /* SQRDMLSH (vector) */ +- switch (size) { +- case 1: +- gen_gvec_op3_env(s, is_q, rd, rn, rm, gen_helper_gvec_qrdmlsh_s16); +- break; +- case 2: +- gen_gvec_op3_env(s, is_q, rd, rn, rm, gen_helper_gvec_qrdmlsh_s32); +- break; +- default: +- g_assert_not_reached(); +- } ++ gen_gvec_fn3(s, is_q, rd, rn, rm, gen_gvec_sqrdmlsh_qc, size); + return; + + case 0x2: /* SDOT / UDOT */ +diff --git a/target/arm/translate.c b/target/arm/translate.c +index 391a09b439..39626e0df9 100644 +--- a/target/arm/translate.c ++++ b/target/arm/translate.c +@@ -3629,20 +3629,26 @@ static const uint8_t neon_2rm_sizes[] = { + [NEON_2RM_VCVT_UF] = 0x4, + }; + ++void gen_gvec_sqrdmlah_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs, ++ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz) ++{ ++ static gen_helper_gvec_3_ptr * const fns[2] = { ++ gen_helper_gvec_qrdmlah_s16, gen_helper_gvec_qrdmlah_s32 ++ }; ++ tcg_debug_assert(vece >= 1 && vece <= 2); ++ tcg_gen_gvec_3_ptr(rd_ofs, rn_ofs, rm_ofs, cpu_env, ++ opr_sz, max_sz, 0, fns[vece - 1]); ++} + +-/* Expand v8.1 simd helper. */ +-static int do_v81_helper(DisasContext *s, gen_helper_gvec_3_ptr *fn, +- int q, int rd, int rn, int rm) ++void gen_gvec_sqrdmlsh_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs, ++ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz) + { +- if (dc_isar_feature(aa32_rdm, s)) { +- int opr_sz = (1 + q) * 8; +- tcg_gen_gvec_3_ptr(vfp_reg_offset(1, rd), +- vfp_reg_offset(1, rn), +- vfp_reg_offset(1, rm), cpu_env, +- opr_sz, opr_sz, 0, fn); +- return 0; +- } +- return 1; ++ static gen_helper_gvec_3_ptr * const fns[2] = { ++ gen_helper_gvec_qrdmlsh_s16, gen_helper_gvec_qrdmlsh_s32 ++ }; ++ tcg_debug_assert(vece >= 1 && vece <= 2); ++ tcg_gen_gvec_3_ptr(rd_ofs, rn_ofs, rm_ofs, cpu_env, ++ opr_sz, max_sz, 0, fns[vece - 1]); + } + + #define GEN_CMP0(NAME, COND) \ +@@ -5197,13 +5203,10 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn) + break; /* VPADD */ + } + /* VQRDMLAH */ +- switch (size) { +- case 1: +- return do_v81_helper(s, gen_helper_gvec_qrdmlah_s16, +- q, rd, rn, rm); +- case 2: +- return do_v81_helper(s, gen_helper_gvec_qrdmlah_s32, +- q, rd, rn, rm); ++ if (dc_isar_feature(aa32_rdm, s) && (size == 1 || size == 2)) { ++ gen_gvec_sqrdmlah_qc(size, rd_ofs, rn_ofs, rm_ofs, ++ vec_size, vec_size); ++ return 0; + } + return 1; + +@@ -5216,13 +5219,10 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn) + break; + } + /* VQRDMLSH */ +- switch (size) { +- case 1: +- return do_v81_helper(s, gen_helper_gvec_qrdmlsh_s16, +- q, rd, rn, rm); +- case 2: +- return do_v81_helper(s, gen_helper_gvec_qrdmlsh_s32, +- q, rd, rn, rm); ++ if (dc_isar_feature(aa32_rdm, s) && (size == 1 || size == 2)) { ++ gen_gvec_sqrdmlsh_qc(size, rd_ofs, rn_ofs, rm_ofs, ++ vec_size, vec_size); ++ return 0; + } + return 1; + +diff --git a/target/arm/translate.h b/target/arm/translate.h +index 4e1778c5e0..aea8a9759d 100644 +--- a/target/arm/translate.h ++++ b/target/arm/translate.h +@@ -332,6 +332,11 @@ void gen_gvec_sri(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs, + void gen_gvec_sli(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs, + int64_t shift, uint32_t opr_sz, uint32_t max_sz); + ++void gen_gvec_sqrdmlah_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs, ++ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz); ++void gen_gvec_sqrdmlsh_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs, ++ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz); ++ + /* + * Forward to the isar_feature_* tests given a DisasContext pointer. + */ +-- +2.23.0 + diff --git a/target-arm-Create-gen_gvec_-sri-sli.patch b/target-arm-Create-gen_gvec_-sri-sli.patch new file mode 100644 index 0000000000000000000000000000000000000000..897eed68acfa119ef4aca68cd054663498a6aaac --- /dev/null +++ b/target-arm-Create-gen_gvec_-sri-sli.patch @@ -0,0 +1,402 @@ +From 893ab0542aa385a287cbe46d5535c8b9e95ce699 Mon Sep 17 00:00:00 2001 +From: Richard Henderson +Date: Wed, 13 May 2020 09:32:32 -0700 +Subject: [PATCH 421/709] target/arm: Create gen_gvec_{sri,sli} + +The functions eliminate duplication of the special cases for +this operation. They match up with the GVecGen2iFn typedef. + +Add out-of-line helpers. We got away with only having inline +expanders because the neon vector size is only 16 bytes, and +we know that the inline expansion will always succeed. +When we reuse this for SVE, tcg-gvec-op may decide to use an +out-of-line helper due to longer vector lengths. + +Reviewed-by: Peter Maydell +Signed-off-by: Richard Henderson +Message-id: 20200513163245.17915-4-richard.henderson@linaro.org +Signed-off-by: Peter Maydell +--- + target/arm/helper.h | 10 ++ + target/arm/translate-a64.c | 20 +--- + target/arm/translate.c | 186 +++++++++++++++++++++---------------- + target/arm/translate.h | 7 +- + target/arm/vec_helper.c | 38 ++++++++ + 5 files changed, 160 insertions(+), 101 deletions(-) + +diff --git a/target/arm/helper.h b/target/arm/helper.h +index aeb1f52455..33c76192d2 100644 +--- a/target/arm/helper.h ++++ b/target/arm/helper.h +@@ -721,6 +721,16 @@ DEF_HELPER_FLAGS_3(gvec_ursra_h, TCG_CALL_NO_RWG, void, ptr, ptr, i32) + DEF_HELPER_FLAGS_3(gvec_ursra_s, TCG_CALL_NO_RWG, void, ptr, ptr, i32) + DEF_HELPER_FLAGS_3(gvec_ursra_d, TCG_CALL_NO_RWG, void, ptr, ptr, i32) + ++DEF_HELPER_FLAGS_3(gvec_sri_b, TCG_CALL_NO_RWG, void, ptr, ptr, i32) ++DEF_HELPER_FLAGS_3(gvec_sri_h, TCG_CALL_NO_RWG, void, ptr, ptr, i32) ++DEF_HELPER_FLAGS_3(gvec_sri_s, TCG_CALL_NO_RWG, void, ptr, ptr, i32) ++DEF_HELPER_FLAGS_3(gvec_sri_d, TCG_CALL_NO_RWG, void, ptr, ptr, i32) ++ ++DEF_HELPER_FLAGS_3(gvec_sli_b, TCG_CALL_NO_RWG, void, ptr, ptr, i32) ++DEF_HELPER_FLAGS_3(gvec_sli_h, TCG_CALL_NO_RWG, void, ptr, ptr, i32) ++DEF_HELPER_FLAGS_3(gvec_sli_s, TCG_CALL_NO_RWG, void, ptr, ptr, i32) ++DEF_HELPER_FLAGS_3(gvec_sli_d, TCG_CALL_NO_RWG, void, ptr, ptr, i32) ++ + #ifdef TARGET_AARCH64 + #include "helper-a64.h" + #include "helper-sve.h" +diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c +index 50949d306b..2d7dad6c3f 100644 +--- a/target/arm/translate-a64.c ++++ b/target/arm/translate-a64.c +@@ -585,16 +585,6 @@ static void gen_gvec_op2(DisasContext *s, bool is_q, int rd, + is_q ? 16 : 8, vec_full_reg_size(s), gvec_op); + } + +-/* Expand a 2-operand + immediate AdvSIMD vector operation using +- * an op descriptor. +- */ +-static void gen_gvec_op2i(DisasContext *s, bool is_q, int rd, +- int rn, int64_t imm, const GVecGen2i *gvec_op) +-{ +- tcg_gen_gvec_2i(vec_full_reg_offset(s, rd), vec_full_reg_offset(s, rn), +- is_q ? 16 : 8, vec_full_reg_size(s), imm, gvec_op); +-} +- + /* Expand a 3-operand AdvSIMD vector operation using an op descriptor. */ + static void gen_gvec_op3(DisasContext *s, bool is_q, int rd, + int rn, int rm, const GVecGen3 *gvec_op) +@@ -10191,12 +10181,9 @@ static void handle_vec_simd_shri(DisasContext *s, bool is_q, bool is_u, + gen_gvec_fn2i(s, is_q, rd, rn, shift, + is_u ? gen_gvec_usra : gen_gvec_ssra, size); + return; ++ + case 0x08: /* SRI */ +- /* Shift count same as element size is valid but does nothing. */ +- if (shift == 8 << size) { +- goto done; +- } +- gen_gvec_op2i(s, is_q, rd, rn, shift, &sri_op[size]); ++ gen_gvec_fn2i(s, is_q, rd, rn, shift, gen_gvec_sri, size); + return; + + case 0x00: /* SSHR / USHR */ +@@ -10247,7 +10234,6 @@ static void handle_vec_simd_shri(DisasContext *s, bool is_q, bool is_u, + } + tcg_temp_free_i64(tcg_round); + +- done: + clear_vec_high(s, is_q, rd); + } + +@@ -10272,7 +10258,7 @@ static void handle_vec_simd_shli(DisasContext *s, bool is_q, bool insert, + } + + if (insert) { +- gen_gvec_op2i(s, is_q, rd, rn, shift, &sli_op[size]); ++ gen_gvec_fn2i(s, is_q, rd, rn, shift, gen_gvec_sli, size); + } else { + gen_gvec_fn2i(s, is_q, rd, rn, shift, tcg_gen_gvec_shli, size); + } +diff --git a/target/arm/translate.c b/target/arm/translate.c +index aa03dc236b..3c489852dc 100644 +--- a/target/arm/translate.c ++++ b/target/arm/translate.c +@@ -4454,47 +4454,62 @@ static void gen_shr64_ins_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift) + + static void gen_shr_ins_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t sh) + { +- if (sh == 0) { +- tcg_gen_mov_vec(d, a); +- } else { +- TCGv_vec t = tcg_temp_new_vec_matching(d); +- TCGv_vec m = tcg_temp_new_vec_matching(d); ++ TCGv_vec t = tcg_temp_new_vec_matching(d); ++ TCGv_vec m = tcg_temp_new_vec_matching(d); + +- tcg_gen_dupi_vec(vece, m, MAKE_64BIT_MASK((8 << vece) - sh, sh)); +- tcg_gen_shri_vec(vece, t, a, sh); +- tcg_gen_and_vec(vece, d, d, m); +- tcg_gen_or_vec(vece, d, d, t); ++ tcg_gen_dupi_vec(vece, m, MAKE_64BIT_MASK((8 << vece) - sh, sh)); ++ tcg_gen_shri_vec(vece, t, a, sh); ++ tcg_gen_and_vec(vece, d, d, m); ++ tcg_gen_or_vec(vece, d, d, t); + +- tcg_temp_free_vec(t); +- tcg_temp_free_vec(m); +- } ++ tcg_temp_free_vec(t); ++ tcg_temp_free_vec(m); + } + +-static const TCGOpcode vecop_list_sri[] = { INDEX_op_shri_vec, 0 }; ++void gen_gvec_sri(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs, ++ int64_t shift, uint32_t opr_sz, uint32_t max_sz) ++{ ++ static const TCGOpcode vecop_list[] = { INDEX_op_shri_vec, 0 }; ++ const GVecGen2i ops[4] = { ++ { .fni8 = gen_shr8_ins_i64, ++ .fniv = gen_shr_ins_vec, ++ .fno = gen_helper_gvec_sri_b, ++ .load_dest = true, ++ .opt_opc = vecop_list, ++ .vece = MO_8 }, ++ { .fni8 = gen_shr16_ins_i64, ++ .fniv = gen_shr_ins_vec, ++ .fno = gen_helper_gvec_sri_h, ++ .load_dest = true, ++ .opt_opc = vecop_list, ++ .vece = MO_16 }, ++ { .fni4 = gen_shr32_ins_i32, ++ .fniv = gen_shr_ins_vec, ++ .fno = gen_helper_gvec_sri_s, ++ .load_dest = true, ++ .opt_opc = vecop_list, ++ .vece = MO_32 }, ++ { .fni8 = gen_shr64_ins_i64, ++ .fniv = gen_shr_ins_vec, ++ .fno = gen_helper_gvec_sri_d, ++ .prefer_i64 = TCG_TARGET_REG_BITS == 64, ++ .load_dest = true, ++ .opt_opc = vecop_list, ++ .vece = MO_64 }, ++ }; + +-const GVecGen2i sri_op[4] = { +- { .fni8 = gen_shr8_ins_i64, +- .fniv = gen_shr_ins_vec, +- .load_dest = true, +- .opt_opc = vecop_list_sri, +- .vece = MO_8 }, +- { .fni8 = gen_shr16_ins_i64, +- .fniv = gen_shr_ins_vec, +- .load_dest = true, +- .opt_opc = vecop_list_sri, +- .vece = MO_16 }, +- { .fni4 = gen_shr32_ins_i32, +- .fniv = gen_shr_ins_vec, +- .load_dest = true, +- .opt_opc = vecop_list_sri, +- .vece = MO_32 }, +- { .fni8 = gen_shr64_ins_i64, +- .fniv = gen_shr_ins_vec, +- .prefer_i64 = TCG_TARGET_REG_BITS == 64, +- .load_dest = true, +- .opt_opc = vecop_list_sri, +- .vece = MO_64 }, +-}; ++ /* tszimm encoding produces immediates in the range [1..esize]. */ ++ tcg_debug_assert(shift > 0); ++ tcg_debug_assert(shift <= (8 << vece)); ++ ++ /* Shift of esize leaves destination unchanged. */ ++ if (shift < (8 << vece)) { ++ tcg_gen_gvec_2i(rd_ofs, rm_ofs, opr_sz, max_sz, shift, &ops[vece]); ++ } else { ++ /* Nop, but we do need to clear the tail. */ ++ tcg_gen_gvec_mov(vece, rd_ofs, rd_ofs, opr_sz, max_sz); ++ } ++} + + static void gen_shl8_ins_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift) + { +@@ -4532,47 +4547,60 @@ static void gen_shl64_ins_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift) + + static void gen_shl_ins_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t sh) + { +- if (sh == 0) { +- tcg_gen_mov_vec(d, a); +- } else { +- TCGv_vec t = tcg_temp_new_vec_matching(d); +- TCGv_vec m = tcg_temp_new_vec_matching(d); ++ TCGv_vec t = tcg_temp_new_vec_matching(d); ++ TCGv_vec m = tcg_temp_new_vec_matching(d); + +- tcg_gen_dupi_vec(vece, m, MAKE_64BIT_MASK(0, sh)); +- tcg_gen_shli_vec(vece, t, a, sh); +- tcg_gen_and_vec(vece, d, d, m); +- tcg_gen_or_vec(vece, d, d, t); ++ tcg_gen_shli_vec(vece, t, a, sh); ++ tcg_gen_dupi_vec(vece, m, MAKE_64BIT_MASK(0, sh)); ++ tcg_gen_and_vec(vece, d, d, m); ++ tcg_gen_or_vec(vece, d, d, t); + +- tcg_temp_free_vec(t); +- tcg_temp_free_vec(m); +- } ++ tcg_temp_free_vec(t); ++ tcg_temp_free_vec(m); + } + +-static const TCGOpcode vecop_list_sli[] = { INDEX_op_shli_vec, 0 }; ++void gen_gvec_sli(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs, ++ int64_t shift, uint32_t opr_sz, uint32_t max_sz) ++{ ++ static const TCGOpcode vecop_list[] = { INDEX_op_shli_vec, 0 }; ++ const GVecGen2i ops[4] = { ++ { .fni8 = gen_shl8_ins_i64, ++ .fniv = gen_shl_ins_vec, ++ .fno = gen_helper_gvec_sli_b, ++ .load_dest = true, ++ .opt_opc = vecop_list, ++ .vece = MO_8 }, ++ { .fni8 = gen_shl16_ins_i64, ++ .fniv = gen_shl_ins_vec, ++ .fno = gen_helper_gvec_sli_h, ++ .load_dest = true, ++ .opt_opc = vecop_list, ++ .vece = MO_16 }, ++ { .fni4 = gen_shl32_ins_i32, ++ .fniv = gen_shl_ins_vec, ++ .fno = gen_helper_gvec_sli_s, ++ .load_dest = true, ++ .opt_opc = vecop_list, ++ .vece = MO_32 }, ++ { .fni8 = gen_shl64_ins_i64, ++ .fniv = gen_shl_ins_vec, ++ .fno = gen_helper_gvec_sli_d, ++ .prefer_i64 = TCG_TARGET_REG_BITS == 64, ++ .load_dest = true, ++ .opt_opc = vecop_list, ++ .vece = MO_64 }, ++ }; ++ ++ /* tszimm encoding produces immediates in the range [0..esize-1]. */ ++ tcg_debug_assert(shift >= 0); ++ tcg_debug_assert(shift < (8 << vece)); + +-const GVecGen2i sli_op[4] = { +- { .fni8 = gen_shl8_ins_i64, +- .fniv = gen_shl_ins_vec, +- .load_dest = true, +- .opt_opc = vecop_list_sli, +- .vece = MO_8 }, +- { .fni8 = gen_shl16_ins_i64, +- .fniv = gen_shl_ins_vec, +- .load_dest = true, +- .opt_opc = vecop_list_sli, +- .vece = MO_16 }, +- { .fni4 = gen_shl32_ins_i32, +- .fniv = gen_shl_ins_vec, +- .load_dest = true, +- .opt_opc = vecop_list_sli, +- .vece = MO_32 }, +- { .fni8 = gen_shl64_ins_i64, +- .fniv = gen_shl_ins_vec, +- .prefer_i64 = TCG_TARGET_REG_BITS == 64, +- .load_dest = true, +- .opt_opc = vecop_list_sli, +- .vece = MO_64 }, +-}; ++ if (shift == 0) { ++ tcg_gen_gvec_mov(vece, rd_ofs, rm_ofs, opr_sz, max_sz); ++ } else { ++ tcg_gen_gvec_2i(rd_ofs, rm_ofs, opr_sz, max_sz, shift, &ops[vece]); ++ } ++} + + static void gen_mla8_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b) + { +@@ -5715,20 +5743,14 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn) + } + /* Right shift comes here negative. */ + shift = -shift; +- /* Shift out of range leaves destination unchanged. */ +- if (shift < 8 << size) { +- tcg_gen_gvec_2i(rd_ofs, rm_ofs, vec_size, vec_size, +- shift, &sri_op[size]); +- } ++ gen_gvec_sri(size, rd_ofs, rm_ofs, shift, ++ vec_size, vec_size); + return 0; + + case 5: /* VSHL, VSLI */ + if (u) { /* VSLI */ +- /* Shift out of range leaves destination unchanged. */ +- if (shift < 8 << size) { +- tcg_gen_gvec_2i(rd_ofs, rm_ofs, vec_size, +- vec_size, shift, &sli_op[size]); +- } ++ gen_gvec_sli(size, rd_ofs, rm_ofs, shift, ++ vec_size, vec_size); + } else { /* VSHL */ + /* Shifts larger than the element size are + * architecturally valid and results in zero. +diff --git a/target/arm/translate.h b/target/arm/translate.h +index 1db3b43a61..fa5c3f12b9 100644 +--- a/target/arm/translate.h ++++ b/target/arm/translate.h +@@ -285,8 +285,6 @@ extern const GVecGen3 mls_op[4]; + extern const GVecGen3 cmtst_op[4]; + extern const GVecGen3 sshl_op[4]; + extern const GVecGen3 ushl_op[4]; +-extern const GVecGen2i sri_op[4]; +-extern const GVecGen2i sli_op[4]; + extern const GVecGen4 uqadd_op[4]; + extern const GVecGen4 sqadd_op[4]; + extern const GVecGen4 uqsub_op[4]; +@@ -311,6 +309,11 @@ void gen_gvec_srsra(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs, + void gen_gvec_ursra(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs, + int64_t shift, uint32_t opr_sz, uint32_t max_sz); + ++void gen_gvec_sri(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs, ++ int64_t shift, uint32_t opr_sz, uint32_t max_sz); ++void gen_gvec_sli(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs, ++ int64_t shift, uint32_t opr_sz, uint32_t max_sz); ++ + /* + * Forward to the isar_feature_* tests given a DisasContext pointer. + */ +diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c +index fd8b2bff49..096fea67ef 100644 +--- a/target/arm/vec_helper.c ++++ b/target/arm/vec_helper.c +@@ -974,6 +974,44 @@ DO_RSRA(gvec_ursra_d, uint64_t) + + #undef DO_RSRA + ++#define DO_SRI(NAME, TYPE) \ ++void HELPER(NAME)(void *vd, void *vn, uint32_t desc) \ ++{ \ ++ intptr_t i, oprsz = simd_oprsz(desc); \ ++ int shift = simd_data(desc); \ ++ TYPE *d = vd, *n = vn; \ ++ for (i = 0; i < oprsz / sizeof(TYPE); i++) { \ ++ d[i] = deposit64(d[i], 0, sizeof(TYPE) * 8 - shift, n[i] >> shift); \ ++ } \ ++ clear_tail(d, oprsz, simd_maxsz(desc)); \ ++} ++ ++DO_SRI(gvec_sri_b, uint8_t) ++DO_SRI(gvec_sri_h, uint16_t) ++DO_SRI(gvec_sri_s, uint32_t) ++DO_SRI(gvec_sri_d, uint64_t) ++ ++#undef DO_SRI ++ ++#define DO_SLI(NAME, TYPE) \ ++void HELPER(NAME)(void *vd, void *vn, uint32_t desc) \ ++{ \ ++ intptr_t i, oprsz = simd_oprsz(desc); \ ++ int shift = simd_data(desc); \ ++ TYPE *d = vd, *n = vn; \ ++ for (i = 0; i < oprsz / sizeof(TYPE); i++) { \ ++ d[i] = deposit64(d[i], shift, sizeof(TYPE) * 8 - shift, n[i]); \ ++ } \ ++ clear_tail(d, oprsz, simd_maxsz(desc)); \ ++} ++ ++DO_SLI(gvec_sli_b, uint8_t) ++DO_SLI(gvec_sli_h, uint16_t) ++DO_SLI(gvec_sli_s, uint32_t) ++DO_SLI(gvec_sli_d, uint64_t) ++ ++#undef DO_SLI ++ + /* + * Convert float16 to float32, raising no exceptions and + * preserving exceptional values, including SNaN. +-- +2.23.0 + diff --git a/target-arm-Create-gen_gvec_-u-s-rshr-rsra.patch b/target-arm-Create-gen_gvec_-u-s-rshr-rsra.patch new file mode 100644 index 0000000000000000000000000000000000000000..512cf4bd3ee3fb94039acff03e2ec1729bbba43a --- /dev/null +++ b/target-arm-Create-gen_gvec_-u-s-rshr-rsra.patch @@ -0,0 +1,668 @@ +From 6ccd48d4ea244c1c46a24dfa50bfb547f11422dd Mon Sep 17 00:00:00 2001 +From: Richard Henderson +Date: Wed, 13 May 2020 09:32:31 -0700 +Subject: [PATCH 420/709] target/arm: Create gen_gvec_{u,s}{rshr,rsra} + +Create vectorized versions of handle_shri_with_rndacc +for shift+round and shift+round+accumulate. Add out-of-line +helpers in preparation for longer vector lengths from SVE. + +Reviewed-by: Peter Maydell +Signed-off-by: Richard Henderson +Message-id: 20200513163245.17915-3-richard.henderson@linaro.org +Signed-off-by: Peter Maydell +--- + target/arm/helper.h | 20 ++ + target/arm/translate-a64.c | 11 +- + target/arm/translate.c | 463 +++++++++++++++++++++++++++++++++++-- + target/arm/translate.h | 9 + + target/arm/vec_helper.c | 50 ++++ + 5 files changed, 527 insertions(+), 26 deletions(-) + +diff --git a/target/arm/helper.h b/target/arm/helper.h +index 9bc162345c..aeb1f52455 100644 +--- a/target/arm/helper.h ++++ b/target/arm/helper.h +@@ -701,6 +701,26 @@ DEF_HELPER_FLAGS_3(gvec_usra_h, TCG_CALL_NO_RWG, void, ptr, ptr, i32) + DEF_HELPER_FLAGS_3(gvec_usra_s, TCG_CALL_NO_RWG, void, ptr, ptr, i32) + DEF_HELPER_FLAGS_3(gvec_usra_d, TCG_CALL_NO_RWG, void, ptr, ptr, i32) + ++DEF_HELPER_FLAGS_3(gvec_srshr_b, TCG_CALL_NO_RWG, void, ptr, ptr, i32) ++DEF_HELPER_FLAGS_3(gvec_srshr_h, TCG_CALL_NO_RWG, void, ptr, ptr, i32) ++DEF_HELPER_FLAGS_3(gvec_srshr_s, TCG_CALL_NO_RWG, void, ptr, ptr, i32) ++DEF_HELPER_FLAGS_3(gvec_srshr_d, TCG_CALL_NO_RWG, void, ptr, ptr, i32) ++ ++DEF_HELPER_FLAGS_3(gvec_urshr_b, TCG_CALL_NO_RWG, void, ptr, ptr, i32) ++DEF_HELPER_FLAGS_3(gvec_urshr_h, TCG_CALL_NO_RWG, void, ptr, ptr, i32) ++DEF_HELPER_FLAGS_3(gvec_urshr_s, TCG_CALL_NO_RWG, void, ptr, ptr, i32) ++DEF_HELPER_FLAGS_3(gvec_urshr_d, TCG_CALL_NO_RWG, void, ptr, ptr, i32) ++ ++DEF_HELPER_FLAGS_3(gvec_srsra_b, TCG_CALL_NO_RWG, void, ptr, ptr, i32) ++DEF_HELPER_FLAGS_3(gvec_srsra_h, TCG_CALL_NO_RWG, void, ptr, ptr, i32) ++DEF_HELPER_FLAGS_3(gvec_srsra_s, TCG_CALL_NO_RWG, void, ptr, ptr, i32) ++DEF_HELPER_FLAGS_3(gvec_srsra_d, TCG_CALL_NO_RWG, void, ptr, ptr, i32) ++ ++DEF_HELPER_FLAGS_3(gvec_ursra_b, TCG_CALL_NO_RWG, void, ptr, ptr, i32) ++DEF_HELPER_FLAGS_3(gvec_ursra_h, TCG_CALL_NO_RWG, void, ptr, ptr, i32) ++DEF_HELPER_FLAGS_3(gvec_ursra_s, TCG_CALL_NO_RWG, void, ptr, ptr, i32) ++DEF_HELPER_FLAGS_3(gvec_ursra_d, TCG_CALL_NO_RWG, void, ptr, ptr, i32) ++ + #ifdef TARGET_AARCH64 + #include "helper-a64.h" + #include "helper-sve.h" +diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c +index 315de9a9b6..50949d306b 100644 +--- a/target/arm/translate-a64.c ++++ b/target/arm/translate-a64.c +@@ -10218,10 +10218,15 @@ static void handle_vec_simd_shri(DisasContext *s, bool is_q, bool is_u, + return; + + case 0x04: /* SRSHR / URSHR (rounding) */ +- break; ++ gen_gvec_fn2i(s, is_q, rd, rn, shift, ++ is_u ? gen_gvec_urshr : gen_gvec_srshr, size); ++ return; ++ + case 0x06: /* SRSRA / URSRA (accum + rounding) */ +- accumulate = true; +- break; ++ gen_gvec_fn2i(s, is_q, rd, rn, shift, ++ is_u ? gen_gvec_ursra : gen_gvec_srsra, size); ++ return; ++ + default: + g_assert_not_reached(); + } +diff --git a/target/arm/translate.c b/target/arm/translate.c +index c18140f2e6..aa03dc236b 100644 +--- a/target/arm/translate.c ++++ b/target/arm/translate.c +@@ -4000,6 +4000,422 @@ void gen_gvec_usra(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs, + } + } + ++/* ++ * Shift one less than the requested amount, and the low bit is ++ * the rounding bit. For the 8 and 16-bit operations, because we ++ * mask the low bit, we can perform a normal integer shift instead ++ * of a vector shift. ++ */ ++static void gen_srshr8_i64(TCGv_i64 d, TCGv_i64 a, int64_t sh) ++{ ++ TCGv_i64 t = tcg_temp_new_i64(); ++ ++ tcg_gen_shri_i64(t, a, sh - 1); ++ tcg_gen_andi_i64(t, t, dup_const(MO_8, 1)); ++ tcg_gen_vec_sar8i_i64(d, a, sh); ++ tcg_gen_vec_add8_i64(d, d, t); ++ tcg_temp_free_i64(t); ++} ++ ++static void gen_srshr16_i64(TCGv_i64 d, TCGv_i64 a, int64_t sh) ++{ ++ TCGv_i64 t = tcg_temp_new_i64(); ++ ++ tcg_gen_shri_i64(t, a, sh - 1); ++ tcg_gen_andi_i64(t, t, dup_const(MO_16, 1)); ++ tcg_gen_vec_sar16i_i64(d, a, sh); ++ tcg_gen_vec_add16_i64(d, d, t); ++ tcg_temp_free_i64(t); ++} ++ ++static void gen_srshr32_i32(TCGv_i32 d, TCGv_i32 a, int32_t sh) ++{ ++ TCGv_i32 t = tcg_temp_new_i32(); ++ ++ tcg_gen_extract_i32(t, a, sh - 1, 1); ++ tcg_gen_sari_i32(d, a, sh); ++ tcg_gen_add_i32(d, d, t); ++ tcg_temp_free_i32(t); ++} ++ ++static void gen_srshr64_i64(TCGv_i64 d, TCGv_i64 a, int64_t sh) ++{ ++ TCGv_i64 t = tcg_temp_new_i64(); ++ ++ tcg_gen_extract_i64(t, a, sh - 1, 1); ++ tcg_gen_sari_i64(d, a, sh); ++ tcg_gen_add_i64(d, d, t); ++ tcg_temp_free_i64(t); ++} ++ ++static void gen_srshr_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t sh) ++{ ++ TCGv_vec t = tcg_temp_new_vec_matching(d); ++ TCGv_vec ones = tcg_temp_new_vec_matching(d); ++ ++ tcg_gen_shri_vec(vece, t, a, sh - 1); ++ tcg_gen_dupi_vec(vece, ones, 1); ++ tcg_gen_and_vec(vece, t, t, ones); ++ tcg_gen_sari_vec(vece, d, a, sh); ++ tcg_gen_add_vec(vece, d, d, t); ++ ++ tcg_temp_free_vec(t); ++ tcg_temp_free_vec(ones); ++} ++ ++void gen_gvec_srshr(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs, ++ int64_t shift, uint32_t opr_sz, uint32_t max_sz) ++{ ++ static const TCGOpcode vecop_list[] = { ++ INDEX_op_shri_vec, INDEX_op_sari_vec, INDEX_op_add_vec, 0 ++ }; ++ static const GVecGen2i ops[4] = { ++ { .fni8 = gen_srshr8_i64, ++ .fniv = gen_srshr_vec, ++ .fno = gen_helper_gvec_srshr_b, ++ .opt_opc = vecop_list, ++ .vece = MO_8 }, ++ { .fni8 = gen_srshr16_i64, ++ .fniv = gen_srshr_vec, ++ .fno = gen_helper_gvec_srshr_h, ++ .opt_opc = vecop_list, ++ .vece = MO_16 }, ++ { .fni4 = gen_srshr32_i32, ++ .fniv = gen_srshr_vec, ++ .fno = gen_helper_gvec_srshr_s, ++ .opt_opc = vecop_list, ++ .vece = MO_32 }, ++ { .fni8 = gen_srshr64_i64, ++ .fniv = gen_srshr_vec, ++ .fno = gen_helper_gvec_srshr_d, ++ .prefer_i64 = TCG_TARGET_REG_BITS == 64, ++ .opt_opc = vecop_list, ++ .vece = MO_64 }, ++ }; ++ ++ /* tszimm encoding produces immediates in the range [1..esize] */ ++ tcg_debug_assert(shift > 0); ++ tcg_debug_assert(shift <= (8 << vece)); ++ ++ if (shift == (8 << vece)) { ++ /* ++ * Shifts larger than the element size are architecturally valid. ++ * Signed results in all sign bits. With rounding, this produces ++ * (-1 + 1) >> 1 == 0, or (0 + 1) >> 1 == 0. ++ * I.e. always zero. ++ */ ++ tcg_gen_gvec_dup_imm(vece, rd_ofs, opr_sz, max_sz, 0); ++ } else { ++ tcg_gen_gvec_2i(rd_ofs, rm_ofs, opr_sz, max_sz, shift, &ops[vece]); ++ } ++} ++ ++static void gen_srsra8_i64(TCGv_i64 d, TCGv_i64 a, int64_t sh) ++{ ++ TCGv_i64 t = tcg_temp_new_i64(); ++ ++ gen_srshr8_i64(t, a, sh); ++ tcg_gen_vec_add8_i64(d, d, t); ++ tcg_temp_free_i64(t); ++} ++ ++static void gen_srsra16_i64(TCGv_i64 d, TCGv_i64 a, int64_t sh) ++{ ++ TCGv_i64 t = tcg_temp_new_i64(); ++ ++ gen_srshr16_i64(t, a, sh); ++ tcg_gen_vec_add16_i64(d, d, t); ++ tcg_temp_free_i64(t); ++} ++ ++static void gen_srsra32_i32(TCGv_i32 d, TCGv_i32 a, int32_t sh) ++{ ++ TCGv_i32 t = tcg_temp_new_i32(); ++ ++ gen_srshr32_i32(t, a, sh); ++ tcg_gen_add_i32(d, d, t); ++ tcg_temp_free_i32(t); ++} ++ ++static void gen_srsra64_i64(TCGv_i64 d, TCGv_i64 a, int64_t sh) ++{ ++ TCGv_i64 t = tcg_temp_new_i64(); ++ ++ gen_srshr64_i64(t, a, sh); ++ tcg_gen_add_i64(d, d, t); ++ tcg_temp_free_i64(t); ++} ++ ++static void gen_srsra_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t sh) ++{ ++ TCGv_vec t = tcg_temp_new_vec_matching(d); ++ ++ gen_srshr_vec(vece, t, a, sh); ++ tcg_gen_add_vec(vece, d, d, t); ++ tcg_temp_free_vec(t); ++} ++ ++void gen_gvec_srsra(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs, ++ int64_t shift, uint32_t opr_sz, uint32_t max_sz) ++{ ++ static const TCGOpcode vecop_list[] = { ++ INDEX_op_shri_vec, INDEX_op_sari_vec, INDEX_op_add_vec, 0 ++ }; ++ static const GVecGen2i ops[4] = { ++ { .fni8 = gen_srsra8_i64, ++ .fniv = gen_srsra_vec, ++ .fno = gen_helper_gvec_srsra_b, ++ .opt_opc = vecop_list, ++ .load_dest = true, ++ .vece = MO_8 }, ++ { .fni8 = gen_srsra16_i64, ++ .fniv = gen_srsra_vec, ++ .fno = gen_helper_gvec_srsra_h, ++ .opt_opc = vecop_list, ++ .load_dest = true, ++ .vece = MO_16 }, ++ { .fni4 = gen_srsra32_i32, ++ .fniv = gen_srsra_vec, ++ .fno = gen_helper_gvec_srsra_s, ++ .opt_opc = vecop_list, ++ .load_dest = true, ++ .vece = MO_32 }, ++ { .fni8 = gen_srsra64_i64, ++ .fniv = gen_srsra_vec, ++ .fno = gen_helper_gvec_srsra_d, ++ .prefer_i64 = TCG_TARGET_REG_BITS == 64, ++ .opt_opc = vecop_list, ++ .load_dest = true, ++ .vece = MO_64 }, ++ }; ++ ++ /* tszimm encoding produces immediates in the range [1..esize] */ ++ tcg_debug_assert(shift > 0); ++ tcg_debug_assert(shift <= (8 << vece)); ++ ++ /* ++ * Shifts larger than the element size are architecturally valid. ++ * Signed results in all sign bits. With rounding, this produces ++ * (-1 + 1) >> 1 == 0, or (0 + 1) >> 1 == 0. ++ * I.e. always zero. With accumulation, this leaves D unchanged. ++ */ ++ if (shift == (8 << vece)) { ++ /* Nop, but we do need to clear the tail. */ ++ tcg_gen_gvec_mov(vece, rd_ofs, rd_ofs, opr_sz, max_sz); ++ } else { ++ tcg_gen_gvec_2i(rd_ofs, rm_ofs, opr_sz, max_sz, shift, &ops[vece]); ++ } ++} ++ ++static void gen_urshr8_i64(TCGv_i64 d, TCGv_i64 a, int64_t sh) ++{ ++ TCGv_i64 t = tcg_temp_new_i64(); ++ ++ tcg_gen_shri_i64(t, a, sh - 1); ++ tcg_gen_andi_i64(t, t, dup_const(MO_8, 1)); ++ tcg_gen_vec_shr8i_i64(d, a, sh); ++ tcg_gen_vec_add8_i64(d, d, t); ++ tcg_temp_free_i64(t); ++} ++ ++static void gen_urshr16_i64(TCGv_i64 d, TCGv_i64 a, int64_t sh) ++{ ++ TCGv_i64 t = tcg_temp_new_i64(); ++ ++ tcg_gen_shri_i64(t, a, sh - 1); ++ tcg_gen_andi_i64(t, t, dup_const(MO_16, 1)); ++ tcg_gen_vec_shr16i_i64(d, a, sh); ++ tcg_gen_vec_add16_i64(d, d, t); ++ tcg_temp_free_i64(t); ++} ++ ++static void gen_urshr32_i32(TCGv_i32 d, TCGv_i32 a, int32_t sh) ++{ ++ TCGv_i32 t = tcg_temp_new_i32(); ++ ++ tcg_gen_extract_i32(t, a, sh - 1, 1); ++ tcg_gen_shri_i32(d, a, sh); ++ tcg_gen_add_i32(d, d, t); ++ tcg_temp_free_i32(t); ++} ++ ++static void gen_urshr64_i64(TCGv_i64 d, TCGv_i64 a, int64_t sh) ++{ ++ TCGv_i64 t = tcg_temp_new_i64(); ++ ++ tcg_gen_extract_i64(t, a, sh - 1, 1); ++ tcg_gen_shri_i64(d, a, sh); ++ tcg_gen_add_i64(d, d, t); ++ tcg_temp_free_i64(t); ++} ++ ++static void gen_urshr_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t shift) ++{ ++ TCGv_vec t = tcg_temp_new_vec_matching(d); ++ TCGv_vec ones = tcg_temp_new_vec_matching(d); ++ ++ tcg_gen_shri_vec(vece, t, a, shift - 1); ++ tcg_gen_dupi_vec(vece, ones, 1); ++ tcg_gen_and_vec(vece, t, t, ones); ++ tcg_gen_shri_vec(vece, d, a, shift); ++ tcg_gen_add_vec(vece, d, d, t); ++ ++ tcg_temp_free_vec(t); ++ tcg_temp_free_vec(ones); ++} ++ ++void gen_gvec_urshr(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs, ++ int64_t shift, uint32_t opr_sz, uint32_t max_sz) ++{ ++ static const TCGOpcode vecop_list[] = { ++ INDEX_op_shri_vec, INDEX_op_add_vec, 0 ++ }; ++ static const GVecGen2i ops[4] = { ++ { .fni8 = gen_urshr8_i64, ++ .fniv = gen_urshr_vec, ++ .fno = gen_helper_gvec_urshr_b, ++ .opt_opc = vecop_list, ++ .vece = MO_8 }, ++ { .fni8 = gen_urshr16_i64, ++ .fniv = gen_urshr_vec, ++ .fno = gen_helper_gvec_urshr_h, ++ .opt_opc = vecop_list, ++ .vece = MO_16 }, ++ { .fni4 = gen_urshr32_i32, ++ .fniv = gen_urshr_vec, ++ .fno = gen_helper_gvec_urshr_s, ++ .opt_opc = vecop_list, ++ .vece = MO_32 }, ++ { .fni8 = gen_urshr64_i64, ++ .fniv = gen_urshr_vec, ++ .fno = gen_helper_gvec_urshr_d, ++ .prefer_i64 = TCG_TARGET_REG_BITS == 64, ++ .opt_opc = vecop_list, ++ .vece = MO_64 }, ++ }; ++ ++ /* tszimm encoding produces immediates in the range [1..esize] */ ++ tcg_debug_assert(shift > 0); ++ tcg_debug_assert(shift <= (8 << vece)); ++ ++ if (shift == (8 << vece)) { ++ /* ++ * Shifts larger than the element size are architecturally valid. ++ * Unsigned results in zero. With rounding, this produces a ++ * copy of the most significant bit. ++ */ ++ tcg_gen_gvec_shri(vece, rd_ofs, rm_ofs, shift - 1, opr_sz, max_sz); ++ } else { ++ tcg_gen_gvec_2i(rd_ofs, rm_ofs, opr_sz, max_sz, shift, &ops[vece]); ++ } ++} ++ ++static void gen_ursra8_i64(TCGv_i64 d, TCGv_i64 a, int64_t sh) ++{ ++ TCGv_i64 t = tcg_temp_new_i64(); ++ ++ if (sh == 8) { ++ tcg_gen_vec_shr8i_i64(t, a, 7); ++ } else { ++ gen_urshr8_i64(t, a, sh); ++ } ++ tcg_gen_vec_add8_i64(d, d, t); ++ tcg_temp_free_i64(t); ++} ++ ++static void gen_ursra16_i64(TCGv_i64 d, TCGv_i64 a, int64_t sh) ++{ ++ TCGv_i64 t = tcg_temp_new_i64(); ++ ++ if (sh == 16) { ++ tcg_gen_vec_shr16i_i64(t, a, 15); ++ } else { ++ gen_urshr16_i64(t, a, sh); ++ } ++ tcg_gen_vec_add16_i64(d, d, t); ++ tcg_temp_free_i64(t); ++} ++ ++static void gen_ursra32_i32(TCGv_i32 d, TCGv_i32 a, int32_t sh) ++{ ++ TCGv_i32 t = tcg_temp_new_i32(); ++ ++ if (sh == 32) { ++ tcg_gen_shri_i32(t, a, 31); ++ } else { ++ gen_urshr32_i32(t, a, sh); ++ } ++ tcg_gen_add_i32(d, d, t); ++ tcg_temp_free_i32(t); ++} ++ ++static void gen_ursra64_i64(TCGv_i64 d, TCGv_i64 a, int64_t sh) ++{ ++ TCGv_i64 t = tcg_temp_new_i64(); ++ ++ if (sh == 64) { ++ tcg_gen_shri_i64(t, a, 63); ++ } else { ++ gen_urshr64_i64(t, a, sh); ++ } ++ tcg_gen_add_i64(d, d, t); ++ tcg_temp_free_i64(t); ++} ++ ++static void gen_ursra_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t sh) ++{ ++ TCGv_vec t = tcg_temp_new_vec_matching(d); ++ ++ if (sh == (8 << vece)) { ++ tcg_gen_shri_vec(vece, t, a, sh - 1); ++ } else { ++ gen_urshr_vec(vece, t, a, sh); ++ } ++ tcg_gen_add_vec(vece, d, d, t); ++ tcg_temp_free_vec(t); ++} ++ ++void gen_gvec_ursra(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs, ++ int64_t shift, uint32_t opr_sz, uint32_t max_sz) ++{ ++ static const TCGOpcode vecop_list[] = { ++ INDEX_op_shri_vec, INDEX_op_add_vec, 0 ++ }; ++ static const GVecGen2i ops[4] = { ++ { .fni8 = gen_ursra8_i64, ++ .fniv = gen_ursra_vec, ++ .fno = gen_helper_gvec_ursra_b, ++ .opt_opc = vecop_list, ++ .load_dest = true, ++ .vece = MO_8 }, ++ { .fni8 = gen_ursra16_i64, ++ .fniv = gen_ursra_vec, ++ .fno = gen_helper_gvec_ursra_h, ++ .opt_opc = vecop_list, ++ .load_dest = true, ++ .vece = MO_16 }, ++ { .fni4 = gen_ursra32_i32, ++ .fniv = gen_ursra_vec, ++ .fno = gen_helper_gvec_ursra_s, ++ .opt_opc = vecop_list, ++ .load_dest = true, ++ .vece = MO_32 }, ++ { .fni8 = gen_ursra64_i64, ++ .fniv = gen_ursra_vec, ++ .fno = gen_helper_gvec_ursra_d, ++ .prefer_i64 = TCG_TARGET_REG_BITS == 64, ++ .opt_opc = vecop_list, ++ .load_dest = true, ++ .vece = MO_64 }, ++ }; ++ ++ /* tszimm encoding produces immediates in the range [1..esize] */ ++ tcg_debug_assert(shift > 0); ++ tcg_debug_assert(shift <= (8 << vece)); ++ ++ tcg_gen_gvec_2i(rd_ofs, rm_ofs, opr_sz, max_sz, shift, &ops[vece]); ++} ++ + static void gen_shr8_ins_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift) + { + uint64_t mask = dup_const(MO_8, 0xff >> shift); +@@ -5269,6 +5685,30 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn) + } + return 0; + ++ case 2: /* VRSHR */ ++ /* Right shift comes here negative. */ ++ shift = -shift; ++ if (u) { ++ gen_gvec_urshr(size, rd_ofs, rm_ofs, shift, ++ vec_size, vec_size); ++ } else { ++ gen_gvec_srshr(size, rd_ofs, rm_ofs, shift, ++ vec_size, vec_size); ++ } ++ return 0; ++ ++ case 3: /* VRSRA */ ++ /* Right shift comes here negative. */ ++ shift = -shift; ++ if (u) { ++ gen_gvec_ursra(size, rd_ofs, rm_ofs, shift, ++ vec_size, vec_size); ++ } else { ++ gen_gvec_srsra(size, rd_ofs, rm_ofs, shift, ++ vec_size, vec_size); ++ } ++ return 0; ++ + case 4: /* VSRI */ + if (!u) { + return 1; +@@ -5320,13 +5760,6 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn) + neon_load_reg64(cpu_V0, rm + pass); + tcg_gen_movi_i64(cpu_V1, imm); + switch (op) { +- case 2: /* VRSHR */ +- case 3: /* VRSRA */ +- if (u) +- gen_helper_neon_rshl_u64(cpu_V0, cpu_V0, cpu_V1); +- else +- gen_helper_neon_rshl_s64(cpu_V0, cpu_V0, cpu_V1); +- break; + case 6: /* VQSHLU */ + gen_helper_neon_qshlu_s64(cpu_V0, cpu_env, + cpu_V0, cpu_V1); +@@ -5343,11 +5776,6 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn) + default: + g_assert_not_reached(); + } +- if (op == 3) { +- /* Accumulate. */ +- neon_load_reg64(cpu_V1, rd + pass); +- tcg_gen_add_i64(cpu_V0, cpu_V0, cpu_V1); +- } + neon_store_reg64(cpu_V0, rd + pass); + } else { /* size < 3 */ + /* Operands in T0 and T1. */ +@@ -5355,10 +5783,6 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn) + tmp2 = tcg_temp_new_i32(); + tcg_gen_movi_i32(tmp2, imm); + switch (op) { +- case 2: /* VRSHR */ +- case 3: /* VRSRA */ +- GEN_NEON_INTEGER_OP(rshl); +- break; + case 6: /* VQSHLU */ + switch (size) { + case 0: +@@ -5384,13 +5808,6 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn) + g_assert_not_reached(); + } + tcg_temp_free_i32(tmp2); +- +- if (op == 3) { +- /* Accumulate. */ +- tmp2 = neon_load_reg(rd, pass); +- gen_neon_add(size, tmp, tmp2); +- tcg_temp_free_i32(tmp2); +- } + neon_store_reg(rd, pass, tmp); + } + } /* for pass */ +diff --git a/target/arm/translate.h b/target/arm/translate.h +index 1839a59a8e..1db3b43a61 100644 +--- a/target/arm/translate.h ++++ b/target/arm/translate.h +@@ -302,6 +302,15 @@ void gen_gvec_ssra(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs, + void gen_gvec_usra(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs, + int64_t shift, uint32_t opr_sz, uint32_t max_sz); + ++void gen_gvec_srshr(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs, ++ int64_t shift, uint32_t opr_sz, uint32_t max_sz); ++void gen_gvec_urshr(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs, ++ int64_t shift, uint32_t opr_sz, uint32_t max_sz); ++void gen_gvec_srsra(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs, ++ int64_t shift, uint32_t opr_sz, uint32_t max_sz); ++void gen_gvec_ursra(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs, ++ int64_t shift, uint32_t opr_sz, uint32_t max_sz); ++ + /* + * Forward to the isar_feature_* tests given a DisasContext pointer. + */ +diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c +index 230085b35e..fd8b2bff49 100644 +--- a/target/arm/vec_helper.c ++++ b/target/arm/vec_helper.c +@@ -924,6 +924,56 @@ DO_SRA(gvec_usra_d, uint64_t) + + #undef DO_SRA + ++#define DO_RSHR(NAME, TYPE) \ ++void HELPER(NAME)(void *vd, void *vn, uint32_t desc) \ ++{ \ ++ intptr_t i, oprsz = simd_oprsz(desc); \ ++ int shift = simd_data(desc); \ ++ TYPE *d = vd, *n = vn; \ ++ for (i = 0; i < oprsz / sizeof(TYPE); i++) { \ ++ TYPE tmp = n[i] >> (shift - 1); \ ++ d[i] = (tmp >> 1) + (tmp & 1); \ ++ } \ ++ clear_tail(d, oprsz, simd_maxsz(desc)); \ ++} ++ ++DO_RSHR(gvec_srshr_b, int8_t) ++DO_RSHR(gvec_srshr_h, int16_t) ++DO_RSHR(gvec_srshr_s, int32_t) ++DO_RSHR(gvec_srshr_d, int64_t) ++ ++DO_RSHR(gvec_urshr_b, uint8_t) ++DO_RSHR(gvec_urshr_h, uint16_t) ++DO_RSHR(gvec_urshr_s, uint32_t) ++DO_RSHR(gvec_urshr_d, uint64_t) ++ ++#undef DO_RSHR ++ ++#define DO_RSRA(NAME, TYPE) \ ++void HELPER(NAME)(void *vd, void *vn, uint32_t desc) \ ++{ \ ++ intptr_t i, oprsz = simd_oprsz(desc); \ ++ int shift = simd_data(desc); \ ++ TYPE *d = vd, *n = vn; \ ++ for (i = 0; i < oprsz / sizeof(TYPE); i++) { \ ++ TYPE tmp = n[i] >> (shift - 1); \ ++ d[i] += (tmp >> 1) + (tmp & 1); \ ++ } \ ++ clear_tail(d, oprsz, simd_maxsz(desc)); \ ++} ++ ++DO_RSRA(gvec_srsra_b, int8_t) ++DO_RSRA(gvec_srsra_h, int16_t) ++DO_RSRA(gvec_srsra_s, int32_t) ++DO_RSRA(gvec_srsra_d, int64_t) ++ ++DO_RSRA(gvec_ursra_b, uint8_t) ++DO_RSRA(gvec_ursra_h, uint16_t) ++DO_RSRA(gvec_ursra_s, uint32_t) ++DO_RSRA(gvec_ursra_d, uint64_t) ++ ++#undef DO_RSRA ++ + /* + * Convert float16 to float32, raising no exceptions and + * preserving exceptional values, including SNaN. +-- +2.23.0 + diff --git a/target-arm-Create-gen_gvec_-uqadd-sqadd-uqsub-sqsub.patch b/target-arm-Create-gen_gvec_-uqadd-sqadd-uqsub-sqsub.patch new file mode 100644 index 0000000000000000000000000000000000000000..68a82cb9dcb6baa41a5157e8d03bb5f80d2010cc --- /dev/null +++ b/target-arm-Create-gen_gvec_-uqadd-sqadd-uqsub-sqsub.patch @@ -0,0 +1,386 @@ +From c7715b6b51a6f7a5412c5fcb40a4c8586105e597 Mon Sep 17 00:00:00 2001 +From: Richard Henderson +Date: Wed, 13 May 2020 09:32:39 -0700 +Subject: [PATCH 428/709] target/arm: Create gen_gvec_{uqadd, sqadd, uqsub, + sqsub} + +Provide a functional interface for the vector expansion. +This fits better with the existing set of helpers that +we provide for other operations. + +Reviewed-by: Peter Maydell +Signed-off-by: Richard Henderson +Message-id: 20200513163245.17915-11-richard.henderson@linaro.org +Signed-off-by: Peter Maydell +--- + target/arm/translate-a64.c | 22 ++- + target/arm/translate-neon.inc.c | 19 +-- + target/arm/translate.c | 228 +++++++++++++++++--------------- + target/arm/translate.h | 13 +- + 4 files changed, 147 insertions(+), 135 deletions(-) + +diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c +index 3956c19ed8..ea5f6ceadc 100644 +--- a/target/arm/translate-a64.c ++++ b/target/arm/translate-a64.c +@@ -11168,20 +11168,18 @@ static void disas_simd_3same_int(DisasContext *s, uint32_t insn) + + switch (opcode) { + case 0x01: /* SQADD, UQADD */ +- tcg_gen_gvec_4(vec_full_reg_offset(s, rd), +- offsetof(CPUARMState, vfp.qc), +- vec_full_reg_offset(s, rn), +- vec_full_reg_offset(s, rm), +- is_q ? 16 : 8, vec_full_reg_size(s), +- (u ? uqadd_op : sqadd_op) + size); ++ if (u) { ++ gen_gvec_fn3(s, is_q, rd, rn, rm, gen_gvec_uqadd_qc, size); ++ } else { ++ gen_gvec_fn3(s, is_q, rd, rn, rm, gen_gvec_sqadd_qc, size); ++ } + return; + case 0x05: /* SQSUB, UQSUB */ +- tcg_gen_gvec_4(vec_full_reg_offset(s, rd), +- offsetof(CPUARMState, vfp.qc), +- vec_full_reg_offset(s, rn), +- vec_full_reg_offset(s, rm), +- is_q ? 16 : 8, vec_full_reg_size(s), +- (u ? uqsub_op : sqsub_op) + size); ++ if (u) { ++ gen_gvec_fn3(s, is_q, rd, rn, rm, gen_gvec_uqsub_qc, size); ++ } else { ++ gen_gvec_fn3(s, is_q, rd, rn, rm, gen_gvec_sqsub_qc, size); ++ } + return; + case 0x08: /* SSHL, USHL */ + if (u) { +diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c +index e16475c212..099491b16f 100644 +--- a/target/arm/translate-neon.inc.c ++++ b/target/arm/translate-neon.inc.c +@@ -605,6 +605,10 @@ DO_3SAME(VORN, tcg_gen_gvec_orc) + DO_3SAME(VEOR, tcg_gen_gvec_xor) + DO_3SAME(VSHL_S, gen_gvec_sshl) + DO_3SAME(VSHL_U, gen_gvec_ushl) ++DO_3SAME(VQADD_S, gen_gvec_sqadd_qc) ++DO_3SAME(VQADD_U, gen_gvec_uqadd_qc) ++DO_3SAME(VQSUB_S, gen_gvec_sqsub_qc) ++DO_3SAME(VQSUB_U, gen_gvec_uqsub_qc) + + /* These insns are all gvec_bitsel but with the inputs in various orders. */ + #define DO_3SAME_BITSEL(INSN, O1, O2, O3) \ +@@ -653,21 +657,6 @@ DO_3SAME_CMP(VCGE_S, TCG_COND_GE) + DO_3SAME_CMP(VCGE_U, TCG_COND_GEU) + DO_3SAME_CMP(VCEQ, TCG_COND_EQ) + +-#define DO_3SAME_GVEC4(INSN, OPARRAY) \ +- static void gen_##INSN##_3s(unsigned vece, uint32_t rd_ofs, \ +- uint32_t rn_ofs, uint32_t rm_ofs, \ +- uint32_t oprsz, uint32_t maxsz) \ +- { \ +- tcg_gen_gvec_4(rd_ofs, offsetof(CPUARMState, vfp.qc), \ +- rn_ofs, rm_ofs, oprsz, maxsz, &OPARRAY[vece]); \ +- } \ +- DO_3SAME(INSN, gen_##INSN##_3s) +- +-DO_3SAME_GVEC4(VQADD_S, sqadd_op) +-DO_3SAME_GVEC4(VQADD_U, uqadd_op) +-DO_3SAME_GVEC4(VQSUB_S, sqsub_op) +-DO_3SAME_GVEC4(VQSUB_U, uqsub_op) +- + static void gen_VMUL_p_3s(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs, + uint32_t rm_ofs, uint32_t oprsz, uint32_t maxsz) + { +diff --git a/target/arm/translate.c b/target/arm/translate.c +index df91ff73e3..7eb30cde60 100644 +--- a/target/arm/translate.c ++++ b/target/arm/translate.c +@@ -4925,32 +4925,37 @@ static void gen_uqadd_vec(unsigned vece, TCGv_vec t, TCGv_vec sat, + tcg_temp_free_vec(x); + } + +-static const TCGOpcode vecop_list_uqadd[] = { +- INDEX_op_usadd_vec, INDEX_op_cmp_vec, INDEX_op_add_vec, 0 +-}; +- +-const GVecGen4 uqadd_op[4] = { +- { .fniv = gen_uqadd_vec, +- .fno = gen_helper_gvec_uqadd_b, +- .write_aofs = true, +- .opt_opc = vecop_list_uqadd, +- .vece = MO_8 }, +- { .fniv = gen_uqadd_vec, +- .fno = gen_helper_gvec_uqadd_h, +- .write_aofs = true, +- .opt_opc = vecop_list_uqadd, +- .vece = MO_16 }, +- { .fniv = gen_uqadd_vec, +- .fno = gen_helper_gvec_uqadd_s, +- .write_aofs = true, +- .opt_opc = vecop_list_uqadd, +- .vece = MO_32 }, +- { .fniv = gen_uqadd_vec, +- .fno = gen_helper_gvec_uqadd_d, +- .write_aofs = true, +- .opt_opc = vecop_list_uqadd, +- .vece = MO_64 }, +-}; ++void gen_gvec_uqadd_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs, ++ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz) ++{ ++ static const TCGOpcode vecop_list[] = { ++ INDEX_op_usadd_vec, INDEX_op_cmp_vec, INDEX_op_add_vec, 0 ++ }; ++ static const GVecGen4 ops[4] = { ++ { .fniv = gen_uqadd_vec, ++ .fno = gen_helper_gvec_uqadd_b, ++ .write_aofs = true, ++ .opt_opc = vecop_list, ++ .vece = MO_8 }, ++ { .fniv = gen_uqadd_vec, ++ .fno = gen_helper_gvec_uqadd_h, ++ .write_aofs = true, ++ .opt_opc = vecop_list, ++ .vece = MO_16 }, ++ { .fniv = gen_uqadd_vec, ++ .fno = gen_helper_gvec_uqadd_s, ++ .write_aofs = true, ++ .opt_opc = vecop_list, ++ .vece = MO_32 }, ++ { .fniv = gen_uqadd_vec, ++ .fno = gen_helper_gvec_uqadd_d, ++ .write_aofs = true, ++ .opt_opc = vecop_list, ++ .vece = MO_64 }, ++ }; ++ tcg_gen_gvec_4(rd_ofs, offsetof(CPUARMState, vfp.qc), ++ rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]); ++} + + static void gen_sqadd_vec(unsigned vece, TCGv_vec t, TCGv_vec sat, + TCGv_vec a, TCGv_vec b) +@@ -4963,32 +4968,37 @@ static void gen_sqadd_vec(unsigned vece, TCGv_vec t, TCGv_vec sat, + tcg_temp_free_vec(x); + } + +-static const TCGOpcode vecop_list_sqadd[] = { +- INDEX_op_ssadd_vec, INDEX_op_cmp_vec, INDEX_op_add_vec, 0 +-}; +- +-const GVecGen4 sqadd_op[4] = { +- { .fniv = gen_sqadd_vec, +- .fno = gen_helper_gvec_sqadd_b, +- .opt_opc = vecop_list_sqadd, +- .write_aofs = true, +- .vece = MO_8 }, +- { .fniv = gen_sqadd_vec, +- .fno = gen_helper_gvec_sqadd_h, +- .opt_opc = vecop_list_sqadd, +- .write_aofs = true, +- .vece = MO_16 }, +- { .fniv = gen_sqadd_vec, +- .fno = gen_helper_gvec_sqadd_s, +- .opt_opc = vecop_list_sqadd, +- .write_aofs = true, +- .vece = MO_32 }, +- { .fniv = gen_sqadd_vec, +- .fno = gen_helper_gvec_sqadd_d, +- .opt_opc = vecop_list_sqadd, +- .write_aofs = true, +- .vece = MO_64 }, +-}; ++void gen_gvec_sqadd_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs, ++ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz) ++{ ++ static const TCGOpcode vecop_list[] = { ++ INDEX_op_ssadd_vec, INDEX_op_cmp_vec, INDEX_op_add_vec, 0 ++ }; ++ static const GVecGen4 ops[4] = { ++ { .fniv = gen_sqadd_vec, ++ .fno = gen_helper_gvec_sqadd_b, ++ .opt_opc = vecop_list, ++ .write_aofs = true, ++ .vece = MO_8 }, ++ { .fniv = gen_sqadd_vec, ++ .fno = gen_helper_gvec_sqadd_h, ++ .opt_opc = vecop_list, ++ .write_aofs = true, ++ .vece = MO_16 }, ++ { .fniv = gen_sqadd_vec, ++ .fno = gen_helper_gvec_sqadd_s, ++ .opt_opc = vecop_list, ++ .write_aofs = true, ++ .vece = MO_32 }, ++ { .fniv = gen_sqadd_vec, ++ .fno = gen_helper_gvec_sqadd_d, ++ .opt_opc = vecop_list, ++ .write_aofs = true, ++ .vece = MO_64 }, ++ }; ++ tcg_gen_gvec_4(rd_ofs, offsetof(CPUARMState, vfp.qc), ++ rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]); ++} + + static void gen_uqsub_vec(unsigned vece, TCGv_vec t, TCGv_vec sat, + TCGv_vec a, TCGv_vec b) +@@ -5001,32 +5011,37 @@ static void gen_uqsub_vec(unsigned vece, TCGv_vec t, TCGv_vec sat, + tcg_temp_free_vec(x); + } + +-static const TCGOpcode vecop_list_uqsub[] = { +- INDEX_op_ussub_vec, INDEX_op_cmp_vec, INDEX_op_sub_vec, 0 +-}; +- +-const GVecGen4 uqsub_op[4] = { +- { .fniv = gen_uqsub_vec, +- .fno = gen_helper_gvec_uqsub_b, +- .opt_opc = vecop_list_uqsub, +- .write_aofs = true, +- .vece = MO_8 }, +- { .fniv = gen_uqsub_vec, +- .fno = gen_helper_gvec_uqsub_h, +- .opt_opc = vecop_list_uqsub, +- .write_aofs = true, +- .vece = MO_16 }, +- { .fniv = gen_uqsub_vec, +- .fno = gen_helper_gvec_uqsub_s, +- .opt_opc = vecop_list_uqsub, +- .write_aofs = true, +- .vece = MO_32 }, +- { .fniv = gen_uqsub_vec, +- .fno = gen_helper_gvec_uqsub_d, +- .opt_opc = vecop_list_uqsub, +- .write_aofs = true, +- .vece = MO_64 }, +-}; ++void gen_gvec_uqsub_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs, ++ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz) ++{ ++ static const TCGOpcode vecop_list[] = { ++ INDEX_op_ussub_vec, INDEX_op_cmp_vec, INDEX_op_sub_vec, 0 ++ }; ++ static const GVecGen4 ops[4] = { ++ { .fniv = gen_uqsub_vec, ++ .fno = gen_helper_gvec_uqsub_b, ++ .opt_opc = vecop_list, ++ .write_aofs = true, ++ .vece = MO_8 }, ++ { .fniv = gen_uqsub_vec, ++ .fno = gen_helper_gvec_uqsub_h, ++ .opt_opc = vecop_list, ++ .write_aofs = true, ++ .vece = MO_16 }, ++ { .fniv = gen_uqsub_vec, ++ .fno = gen_helper_gvec_uqsub_s, ++ .opt_opc = vecop_list, ++ .write_aofs = true, ++ .vece = MO_32 }, ++ { .fniv = gen_uqsub_vec, ++ .fno = gen_helper_gvec_uqsub_d, ++ .opt_opc = vecop_list, ++ .write_aofs = true, ++ .vece = MO_64 }, ++ }; ++ tcg_gen_gvec_4(rd_ofs, offsetof(CPUARMState, vfp.qc), ++ rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]); ++} + + static void gen_sqsub_vec(unsigned vece, TCGv_vec t, TCGv_vec sat, + TCGv_vec a, TCGv_vec b) +@@ -5039,32 +5054,37 @@ static void gen_sqsub_vec(unsigned vece, TCGv_vec t, TCGv_vec sat, + tcg_temp_free_vec(x); + } + +-static const TCGOpcode vecop_list_sqsub[] = { +- INDEX_op_sssub_vec, INDEX_op_cmp_vec, INDEX_op_sub_vec, 0 +-}; +- +-const GVecGen4 sqsub_op[4] = { +- { .fniv = gen_sqsub_vec, +- .fno = gen_helper_gvec_sqsub_b, +- .opt_opc = vecop_list_sqsub, +- .write_aofs = true, +- .vece = MO_8 }, +- { .fniv = gen_sqsub_vec, +- .fno = gen_helper_gvec_sqsub_h, +- .opt_opc = vecop_list_sqsub, +- .write_aofs = true, +- .vece = MO_16 }, +- { .fniv = gen_sqsub_vec, +- .fno = gen_helper_gvec_sqsub_s, +- .opt_opc = vecop_list_sqsub, +- .write_aofs = true, +- .vece = MO_32 }, +- { .fniv = gen_sqsub_vec, +- .fno = gen_helper_gvec_sqsub_d, +- .opt_opc = vecop_list_sqsub, +- .write_aofs = true, +- .vece = MO_64 }, +-}; ++void gen_gvec_sqsub_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs, ++ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz) ++{ ++ static const TCGOpcode vecop_list[] = { ++ INDEX_op_sssub_vec, INDEX_op_cmp_vec, INDEX_op_sub_vec, 0 ++ }; ++ static const GVecGen4 ops[4] = { ++ { .fniv = gen_sqsub_vec, ++ .fno = gen_helper_gvec_sqsub_b, ++ .opt_opc = vecop_list, ++ .write_aofs = true, ++ .vece = MO_8 }, ++ { .fniv = gen_sqsub_vec, ++ .fno = gen_helper_gvec_sqsub_h, ++ .opt_opc = vecop_list, ++ .write_aofs = true, ++ .vece = MO_16 }, ++ { .fniv = gen_sqsub_vec, ++ .fno = gen_helper_gvec_sqsub_s, ++ .opt_opc = vecop_list, ++ .write_aofs = true, ++ .vece = MO_32 }, ++ { .fniv = gen_sqsub_vec, ++ .fno = gen_helper_gvec_sqsub_d, ++ .opt_opc = vecop_list, ++ .write_aofs = true, ++ .vece = MO_64 }, ++ }; ++ tcg_gen_gvec_4(rd_ofs, offsetof(CPUARMState, vfp.qc), ++ rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]); ++} + + /* Translate a NEON data processing instruction. Return nonzero if the + instruction is invalid. +diff --git a/target/arm/translate.h b/target/arm/translate.h +index a02a54cabf..4e1778c5e0 100644 +--- a/target/arm/translate.h ++++ b/target/arm/translate.h +@@ -298,16 +298,21 @@ void gen_gvec_sshl(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs, + void gen_gvec_ushl(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs, + uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz); + +-extern const GVecGen4 uqadd_op[4]; +-extern const GVecGen4 sqadd_op[4]; +-extern const GVecGen4 uqsub_op[4]; +-extern const GVecGen4 sqsub_op[4]; + void gen_cmtst_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b); + void gen_ushl_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b); + void gen_sshl_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b); + void gen_ushl_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b); + void gen_sshl_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b); + ++void gen_gvec_uqadd_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs, ++ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz); ++void gen_gvec_sqadd_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs, ++ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz); ++void gen_gvec_uqsub_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs, ++ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz); ++void gen_gvec_sqsub_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs, ++ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz); ++ + void gen_gvec_ssra(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs, + int64_t shift, uint32_t opr_sz, uint32_t max_sz); + void gen_gvec_usra(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs, +-- +2.23.0 + diff --git a/target-arm-Create-gen_gvec_-us-sra.patch b/target-arm-Create-gen_gvec_-us-sra.patch new file mode 100644 index 0000000000000000000000000000000000000000..d68aa7b851be895720ace3e10aa6eb3c7fbed955 --- /dev/null +++ b/target-arm-Create-gen_gvec_-us-sra.patch @@ -0,0 +1,326 @@ +From 631e565450c483e0622eec3d8b61d7fa41d16bca Mon Sep 17 00:00:00 2001 +From: Richard Henderson +Date: Wed, 13 May 2020 09:32:30 -0700 +Subject: [PATCH 419/709] target/arm: Create gen_gvec_[us]sra + +The functions eliminate duplication of the special cases for +this operation. They match up with the GVecGen2iFn typedef. + +Add out-of-line helpers. We got away with only having inline +expanders because the neon vector size is only 16 bytes, and +we know that the inline expansion will always succeed. +When we reuse this for SVE, tcg-gvec-op may decide to use an +out-of-line helper due to longer vector lengths. + +Reviewed-by: Peter Maydell +Signed-off-by: Richard Henderson +Message-id: 20200513163245.17915-2-richard.henderson@linaro.org +Signed-off-by: Peter Maydell +--- + target/arm/helper.h | 10 +++ + target/arm/translate-a64.c | 15 +--- + target/arm/translate.c | 161 ++++++++++++++++++++++--------------- + target/arm/translate.h | 7 +- + target/arm/vec_helper.c | 25 ++++++ + 5 files changed, 139 insertions(+), 79 deletions(-) + +diff --git a/target/arm/helper.h b/target/arm/helper.h +index 5817626b20..9bc162345c 100644 +--- a/target/arm/helper.h ++++ b/target/arm/helper.h +@@ -691,6 +691,16 @@ DEF_HELPER_FLAGS_4(gvec_pmull_q, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) + + DEF_HELPER_FLAGS_4(neon_pmull_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) + ++DEF_HELPER_FLAGS_3(gvec_ssra_b, TCG_CALL_NO_RWG, void, ptr, ptr, i32) ++DEF_HELPER_FLAGS_3(gvec_ssra_h, TCG_CALL_NO_RWG, void, ptr, ptr, i32) ++DEF_HELPER_FLAGS_3(gvec_ssra_s, TCG_CALL_NO_RWG, void, ptr, ptr, i32) ++DEF_HELPER_FLAGS_3(gvec_ssra_d, TCG_CALL_NO_RWG, void, ptr, ptr, i32) ++ ++DEF_HELPER_FLAGS_3(gvec_usra_b, TCG_CALL_NO_RWG, void, ptr, ptr, i32) ++DEF_HELPER_FLAGS_3(gvec_usra_h, TCG_CALL_NO_RWG, void, ptr, ptr, i32) ++DEF_HELPER_FLAGS_3(gvec_usra_s, TCG_CALL_NO_RWG, void, ptr, ptr, i32) ++DEF_HELPER_FLAGS_3(gvec_usra_d, TCG_CALL_NO_RWG, void, ptr, ptr, i32) ++ + #ifdef TARGET_AARCH64 + #include "helper-a64.h" + #include "helper-sve.h" +diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c +index 62e5729904..315de9a9b6 100644 +--- a/target/arm/translate-a64.c ++++ b/target/arm/translate-a64.c +@@ -10188,19 +10188,8 @@ static void handle_vec_simd_shri(DisasContext *s, bool is_q, bool is_u, + + switch (opcode) { + case 0x02: /* SSRA / USRA (accumulate) */ +- if (is_u) { +- /* Shift count same as element size produces zero to add. */ +- if (shift == 8 << size) { +- goto done; +- } +- gen_gvec_op2i(s, is_q, rd, rn, shift, &usra_op[size]); +- } else { +- /* Shift count same as element size produces all sign to add. */ +- if (shift == 8 << size) { +- shift -= 1; +- } +- gen_gvec_op2i(s, is_q, rd, rn, shift, &ssra_op[size]); +- } ++ gen_gvec_fn2i(s, is_q, rd, rn, shift, ++ is_u ? gen_gvec_usra : gen_gvec_ssra, size); + return; + case 0x08: /* SRI */ + /* Shift count same as element size is valid but does nothing. */ +diff --git a/target/arm/translate.c b/target/arm/translate.c +index 74fac1d09c..c18140f2e6 100644 +--- a/target/arm/translate.c ++++ b/target/arm/translate.c +@@ -3874,33 +3874,51 @@ static void gen_ssra_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t sh) + tcg_gen_add_vec(vece, d, d, a); + } + +-static const TCGOpcode vecop_list_ssra[] = { +- INDEX_op_sari_vec, INDEX_op_add_vec, 0 +-}; ++void gen_gvec_ssra(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs, ++ int64_t shift, uint32_t opr_sz, uint32_t max_sz) ++{ ++ static const TCGOpcode vecop_list[] = { ++ INDEX_op_sari_vec, INDEX_op_add_vec, 0 ++ }; ++ static const GVecGen2i ops[4] = { ++ { .fni8 = gen_ssra8_i64, ++ .fniv = gen_ssra_vec, ++ .fno = gen_helper_gvec_ssra_b, ++ .load_dest = true, ++ .opt_opc = vecop_list, ++ .vece = MO_8 }, ++ { .fni8 = gen_ssra16_i64, ++ .fniv = gen_ssra_vec, ++ .fno = gen_helper_gvec_ssra_h, ++ .load_dest = true, ++ .opt_opc = vecop_list, ++ .vece = MO_16 }, ++ { .fni4 = gen_ssra32_i32, ++ .fniv = gen_ssra_vec, ++ .fno = gen_helper_gvec_ssra_s, ++ .load_dest = true, ++ .opt_opc = vecop_list, ++ .vece = MO_32 }, ++ { .fni8 = gen_ssra64_i64, ++ .fniv = gen_ssra_vec, ++ .fno = gen_helper_gvec_ssra_b, ++ .prefer_i64 = TCG_TARGET_REG_BITS == 64, ++ .opt_opc = vecop_list, ++ .load_dest = true, ++ .vece = MO_64 }, ++ }; + +-const GVecGen2i ssra_op[4] = { +- { .fni8 = gen_ssra8_i64, +- .fniv = gen_ssra_vec, +- .load_dest = true, +- .opt_opc = vecop_list_ssra, +- .vece = MO_8 }, +- { .fni8 = gen_ssra16_i64, +- .fniv = gen_ssra_vec, +- .load_dest = true, +- .opt_opc = vecop_list_ssra, +- .vece = MO_16 }, +- { .fni4 = gen_ssra32_i32, +- .fniv = gen_ssra_vec, +- .load_dest = true, +- .opt_opc = vecop_list_ssra, +- .vece = MO_32 }, +- { .fni8 = gen_ssra64_i64, +- .fniv = gen_ssra_vec, +- .prefer_i64 = TCG_TARGET_REG_BITS == 64, +- .opt_opc = vecop_list_ssra, +- .load_dest = true, +- .vece = MO_64 }, +-}; ++ /* tszimm encoding produces immediates in the range [1..esize]. */ ++ tcg_debug_assert(shift > 0); ++ tcg_debug_assert(shift <= (8 << vece)); ++ ++ /* ++ * Shifts larger than the element size are architecturally valid. ++ * Signed results in all sign bits. ++ */ ++ shift = MIN(shift, (8 << vece) - 1); ++ tcg_gen_gvec_2i(rd_ofs, rm_ofs, opr_sz, max_sz, shift, &ops[vece]); ++} + + static void gen_usra8_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift) + { +@@ -3932,33 +3950,55 @@ static void gen_usra_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t sh) + tcg_gen_add_vec(vece, d, d, a); + } + +-static const TCGOpcode vecop_list_usra[] = { +- INDEX_op_shri_vec, INDEX_op_add_vec, 0 +-}; ++void gen_gvec_usra(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs, ++ int64_t shift, uint32_t opr_sz, uint32_t max_sz) ++{ ++ static const TCGOpcode vecop_list[] = { ++ INDEX_op_shri_vec, INDEX_op_add_vec, 0 ++ }; ++ static const GVecGen2i ops[4] = { ++ { .fni8 = gen_usra8_i64, ++ .fniv = gen_usra_vec, ++ .fno = gen_helper_gvec_usra_b, ++ .load_dest = true, ++ .opt_opc = vecop_list, ++ .vece = MO_8, }, ++ { .fni8 = gen_usra16_i64, ++ .fniv = gen_usra_vec, ++ .fno = gen_helper_gvec_usra_h, ++ .load_dest = true, ++ .opt_opc = vecop_list, ++ .vece = MO_16, }, ++ { .fni4 = gen_usra32_i32, ++ .fniv = gen_usra_vec, ++ .fno = gen_helper_gvec_usra_s, ++ .load_dest = true, ++ .opt_opc = vecop_list, ++ .vece = MO_32, }, ++ { .fni8 = gen_usra64_i64, ++ .fniv = gen_usra_vec, ++ .fno = gen_helper_gvec_usra_d, ++ .prefer_i64 = TCG_TARGET_REG_BITS == 64, ++ .load_dest = true, ++ .opt_opc = vecop_list, ++ .vece = MO_64, }, ++ }; + +-const GVecGen2i usra_op[4] = { +- { .fni8 = gen_usra8_i64, +- .fniv = gen_usra_vec, +- .load_dest = true, +- .opt_opc = vecop_list_usra, +- .vece = MO_8, }, +- { .fni8 = gen_usra16_i64, +- .fniv = gen_usra_vec, +- .load_dest = true, +- .opt_opc = vecop_list_usra, +- .vece = MO_16, }, +- { .fni4 = gen_usra32_i32, +- .fniv = gen_usra_vec, +- .load_dest = true, +- .opt_opc = vecop_list_usra, +- .vece = MO_32, }, +- { .fni8 = gen_usra64_i64, +- .fniv = gen_usra_vec, +- .prefer_i64 = TCG_TARGET_REG_BITS == 64, +- .load_dest = true, +- .opt_opc = vecop_list_usra, +- .vece = MO_64, }, +-}; ++ /* tszimm encoding produces immediates in the range [1..esize]. */ ++ tcg_debug_assert(shift > 0); ++ tcg_debug_assert(shift <= (8 << vece)); ++ ++ /* ++ * Shifts larger than the element size are architecturally valid. ++ * Unsigned results in all zeros as input to accumulate: nop. ++ */ ++ if (shift < (8 << vece)) { ++ tcg_gen_gvec_2i(rd_ofs, rm_ofs, opr_sz, max_sz, shift, &ops[vece]); ++ } else { ++ /* Nop, but we do need to clear the tail. */ ++ tcg_gen_gvec_mov(vece, rd_ofs, rd_ofs, opr_sz, max_sz); ++ } ++} + + static void gen_shr8_ins_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift) + { +@@ -5220,19 +5260,12 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn) + case 1: /* VSRA */ + /* Right shift comes here negative. */ + shift = -shift; +- /* Shifts larger than the element size are architecturally +- * valid. Unsigned results in all zeros; signed results +- * in all sign bits. +- */ +- if (!u) { +- tcg_gen_gvec_2i(rd_ofs, rm_ofs, vec_size, vec_size, +- MIN(shift, (8 << size) - 1), +- &ssra_op[size]); +- } else if (shift >= 8 << size) { +- /* rd += 0 */ ++ if (u) { ++ gen_gvec_usra(size, rd_ofs, rm_ofs, shift, ++ vec_size, vec_size); + } else { +- tcg_gen_gvec_2i(rd_ofs, rm_ofs, vec_size, vec_size, +- shift, &usra_op[size]); ++ gen_gvec_ssra(size, rd_ofs, rm_ofs, shift, ++ vec_size, vec_size); + } + return 0; + +diff --git a/target/arm/translate.h b/target/arm/translate.h +index cb7925ea46..1839a59a8e 100644 +--- a/target/arm/translate.h ++++ b/target/arm/translate.h +@@ -285,8 +285,6 @@ extern const GVecGen3 mls_op[4]; + extern const GVecGen3 cmtst_op[4]; + extern const GVecGen3 sshl_op[4]; + extern const GVecGen3 ushl_op[4]; +-extern const GVecGen2i ssra_op[4]; +-extern const GVecGen2i usra_op[4]; + extern const GVecGen2i sri_op[4]; + extern const GVecGen2i sli_op[4]; + extern const GVecGen4 uqadd_op[4]; +@@ -299,6 +297,11 @@ void gen_sshl_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b); + void gen_ushl_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b); + void gen_sshl_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b); + ++void gen_gvec_ssra(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs, ++ int64_t shift, uint32_t opr_sz, uint32_t max_sz); ++void gen_gvec_usra(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs, ++ int64_t shift, uint32_t opr_sz, uint32_t max_sz); ++ + /* + * Forward to the isar_feature_* tests given a DisasContext pointer. + */ +diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c +index 3d534188a8..230085b35e 100644 +--- a/target/arm/vec_helper.c ++++ b/target/arm/vec_helper.c +@@ -899,6 +899,31 @@ void HELPER(gvec_sqsub_d)(void *vd, void *vq, void *vn, + clear_tail(d, oprsz, simd_maxsz(desc)); + } + ++ ++#define DO_SRA(NAME, TYPE) \ ++void HELPER(NAME)(void *vd, void *vn, uint32_t desc) \ ++{ \ ++ intptr_t i, oprsz = simd_oprsz(desc); \ ++ int shift = simd_data(desc); \ ++ TYPE *d = vd, *n = vn; \ ++ for (i = 0; i < oprsz / sizeof(TYPE); i++) { \ ++ d[i] += n[i] >> shift; \ ++ } \ ++ clear_tail(d, oprsz, simd_maxsz(desc)); \ ++} ++ ++DO_SRA(gvec_ssra_b, int8_t) ++DO_SRA(gvec_ssra_h, int16_t) ++DO_SRA(gvec_ssra_s, int32_t) ++DO_SRA(gvec_ssra_d, int64_t) ++ ++DO_SRA(gvec_usra_b, uint8_t) ++DO_SRA(gvec_usra_h, uint16_t) ++DO_SRA(gvec_usra_s, uint32_t) ++DO_SRA(gvec_usra_d, uint64_t) ++ ++#undef DO_SRA ++ + /* + * Convert float16 to float32, raising no exceptions and + * preserving exceptional values, including SNaN. +-- +2.23.0 + diff --git a/target-arm-Don-t-allow-Thumb-Neon-insns-without-FEAT.patch b/target-arm-Don-t-allow-Thumb-Neon-insns-without-FEAT.patch new file mode 100644 index 0000000000000000000000000000000000000000..ce2e00621c370a5e13155bab8620c4904bf11c5e --- /dev/null +++ b/target-arm-Don-t-allow-Thumb-Neon-insns-without-FEAT.patch @@ -0,0 +1,75 @@ +From d1a6d3b594157425232a1ae5ea7f51b7a1c1aa2e Mon Sep 17 00:00:00 2001 +From: Peter Maydell +Date: Thu, 30 Apr 2020 19:09:29 +0100 +Subject: [PATCH 169/709] target/arm: Don't allow Thumb Neon insns without + FEATURE_NEON +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +We were accidentally permitting decode of Thumb Neon insns even if +the CPU didn't have the FEATURE_NEON bit set, because the feature +check was being done before the call to disas_neon_data_insn() and +disas_neon_ls_insn() in the Arm decoder but was omitted from the +Thumb decoder. Push the feature bit check down into the called +functions so it is done for both Arm and Thumb encodings. + +Signed-off-by: Peter Maydell +Reviewed-by: Richard Henderson +Reviewed-by: Philippe Mathieu-Daudé +Message-id: 20200430181003.21682-3-peter.maydell@linaro.org +--- + target/arm/translate.c | 16 ++++++++-------- + 1 file changed, 8 insertions(+), 8 deletions(-) + +diff --git a/target/arm/translate.c b/target/arm/translate.c +index e3fc792442..4cf5267be0 100644 +--- a/target/arm/translate.c ++++ b/target/arm/translate.c +@@ -3258,6 +3258,10 @@ static int disas_neon_ls_insn(DisasContext *s, uint32_t insn) + TCGv_i32 tmp2; + TCGv_i64 tmp64; + ++ if (!arm_dc_feature(s, ARM_FEATURE_NEON)) { ++ return 1; ++ } ++ + /* FIXME: this access check should not take precedence over UNDEF + * for invalid encodings; we will generate incorrect syndrome information + * for attempts to execute invalid vfp/neon encodings with FP disabled. +@@ -5002,6 +5006,10 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn) + TCGv_ptr ptr1, ptr2, ptr3; + TCGv_i64 tmp64; + ++ if (!arm_dc_feature(s, ARM_FEATURE_NEON)) { ++ return 1; ++ } ++ + /* FIXME: this access check should not take precedence over UNDEF + * for invalid encodings; we will generate incorrect syndrome information + * for attempts to execute invalid vfp/neon encodings with FP disabled. +@@ -10948,10 +10956,6 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn) + + if (((insn >> 25) & 7) == 1) { + /* NEON Data processing. */ +- if (!arm_dc_feature(s, ARM_FEATURE_NEON)) { +- goto illegal_op; +- } +- + if (disas_neon_data_insn(s, insn)) { + goto illegal_op; + } +@@ -10959,10 +10963,6 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn) + } + if ((insn & 0x0f100000) == 0x04000000) { + /* NEON load/store. */ +- if (!arm_dc_feature(s, ARM_FEATURE_NEON)) { +- goto illegal_op; +- } +- + if (disas_neon_ls_insn(s, insn)) { + goto illegal_op; + } +-- +2.23.0 + diff --git a/target-arm-Don-t-use-a-TLB-for-ARMMMUIdx_Stage2.patch b/target-arm-Don-t-use-a-TLB-for-ARMMMUIdx_Stage2.patch new file mode 100644 index 0000000000000000000000000000000000000000..04097fb0ab51ce63820c591995d701a32f4e98cf --- /dev/null +++ b/target-arm-Don-t-use-a-TLB-for-ARMMMUIdx_Stage2.patch @@ -0,0 +1,311 @@ +From bf05340cb655637451162c02dadcd6581a05c02c Mon Sep 17 00:00:00 2001 +From: Peter Maydell +Date: Mon, 30 Mar 2020 22:03:57 +0100 +Subject: [PATCH 151/709] target/arm: Don't use a TLB for ARMMMUIdx_Stage2 + +We define ARMMMUIdx_Stage2 as being an MMU index which uses a QEMU +TLB. However we never actually use the TLB -- all stage 2 lookups +are done by direct calls to get_phys_addr_lpae() followed by a +physical address load via address_space_ld*(). + +Remove Stage2 from the list of ARM MMU indexes which correspond to +real core MMU indexes, and instead put it in the set of "NOTLB" ARM +MMU indexes. + +This allows us to drop NB_MMU_MODES to 11. It also means we can +safely add support for the ARMv8.3-TTS2UXN extension, which adds +permission bits to the stage 2 descriptors which define execute +permission separatel for EL0 and EL1; supporting that while keeping +Stage2 in a QEMU TLB would require us to use separate TLBs for +"Stage2 for an EL0 access" and "Stage2 for an EL1 access", which is a +lot of extra complication given we aren't even using the QEMU TLB. + +In the process of updating the comment on our MMU index use, +fix a couple of other minor errors: + * NS EL2 EL2&0 was missing from the list in the comment + * some text hadn't been updated from when we bumped NB_MMU_MODES + above 8 + +Signed-off-by: Peter Maydell +Reviewed-by: Edgar E. Iglesias +Reviewed-by: Richard Henderson +Message-id: 20200330210400.11724-2-peter.maydell@linaro.org +--- + target/arm/cpu-param.h | 2 +- + target/arm/cpu.h | 21 +++++--- + target/arm/helper.c | 112 ++++------------------------------------- + 3 files changed, 27 insertions(+), 108 deletions(-) + +diff --git a/target/arm/cpu-param.h b/target/arm/cpu-param.h +index d593b60b28..6321385b46 100644 +--- a/target/arm/cpu-param.h ++++ b/target/arm/cpu-param.h +@@ -29,6 +29,6 @@ + # define TARGET_PAGE_BITS_MIN 10 + #endif + +-#define NB_MMU_MODES 12 ++#define NB_MMU_MODES 11 + + #endif +diff --git a/target/arm/cpu.h b/target/arm/cpu.h +index 8b9f2961ba..fe03a74bf0 100644 +--- a/target/arm/cpu.h ++++ b/target/arm/cpu.h +@@ -2801,6 +2801,9 @@ bool write_cpustate_to_list(ARMCPU *cpu, bool kvm_sync); + * handling via the TLB. The only way to do a stage 1 translation without + * the immediate stage 2 translation is via the ATS or AT system insns, + * which can be slow-pathed and always do a page table walk. ++ * The only use of stage 2 translations is either as part of an s1+2 ++ * lookup or when loading the descriptors during a stage 1 page table walk, ++ * and in both those cases we don't use the TLB. + * 4. we can also safely fold together the "32 bit EL3" and "64 bit EL3" + * translation regimes, because they map reasonably well to each other + * and they can't both be active at the same time. +@@ -2816,15 +2819,15 @@ bool write_cpustate_to_list(ARMCPU *cpu, bool kvm_sync); + * 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) +- * NS EL1&0 stage 2 + * +- * for a total of 12 different mmu_idx. ++ * for a total of 11 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 +@@ -2846,7 +2849,8 @@ bool write_cpustate_to_list(ARMCPU *cpu, bool kvm_sync); + * are not quite the same -- different CPU types (most notably M profile + * vs A/R profile) would like to use MMU indexes with different semantics, + * but since we don't ever need to use all of those in a single CPU we +- * can avoid setting NB_MMU_MODES to more than 8. The lower bits of ++ * can avoid having to set NB_MMU_MODES to "total number of A profile MMU ++ * modes + total number of M profile MMU modes". The lower bits of + * ARMMMUIdx are the core TLB mmu index, and the higher bits are always + * the same for any particular CPU. + * Variables of type ARMMUIdx are always full values, and the core +@@ -2894,8 +2898,6 @@ typedef enum ARMMMUIdx { + ARMMMUIdx_SE10_1_PAN = 9 | ARM_MMU_IDX_A, + ARMMMUIdx_SE3 = 10 | ARM_MMU_IDX_A, + +- ARMMMUIdx_Stage2 = 11 | ARM_MMU_IDX_A, +- + /* + * These are not allocated TLBs and are used only for AT system + * instructions or for the first stage of an S12 page table walk. +@@ -2903,6 +2905,14 @@ 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, ++ /* ++ * 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 ++ * page table walk. Note that if we ever want to have a TLB for this ++ * 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 = 3 | ARM_MMU_IDX_NOTLB, + + /* + * M-profile. +@@ -2936,7 +2946,6 @@ typedef enum ARMMMUIdxBit { + TO_CORE_BIT(SE10_1), + TO_CORE_BIT(SE10_1_PAN), + TO_CORE_BIT(SE3), +- TO_CORE_BIT(Stage2), + + TO_CORE_BIT(MUser), + TO_CORE_BIT(MPriv), +diff --git a/target/arm/helper.c b/target/arm/helper.c +index dfefb9b3d9..f785e012cd 100644 +--- a/target/arm/helper.c ++++ b/target/arm/helper.c +@@ -814,8 +814,7 @@ static void tlbiall_nsnh_write(CPUARMState *env, const ARMCPRegInfo *ri, + tlb_flush_by_mmuidx(cs, + ARMMMUIdxBit_E10_1 | + ARMMMUIdxBit_E10_1_PAN | +- ARMMMUIdxBit_E10_0 | +- ARMMMUIdxBit_Stage2); ++ ARMMMUIdxBit_E10_0); + } + + static void tlbiall_nsnh_is_write(CPUARMState *env, const ARMCPRegInfo *ri, +@@ -826,46 +825,9 @@ static void tlbiall_nsnh_is_write(CPUARMState *env, const ARMCPRegInfo *ri, + tlb_flush_by_mmuidx_all_cpus_synced(cs, + ARMMMUIdxBit_E10_1 | + ARMMMUIdxBit_E10_1_PAN | +- ARMMMUIdxBit_E10_0 | +- ARMMMUIdxBit_Stage2); ++ ARMMMUIdxBit_E10_0); + } + +-static void tlbiipas2_write(CPUARMState *env, const ARMCPRegInfo *ri, +- uint64_t value) +-{ +- /* Invalidate by IPA. This has to invalidate any structures that +- * contain only stage 2 translation information, but does not need +- * to apply to structures that contain combined stage 1 and stage 2 +- * translation information. +- * This must NOP if EL2 isn't implemented or SCR_EL3.NS is zero. +- */ +- CPUState *cs = env_cpu(env); +- uint64_t pageaddr; +- +- if (!arm_feature(env, ARM_FEATURE_EL2) || !(env->cp15.scr_el3 & SCR_NS)) { +- return; +- } +- +- pageaddr = sextract64(value << 12, 0, 40); +- +- tlb_flush_page_by_mmuidx(cs, pageaddr, ARMMMUIdxBit_Stage2); +-} +- +-static void tlbiipas2_is_write(CPUARMState *env, const ARMCPRegInfo *ri, +- uint64_t value) +-{ +- CPUState *cs = env_cpu(env); +- uint64_t pageaddr; +- +- if (!arm_feature(env, ARM_FEATURE_EL2) || !(env->cp15.scr_el3 & SCR_NS)) { +- return; +- } +- +- pageaddr = sextract64(value << 12, 0, 40); +- +- tlb_flush_page_by_mmuidx_all_cpus_synced(cs, pageaddr, +- ARMMMUIdxBit_Stage2); +-} + + static void tlbiall_hyp_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +@@ -4055,8 +4017,7 @@ static void vttbr_write(CPUARMState *env, const ARMCPRegInfo *ri, + tlb_flush_by_mmuidx(cs, + ARMMMUIdxBit_E10_1 | + ARMMMUIdxBit_E10_1_PAN | +- ARMMMUIdxBit_E10_0 | +- ARMMMUIdxBit_Stage2); ++ ARMMMUIdxBit_E10_0); + raw_write(env, ri, value); + } + } +@@ -4538,11 +4499,6 @@ static int alle1_tlbmask(CPUARMState *env) + return ARMMMUIdxBit_SE10_1 | + ARMMMUIdxBit_SE10_1_PAN | + ARMMMUIdxBit_SE10_0; +- } else if (arm_feature(env, ARM_FEATURE_EL2)) { +- return ARMMMUIdxBit_E10_1 | +- ARMMMUIdxBit_E10_1_PAN | +- ARMMMUIdxBit_E10_0 | +- ARMMMUIdxBit_Stage2; + } else { + return ARMMMUIdxBit_E10_1 | + ARMMMUIdxBit_E10_1_PAN | +@@ -4689,44 +4645,6 @@ static void tlbi_aa64_vae3is_write(CPUARMState *env, const ARMCPRegInfo *ri, + ARMMMUIdxBit_SE3); + } + +-static void tlbi_aa64_ipas2e1_write(CPUARMState *env, const ARMCPRegInfo *ri, +- uint64_t value) +-{ +- /* Invalidate by IPA. This has to invalidate any structures that +- * contain only stage 2 translation information, but does not need +- * to apply to structures that contain combined stage 1 and stage 2 +- * translation information. +- * This must NOP if EL2 isn't implemented or SCR_EL3.NS is zero. +- */ +- ARMCPU *cpu = env_archcpu(env); +- CPUState *cs = CPU(cpu); +- uint64_t pageaddr; +- +- if (!arm_feature(env, ARM_FEATURE_EL2) || !(env->cp15.scr_el3 & SCR_NS)) { +- return; +- } +- +- pageaddr = sextract64(value << 12, 0, 48); +- +- tlb_flush_page_by_mmuidx(cs, pageaddr, ARMMMUIdxBit_Stage2); +-} +- +-static void tlbi_aa64_ipas2e1is_write(CPUARMState *env, const ARMCPRegInfo *ri, +- uint64_t value) +-{ +- CPUState *cs = env_cpu(env); +- uint64_t pageaddr; +- +- if (!arm_feature(env, ARM_FEATURE_EL2) || !(env->cp15.scr_el3 & SCR_NS)) { +- return; +- } +- +- pageaddr = sextract64(value << 12, 0, 48); +- +- tlb_flush_page_by_mmuidx_all_cpus_synced(cs, pageaddr, +- ARMMMUIdxBit_Stage2); +-} +- + static CPAccessResult aa64_zva_access(CPUARMState *env, const ARMCPRegInfo *ri, + bool isread) + { +@@ -4965,12 +4883,10 @@ static const ARMCPRegInfo v8_cp_reginfo[] = { + .writefn = tlbi_aa64_vae1_write }, + { .name = "TLBI_IPAS2E1IS", .state = ARM_CP_STATE_AA64, + .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 0, .opc2 = 1, +- .access = PL2_W, .type = ARM_CP_NO_RAW, +- .writefn = tlbi_aa64_ipas2e1is_write }, ++ .access = PL2_W, .type = ARM_CP_NOP }, + { .name = "TLBI_IPAS2LE1IS", .state = ARM_CP_STATE_AA64, + .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 0, .opc2 = 5, +- .access = PL2_W, .type = ARM_CP_NO_RAW, +- .writefn = tlbi_aa64_ipas2e1is_write }, ++ .access = PL2_W, .type = ARM_CP_NOP }, + { .name = "TLBI_ALLE1IS", .state = ARM_CP_STATE_AA64, + .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 3, .opc2 = 4, + .access = PL2_W, .type = ARM_CP_NO_RAW, +@@ -4981,12 +4897,10 @@ static const ARMCPRegInfo v8_cp_reginfo[] = { + .writefn = tlbi_aa64_alle1is_write }, + { .name = "TLBI_IPAS2E1", .state = ARM_CP_STATE_AA64, + .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 4, .opc2 = 1, +- .access = PL2_W, .type = ARM_CP_NO_RAW, +- .writefn = tlbi_aa64_ipas2e1_write }, ++ .access = PL2_W, .type = ARM_CP_NOP }, + { .name = "TLBI_IPAS2LE1", .state = ARM_CP_STATE_AA64, + .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 4, .opc2 = 5, +- .access = PL2_W, .type = ARM_CP_NO_RAW, +- .writefn = tlbi_aa64_ipas2e1_write }, ++ .access = PL2_W, .type = ARM_CP_NOP }, + { .name = "TLBI_ALLE1", .state = ARM_CP_STATE_AA64, + .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 7, .opc2 = 4, + .access = PL2_W, .type = ARM_CP_NO_RAW, +@@ -5067,20 +4981,16 @@ static const ARMCPRegInfo v8_cp_reginfo[] = { + .writefn = tlbimva_hyp_is_write }, + { .name = "TLBIIPAS2", + .cp = 15, .opc1 = 4, .crn = 8, .crm = 4, .opc2 = 1, +- .type = ARM_CP_NO_RAW, .access = PL2_W, +- .writefn = tlbiipas2_write }, ++ .type = ARM_CP_NOP, .access = PL2_W }, + { .name = "TLBIIPAS2IS", + .cp = 15, .opc1 = 4, .crn = 8, .crm = 0, .opc2 = 1, +- .type = ARM_CP_NO_RAW, .access = PL2_W, +- .writefn = tlbiipas2_is_write }, ++ .type = ARM_CP_NOP, .access = PL2_W }, + { .name = "TLBIIPAS2L", + .cp = 15, .opc1 = 4, .crn = 8, .crm = 4, .opc2 = 5, +- .type = ARM_CP_NO_RAW, .access = PL2_W, +- .writefn = tlbiipas2_write }, ++ .type = ARM_CP_NOP, .access = PL2_W }, + { .name = "TLBIIPAS2LIS", + .cp = 15, .opc1 = 4, .crn = 8, .crm = 0, .opc2 = 5, +- .type = ARM_CP_NO_RAW, .access = PL2_W, +- .writefn = tlbiipas2_is_write }, ++ .type = ARM_CP_NOP, .access = PL2_W }, + /* 32 bit cache operations */ + { .name = "ICIALLUIS", .cp = 15, .opc1 = 0, .crn = 7, .crm = 1, .opc2 = 0, + .type = ARM_CP_NOP, .access = PL1_W, .accessfn = aa64_cacheop_pou_access }, +-- +2.23.0 + diff --git a/target-arm-Drop-access_el3_aa32ns_aa64any.patch b/target-arm-Drop-access_el3_aa32ns_aa64any.patch new file mode 100644 index 0000000000000000000000000000000000000000..fc4e37124aabec67fb1ede8597576047ab65c65b --- /dev/null +++ b/target-arm-Drop-access_el3_aa32ns_aa64any.patch @@ -0,0 +1,101 @@ +From 93dd1e6140e2652347cfe7208591d4cd32762d08 Mon Sep 17 00:00:00 2001 +From: "Edgar E. Iglesias" +Date: Tue, 5 May 2020 16:17:29 +0200 +Subject: [PATCH 359/709] target/arm: Drop access_el3_aa32ns_aa64any() + +Calling access_el3_aa32ns() works for AArch32 only cores +but it does not handle 32-bit EL2 on top of 64-bit EL3 +for mixed 32/64-bit cores. + +Merge access_el3_aa32ns_aa64any() into access_el3_aa32ns() +and only use the latter. + +Fixes: 68e9c2fe65 ("target-arm: Add VTCR_EL2") +Reported-by: Laurent Desnogues +Signed-off-by: Edgar E. Iglesias +Message-id: 20200505141729.31930-2-edgar.iglesias@gmail.com +Reviewed-by: Peter Maydell +Signed-off-by: Peter Maydell +--- + target/arm/helper.c | 30 +++++++----------------------- + 1 file changed, 7 insertions(+), 23 deletions(-) + +diff --git a/target/arm/helper.c b/target/arm/helper.c +index a94f650795..b88d27819d 100644 +--- a/target/arm/helper.c ++++ b/target/arm/helper.c +@@ -503,35 +503,19 @@ void init_cpreg_list(ARMCPU *cpu) + } + + /* +- * Some registers are not accessible if EL3.NS=0 and EL3 is using AArch32 but +- * they are accessible when EL3 is using AArch64 regardless of EL3.NS. +- * +- * access_el3_aa32ns: Used to check AArch32 register views. +- * access_el3_aa32ns_aa64any: Used to check both AArch32/64 register views. ++ * Some registers are not accessible from AArch32 EL3 if SCR.NS == 0. + */ + static CPAccessResult access_el3_aa32ns(CPUARMState *env, + const ARMCPRegInfo *ri, + bool isread) + { +- bool secure = arm_is_secure_below_el3(env); +- +- assert(!arm_el_is_aa64(env, 3)); +- if (secure) { ++ if (!is_a64(env) && arm_current_el(env) == 3 && ++ arm_is_secure_below_el3(env)) { + return CP_ACCESS_TRAP_UNCATEGORIZED; + } + return CP_ACCESS_OK; + } + +-static CPAccessResult access_el3_aa32ns_aa64any(CPUARMState *env, +- const ARMCPRegInfo *ri, +- bool isread) +-{ +- if (!arm_el_is_aa64(env, 3)) { +- return access_el3_aa32ns(env, ri, isread); +- } +- return CP_ACCESS_OK; +-} +- + /* Some secure-only AArch32 registers trap to EL3 if used from + * Secure EL1 (but are just ordinary UNDEF in other non-EL3 contexts). + * Note that an access from Secure EL1 can only happen if EL3 is AArch64. +@@ -5147,7 +5131,7 @@ static const ARMCPRegInfo el3_no_el2_cp_reginfo[] = { + .access = PL2_RW, .type = ARM_CP_CONST, .resetvalue = 0 }, + { .name = "VTCR_EL2", .state = ARM_CP_STATE_BOTH, + .opc0 = 3, .opc1 = 4, .crn = 2, .crm = 1, .opc2 = 2, +- .access = PL2_RW, .accessfn = access_el3_aa32ns_aa64any, ++ .access = PL2_RW, .accessfn = access_el3_aa32ns, + .type = ARM_CP_CONST, .resetvalue = 0 }, + { .name = "VTTBR", .state = ARM_CP_STATE_AA32, + .cp = 15, .opc1 = 6, .crm = 2, +@@ -5195,7 +5179,7 @@ static const ARMCPRegInfo el3_no_el2_cp_reginfo[] = { + .type = ARM_CP_CONST, .resetvalue = 0 }, + { .name = "HPFAR_EL2", .state = ARM_CP_STATE_BOTH, + .opc0 = 3, .opc1 = 4, .crn = 6, .crm = 0, .opc2 = 4, +- .access = PL2_RW, .accessfn = access_el3_aa32ns_aa64any, ++ .access = PL2_RW, .accessfn = access_el3_aa32ns, + .type = ARM_CP_CONST, .resetvalue = 0 }, + { .name = "HSTR_EL2", .state = ARM_CP_STATE_BOTH, + .opc0 = 3, .opc1 = 4, .crn = 1, .crm = 1, .opc2 = 3, +@@ -7537,12 +7521,12 @@ void register_cp_regs_for_features(ARMCPU *cpu) + ARMCPRegInfo vpidr_regs[] = { + { .name = "VPIDR_EL2", .state = ARM_CP_STATE_BOTH, + .opc0 = 3, .opc1 = 4, .crn = 0, .crm = 0, .opc2 = 0, +- .access = PL2_RW, .accessfn = access_el3_aa32ns_aa64any, ++ .access = PL2_RW, .accessfn = access_el3_aa32ns, + .type = ARM_CP_CONST, .resetvalue = cpu->midr, + .fieldoffset = offsetof(CPUARMState, cp15.vpidr_el2) }, + { .name = "VMPIDR_EL2", .state = ARM_CP_STATE_BOTH, + .opc0 = 3, .opc1 = 4, .crn = 0, .crm = 0, .opc2 = 5, +- .access = PL2_RW, .accessfn = access_el3_aa32ns_aa64any, ++ .access = PL2_RW, .accessfn = access_el3_aa32ns, + .type = ARM_CP_NO_RAW, + .writefn = arm_cp_write_ignore, .readfn = mpidr_read }, + REGINFO_SENTINEL +-- +2.23.0 + diff --git a/target-arm-Drop-manual-handling-of-set-clear_helper_.patch b/target-arm-Drop-manual-handling-of-set-clear_helper_.patch new file mode 100644 index 0000000000000000000000000000000000000000..af70ab9f7dee8872ec48764dd03345cf033889fe --- /dev/null +++ b/target-arm-Drop-manual-handling-of-set-clear_helper_.patch @@ -0,0 +1,289 @@ +From f32e2ab65f3a0fc03d58936709e5a565c4b0db50 Mon Sep 17 00:00:00 2001 +From: Richard Henderson +Date: Fri, 8 May 2020 08:43:48 -0700 +Subject: [PATCH 372/709] target/arm: Drop manual handling of + set/clear_helper_retaddr + +Since we converted back to cpu_*_data_ra, we do not need to +do this ourselves. + +Reviewed-by: Peter Maydell +Signed-off-by: Richard Henderson +Message-id: 20200508154359.7494-9-richard.henderson@linaro.org +Signed-off-by: Peter Maydell +--- + target/arm/sve_helper.c | 38 -------------------------------------- + 1 file changed, 38 deletions(-) + +diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c +index 655bc9476f..aad2c8c237 100644 +--- a/target/arm/sve_helper.c ++++ b/target/arm/sve_helper.c +@@ -4133,12 +4133,6 @@ static intptr_t max_for_page(target_ulong base, intptr_t mem_off, + return MIN(split, mem_max - mem_off) + mem_off; + } + +-#ifndef CONFIG_USER_ONLY +-/* These are normally defined only for CONFIG_USER_ONLY in */ +-static inline void set_helper_retaddr(uintptr_t ra) { } +-static inline void clear_helper_retaddr(void) { } +-#endif +- + /* + * The result of tlb_vaddr_to_host for user-only is just g2h(x), + * which is always non-null. Elide the useless test. +@@ -4180,7 +4174,6 @@ static void sve_ld1_r(CPUARMState *env, void *vg, const target_ulong addr, + return; + } + mem_off = reg_off >> diffsz; +- set_helper_retaddr(retaddr); + + /* + * If the (remaining) load is entirely within a single page, then: +@@ -4195,7 +4188,6 @@ static void sve_ld1_r(CPUARMState *env, void *vg, const target_ulong addr, + if (test_host_page(host)) { + mem_off = host_fn(vd, vg, host - mem_off, mem_off, mem_max); + tcg_debug_assert(mem_off == mem_max); +- clear_helper_retaddr(); + /* After having taken any fault, zero leading inactive elements. */ + swap_memzero(vd, reg_off); + return; +@@ -4246,7 +4238,6 @@ static void sve_ld1_r(CPUARMState *env, void *vg, const target_ulong addr, + } + #endif + +- clear_helper_retaddr(); + memcpy(vd, &scratch, reg_max); + } + +@@ -4306,7 +4297,6 @@ static void sve_ld2_r(CPUARMState *env, void *vg, target_ulong addr, + intptr_t i, oprsz = simd_oprsz(desc); + ARMVectorReg scratch[2] = { }; + +- set_helper_retaddr(ra); + for (i = 0; i < oprsz; ) { + uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3)); + do { +@@ -4318,7 +4308,6 @@ static void sve_ld2_r(CPUARMState *env, void *vg, target_ulong addr, + addr += 2 * size; + } while (i & 15); + } +- clear_helper_retaddr(); + + /* Wait until all exceptions have been raised to write back. */ + memcpy(&env->vfp.zregs[rd], &scratch[0], oprsz); +@@ -4333,7 +4322,6 @@ static void sve_ld3_r(CPUARMState *env, void *vg, target_ulong addr, + intptr_t i, oprsz = simd_oprsz(desc); + ARMVectorReg scratch[3] = { }; + +- set_helper_retaddr(ra); + for (i = 0; i < oprsz; ) { + uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3)); + do { +@@ -4346,7 +4334,6 @@ static void sve_ld3_r(CPUARMState *env, void *vg, target_ulong addr, + addr += 3 * size; + } while (i & 15); + } +- clear_helper_retaddr(); + + /* Wait until all exceptions have been raised to write back. */ + memcpy(&env->vfp.zregs[rd], &scratch[0], oprsz); +@@ -4362,7 +4349,6 @@ static void sve_ld4_r(CPUARMState *env, void *vg, target_ulong addr, + intptr_t i, oprsz = simd_oprsz(desc); + ARMVectorReg scratch[4] = { }; + +- set_helper_retaddr(ra); + for (i = 0; i < oprsz; ) { + uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3)); + do { +@@ -4376,7 +4362,6 @@ static void sve_ld4_r(CPUARMState *env, void *vg, target_ulong addr, + addr += 4 * size; + } while (i & 15); + } +- clear_helper_retaddr(); + + /* Wait until all exceptions have been raised to write back. */ + memcpy(&env->vfp.zregs[rd], &scratch[0], oprsz); +@@ -4483,7 +4468,6 @@ static void sve_ldff1_r(CPUARMState *env, void *vg, const target_ulong addr, + return; + } + mem_off = reg_off >> diffsz; +- set_helper_retaddr(retaddr); + + /* + * If the (remaining) load is entirely within a single page, then: +@@ -4498,7 +4482,6 @@ static void sve_ldff1_r(CPUARMState *env, void *vg, const target_ulong addr, + if (test_host_page(host)) { + mem_off = host_fn(vd, vg, host - mem_off, mem_off, mem_max); + tcg_debug_assert(mem_off == mem_max); +- clear_helper_retaddr(); + /* After any fault, zero any leading inactive elements. */ + swap_memzero(vd, reg_off); + return; +@@ -4541,7 +4524,6 @@ static void sve_ldff1_r(CPUARMState *env, void *vg, const target_ulong addr, + } + #endif + +- clear_helper_retaddr(); + record_fault(env, reg_off, reg_max); + } + +@@ -4687,7 +4669,6 @@ static void sve_st1_r(CPUARMState *env, void *vg, target_ulong addr, + intptr_t i, oprsz = simd_oprsz(desc); + void *vd = &env->vfp.zregs[rd]; + +- set_helper_retaddr(ra); + for (i = 0; i < oprsz; ) { + uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3)); + do { +@@ -4698,7 +4679,6 @@ static void sve_st1_r(CPUARMState *env, void *vg, target_ulong addr, + addr += msize; + } while (i & 15); + } +- clear_helper_retaddr(); + } + + static void sve_st2_r(CPUARMState *env, void *vg, target_ulong addr, +@@ -4711,7 +4691,6 @@ static void sve_st2_r(CPUARMState *env, void *vg, target_ulong addr, + void *d1 = &env->vfp.zregs[rd]; + void *d2 = &env->vfp.zregs[(rd + 1) & 31]; + +- set_helper_retaddr(ra); + for (i = 0; i < oprsz; ) { + uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3)); + do { +@@ -4723,7 +4702,6 @@ static void sve_st2_r(CPUARMState *env, void *vg, target_ulong addr, + addr += 2 * msize; + } while (i & 15); + } +- clear_helper_retaddr(); + } + + static void sve_st3_r(CPUARMState *env, void *vg, target_ulong addr, +@@ -4737,7 +4715,6 @@ static void sve_st3_r(CPUARMState *env, void *vg, target_ulong addr, + void *d2 = &env->vfp.zregs[(rd + 1) & 31]; + void *d3 = &env->vfp.zregs[(rd + 2) & 31]; + +- set_helper_retaddr(ra); + for (i = 0; i < oprsz; ) { + uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3)); + do { +@@ -4750,7 +4727,6 @@ static void sve_st3_r(CPUARMState *env, void *vg, target_ulong addr, + addr += 3 * msize; + } while (i & 15); + } +- clear_helper_retaddr(); + } + + static void sve_st4_r(CPUARMState *env, void *vg, target_ulong addr, +@@ -4765,7 +4741,6 @@ static void sve_st4_r(CPUARMState *env, void *vg, target_ulong addr, + void *d3 = &env->vfp.zregs[(rd + 2) & 31]; + void *d4 = &env->vfp.zregs[(rd + 3) & 31]; + +- set_helper_retaddr(ra); + for (i = 0; i < oprsz; ) { + uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3)); + do { +@@ -4779,7 +4754,6 @@ static void sve_st4_r(CPUARMState *env, void *vg, target_ulong addr, + addr += 4 * msize; + } while (i & 15); + } +- clear_helper_retaddr(); + } + + #define DO_STN_1(N, NAME, ESIZE) \ +@@ -4875,7 +4849,6 @@ static void sve_ld1_zs(CPUARMState *env, void *vd, void *vg, void *vm, + intptr_t i, oprsz = simd_oprsz(desc); + ARMVectorReg scratch = { }; + +- set_helper_retaddr(ra); + for (i = 0; i < oprsz; ) { + uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3)); + do { +@@ -4886,7 +4859,6 @@ static void sve_ld1_zs(CPUARMState *env, void *vd, void *vg, void *vm, + i += 4, pg >>= 4; + } while (i & 15); + } +- clear_helper_retaddr(); + + /* Wait until all exceptions have been raised to write back. */ + memcpy(vd, &scratch, oprsz); +@@ -4900,7 +4872,6 @@ static void sve_ld1_zd(CPUARMState *env, void *vd, void *vg, void *vm, + intptr_t i, oprsz = simd_oprsz(desc) / 8; + ARMVectorReg scratch = { }; + +- set_helper_retaddr(ra); + for (i = 0; i < oprsz; i++) { + uint8_t pg = *(uint8_t *)(vg + H1(i)); + if (likely(pg & 1)) { +@@ -4908,7 +4879,6 @@ static void sve_ld1_zd(CPUARMState *env, void *vd, void *vg, void *vm, + tlb_fn(env, &scratch, i * 8, base + (off << scale), ra); + } + } +- clear_helper_retaddr(); + + /* Wait until all exceptions have been raised to write back. */ + memcpy(vd, &scratch, oprsz * 8); +@@ -5080,13 +5050,11 @@ static inline void sve_ldff1_zs(CPUARMState *env, void *vd, void *vg, void *vm, + reg_off = find_next_active(vg, 0, reg_max, MO_32); + if (likely(reg_off < reg_max)) { + /* Perform one normal read, which will fault or not. */ +- set_helper_retaddr(ra); + addr = off_fn(vm, reg_off); + addr = base + (addr << scale); + tlb_fn(env, vd, reg_off, addr, ra); + + /* The rest of the reads will be non-faulting. */ +- clear_helper_retaddr(); + } + + /* After any fault, zero the leading predicated false elements. */ +@@ -5122,13 +5090,11 @@ static inline void sve_ldff1_zd(CPUARMState *env, void *vd, void *vg, void *vm, + reg_off = find_next_active(vg, 0, reg_max, MO_64); + if (likely(reg_off < reg_max)) { + /* Perform one normal read, which will fault or not. */ +- set_helper_retaddr(ra); + addr = off_fn(vm, reg_off); + addr = base + (addr << scale); + tlb_fn(env, vd, reg_off, addr, ra); + + /* The rest of the reads will be non-faulting. */ +- clear_helper_retaddr(); + } + + /* After any fault, zero the leading predicated false elements. */ +@@ -5240,7 +5206,6 @@ static void sve_st1_zs(CPUARMState *env, void *vd, void *vg, void *vm, + const int scale = extract32(desc, SIMD_DATA_SHIFT + MEMOPIDX_SHIFT, 2); + intptr_t i, oprsz = simd_oprsz(desc); + +- set_helper_retaddr(ra); + for (i = 0; i < oprsz; ) { + uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3)); + do { +@@ -5251,7 +5216,6 @@ static void sve_st1_zs(CPUARMState *env, void *vd, void *vg, void *vm, + i += 4, pg >>= 4; + } while (i & 15); + } +- clear_helper_retaddr(); + } + + static void sve_st1_zd(CPUARMState *env, void *vd, void *vg, void *vm, +@@ -5261,7 +5225,6 @@ static void sve_st1_zd(CPUARMState *env, void *vd, void *vg, void *vm, + const int scale = extract32(desc, SIMD_DATA_SHIFT + MEMOPIDX_SHIFT, 2); + intptr_t i, oprsz = simd_oprsz(desc) / 8; + +- set_helper_retaddr(ra); + for (i = 0; i < oprsz; i++) { + uint8_t pg = *(uint8_t *)(vg + H1(i)); + if (likely(pg & 1)) { +@@ -5269,7 +5232,6 @@ static void sve_st1_zd(CPUARMState *env, void *vd, void *vg, void *vm, + tlb_fn(env, vd, i * 8, base + (off << scale), ra); + } + } +- clear_helper_retaddr(); + } + + #define DO_ST1_ZPZ_S(MEM, OFS) \ +-- +2.23.0 + diff --git a/target-arm-Fix-tcg_gen_gvec_dup_imm-vs-DUP-indexed.patch b/target-arm-Fix-tcg_gen_gvec_dup_imm-vs-DUP-indexed.patch new file mode 100644 index 0000000000000000000000000000000000000000..3042d012aae1cf3d1d3c6c1a1f73ba416bd1e00d --- /dev/null +++ b/target-arm-Fix-tcg_gen_gvec_dup_imm-vs-DUP-indexed.patch @@ -0,0 +1,39 @@ +From 7e17d50ebd359ee5fa3d65d7fdc0fe0336d60694 Mon Sep 17 00:00:00 2001 +From: Richard Henderson +Date: Thu, 7 May 2020 10:23:52 -0700 +Subject: [PATCH 391/709] target/arm: Fix tcg_gen_gvec_dup_imm vs DUP (indexed) + +DUP (indexed) can duplicate 128-bit elements, so using esz +unconditionally can assert in tcg_gen_gvec_dup_imm. + +Fixes: 8711e71f9cbb +Reported-by: Laurent Desnogues +Signed-off-by: Richard Henderson +Reviewed-by: Laurent Desnogues +Tested-by: Laurent Desnogues +Message-id: 20200507172352.15418-5-richard.henderson@linaro.org +Signed-off-by: Peter Maydell +--- + target/arm/translate-sve.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c +index 8398c32362..ac7b3119e5 100644 +--- a/target/arm/translate-sve.c ++++ b/target/arm/translate-sve.c +@@ -2044,7 +2044,11 @@ static bool trans_DUP_x(DisasContext *s, arg_DUP_x *a) + unsigned nofs = vec_reg_offset(s, a->rn, index, esz); + tcg_gen_gvec_dup_mem(esz, dofs, nofs, vsz, vsz); + } else { +- tcg_gen_gvec_dup_imm(esz, dofs, vsz, vsz, 0); ++ /* ++ * While dup_mem handles 128-bit elements, dup_imm does not. ++ * Thankfully element size doesn't matter for splatting zero. ++ */ ++ tcg_gen_gvec_dup_imm(MO_64, dofs, vsz, vsz, 0); + } + } + return true; +-- +2.23.0 + diff --git a/target-arm-Handle-watchpoints-in-sve_ld1_r.patch b/target-arm-Handle-watchpoints-in-sve_ld1_r.patch new file mode 100644 index 0000000000000000000000000000000000000000..5678a269199fc8a22613b03e73d0bd064b92be9c --- /dev/null +++ b/target-arm-Handle-watchpoints-in-sve_ld1_r.patch @@ -0,0 +1,117 @@ +From 4bcc3f0ff8e5ae2b17b5aab9aa613ff1b8025896 Mon Sep 17 00:00:00 2001 +From: Richard Henderson +Date: Fri, 8 May 2020 08:43:52 -0700 +Subject: [PATCH 376/709] target/arm: Handle watchpoints in sve_ld1_r + +Handle all of the watchpoints for active elements all at once, +before we've modified the vector register. This removes the +TLB_WATCHPOINT bit from page[].flags, which means that we can +use the normal fast path via RAM. + +Reviewed-by: Peter Maydell +Signed-off-by: Richard Henderson +Message-id: 20200508154359.7494-13-richard.henderson@linaro.org +Signed-off-by: Peter Maydell +--- + target/arm/sve_helper.c | 72 ++++++++++++++++++++++++++++++++++++++++- + 1 file changed, 71 insertions(+), 1 deletion(-) + +diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c +index 6bae342a17..7992a569b0 100644 +--- a/target/arm/sve_helper.c ++++ b/target/arm/sve_helper.c +@@ -4371,6 +4371,70 @@ static bool sve_cont_ldst_pages(SVEContLdSt *info, SVEContFault fault, + return have_work; + } + ++static void sve_cont_ldst_watchpoints(SVEContLdSt *info, CPUARMState *env, ++ uint64_t *vg, target_ulong addr, ++ int esize, int msize, int wp_access, ++ uintptr_t retaddr) ++{ ++#ifndef CONFIG_USER_ONLY ++ intptr_t mem_off, reg_off, reg_last; ++ int flags0 = info->page[0].flags; ++ int flags1 = info->page[1].flags; ++ ++ if (likely(!((flags0 | flags1) & TLB_WATCHPOINT))) { ++ return; ++ } ++ ++ /* Indicate that watchpoints are handled. */ ++ info->page[0].flags = flags0 & ~TLB_WATCHPOINT; ++ info->page[1].flags = flags1 & ~TLB_WATCHPOINT; ++ ++ if (flags0 & TLB_WATCHPOINT) { ++ mem_off = info->mem_off_first[0]; ++ reg_off = info->reg_off_first[0]; ++ reg_last = info->reg_off_last[0]; ++ ++ while (reg_off <= reg_last) { ++ uint64_t pg = vg[reg_off >> 6]; ++ do { ++ if ((pg >> (reg_off & 63)) & 1) { ++ cpu_check_watchpoint(env_cpu(env), addr + mem_off, ++ msize, info->page[0].attrs, ++ wp_access, retaddr); ++ } ++ reg_off += esize; ++ mem_off += msize; ++ } while (reg_off <= reg_last && (reg_off & 63)); ++ } ++ } ++ ++ mem_off = info->mem_off_split; ++ if (mem_off >= 0) { ++ cpu_check_watchpoint(env_cpu(env), addr + mem_off, msize, ++ info->page[0].attrs, wp_access, retaddr); ++ } ++ ++ mem_off = info->mem_off_first[1]; ++ if ((flags1 & TLB_WATCHPOINT) && mem_off >= 0) { ++ reg_off = info->reg_off_first[1]; ++ reg_last = info->reg_off_last[1]; ++ ++ do { ++ uint64_t pg = vg[reg_off >> 6]; ++ do { ++ if ((pg >> (reg_off & 63)) & 1) { ++ cpu_check_watchpoint(env_cpu(env), addr + mem_off, ++ msize, info->page[1].attrs, ++ wp_access, retaddr); ++ } ++ reg_off += esize; ++ mem_off += msize; ++ } while (reg_off & 63); ++ } while (reg_off <= reg_last); ++ } ++#endif ++} ++ + /* + * The result of tlb_vaddr_to_host for user-only is just g2h(x), + * which is always non-null. Elide the useless test. +@@ -4412,13 +4476,19 @@ void sve_ld1_r(CPUARMState *env, uint64_t *vg, const target_ulong addr, + /* Probe the page(s). Exit with exception for any invalid page. */ + sve_cont_ldst_pages(&info, FAULT_ALL, env, addr, MMU_DATA_LOAD, retaddr); + ++ /* Handle watchpoints for all active elements. */ ++ sve_cont_ldst_watchpoints(&info, env, vg, addr, 1 << esz, 1 << msz, ++ BP_MEM_READ, retaddr); ++ ++ /* TODO: MTE check. */ ++ + flags = info.page[0].flags | info.page[1].flags; + if (unlikely(flags != 0)) { + #ifdef CONFIG_USER_ONLY + g_assert_not_reached(); + #else + /* +- * At least one page includes MMIO (or watchpoints). ++ * At least one page includes MMIO. + * Any bus operation can fail with cpu_transaction_failed, + * which for ARM will raise SyncExternal. Perform the load + * into scratch memory to preserve register state until the end. +-- +2.23.0 + diff --git a/target-arm-Implement-ARMv8.2-TTS2UXN.patch b/target-arm-Implement-ARMv8.2-TTS2UXN.patch new file mode 100644 index 0000000000000000000000000000000000000000..6b48bcfaf3ff77e08e6c62962b39ef7259f9e777 --- /dev/null +++ b/target-arm-Implement-ARMv8.2-TTS2UXN.patch @@ -0,0 +1,166 @@ +From ce3125bed935a12e619a8253c19340ecaa899347 Mon Sep 17 00:00:00 2001 +From: Peter Maydell +Date: Mon, 30 Mar 2020 22:04:00 +0100 +Subject: [PATCH 154/709] target/arm: Implement ARMv8.2-TTS2UXN + +The ARMv8.2-TTS2UXN feature extends the XN field in stage 2 +translation table descriptors from just bit [54] to bits [54:53], +allowing stage 2 to control execution permissions separately for EL0 +and EL1. Implement the new semantics of the XN field and enable +the feature for our 'max' CPU. + +Signed-off-by: Peter Maydell +Reviewed-by: Edgar E. Iglesias +Reviewed-by: Richard Henderson +Message-id: 20200330210400.11724-5-peter.maydell@linaro.org +--- + target/arm/cpu.c | 1 + + target/arm/cpu.h | 15 +++++++++++++++ + target/arm/cpu64.c | 2 ++ + target/arm/helper.c | 37 +++++++++++++++++++++++++++++++------ + 4 files changed, 49 insertions(+), 6 deletions(-) + +diff --git a/target/arm/cpu.c b/target/arm/cpu.c +index 141d947775..f588344df8 100644 +--- a/target/arm/cpu.c ++++ b/target/arm/cpu.c +@@ -2686,6 +2686,7 @@ static void arm_max_initfn(Object *obj) + t = FIELD_DP32(t, ID_MMFR4, HPDS, 1); /* AA32HPD */ + t = FIELD_DP32(t, ID_MMFR4, AC2, 1); /* ACTLR2, HACTLR2 */ + t = FIELD_DP32(t, ID_MMFR4, CNP, 1); /* TTCNP */ ++ t = FIELD_DP32(t, ID_MMFR4, XNX, 1); /* TTS2UXN */ + cpu->isar.id_mmfr4 = t; + } + #endif +diff --git a/target/arm/cpu.h b/target/arm/cpu.h +index fe03a74bf0..9aae324d0f 100644 +--- a/target/arm/cpu.h ++++ b/target/arm/cpu.h +@@ -3610,6 +3610,11 @@ static inline bool isar_feature_aa32_ccidx(const ARMISARegisters *id) + return FIELD_EX32(id->id_mmfr4, ID_MMFR4, CCIDX) != 0; + } + ++static inline bool isar_feature_aa32_tts2uxn(const ARMISARegisters *id) ++{ ++ return FIELD_EX32(id->id_mmfr4, ID_MMFR4, XNX) != 0; ++} ++ + /* + * 64-bit feature tests via id registers. + */ +@@ -3822,6 +3827,11 @@ static inline bool isar_feature_aa64_ccidx(const ARMISARegisters *id) + return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, CCIDX) != 0; + } + ++static inline bool isar_feature_aa64_tts2uxn(const ARMISARegisters *id) ++{ ++ return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, XNX) != 0; ++} ++ + /* + * Feature tests for "does this exist in either 32-bit or 64-bit?" + */ +@@ -3850,6 +3860,11 @@ static inline bool isar_feature_any_ccidx(const ARMISARegisters *id) + return isar_feature_aa64_ccidx(id) || isar_feature_aa32_ccidx(id); + } + ++static inline bool isar_feature_any_tts2uxn(const ARMISARegisters *id) ++{ ++ return isar_feature_aa64_tts2uxn(id) || isar_feature_aa32_tts2uxn(id); ++} ++ + /* + * Forward to the above feature tests given an ARMCPU pointer. + */ +diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c +index 74afc28d53..e232c0ea12 100644 +--- a/target/arm/cpu64.c ++++ b/target/arm/cpu64.c +@@ -673,6 +673,7 @@ static void aarch64_max_initfn(Object *obj) + t = FIELD_DP64(t, ID_AA64MMFR1, VH, 1); + t = FIELD_DP64(t, ID_AA64MMFR1, PAN, 2); /* ATS1E1 */ + t = FIELD_DP64(t, ID_AA64MMFR1, VMIDBITS, 2); /* VMID16 */ ++ t = FIELD_DP64(t, ID_AA64MMFR1, XNX, 1); /* TTS2UXN */ + cpu->isar.id_aa64mmfr1 = t; + + t = cpu->isar.id_aa64mmfr2; +@@ -706,6 +707,7 @@ static void aarch64_max_initfn(Object *obj) + u = FIELD_DP32(u, ID_MMFR4, HPDS, 1); /* AA32HPD */ + u = FIELD_DP32(u, ID_MMFR4, AC2, 1); /* ACTLR2, HACTLR2 */ + u = FIELD_DP32(u, ID_MMFR4, CNP, 1); /* TTCNP */ ++ u = FIELD_DP32(u, ID_MMFR4, XNX, 1); /* TTS2UXN */ + cpu->isar.id_mmfr4 = u; + + u = cpu->isar.id_aa64dfr0; +diff --git a/target/arm/helper.c b/target/arm/helper.c +index b26f580194..a94f650795 100644 +--- a/target/arm/helper.c ++++ b/target/arm/helper.c +@@ -9908,9 +9908,10 @@ simple_ap_to_rw_prot(CPUARMState *env, ARMMMUIdx mmu_idx, int ap) + * + * @env: CPUARMState + * @s2ap: The 2-bit stage2 access permissions (S2AP) +- * @xn: XN (execute-never) bit ++ * @xn: XN (execute-never) bits ++ * @s1_is_el0: true if this is S2 of an S1+2 walk for EL0 + */ +-static int get_S2prot(CPUARMState *env, int s2ap, int xn) ++static int get_S2prot(CPUARMState *env, int s2ap, int xn, bool s1_is_el0) + { + int prot = 0; + +@@ -9920,9 +9921,32 @@ static int get_S2prot(CPUARMState *env, int s2ap, int xn) + if (s2ap & 2) { + prot |= PAGE_WRITE; + } +- if (!xn) { +- if (arm_el_is_aa64(env, 2) || prot & PAGE_READ) { ++ ++ if (cpu_isar_feature(any_tts2uxn, env_archcpu(env))) { ++ switch (xn) { ++ case 0: + prot |= PAGE_EXEC; ++ break; ++ case 1: ++ if (s1_is_el0) { ++ prot |= PAGE_EXEC; ++ } ++ break; ++ case 2: ++ break; ++ case 3: ++ if (!s1_is_el0) { ++ prot |= PAGE_EXEC; ++ } ++ break; ++ default: ++ g_assert_not_reached(); ++ } ++ } else { ++ if (!extract32(xn, 1, 1)) { ++ if (arm_el_is_aa64(env, 2) || prot & PAGE_READ) { ++ prot |= PAGE_EXEC; ++ } + } + } + return prot; +@@ -10901,13 +10925,14 @@ static bool get_phys_addr_lpae(CPUARMState *env, target_ulong address, + } + + ap = extract32(attrs, 4, 2); +- xn = extract32(attrs, 12, 1); + + if (mmu_idx == ARMMMUIdx_Stage2) { + ns = true; +- *prot = get_S2prot(env, ap, xn); ++ xn = extract32(attrs, 11, 2); ++ *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); + } +-- +2.23.0 + diff --git a/target-arm-Make-VQDMULL-undefined-when-U-1.patch b/target-arm-Make-VQDMULL-undefined-when-U-1.patch new file mode 100644 index 0000000000000000000000000000000000000000..e861acb518b889c3763dd0af572bf3feaf8dee83 --- /dev/null +++ b/target-arm-Make-VQDMULL-undefined-when-U-1.patch @@ -0,0 +1,32 @@ +From ab553ef74ee52c0889679d0bd0da084aaf938f5c Mon Sep 17 00:00:00 2001 +From: Fredrik Strupe +Date: Wed, 8 Apr 2020 13:59:53 +0200 +Subject: [PATCH 149/709] target/arm: Make VQDMULL undefined when U=1 + +According to Arm ARM, VQDMULL is only valid when U=0, while having +U=1 is unallocated. + +Signed-off-by: Fredrik Strupe +Fixes: 695272dcb976 ("target-arm: Handle UNDEF cases for Neon 3-regs-different-widths") +Reviewed-by: Peter Maydell +Signed-off-by: Peter Maydell +--- + target/arm/translate.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/target/arm/translate.c b/target/arm/translate.c +index d4ad2028f1..e3fc792442 100644 +--- a/target/arm/translate.c ++++ b/target/arm/translate.c +@@ -6016,7 +6016,7 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn) + {0, 0, 0, 0}, /* VMLSL */ + {0, 0, 0, 9}, /* VQDMLSL */ + {0, 0, 0, 0}, /* Integer VMULL */ +- {0, 0, 0, 1}, /* VQDMULL */ ++ {0, 0, 0, 9}, /* VQDMULL */ + {0, 0, 0, 0xa}, /* Polynomial VMULL */ + {0, 0, 0, 7}, /* Reserved: always UNDEF */ + }; +-- +2.23.0 + diff --git a/target-arm-Make-cpu_register-available-for-other-fil.patch b/target-arm-Make-cpu_register-available-for-other-fil.patch new file mode 100644 index 0000000000000000000000000000000000000000..2313afa4fc94b6fab631c4e51dd1b9709e9988a3 --- /dev/null +++ b/target-arm-Make-cpu_register-available-for-other-fil.patch @@ -0,0 +1,112 @@ +From 37bcf244454f4efb82e2c0c64bbd7eabcc165a0c Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Thu, 23 Apr 2020 09:33:55 +0200 +Subject: [PATCH 118/709] target/arm: Make cpu_register() available for other + files +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Make cpu_register() (renamed to arm_cpu_register()) available +from internals.h so we can register CPUs also from other files +in the future. + +Signed-off-by: Thomas Huth +Reviewed-by: Richard Henderson +Reviewed-by: Eric Auger +Signed-off-by: Philippe Mathieu-Daudé +Message-id: 20200423073358.27155-3-philmd@redhat.com +Message-ID: <20190921150420.30743-2-thuth@redhat.com> +[PMD: Only take cpu_register() from Thomas's patch] +Signed-off-by: Philippe Mathieu-Daudé +Signed-off-by: Peter Maydell +--- + target/arm/cpu-qom.h | 9 ++++++++- + target/arm/cpu.c | 10 ++-------- + target/arm/cpu64.c | 8 +------- + 3 files changed, 11 insertions(+), 16 deletions(-) + +diff --git a/target/arm/cpu-qom.h b/target/arm/cpu-qom.h +index d95568bf05..56395b87f6 100644 +--- a/target/arm/cpu-qom.h ++++ b/target/arm/cpu-qom.h +@@ -35,7 +35,14 @@ struct arm_boot_info; + + #define TYPE_ARM_MAX_CPU "max-" TYPE_ARM_CPU + +-typedef struct ARMCPUInfo ARMCPUInfo; ++typedef struct ARMCPUInfo { ++ const char *name; ++ void (*initfn)(Object *obj); ++ void (*class_init)(ObjectClass *oc, void *data); ++} ARMCPUInfo; ++ ++void arm_cpu_register(const ARMCPUInfo *info); ++void aarch64_cpu_register(const ARMCPUInfo *info); + + /** + * ARMCPUClass: +diff --git a/target/arm/cpu.c b/target/arm/cpu.c +index a79f233b17..47e35400da 100644 +--- a/target/arm/cpu.c ++++ b/target/arm/cpu.c +@@ -2693,12 +2693,6 @@ static void arm_max_initfn(Object *obj) + + #endif /* !defined(CONFIG_USER_ONLY) || !defined(TARGET_AARCH64) */ + +-struct ARMCPUInfo { +- const char *name; +- void (*initfn)(Object *obj); +- void (*class_init)(ObjectClass *oc, void *data); +-}; +- + static const ARMCPUInfo arm_cpus[] = { + #if !defined(CONFIG_USER_ONLY) || !defined(TARGET_AARCH64) + { .name = "arm926", .initfn = arm926_initfn }, +@@ -2864,7 +2858,7 @@ static void cpu_register_class_init(ObjectClass *oc, void *data) + acc->info = data; + } + +-static void cpu_register(const ARMCPUInfo *info) ++void arm_cpu_register(const ARMCPUInfo *info) + { + TypeInfo type_info = { + .parent = TYPE_ARM_CPU, +@@ -2905,7 +2899,7 @@ static void arm_cpu_register_types(void) + type_register_static(&idau_interface_type_info); + + while (info->name) { +- cpu_register(info); ++ arm_cpu_register(info); + info++; + } + +diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c +index 95d0c8c101..74afc28d53 100644 +--- a/target/arm/cpu64.c ++++ b/target/arm/cpu64.c +@@ -737,12 +737,6 @@ static void aarch64_max_initfn(Object *obj) + cpu_max_set_sve_max_vq, NULL, NULL, &error_fatal); + } + +-struct ARMCPUInfo { +- const char *name; +- void (*initfn)(Object *obj); +- void (*class_init)(ObjectClass *oc, void *data); +-}; +- + static const ARMCPUInfo aarch64_cpus[] = { + { .name = "cortex-a57", .initfn = aarch64_a57_initfn }, + { .name = "cortex-a53", .initfn = aarch64_a53_initfn }, +@@ -825,7 +819,7 @@ static void cpu_register_class_init(ObjectClass *oc, void *data) + acc->info = data; + } + +-static void aarch64_cpu_register(const ARMCPUInfo *info) ++void aarch64_cpu_register(const ARMCPUInfo *info) + { + TypeInfo type_info = { + .parent = TYPE_AARCH64_CPU, +-- +2.23.0 + diff --git a/target-arm-Make-set_feature-available-for-other-file.patch b/target-arm-Make-set_feature-available-for-other-file.patch new file mode 100644 index 0000000000000000000000000000000000000000..ffbd5eec5714238ad3c6d63a9df7713bc8208d84 --- /dev/null +++ b/target-arm-Make-set_feature-available-for-other-file.patch @@ -0,0 +1,94 @@ +From 5fda95041d7237ab35733ceb66e0cb89f6107169 Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Mon, 4 May 2020 19:24:45 +0200 +Subject: [PATCH 385/709] target/arm: Make set_feature() available for other + files +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Move the common set_feature() and unset_feature() functions +from cpu.c and cpu64.c to cpu.h. + +Suggested-by: Peter Maydell +Signed-off-by: Thomas Huth +Reviewed-by: Richard Henderson +Reviewed-by: Eric Auger +Signed-off-by: Philippe Mathieu-Daudé +Message-id: 20200504172448.9402-3-philmd@redhat.com +Message-ID: <20190921150420.30743-2-thuth@redhat.com> +[PMD: Split Thomas's patch in two: set_feature, cpu_register] +Signed-off-by: Philippe Mathieu-Daudé +Signed-off-by: Peter Maydell +--- + target/arm/cpu.c | 10 ---------- + target/arm/cpu.h | 10 ++++++++++ + target/arm/cpu64.c | 10 ---------- + 3 files changed, 10 insertions(+), 20 deletions(-) + +diff --git a/target/arm/cpu.c b/target/arm/cpu.c +index 5d64adfe76..13959cb643 100644 +--- a/target/arm/cpu.c ++++ b/target/arm/cpu.c +@@ -725,16 +725,6 @@ static bool arm_cpu_virtio_is_big_endian(CPUState *cs) + + #endif + +-static inline void set_feature(CPUARMState *env, int feature) +-{ +- env->features |= 1ULL << feature; +-} +- +-static inline void unset_feature(CPUARMState *env, int feature) +-{ +- env->features &= ~(1ULL << feature); +-} +- + static int + print_insn_thumb1(bfd_vma pc, disassemble_info *info) + { +diff --git a/target/arm/cpu.h b/target/arm/cpu.h +index 8608da6b6f..676f216b67 100644 +--- a/target/arm/cpu.h ++++ b/target/arm/cpu.h +@@ -696,6 +696,16 @@ typedef struct CPUARMState { + void *gicv3state; + } CPUARMState; + ++static inline void set_feature(CPUARMState *env, int feature) ++{ ++ env->features |= 1ULL << feature; ++} ++ ++static inline void unset_feature(CPUARMState *env, int feature) ++{ ++ env->features &= ~(1ULL << feature); ++} ++ + /** + * ARMELChangeHookFn: + * type of a function which can be registered via arm_register_el_change_hook() +diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c +index 9bdf75b1ab..cbaa5ed228 100644 +--- a/target/arm/cpu64.c ++++ b/target/arm/cpu64.c +@@ -29,16 +29,6 @@ + #include "kvm_arm.h" + #include "qapi/visitor.h" + +-static inline void set_feature(CPUARMState *env, int feature) +-{ +- env->features |= 1ULL << feature; +-} +- +-static inline void unset_feature(CPUARMState *env, int feature) +-{ +- env->features &= ~(1ULL << feature); +-} +- + #ifndef CONFIG_USER_ONLY + static uint64_t a57_a53_l2ctlr_read(CPUARMState *env, const ARMCPRegInfo *ri) + { +-- +2.23.0 + diff --git a/target-arm-Move-env-argument-of-recps_f32-and-rsqrts.patch b/target-arm-Move-env-argument-of-recps_f32-and-rsqrts.patch new file mode 100644 index 0000000000000000000000000000000000000000..673132a396b7bfea38cf1333a0ff208e5b633e5f --- /dev/null +++ b/target-arm-Move-env-argument-of-recps_f32-and-rsqrts.patch @@ -0,0 +1,78 @@ +From 26c6f695cfd2a3ccddb4d015a25b56f56aa62928 Mon Sep 17 00:00:00 2001 +From: Peter Maydell +Date: Tue, 12 May 2020 17:39:02 +0100 +Subject: [PATCH 460/709] target/arm: Move 'env' argument of recps_f32 and + rsqrts_f32 helpers to usual place + +The usual location for the env argument in the argument list of a TCG helper +is immediately after the return-value argument. recps_f32 and rsqrts_f32 +differ in that they put it at the end. + +Move the env argument to its usual place; this will allow us to +more easily use these helper functions with the gvec APIs. + +Signed-off-by: Peter Maydell +Reviewed-by: Richard Henderson +Message-id: 20200512163904.10918-16-peter.maydell@linaro.org +--- + target/arm/helper.h | 4 ++-- + target/arm/translate.c | 4 ++-- + target/arm/vfp_helper.c | 4 ++-- + 3 files changed, 6 insertions(+), 6 deletions(-) + +diff --git a/target/arm/helper.h b/target/arm/helper.h +index 6e9629c87b..49336dc432 100644 +--- a/target/arm/helper.h ++++ b/target/arm/helper.h +@@ -203,8 +203,8 @@ DEF_HELPER_FLAGS_3(vfp_fcvt_f64_to_f16, TCG_CALL_NO_RWG, f16, f64, ptr, i32) + DEF_HELPER_4(vfp_muladdd, f64, f64, f64, f64, ptr) + DEF_HELPER_4(vfp_muladds, f32, f32, f32, f32, ptr) + +-DEF_HELPER_3(recps_f32, f32, f32, f32, env) +-DEF_HELPER_3(rsqrts_f32, f32, f32, f32, env) ++DEF_HELPER_3(recps_f32, f32, env, f32, f32) ++DEF_HELPER_3(rsqrts_f32, f32, env, f32, f32) + DEF_HELPER_FLAGS_2(recpe_f16, TCG_CALL_NO_RWG, f16, f16, ptr) + DEF_HELPER_FLAGS_2(recpe_f32, TCG_CALL_NO_RWG, f32, f32, ptr) + DEF_HELPER_FLAGS_2(recpe_f64, TCG_CALL_NO_RWG, f64, f64, ptr) +diff --git a/target/arm/translate.c b/target/arm/translate.c +index b9fcbbcbcb..23e3705172 100644 +--- a/target/arm/translate.c ++++ b/target/arm/translate.c +@@ -5494,9 +5494,9 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn) + tcg_temp_free_ptr(fpstatus); + } else { + if (size == 0) { +- gen_helper_recps_f32(tmp, tmp, tmp2, cpu_env); ++ gen_helper_recps_f32(tmp, cpu_env, tmp, tmp2); + } else { +- gen_helper_rsqrts_f32(tmp, tmp, tmp2, cpu_env); ++ gen_helper_rsqrts_f32(tmp, cpu_env, tmp, tmp2); + } + } + break; +diff --git a/target/arm/vfp_helper.c b/target/arm/vfp_helper.c +index ec007fce25..88483d4066 100644 +--- a/target/arm/vfp_helper.c ++++ b/target/arm/vfp_helper.c +@@ -581,7 +581,7 @@ uint32_t HELPER(vfp_fcvt_f64_to_f16)(float64 a, void *fpstp, uint32_t ahp_mode) + #define float32_three make_float32(0x40400000) + #define float32_one_point_five make_float32(0x3fc00000) + +-float32 HELPER(recps_f32)(float32 a, float32 b, CPUARMState *env) ++float32 HELPER(recps_f32)(CPUARMState *env, float32 a, float32 b) + { + float_status *s = &env->vfp.standard_fp_status; + if ((float32_is_infinity(a) && float32_is_zero_or_denormal(b)) || +@@ -594,7 +594,7 @@ float32 HELPER(recps_f32)(float32 a, float32 b, CPUARMState *env) + return float32_sub(float32_two, float32_mul(a, b, s), s); + } + +-float32 HELPER(rsqrts_f32)(float32 a, float32 b, CPUARMState *env) ++float32 HELPER(rsqrts_f32)(CPUARMState *env, float32 a, float32 b) + { + float_status *s = &env->vfp.standard_fp_status; + float32 product; +-- +2.23.0 + diff --git a/target-arm-Move-gen_-function-typedefs-to-translate..patch b/target-arm-Move-gen_-function-typedefs-to-translate..patch new file mode 100644 index 0000000000000000000000000000000000000000..2d4bf973efabe727893d1cd5b3ff7abb36d8745b --- /dev/null +++ b/target-arm-Move-gen_-function-typedefs-to-translate..patch @@ -0,0 +1,76 @@ +From 9aefc6cf9b73f66062d2f914a0136756e7a28211 Mon Sep 17 00:00:00 2001 +From: Peter Maydell +Date: Thu, 30 Apr 2020 19:09:49 +0100 +Subject: [PATCH 187/709] target/arm: Move gen_ function typedefs to + translate.h + +We're going to want at least some of the NeonGen* typedefs +for the refactored 32-bit Neon decoder, so move them all +to translate.h since it makes more sense to keep them in +one group. + +Signed-off-by: Peter Maydell +Reviewed-by: Richard Henderson +Message-id: 20200430181003.21682-23-peter.maydell@linaro.org +--- + target/arm/translate-a64.c | 17 ----------------- + target/arm/translate.h | 17 +++++++++++++++++ + 2 files changed, 17 insertions(+), 17 deletions(-) + +diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c +index efb1c4adc4..a896f9c4b8 100644 +--- a/target/arm/translate-a64.c ++++ b/target/arm/translate-a64.c +@@ -70,23 +70,6 @@ typedef struct AArch64DecodeTable { + AArch64DecodeFn *disas_fn; + } AArch64DecodeTable; + +-/* Function prototype for gen_ functions for calling Neon helpers */ +-typedef void NeonGenOneOpEnvFn(TCGv_i32, TCGv_ptr, TCGv_i32); +-typedef void NeonGenTwoOpFn(TCGv_i32, TCGv_i32, TCGv_i32); +-typedef void NeonGenTwoOpEnvFn(TCGv_i32, TCGv_ptr, TCGv_i32, TCGv_i32); +-typedef void NeonGenTwo64OpFn(TCGv_i64, TCGv_i64, TCGv_i64); +-typedef void NeonGenTwo64OpEnvFn(TCGv_i64, TCGv_ptr, TCGv_i64, TCGv_i64); +-typedef void NeonGenNarrowFn(TCGv_i32, TCGv_i64); +-typedef void NeonGenNarrowEnvFn(TCGv_i32, TCGv_ptr, TCGv_i64); +-typedef void NeonGenWidenFn(TCGv_i64, TCGv_i32); +-typedef void NeonGenTwoSingleOPFn(TCGv_i32, TCGv_i32, TCGv_i32, TCGv_ptr); +-typedef void NeonGenTwoDoubleOPFn(TCGv_i64, TCGv_i64, TCGv_i64, TCGv_ptr); +-typedef void NeonGenOneOpFn(TCGv_i64, TCGv_i64); +-typedef void CryptoTwoOpFn(TCGv_ptr, TCGv_ptr); +-typedef void CryptoThreeOpIntFn(TCGv_ptr, TCGv_ptr, TCGv_i32); +-typedef void CryptoThreeOpFn(TCGv_ptr, TCGv_ptr, TCGv_ptr); +-typedef void AtomicThreeOpFn(TCGv_i64, TCGv_i64, TCGv_i64, TCGArg, MemOp); +- + /* initialize TCG globals. */ + void a64_translate_init(void) + { +diff --git a/target/arm/translate.h b/target/arm/translate.h +index 95b43e7ab6..cb7925ea46 100644 +--- a/target/arm/translate.h ++++ b/target/arm/translate.h +@@ -314,4 +314,21 @@ typedef void GVecGen3Fn(unsigned, uint32_t, uint32_t, + typedef void GVecGen4Fn(unsigned, uint32_t, uint32_t, uint32_t, + uint32_t, uint32_t, uint32_t); + ++/* Function prototype for gen_ functions for calling Neon helpers */ ++typedef void NeonGenOneOpEnvFn(TCGv_i32, TCGv_ptr, TCGv_i32); ++typedef void NeonGenTwoOpFn(TCGv_i32, TCGv_i32, TCGv_i32); ++typedef void NeonGenTwoOpEnvFn(TCGv_i32, TCGv_ptr, TCGv_i32, TCGv_i32); ++typedef void NeonGenTwo64OpFn(TCGv_i64, TCGv_i64, TCGv_i64); ++typedef void NeonGenTwo64OpEnvFn(TCGv_i64, TCGv_ptr, TCGv_i64, TCGv_i64); ++typedef void NeonGenNarrowFn(TCGv_i32, TCGv_i64); ++typedef void NeonGenNarrowEnvFn(TCGv_i32, TCGv_ptr, TCGv_i64); ++typedef void NeonGenWidenFn(TCGv_i64, TCGv_i32); ++typedef void NeonGenTwoSingleOPFn(TCGv_i32, TCGv_i32, TCGv_i32, TCGv_ptr); ++typedef void NeonGenTwoDoubleOPFn(TCGv_i64, TCGv_i64, TCGv_i64, TCGv_ptr); ++typedef void NeonGenOneOpFn(TCGv_i64, TCGv_i64); ++typedef void CryptoTwoOpFn(TCGv_ptr, TCGv_ptr); ++typedef void CryptoThreeOpIntFn(TCGv_ptr, TCGv_ptr, TCGv_i32); ++typedef void CryptoThreeOpFn(TCGv_ptr, TCGv_ptr, TCGv_ptr); ++typedef void AtomicThreeOpFn(TCGv_i64, TCGv_i64, TCGv_i64, TCGArg, MemOp); ++ + #endif /* TARGET_ARM_TRANSLATE_H */ +-- +2.23.0 + diff --git a/target-arm-Pass-pointer-to-qc-to-qrdmla-qrdmls.patch b/target-arm-Pass-pointer-to-qc-to-qrdmla-qrdmls.patch new file mode 100644 index 0000000000000000000000000000000000000000..9a507715f63d395ee259b05afeb24453403e68c4 --- /dev/null +++ b/target-arm-Pass-pointer-to-qc-to-qrdmla-qrdmls.patch @@ -0,0 +1,262 @@ +From e286bf4a72fe3a60490b8d6e3f28d6335677e08c Mon Sep 17 00:00:00 2001 +From: Richard Henderson +Date: Wed, 13 May 2020 09:32:42 -0700 +Subject: [PATCH 431/709] target/arm: Pass pointer to qc to qrdmla/qrdmls + +Pass a pointer directly to env->vfp.qc[0], rather than env. +This will allow SVE2, which does not modify QC, to pass a +pointer to dummy storage. + +Change the return type of inl_qrdml.h_s16 to match the +sense of the operation: signed. + +Reviewed-by: Peter Maydell +Signed-off-by: Richard Henderson +Message-id: 20200513163245.17915-14-richard.henderson@linaro.org +Signed-off-by: Peter Maydell +--- + target/arm/translate.c | 18 ++++++++--- + target/arm/vec_helper.c | 70 +++++++++++++++++++++++------------------ + 2 files changed, 54 insertions(+), 34 deletions(-) + +diff --git a/target/arm/translate.c b/target/arm/translate.c +index 39626e0df9..21529a9b8f 100644 +--- a/target/arm/translate.c ++++ b/target/arm/translate.c +@@ -3629,6 +3629,18 @@ static const uint8_t neon_2rm_sizes[] = { + [NEON_2RM_VCVT_UF] = 0x4, + }; + ++static void gen_gvec_fn3_qc(uint32_t rd_ofs, uint32_t rn_ofs, uint32_t rm_ofs, ++ uint32_t opr_sz, uint32_t max_sz, ++ gen_helper_gvec_3_ptr *fn) ++{ ++ TCGv_ptr qc_ptr = tcg_temp_new_ptr(); ++ ++ tcg_gen_addi_ptr(qc_ptr, cpu_env, offsetof(CPUARMState, vfp.qc)); ++ tcg_gen_gvec_3_ptr(rd_ofs, rn_ofs, rm_ofs, qc_ptr, ++ opr_sz, max_sz, 0, fn); ++ tcg_temp_free_ptr(qc_ptr); ++} ++ + void gen_gvec_sqrdmlah_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs, + uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz) + { +@@ -3636,8 +3648,7 @@ void gen_gvec_sqrdmlah_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs, + gen_helper_gvec_qrdmlah_s16, gen_helper_gvec_qrdmlah_s32 + }; + tcg_debug_assert(vece >= 1 && vece <= 2); +- tcg_gen_gvec_3_ptr(rd_ofs, rn_ofs, rm_ofs, cpu_env, +- opr_sz, max_sz, 0, fns[vece - 1]); ++ gen_gvec_fn3_qc(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, fns[vece - 1]); + } + + void gen_gvec_sqrdmlsh_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs, +@@ -3647,8 +3658,7 @@ void gen_gvec_sqrdmlsh_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs, + gen_helper_gvec_qrdmlsh_s16, gen_helper_gvec_qrdmlsh_s32 + }; + tcg_debug_assert(vece >= 1 && vece <= 2); +- tcg_gen_gvec_3_ptr(rd_ofs, rn_ofs, rm_ofs, cpu_env, +- opr_sz, max_sz, 0, fns[vece - 1]); ++ gen_gvec_fn3_qc(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, fns[vece - 1]); + } + + #define GEN_CMP0(NAME, COND) \ +diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c +index 096fea67ef..6aa2ca0827 100644 +--- a/target/arm/vec_helper.c ++++ b/target/arm/vec_helper.c +@@ -36,8 +36,6 @@ + #define H4(x) (x) + #endif + +-#define SET_QC() env->vfp.qc[0] = 1 +- + static void clear_tail(void *vd, uintptr_t opr_sz, uintptr_t max_sz) + { + uint64_t *d = vd + opr_sz; +@@ -49,8 +47,8 @@ static void clear_tail(void *vd, uintptr_t opr_sz, uintptr_t max_sz) + } + + /* Signed saturating rounding doubling multiply-accumulate high half, 16-bit */ +-static uint16_t inl_qrdmlah_s16(CPUARMState *env, int16_t src1, +- int16_t src2, int16_t src3) ++static int16_t inl_qrdmlah_s16(int16_t src1, int16_t src2, ++ int16_t src3, uint32_t *sat) + { + /* Simplify: + * = ((a3 << 16) + ((e1 * e2) << 1) + (1 << 15)) >> 16 +@@ -60,7 +58,7 @@ static uint16_t inl_qrdmlah_s16(CPUARMState *env, int16_t src1, + ret = ((int32_t)src3 << 15) + ret + (1 << 14); + ret >>= 15; + if (ret != (int16_t)ret) { +- SET_QC(); ++ *sat = 1; + ret = (ret < 0 ? -0x8000 : 0x7fff); + } + return ret; +@@ -69,30 +67,30 @@ static uint16_t inl_qrdmlah_s16(CPUARMState *env, int16_t src1, + uint32_t HELPER(neon_qrdmlah_s16)(CPUARMState *env, uint32_t src1, + uint32_t src2, uint32_t src3) + { +- uint16_t e1 = inl_qrdmlah_s16(env, src1, src2, src3); +- uint16_t e2 = inl_qrdmlah_s16(env, src1 >> 16, src2 >> 16, src3 >> 16); ++ uint32_t *sat = &env->vfp.qc[0]; ++ uint16_t e1 = inl_qrdmlah_s16(src1, src2, src3, sat); ++ uint16_t e2 = inl_qrdmlah_s16(src1 >> 16, src2 >> 16, src3 >> 16, sat); + return deposit32(e1, 16, 16, e2); + } + + void HELPER(gvec_qrdmlah_s16)(void *vd, void *vn, void *vm, +- void *ve, uint32_t desc) ++ void *vq, uint32_t desc) + { + uintptr_t opr_sz = simd_oprsz(desc); + int16_t *d = vd; + int16_t *n = vn; + int16_t *m = vm; +- CPUARMState *env = ve; + uintptr_t i; + + for (i = 0; i < opr_sz / 2; ++i) { +- d[i] = inl_qrdmlah_s16(env, n[i], m[i], d[i]); ++ d[i] = inl_qrdmlah_s16(n[i], m[i], d[i], vq); + } + clear_tail(d, opr_sz, simd_maxsz(desc)); + } + + /* Signed saturating rounding doubling multiply-subtract high half, 16-bit */ +-static uint16_t inl_qrdmlsh_s16(CPUARMState *env, int16_t src1, +- int16_t src2, int16_t src3) ++static int16_t inl_qrdmlsh_s16(int16_t src1, int16_t src2, ++ int16_t src3, uint32_t *sat) + { + /* Similarly, using subtraction: + * = ((a3 << 16) - ((e1 * e2) << 1) + (1 << 15)) >> 16 +@@ -102,7 +100,7 @@ static uint16_t inl_qrdmlsh_s16(CPUARMState *env, int16_t src1, + ret = ((int32_t)src3 << 15) - ret + (1 << 14); + ret >>= 15; + if (ret != (int16_t)ret) { +- SET_QC(); ++ *sat = 1; + ret = (ret < 0 ? -0x8000 : 0x7fff); + } + return ret; +@@ -111,85 +109,97 @@ static uint16_t inl_qrdmlsh_s16(CPUARMState *env, int16_t src1, + uint32_t HELPER(neon_qrdmlsh_s16)(CPUARMState *env, uint32_t src1, + uint32_t src2, uint32_t src3) + { +- uint16_t e1 = inl_qrdmlsh_s16(env, src1, src2, src3); +- uint16_t e2 = inl_qrdmlsh_s16(env, src1 >> 16, src2 >> 16, src3 >> 16); ++ uint32_t *sat = &env->vfp.qc[0]; ++ uint16_t e1 = inl_qrdmlsh_s16(src1, src2, src3, sat); ++ uint16_t e2 = inl_qrdmlsh_s16(src1 >> 16, src2 >> 16, src3 >> 16, sat); + return deposit32(e1, 16, 16, e2); + } + + void HELPER(gvec_qrdmlsh_s16)(void *vd, void *vn, void *vm, +- void *ve, uint32_t desc) ++ void *vq, uint32_t desc) + { + uintptr_t opr_sz = simd_oprsz(desc); + int16_t *d = vd; + int16_t *n = vn; + int16_t *m = vm; +- CPUARMState *env = ve; + uintptr_t i; + + for (i = 0; i < opr_sz / 2; ++i) { +- d[i] = inl_qrdmlsh_s16(env, n[i], m[i], d[i]); ++ d[i] = inl_qrdmlsh_s16(n[i], m[i], d[i], vq); + } + clear_tail(d, opr_sz, simd_maxsz(desc)); + } + + /* Signed saturating rounding doubling multiply-accumulate high half, 32-bit */ +-uint32_t HELPER(neon_qrdmlah_s32)(CPUARMState *env, int32_t src1, +- int32_t src2, int32_t src3) ++static int32_t inl_qrdmlah_s32(int32_t src1, int32_t src2, ++ int32_t src3, uint32_t *sat) + { + /* Simplify similarly to int_qrdmlah_s16 above. */ + int64_t ret = (int64_t)src1 * src2; + ret = ((int64_t)src3 << 31) + ret + (1 << 30); + ret >>= 31; + if (ret != (int32_t)ret) { +- SET_QC(); ++ *sat = 1; + ret = (ret < 0 ? INT32_MIN : INT32_MAX); + } + return ret; + } + ++uint32_t HELPER(neon_qrdmlah_s32)(CPUARMState *env, int32_t src1, ++ int32_t src2, int32_t src3) ++{ ++ uint32_t *sat = &env->vfp.qc[0]; ++ return inl_qrdmlah_s32(src1, src2, src3, sat); ++} ++ + void HELPER(gvec_qrdmlah_s32)(void *vd, void *vn, void *vm, +- void *ve, uint32_t desc) ++ void *vq, uint32_t desc) + { + uintptr_t opr_sz = simd_oprsz(desc); + int32_t *d = vd; + int32_t *n = vn; + int32_t *m = vm; +- CPUARMState *env = ve; + uintptr_t i; + + for (i = 0; i < opr_sz / 4; ++i) { +- d[i] = helper_neon_qrdmlah_s32(env, n[i], m[i], d[i]); ++ d[i] = inl_qrdmlah_s32(n[i], m[i], d[i], vq); + } + clear_tail(d, opr_sz, simd_maxsz(desc)); + } + + /* Signed saturating rounding doubling multiply-subtract high half, 32-bit */ +-uint32_t HELPER(neon_qrdmlsh_s32)(CPUARMState *env, int32_t src1, +- int32_t src2, int32_t src3) ++static int32_t inl_qrdmlsh_s32(int32_t src1, int32_t src2, ++ int32_t src3, uint32_t *sat) + { + /* Simplify similarly to int_qrdmlsh_s16 above. */ + int64_t ret = (int64_t)src1 * src2; + ret = ((int64_t)src3 << 31) - ret + (1 << 30); + ret >>= 31; + if (ret != (int32_t)ret) { +- SET_QC(); ++ *sat = 1; + ret = (ret < 0 ? INT32_MIN : INT32_MAX); + } + return ret; + } + ++uint32_t HELPER(neon_qrdmlsh_s32)(CPUARMState *env, int32_t src1, ++ int32_t src2, int32_t src3) ++{ ++ uint32_t *sat = &env->vfp.qc[0]; ++ return inl_qrdmlsh_s32(src1, src2, src3, sat); ++} ++ + void HELPER(gvec_qrdmlsh_s32)(void *vd, void *vn, void *vm, +- void *ve, uint32_t desc) ++ void *vq, uint32_t desc) + { + uintptr_t opr_sz = simd_oprsz(desc); + int32_t *d = vd; + int32_t *n = vn; + int32_t *m = vm; +- CPUARMState *env = ve; + uintptr_t i; + + for (i = 0; i < opr_sz / 4; ++i) { +- d[i] = helper_neon_qrdmlsh_s32(env, n[i], m[i], d[i]); ++ d[i] = inl_qrdmlsh_s32(n[i], m[i], d[i], vq); + } + clear_tail(d, opr_sz, simd_maxsz(desc)); + } +-- +2.23.0 + diff --git a/target-arm-Remove-fp_status-from-helper_-recpe-rsqrt.patch b/target-arm-Remove-fp_status-from-helper_-recpe-rsqrt.patch new file mode 100644 index 0000000000000000000000000000000000000000..d7dcf49e6693f65ba2c822db73b152853bf099e9 --- /dev/null +++ b/target-arm-Remove-fp_status-from-helper_-recpe-rsqrt.patch @@ -0,0 +1,117 @@ +From fe6fb4beb2f9bb0afc813e565504b66a92bbf04b Mon Sep 17 00:00:00 2001 +From: Richard Henderson +Date: Wed, 13 May 2020 09:32:40 -0700 +Subject: [PATCH 429/709] target/arm: Remove fp_status from helper_{recpe, + rsqrte}_u32 + +These operations do not touch fp_status. + +Reviewed-by: Peter Maydell +Signed-off-by: Richard Henderson +Message-id: 20200513163245.17915-12-richard.henderson@linaro.org +Signed-off-by: Peter Maydell +--- + target/arm/helper.h | 4 ++-- + target/arm/translate-a64.c | 5 ++--- + target/arm/translate.c | 12 ++---------- + target/arm/vfp_helper.c | 5 ++--- + 4 files changed, 8 insertions(+), 18 deletions(-) + +diff --git a/target/arm/helper.h b/target/arm/helper.h +index 33c76192d2..aed3050965 100644 +--- a/target/arm/helper.h ++++ b/target/arm/helper.h +@@ -211,8 +211,8 @@ DEF_HELPER_FLAGS_2(recpe_f64, TCG_CALL_NO_RWG, f64, f64, ptr) + DEF_HELPER_FLAGS_2(rsqrte_f16, TCG_CALL_NO_RWG, f16, f16, ptr) + DEF_HELPER_FLAGS_2(rsqrte_f32, TCG_CALL_NO_RWG, f32, f32, ptr) + DEF_HELPER_FLAGS_2(rsqrte_f64, TCG_CALL_NO_RWG, f64, f64, ptr) +-DEF_HELPER_2(recpe_u32, i32, i32, ptr) +-DEF_HELPER_FLAGS_2(rsqrte_u32, TCG_CALL_NO_RWG, i32, i32, ptr) ++DEF_HELPER_FLAGS_1(recpe_u32, TCG_CALL_NO_RWG, i32, i32) ++DEF_HELPER_FLAGS_1(rsqrte_u32, TCG_CALL_NO_RWG, i32, i32) + DEF_HELPER_FLAGS_4(neon_tbl, TCG_CALL_NO_RWG, i32, i32, i32, ptr, i32) + + DEF_HELPER_3(shl_cc, i32, env, i32, i32) +diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c +index ea5f6ceadc..367fa403ae 100644 +--- a/target/arm/translate-a64.c ++++ b/target/arm/translate-a64.c +@@ -9699,7 +9699,7 @@ static void handle_2misc_reciprocal(DisasContext *s, int opcode, + + switch (opcode) { + case 0x3c: /* URECPE */ +- gen_helper_recpe_u32(tcg_res, tcg_op, fpst); ++ gen_helper_recpe_u32(tcg_res, tcg_op); + break; + case 0x3d: /* FRECPE */ + gen_helper_recpe_f32(tcg_res, tcg_op, fpst); +@@ -12244,7 +12244,6 @@ static void disas_simd_two_reg_misc(DisasContext *s, uint32_t insn) + unallocated_encoding(s); + return; + } +- need_fpstatus = true; + break; + case 0x1e: /* FRINT32Z */ + case 0x1f: /* FRINT64Z */ +@@ -12412,7 +12411,7 @@ static void disas_simd_two_reg_misc(DisasContext *s, uint32_t insn) + gen_helper_rints_exact(tcg_res, tcg_op, tcg_fpstatus); + break; + case 0x7c: /* URSQRTE */ +- gen_helper_rsqrte_u32(tcg_res, tcg_op, tcg_fpstatus); ++ gen_helper_rsqrte_u32(tcg_res, tcg_op); + break; + case 0x1e: /* FRINT32Z */ + case 0x5e: /* FRINT32X */ +diff --git a/target/arm/translate.c b/target/arm/translate.c +index 7eb30cde60..391a09b439 100644 +--- a/target/arm/translate.c ++++ b/target/arm/translate.c +@@ -6875,19 +6875,11 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn) + break; + } + case NEON_2RM_VRECPE: +- { +- TCGv_ptr fpstatus = get_fpstatus_ptr(1); +- gen_helper_recpe_u32(tmp, tmp, fpstatus); +- tcg_temp_free_ptr(fpstatus); ++ gen_helper_recpe_u32(tmp, tmp); + break; +- } + case NEON_2RM_VRSQRTE: +- { +- TCGv_ptr fpstatus = get_fpstatus_ptr(1); +- gen_helper_rsqrte_u32(tmp, tmp, fpstatus); +- tcg_temp_free_ptr(fpstatus); ++ gen_helper_rsqrte_u32(tmp, tmp); + break; +- } + case NEON_2RM_VRECPE_F: + { + TCGv_ptr fpstatus = get_fpstatus_ptr(1); +diff --git a/target/arm/vfp_helper.c b/target/arm/vfp_helper.c +index 930d6e747f..ec007fce25 100644 +--- a/target/arm/vfp_helper.c ++++ b/target/arm/vfp_helper.c +@@ -1023,9 +1023,8 @@ float64 HELPER(rsqrte_f64)(float64 input, void *fpstp) + return make_float64(val); + } + +-uint32_t HELPER(recpe_u32)(uint32_t a, void *fpstp) ++uint32_t HELPER(recpe_u32)(uint32_t a) + { +- /* float_status *s = fpstp; */ + int input, estimate; + + if ((a & 0x80000000) == 0) { +@@ -1038,7 +1037,7 @@ uint32_t HELPER(recpe_u32)(uint32_t a, void *fpstp) + return deposit32(0, (32 - 9), 9, estimate); + } + +-uint32_t HELPER(rsqrte_u32)(uint32_t a, void *fpstp) ++uint32_t HELPER(rsqrte_u32)(uint32_t a) + { + int estimate; + +-- +2.23.0 + diff --git a/target-arm-Remove-sve_memopidx.patch b/target-arm-Remove-sve_memopidx.patch new file mode 100644 index 0000000000000000000000000000000000000000..0cb1cf78e3832c22cba9e030ce0b1e113ae9868f --- /dev/null +++ b/target-arm-Remove-sve_memopidx.patch @@ -0,0 +1,152 @@ +From ba080b8682fc6bde7f2d9dedddb519d63cbe138f Mon Sep 17 00:00:00 2001 +From: Richard Henderson +Date: Fri, 8 May 2020 08:43:59 -0700 +Subject: [PATCH 383/709] target/arm: Remove sve_memopidx + +None of the sve helpers use TCGMemOpIdx any longer, so we can +stop passing it. + +Reviewed-by: Peter Maydell +Signed-off-by: Richard Henderson +Message-id: 20200508154359.7494-20-richard.henderson@linaro.org +Signed-off-by: Peter Maydell +--- + target/arm/internals.h | 5 ----- + target/arm/sve_helper.c | 14 +++++++------- + target/arm/translate-sve.c | 17 +++-------------- + 3 files changed, 10 insertions(+), 26 deletions(-) + +diff --git a/target/arm/internals.h b/target/arm/internals.h +index e633aff36e..a833e3941d 100644 +--- a/target/arm/internals.h ++++ b/target/arm/internals.h +@@ -979,11 +979,6 @@ static inline int arm_num_ctx_cmps(ARMCPU *cpu) + } + } + +-/* Note make_memop_idx reserves 4 bits for mmu_idx, and MO_BSWAP is bit 3. +- * Thus a TCGMemOpIdx, without any MO_ALIGN bits, fits in 8 bits. +- */ +-#define MEMOPIDX_SHIFT 8 +- + /** + * v7m_using_psp: Return true if using process stack pointer + * Return true if the CPU is currently using the process stack +diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c +index f1870aabc2..116d535fa5 100644 +--- a/target/arm/sve_helper.c ++++ b/target/arm/sve_helper.c +@@ -4440,7 +4440,7 @@ void sve_ldN_r(CPUARMState *env, uint64_t *vg, const target_ulong addr, + sve_ldst1_host_fn *host_fn, + sve_ldst1_tlb_fn *tlb_fn) + { +- const unsigned rd = extract32(desc, SIMD_DATA_SHIFT + MEMOPIDX_SHIFT, 5); ++ const unsigned rd = simd_data(desc); + const intptr_t reg_max = simd_oprsz(desc); + intptr_t reg_off, reg_last, mem_off; + SVEContLdSt info; +@@ -4696,7 +4696,7 @@ void sve_ldnfff1_r(CPUARMState *env, void *vg, const target_ulong addr, + sve_ldst1_host_fn *host_fn, + sve_ldst1_tlb_fn *tlb_fn) + { +- const unsigned rd = extract32(desc, SIMD_DATA_SHIFT + MEMOPIDX_SHIFT, 5); ++ const unsigned rd = simd_data(desc); + void *vd = &env->vfp.zregs[rd]; + const intptr_t reg_max = simd_oprsz(desc); + intptr_t reg_off, mem_off, reg_last; +@@ -4925,7 +4925,7 @@ void sve_stN_r(CPUARMState *env, uint64_t *vg, target_ulong addr, uint32_t desc, + sve_ldst1_host_fn *host_fn, + sve_ldst1_tlb_fn *tlb_fn) + { +- const unsigned rd = extract32(desc, SIMD_DATA_SHIFT + MEMOPIDX_SHIFT, 5); ++ const unsigned rd = simd_data(desc); + const intptr_t reg_max = simd_oprsz(desc); + intptr_t reg_off, reg_last, mem_off; + SVEContLdSt info; +@@ -5131,9 +5131,9 @@ void sve_ld1_z(CPUARMState *env, void *vd, uint64_t *vg, void *vm, + sve_ldst1_host_fn *host_fn, + sve_ldst1_tlb_fn *tlb_fn) + { +- const int scale = extract32(desc, SIMD_DATA_SHIFT + MEMOPIDX_SHIFT, 2); + const int mmu_idx = cpu_mmu_index(env, false); + const intptr_t reg_max = simd_oprsz(desc); ++ const int scale = simd_data(desc); + ARMVectorReg scratch; + intptr_t reg_off; + SVEHostPage info, info2; +@@ -5276,10 +5276,10 @@ void sve_ldff1_z(CPUARMState *env, void *vd, uint64_t *vg, void *vm, + sve_ldst1_tlb_fn *tlb_fn) + { + const int mmu_idx = cpu_mmu_index(env, false); +- const int scale = extract32(desc, SIMD_DATA_SHIFT + MEMOPIDX_SHIFT, 2); ++ const intptr_t reg_max = simd_oprsz(desc); ++ const int scale = simd_data(desc); + const int esize = 1 << esz; + const int msize = 1 << msz; +- const intptr_t reg_max = simd_oprsz(desc); + intptr_t reg_off; + SVEHostPage info; + target_ulong addr, in_page; +@@ -5430,9 +5430,9 @@ void sve_st1_z(CPUARMState *env, void *vd, uint64_t *vg, void *vm, + sve_ldst1_host_fn *host_fn, + sve_ldst1_tlb_fn *tlb_fn) + { +- const int scale = extract32(desc, SIMD_DATA_SHIFT + MEMOPIDX_SHIFT, 2); + const int mmu_idx = cpu_mmu_index(env, false); + const intptr_t reg_max = simd_oprsz(desc); ++ const int scale = simd_data(desc); + void *host[ARM_MAX_VQ * 4]; + intptr_t reg_off, i; + SVEHostPage info, info2; +diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c +index 6c8bda4e4c..36816aafaf 100644 +--- a/target/arm/translate-sve.c ++++ b/target/arm/translate-sve.c +@@ -4582,11 +4582,6 @@ static const uint8_t dtype_esz[16] = { + 3, 2, 1, 3 + }; + +-static TCGMemOpIdx sve_memopidx(DisasContext *s, int dtype) +-{ +- return make_memop_idx(s->be_data | dtype_mop[dtype], get_mem_index(s)); +-} +- + static void do_mem_zpa(DisasContext *s, int zt, int pg, TCGv_i64 addr, + int dtype, gen_helper_gvec_mem *fn) + { +@@ -4599,9 +4594,7 @@ static void do_mem_zpa(DisasContext *s, int zt, int pg, TCGv_i64 addr, + * registers as pointers, so encode the regno into the data field. + * For consistency, do this even for LD1. + */ +- desc = sve_memopidx(s, dtype); +- desc |= zt << MEMOPIDX_SHIFT; +- desc = simd_desc(vsz, vsz, desc); ++ desc = simd_desc(vsz, vsz, zt); + t_desc = tcg_const_i32(desc); + t_pg = tcg_temp_new_ptr(); + +@@ -4833,9 +4826,7 @@ static void do_ldrq(DisasContext *s, int zt, int pg, TCGv_i64 addr, int msz) + int desc, poff; + + /* Load the first quadword using the normal predicated load helpers. */ +- desc = sve_memopidx(s, msz_dtype(s, msz)); +- desc |= zt << MEMOPIDX_SHIFT; +- desc = simd_desc(16, 16, desc); ++ desc = simd_desc(16, 16, zt); + t_desc = tcg_const_i32(desc); + + poff = pred_full_reg_offset(s, pg); +@@ -5064,9 +5055,7 @@ static void do_mem_zpz(DisasContext *s, int zt, int pg, int zm, + TCGv_i32 t_desc; + int desc; + +- desc = sve_memopidx(s, msz_dtype(s, msz)); +- desc |= scale << MEMOPIDX_SHIFT; +- desc = simd_desc(vsz, vsz, desc); ++ desc = simd_desc(vsz, vsz, scale); + t_desc = tcg_const_i32(desc); + + tcg_gen_addi_ptr(t_pg, cpu_env, pred_full_reg_offset(s, pg)); +-- +2.23.0 + diff --git a/target-arm-Remove-unnecessary-range-check-for-VSHL.patch b/target-arm-Remove-unnecessary-range-check-for-VSHL.patch new file mode 100644 index 0000000000000000000000000000000000000000..7723ff59c28812c7a755ca06fb74fcd4dfc17423 --- /dev/null +++ b/target-arm-Remove-unnecessary-range-check-for-VSHL.patch @@ -0,0 +1,43 @@ +From 2f27c5244db300387f15d9ffa5067a204ffd625d Mon Sep 17 00:00:00 2001 +From: Richard Henderson +Date: Wed, 13 May 2020 09:32:33 -0700 +Subject: [PATCH 422/709] target/arm: Remove unnecessary range check for VSHL + +In 1dc8425e551, while converting to gvec, I added an extra range check +against the shift count. This was unnecessary because the encoding of +the shift count produces 0 to the element size - 1. + +Reviewed-by: Peter Maydell +Signed-off-by: Richard Henderson +Message-id: 20200513163245.17915-5-richard.henderson@linaro.org +Signed-off-by: Peter Maydell +--- + target/arm/translate.c | 12 ++---------- + 1 file changed, 2 insertions(+), 10 deletions(-) + +diff --git a/target/arm/translate.c b/target/arm/translate.c +index 3c489852dc..2eec689c5e 100644 +--- a/target/arm/translate.c ++++ b/target/arm/translate.c +@@ -5752,16 +5752,8 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn) + gen_gvec_sli(size, rd_ofs, rm_ofs, shift, + vec_size, vec_size); + } else { /* VSHL */ +- /* Shifts larger than the element size are +- * architecturally valid and results in zero. +- */ +- if (shift >= 8 << size) { +- tcg_gen_gvec_dup_imm(size, rd_ofs, +- vec_size, vec_size, 0); +- } else { +- tcg_gen_gvec_shli(size, rd_ofs, rm_ofs, shift, +- vec_size, vec_size); +- } ++ tcg_gen_gvec_shli(size, rd_ofs, rm_ofs, shift, ++ vec_size, vec_size); + } + return 0; + } +-- +2.23.0 + diff --git a/target-arm-Remove-unused-GEN_NEON_INTEGER_OP-macro.patch b/target-arm-Remove-unused-GEN_NEON_INTEGER_OP-macro.patch new file mode 100644 index 0000000000000000000000000000000000000000..aa085f87d81665e1b4d1d20b7c41f7a73ef0e9de --- /dev/null +++ b/target-arm-Remove-unused-GEN_NEON_INTEGER_OP-macro.patch @@ -0,0 +1,50 @@ +From ef81aa68a708ba5162e1d5fa8d98171ac1059e2d Mon Sep 17 00:00:00 2001 +From: Peter Maydell +Date: Fri, 15 May 2020 15:20:47 +0100 +Subject: [PATCH 616/709] target/arm: Remove unused GEN_NEON_INTEGER_OP macro + +The GEN_NEON_INTEGER_OP macro is no longer used; remove it. + +Signed-off-by: Peter Maydell +Reviewed-by: Richard Henderson +--- + target/arm/translate.c | 23 ----------------------- + 1 file changed, 23 deletions(-) + +diff --git a/target/arm/translate.c b/target/arm/translate.c +index 4c9bb8b5ac..c8296116d4 100644 +--- a/target/arm/translate.c ++++ b/target/arm/translate.c +@@ -3034,29 +3034,6 @@ static inline void gen_neon_rsb(int size, TCGv_i32 t0, TCGv_i32 t1) + default: return 1; \ + }} while (0) + +-#define GEN_NEON_INTEGER_OP(name) do { \ +- switch ((size << 1) | u) { \ +- case 0: \ +- gen_helper_neon_##name##_s8(tmp, tmp, tmp2); \ +- break; \ +- case 1: \ +- gen_helper_neon_##name##_u8(tmp, tmp, tmp2); \ +- break; \ +- case 2: \ +- gen_helper_neon_##name##_s16(tmp, tmp, tmp2); \ +- break; \ +- case 3: \ +- gen_helper_neon_##name##_u16(tmp, tmp, tmp2); \ +- break; \ +- case 4: \ +- gen_helper_neon_##name##_s32(tmp, tmp, tmp2); \ +- break; \ +- case 5: \ +- gen_helper_neon_##name##_u32(tmp, tmp, tmp2); \ +- break; \ +- default: return 1; \ +- }} while (0) +- + static TCGv_i32 neon_load_scratch(int scratch) + { + TCGv_i32 tmp = tcg_temp_new_i32(); +-- +2.23.0 + diff --git a/target-arm-Restrict-TCG-cpus-to-TCG-accel.patch b/target-arm-Restrict-TCG-cpus-to-TCG-accel.patch new file mode 100644 index 0000000000000000000000000000000000000000..c0595e9f26dbe2b43fcc5d076edf3edf00f74689 --- /dev/null +++ b/target-arm-Restrict-TCG-cpus-to-TCG-accel.patch @@ -0,0 +1,1376 @@ +From 2465b07c0bd4f7a97bbcbefbd7f7432230485bea Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Mon, 4 May 2020 19:24:48 +0200 +Subject: [PATCH 388/709] target/arm: Restrict TCG cpus to TCG accel +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +A KVM-only build won't be able to run TCG cpus. + +Reviewed-by: Richard Henderson +Signed-off-by: Philippe Mathieu-Daudé +Message-id: 20200504172448.9402-6-philmd@redhat.com +Signed-off-by: Peter Maydell +--- + target/arm/Makefile.objs | 1 + + target/arm/cpu.c | 634 ------------------------------------- + target/arm/cpu_tcg.c | 664 +++++++++++++++++++++++++++++++++++++++ + 3 files changed, 665 insertions(+), 634 deletions(-) + create mode 100644 target/arm/cpu_tcg.c + +diff --git a/target/arm/Makefile.objs b/target/arm/Makefile.objs +index 775b3e24f2..83febd232c 100644 +--- a/target/arm/Makefile.objs ++++ b/target/arm/Makefile.objs +@@ -79,6 +79,7 @@ obj-y += translate.o op_helper.o + obj-y += crypto_helper.o + obj-y += iwmmxt_helper.o vec_helper.o neon_helper.o + obj-y += m_helper.o ++obj-y += cpu_tcg.o + + obj-$(CONFIG_SOFTMMU) += psci.o + +diff --git a/target/arm/cpu.c b/target/arm/cpu.c +index a10f8c4044..3794f0dbc4 100644 +--- a/target/arm/cpu.c ++++ b/target/arm/cpu.c +@@ -574,32 +574,6 @@ bool arm_cpu_exec_interrupt(CPUState *cs, int interrupt_request) + return true; + } + +-#if !defined(CONFIG_USER_ONLY) || !defined(TARGET_AARCH64) +-static bool arm_v7m_cpu_exec_interrupt(CPUState *cs, int interrupt_request) +-{ +- CPUClass *cc = CPU_GET_CLASS(cs); +- ARMCPU *cpu = ARM_CPU(cs); +- CPUARMState *env = &cpu->env; +- bool ret = false; +- +- /* +- * ARMv7-M interrupt masking works differently than -A or -R. +- * There is no FIQ/IRQ distinction. Instead of I and F bits +- * masking FIQ and IRQ interrupts, an exception is taken only +- * if it is higher priority than the current execution priority +- * (which depends on state like BASEPRI, FAULTMASK and the +- * currently active exception). +- */ +- if (interrupt_request & CPU_INTERRUPT_HARD +- && (armv7m_nvic_can_take_pending_exception(env->nvic))) { +- cs->exception_index = EXCP_IRQ; +- cc->do_interrupt(cs); +- ret = true; +- } +- return ret; +-} +-#endif +- + void arm_cpu_update_virq(ARMCPU *cpu) + { + /* +@@ -1820,406 +1794,6 @@ static ObjectClass *arm_cpu_class_by_name(const char *cpu_model) + /* CPU models. These are not needed for the AArch64 linux-user build. */ + #if !defined(CONFIG_USER_ONLY) || !defined(TARGET_AARCH64) + +-static void arm926_initfn(Object *obj) +-{ +- ARMCPU *cpu = ARM_CPU(obj); +- +- cpu->dtb_compatible = "arm,arm926"; +- set_feature(&cpu->env, ARM_FEATURE_V5); +- set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS); +- set_feature(&cpu->env, ARM_FEATURE_CACHE_TEST_CLEAN); +- cpu->midr = 0x41069265; +- cpu->reset_fpsid = 0x41011090; +- cpu->ctr = 0x1dd20d2; +- cpu->reset_sctlr = 0x00090078; +- +- /* +- * ARMv5 does not have the ID_ISAR registers, but we can still +- * set the field to indicate Jazelle support within QEMU. +- */ +- cpu->isar.id_isar1 = FIELD_DP32(cpu->isar.id_isar1, ID_ISAR1, JAZELLE, 1); +- /* +- * Similarly, we need to set MVFR0 fields to enable vfp and short vector +- * support even though ARMv5 doesn't have this register. +- */ +- cpu->isar.mvfr0 = FIELD_DP32(cpu->isar.mvfr0, MVFR0, FPSHVEC, 1); +- cpu->isar.mvfr0 = FIELD_DP32(cpu->isar.mvfr0, MVFR0, FPSP, 1); +- cpu->isar.mvfr0 = FIELD_DP32(cpu->isar.mvfr0, MVFR0, FPDP, 1); +-} +- +-static void arm946_initfn(Object *obj) +-{ +- ARMCPU *cpu = ARM_CPU(obj); +- +- cpu->dtb_compatible = "arm,arm946"; +- set_feature(&cpu->env, ARM_FEATURE_V5); +- set_feature(&cpu->env, ARM_FEATURE_PMSA); +- set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS); +- cpu->midr = 0x41059461; +- cpu->ctr = 0x0f004006; +- cpu->reset_sctlr = 0x00000078; +-} +- +-static void arm1026_initfn(Object *obj) +-{ +- ARMCPU *cpu = ARM_CPU(obj); +- +- cpu->dtb_compatible = "arm,arm1026"; +- set_feature(&cpu->env, ARM_FEATURE_V5); +- set_feature(&cpu->env, ARM_FEATURE_AUXCR); +- set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS); +- set_feature(&cpu->env, ARM_FEATURE_CACHE_TEST_CLEAN); +- cpu->midr = 0x4106a262; +- cpu->reset_fpsid = 0x410110a0; +- cpu->ctr = 0x1dd20d2; +- cpu->reset_sctlr = 0x00090078; +- cpu->reset_auxcr = 1; +- +- /* +- * ARMv5 does not have the ID_ISAR registers, but we can still +- * set the field to indicate Jazelle support within QEMU. +- */ +- cpu->isar.id_isar1 = FIELD_DP32(cpu->isar.id_isar1, ID_ISAR1, JAZELLE, 1); +- /* +- * Similarly, we need to set MVFR0 fields to enable vfp and short vector +- * support even though ARMv5 doesn't have this register. +- */ +- cpu->isar.mvfr0 = FIELD_DP32(cpu->isar.mvfr0, MVFR0, FPSHVEC, 1); +- cpu->isar.mvfr0 = FIELD_DP32(cpu->isar.mvfr0, MVFR0, FPSP, 1); +- cpu->isar.mvfr0 = FIELD_DP32(cpu->isar.mvfr0, MVFR0, FPDP, 1); +- +- { +- /* The 1026 had an IFAR at c6,c0,0,1 rather than the ARMv6 c6,c0,0,2 */ +- ARMCPRegInfo ifar = { +- .name = "IFAR", .cp = 15, .crn = 6, .crm = 0, .opc1 = 0, .opc2 = 1, +- .access = PL1_RW, +- .fieldoffset = offsetof(CPUARMState, cp15.ifar_ns), +- .resetvalue = 0 +- }; +- define_one_arm_cp_reg(cpu, &ifar); +- } +-} +- +-static void arm1136_r2_initfn(Object *obj) +-{ +- ARMCPU *cpu = ARM_CPU(obj); +- /* +- * What qemu calls "arm1136_r2" is actually the 1136 r0p2, ie an +- * older core than plain "arm1136". In particular this does not +- * have the v6K features. +- * These ID register values are correct for 1136 but may be wrong +- * for 1136_r2 (in particular r0p2 does not actually implement most +- * of the ID registers). +- */ +- +- cpu->dtb_compatible = "arm,arm1136"; +- set_feature(&cpu->env, ARM_FEATURE_V6); +- set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS); +- set_feature(&cpu->env, ARM_FEATURE_CACHE_DIRTY_REG); +- set_feature(&cpu->env, ARM_FEATURE_CACHE_BLOCK_OPS); +- cpu->midr = 0x4107b362; +- cpu->reset_fpsid = 0x410120b4; +- cpu->isar.mvfr0 = 0x11111111; +- cpu->isar.mvfr1 = 0x00000000; +- cpu->ctr = 0x1dd20d2; +- cpu->reset_sctlr = 0x00050078; +- cpu->id_pfr0 = 0x111; +- cpu->id_pfr1 = 0x1; +- cpu->isar.id_dfr0 = 0x2; +- cpu->id_afr0 = 0x3; +- cpu->isar.id_mmfr0 = 0x01130003; +- cpu->isar.id_mmfr1 = 0x10030302; +- cpu->isar.id_mmfr2 = 0x01222110; +- cpu->isar.id_isar0 = 0x00140011; +- cpu->isar.id_isar1 = 0x12002111; +- cpu->isar.id_isar2 = 0x11231111; +- cpu->isar.id_isar3 = 0x01102131; +- cpu->isar.id_isar4 = 0x141; +- cpu->reset_auxcr = 7; +-} +- +-static void arm1136_initfn(Object *obj) +-{ +- ARMCPU *cpu = ARM_CPU(obj); +- +- cpu->dtb_compatible = "arm,arm1136"; +- set_feature(&cpu->env, ARM_FEATURE_V6K); +- set_feature(&cpu->env, ARM_FEATURE_V6); +- set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS); +- set_feature(&cpu->env, ARM_FEATURE_CACHE_DIRTY_REG); +- set_feature(&cpu->env, ARM_FEATURE_CACHE_BLOCK_OPS); +- cpu->midr = 0x4117b363; +- cpu->reset_fpsid = 0x410120b4; +- cpu->isar.mvfr0 = 0x11111111; +- cpu->isar.mvfr1 = 0x00000000; +- cpu->ctr = 0x1dd20d2; +- cpu->reset_sctlr = 0x00050078; +- cpu->id_pfr0 = 0x111; +- cpu->id_pfr1 = 0x1; +- cpu->isar.id_dfr0 = 0x2; +- cpu->id_afr0 = 0x3; +- cpu->isar.id_mmfr0 = 0x01130003; +- cpu->isar.id_mmfr1 = 0x10030302; +- cpu->isar.id_mmfr2 = 0x01222110; +- cpu->isar.id_isar0 = 0x00140011; +- cpu->isar.id_isar1 = 0x12002111; +- cpu->isar.id_isar2 = 0x11231111; +- cpu->isar.id_isar3 = 0x01102131; +- cpu->isar.id_isar4 = 0x141; +- cpu->reset_auxcr = 7; +-} +- +-static void arm1176_initfn(Object *obj) +-{ +- ARMCPU *cpu = ARM_CPU(obj); +- +- cpu->dtb_compatible = "arm,arm1176"; +- set_feature(&cpu->env, ARM_FEATURE_V6K); +- set_feature(&cpu->env, ARM_FEATURE_VAPA); +- set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS); +- set_feature(&cpu->env, ARM_FEATURE_CACHE_DIRTY_REG); +- set_feature(&cpu->env, ARM_FEATURE_CACHE_BLOCK_OPS); +- set_feature(&cpu->env, ARM_FEATURE_EL3); +- cpu->midr = 0x410fb767; +- cpu->reset_fpsid = 0x410120b5; +- cpu->isar.mvfr0 = 0x11111111; +- cpu->isar.mvfr1 = 0x00000000; +- cpu->ctr = 0x1dd20d2; +- cpu->reset_sctlr = 0x00050078; +- cpu->id_pfr0 = 0x111; +- cpu->id_pfr1 = 0x11; +- cpu->isar.id_dfr0 = 0x33; +- cpu->id_afr0 = 0; +- cpu->isar.id_mmfr0 = 0x01130003; +- cpu->isar.id_mmfr1 = 0x10030302; +- cpu->isar.id_mmfr2 = 0x01222100; +- cpu->isar.id_isar0 = 0x0140011; +- cpu->isar.id_isar1 = 0x12002111; +- cpu->isar.id_isar2 = 0x11231121; +- cpu->isar.id_isar3 = 0x01102131; +- cpu->isar.id_isar4 = 0x01141; +- cpu->reset_auxcr = 7; +-} +- +-static void arm11mpcore_initfn(Object *obj) +-{ +- ARMCPU *cpu = ARM_CPU(obj); +- +- cpu->dtb_compatible = "arm,arm11mpcore"; +- set_feature(&cpu->env, ARM_FEATURE_V6K); +- set_feature(&cpu->env, ARM_FEATURE_VAPA); +- set_feature(&cpu->env, ARM_FEATURE_MPIDR); +- set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS); +- cpu->midr = 0x410fb022; +- cpu->reset_fpsid = 0x410120b4; +- cpu->isar.mvfr0 = 0x11111111; +- cpu->isar.mvfr1 = 0x00000000; +- cpu->ctr = 0x1d192992; /* 32K icache 32K dcache */ +- cpu->id_pfr0 = 0x111; +- cpu->id_pfr1 = 0x1; +- cpu->isar.id_dfr0 = 0; +- cpu->id_afr0 = 0x2; +- cpu->isar.id_mmfr0 = 0x01100103; +- cpu->isar.id_mmfr1 = 0x10020302; +- cpu->isar.id_mmfr2 = 0x01222000; +- cpu->isar.id_isar0 = 0x00100011; +- cpu->isar.id_isar1 = 0x12002111; +- cpu->isar.id_isar2 = 0x11221011; +- cpu->isar.id_isar3 = 0x01102131; +- cpu->isar.id_isar4 = 0x141; +- cpu->reset_auxcr = 1; +-} +- +-static void cortex_m0_initfn(Object *obj) +-{ +- ARMCPU *cpu = ARM_CPU(obj); +- set_feature(&cpu->env, ARM_FEATURE_V6); +- set_feature(&cpu->env, ARM_FEATURE_M); +- +- cpu->midr = 0x410cc200; +-} +- +-static void cortex_m3_initfn(Object *obj) +-{ +- ARMCPU *cpu = ARM_CPU(obj); +- set_feature(&cpu->env, ARM_FEATURE_V7); +- set_feature(&cpu->env, ARM_FEATURE_M); +- set_feature(&cpu->env, ARM_FEATURE_M_MAIN); +- cpu->midr = 0x410fc231; +- cpu->pmsav7_dregion = 8; +- cpu->id_pfr0 = 0x00000030; +- cpu->id_pfr1 = 0x00000200; +- cpu->isar.id_dfr0 = 0x00100000; +- cpu->id_afr0 = 0x00000000; +- cpu->isar.id_mmfr0 = 0x00000030; +- cpu->isar.id_mmfr1 = 0x00000000; +- cpu->isar.id_mmfr2 = 0x00000000; +- cpu->isar.id_mmfr3 = 0x00000000; +- cpu->isar.id_isar0 = 0x01141110; +- cpu->isar.id_isar1 = 0x02111000; +- cpu->isar.id_isar2 = 0x21112231; +- cpu->isar.id_isar3 = 0x01111110; +- cpu->isar.id_isar4 = 0x01310102; +- cpu->isar.id_isar5 = 0x00000000; +- cpu->isar.id_isar6 = 0x00000000; +-} +- +-static void cortex_m4_initfn(Object *obj) +-{ +- ARMCPU *cpu = ARM_CPU(obj); +- +- set_feature(&cpu->env, ARM_FEATURE_V7); +- set_feature(&cpu->env, ARM_FEATURE_M); +- set_feature(&cpu->env, ARM_FEATURE_M_MAIN); +- set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP); +- cpu->midr = 0x410fc240; /* r0p0 */ +- cpu->pmsav7_dregion = 8; +- cpu->isar.mvfr0 = 0x10110021; +- cpu->isar.mvfr1 = 0x11000011; +- cpu->isar.mvfr2 = 0x00000000; +- cpu->id_pfr0 = 0x00000030; +- cpu->id_pfr1 = 0x00000200; +- cpu->isar.id_dfr0 = 0x00100000; +- cpu->id_afr0 = 0x00000000; +- cpu->isar.id_mmfr0 = 0x00000030; +- cpu->isar.id_mmfr1 = 0x00000000; +- cpu->isar.id_mmfr2 = 0x00000000; +- cpu->isar.id_mmfr3 = 0x00000000; +- cpu->isar.id_isar0 = 0x01141110; +- cpu->isar.id_isar1 = 0x02111000; +- cpu->isar.id_isar2 = 0x21112231; +- cpu->isar.id_isar3 = 0x01111110; +- cpu->isar.id_isar4 = 0x01310102; +- cpu->isar.id_isar5 = 0x00000000; +- cpu->isar.id_isar6 = 0x00000000; +-} +- +-static void cortex_m7_initfn(Object *obj) +-{ +- ARMCPU *cpu = ARM_CPU(obj); +- +- set_feature(&cpu->env, ARM_FEATURE_V7); +- set_feature(&cpu->env, ARM_FEATURE_M); +- set_feature(&cpu->env, ARM_FEATURE_M_MAIN); +- set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP); +- cpu->midr = 0x411fc272; /* r1p2 */ +- cpu->pmsav7_dregion = 8; +- cpu->isar.mvfr0 = 0x10110221; +- cpu->isar.mvfr1 = 0x12000011; +- cpu->isar.mvfr2 = 0x00000040; +- cpu->id_pfr0 = 0x00000030; +- cpu->id_pfr1 = 0x00000200; +- cpu->isar.id_dfr0 = 0x00100000; +- cpu->id_afr0 = 0x00000000; +- cpu->isar.id_mmfr0 = 0x00100030; +- cpu->isar.id_mmfr1 = 0x00000000; +- cpu->isar.id_mmfr2 = 0x01000000; +- cpu->isar.id_mmfr3 = 0x00000000; +- cpu->isar.id_isar0 = 0x01101110; +- cpu->isar.id_isar1 = 0x02112000; +- cpu->isar.id_isar2 = 0x20232231; +- cpu->isar.id_isar3 = 0x01111131; +- cpu->isar.id_isar4 = 0x01310132; +- cpu->isar.id_isar5 = 0x00000000; +- cpu->isar.id_isar6 = 0x00000000; +-} +- +-static void cortex_m33_initfn(Object *obj) +-{ +- ARMCPU *cpu = ARM_CPU(obj); +- +- set_feature(&cpu->env, ARM_FEATURE_V8); +- set_feature(&cpu->env, ARM_FEATURE_M); +- set_feature(&cpu->env, ARM_FEATURE_M_MAIN); +- set_feature(&cpu->env, ARM_FEATURE_M_SECURITY); +- set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP); +- cpu->midr = 0x410fd213; /* r0p3 */ +- cpu->pmsav7_dregion = 16; +- cpu->sau_sregion = 8; +- cpu->isar.mvfr0 = 0x10110021; +- cpu->isar.mvfr1 = 0x11000011; +- cpu->isar.mvfr2 = 0x00000040; +- cpu->id_pfr0 = 0x00000030; +- cpu->id_pfr1 = 0x00000210; +- cpu->isar.id_dfr0 = 0x00200000; +- cpu->id_afr0 = 0x00000000; +- cpu->isar.id_mmfr0 = 0x00101F40; +- cpu->isar.id_mmfr1 = 0x00000000; +- cpu->isar.id_mmfr2 = 0x01000000; +- cpu->isar.id_mmfr3 = 0x00000000; +- cpu->isar.id_isar0 = 0x01101110; +- cpu->isar.id_isar1 = 0x02212000; +- cpu->isar.id_isar2 = 0x20232232; +- cpu->isar.id_isar3 = 0x01111131; +- cpu->isar.id_isar4 = 0x01310132; +- cpu->isar.id_isar5 = 0x00000000; +- cpu->isar.id_isar6 = 0x00000000; +- cpu->clidr = 0x00000000; +- cpu->ctr = 0x8000c000; +-} +- +-static void arm_v7m_class_init(ObjectClass *oc, void *data) +-{ +- ARMCPUClass *acc = ARM_CPU_CLASS(oc); +- CPUClass *cc = CPU_CLASS(oc); +- +- acc->info = data; +-#ifndef CONFIG_USER_ONLY +- cc->do_interrupt = arm_v7m_cpu_do_interrupt; +-#endif +- +- cc->cpu_exec_interrupt = arm_v7m_cpu_exec_interrupt; +-} +- +-static const ARMCPRegInfo cortexr5_cp_reginfo[] = { +- /* Dummy the TCM region regs for the moment */ +- { .name = "ATCM", .cp = 15, .opc1 = 0, .crn = 9, .crm = 1, .opc2 = 0, +- .access = PL1_RW, .type = ARM_CP_CONST }, +- { .name = "BTCM", .cp = 15, .opc1 = 0, .crn = 9, .crm = 1, .opc2 = 1, +- .access = PL1_RW, .type = ARM_CP_CONST }, +- { .name = "DCACHE_INVAL", .cp = 15, .opc1 = 0, .crn = 15, .crm = 5, +- .opc2 = 0, .access = PL1_W, .type = ARM_CP_NOP }, +- REGINFO_SENTINEL +-}; +- +-static void cortex_r5_initfn(Object *obj) +-{ +- ARMCPU *cpu = ARM_CPU(obj); +- +- set_feature(&cpu->env, ARM_FEATURE_V7); +- set_feature(&cpu->env, ARM_FEATURE_V7MP); +- set_feature(&cpu->env, ARM_FEATURE_PMSA); +- set_feature(&cpu->env, ARM_FEATURE_PMU); +- cpu->midr = 0x411fc153; /* r1p3 */ +- cpu->id_pfr0 = 0x0131; +- cpu->id_pfr1 = 0x001; +- cpu->isar.id_dfr0 = 0x010400; +- cpu->id_afr0 = 0x0; +- cpu->isar.id_mmfr0 = 0x0210030; +- cpu->isar.id_mmfr1 = 0x00000000; +- cpu->isar.id_mmfr2 = 0x01200000; +- cpu->isar.id_mmfr3 = 0x0211; +- cpu->isar.id_isar0 = 0x02101111; +- cpu->isar.id_isar1 = 0x13112111; +- cpu->isar.id_isar2 = 0x21232141; +- cpu->isar.id_isar3 = 0x01112131; +- cpu->isar.id_isar4 = 0x0010142; +- cpu->isar.id_isar5 = 0x0; +- cpu->isar.id_isar6 = 0x0; +- cpu->mp_is_up = true; +- cpu->pmsav7_dregion = 16; +- define_arm_cp_regs(cpu, cortexr5_cp_reginfo); +-} +- +-static void cortex_r5f_initfn(Object *obj) +-{ +- ARMCPU *cpu = ARM_CPU(obj); +- +- cortex_r5_initfn(obj); +- cpu->isar.mvfr0 = 0x10110221; +- cpu->isar.mvfr1 = 0x00000011; +-} +- + static const ARMCPRegInfo cortexa8_cp_reginfo[] = { + { .name = "L2LOCKDOWN", .cp = 15, .crn = 9, .crm = 0, .opc1 = 1, .opc2 = 0, + .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 }, +@@ -2446,174 +2020,6 @@ static void cortex_a15_initfn(Object *obj) + define_arm_cp_regs(cpu, cortexa15_cp_reginfo); + } + +-static void ti925t_initfn(Object *obj) +-{ +- ARMCPU *cpu = ARM_CPU(obj); +- set_feature(&cpu->env, ARM_FEATURE_V4T); +- set_feature(&cpu->env, ARM_FEATURE_OMAPCP); +- cpu->midr = ARM_CPUID_TI925T; +- cpu->ctr = 0x5109149; +- cpu->reset_sctlr = 0x00000070; +-} +- +-static void sa1100_initfn(Object *obj) +-{ +- ARMCPU *cpu = ARM_CPU(obj); +- +- cpu->dtb_compatible = "intel,sa1100"; +- set_feature(&cpu->env, ARM_FEATURE_STRONGARM); +- set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS); +- cpu->midr = 0x4401A11B; +- cpu->reset_sctlr = 0x00000070; +-} +- +-static void sa1110_initfn(Object *obj) +-{ +- ARMCPU *cpu = ARM_CPU(obj); +- set_feature(&cpu->env, ARM_FEATURE_STRONGARM); +- set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS); +- cpu->midr = 0x6901B119; +- cpu->reset_sctlr = 0x00000070; +-} +- +-static void pxa250_initfn(Object *obj) +-{ +- ARMCPU *cpu = ARM_CPU(obj); +- +- cpu->dtb_compatible = "marvell,xscale"; +- set_feature(&cpu->env, ARM_FEATURE_V5); +- set_feature(&cpu->env, ARM_FEATURE_XSCALE); +- cpu->midr = 0x69052100; +- cpu->ctr = 0xd172172; +- cpu->reset_sctlr = 0x00000078; +-} +- +-static void pxa255_initfn(Object *obj) +-{ +- ARMCPU *cpu = ARM_CPU(obj); +- +- cpu->dtb_compatible = "marvell,xscale"; +- set_feature(&cpu->env, ARM_FEATURE_V5); +- set_feature(&cpu->env, ARM_FEATURE_XSCALE); +- cpu->midr = 0x69052d00; +- cpu->ctr = 0xd172172; +- cpu->reset_sctlr = 0x00000078; +-} +- +-static void pxa260_initfn(Object *obj) +-{ +- ARMCPU *cpu = ARM_CPU(obj); +- +- cpu->dtb_compatible = "marvell,xscale"; +- set_feature(&cpu->env, ARM_FEATURE_V5); +- set_feature(&cpu->env, ARM_FEATURE_XSCALE); +- cpu->midr = 0x69052903; +- cpu->ctr = 0xd172172; +- cpu->reset_sctlr = 0x00000078; +-} +- +-static void pxa261_initfn(Object *obj) +-{ +- ARMCPU *cpu = ARM_CPU(obj); +- +- cpu->dtb_compatible = "marvell,xscale"; +- set_feature(&cpu->env, ARM_FEATURE_V5); +- set_feature(&cpu->env, ARM_FEATURE_XSCALE); +- cpu->midr = 0x69052d05; +- cpu->ctr = 0xd172172; +- cpu->reset_sctlr = 0x00000078; +-} +- +-static void pxa262_initfn(Object *obj) +-{ +- ARMCPU *cpu = ARM_CPU(obj); +- +- cpu->dtb_compatible = "marvell,xscale"; +- set_feature(&cpu->env, ARM_FEATURE_V5); +- set_feature(&cpu->env, ARM_FEATURE_XSCALE); +- cpu->midr = 0x69052d06; +- cpu->ctr = 0xd172172; +- cpu->reset_sctlr = 0x00000078; +-} +- +-static void pxa270a0_initfn(Object *obj) +-{ +- ARMCPU *cpu = ARM_CPU(obj); +- +- cpu->dtb_compatible = "marvell,xscale"; +- set_feature(&cpu->env, ARM_FEATURE_V5); +- set_feature(&cpu->env, ARM_FEATURE_XSCALE); +- set_feature(&cpu->env, ARM_FEATURE_IWMMXT); +- cpu->midr = 0x69054110; +- cpu->ctr = 0xd172172; +- cpu->reset_sctlr = 0x00000078; +-} +- +-static void pxa270a1_initfn(Object *obj) +-{ +- ARMCPU *cpu = ARM_CPU(obj); +- +- cpu->dtb_compatible = "marvell,xscale"; +- set_feature(&cpu->env, ARM_FEATURE_V5); +- set_feature(&cpu->env, ARM_FEATURE_XSCALE); +- set_feature(&cpu->env, ARM_FEATURE_IWMMXT); +- cpu->midr = 0x69054111; +- cpu->ctr = 0xd172172; +- cpu->reset_sctlr = 0x00000078; +-} +- +-static void pxa270b0_initfn(Object *obj) +-{ +- ARMCPU *cpu = ARM_CPU(obj); +- +- cpu->dtb_compatible = "marvell,xscale"; +- set_feature(&cpu->env, ARM_FEATURE_V5); +- set_feature(&cpu->env, ARM_FEATURE_XSCALE); +- set_feature(&cpu->env, ARM_FEATURE_IWMMXT); +- cpu->midr = 0x69054112; +- cpu->ctr = 0xd172172; +- cpu->reset_sctlr = 0x00000078; +-} +- +-static void pxa270b1_initfn(Object *obj) +-{ +- ARMCPU *cpu = ARM_CPU(obj); +- +- cpu->dtb_compatible = "marvell,xscale"; +- set_feature(&cpu->env, ARM_FEATURE_V5); +- set_feature(&cpu->env, ARM_FEATURE_XSCALE); +- set_feature(&cpu->env, ARM_FEATURE_IWMMXT); +- cpu->midr = 0x69054113; +- cpu->ctr = 0xd172172; +- cpu->reset_sctlr = 0x00000078; +-} +- +-static void pxa270c0_initfn(Object *obj) +-{ +- ARMCPU *cpu = ARM_CPU(obj); +- +- cpu->dtb_compatible = "marvell,xscale"; +- set_feature(&cpu->env, ARM_FEATURE_V5); +- set_feature(&cpu->env, ARM_FEATURE_XSCALE); +- set_feature(&cpu->env, ARM_FEATURE_IWMMXT); +- cpu->midr = 0x69054114; +- cpu->ctr = 0xd172172; +- cpu->reset_sctlr = 0x00000078; +-} +- +-static void pxa270c5_initfn(Object *obj) +-{ +- ARMCPU *cpu = ARM_CPU(obj); +- +- cpu->dtb_compatible = "marvell,xscale"; +- set_feature(&cpu->env, ARM_FEATURE_V5); +- set_feature(&cpu->env, ARM_FEATURE_XSCALE); +- set_feature(&cpu->env, ARM_FEATURE_IWMMXT); +- cpu->midr = 0x69054117; +- cpu->ctr = 0xd172172; +- cpu->reset_sctlr = 0x00000078; +-} +- + #ifndef TARGET_AARCH64 + /* -cpu max: if KVM is enabled, like -cpu host (best possible with this host); + * otherwise, a CPU with as many features enabled as our emulation supports. +@@ -2688,50 +2094,10 @@ static void arm_max_initfn(Object *obj) + + static const ARMCPUInfo arm_cpus[] = { + #if !defined(CONFIG_USER_ONLY) || !defined(TARGET_AARCH64) +- { .name = "arm926", .initfn = arm926_initfn }, +- { .name = "arm946", .initfn = arm946_initfn }, +- { .name = "arm1026", .initfn = arm1026_initfn }, +- /* +- * What QEMU calls "arm1136-r2" is actually the 1136 r0p2, i.e. an +- * older core than plain "arm1136". In particular this does not +- * have the v6K features. +- */ +- { .name = "arm1136-r2", .initfn = arm1136_r2_initfn }, +- { .name = "arm1136", .initfn = arm1136_initfn }, +- { .name = "arm1176", .initfn = arm1176_initfn }, +- { .name = "arm11mpcore", .initfn = arm11mpcore_initfn }, +- { .name = "cortex-m0", .initfn = cortex_m0_initfn, +- .class_init = arm_v7m_class_init }, +- { .name = "cortex-m3", .initfn = cortex_m3_initfn, +- .class_init = arm_v7m_class_init }, +- { .name = "cortex-m4", .initfn = cortex_m4_initfn, +- .class_init = arm_v7m_class_init }, +- { .name = "cortex-m7", .initfn = cortex_m7_initfn, +- .class_init = arm_v7m_class_init }, +- { .name = "cortex-m33", .initfn = cortex_m33_initfn, +- .class_init = arm_v7m_class_init }, +- { .name = "cortex-r5", .initfn = cortex_r5_initfn }, +- { .name = "cortex-r5f", .initfn = cortex_r5f_initfn }, + { .name = "cortex-a7", .initfn = cortex_a7_initfn }, + { .name = "cortex-a8", .initfn = cortex_a8_initfn }, + { .name = "cortex-a9", .initfn = cortex_a9_initfn }, + { .name = "cortex-a15", .initfn = cortex_a15_initfn }, +- { .name = "ti925t", .initfn = ti925t_initfn }, +- { .name = "sa1100", .initfn = sa1100_initfn }, +- { .name = "sa1110", .initfn = sa1110_initfn }, +- { .name = "pxa250", .initfn = pxa250_initfn }, +- { .name = "pxa255", .initfn = pxa255_initfn }, +- { .name = "pxa260", .initfn = pxa260_initfn }, +- { .name = "pxa261", .initfn = pxa261_initfn }, +- { .name = "pxa262", .initfn = pxa262_initfn }, +- /* "pxa270" is an alias for "pxa270-a0" */ +- { .name = "pxa270", .initfn = pxa270a0_initfn }, +- { .name = "pxa270-a0", .initfn = pxa270a0_initfn }, +- { .name = "pxa270-a1", .initfn = pxa270a1_initfn }, +- { .name = "pxa270-b0", .initfn = pxa270b0_initfn }, +- { .name = "pxa270-b1", .initfn = pxa270b1_initfn }, +- { .name = "pxa270-c0", .initfn = pxa270c0_initfn }, +- { .name = "pxa270-c5", .initfn = pxa270c5_initfn }, + #ifndef TARGET_AARCH64 + { .name = "max", .initfn = arm_max_initfn }, + #endif +diff --git a/target/arm/cpu_tcg.c b/target/arm/cpu_tcg.c +new file mode 100644 +index 0000000000..591baef535 +--- /dev/null ++++ b/target/arm/cpu_tcg.c +@@ -0,0 +1,664 @@ ++/* ++ * QEMU ARM TCG CPUs. ++ * ++ * Copyright (c) 2012 SUSE LINUX Products GmbH ++ * ++ * This code is licensed under the GNU GPL v2 or later. ++ * ++ * SPDX-License-Identifier: GPL-2.0-or-later ++ */ ++ ++#include "qemu/osdep.h" ++#include "cpu.h" ++#include "internals.h" ++ ++/* CPU models. These are not needed for the AArch64 linux-user build. */ ++#if !defined(CONFIG_USER_ONLY) || !defined(TARGET_AARCH64) ++ ++static bool arm_v7m_cpu_exec_interrupt(CPUState *cs, int interrupt_request) ++{ ++ CPUClass *cc = CPU_GET_CLASS(cs); ++ ARMCPU *cpu = ARM_CPU(cs); ++ CPUARMState *env = &cpu->env; ++ bool ret = false; ++ ++ /* ++ * ARMv7-M interrupt masking works differently than -A or -R. ++ * There is no FIQ/IRQ distinction. Instead of I and F bits ++ * masking FIQ and IRQ interrupts, an exception is taken only ++ * if it is higher priority than the current execution priority ++ * (which depends on state like BASEPRI, FAULTMASK and the ++ * currently active exception). ++ */ ++ if (interrupt_request & CPU_INTERRUPT_HARD ++ && (armv7m_nvic_can_take_pending_exception(env->nvic))) { ++ cs->exception_index = EXCP_IRQ; ++ cc->do_interrupt(cs); ++ ret = true; ++ } ++ return ret; ++} ++ ++static void arm926_initfn(Object *obj) ++{ ++ ARMCPU *cpu = ARM_CPU(obj); ++ ++ cpu->dtb_compatible = "arm,arm926"; ++ set_feature(&cpu->env, ARM_FEATURE_V5); ++ set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS); ++ set_feature(&cpu->env, ARM_FEATURE_CACHE_TEST_CLEAN); ++ cpu->midr = 0x41069265; ++ cpu->reset_fpsid = 0x41011090; ++ cpu->ctr = 0x1dd20d2; ++ cpu->reset_sctlr = 0x00090078; ++ ++ /* ++ * ARMv5 does not have the ID_ISAR registers, but we can still ++ * set the field to indicate Jazelle support within QEMU. ++ */ ++ cpu->isar.id_isar1 = FIELD_DP32(cpu->isar.id_isar1, ID_ISAR1, JAZELLE, 1); ++ /* ++ * Similarly, we need to set MVFR0 fields to enable vfp and short vector ++ * support even though ARMv5 doesn't have this register. ++ */ ++ cpu->isar.mvfr0 = FIELD_DP32(cpu->isar.mvfr0, MVFR0, FPSHVEC, 1); ++ cpu->isar.mvfr0 = FIELD_DP32(cpu->isar.mvfr0, MVFR0, FPSP, 1); ++ cpu->isar.mvfr0 = FIELD_DP32(cpu->isar.mvfr0, MVFR0, FPDP, 1); ++} ++ ++static void arm946_initfn(Object *obj) ++{ ++ ARMCPU *cpu = ARM_CPU(obj); ++ ++ cpu->dtb_compatible = "arm,arm946"; ++ set_feature(&cpu->env, ARM_FEATURE_V5); ++ set_feature(&cpu->env, ARM_FEATURE_PMSA); ++ set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS); ++ cpu->midr = 0x41059461; ++ cpu->ctr = 0x0f004006; ++ cpu->reset_sctlr = 0x00000078; ++} ++ ++static void arm1026_initfn(Object *obj) ++{ ++ ARMCPU *cpu = ARM_CPU(obj); ++ ++ cpu->dtb_compatible = "arm,arm1026"; ++ set_feature(&cpu->env, ARM_FEATURE_V5); ++ set_feature(&cpu->env, ARM_FEATURE_AUXCR); ++ set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS); ++ set_feature(&cpu->env, ARM_FEATURE_CACHE_TEST_CLEAN); ++ cpu->midr = 0x4106a262; ++ cpu->reset_fpsid = 0x410110a0; ++ cpu->ctr = 0x1dd20d2; ++ cpu->reset_sctlr = 0x00090078; ++ cpu->reset_auxcr = 1; ++ ++ /* ++ * ARMv5 does not have the ID_ISAR registers, but we can still ++ * set the field to indicate Jazelle support within QEMU. ++ */ ++ cpu->isar.id_isar1 = FIELD_DP32(cpu->isar.id_isar1, ID_ISAR1, JAZELLE, 1); ++ /* ++ * Similarly, we need to set MVFR0 fields to enable vfp and short vector ++ * support even though ARMv5 doesn't have this register. ++ */ ++ cpu->isar.mvfr0 = FIELD_DP32(cpu->isar.mvfr0, MVFR0, FPSHVEC, 1); ++ cpu->isar.mvfr0 = FIELD_DP32(cpu->isar.mvfr0, MVFR0, FPSP, 1); ++ cpu->isar.mvfr0 = FIELD_DP32(cpu->isar.mvfr0, MVFR0, FPDP, 1); ++ ++ { ++ /* The 1026 had an IFAR at c6,c0,0,1 rather than the ARMv6 c6,c0,0,2 */ ++ ARMCPRegInfo ifar = { ++ .name = "IFAR", .cp = 15, .crn = 6, .crm = 0, .opc1 = 0, .opc2 = 1, ++ .access = PL1_RW, ++ .fieldoffset = offsetof(CPUARMState, cp15.ifar_ns), ++ .resetvalue = 0 ++ }; ++ define_one_arm_cp_reg(cpu, &ifar); ++ } ++} ++ ++static void arm1136_r2_initfn(Object *obj) ++{ ++ ARMCPU *cpu = ARM_CPU(obj); ++ /* ++ * What qemu calls "arm1136_r2" is actually the 1136 r0p2, ie an ++ * older core than plain "arm1136". In particular this does not ++ * have the v6K features. ++ * These ID register values are correct for 1136 but may be wrong ++ * for 1136_r2 (in particular r0p2 does not actually implement most ++ * of the ID registers). ++ */ ++ ++ cpu->dtb_compatible = "arm,arm1136"; ++ set_feature(&cpu->env, ARM_FEATURE_V6); ++ set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS); ++ set_feature(&cpu->env, ARM_FEATURE_CACHE_DIRTY_REG); ++ set_feature(&cpu->env, ARM_FEATURE_CACHE_BLOCK_OPS); ++ cpu->midr = 0x4107b362; ++ cpu->reset_fpsid = 0x410120b4; ++ cpu->isar.mvfr0 = 0x11111111; ++ cpu->isar.mvfr1 = 0x00000000; ++ cpu->ctr = 0x1dd20d2; ++ cpu->reset_sctlr = 0x00050078; ++ cpu->id_pfr0 = 0x111; ++ cpu->id_pfr1 = 0x1; ++ cpu->isar.id_dfr0 = 0x2; ++ cpu->id_afr0 = 0x3; ++ cpu->isar.id_mmfr0 = 0x01130003; ++ cpu->isar.id_mmfr1 = 0x10030302; ++ cpu->isar.id_mmfr2 = 0x01222110; ++ cpu->isar.id_isar0 = 0x00140011; ++ cpu->isar.id_isar1 = 0x12002111; ++ cpu->isar.id_isar2 = 0x11231111; ++ cpu->isar.id_isar3 = 0x01102131; ++ cpu->isar.id_isar4 = 0x141; ++ cpu->reset_auxcr = 7; ++} ++ ++static void arm1136_initfn(Object *obj) ++{ ++ ARMCPU *cpu = ARM_CPU(obj); ++ ++ cpu->dtb_compatible = "arm,arm1136"; ++ set_feature(&cpu->env, ARM_FEATURE_V6K); ++ set_feature(&cpu->env, ARM_FEATURE_V6); ++ set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS); ++ set_feature(&cpu->env, ARM_FEATURE_CACHE_DIRTY_REG); ++ set_feature(&cpu->env, ARM_FEATURE_CACHE_BLOCK_OPS); ++ cpu->midr = 0x4117b363; ++ cpu->reset_fpsid = 0x410120b4; ++ cpu->isar.mvfr0 = 0x11111111; ++ cpu->isar.mvfr1 = 0x00000000; ++ cpu->ctr = 0x1dd20d2; ++ cpu->reset_sctlr = 0x00050078; ++ cpu->id_pfr0 = 0x111; ++ cpu->id_pfr1 = 0x1; ++ cpu->isar.id_dfr0 = 0x2; ++ cpu->id_afr0 = 0x3; ++ cpu->isar.id_mmfr0 = 0x01130003; ++ cpu->isar.id_mmfr1 = 0x10030302; ++ cpu->isar.id_mmfr2 = 0x01222110; ++ cpu->isar.id_isar0 = 0x00140011; ++ cpu->isar.id_isar1 = 0x12002111; ++ cpu->isar.id_isar2 = 0x11231111; ++ cpu->isar.id_isar3 = 0x01102131; ++ cpu->isar.id_isar4 = 0x141; ++ cpu->reset_auxcr = 7; ++} ++ ++static void arm1176_initfn(Object *obj) ++{ ++ ARMCPU *cpu = ARM_CPU(obj); ++ ++ cpu->dtb_compatible = "arm,arm1176"; ++ set_feature(&cpu->env, ARM_FEATURE_V6K); ++ set_feature(&cpu->env, ARM_FEATURE_VAPA); ++ set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS); ++ set_feature(&cpu->env, ARM_FEATURE_CACHE_DIRTY_REG); ++ set_feature(&cpu->env, ARM_FEATURE_CACHE_BLOCK_OPS); ++ set_feature(&cpu->env, ARM_FEATURE_EL3); ++ cpu->midr = 0x410fb767; ++ cpu->reset_fpsid = 0x410120b5; ++ cpu->isar.mvfr0 = 0x11111111; ++ cpu->isar.mvfr1 = 0x00000000; ++ cpu->ctr = 0x1dd20d2; ++ cpu->reset_sctlr = 0x00050078; ++ cpu->id_pfr0 = 0x111; ++ cpu->id_pfr1 = 0x11; ++ cpu->isar.id_dfr0 = 0x33; ++ cpu->id_afr0 = 0; ++ cpu->isar.id_mmfr0 = 0x01130003; ++ cpu->isar.id_mmfr1 = 0x10030302; ++ cpu->isar.id_mmfr2 = 0x01222100; ++ cpu->isar.id_isar0 = 0x0140011; ++ cpu->isar.id_isar1 = 0x12002111; ++ cpu->isar.id_isar2 = 0x11231121; ++ cpu->isar.id_isar3 = 0x01102131; ++ cpu->isar.id_isar4 = 0x01141; ++ cpu->reset_auxcr = 7; ++} ++ ++static void arm11mpcore_initfn(Object *obj) ++{ ++ ARMCPU *cpu = ARM_CPU(obj); ++ ++ cpu->dtb_compatible = "arm,arm11mpcore"; ++ set_feature(&cpu->env, ARM_FEATURE_V6K); ++ set_feature(&cpu->env, ARM_FEATURE_VAPA); ++ set_feature(&cpu->env, ARM_FEATURE_MPIDR); ++ set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS); ++ cpu->midr = 0x410fb022; ++ cpu->reset_fpsid = 0x410120b4; ++ cpu->isar.mvfr0 = 0x11111111; ++ cpu->isar.mvfr1 = 0x00000000; ++ cpu->ctr = 0x1d192992; /* 32K icache 32K dcache */ ++ cpu->id_pfr0 = 0x111; ++ cpu->id_pfr1 = 0x1; ++ cpu->isar.id_dfr0 = 0; ++ cpu->id_afr0 = 0x2; ++ cpu->isar.id_mmfr0 = 0x01100103; ++ cpu->isar.id_mmfr1 = 0x10020302; ++ cpu->isar.id_mmfr2 = 0x01222000; ++ cpu->isar.id_isar0 = 0x00100011; ++ cpu->isar.id_isar1 = 0x12002111; ++ cpu->isar.id_isar2 = 0x11221011; ++ cpu->isar.id_isar3 = 0x01102131; ++ cpu->isar.id_isar4 = 0x141; ++ cpu->reset_auxcr = 1; ++} ++ ++static void cortex_m0_initfn(Object *obj) ++{ ++ ARMCPU *cpu = ARM_CPU(obj); ++ set_feature(&cpu->env, ARM_FEATURE_V6); ++ set_feature(&cpu->env, ARM_FEATURE_M); ++ ++ cpu->midr = 0x410cc200; ++} ++ ++static void cortex_m3_initfn(Object *obj) ++{ ++ ARMCPU *cpu = ARM_CPU(obj); ++ set_feature(&cpu->env, ARM_FEATURE_V7); ++ set_feature(&cpu->env, ARM_FEATURE_M); ++ set_feature(&cpu->env, ARM_FEATURE_M_MAIN); ++ cpu->midr = 0x410fc231; ++ cpu->pmsav7_dregion = 8; ++ cpu->id_pfr0 = 0x00000030; ++ cpu->id_pfr1 = 0x00000200; ++ cpu->isar.id_dfr0 = 0x00100000; ++ cpu->id_afr0 = 0x00000000; ++ cpu->isar.id_mmfr0 = 0x00000030; ++ cpu->isar.id_mmfr1 = 0x00000000; ++ cpu->isar.id_mmfr2 = 0x00000000; ++ cpu->isar.id_mmfr3 = 0x00000000; ++ cpu->isar.id_isar0 = 0x01141110; ++ cpu->isar.id_isar1 = 0x02111000; ++ cpu->isar.id_isar2 = 0x21112231; ++ cpu->isar.id_isar3 = 0x01111110; ++ cpu->isar.id_isar4 = 0x01310102; ++ cpu->isar.id_isar5 = 0x00000000; ++ cpu->isar.id_isar6 = 0x00000000; ++} ++ ++static void cortex_m4_initfn(Object *obj) ++{ ++ ARMCPU *cpu = ARM_CPU(obj); ++ ++ set_feature(&cpu->env, ARM_FEATURE_V7); ++ set_feature(&cpu->env, ARM_FEATURE_M); ++ set_feature(&cpu->env, ARM_FEATURE_M_MAIN); ++ set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP); ++ cpu->midr = 0x410fc240; /* r0p0 */ ++ cpu->pmsav7_dregion = 8; ++ cpu->isar.mvfr0 = 0x10110021; ++ cpu->isar.mvfr1 = 0x11000011; ++ cpu->isar.mvfr2 = 0x00000000; ++ cpu->id_pfr0 = 0x00000030; ++ cpu->id_pfr1 = 0x00000200; ++ cpu->isar.id_dfr0 = 0x00100000; ++ cpu->id_afr0 = 0x00000000; ++ cpu->isar.id_mmfr0 = 0x00000030; ++ cpu->isar.id_mmfr1 = 0x00000000; ++ cpu->isar.id_mmfr2 = 0x00000000; ++ cpu->isar.id_mmfr3 = 0x00000000; ++ cpu->isar.id_isar0 = 0x01141110; ++ cpu->isar.id_isar1 = 0x02111000; ++ cpu->isar.id_isar2 = 0x21112231; ++ cpu->isar.id_isar3 = 0x01111110; ++ cpu->isar.id_isar4 = 0x01310102; ++ cpu->isar.id_isar5 = 0x00000000; ++ cpu->isar.id_isar6 = 0x00000000; ++} ++ ++static void cortex_m7_initfn(Object *obj) ++{ ++ ARMCPU *cpu = ARM_CPU(obj); ++ ++ set_feature(&cpu->env, ARM_FEATURE_V7); ++ set_feature(&cpu->env, ARM_FEATURE_M); ++ set_feature(&cpu->env, ARM_FEATURE_M_MAIN); ++ set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP); ++ cpu->midr = 0x411fc272; /* r1p2 */ ++ cpu->pmsav7_dregion = 8; ++ cpu->isar.mvfr0 = 0x10110221; ++ cpu->isar.mvfr1 = 0x12000011; ++ cpu->isar.mvfr2 = 0x00000040; ++ cpu->id_pfr0 = 0x00000030; ++ cpu->id_pfr1 = 0x00000200; ++ cpu->isar.id_dfr0 = 0x00100000; ++ cpu->id_afr0 = 0x00000000; ++ cpu->isar.id_mmfr0 = 0x00100030; ++ cpu->isar.id_mmfr1 = 0x00000000; ++ cpu->isar.id_mmfr2 = 0x01000000; ++ cpu->isar.id_mmfr3 = 0x00000000; ++ cpu->isar.id_isar0 = 0x01101110; ++ cpu->isar.id_isar1 = 0x02112000; ++ cpu->isar.id_isar2 = 0x20232231; ++ cpu->isar.id_isar3 = 0x01111131; ++ cpu->isar.id_isar4 = 0x01310132; ++ cpu->isar.id_isar5 = 0x00000000; ++ cpu->isar.id_isar6 = 0x00000000; ++} ++ ++static void cortex_m33_initfn(Object *obj) ++{ ++ ARMCPU *cpu = ARM_CPU(obj); ++ ++ set_feature(&cpu->env, ARM_FEATURE_V8); ++ set_feature(&cpu->env, ARM_FEATURE_M); ++ set_feature(&cpu->env, ARM_FEATURE_M_MAIN); ++ set_feature(&cpu->env, ARM_FEATURE_M_SECURITY); ++ set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP); ++ cpu->midr = 0x410fd213; /* r0p3 */ ++ cpu->pmsav7_dregion = 16; ++ cpu->sau_sregion = 8; ++ cpu->isar.mvfr0 = 0x10110021; ++ cpu->isar.mvfr1 = 0x11000011; ++ cpu->isar.mvfr2 = 0x00000040; ++ cpu->id_pfr0 = 0x00000030; ++ cpu->id_pfr1 = 0x00000210; ++ cpu->isar.id_dfr0 = 0x00200000; ++ cpu->id_afr0 = 0x00000000; ++ cpu->isar.id_mmfr0 = 0x00101F40; ++ cpu->isar.id_mmfr1 = 0x00000000; ++ cpu->isar.id_mmfr2 = 0x01000000; ++ cpu->isar.id_mmfr3 = 0x00000000; ++ cpu->isar.id_isar0 = 0x01101110; ++ cpu->isar.id_isar1 = 0x02212000; ++ cpu->isar.id_isar2 = 0x20232232; ++ cpu->isar.id_isar3 = 0x01111131; ++ cpu->isar.id_isar4 = 0x01310132; ++ cpu->isar.id_isar5 = 0x00000000; ++ cpu->isar.id_isar6 = 0x00000000; ++ cpu->clidr = 0x00000000; ++ cpu->ctr = 0x8000c000; ++} ++ ++static const ARMCPRegInfo cortexr5_cp_reginfo[] = { ++ /* Dummy the TCM region regs for the moment */ ++ { .name = "ATCM", .cp = 15, .opc1 = 0, .crn = 9, .crm = 1, .opc2 = 0, ++ .access = PL1_RW, .type = ARM_CP_CONST }, ++ { .name = "BTCM", .cp = 15, .opc1 = 0, .crn = 9, .crm = 1, .opc2 = 1, ++ .access = PL1_RW, .type = ARM_CP_CONST }, ++ { .name = "DCACHE_INVAL", .cp = 15, .opc1 = 0, .crn = 15, .crm = 5, ++ .opc2 = 0, .access = PL1_W, .type = ARM_CP_NOP }, ++ REGINFO_SENTINEL ++}; ++ ++static void cortex_r5_initfn(Object *obj) ++{ ++ ARMCPU *cpu = ARM_CPU(obj); ++ ++ set_feature(&cpu->env, ARM_FEATURE_V7); ++ set_feature(&cpu->env, ARM_FEATURE_V7MP); ++ set_feature(&cpu->env, ARM_FEATURE_PMSA); ++ set_feature(&cpu->env, ARM_FEATURE_PMU); ++ cpu->midr = 0x411fc153; /* r1p3 */ ++ cpu->id_pfr0 = 0x0131; ++ cpu->id_pfr1 = 0x001; ++ cpu->isar.id_dfr0 = 0x010400; ++ cpu->id_afr0 = 0x0; ++ cpu->isar.id_mmfr0 = 0x0210030; ++ cpu->isar.id_mmfr1 = 0x00000000; ++ cpu->isar.id_mmfr2 = 0x01200000; ++ cpu->isar.id_mmfr3 = 0x0211; ++ cpu->isar.id_isar0 = 0x02101111; ++ cpu->isar.id_isar1 = 0x13112111; ++ cpu->isar.id_isar2 = 0x21232141; ++ cpu->isar.id_isar3 = 0x01112131; ++ cpu->isar.id_isar4 = 0x0010142; ++ cpu->isar.id_isar5 = 0x0; ++ cpu->isar.id_isar6 = 0x0; ++ cpu->mp_is_up = true; ++ cpu->pmsav7_dregion = 16; ++ define_arm_cp_regs(cpu, cortexr5_cp_reginfo); ++} ++ ++static void cortex_r5f_initfn(Object *obj) ++{ ++ ARMCPU *cpu = ARM_CPU(obj); ++ ++ cortex_r5_initfn(obj); ++ cpu->isar.mvfr0 = 0x10110221; ++ cpu->isar.mvfr1 = 0x00000011; ++} ++ ++static void ti925t_initfn(Object *obj) ++{ ++ ARMCPU *cpu = ARM_CPU(obj); ++ set_feature(&cpu->env, ARM_FEATURE_V4T); ++ set_feature(&cpu->env, ARM_FEATURE_OMAPCP); ++ cpu->midr = ARM_CPUID_TI925T; ++ cpu->ctr = 0x5109149; ++ cpu->reset_sctlr = 0x00000070; ++} ++ ++static void sa1100_initfn(Object *obj) ++{ ++ ARMCPU *cpu = ARM_CPU(obj); ++ ++ cpu->dtb_compatible = "intel,sa1100"; ++ set_feature(&cpu->env, ARM_FEATURE_STRONGARM); ++ set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS); ++ cpu->midr = 0x4401A11B; ++ cpu->reset_sctlr = 0x00000070; ++} ++ ++static void sa1110_initfn(Object *obj) ++{ ++ ARMCPU *cpu = ARM_CPU(obj); ++ set_feature(&cpu->env, ARM_FEATURE_STRONGARM); ++ set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS); ++ cpu->midr = 0x6901B119; ++ cpu->reset_sctlr = 0x00000070; ++} ++ ++static void pxa250_initfn(Object *obj) ++{ ++ ARMCPU *cpu = ARM_CPU(obj); ++ ++ cpu->dtb_compatible = "marvell,xscale"; ++ set_feature(&cpu->env, ARM_FEATURE_V5); ++ set_feature(&cpu->env, ARM_FEATURE_XSCALE); ++ cpu->midr = 0x69052100; ++ cpu->ctr = 0xd172172; ++ cpu->reset_sctlr = 0x00000078; ++} ++ ++static void pxa255_initfn(Object *obj) ++{ ++ ARMCPU *cpu = ARM_CPU(obj); ++ ++ cpu->dtb_compatible = "marvell,xscale"; ++ set_feature(&cpu->env, ARM_FEATURE_V5); ++ set_feature(&cpu->env, ARM_FEATURE_XSCALE); ++ cpu->midr = 0x69052d00; ++ cpu->ctr = 0xd172172; ++ cpu->reset_sctlr = 0x00000078; ++} ++ ++static void pxa260_initfn(Object *obj) ++{ ++ ARMCPU *cpu = ARM_CPU(obj); ++ ++ cpu->dtb_compatible = "marvell,xscale"; ++ set_feature(&cpu->env, ARM_FEATURE_V5); ++ set_feature(&cpu->env, ARM_FEATURE_XSCALE); ++ cpu->midr = 0x69052903; ++ cpu->ctr = 0xd172172; ++ cpu->reset_sctlr = 0x00000078; ++} ++ ++static void pxa261_initfn(Object *obj) ++{ ++ ARMCPU *cpu = ARM_CPU(obj); ++ ++ cpu->dtb_compatible = "marvell,xscale"; ++ set_feature(&cpu->env, ARM_FEATURE_V5); ++ set_feature(&cpu->env, ARM_FEATURE_XSCALE); ++ cpu->midr = 0x69052d05; ++ cpu->ctr = 0xd172172; ++ cpu->reset_sctlr = 0x00000078; ++} ++ ++static void pxa262_initfn(Object *obj) ++{ ++ ARMCPU *cpu = ARM_CPU(obj); ++ ++ cpu->dtb_compatible = "marvell,xscale"; ++ set_feature(&cpu->env, ARM_FEATURE_V5); ++ set_feature(&cpu->env, ARM_FEATURE_XSCALE); ++ cpu->midr = 0x69052d06; ++ cpu->ctr = 0xd172172; ++ cpu->reset_sctlr = 0x00000078; ++} ++ ++static void pxa270a0_initfn(Object *obj) ++{ ++ ARMCPU *cpu = ARM_CPU(obj); ++ ++ cpu->dtb_compatible = "marvell,xscale"; ++ set_feature(&cpu->env, ARM_FEATURE_V5); ++ set_feature(&cpu->env, ARM_FEATURE_XSCALE); ++ set_feature(&cpu->env, ARM_FEATURE_IWMMXT); ++ cpu->midr = 0x69054110; ++ cpu->ctr = 0xd172172; ++ cpu->reset_sctlr = 0x00000078; ++} ++ ++static void pxa270a1_initfn(Object *obj) ++{ ++ ARMCPU *cpu = ARM_CPU(obj); ++ ++ cpu->dtb_compatible = "marvell,xscale"; ++ set_feature(&cpu->env, ARM_FEATURE_V5); ++ set_feature(&cpu->env, ARM_FEATURE_XSCALE); ++ set_feature(&cpu->env, ARM_FEATURE_IWMMXT); ++ cpu->midr = 0x69054111; ++ cpu->ctr = 0xd172172; ++ cpu->reset_sctlr = 0x00000078; ++} ++ ++static void pxa270b0_initfn(Object *obj) ++{ ++ ARMCPU *cpu = ARM_CPU(obj); ++ ++ cpu->dtb_compatible = "marvell,xscale"; ++ set_feature(&cpu->env, ARM_FEATURE_V5); ++ set_feature(&cpu->env, ARM_FEATURE_XSCALE); ++ set_feature(&cpu->env, ARM_FEATURE_IWMMXT); ++ cpu->midr = 0x69054112; ++ cpu->ctr = 0xd172172; ++ cpu->reset_sctlr = 0x00000078; ++} ++ ++static void pxa270b1_initfn(Object *obj) ++{ ++ ARMCPU *cpu = ARM_CPU(obj); ++ ++ cpu->dtb_compatible = "marvell,xscale"; ++ set_feature(&cpu->env, ARM_FEATURE_V5); ++ set_feature(&cpu->env, ARM_FEATURE_XSCALE); ++ set_feature(&cpu->env, ARM_FEATURE_IWMMXT); ++ cpu->midr = 0x69054113; ++ cpu->ctr = 0xd172172; ++ cpu->reset_sctlr = 0x00000078; ++} ++ ++static void pxa270c0_initfn(Object *obj) ++{ ++ ARMCPU *cpu = ARM_CPU(obj); ++ ++ cpu->dtb_compatible = "marvell,xscale"; ++ set_feature(&cpu->env, ARM_FEATURE_V5); ++ set_feature(&cpu->env, ARM_FEATURE_XSCALE); ++ set_feature(&cpu->env, ARM_FEATURE_IWMMXT); ++ cpu->midr = 0x69054114; ++ cpu->ctr = 0xd172172; ++ cpu->reset_sctlr = 0x00000078; ++} ++ ++static void pxa270c5_initfn(Object *obj) ++{ ++ ARMCPU *cpu = ARM_CPU(obj); ++ ++ cpu->dtb_compatible = "marvell,xscale"; ++ set_feature(&cpu->env, ARM_FEATURE_V5); ++ set_feature(&cpu->env, ARM_FEATURE_XSCALE); ++ set_feature(&cpu->env, ARM_FEATURE_IWMMXT); ++ cpu->midr = 0x69054117; ++ cpu->ctr = 0xd172172; ++ cpu->reset_sctlr = 0x00000078; ++} ++ ++static void arm_v7m_class_init(ObjectClass *oc, void *data) ++{ ++ ARMCPUClass *acc = ARM_CPU_CLASS(oc); ++ CPUClass *cc = CPU_CLASS(oc); ++ ++ acc->info = data; ++#ifndef CONFIG_USER_ONLY ++ cc->do_interrupt = arm_v7m_cpu_do_interrupt; ++#endif ++ ++ cc->cpu_exec_interrupt = arm_v7m_cpu_exec_interrupt; ++} ++ ++static const ARMCPUInfo arm_tcg_cpus[] = { ++ { .name = "arm926", .initfn = arm926_initfn }, ++ { .name = "arm946", .initfn = arm946_initfn }, ++ { .name = "arm1026", .initfn = arm1026_initfn }, ++ /* ++ * What QEMU calls "arm1136-r2" is actually the 1136 r0p2, i.e. an ++ * older core than plain "arm1136". In particular this does not ++ * have the v6K features. ++ */ ++ { .name = "arm1136-r2", .initfn = arm1136_r2_initfn }, ++ { .name = "arm1136", .initfn = arm1136_initfn }, ++ { .name = "arm1176", .initfn = arm1176_initfn }, ++ { .name = "arm11mpcore", .initfn = arm11mpcore_initfn }, ++ { .name = "cortex-m0", .initfn = cortex_m0_initfn, ++ .class_init = arm_v7m_class_init }, ++ { .name = "cortex-m3", .initfn = cortex_m3_initfn, ++ .class_init = arm_v7m_class_init }, ++ { .name = "cortex-m4", .initfn = cortex_m4_initfn, ++ .class_init = arm_v7m_class_init }, ++ { .name = "cortex-m7", .initfn = cortex_m7_initfn, ++ .class_init = arm_v7m_class_init }, ++ { .name = "cortex-m33", .initfn = cortex_m33_initfn, ++ .class_init = arm_v7m_class_init }, ++ { .name = "cortex-r5", .initfn = cortex_r5_initfn }, ++ { .name = "cortex-r5f", .initfn = cortex_r5f_initfn }, ++ { .name = "ti925t", .initfn = ti925t_initfn }, ++ { .name = "sa1100", .initfn = sa1100_initfn }, ++ { .name = "sa1110", .initfn = sa1110_initfn }, ++ { .name = "pxa250", .initfn = pxa250_initfn }, ++ { .name = "pxa255", .initfn = pxa255_initfn }, ++ { .name = "pxa260", .initfn = pxa260_initfn }, ++ { .name = "pxa261", .initfn = pxa261_initfn }, ++ { .name = "pxa262", .initfn = pxa262_initfn }, ++ /* "pxa270" is an alias for "pxa270-a0" */ ++ { .name = "pxa270", .initfn = pxa270a0_initfn }, ++ { .name = "pxa270-a0", .initfn = pxa270a0_initfn }, ++ { .name = "pxa270-a1", .initfn = pxa270a1_initfn }, ++ { .name = "pxa270-b0", .initfn = pxa270b0_initfn }, ++ { .name = "pxa270-b1", .initfn = pxa270b1_initfn }, ++ { .name = "pxa270-c0", .initfn = pxa270c0_initfn }, ++ { .name = "pxa270-c5", .initfn = pxa270c5_initfn }, ++}; ++ ++static void arm_tcg_cpu_register_types(void) ++{ ++ size_t i; ++ ++ for (i = 0; i < ARRAY_SIZE(arm_tcg_cpus); ++i) { ++ arm_cpu_register(&arm_tcg_cpus[i]); ++ } ++} ++ ++type_init(arm_tcg_cpu_register_types) ++ ++#endif /* !CONFIG_USER_ONLY || !TARGET_AARCH64 */ +-- +2.23.0 + diff --git a/target-arm-Restrict-the-Address-Translate-write-oper.patch b/target-arm-Restrict-the-Address-Translate-write-oper.patch new file mode 100644 index 0000000000000000000000000000000000000000..b8ac2fd4ab6198042a4908c28b356ff5b73a053d --- /dev/null +++ b/target-arm-Restrict-the-Address-Translate-write-oper.patch @@ -0,0 +1,99 @@ +From 9fb005b02dbda7f47b789b7f19bf5f73622a4756 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Thu, 23 Apr 2020 09:33:54 +0200 +Subject: [PATCH 117/709] target/arm: Restrict the Address Translate write + operation to TCG accel +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Under KVM these registers are written by the hardware. +Restrict the writefn handlers to TCG to avoid when building +without TCG: + + LINK aarch64-softmmu/qemu-system-aarch64 + target/arm/helper.o: In function `do_ats_write': + target/arm/helper.c:3524: undefined reference to `raise_exception' + +Suggested-by: Richard Henderson +Reviewed-by: Richard Henderson +Signed-off-by: Philippe Mathieu-Daudé +Message-id: 20200423073358.27155-2-philmd@redhat.com +Signed-off-by: Peter Maydell +--- + target/arm/helper.c | 17 +++++++++++++++++ + 1 file changed, 17 insertions(+) + +diff --git a/target/arm/helper.c b/target/arm/helper.c +index 7e9ea5d20f..dfefb9b3d9 100644 +--- a/target/arm/helper.c ++++ b/target/arm/helper.c +@@ -3442,6 +3442,7 @@ static CPAccessResult ats_access(CPUARMState *env, const ARMCPRegInfo *ri, + return CP_ACCESS_OK; + } + ++#ifdef CONFIG_TCG + static uint64_t do_ats_write(CPUARMState *env, uint64_t value, + MMUAccessType access_type, ARMMMUIdx mmu_idx) + { +@@ -3602,9 +3603,11 @@ static uint64_t do_ats_write(CPUARMState *env, uint64_t value, + } + return par64; + } ++#endif /* CONFIG_TCG */ + + static void ats_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) + { ++#ifdef CONFIG_TCG + MMUAccessType access_type = ri->opc2 & 1 ? MMU_DATA_STORE : MMU_DATA_LOAD; + uint64_t par64; + ARMMMUIdx mmu_idx; +@@ -3664,17 +3667,26 @@ static void ats_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) + par64 = do_ats_write(env, value, access_type, mmu_idx); + + A32_BANKED_CURRENT_REG_SET(env, par, par64); ++#else ++ /* Handled by hardware accelerator. */ ++ g_assert_not_reached(); ++#endif /* CONFIG_TCG */ + } + + static void ats1h_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) + { ++#ifdef CONFIG_TCG + 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); + + A32_BANKED_CURRENT_REG_SET(env, par, par64); ++#else ++ /* Handled by hardware accelerator. */ ++ g_assert_not_reached(); ++#endif /* CONFIG_TCG */ + } + + static CPAccessResult at_s1e2_access(CPUARMState *env, const ARMCPRegInfo *ri, +@@ -3689,6 +3701,7 @@ static CPAccessResult at_s1e2_access(CPUARMState *env, const ARMCPRegInfo *ri, + static void ats_write64(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) + { ++#ifdef CONFIG_TCG + MMUAccessType access_type = ri->opc2 & 1 ? MMU_DATA_STORE : MMU_DATA_LOAD; + ARMMMUIdx mmu_idx; + int secure = arm_is_secure_below_el3(env); +@@ -3728,6 +3741,10 @@ static void ats_write64(CPUARMState *env, const ARMCPRegInfo *ri, + } + + env->cp15.par_el[1] = do_ats_write(env, value, access_type, mmu_idx); ++#else ++ /* Handled by hardware accelerator. */ ++ g_assert_not_reached(); ++#endif /* CONFIG_TCG */ + } + #endif + +-- +2.23.0 + diff --git a/target-arm-Reuse-sve_probe_page-for-gather-first-fau.patch b/target-arm-Reuse-sve_probe_page-for-gather-first-fau.patch new file mode 100644 index 0000000000000000000000000000000000000000..196f0be925da87853999cc030f57cf72496c5d03 --- /dev/null +++ b/target-arm-Reuse-sve_probe_page-for-gather-first-fau.patch @@ -0,0 +1,394 @@ +From 50de9b78cec06e6d16e92a114a505779359ca532 Mon Sep 17 00:00:00 2001 +From: Richard Henderson +Date: Fri, 8 May 2020 08:43:56 -0700 +Subject: [PATCH 380/709] target/arm: Reuse sve_probe_page for gather + first-fault loads + +This avoids the need for a separate set of helpers to implement +no-fault semantics, and will enable MTE in the future. + +Reviewed-by: Peter Maydell +Signed-off-by: Richard Henderson +Message-id: 20200508154359.7494-17-richard.henderson@linaro.org +Signed-off-by: Peter Maydell +--- + target/arm/sve_helper.c | 345 ++++++++++++++++------------------------ + 1 file changed, 138 insertions(+), 207 deletions(-) + +diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c +index 4ed9bbe1ee..1560129b08 100644 +--- a/target/arm/sve_helper.c ++++ b/target/arm/sve_helper.c +@@ -5254,231 +5254,162 @@ DO_LD1_ZPZ_D(dd_be, zd) + + /* First fault loads with a vector index. */ + +-/* Load one element into VD+REG_OFF from (ENV,VADDR) without faulting. +- * The controlling predicate is known to be true. Return true if the +- * load was successful. +- */ +-typedef bool sve_ld1_nf_fn(CPUARMState *env, void *vd, intptr_t reg_off, +- target_ulong vaddr, int mmu_idx); +- +-#ifdef CONFIG_SOFTMMU +-#define DO_LD_NF(NAME, H, TYPEE, TYPEM, HOST) \ +-static bool sve_ld##NAME##_nf(CPUARMState *env, void *vd, intptr_t reg_off, \ +- target_ulong addr, int mmu_idx) \ +-{ \ +- target_ulong next_page = -(addr | TARGET_PAGE_MASK); \ +- if (likely(next_page - addr >= sizeof(TYPEM))) { \ +- void *host = tlb_vaddr_to_host(env, addr, MMU_DATA_LOAD, mmu_idx); \ +- if (likely(host)) { \ +- TYPEM val = HOST(host); \ +- *(TYPEE *)(vd + H(reg_off)) = val; \ +- return true; \ +- } \ +- } \ +- return false; \ +-} +-#else +-#define DO_LD_NF(NAME, H, TYPEE, TYPEM, HOST) \ +-static bool sve_ld##NAME##_nf(CPUARMState *env, void *vd, intptr_t reg_off, \ +- target_ulong addr, int mmu_idx) \ +-{ \ +- if (likely(page_check_range(addr, sizeof(TYPEM), PAGE_READ))) { \ +- TYPEM val = HOST(g2h(addr)); \ +- *(TYPEE *)(vd + H(reg_off)) = val; \ +- return true; \ +- } \ +- return false; \ +-} +-#endif +- +-DO_LD_NF(bsu, H1_4, uint32_t, uint8_t, ldub_p) +-DO_LD_NF(bss, H1_4, uint32_t, int8_t, ldsb_p) +-DO_LD_NF(bdu, , uint64_t, uint8_t, ldub_p) +-DO_LD_NF(bds, , uint64_t, int8_t, ldsb_p) +- +-DO_LD_NF(hsu_le, H1_4, uint32_t, uint16_t, lduw_le_p) +-DO_LD_NF(hss_le, H1_4, uint32_t, int16_t, ldsw_le_p) +-DO_LD_NF(hsu_be, H1_4, uint32_t, uint16_t, lduw_be_p) +-DO_LD_NF(hss_be, H1_4, uint32_t, int16_t, ldsw_be_p) +-DO_LD_NF(hdu_le, , uint64_t, uint16_t, lduw_le_p) +-DO_LD_NF(hds_le, , uint64_t, int16_t, ldsw_le_p) +-DO_LD_NF(hdu_be, , uint64_t, uint16_t, lduw_be_p) +-DO_LD_NF(hds_be, , uint64_t, int16_t, ldsw_be_p) +- +-DO_LD_NF(ss_le, H1_4, uint32_t, uint32_t, ldl_le_p) +-DO_LD_NF(ss_be, H1_4, uint32_t, uint32_t, ldl_be_p) +-DO_LD_NF(sdu_le, , uint64_t, uint32_t, ldl_le_p) +-DO_LD_NF(sds_le, , uint64_t, int32_t, ldl_le_p) +-DO_LD_NF(sdu_be, , uint64_t, uint32_t, ldl_be_p) +-DO_LD_NF(sds_be, , uint64_t, int32_t, ldl_be_p) +- +-DO_LD_NF(dd_le, , uint64_t, uint64_t, ldq_le_p) +-DO_LD_NF(dd_be, , uint64_t, uint64_t, ldq_be_p) +- + /* +- * Common helper for all gather first-faulting loads. ++ * Common helpers for all gather first-faulting loads. + */ +-static inline void sve_ldff1_zs(CPUARMState *env, void *vd, void *vg, void *vm, +- target_ulong base, uint32_t desc, uintptr_t ra, +- zreg_off_fn *off_fn, sve_ldst1_tlb_fn *tlb_fn, +- sve_ld1_nf_fn *nonfault_fn) ++ ++static inline QEMU_ALWAYS_INLINE ++void sve_ldff1_z(CPUARMState *env, void *vd, uint64_t *vg, void *vm, ++ target_ulong base, uint32_t desc, uintptr_t retaddr, ++ const int esz, const int msz, zreg_off_fn *off_fn, ++ sve_ldst1_host_fn *host_fn, ++ sve_ldst1_tlb_fn *tlb_fn) + { +- const TCGMemOpIdx oi = extract32(desc, SIMD_DATA_SHIFT, MEMOPIDX_SHIFT); +- const int mmu_idx = get_mmuidx(oi); ++ const int mmu_idx = cpu_mmu_index(env, false); + const int scale = extract32(desc, SIMD_DATA_SHIFT + MEMOPIDX_SHIFT, 2); +- intptr_t reg_off, reg_max = simd_oprsz(desc); +- target_ulong addr; ++ const int esize = 1 << esz; ++ const int msize = 1 << msz; ++ const intptr_t reg_max = simd_oprsz(desc); ++ intptr_t reg_off; ++ SVEHostPage info; ++ target_ulong addr, in_page; + + /* Skip to the first true predicate. */ +- reg_off = find_next_active(vg, 0, reg_max, MO_32); +- if (likely(reg_off < reg_max)) { +- /* Perform one normal read, which will fault or not. */ +- addr = off_fn(vm, reg_off); +- addr = base + (addr << scale); +- tlb_fn(env, vd, reg_off, addr, ra); +- +- /* The rest of the reads will be non-faulting. */ ++ reg_off = find_next_active(vg, 0, reg_max, esz); ++ if (unlikely(reg_off >= reg_max)) { ++ /* The entire predicate was false; no load occurs. */ ++ memset(vd, 0, reg_max); ++ return; + } + +- /* After any fault, zero the leading predicated false elements. */ +- swap_memzero(vd, reg_off); +- +- while (likely((reg_off += 4) < reg_max)) { +- uint64_t pg = *(uint64_t *)(vg + (reg_off >> 6) * 8); +- if (likely((pg >> (reg_off & 63)) & 1)) { +- addr = off_fn(vm, reg_off); +- addr = base + (addr << scale); +- if (!nonfault_fn(env, vd, reg_off, addr, mmu_idx)) { +- record_fault(env, reg_off, reg_max); +- break; +- } +- } else { +- *(uint32_t *)(vd + H1_4(reg_off)) = 0; +- } +- } +-} ++ /* ++ * Probe the first element, allowing faults. ++ */ ++ addr = base + (off_fn(vm, reg_off) << scale); ++ tlb_fn(env, vd, reg_off, addr, retaddr); + +-static inline void sve_ldff1_zd(CPUARMState *env, void *vd, void *vg, void *vm, +- target_ulong base, uint32_t desc, uintptr_t ra, +- zreg_off_fn *off_fn, sve_ldst1_tlb_fn *tlb_fn, +- sve_ld1_nf_fn *nonfault_fn) +-{ +- const TCGMemOpIdx oi = extract32(desc, SIMD_DATA_SHIFT, MEMOPIDX_SHIFT); +- const int mmu_idx = get_mmuidx(oi); +- const int scale = extract32(desc, SIMD_DATA_SHIFT + MEMOPIDX_SHIFT, 2); +- intptr_t reg_off, reg_max = simd_oprsz(desc); +- target_ulong addr; ++ /* After any fault, zero the other elements. */ ++ swap_memzero(vd, reg_off); ++ reg_off += esize; ++ swap_memzero(vd + reg_off, reg_max - reg_off); + +- /* Skip to the first true predicate. */ +- reg_off = find_next_active(vg, 0, reg_max, MO_64); +- if (likely(reg_off < reg_max)) { +- /* Perform one normal read, which will fault or not. */ +- addr = off_fn(vm, reg_off); +- addr = base + (addr << scale); +- tlb_fn(env, vd, reg_off, addr, ra); ++ /* ++ * Probe the remaining elements, not allowing faults. ++ */ ++ while (reg_off < reg_max) { ++ uint64_t pg = vg[reg_off >> 6]; ++ do { ++ if (likely((pg >> (reg_off & 63)) & 1)) { ++ addr = base + (off_fn(vm, reg_off) << scale); ++ in_page = -(addr | TARGET_PAGE_MASK); + +- /* The rest of the reads will be non-faulting. */ +- } ++ if (unlikely(in_page < msize)) { ++ /* Stop if the element crosses a page boundary. */ ++ goto fault; ++ } + +- /* After any fault, zero the leading predicated false elements. */ +- swap_memzero(vd, reg_off); ++ sve_probe_page(&info, true, env, addr, 0, MMU_DATA_LOAD, ++ mmu_idx, retaddr); ++ if (unlikely(info.flags & (TLB_INVALID_MASK | TLB_MMIO))) { ++ goto fault; ++ } ++ if (unlikely(info.flags & TLB_WATCHPOINT) && ++ (cpu_watchpoint_address_matches ++ (env_cpu(env), addr, msize) & BP_MEM_READ)) { ++ goto fault; ++ } ++ /* TODO: MTE check. */ + +- while (likely((reg_off += 8) < reg_max)) { +- uint8_t pg = *(uint8_t *)(vg + H1(reg_off >> 3)); +- if (likely(pg & 1)) { +- addr = off_fn(vm, reg_off); +- addr = base + (addr << scale); +- if (!nonfault_fn(env, vd, reg_off, addr, mmu_idx)) { +- record_fault(env, reg_off, reg_max); +- break; ++ host_fn(vd, reg_off, info.host); + } +- } else { +- *(uint64_t *)(vd + reg_off) = 0; +- } ++ reg_off += esize; ++ } while (reg_off & 63); + } +-} ++ return; + +-#define DO_LDFF1_ZPZ_S(MEM, OFS) \ +-void HELPER(sve_ldff##MEM##_##OFS) \ +- (CPUARMState *env, void *vd, void *vg, void *vm, \ +- target_ulong base, uint32_t desc) \ +-{ \ +- sve_ldff1_zs(env, vd, vg, vm, base, desc, GETPC(), \ +- off_##OFS##_s, sve_ld1##MEM##_tlb, sve_ld##MEM##_nf); \ ++ fault: ++ record_fault(env, reg_off, reg_max); + } + +-#define DO_LDFF1_ZPZ_D(MEM, OFS) \ +-void HELPER(sve_ldff##MEM##_##OFS) \ +- (CPUARMState *env, void *vd, void *vg, void *vm, \ +- target_ulong base, uint32_t desc) \ +-{ \ +- sve_ldff1_zd(env, vd, vg, vm, base, desc, GETPC(), \ +- off_##OFS##_d, sve_ld1##MEM##_tlb, sve_ld##MEM##_nf); \ +-} +- +-DO_LDFF1_ZPZ_S(bsu, zsu) +-DO_LDFF1_ZPZ_S(bsu, zss) +-DO_LDFF1_ZPZ_D(bdu, zsu) +-DO_LDFF1_ZPZ_D(bdu, zss) +-DO_LDFF1_ZPZ_D(bdu, zd) +- +-DO_LDFF1_ZPZ_S(bss, zsu) +-DO_LDFF1_ZPZ_S(bss, zss) +-DO_LDFF1_ZPZ_D(bds, zsu) +-DO_LDFF1_ZPZ_D(bds, zss) +-DO_LDFF1_ZPZ_D(bds, zd) +- +-DO_LDFF1_ZPZ_S(hsu_le, zsu) +-DO_LDFF1_ZPZ_S(hsu_le, zss) +-DO_LDFF1_ZPZ_D(hdu_le, zsu) +-DO_LDFF1_ZPZ_D(hdu_le, zss) +-DO_LDFF1_ZPZ_D(hdu_le, zd) +- +-DO_LDFF1_ZPZ_S(hsu_be, zsu) +-DO_LDFF1_ZPZ_S(hsu_be, zss) +-DO_LDFF1_ZPZ_D(hdu_be, zsu) +-DO_LDFF1_ZPZ_D(hdu_be, zss) +-DO_LDFF1_ZPZ_D(hdu_be, zd) +- +-DO_LDFF1_ZPZ_S(hss_le, zsu) +-DO_LDFF1_ZPZ_S(hss_le, zss) +-DO_LDFF1_ZPZ_D(hds_le, zsu) +-DO_LDFF1_ZPZ_D(hds_le, zss) +-DO_LDFF1_ZPZ_D(hds_le, zd) +- +-DO_LDFF1_ZPZ_S(hss_be, zsu) +-DO_LDFF1_ZPZ_S(hss_be, zss) +-DO_LDFF1_ZPZ_D(hds_be, zsu) +-DO_LDFF1_ZPZ_D(hds_be, zss) +-DO_LDFF1_ZPZ_D(hds_be, zd) +- +-DO_LDFF1_ZPZ_S(ss_le, zsu) +-DO_LDFF1_ZPZ_S(ss_le, zss) +-DO_LDFF1_ZPZ_D(sdu_le, zsu) +-DO_LDFF1_ZPZ_D(sdu_le, zss) +-DO_LDFF1_ZPZ_D(sdu_le, zd) +- +-DO_LDFF1_ZPZ_S(ss_be, zsu) +-DO_LDFF1_ZPZ_S(ss_be, zss) +-DO_LDFF1_ZPZ_D(sdu_be, zsu) +-DO_LDFF1_ZPZ_D(sdu_be, zss) +-DO_LDFF1_ZPZ_D(sdu_be, zd) +- +-DO_LDFF1_ZPZ_D(sds_le, zsu) +-DO_LDFF1_ZPZ_D(sds_le, zss) +-DO_LDFF1_ZPZ_D(sds_le, zd) +- +-DO_LDFF1_ZPZ_D(sds_be, zsu) +-DO_LDFF1_ZPZ_D(sds_be, zss) +-DO_LDFF1_ZPZ_D(sds_be, zd) +- +-DO_LDFF1_ZPZ_D(dd_le, zsu) +-DO_LDFF1_ZPZ_D(dd_le, zss) +-DO_LDFF1_ZPZ_D(dd_le, zd) +- +-DO_LDFF1_ZPZ_D(dd_be, zsu) +-DO_LDFF1_ZPZ_D(dd_be, zss) +-DO_LDFF1_ZPZ_D(dd_be, zd) ++#define DO_LDFF1_ZPZ_S(MEM, OFS, MSZ) \ ++void HELPER(sve_ldff##MEM##_##OFS)(CPUARMState *env, void *vd, void *vg, \ ++ void *vm, target_ulong base, uint32_t desc) \ ++{ \ ++ sve_ldff1_z(env, vd, vg, vm, base, desc, GETPC(), MO_32, MSZ, \ ++ off_##OFS##_s, sve_ld1##MEM##_host, sve_ld1##MEM##_tlb); \ ++} ++ ++#define DO_LDFF1_ZPZ_D(MEM, OFS, MSZ) \ ++void HELPER(sve_ldff##MEM##_##OFS)(CPUARMState *env, void *vd, void *vg, \ ++ void *vm, target_ulong base, uint32_t desc) \ ++{ \ ++ sve_ldff1_z(env, vd, vg, vm, base, desc, GETPC(), MO_64, MSZ, \ ++ off_##OFS##_d, sve_ld1##MEM##_host, sve_ld1##MEM##_tlb); \ ++} ++ ++DO_LDFF1_ZPZ_S(bsu, zsu, MO_8) ++DO_LDFF1_ZPZ_S(bsu, zss, MO_8) ++DO_LDFF1_ZPZ_D(bdu, zsu, MO_8) ++DO_LDFF1_ZPZ_D(bdu, zss, MO_8) ++DO_LDFF1_ZPZ_D(bdu, zd, MO_8) ++ ++DO_LDFF1_ZPZ_S(bss, zsu, MO_8) ++DO_LDFF1_ZPZ_S(bss, zss, MO_8) ++DO_LDFF1_ZPZ_D(bds, zsu, MO_8) ++DO_LDFF1_ZPZ_D(bds, zss, MO_8) ++DO_LDFF1_ZPZ_D(bds, zd, MO_8) ++ ++DO_LDFF1_ZPZ_S(hsu_le, zsu, MO_16) ++DO_LDFF1_ZPZ_S(hsu_le, zss, MO_16) ++DO_LDFF1_ZPZ_D(hdu_le, zsu, MO_16) ++DO_LDFF1_ZPZ_D(hdu_le, zss, MO_16) ++DO_LDFF1_ZPZ_D(hdu_le, zd, MO_16) ++ ++DO_LDFF1_ZPZ_S(hsu_be, zsu, MO_16) ++DO_LDFF1_ZPZ_S(hsu_be, zss, MO_16) ++DO_LDFF1_ZPZ_D(hdu_be, zsu, MO_16) ++DO_LDFF1_ZPZ_D(hdu_be, zss, MO_16) ++DO_LDFF1_ZPZ_D(hdu_be, zd, MO_16) ++ ++DO_LDFF1_ZPZ_S(hss_le, zsu, MO_16) ++DO_LDFF1_ZPZ_S(hss_le, zss, MO_16) ++DO_LDFF1_ZPZ_D(hds_le, zsu, MO_16) ++DO_LDFF1_ZPZ_D(hds_le, zss, MO_16) ++DO_LDFF1_ZPZ_D(hds_le, zd, MO_16) ++ ++DO_LDFF1_ZPZ_S(hss_be, zsu, MO_16) ++DO_LDFF1_ZPZ_S(hss_be, zss, MO_16) ++DO_LDFF1_ZPZ_D(hds_be, zsu, MO_16) ++DO_LDFF1_ZPZ_D(hds_be, zss, MO_16) ++DO_LDFF1_ZPZ_D(hds_be, zd, MO_16) ++ ++DO_LDFF1_ZPZ_S(ss_le, zsu, MO_32) ++DO_LDFF1_ZPZ_S(ss_le, zss, MO_32) ++DO_LDFF1_ZPZ_D(sdu_le, zsu, MO_32) ++DO_LDFF1_ZPZ_D(sdu_le, zss, MO_32) ++DO_LDFF1_ZPZ_D(sdu_le, zd, MO_32) ++ ++DO_LDFF1_ZPZ_S(ss_be, zsu, MO_32) ++DO_LDFF1_ZPZ_S(ss_be, zss, MO_32) ++DO_LDFF1_ZPZ_D(sdu_be, zsu, MO_32) ++DO_LDFF1_ZPZ_D(sdu_be, zss, MO_32) ++DO_LDFF1_ZPZ_D(sdu_be, zd, MO_32) ++ ++DO_LDFF1_ZPZ_D(sds_le, zsu, MO_32) ++DO_LDFF1_ZPZ_D(sds_le, zss, MO_32) ++DO_LDFF1_ZPZ_D(sds_le, zd, MO_32) ++ ++DO_LDFF1_ZPZ_D(sds_be, zsu, MO_32) ++DO_LDFF1_ZPZ_D(sds_be, zss, MO_32) ++DO_LDFF1_ZPZ_D(sds_be, zd, MO_32) ++ ++DO_LDFF1_ZPZ_D(dd_le, zsu, MO_64) ++DO_LDFF1_ZPZ_D(dd_le, zss, MO_64) ++DO_LDFF1_ZPZ_D(dd_le, zd, MO_64) ++ ++DO_LDFF1_ZPZ_D(dd_be, zsu, MO_64) ++DO_LDFF1_ZPZ_D(dd_be, zss, MO_64) ++DO_LDFF1_ZPZ_D(dd_be, zd, MO_64) + + /* Stores with a vector index. */ + +-- +2.23.0 + diff --git a/target-arm-Reuse-sve_probe_page-for-gather-loads.patch b/target-arm-Reuse-sve_probe_page-for-gather-loads.patch new file mode 100644 index 0000000000000000000000000000000000000000..a3905084f3c9bc35ad02b62a9c6d298547eecdcb --- /dev/null +++ b/target-arm-Reuse-sve_probe_page-for-gather-loads.patch @@ -0,0 +1,274 @@ +From 10a85e2c8ab6e004e7f3f1dcfea8cb0bf58fb9fb Mon Sep 17 00:00:00 2001 +From: Richard Henderson +Date: Fri, 8 May 2020 08:43:58 -0700 +Subject: [PATCH 382/709] target/arm: Reuse sve_probe_page for gather loads + +Reviewed-by: Peter Maydell +Signed-off-by: Richard Henderson +Message-id: 20200508154359.7494-19-richard.henderson@linaro.org +Signed-off-by: Peter Maydell +--- + target/arm/sve_helper.c | 236 +++++++++++++++++++++------------------- + 1 file changed, 123 insertions(+), 113 deletions(-) + +diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c +index ad7e10f1e7..f1870aabc2 100644 +--- a/target/arm/sve_helper.c ++++ b/target/arm/sve_helper.c +@@ -5124,130 +5124,140 @@ static target_ulong off_zd_d(void *reg, intptr_t reg_ofs) + return *(uint64_t *)(reg + reg_ofs); + } + +-static void sve_ld1_zs(CPUARMState *env, void *vd, void *vg, void *vm, +- target_ulong base, uint32_t desc, uintptr_t ra, +- zreg_off_fn *off_fn, sve_ldst1_tlb_fn *tlb_fn) ++static inline QEMU_ALWAYS_INLINE ++void sve_ld1_z(CPUARMState *env, void *vd, uint64_t *vg, void *vm, ++ target_ulong base, uint32_t desc, uintptr_t retaddr, ++ int esize, int msize, zreg_off_fn *off_fn, ++ sve_ldst1_host_fn *host_fn, ++ sve_ldst1_tlb_fn *tlb_fn) + { + const int scale = extract32(desc, SIMD_DATA_SHIFT + MEMOPIDX_SHIFT, 2); +- intptr_t i, oprsz = simd_oprsz(desc); +- ARMVectorReg scratch = { }; ++ const int mmu_idx = cpu_mmu_index(env, false); ++ const intptr_t reg_max = simd_oprsz(desc); ++ ARMVectorReg scratch; ++ intptr_t reg_off; ++ SVEHostPage info, info2; + +- for (i = 0; i < oprsz; ) { +- uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3)); ++ memset(&scratch, 0, reg_max); ++ reg_off = 0; ++ do { ++ uint64_t pg = vg[reg_off >> 6]; + do { + if (likely(pg & 1)) { +- target_ulong off = off_fn(vm, i); +- tlb_fn(env, &scratch, i, base + (off << scale), ra); ++ target_ulong addr = base + (off_fn(vm, reg_off) << scale); ++ target_ulong in_page = -(addr | TARGET_PAGE_MASK); ++ ++ sve_probe_page(&info, false, env, addr, 0, MMU_DATA_LOAD, ++ mmu_idx, retaddr); ++ ++ if (likely(in_page >= msize)) { ++ if (unlikely(info.flags & TLB_WATCHPOINT)) { ++ cpu_check_watchpoint(env_cpu(env), addr, msize, ++ info.attrs, BP_MEM_READ, retaddr); ++ } ++ /* TODO: MTE check */ ++ host_fn(&scratch, reg_off, info.host); ++ } else { ++ /* Element crosses the page boundary. */ ++ sve_probe_page(&info2, false, env, addr + in_page, 0, ++ MMU_DATA_LOAD, mmu_idx, retaddr); ++ if (unlikely((info.flags | info2.flags) & TLB_WATCHPOINT)) { ++ cpu_check_watchpoint(env_cpu(env), addr, ++ msize, info.attrs, ++ BP_MEM_READ, retaddr); ++ } ++ /* TODO: MTE check */ ++ tlb_fn(env, &scratch, reg_off, addr, retaddr); ++ } + } +- i += 4, pg >>= 4; +- } while (i & 15); +- } ++ reg_off += esize; ++ pg >>= esize; ++ } while (reg_off & 63); ++ } while (reg_off < reg_max); + + /* Wait until all exceptions have been raised to write back. */ +- memcpy(vd, &scratch, oprsz); ++ memcpy(vd, &scratch, reg_max); + } + +-static void sve_ld1_zd(CPUARMState *env, void *vd, void *vg, void *vm, +- target_ulong base, uint32_t desc, uintptr_t ra, +- zreg_off_fn *off_fn, sve_ldst1_tlb_fn *tlb_fn) +-{ +- const int scale = extract32(desc, SIMD_DATA_SHIFT + MEMOPIDX_SHIFT, 2); +- intptr_t i, oprsz = simd_oprsz(desc) / 8; +- ARMVectorReg scratch = { }; +- +- for (i = 0; i < oprsz; i++) { +- uint8_t pg = *(uint8_t *)(vg + H1(i)); +- if (likely(pg & 1)) { +- target_ulong off = off_fn(vm, i * 8); +- tlb_fn(env, &scratch, i * 8, base + (off << scale), ra); +- } +- } ++#define DO_LD1_ZPZ_S(MEM, OFS, MSZ) \ ++void HELPER(sve_ld##MEM##_##OFS)(CPUARMState *env, void *vd, void *vg, \ ++ void *vm, target_ulong base, uint32_t desc) \ ++{ \ ++ sve_ld1_z(env, vd, vg, vm, base, desc, GETPC(), 4, 1 << MSZ, \ ++ off_##OFS##_s, sve_ld1##MEM##_host, sve_ld1##MEM##_tlb); \ ++} + +- /* Wait until all exceptions have been raised to write back. */ +- memcpy(vd, &scratch, oprsz * 8); +-} +- +-#define DO_LD1_ZPZ_S(MEM, OFS) \ +-void QEMU_FLATTEN HELPER(sve_ld##MEM##_##OFS) \ +- (CPUARMState *env, void *vd, void *vg, void *vm, \ +- target_ulong base, uint32_t desc) \ +-{ \ +- sve_ld1_zs(env, vd, vg, vm, base, desc, GETPC(), \ +- off_##OFS##_s, sve_ld1##MEM##_tlb); \ +-} +- +-#define DO_LD1_ZPZ_D(MEM, OFS) \ +-void QEMU_FLATTEN HELPER(sve_ld##MEM##_##OFS) \ +- (CPUARMState *env, void *vd, void *vg, void *vm, \ +- target_ulong base, uint32_t desc) \ +-{ \ +- sve_ld1_zd(env, vd, vg, vm, base, desc, GETPC(), \ +- off_##OFS##_d, sve_ld1##MEM##_tlb); \ +-} +- +-DO_LD1_ZPZ_S(bsu, zsu) +-DO_LD1_ZPZ_S(bsu, zss) +-DO_LD1_ZPZ_D(bdu, zsu) +-DO_LD1_ZPZ_D(bdu, zss) +-DO_LD1_ZPZ_D(bdu, zd) +- +-DO_LD1_ZPZ_S(bss, zsu) +-DO_LD1_ZPZ_S(bss, zss) +-DO_LD1_ZPZ_D(bds, zsu) +-DO_LD1_ZPZ_D(bds, zss) +-DO_LD1_ZPZ_D(bds, zd) +- +-DO_LD1_ZPZ_S(hsu_le, zsu) +-DO_LD1_ZPZ_S(hsu_le, zss) +-DO_LD1_ZPZ_D(hdu_le, zsu) +-DO_LD1_ZPZ_D(hdu_le, zss) +-DO_LD1_ZPZ_D(hdu_le, zd) +- +-DO_LD1_ZPZ_S(hsu_be, zsu) +-DO_LD1_ZPZ_S(hsu_be, zss) +-DO_LD1_ZPZ_D(hdu_be, zsu) +-DO_LD1_ZPZ_D(hdu_be, zss) +-DO_LD1_ZPZ_D(hdu_be, zd) +- +-DO_LD1_ZPZ_S(hss_le, zsu) +-DO_LD1_ZPZ_S(hss_le, zss) +-DO_LD1_ZPZ_D(hds_le, zsu) +-DO_LD1_ZPZ_D(hds_le, zss) +-DO_LD1_ZPZ_D(hds_le, zd) +- +-DO_LD1_ZPZ_S(hss_be, zsu) +-DO_LD1_ZPZ_S(hss_be, zss) +-DO_LD1_ZPZ_D(hds_be, zsu) +-DO_LD1_ZPZ_D(hds_be, zss) +-DO_LD1_ZPZ_D(hds_be, zd) +- +-DO_LD1_ZPZ_S(ss_le, zsu) +-DO_LD1_ZPZ_S(ss_le, zss) +-DO_LD1_ZPZ_D(sdu_le, zsu) +-DO_LD1_ZPZ_D(sdu_le, zss) +-DO_LD1_ZPZ_D(sdu_le, zd) +- +-DO_LD1_ZPZ_S(ss_be, zsu) +-DO_LD1_ZPZ_S(ss_be, zss) +-DO_LD1_ZPZ_D(sdu_be, zsu) +-DO_LD1_ZPZ_D(sdu_be, zss) +-DO_LD1_ZPZ_D(sdu_be, zd) +- +-DO_LD1_ZPZ_D(sds_le, zsu) +-DO_LD1_ZPZ_D(sds_le, zss) +-DO_LD1_ZPZ_D(sds_le, zd) +- +-DO_LD1_ZPZ_D(sds_be, zsu) +-DO_LD1_ZPZ_D(sds_be, zss) +-DO_LD1_ZPZ_D(sds_be, zd) +- +-DO_LD1_ZPZ_D(dd_le, zsu) +-DO_LD1_ZPZ_D(dd_le, zss) +-DO_LD1_ZPZ_D(dd_le, zd) +- +-DO_LD1_ZPZ_D(dd_be, zsu) +-DO_LD1_ZPZ_D(dd_be, zss) +-DO_LD1_ZPZ_D(dd_be, zd) ++#define DO_LD1_ZPZ_D(MEM, OFS, MSZ) \ ++void HELPER(sve_ld##MEM##_##OFS)(CPUARMState *env, void *vd, void *vg, \ ++ void *vm, target_ulong base, uint32_t desc) \ ++{ \ ++ sve_ld1_z(env, vd, vg, vm, base, desc, GETPC(), 8, 1 << MSZ, \ ++ off_##OFS##_d, sve_ld1##MEM##_host, sve_ld1##MEM##_tlb); \ ++} ++ ++DO_LD1_ZPZ_S(bsu, zsu, MO_8) ++DO_LD1_ZPZ_S(bsu, zss, MO_8) ++DO_LD1_ZPZ_D(bdu, zsu, MO_8) ++DO_LD1_ZPZ_D(bdu, zss, MO_8) ++DO_LD1_ZPZ_D(bdu, zd, MO_8) ++ ++DO_LD1_ZPZ_S(bss, zsu, MO_8) ++DO_LD1_ZPZ_S(bss, zss, MO_8) ++DO_LD1_ZPZ_D(bds, zsu, MO_8) ++DO_LD1_ZPZ_D(bds, zss, MO_8) ++DO_LD1_ZPZ_D(bds, zd, MO_8) ++ ++DO_LD1_ZPZ_S(hsu_le, zsu, MO_16) ++DO_LD1_ZPZ_S(hsu_le, zss, MO_16) ++DO_LD1_ZPZ_D(hdu_le, zsu, MO_16) ++DO_LD1_ZPZ_D(hdu_le, zss, MO_16) ++DO_LD1_ZPZ_D(hdu_le, zd, MO_16) ++ ++DO_LD1_ZPZ_S(hsu_be, zsu, MO_16) ++DO_LD1_ZPZ_S(hsu_be, zss, MO_16) ++DO_LD1_ZPZ_D(hdu_be, zsu, MO_16) ++DO_LD1_ZPZ_D(hdu_be, zss, MO_16) ++DO_LD1_ZPZ_D(hdu_be, zd, MO_16) ++ ++DO_LD1_ZPZ_S(hss_le, zsu, MO_16) ++DO_LD1_ZPZ_S(hss_le, zss, MO_16) ++DO_LD1_ZPZ_D(hds_le, zsu, MO_16) ++DO_LD1_ZPZ_D(hds_le, zss, MO_16) ++DO_LD1_ZPZ_D(hds_le, zd, MO_16) ++ ++DO_LD1_ZPZ_S(hss_be, zsu, MO_16) ++DO_LD1_ZPZ_S(hss_be, zss, MO_16) ++DO_LD1_ZPZ_D(hds_be, zsu, MO_16) ++DO_LD1_ZPZ_D(hds_be, zss, MO_16) ++DO_LD1_ZPZ_D(hds_be, zd, MO_16) ++ ++DO_LD1_ZPZ_S(ss_le, zsu, MO_32) ++DO_LD1_ZPZ_S(ss_le, zss, MO_32) ++DO_LD1_ZPZ_D(sdu_le, zsu, MO_32) ++DO_LD1_ZPZ_D(sdu_le, zss, MO_32) ++DO_LD1_ZPZ_D(sdu_le, zd, MO_32) ++ ++DO_LD1_ZPZ_S(ss_be, zsu, MO_32) ++DO_LD1_ZPZ_S(ss_be, zss, MO_32) ++DO_LD1_ZPZ_D(sdu_be, zsu, MO_32) ++DO_LD1_ZPZ_D(sdu_be, zss, MO_32) ++DO_LD1_ZPZ_D(sdu_be, zd, MO_32) ++ ++DO_LD1_ZPZ_D(sds_le, zsu, MO_32) ++DO_LD1_ZPZ_D(sds_le, zss, MO_32) ++DO_LD1_ZPZ_D(sds_le, zd, MO_32) ++ ++DO_LD1_ZPZ_D(sds_be, zsu, MO_32) ++DO_LD1_ZPZ_D(sds_be, zss, MO_32) ++DO_LD1_ZPZ_D(sds_be, zd, MO_32) ++ ++DO_LD1_ZPZ_D(dd_le, zsu, MO_64) ++DO_LD1_ZPZ_D(dd_le, zss, MO_64) ++DO_LD1_ZPZ_D(dd_le, zd, MO_64) ++ ++DO_LD1_ZPZ_D(dd_be, zsu, MO_64) ++DO_LD1_ZPZ_D(dd_be, zss, MO_64) ++DO_LD1_ZPZ_D(dd_be, zd, MO_64) + + #undef DO_LD1_ZPZ_S + #undef DO_LD1_ZPZ_D +-- +2.23.0 + diff --git a/target-arm-Reuse-sve_probe_page-for-scatter-stores.patch b/target-arm-Reuse-sve_probe_page-for-scatter-stores.patch new file mode 100644 index 0000000000000000000000000000000000000000..5ebf9fe60dae0b56535cb859129ef4d42f7a823e --- /dev/null +++ b/target-arm-Reuse-sve_probe_page-for-scatter-stores.patch @@ -0,0 +1,232 @@ +From 88a660a48ef513ce9875b595e19b2a820b3f3fca Mon Sep 17 00:00:00 2001 +From: Richard Henderson +Date: Fri, 8 May 2020 08:43:57 -0700 +Subject: [PATCH 381/709] target/arm: Reuse sve_probe_page for scatter stores + +Reviewed-by: Peter Maydell +Signed-off-by: Richard Henderson +Message-id: 20200508154359.7494-18-richard.henderson@linaro.org +Signed-off-by: Peter Maydell +--- + target/arm/sve_helper.c | 194 ++++++++++++++++++++++++---------------- + 1 file changed, 117 insertions(+), 77 deletions(-) + +diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c +index 1560129b08..ad7e10f1e7 100644 +--- a/target/arm/sve_helper.c ++++ b/target/arm/sve_helper.c +@@ -5413,94 +5413,134 @@ DO_LDFF1_ZPZ_D(dd_be, zd, MO_64) + + /* Stores with a vector index. */ + +-static void sve_st1_zs(CPUARMState *env, void *vd, void *vg, void *vm, +- target_ulong base, uint32_t desc, uintptr_t ra, +- zreg_off_fn *off_fn, sve_ldst1_tlb_fn *tlb_fn) ++static inline QEMU_ALWAYS_INLINE ++void sve_st1_z(CPUARMState *env, void *vd, uint64_t *vg, void *vm, ++ target_ulong base, uint32_t desc, uintptr_t retaddr, ++ int esize, int msize, zreg_off_fn *off_fn, ++ sve_ldst1_host_fn *host_fn, ++ sve_ldst1_tlb_fn *tlb_fn) + { + const int scale = extract32(desc, SIMD_DATA_SHIFT + MEMOPIDX_SHIFT, 2); +- intptr_t i, oprsz = simd_oprsz(desc); ++ const int mmu_idx = cpu_mmu_index(env, false); ++ const intptr_t reg_max = simd_oprsz(desc); ++ void *host[ARM_MAX_VQ * 4]; ++ intptr_t reg_off, i; ++ SVEHostPage info, info2; + +- for (i = 0; i < oprsz; ) { +- uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3)); ++ /* ++ * Probe all of the elements for host addresses and flags. ++ */ ++ i = reg_off = 0; ++ do { ++ uint64_t pg = vg[reg_off >> 6]; + do { +- if (likely(pg & 1)) { +- target_ulong off = off_fn(vm, i); +- tlb_fn(env, vd, i, base + (off << scale), ra); +- } +- i += 4, pg >>= 4; +- } while (i & 15); +- } +-} ++ target_ulong addr = base + (off_fn(vm, reg_off) << scale); ++ target_ulong in_page = -(addr | TARGET_PAGE_MASK); + +-static void sve_st1_zd(CPUARMState *env, void *vd, void *vg, void *vm, +- target_ulong base, uint32_t desc, uintptr_t ra, +- zreg_off_fn *off_fn, sve_ldst1_tlb_fn *tlb_fn) +-{ +- const int scale = extract32(desc, SIMD_DATA_SHIFT + MEMOPIDX_SHIFT, 2); +- intptr_t i, oprsz = simd_oprsz(desc) / 8; ++ host[i] = NULL; ++ if (likely((pg >> (reg_off & 63)) & 1)) { ++ if (likely(in_page >= msize)) { ++ sve_probe_page(&info, false, env, addr, 0, MMU_DATA_STORE, ++ mmu_idx, retaddr); ++ host[i] = info.host; ++ } else { ++ /* ++ * Element crosses the page boundary. ++ * Probe both pages, but do not record the host address, ++ * so that we use the slow path. ++ */ ++ sve_probe_page(&info, false, env, addr, 0, ++ MMU_DATA_STORE, mmu_idx, retaddr); ++ sve_probe_page(&info2, false, env, addr + in_page, 0, ++ MMU_DATA_STORE, mmu_idx, retaddr); ++ info.flags |= info2.flags; ++ } + +- for (i = 0; i < oprsz; i++) { +- uint8_t pg = *(uint8_t *)(vg + H1(i)); +- if (likely(pg & 1)) { +- target_ulong off = off_fn(vm, i * 8); +- tlb_fn(env, vd, i * 8, base + (off << scale), ra); ++ if (unlikely(info.flags & TLB_WATCHPOINT)) { ++ cpu_check_watchpoint(env_cpu(env), addr, msize, ++ info.attrs, BP_MEM_WRITE, retaddr); ++ } ++ /* TODO: MTE check. */ ++ } ++ i += 1; ++ reg_off += esize; ++ } while (reg_off & 63); ++ } while (reg_off < reg_max); ++ ++ /* ++ * Now that we have recognized all exceptions except SyncExternal ++ * (from TLB_MMIO), which we cannot avoid, perform all of the stores. ++ * ++ * Note for the common case of an element in RAM, not crossing a page ++ * boundary, we have stored the host address in host[]. This doubles ++ * as a first-level check against the predicate, since only enabled ++ * elements have non-null host addresses. ++ */ ++ i = reg_off = 0; ++ do { ++ void *h = host[i]; ++ if (likely(h != NULL)) { ++ host_fn(vd, reg_off, h); ++ } else if ((vg[reg_off >> 6] >> (reg_off & 63)) & 1) { ++ target_ulong addr = base + (off_fn(vm, reg_off) << scale); ++ tlb_fn(env, vd, reg_off, addr, retaddr); + } +- } ++ i += 1; ++ reg_off += esize; ++ } while (reg_off < reg_max); + } + +-#define DO_ST1_ZPZ_S(MEM, OFS) \ +-void QEMU_FLATTEN HELPER(sve_st##MEM##_##OFS) \ +- (CPUARMState *env, void *vd, void *vg, void *vm, \ +- target_ulong base, uint32_t desc) \ +-{ \ +- sve_st1_zs(env, vd, vg, vm, base, desc, GETPC(), \ +- off_##OFS##_s, sve_st1##MEM##_tlb); \ ++#define DO_ST1_ZPZ_S(MEM, OFS, MSZ) \ ++void HELPER(sve_st##MEM##_##OFS)(CPUARMState *env, void *vd, void *vg, \ ++ void *vm, target_ulong base, uint32_t desc) \ ++{ \ ++ sve_st1_z(env, vd, vg, vm, base, desc, GETPC(), 4, 1 << MSZ, \ ++ off_##OFS##_s, sve_st1##MEM##_host, sve_st1##MEM##_tlb); \ + } + +-#define DO_ST1_ZPZ_D(MEM, OFS) \ +-void QEMU_FLATTEN HELPER(sve_st##MEM##_##OFS) \ +- (CPUARMState *env, void *vd, void *vg, void *vm, \ +- target_ulong base, uint32_t desc) \ +-{ \ +- sve_st1_zd(env, vd, vg, vm, base, desc, GETPC(), \ +- off_##OFS##_d, sve_st1##MEM##_tlb); \ +-} +- +-DO_ST1_ZPZ_S(bs, zsu) +-DO_ST1_ZPZ_S(hs_le, zsu) +-DO_ST1_ZPZ_S(hs_be, zsu) +-DO_ST1_ZPZ_S(ss_le, zsu) +-DO_ST1_ZPZ_S(ss_be, zsu) +- +-DO_ST1_ZPZ_S(bs, zss) +-DO_ST1_ZPZ_S(hs_le, zss) +-DO_ST1_ZPZ_S(hs_be, zss) +-DO_ST1_ZPZ_S(ss_le, zss) +-DO_ST1_ZPZ_S(ss_be, zss) +- +-DO_ST1_ZPZ_D(bd, zsu) +-DO_ST1_ZPZ_D(hd_le, zsu) +-DO_ST1_ZPZ_D(hd_be, zsu) +-DO_ST1_ZPZ_D(sd_le, zsu) +-DO_ST1_ZPZ_D(sd_be, zsu) +-DO_ST1_ZPZ_D(dd_le, zsu) +-DO_ST1_ZPZ_D(dd_be, zsu) +- +-DO_ST1_ZPZ_D(bd, zss) +-DO_ST1_ZPZ_D(hd_le, zss) +-DO_ST1_ZPZ_D(hd_be, zss) +-DO_ST1_ZPZ_D(sd_le, zss) +-DO_ST1_ZPZ_D(sd_be, zss) +-DO_ST1_ZPZ_D(dd_le, zss) +-DO_ST1_ZPZ_D(dd_be, zss) +- +-DO_ST1_ZPZ_D(bd, zd) +-DO_ST1_ZPZ_D(hd_le, zd) +-DO_ST1_ZPZ_D(hd_be, zd) +-DO_ST1_ZPZ_D(sd_le, zd) +-DO_ST1_ZPZ_D(sd_be, zd) +-DO_ST1_ZPZ_D(dd_le, zd) +-DO_ST1_ZPZ_D(dd_be, zd) ++#define DO_ST1_ZPZ_D(MEM, OFS, MSZ) \ ++void HELPER(sve_st##MEM##_##OFS)(CPUARMState *env, void *vd, void *vg, \ ++ void *vm, target_ulong base, uint32_t desc) \ ++{ \ ++ sve_st1_z(env, vd, vg, vm, base, desc, GETPC(), 8, 1 << MSZ, \ ++ off_##OFS##_d, sve_st1##MEM##_host, sve_st1##MEM##_tlb); \ ++} ++ ++DO_ST1_ZPZ_S(bs, zsu, MO_8) ++DO_ST1_ZPZ_S(hs_le, zsu, MO_16) ++DO_ST1_ZPZ_S(hs_be, zsu, MO_16) ++DO_ST1_ZPZ_S(ss_le, zsu, MO_32) ++DO_ST1_ZPZ_S(ss_be, zsu, MO_32) ++ ++DO_ST1_ZPZ_S(bs, zss, MO_8) ++DO_ST1_ZPZ_S(hs_le, zss, MO_16) ++DO_ST1_ZPZ_S(hs_be, zss, MO_16) ++DO_ST1_ZPZ_S(ss_le, zss, MO_32) ++DO_ST1_ZPZ_S(ss_be, zss, MO_32) ++ ++DO_ST1_ZPZ_D(bd, zsu, MO_8) ++DO_ST1_ZPZ_D(hd_le, zsu, MO_16) ++DO_ST1_ZPZ_D(hd_be, zsu, MO_16) ++DO_ST1_ZPZ_D(sd_le, zsu, MO_32) ++DO_ST1_ZPZ_D(sd_be, zsu, MO_32) ++DO_ST1_ZPZ_D(dd_le, zsu, MO_64) ++DO_ST1_ZPZ_D(dd_be, zsu, MO_64) ++ ++DO_ST1_ZPZ_D(bd, zss, MO_8) ++DO_ST1_ZPZ_D(hd_le, zss, MO_16) ++DO_ST1_ZPZ_D(hd_be, zss, MO_16) ++DO_ST1_ZPZ_D(sd_le, zss, MO_32) ++DO_ST1_ZPZ_D(sd_be, zss, MO_32) ++DO_ST1_ZPZ_D(dd_le, zss, MO_64) ++DO_ST1_ZPZ_D(dd_be, zss, MO_64) ++ ++DO_ST1_ZPZ_D(bd, zd, MO_8) ++DO_ST1_ZPZ_D(hd_le, zd, MO_16) ++DO_ST1_ZPZ_D(hd_be, zd, MO_16) ++DO_ST1_ZPZ_D(sd_le, zd, MO_32) ++DO_ST1_ZPZ_D(sd_be, zd, MO_32) ++DO_ST1_ZPZ_D(dd_le, zd, MO_64) ++DO_ST1_ZPZ_D(dd_be, zd, MO_64) + + #undef DO_ST1_ZPZ_S + #undef DO_ST1_ZPZ_D +-- +2.23.0 + diff --git a/target-arm-Swap-argument-order-for-VSHL-during-decod.patch b/target-arm-Swap-argument-order-for-VSHL-during-decod.patch new file mode 100644 index 0000000000000000000000000000000000000000..b1a3dfcb192b2cb8c3ef923b8af89795d88eff8a --- /dev/null +++ b/target-arm-Swap-argument-order-for-VSHL-during-decod.patch @@ -0,0 +1,66 @@ +From e9eee5316ffec5f37643de806b2e5577c5c189cf Mon Sep 17 00:00:00 2001 +From: Richard Henderson +Date: Wed, 13 May 2020 09:32:37 -0700 +Subject: [PATCH 426/709] target/arm: Swap argument order for VSHL during + decode + +Rather than perform the argument swap during code generation, +perform it during decode. This means it doesn't have to be +special cased later, and we can share code with aarch64 code +generation. Hopefully the decode comment addresses any confusion +that might arise in between. + +Reviewed-by: Peter Maydell +Signed-off-by: Richard Henderson +Message-id: 20200513163245.17915-9-richard.henderson@linaro.org +Signed-off-by: Peter Maydell +--- + target/arm/neon-dp.decode | 17 +++++++++++++++-- + target/arm/translate-neon.inc.c | 3 +-- + 2 files changed, 16 insertions(+), 4 deletions(-) + +diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode +index ec3a92fe75..593f7fff03 100644 +--- a/target/arm/neon-dp.decode ++++ b/target/arm/neon-dp.decode +@@ -65,8 +65,21 @@ VCGT_U_3s 1111 001 1 0 . .. .... .... 0011 . . . 0 .... @3same + VCGE_S_3s 1111 001 0 0 . .. .... .... 0011 . . . 1 .... @3same + VCGE_U_3s 1111 001 1 0 . .. .... .... 0011 . . . 1 .... @3same + +-VSHL_S_3s 1111 001 0 0 . .. .... .... 0100 . . . 0 .... @3same +-VSHL_U_3s 1111 001 1 0 . .. .... .... 0100 . . . 0 .... @3same ++# The _rev suffix indicates that Vn and Vm are reversed. This is ++# the case for shifts. In the Arm ARM these insns are documented ++# with the Vm and Vn fields in their usual places, but in the ++# assembly the operands are listed "backwards", ie in the order ++# Dd, Dm, Dn where other insns use Dd, Dn, Dm. For QEMU we choose ++# to consider Vm and Vn as being in different fields in the insn, ++# which allows us to avoid special-casing shifts in the trans_ ++# function code. We would otherwise need to manually swap the operands ++# over to call Neon helper functions that are shared with AArch64, ++# which does not have this odd reversed-operand situation. ++@3same_rev .... ... . . . size:2 .... .... .... . q:1 . . .... \ ++ &3same vn=%vm_dp vm=%vn_dp vd=%vd_dp ++ ++VSHL_S_3s 1111 001 0 0 . .. .... .... 0100 . . . 0 .... @3same_rev ++VSHL_U_3s 1111 001 1 0 . .. .... .... 0100 . . . 0 .... @3same_rev + + VMAX_S_3s 1111 001 0 0 . .. .... .... 0110 . . . 0 .... @3same + VMAX_U_3s 1111 001 1 0 . .. .... .... 0110 . . . 0 .... @3same +diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c +index aefeff498a..416302bcc7 100644 +--- a/target/arm/translate-neon.inc.c ++++ b/target/arm/translate-neon.inc.c +@@ -692,8 +692,7 @@ static bool trans_VMUL_p_3s(DisasContext *s, arg_3same *a) + uint32_t rn_ofs, uint32_t rm_ofs, \ + uint32_t oprsz, uint32_t maxsz) \ + { \ +- /* Note the operation is vshl vd,vm,vn */ \ +- tcg_gen_gvec_3(rd_ofs, rm_ofs, rn_ofs, \ ++ tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, \ + oprsz, maxsz, &OPARRAY[vece]); \ + } \ + DO_3SAME(INSN, gen_##INSN##_3s) +-- +2.23.0 + diff --git a/target-arm-Tidy-handle_vec_simd_shri.patch b/target-arm-Tidy-handle_vec_simd_shri.patch new file mode 100644 index 0000000000000000000000000000000000000000..a4aeb6bd6ff872fe68c10602a0c9130ce2cda2d7 --- /dev/null +++ b/target-arm-Tidy-handle_vec_simd_shri.patch @@ -0,0 +1,121 @@ +From 3f08f0bce841e7857ec98ce7909629d0c335005e Mon Sep 17 00:00:00 2001 +From: Richard Henderson +Date: Wed, 13 May 2020 09:32:34 -0700 +Subject: [PATCH 423/709] target/arm: Tidy handle_vec_simd_shri + +Now that we've converted all cases to gvec, there is quite a bit +of dead code at the end of the function. Remove it. + +Sink the call to gen_gvec_fn2i to the end, loading a function +pointer within the switch statement. + +Reviewed-by: Peter Maydell +Signed-off-by: Richard Henderson +Message-id: 20200513163245.17915-6-richard.henderson@linaro.org +Signed-off-by: Peter Maydell +--- + target/arm/translate-a64.c | 56 ++++++++++---------------------------- + 1 file changed, 14 insertions(+), 42 deletions(-) + +diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c +index 2d7dad6c3f..d5e77f34a7 100644 +--- a/target/arm/translate-a64.c ++++ b/target/arm/translate-a64.c +@@ -10155,16 +10155,7 @@ static void handle_vec_simd_shri(DisasContext *s, bool is_q, bool is_u, + int size = 32 - clz32(immh) - 1; + int immhb = immh << 3 | immb; + int shift = 2 * (8 << size) - immhb; +- bool accumulate = false; +- int dsize = is_q ? 128 : 64; +- int esize = 8 << size; +- int elements = dsize/esize; +- MemOp memop = size | (is_u ? 0 : MO_SIGN); +- TCGv_i64 tcg_rn = new_tmp_a64(s); +- TCGv_i64 tcg_rd = new_tmp_a64(s); +- TCGv_i64 tcg_round; +- uint64_t round_const; +- int i; ++ GVecGen2iFn *gvec_fn; + + if (extract32(immh, 3, 1) && !is_q) { + unallocated_encoding(s); +@@ -10178,13 +10169,12 @@ static void handle_vec_simd_shri(DisasContext *s, bool is_q, bool is_u, + + switch (opcode) { + case 0x02: /* SSRA / USRA (accumulate) */ +- gen_gvec_fn2i(s, is_q, rd, rn, shift, +- is_u ? gen_gvec_usra : gen_gvec_ssra, size); +- return; ++ gvec_fn = is_u ? gen_gvec_usra : gen_gvec_ssra; ++ break; + + case 0x08: /* SRI */ +- gen_gvec_fn2i(s, is_q, rd, rn, shift, gen_gvec_sri, size); +- return; ++ gvec_fn = gen_gvec_sri; ++ break; + + case 0x00: /* SSHR / USHR */ + if (is_u) { +@@ -10192,49 +10182,31 @@ static void handle_vec_simd_shri(DisasContext *s, bool is_q, bool is_u, + /* Shift count the same size as element size produces zero. */ + tcg_gen_gvec_dup_imm(size, vec_full_reg_offset(s, rd), + is_q ? 16 : 8, vec_full_reg_size(s), 0); +- } else { +- gen_gvec_fn2i(s, is_q, rd, rn, shift, tcg_gen_gvec_shri, size); ++ return; + } ++ gvec_fn = tcg_gen_gvec_shri; + } else { + /* Shift count the same size as element size produces all sign. */ + if (shift == 8 << size) { + shift -= 1; + } +- gen_gvec_fn2i(s, is_q, rd, rn, shift, tcg_gen_gvec_sari, size); ++ gvec_fn = tcg_gen_gvec_sari; + } +- return; ++ break; + + case 0x04: /* SRSHR / URSHR (rounding) */ +- gen_gvec_fn2i(s, is_q, rd, rn, shift, +- is_u ? gen_gvec_urshr : gen_gvec_srshr, size); +- return; ++ gvec_fn = is_u ? gen_gvec_urshr : gen_gvec_srshr; ++ break; + + case 0x06: /* SRSRA / URSRA (accum + rounding) */ +- gen_gvec_fn2i(s, is_q, rd, rn, shift, +- is_u ? gen_gvec_ursra : gen_gvec_srsra, size); +- return; ++ gvec_fn = is_u ? gen_gvec_ursra : gen_gvec_srsra; ++ break; + + default: + g_assert_not_reached(); + } + +- round_const = 1ULL << (shift - 1); +- tcg_round = tcg_const_i64(round_const); +- +- for (i = 0; i < elements; i++) { +- read_vec_element(s, tcg_rn, rn, i, memop); +- if (accumulate) { +- read_vec_element(s, tcg_rd, rd, i, memop); +- } +- +- handle_shri_with_rndacc(tcg_rd, tcg_rn, tcg_round, +- accumulate, is_u, size, shift); +- +- write_vec_element(s, tcg_rd, rd, i, size); +- } +- tcg_temp_free_i64(tcg_round); +- +- clear_vec_high(s, is_q, rd); ++ gen_gvec_fn2i(s, is_q, rd, rn, shift, gvec_fn, size); + } + + /* SHL/SLI - Vector shift left */ +-- +2.23.0 + diff --git a/target-arm-Update-contiguous-first-fault-and-no-faul.patch b/target-arm-Update-contiguous-first-fault-and-no-faul.patch new file mode 100644 index 0000000000000000000000000000000000000000..842cb2b238492ee58262bc00df14bdf084496171 --- /dev/null +++ b/target-arm-Update-contiguous-first-fault-and-no-faul.patch @@ -0,0 +1,450 @@ +From c647673ce4d72a8789703c62a7f3cbc732cb1ea8 Mon Sep 17 00:00:00 2001 +From: Richard Henderson +Date: Fri, 8 May 2020 08:43:54 -0700 +Subject: [PATCH 378/709] target/arm: Update contiguous first-fault and + no-fault loads + +With sve_cont_ldst_pages, the differences between first-fault and no-fault +are minimal, so unify the routines. With cpu_probe_watchpoint, we are able +to make progress through pages with TLB_WATCHPOINT set when the watchpoint +does not actually fire. + +Reviewed-by: Peter Maydell +Signed-off-by: Richard Henderson +Message-id: 20200508154359.7494-15-richard.henderson@linaro.org +Signed-off-by: Peter Maydell +--- + target/arm/sve_helper.c | 338 +++++++++++++++++++--------------------- + 1 file changed, 158 insertions(+), 180 deletions(-) + +diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c +index 9365e32646..f4969347d4 100644 +--- a/target/arm/sve_helper.c ++++ b/target/arm/sve_helper.c +@@ -4101,18 +4101,6 @@ static intptr_t find_next_active(uint64_t *vg, intptr_t reg_off, + return reg_off; + } + +-/* +- * Return the maximum offset <= @mem_max which is still within the page +- * referenced by @base + @mem_off. +- */ +-static intptr_t max_for_page(target_ulong base, intptr_t mem_off, +- intptr_t mem_max) +-{ +- target_ulong addr = base + mem_off; +- intptr_t split = -(intptr_t)(addr | TARGET_PAGE_MASK); +- return MIN(split, mem_max - mem_off) + mem_off; +-} +- + /* + * Resolve the guest virtual address to info->host and info->flags. + * If @nofault, return false if the page is invalid, otherwise +@@ -4435,19 +4423,6 @@ static void sve_cont_ldst_watchpoints(SVEContLdSt *info, CPUARMState *env, + #endif + } + +-/* +- * The result of tlb_vaddr_to_host for user-only is just g2h(x), +- * which is always non-null. Elide the useless test. +- */ +-static inline bool test_host_page(void *host) +-{ +-#ifdef CONFIG_USER_ONLY +- return true; +-#else +- return likely(host != NULL); +-#endif +-} +- + /* + * Common helper for all contiguous 1,2,3,4-register predicated stores. + */ +@@ -4705,167 +4680,167 @@ static void record_fault(CPUARMState *env, uintptr_t i, uintptr_t oprsz) + } + + /* +- * Common helper for all contiguous first-fault loads. ++ * Common helper for all contiguous no-fault and first-fault loads. + */ +-static void sve_ldff1_r(CPUARMState *env, void *vg, const target_ulong addr, +- uint32_t desc, const uintptr_t retaddr, +- const int esz, const int msz, +- sve_ldst1_host_fn *host_fn, +- sve_ldst1_tlb_fn *tlb_fn) ++static inline QEMU_ALWAYS_INLINE ++void sve_ldnfff1_r(CPUARMState *env, void *vg, const target_ulong addr, ++ uint32_t desc, const uintptr_t retaddr, ++ const int esz, const int msz, const SVEContFault fault, ++ sve_ldst1_host_fn *host_fn, ++ sve_ldst1_tlb_fn *tlb_fn) + { +- const TCGMemOpIdx oi = extract32(desc, SIMD_DATA_SHIFT, MEMOPIDX_SHIFT); +- const int mmu_idx = get_mmuidx(oi); + const unsigned rd = extract32(desc, SIMD_DATA_SHIFT + MEMOPIDX_SHIFT, 5); + void *vd = &env->vfp.zregs[rd]; +- const int diffsz = esz - msz; + const intptr_t reg_max = simd_oprsz(desc); +- const intptr_t mem_max = reg_max >> diffsz; +- intptr_t split, reg_off, mem_off, i; ++ intptr_t reg_off, mem_off, reg_last; ++ SVEContLdSt info; ++ int flags; + void *host; + +- /* Skip to the first active element. */ +- reg_off = find_next_active(vg, 0, reg_max, esz); +- if (unlikely(reg_off == reg_max)) { ++ /* Find the active elements. */ ++ if (!sve_cont_ldst_elements(&info, addr, vg, reg_max, esz, 1 << msz)) { + /* The entire predicate was false; no load occurs. */ + memset(vd, 0, reg_max); + return; + } +- mem_off = reg_off >> diffsz; ++ reg_off = info.reg_off_first[0]; + +- /* +- * If the (remaining) load is entirely within a single page, then: +- * For softmmu, and the tlb hits, then no faults will occur; +- * For user-only, either the first load will fault or none will. +- * We can thus perform the load directly to the destination and +- * Vd will be unmodified on any exception path. +- */ +- split = max_for_page(addr, mem_off, mem_max); +- if (likely(split == mem_max)) { +- host = tlb_vaddr_to_host(env, addr + mem_off, MMU_DATA_LOAD, mmu_idx); +- if (test_host_page(host)) { +- i = reg_off; +- host -= mem_off; +- do { +- host_fn(vd, i, host + (i >> diffsz)); +- i = find_next_active(vg, i + (1 << esz), reg_max, esz); +- } while (i < reg_max); +- /* After any fault, zero any leading inactive elements. */ ++ /* Probe the page(s). */ ++ if (!sve_cont_ldst_pages(&info, fault, env, addr, MMU_DATA_LOAD, retaddr)) { ++ /* Fault on first element. */ ++ tcg_debug_assert(fault == FAULT_NO); ++ memset(vd, 0, reg_max); ++ goto do_fault; ++ } ++ ++ mem_off = info.mem_off_first[0]; ++ flags = info.page[0].flags; ++ ++ if (fault == FAULT_FIRST) { ++ /* ++ * Special handling of the first active element, ++ * if it crosses a page boundary or is MMIO. ++ */ ++ bool is_split = mem_off == info.mem_off_split; ++ /* TODO: MTE check. */ ++ if (unlikely(flags != 0) || unlikely(is_split)) { ++ /* ++ * Use the slow path for cross-page handling. ++ * Might trap for MMIO or watchpoints. ++ */ ++ tlb_fn(env, vd, reg_off, addr + mem_off, retaddr); ++ ++ /* After any fault, zero the other elements. */ + swap_memzero(vd, reg_off); +- return; ++ reg_off += 1 << esz; ++ mem_off += 1 << msz; ++ swap_memzero(vd + reg_off, reg_max - reg_off); ++ ++ if (is_split) { ++ goto second_page; ++ } ++ } else { ++ memset(vd, 0, reg_max); ++ } ++ } else { ++ memset(vd, 0, reg_max); ++ if (unlikely(mem_off == info.mem_off_split)) { ++ /* The first active element crosses a page boundary. */ ++ flags |= info.page[1].flags; ++ if (unlikely(flags & TLB_MMIO)) { ++ /* Some page is MMIO, see below. */ ++ goto do_fault; ++ } ++ if (unlikely(flags & TLB_WATCHPOINT) && ++ (cpu_watchpoint_address_matches ++ (env_cpu(env), addr + mem_off, 1 << msz) ++ & BP_MEM_READ)) { ++ /* Watchpoint hit, see below. */ ++ goto do_fault; ++ } ++ /* TODO: MTE check. */ ++ /* ++ * Use the slow path for cross-page handling. ++ * This is RAM, without a watchpoint, and will not trap. ++ */ ++ tlb_fn(env, vd, reg_off, addr + mem_off, retaddr); ++ goto second_page; + } + } + + /* +- * Perform one normal read, which will fault or not. +- * But it is likely to bring the page into the tlb. ++ * From this point on, all memory operations are MemSingleNF. ++ * ++ * Per the MemSingleNF pseudocode, a no-fault load from Device memory ++ * must not actually hit the bus -- it returns (UNKNOWN, FAULT) instead. ++ * ++ * Unfortuately we do not have access to the memory attributes from the ++ * PTE to tell Device memory from Normal memory. So we make a mostly ++ * correct check, and indicate (UNKNOWN, FAULT) for any MMIO. ++ * This gives the right answer for the common cases of "Normal memory, ++ * backed by host RAM" and "Device memory, backed by MMIO". ++ * The architecture allows us to suppress an NF load and return ++ * (UNKNOWN, FAULT) for any reason, so our behaviour for the corner ++ * case of "Normal memory, backed by MMIO" is permitted. The case we ++ * get wrong is "Device memory, backed by host RAM", for which we ++ * should return (UNKNOWN, FAULT) for but do not. ++ * ++ * Similarly, CPU_BP breakpoints would raise exceptions, and so ++ * return (UNKNOWN, FAULT). For simplicity, we consider gdb and ++ * architectural breakpoints the same. + */ +- tlb_fn(env, vd, reg_off, addr + mem_off, retaddr); +- +- /* After any fault, zero any leading predicated false elts. */ +- swap_memzero(vd, reg_off); +- mem_off += 1 << msz; +- reg_off += 1 << esz; +- +- /* Try again to read the balance of the page. */ +- split = max_for_page(addr, mem_off - 1, mem_max); +- if (split >= (1 << msz)) { +- host = tlb_vaddr_to_host(env, addr + mem_off, MMU_DATA_LOAD, mmu_idx); +- if (host) { +- host -= mem_off; +- do { +- host_fn(vd, reg_off, host + mem_off); +- reg_off += 1 << esz; +- reg_off = find_next_active(vg, reg_off, reg_max, esz); +- mem_off = reg_off >> diffsz; +- } while (split - mem_off >= (1 << msz)); +- } ++ if (unlikely(flags & TLB_MMIO)) { ++ goto do_fault; + } + +- record_fault(env, reg_off, reg_max); +-} +- +-/* +- * Common helper for all contiguous no-fault loads. +- */ +-static void sve_ldnf1_r(CPUARMState *env, void *vg, const target_ulong addr, +- uint32_t desc, const int esz, const int msz, +- sve_ldst1_host_fn *host_fn) +-{ +- const unsigned rd = extract32(desc, SIMD_DATA_SHIFT + MEMOPIDX_SHIFT, 5); +- void *vd = &env->vfp.zregs[rd]; +- const int diffsz = esz - msz; +- const intptr_t reg_max = simd_oprsz(desc); +- const intptr_t mem_max = reg_max >> diffsz; +- const int mmu_idx = cpu_mmu_index(env, false); +- intptr_t split, reg_off, mem_off; +- void *host; ++ reg_last = info.reg_off_last[0]; ++ host = info.page[0].host; + +-#ifdef CONFIG_USER_ONLY +- host = tlb_vaddr_to_host(env, addr, MMU_DATA_LOAD, mmu_idx); +- if (likely(page_check_range(addr, mem_max, PAGE_READ) == 0)) { +- /* The entire operation is valid and will not fault. */ +- reg_off = 0; ++ do { ++ uint64_t pg = *(uint64_t *)(vg + (reg_off >> 3)); + do { +- mem_off = reg_off >> diffsz; +- host_fn(vd, reg_off, host + mem_off); ++ if ((pg >> (reg_off & 63)) & 1) { ++ if (unlikely(flags & TLB_WATCHPOINT) && ++ (cpu_watchpoint_address_matches ++ (env_cpu(env), addr + mem_off, 1 << msz) ++ & BP_MEM_READ)) { ++ goto do_fault; ++ } ++ /* TODO: MTE check. */ ++ host_fn(vd, reg_off, host + mem_off); ++ } + reg_off += 1 << esz; +- reg_off = find_next_active(vg, reg_off, reg_max, esz); +- } while (reg_off < reg_max); +- return; +- } +-#endif ++ mem_off += 1 << msz; ++ } while (reg_off <= reg_last && (reg_off & 63)); ++ } while (reg_off <= reg_last); + +- /* There will be no fault, so we may modify in advance. */ +- memset(vd, 0, reg_max); ++ /* ++ * MemSingleNF is allowed to fail for any reason. We have special ++ * code above to handle the first element crossing a page boundary. ++ * As an implementation choice, decline to handle a cross-page element ++ * in any other position. ++ */ ++ reg_off = info.reg_off_split; ++ if (reg_off >= 0) { ++ goto do_fault; ++ } + +- /* Skip to the first active element. */ +- reg_off = find_next_active(vg, 0, reg_max, esz); +- if (unlikely(reg_off == reg_max)) { +- /* The entire predicate was false; no load occurs. */ ++ second_page: ++ reg_off = info.reg_off_first[1]; ++ if (likely(reg_off < 0)) { ++ /* No active elements on the second page. All done. */ + return; + } +- mem_off = reg_off >> diffsz; + +-#ifdef CONFIG_USER_ONLY +- if (page_check_range(addr + mem_off, 1 << msz, PAGE_READ) == 0) { +- /* At least one load is valid; take the rest of the page. */ +- split = max_for_page(addr, mem_off + (1 << msz) - 1, mem_max); +- do { +- host_fn(vd, reg_off, host + mem_off); +- reg_off += 1 << esz; +- reg_off = find_next_active(vg, reg_off, reg_max, esz); +- mem_off = reg_off >> diffsz; +- } while (split - mem_off >= (1 << msz)); +- } +-#else + /* +- * If the address is not in the TLB, we have no way to bring the +- * entry into the TLB without also risking a fault. Note that +- * the corollary is that we never load from an address not in RAM. +- * +- * This last is out of spec, in a weird corner case. +- * Per the MemNF/MemSingleNF pseudocode, a NF load from Device memory +- * must not actually hit the bus -- it returns UNKNOWN data instead. +- * But if you map non-RAM with Normal memory attributes and do a NF +- * load then it should access the bus. (Nobody ought actually do this +- * in the real world, obviously.) +- * +- * Then there are the annoying special cases with watchpoints... +- * TODO: Add a form of non-faulting loads using cc->tlb_fill(probe=true). ++ * MemSingleNF is allowed to fail for any reason. As an implementation ++ * choice, decline to handle elements on the second page. This should ++ * be low frequency as the guest walks through memory -- the next ++ * iteration of the guest's loop should be aligned on the page boundary, ++ * and then all following iterations will stay aligned. + */ +- host = tlb_vaddr_to_host(env, addr + mem_off, MMU_DATA_LOAD, mmu_idx); +- split = max_for_page(addr, mem_off, mem_max); +- if (host && split >= (1 << msz)) { +- host -= mem_off; +- do { +- host_fn(vd, reg_off, host + mem_off); +- reg_off += 1 << esz; +- reg_off = find_next_active(vg, reg_off, reg_max, esz); +- mem_off = reg_off >> diffsz; +- } while (split - mem_off >= (1 << msz)); +- } +-#endif + ++ do_fault: + record_fault(env, reg_off, reg_max); + } + +@@ -4873,58 +4848,61 @@ static void sve_ldnf1_r(CPUARMState *env, void *vg, const target_ulong addr, + void HELPER(sve_ldff1##PART##_r)(CPUARMState *env, void *vg, \ + target_ulong addr, uint32_t desc) \ + { \ +- sve_ldff1_r(env, vg, addr, desc, GETPC(), ESZ, 0, \ +- sve_ld1##PART##_host, sve_ld1##PART##_tlb); \ ++ sve_ldnfff1_r(env, vg, addr, desc, GETPC(), ESZ, MO_8, FAULT_FIRST, \ ++ sve_ld1##PART##_host, sve_ld1##PART##_tlb); \ + } \ + void HELPER(sve_ldnf1##PART##_r)(CPUARMState *env, void *vg, \ + target_ulong addr, uint32_t desc) \ + { \ +- sve_ldnf1_r(env, vg, addr, desc, ESZ, 0, sve_ld1##PART##_host); \ ++ sve_ldnfff1_r(env, vg, addr, desc, GETPC(), ESZ, MO_8, FAULT_NO, \ ++ sve_ld1##PART##_host, sve_ld1##PART##_tlb); \ + } + + #define DO_LDFF1_LDNF1_2(PART, ESZ, MSZ) \ + void HELPER(sve_ldff1##PART##_le_r)(CPUARMState *env, void *vg, \ + target_ulong addr, uint32_t desc) \ + { \ +- sve_ldff1_r(env, vg, addr, desc, GETPC(), ESZ, MSZ, \ +- sve_ld1##PART##_le_host, sve_ld1##PART##_le_tlb); \ ++ sve_ldnfff1_r(env, vg, addr, desc, GETPC(), ESZ, MSZ, FAULT_FIRST, \ ++ sve_ld1##PART##_le_host, sve_ld1##PART##_le_tlb); \ + } \ + void HELPER(sve_ldnf1##PART##_le_r)(CPUARMState *env, void *vg, \ + target_ulong addr, uint32_t desc) \ + { \ +- sve_ldnf1_r(env, vg, addr, desc, ESZ, MSZ, sve_ld1##PART##_le_host); \ ++ sve_ldnfff1_r(env, vg, addr, desc, GETPC(), ESZ, MSZ, FAULT_NO, \ ++ sve_ld1##PART##_le_host, sve_ld1##PART##_le_tlb); \ + } \ + void HELPER(sve_ldff1##PART##_be_r)(CPUARMState *env, void *vg, \ + target_ulong addr, uint32_t desc) \ + { \ +- sve_ldff1_r(env, vg, addr, desc, GETPC(), ESZ, MSZ, \ +- sve_ld1##PART##_be_host, sve_ld1##PART##_be_tlb); \ ++ sve_ldnfff1_r(env, vg, addr, desc, GETPC(), ESZ, MSZ, FAULT_FIRST, \ ++ sve_ld1##PART##_be_host, sve_ld1##PART##_be_tlb); \ + } \ + void HELPER(sve_ldnf1##PART##_be_r)(CPUARMState *env, void *vg, \ + target_ulong addr, uint32_t desc) \ + { \ +- sve_ldnf1_r(env, vg, addr, desc, ESZ, MSZ, sve_ld1##PART##_be_host); \ ++ sve_ldnfff1_r(env, vg, addr, desc, GETPC(), ESZ, MSZ, FAULT_NO, \ ++ sve_ld1##PART##_be_host, sve_ld1##PART##_be_tlb); \ + } + +-DO_LDFF1_LDNF1_1(bb, 0) +-DO_LDFF1_LDNF1_1(bhu, 1) +-DO_LDFF1_LDNF1_1(bhs, 1) +-DO_LDFF1_LDNF1_1(bsu, 2) +-DO_LDFF1_LDNF1_1(bss, 2) +-DO_LDFF1_LDNF1_1(bdu, 3) +-DO_LDFF1_LDNF1_1(bds, 3) ++DO_LDFF1_LDNF1_1(bb, MO_8) ++DO_LDFF1_LDNF1_1(bhu, MO_16) ++DO_LDFF1_LDNF1_1(bhs, MO_16) ++DO_LDFF1_LDNF1_1(bsu, MO_32) ++DO_LDFF1_LDNF1_1(bss, MO_32) ++DO_LDFF1_LDNF1_1(bdu, MO_64) ++DO_LDFF1_LDNF1_1(bds, MO_64) + +-DO_LDFF1_LDNF1_2(hh, 1, 1) +-DO_LDFF1_LDNF1_2(hsu, 2, 1) +-DO_LDFF1_LDNF1_2(hss, 2, 1) +-DO_LDFF1_LDNF1_2(hdu, 3, 1) +-DO_LDFF1_LDNF1_2(hds, 3, 1) ++DO_LDFF1_LDNF1_2(hh, MO_16, MO_16) ++DO_LDFF1_LDNF1_2(hsu, MO_32, MO_16) ++DO_LDFF1_LDNF1_2(hss, MO_32, MO_16) ++DO_LDFF1_LDNF1_2(hdu, MO_64, MO_16) ++DO_LDFF1_LDNF1_2(hds, MO_64, MO_16) + +-DO_LDFF1_LDNF1_2(ss, 2, 2) +-DO_LDFF1_LDNF1_2(sdu, 3, 2) +-DO_LDFF1_LDNF1_2(sds, 3, 2) ++DO_LDFF1_LDNF1_2(ss, MO_32, MO_32) ++DO_LDFF1_LDNF1_2(sdu, MO_64, MO_32) ++DO_LDFF1_LDNF1_2(sds, MO_64, MO_32) + +-DO_LDFF1_LDNF1_2(dd, 3, 3) ++DO_LDFF1_LDNF1_2(dd, MO_64, MO_64) + + #undef DO_LDFF1_LDNF1_1 + #undef DO_LDFF1_LDNF1_2 +-- +2.23.0 + diff --git a/target-arm-Use-SVEContLdSt-for-contiguous-stores.patch b/target-arm-Use-SVEContLdSt-for-contiguous-stores.patch new file mode 100644 index 0000000000000000000000000000000000000000..06c95363987aa363654475004df1d370d177949a --- /dev/null +++ b/target-arm-Use-SVEContLdSt-for-contiguous-stores.patch @@ -0,0 +1,349 @@ +From 0fa476c1bb37a70df7eeff1e5bfb4791feb37e0e Mon Sep 17 00:00:00 2001 +From: Richard Henderson +Date: Fri, 8 May 2020 08:43:55 -0700 +Subject: [PATCH 379/709] target/arm: Use SVEContLdSt for contiguous stores + +Follow the model set up for contiguous loads. This handles +watchpoints correctly for contiguous stores, recognizing the +exception before any changes to memory. + +Reviewed-by: Peter Maydell +Signed-off-by: Richard Henderson +Message-id: 20200508154359.7494-16-richard.henderson@linaro.org +Signed-off-by: Peter Maydell +--- + target/arm/sve_helper.c | 271 ++++++++++++++++++++++------------------ + 1 file changed, 152 insertions(+), 119 deletions(-) + +diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c +index f4969347d4..4ed9bbe1ee 100644 +--- a/target/arm/sve_helper.c ++++ b/target/arm/sve_helper.c +@@ -3995,6 +3995,10 @@ static void sve_##NAME##_host(void *vd, intptr_t reg_off, void *host) \ + *(TYPEE *)(vd + H(reg_off)) = val; \ + } + ++#define DO_ST_HOST(NAME, H, TYPEE, TYPEM, HOST) \ ++static void sve_##NAME##_host(void *vd, intptr_t reg_off, void *host) \ ++{ HOST(host, (TYPEM)*(TYPEE *)(vd + H(reg_off))); } ++ + #define DO_LD_TLB(NAME, H, TYPEE, TYPEM, TLB) \ + static void sve_##NAME##_tlb(CPUARMState *env, void *vd, intptr_t reg_off, \ + target_ulong addr, uintptr_t ra) \ +@@ -4022,6 +4026,7 @@ DO_LD_PRIM_1(ld1bdu, , uint64_t, uint8_t) + DO_LD_PRIM_1(ld1bds, , uint64_t, int8_t) + + #define DO_ST_PRIM_1(NAME, H, TE, TM) \ ++ DO_ST_HOST(st1##NAME, H, TE, TM, stb_p) \ + DO_ST_TLB(st1##NAME, H, TE, TM, cpu_stb_data_ra) + + DO_ST_PRIM_1(bb, H1, uint8_t, uint8_t) +@@ -4036,6 +4041,8 @@ DO_ST_PRIM_1(bd, , uint64_t, uint8_t) + DO_LD_TLB(ld1##NAME##_le, H, TE, TM, cpu_##LD##_le_data_ra) + + #define DO_ST_PRIM_2(NAME, H, TE, TM, ST) \ ++ DO_ST_HOST(st1##NAME##_be, H, TE, TM, ST##_be_p) \ ++ DO_ST_HOST(st1##NAME##_le, H, TE, TM, ST##_le_p) \ + DO_ST_TLB(st1##NAME##_be, H, TE, TM, cpu_##ST##_be_data_ra) \ + DO_ST_TLB(st1##NAME##_le, H, TE, TM, cpu_##ST##_le_data_ra) + +@@ -4908,151 +4915,177 @@ DO_LDFF1_LDNF1_2(dd, MO_64, MO_64) + #undef DO_LDFF1_LDNF1_2 + + /* +- * Common helpers for all contiguous 1,2,3,4-register predicated stores. ++ * Common helper for all contiguous 1,2,3,4-register predicated stores. + */ +-static void sve_st1_r(CPUARMState *env, void *vg, target_ulong addr, +- uint32_t desc, const uintptr_t ra, +- const int esize, const int msize, +- sve_ldst1_tlb_fn *tlb_fn) ++ ++static inline QEMU_ALWAYS_INLINE ++void sve_stN_r(CPUARMState *env, uint64_t *vg, target_ulong addr, uint32_t desc, ++ const uintptr_t retaddr, const int esz, ++ const int msz, const int N, ++ sve_ldst1_host_fn *host_fn, ++ sve_ldst1_tlb_fn *tlb_fn) + { + const unsigned rd = extract32(desc, SIMD_DATA_SHIFT + MEMOPIDX_SHIFT, 5); +- intptr_t i, oprsz = simd_oprsz(desc); +- void *vd = &env->vfp.zregs[rd]; ++ const intptr_t reg_max = simd_oprsz(desc); ++ intptr_t reg_off, reg_last, mem_off; ++ SVEContLdSt info; ++ void *host; ++ int i, flags; + +- for (i = 0; i < oprsz; ) { +- uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3)); +- do { +- if (pg & 1) { +- tlb_fn(env, vd, i, addr, ra); +- } +- i += esize, pg >>= esize; +- addr += msize; +- } while (i & 15); ++ /* Find the active elements. */ ++ if (!sve_cont_ldst_elements(&info, addr, vg, reg_max, esz, N << msz)) { ++ /* The entire predicate was false; no store occurs. */ ++ return; + } +-} + +-static void sve_st2_r(CPUARMState *env, void *vg, target_ulong addr, +- uint32_t desc, const uintptr_t ra, +- const int esize, const int msize, +- sve_ldst1_tlb_fn *tlb_fn) +-{ +- const unsigned rd = extract32(desc, SIMD_DATA_SHIFT + MEMOPIDX_SHIFT, 5); +- intptr_t i, oprsz = simd_oprsz(desc); +- void *d1 = &env->vfp.zregs[rd]; +- void *d2 = &env->vfp.zregs[(rd + 1) & 31]; ++ /* Probe the page(s). Exit with exception for any invalid page. */ ++ sve_cont_ldst_pages(&info, FAULT_ALL, env, addr, MMU_DATA_STORE, retaddr); + +- for (i = 0; i < oprsz; ) { +- uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3)); +- do { +- if (pg & 1) { +- tlb_fn(env, d1, i, addr, ra); +- tlb_fn(env, d2, i, addr + msize, ra); ++ /* Handle watchpoints for all active elements. */ ++ sve_cont_ldst_watchpoints(&info, env, vg, addr, 1 << esz, N << msz, ++ BP_MEM_WRITE, retaddr); ++ ++ /* TODO: MTE check. */ ++ ++ flags = info.page[0].flags | info.page[1].flags; ++ if (unlikely(flags != 0)) { ++#ifdef CONFIG_USER_ONLY ++ g_assert_not_reached(); ++#else ++ /* ++ * At least one page includes MMIO. ++ * Any bus operation can fail with cpu_transaction_failed, ++ * which for ARM will raise SyncExternal. We cannot avoid ++ * this fault and will leave with the store incomplete. ++ */ ++ mem_off = info.mem_off_first[0]; ++ reg_off = info.reg_off_first[0]; ++ reg_last = info.reg_off_last[1]; ++ if (reg_last < 0) { ++ reg_last = info.reg_off_split; ++ if (reg_last < 0) { ++ reg_last = info.reg_off_last[0]; + } +- i += esize, pg >>= esize; +- addr += 2 * msize; +- } while (i & 15); ++ } ++ ++ do { ++ uint64_t pg = vg[reg_off >> 6]; ++ do { ++ if ((pg >> (reg_off & 63)) & 1) { ++ for (i = 0; i < N; ++i) { ++ tlb_fn(env, &env->vfp.zregs[(rd + i) & 31], reg_off, ++ addr + mem_off + (i << msz), retaddr); ++ } ++ } ++ reg_off += 1 << esz; ++ mem_off += N << msz; ++ } while (reg_off & 63); ++ } while (reg_off <= reg_last); ++ return; ++#endif + } +-} + +-static void sve_st3_r(CPUARMState *env, void *vg, target_ulong addr, +- uint32_t desc, const uintptr_t ra, +- const int esize, const int msize, +- sve_ldst1_tlb_fn *tlb_fn) +-{ +- const unsigned rd = extract32(desc, SIMD_DATA_SHIFT + MEMOPIDX_SHIFT, 5); +- intptr_t i, oprsz = simd_oprsz(desc); +- void *d1 = &env->vfp.zregs[rd]; +- void *d2 = &env->vfp.zregs[(rd + 1) & 31]; +- void *d3 = &env->vfp.zregs[(rd + 2) & 31]; ++ mem_off = info.mem_off_first[0]; ++ reg_off = info.reg_off_first[0]; ++ reg_last = info.reg_off_last[0]; ++ host = info.page[0].host; + +- for (i = 0; i < oprsz; ) { +- uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3)); ++ while (reg_off <= reg_last) { ++ uint64_t pg = vg[reg_off >> 6]; + do { +- if (pg & 1) { +- tlb_fn(env, d1, i, addr, ra); +- tlb_fn(env, d2, i, addr + msize, ra); +- tlb_fn(env, d3, i, addr + 2 * msize, ra); ++ if ((pg >> (reg_off & 63)) & 1) { ++ for (i = 0; i < N; ++i) { ++ host_fn(&env->vfp.zregs[(rd + i) & 31], reg_off, ++ host + mem_off + (i << msz)); ++ } + } +- i += esize, pg >>= esize; +- addr += 3 * msize; +- } while (i & 15); ++ reg_off += 1 << esz; ++ mem_off += N << msz; ++ } while (reg_off <= reg_last && (reg_off & 63)); + } +-} + +-static void sve_st4_r(CPUARMState *env, void *vg, target_ulong addr, +- uint32_t desc, const uintptr_t ra, +- const int esize, const int msize, +- sve_ldst1_tlb_fn *tlb_fn) +-{ +- const unsigned rd = extract32(desc, SIMD_DATA_SHIFT + MEMOPIDX_SHIFT, 5); +- intptr_t i, oprsz = simd_oprsz(desc); +- void *d1 = &env->vfp.zregs[rd]; +- void *d2 = &env->vfp.zregs[(rd + 1) & 31]; +- void *d3 = &env->vfp.zregs[(rd + 2) & 31]; +- void *d4 = &env->vfp.zregs[(rd + 3) & 31]; ++ /* ++ * Use the slow path to manage the cross-page misalignment. ++ * But we know this is RAM and cannot trap. ++ */ ++ mem_off = info.mem_off_split; ++ if (unlikely(mem_off >= 0)) { ++ reg_off = info.reg_off_split; ++ for (i = 0; i < N; ++i) { ++ tlb_fn(env, &env->vfp.zregs[(rd + i) & 31], reg_off, ++ addr + mem_off + (i << msz), retaddr); ++ } ++ } ++ ++ mem_off = info.mem_off_first[1]; ++ if (unlikely(mem_off >= 0)) { ++ reg_off = info.reg_off_first[1]; ++ reg_last = info.reg_off_last[1]; ++ host = info.page[1].host; + +- for (i = 0; i < oprsz; ) { +- uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3)); + do { +- if (pg & 1) { +- tlb_fn(env, d1, i, addr, ra); +- tlb_fn(env, d2, i, addr + msize, ra); +- tlb_fn(env, d3, i, addr + 2 * msize, ra); +- tlb_fn(env, d4, i, addr + 3 * msize, ra); +- } +- i += esize, pg >>= esize; +- addr += 4 * msize; +- } while (i & 15); ++ uint64_t pg = vg[reg_off >> 6]; ++ do { ++ if ((pg >> (reg_off & 63)) & 1) { ++ for (i = 0; i < N; ++i) { ++ host_fn(&env->vfp.zregs[(rd + i) & 31], reg_off, ++ host + mem_off + (i << msz)); ++ } ++ } ++ reg_off += 1 << esz; ++ mem_off += N << msz; ++ } while (reg_off & 63); ++ } while (reg_off <= reg_last); + } + } + +-#define DO_STN_1(N, NAME, ESIZE) \ +-void QEMU_FLATTEN HELPER(sve_st##N##NAME##_r) \ +- (CPUARMState *env, void *vg, target_ulong addr, uint32_t desc) \ ++#define DO_STN_1(N, NAME, ESZ) \ ++void HELPER(sve_st##N##NAME##_r)(CPUARMState *env, void *vg, \ ++ target_ulong addr, uint32_t desc) \ + { \ +- sve_st##N##_r(env, vg, addr, desc, GETPC(), ESIZE, 1, \ +- sve_st1##NAME##_tlb); \ ++ sve_stN_r(env, vg, addr, desc, GETPC(), ESZ, MO_8, N, \ ++ sve_st1##NAME##_host, sve_st1##NAME##_tlb); \ + } + +-#define DO_STN_2(N, NAME, ESIZE, MSIZE) \ +-void QEMU_FLATTEN HELPER(sve_st##N##NAME##_le_r) \ +- (CPUARMState *env, void *vg, target_ulong addr, uint32_t desc) \ ++#define DO_STN_2(N, NAME, ESZ, MSZ) \ ++void HELPER(sve_st##N##NAME##_le_r)(CPUARMState *env, void *vg, \ ++ target_ulong addr, uint32_t desc) \ + { \ +- sve_st##N##_r(env, vg, addr, desc, GETPC(), ESIZE, MSIZE, \ +- sve_st1##NAME##_le_tlb); \ ++ sve_stN_r(env, vg, addr, desc, GETPC(), ESZ, MSZ, N, \ ++ sve_st1##NAME##_le_host, sve_st1##NAME##_le_tlb); \ + } \ +-void QEMU_FLATTEN HELPER(sve_st##N##NAME##_be_r) \ +- (CPUARMState *env, void *vg, target_ulong addr, uint32_t desc) \ ++void HELPER(sve_st##N##NAME##_be_r)(CPUARMState *env, void *vg, \ ++ target_ulong addr, uint32_t desc) \ + { \ +- sve_st##N##_r(env, vg, addr, desc, GETPC(), ESIZE, MSIZE, \ +- sve_st1##NAME##_be_tlb); \ +-} +- +-DO_STN_1(1, bb, 1) +-DO_STN_1(1, bh, 2) +-DO_STN_1(1, bs, 4) +-DO_STN_1(1, bd, 8) +-DO_STN_1(2, bb, 1) +-DO_STN_1(3, bb, 1) +-DO_STN_1(4, bb, 1) +- +-DO_STN_2(1, hh, 2, 2) +-DO_STN_2(1, hs, 4, 2) +-DO_STN_2(1, hd, 8, 2) +-DO_STN_2(2, hh, 2, 2) +-DO_STN_2(3, hh, 2, 2) +-DO_STN_2(4, hh, 2, 2) +- +-DO_STN_2(1, ss, 4, 4) +-DO_STN_2(1, sd, 8, 4) +-DO_STN_2(2, ss, 4, 4) +-DO_STN_2(3, ss, 4, 4) +-DO_STN_2(4, ss, 4, 4) +- +-DO_STN_2(1, dd, 8, 8) +-DO_STN_2(2, dd, 8, 8) +-DO_STN_2(3, dd, 8, 8) +-DO_STN_2(4, dd, 8, 8) ++ sve_stN_r(env, vg, addr, desc, GETPC(), ESZ, MSZ, N, \ ++ sve_st1##NAME##_be_host, sve_st1##NAME##_be_tlb); \ ++} ++ ++DO_STN_1(1, bb, MO_8) ++DO_STN_1(1, bh, MO_16) ++DO_STN_1(1, bs, MO_32) ++DO_STN_1(1, bd, MO_64) ++DO_STN_1(2, bb, MO_8) ++DO_STN_1(3, bb, MO_8) ++DO_STN_1(4, bb, MO_8) ++ ++DO_STN_2(1, hh, MO_16, MO_16) ++DO_STN_2(1, hs, MO_32, MO_16) ++DO_STN_2(1, hd, MO_64, MO_16) ++DO_STN_2(2, hh, MO_16, MO_16) ++DO_STN_2(3, hh, MO_16, MO_16) ++DO_STN_2(4, hh, MO_16, MO_16) ++ ++DO_STN_2(1, ss, MO_32, MO_32) ++DO_STN_2(1, sd, MO_64, MO_32) ++DO_STN_2(2, ss, MO_32, MO_32) ++DO_STN_2(3, ss, MO_32, MO_32) ++DO_STN_2(4, ss, MO_32, MO_32) ++ ++DO_STN_2(1, dd, MO_64, MO_64) ++DO_STN_2(2, dd, MO_64, MO_64) ++DO_STN_2(3, dd, MO_64, MO_64) ++DO_STN_2(4, dd, MO_64, MO_64) + + #undef DO_STN_1 + #undef DO_STN_2 +-- +2.23.0 + diff --git a/target-arm-Use-SVEContLdSt-for-multi-register-contig.patch b/target-arm-Use-SVEContLdSt-for-multi-register-contig.patch new file mode 100644 index 0000000000000000000000000000000000000000..41c3bcbc0b237ea55b0d08d874648e99eb94f5e2 --- /dev/null +++ b/target-arm-Use-SVEContLdSt-for-multi-register-contig.patch @@ -0,0 +1,366 @@ +From 5c9b8458a0b3008d24d84b67e1c9b6d5f39f4d66 Mon Sep 17 00:00:00 2001 +From: Richard Henderson +Date: Fri, 8 May 2020 08:43:53 -0700 +Subject: [PATCH 377/709] target/arm: Use SVEContLdSt for multi-register + contiguous loads + +Reviewed-by: Peter Maydell +Signed-off-by: Richard Henderson +Message-id: 20200508154359.7494-14-richard.henderson@linaro.org +Signed-off-by: Peter Maydell +--- + target/arm/sve_helper.c | 223 ++++++++++++++-------------------------- + 1 file changed, 79 insertions(+), 144 deletions(-) + +diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c +index 7992a569b0..9365e32646 100644 +--- a/target/arm/sve_helper.c ++++ b/target/arm/sve_helper.c +@@ -4449,27 +4449,28 @@ static inline bool test_host_page(void *host) + } + + /* +- * Common helper for all contiguous one-register predicated loads. ++ * Common helper for all contiguous 1,2,3,4-register predicated stores. + */ + static inline QEMU_ALWAYS_INLINE +-void sve_ld1_r(CPUARMState *env, uint64_t *vg, const target_ulong addr, ++void sve_ldN_r(CPUARMState *env, uint64_t *vg, const target_ulong addr, + uint32_t desc, const uintptr_t retaddr, +- const int esz, const int msz, ++ const int esz, const int msz, const int N, + sve_ldst1_host_fn *host_fn, + sve_ldst1_tlb_fn *tlb_fn) + { + const unsigned rd = extract32(desc, SIMD_DATA_SHIFT + MEMOPIDX_SHIFT, 5); +- void *vd = &env->vfp.zregs[rd]; + const intptr_t reg_max = simd_oprsz(desc); + intptr_t reg_off, reg_last, mem_off; + SVEContLdSt info; + void *host; +- int flags; ++ int flags, i; + + /* Find the active elements. */ +- if (!sve_cont_ldst_elements(&info, addr, vg, reg_max, esz, 1 << msz)) { ++ if (!sve_cont_ldst_elements(&info, addr, vg, reg_max, esz, N << msz)) { + /* The entire predicate was false; no load occurs. */ +- memset(vd, 0, reg_max); ++ for (i = 0; i < N; ++i) { ++ memset(&env->vfp.zregs[(rd + i) & 31], 0, reg_max); ++ } + return; + } + +@@ -4477,7 +4478,7 @@ void sve_ld1_r(CPUARMState *env, uint64_t *vg, const target_ulong addr, + sve_cont_ldst_pages(&info, FAULT_ALL, env, addr, MMU_DATA_LOAD, retaddr); + + /* Handle watchpoints for all active elements. */ +- sve_cont_ldst_watchpoints(&info, env, vg, addr, 1 << esz, 1 << msz, ++ sve_cont_ldst_watchpoints(&info, env, vg, addr, 1 << esz, N << msz, + BP_MEM_READ, retaddr); + + /* TODO: MTE check. */ +@@ -4493,9 +4494,8 @@ void sve_ld1_r(CPUARMState *env, uint64_t *vg, const target_ulong addr, + * which for ARM will raise SyncExternal. Perform the load + * into scratch memory to preserve register state until the end. + */ +- ARMVectorReg scratch; ++ ARMVectorReg scratch[4] = { }; + +- memset(&scratch, 0, reg_max); + mem_off = info.mem_off_first[0]; + reg_off = info.reg_off_first[0]; + reg_last = info.reg_off_last[1]; +@@ -4510,21 +4510,29 @@ void sve_ld1_r(CPUARMState *env, uint64_t *vg, const target_ulong addr, + uint64_t pg = vg[reg_off >> 6]; + do { + if ((pg >> (reg_off & 63)) & 1) { +- tlb_fn(env, &scratch, reg_off, addr + mem_off, retaddr); ++ for (i = 0; i < N; ++i) { ++ tlb_fn(env, &scratch[i], reg_off, ++ addr + mem_off + (i << msz), retaddr); ++ } + } + reg_off += 1 << esz; +- mem_off += 1 << msz; ++ mem_off += N << msz; + } while (reg_off & 63); + } while (reg_off <= reg_last); + +- memcpy(vd, &scratch, reg_max); ++ for (i = 0; i < N; ++i) { ++ memcpy(&env->vfp.zregs[(rd + i) & 31], &scratch[i], reg_max); ++ } + return; + #endif + } + + /* The entire operation is in RAM, on valid pages. */ + +- memset(vd, 0, reg_max); ++ for (i = 0; i < N; ++i) { ++ memset(&env->vfp.zregs[(rd + i) & 31], 0, reg_max); ++ } ++ + mem_off = info.mem_off_first[0]; + reg_off = info.reg_off_first[0]; + reg_last = info.reg_off_last[0]; +@@ -4534,10 +4542,13 @@ void sve_ld1_r(CPUARMState *env, uint64_t *vg, const target_ulong addr, + uint64_t pg = vg[reg_off >> 6]; + do { + if ((pg >> (reg_off & 63)) & 1) { +- host_fn(vd, reg_off, host + mem_off); ++ for (i = 0; i < N; ++i) { ++ host_fn(&env->vfp.zregs[(rd + i) & 31], reg_off, ++ host + mem_off + (i << msz)); ++ } + } + reg_off += 1 << esz; +- mem_off += 1 << msz; ++ mem_off += N << msz; + } while (reg_off <= reg_last && (reg_off & 63)); + } + +@@ -4547,7 +4558,11 @@ void sve_ld1_r(CPUARMState *env, uint64_t *vg, const target_ulong addr, + */ + mem_off = info.mem_off_split; + if (unlikely(mem_off >= 0)) { +- tlb_fn(env, vd, info.reg_off_split, addr + mem_off, retaddr); ++ reg_off = info.reg_off_split; ++ for (i = 0; i < N; ++i) { ++ tlb_fn(env, &env->vfp.zregs[(rd + i) & 31], reg_off, ++ addr + mem_off + (i << msz), retaddr); ++ } + } + + mem_off = info.mem_off_first[1]; +@@ -4560,10 +4575,13 @@ void sve_ld1_r(CPUARMState *env, uint64_t *vg, const target_ulong addr, + uint64_t pg = vg[reg_off >> 6]; + do { + if ((pg >> (reg_off & 63)) & 1) { +- host_fn(vd, reg_off, host + mem_off); ++ for (i = 0; i < N; ++i) { ++ host_fn(&env->vfp.zregs[(rd + i) & 31], reg_off, ++ host + mem_off + (i << msz)); ++ } + } + reg_off += 1 << esz; +- mem_off += 1 << msz; ++ mem_off += N << msz; + } while (reg_off & 63); + } while (reg_off <= reg_last); + } +@@ -4573,7 +4591,7 @@ void sve_ld1_r(CPUARMState *env, uint64_t *vg, const target_ulong addr, + void HELPER(sve_##NAME##_r)(CPUARMState *env, void *vg, \ + target_ulong addr, uint32_t desc) \ + { \ +- sve_ld1_r(env, vg, addr, desc, GETPC(), ESZ, 0, \ ++ sve_ldN_r(env, vg, addr, desc, GETPC(), ESZ, MO_8, 1, \ + sve_##NAME##_host, sve_##NAME##_tlb); \ + } + +@@ -4581,159 +4599,76 @@ void HELPER(sve_##NAME##_r)(CPUARMState *env, void *vg, \ + void HELPER(sve_##NAME##_le_r)(CPUARMState *env, void *vg, \ + target_ulong addr, uint32_t desc) \ + { \ +- sve_ld1_r(env, vg, addr, desc, GETPC(), ESZ, MSZ, \ ++ sve_ldN_r(env, vg, addr, desc, GETPC(), ESZ, MSZ, 1, \ + sve_##NAME##_le_host, sve_##NAME##_le_tlb); \ + } \ + void HELPER(sve_##NAME##_be_r)(CPUARMState *env, void *vg, \ + target_ulong addr, uint32_t desc) \ + { \ +- sve_ld1_r(env, vg, addr, desc, GETPC(), ESZ, MSZ, \ ++ sve_ldN_r(env, vg, addr, desc, GETPC(), ESZ, MSZ, 1, \ + sve_##NAME##_be_host, sve_##NAME##_be_tlb); \ + } + +-DO_LD1_1(ld1bb, 0) +-DO_LD1_1(ld1bhu, 1) +-DO_LD1_1(ld1bhs, 1) +-DO_LD1_1(ld1bsu, 2) +-DO_LD1_1(ld1bss, 2) +-DO_LD1_1(ld1bdu, 3) +-DO_LD1_1(ld1bds, 3) ++DO_LD1_1(ld1bb, MO_8) ++DO_LD1_1(ld1bhu, MO_16) ++DO_LD1_1(ld1bhs, MO_16) ++DO_LD1_1(ld1bsu, MO_32) ++DO_LD1_1(ld1bss, MO_32) ++DO_LD1_1(ld1bdu, MO_64) ++DO_LD1_1(ld1bds, MO_64) + +-DO_LD1_2(ld1hh, 1, 1) +-DO_LD1_2(ld1hsu, 2, 1) +-DO_LD1_2(ld1hss, 2, 1) +-DO_LD1_2(ld1hdu, 3, 1) +-DO_LD1_2(ld1hds, 3, 1) ++DO_LD1_2(ld1hh, MO_16, MO_16) ++DO_LD1_2(ld1hsu, MO_32, MO_16) ++DO_LD1_2(ld1hss, MO_32, MO_16) ++DO_LD1_2(ld1hdu, MO_64, MO_16) ++DO_LD1_2(ld1hds, MO_64, MO_16) + +-DO_LD1_2(ld1ss, 2, 2) +-DO_LD1_2(ld1sdu, 3, 2) +-DO_LD1_2(ld1sds, 3, 2) ++DO_LD1_2(ld1ss, MO_32, MO_32) ++DO_LD1_2(ld1sdu, MO_64, MO_32) ++DO_LD1_2(ld1sds, MO_64, MO_32) + +-DO_LD1_2(ld1dd, 3, 3) ++DO_LD1_2(ld1dd, MO_64, MO_64) + + #undef DO_LD1_1 + #undef DO_LD1_2 + +-/* +- * Common helpers for all contiguous 2,3,4-register predicated loads. +- */ +-static void sve_ld2_r(CPUARMState *env, void *vg, target_ulong addr, +- uint32_t desc, int size, uintptr_t ra, +- sve_ldst1_tlb_fn *tlb_fn) +-{ +- const unsigned rd = extract32(desc, SIMD_DATA_SHIFT + MEMOPIDX_SHIFT, 5); +- intptr_t i, oprsz = simd_oprsz(desc); +- ARMVectorReg scratch[2] = { }; +- +- for (i = 0; i < oprsz; ) { +- uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3)); +- do { +- if (pg & 1) { +- tlb_fn(env, &scratch[0], i, addr, ra); +- tlb_fn(env, &scratch[1], i, addr + size, ra); +- } +- i += size, pg >>= size; +- addr += 2 * size; +- } while (i & 15); +- } +- +- /* Wait until all exceptions have been raised to write back. */ +- memcpy(&env->vfp.zregs[rd], &scratch[0], oprsz); +- memcpy(&env->vfp.zregs[(rd + 1) & 31], &scratch[1], oprsz); +-} +- +-static void sve_ld3_r(CPUARMState *env, void *vg, target_ulong addr, +- uint32_t desc, int size, uintptr_t ra, +- sve_ldst1_tlb_fn *tlb_fn) +-{ +- const unsigned rd = extract32(desc, SIMD_DATA_SHIFT + MEMOPIDX_SHIFT, 5); +- intptr_t i, oprsz = simd_oprsz(desc); +- ARMVectorReg scratch[3] = { }; +- +- for (i = 0; i < oprsz; ) { +- uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3)); +- do { +- if (pg & 1) { +- tlb_fn(env, &scratch[0], i, addr, ra); +- tlb_fn(env, &scratch[1], i, addr + size, ra); +- tlb_fn(env, &scratch[2], i, addr + 2 * size, ra); +- } +- i += size, pg >>= size; +- addr += 3 * size; +- } while (i & 15); +- } +- +- /* Wait until all exceptions have been raised to write back. */ +- memcpy(&env->vfp.zregs[rd], &scratch[0], oprsz); +- memcpy(&env->vfp.zregs[(rd + 1) & 31], &scratch[1], oprsz); +- memcpy(&env->vfp.zregs[(rd + 2) & 31], &scratch[2], oprsz); +-} +- +-static void sve_ld4_r(CPUARMState *env, void *vg, target_ulong addr, +- uint32_t desc, int size, uintptr_t ra, +- sve_ldst1_tlb_fn *tlb_fn) +-{ +- const unsigned rd = extract32(desc, SIMD_DATA_SHIFT + MEMOPIDX_SHIFT, 5); +- intptr_t i, oprsz = simd_oprsz(desc); +- ARMVectorReg scratch[4] = { }; +- +- for (i = 0; i < oprsz; ) { +- uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3)); +- do { +- if (pg & 1) { +- tlb_fn(env, &scratch[0], i, addr, ra); +- tlb_fn(env, &scratch[1], i, addr + size, ra); +- tlb_fn(env, &scratch[2], i, addr + 2 * size, ra); +- tlb_fn(env, &scratch[3], i, addr + 3 * size, ra); +- } +- i += size, pg >>= size; +- addr += 4 * size; +- } while (i & 15); +- } +- +- /* Wait until all exceptions have been raised to write back. */ +- memcpy(&env->vfp.zregs[rd], &scratch[0], oprsz); +- memcpy(&env->vfp.zregs[(rd + 1) & 31], &scratch[1], oprsz); +- memcpy(&env->vfp.zregs[(rd + 2) & 31], &scratch[2], oprsz); +- memcpy(&env->vfp.zregs[(rd + 3) & 31], &scratch[3], oprsz); +-} +- + #define DO_LDN_1(N) \ +-void QEMU_FLATTEN HELPER(sve_ld##N##bb_r) \ +- (CPUARMState *env, void *vg, target_ulong addr, uint32_t desc) \ +-{ \ +- sve_ld##N##_r(env, vg, addr, desc, 1, GETPC(), sve_ld1bb_tlb); \ ++void HELPER(sve_ld##N##bb_r)(CPUARMState *env, void *vg, \ ++ target_ulong addr, uint32_t desc) \ ++{ \ ++ sve_ldN_r(env, vg, addr, desc, GETPC(), MO_8, MO_8, N, \ ++ sve_ld1bb_host, sve_ld1bb_tlb); \ + } + +-#define DO_LDN_2(N, SUFF, SIZE) \ +-void QEMU_FLATTEN HELPER(sve_ld##N##SUFF##_le_r) \ +- (CPUARMState *env, void *vg, target_ulong addr, uint32_t desc) \ ++#define DO_LDN_2(N, SUFF, ESZ) \ ++void HELPER(sve_ld##N##SUFF##_le_r)(CPUARMState *env, void *vg, \ ++ target_ulong addr, uint32_t desc) \ + { \ +- sve_ld##N##_r(env, vg, addr, desc, SIZE, GETPC(), \ +- sve_ld1##SUFF##_le_tlb); \ ++ sve_ldN_r(env, vg, addr, desc, GETPC(), ESZ, ESZ, N, \ ++ sve_ld1##SUFF##_le_host, sve_ld1##SUFF##_le_tlb); \ + } \ +-void QEMU_FLATTEN HELPER(sve_ld##N##SUFF##_be_r) \ +- (CPUARMState *env, void *vg, target_ulong addr, uint32_t desc) \ ++void HELPER(sve_ld##N##SUFF##_be_r)(CPUARMState *env, void *vg, \ ++ target_ulong addr, uint32_t desc) \ + { \ +- sve_ld##N##_r(env, vg, addr, desc, SIZE, GETPC(), \ +- sve_ld1##SUFF##_be_tlb); \ ++ sve_ldN_r(env, vg, addr, desc, GETPC(), ESZ, ESZ, N, \ ++ sve_ld1##SUFF##_be_host, sve_ld1##SUFF##_be_tlb); \ + } + + DO_LDN_1(2) + DO_LDN_1(3) + DO_LDN_1(4) + +-DO_LDN_2(2, hh, 2) +-DO_LDN_2(3, hh, 2) +-DO_LDN_2(4, hh, 2) ++DO_LDN_2(2, hh, MO_16) ++DO_LDN_2(3, hh, MO_16) ++DO_LDN_2(4, hh, MO_16) + +-DO_LDN_2(2, ss, 4) +-DO_LDN_2(3, ss, 4) +-DO_LDN_2(4, ss, 4) ++DO_LDN_2(2, ss, MO_32) ++DO_LDN_2(3, ss, MO_32) ++DO_LDN_2(4, ss, MO_32) + +-DO_LDN_2(2, dd, 8) +-DO_LDN_2(3, dd, 8) +-DO_LDN_2(4, dd, 8) ++DO_LDN_2(2, dd, MO_64) ++DO_LDN_2(3, dd, MO_64) ++DO_LDN_2(4, dd, MO_64) + + #undef DO_LDN_1 + #undef DO_LDN_2 +-- +2.23.0 + diff --git a/target-arm-Use-SVEContLdSt-in-sve_ld1_r.patch b/target-arm-Use-SVEContLdSt-in-sve_ld1_r.patch new file mode 100644 index 0000000000000000000000000000000000000000..1478b83a9f6833246ea904810fdd3a41ead5863b --- /dev/null +++ b/target-arm-Use-SVEContLdSt-in-sve_ld1_r.patch @@ -0,0 +1,253 @@ +From b854fd06a868e0308bcfe05ad0a71210705814c7 Mon Sep 17 00:00:00 2001 +From: Richard Henderson +Date: Fri, 8 May 2020 08:43:51 -0700 +Subject: [PATCH 375/709] target/arm: Use SVEContLdSt in sve_ld1_r + +First use of the new helper functions, so we can remove the +unused markup. No longer need a scratch for user-only, as +we completely probe the page set before reading; system mode +still requires a scratch for MMIO. + +Reviewed-by: Peter Maydell +Signed-off-by: Richard Henderson +Message-id: 20200508154359.7494-12-richard.henderson@linaro.org +Signed-off-by: Peter Maydell +--- + target/arm/sve_helper.c | 188 +++++++++++++++++++++------------------- + 1 file changed, 97 insertions(+), 91 deletions(-) + +diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c +index d007137735..6bae342a17 100644 +--- a/target/arm/sve_helper.c ++++ b/target/arm/sve_helper.c +@@ -4221,9 +4221,9 @@ typedef struct { + * final element on each page. Identify any single element that spans + * the page boundary. Return true if there are any active elements. + */ +-static bool __attribute__((unused)) +-sve_cont_ldst_elements(SVEContLdSt *info, target_ulong addr, uint64_t *vg, +- intptr_t reg_max, int esz, int msize) ++static bool sve_cont_ldst_elements(SVEContLdSt *info, target_ulong addr, ++ uint64_t *vg, intptr_t reg_max, ++ int esz, int msize) + { + const int esize = 1 << esz; + const uint64_t pg_mask = pred_esz_masks[esz]; +@@ -4313,10 +4313,9 @@ sve_cont_ldst_elements(SVEContLdSt *info, target_ulong addr, uint64_t *vg, + * Control the generation of page faults with @fault. Return false if + * there is no work to do, which can only happen with @fault == FAULT_NO. + */ +-static bool __attribute__((unused)) +-sve_cont_ldst_pages(SVEContLdSt *info, SVEContFault fault, CPUARMState *env, +- target_ulong addr, MMUAccessType access_type, +- uintptr_t retaddr) ++static bool sve_cont_ldst_pages(SVEContLdSt *info, SVEContFault fault, ++ CPUARMState *env, target_ulong addr, ++ MMUAccessType access_type, uintptr_t retaddr) + { + int mmu_idx = cpu_mmu_index(env, false); + int mem_off = info->mem_off_first[0]; +@@ -4388,109 +4387,116 @@ static inline bool test_host_page(void *host) + /* + * Common helper for all contiguous one-register predicated loads. + */ +-static void sve_ld1_r(CPUARMState *env, void *vg, const target_ulong addr, +- uint32_t desc, const uintptr_t retaddr, +- const int esz, const int msz, +- sve_ldst1_host_fn *host_fn, +- sve_ldst1_tlb_fn *tlb_fn) ++static inline QEMU_ALWAYS_INLINE ++void sve_ld1_r(CPUARMState *env, uint64_t *vg, const target_ulong addr, ++ uint32_t desc, const uintptr_t retaddr, ++ const int esz, const int msz, ++ sve_ldst1_host_fn *host_fn, ++ sve_ldst1_tlb_fn *tlb_fn) + { +- const TCGMemOpIdx oi = extract32(desc, SIMD_DATA_SHIFT, MEMOPIDX_SHIFT); +- const int mmu_idx = get_mmuidx(oi); + const unsigned rd = extract32(desc, SIMD_DATA_SHIFT + MEMOPIDX_SHIFT, 5); + void *vd = &env->vfp.zregs[rd]; +- const int diffsz = esz - msz; + const intptr_t reg_max = simd_oprsz(desc); +- const intptr_t mem_max = reg_max >> diffsz; +- ARMVectorReg scratch; ++ intptr_t reg_off, reg_last, mem_off; ++ SVEContLdSt info; + void *host; +- intptr_t split, reg_off, mem_off; ++ int flags; + +- /* Find the first active element. */ +- reg_off = find_next_active(vg, 0, reg_max, esz); +- if (unlikely(reg_off == reg_max)) { ++ /* Find the active elements. */ ++ if (!sve_cont_ldst_elements(&info, addr, vg, reg_max, esz, 1 << msz)) { + /* The entire predicate was false; no load occurs. */ + memset(vd, 0, reg_max); + return; + } +- mem_off = reg_off >> diffsz; + +- /* +- * If the (remaining) load is entirely within a single page, then: +- * For softmmu, and the tlb hits, then no faults will occur; +- * For user-only, either the first load will fault or none will. +- * We can thus perform the load directly to the destination and +- * Vd will be unmodified on any exception path. +- */ +- split = max_for_page(addr, mem_off, mem_max); +- if (likely(split == mem_max)) { +- host = tlb_vaddr_to_host(env, addr + mem_off, MMU_DATA_LOAD, mmu_idx); +- if (test_host_page(host)) { +- intptr_t i = reg_off; +- host -= mem_off; +- do { +- host_fn(vd, i, host + (i >> diffsz)); +- i = find_next_active(vg, i + (1 << esz), reg_max, esz); +- } while (i < reg_max); +- /* After having taken any fault, zero leading inactive elements. */ +- swap_memzero(vd, reg_off); +- return; +- } +- } ++ /* Probe the page(s). Exit with exception for any invalid page. */ ++ sve_cont_ldst_pages(&info, FAULT_ALL, env, addr, MMU_DATA_LOAD, retaddr); + +- /* +- * Perform the predicated read into a temporary, thus ensuring +- * if the load of the last element faults, Vd is not modified. +- */ ++ flags = info.page[0].flags | info.page[1].flags; ++ if (unlikely(flags != 0)) { + #ifdef CONFIG_USER_ONLY +- swap_memzero(&scratch, reg_off); +- host = g2h(addr); +- do { +- host_fn(&scratch, reg_off, host + (reg_off >> diffsz)); +- reg_off += 1 << esz; +- reg_off = find_next_active(vg, reg_off, reg_max, esz); +- } while (reg_off < reg_max); ++ g_assert_not_reached(); + #else +- memset(&scratch, 0, reg_max); +- goto start; +- while (1) { +- reg_off = find_next_active(vg, reg_off, reg_max, esz); +- if (reg_off >= reg_max) { +- break; +- } +- mem_off = reg_off >> diffsz; +- split = max_for_page(addr, mem_off, mem_max); +- +- start: +- if (split - mem_off >= (1 << msz)) { +- /* At least one whole element on this page. */ +- host = tlb_vaddr_to_host(env, addr + mem_off, +- MMU_DATA_LOAD, mmu_idx); +- if (host) { +- host -= mem_off; +- do { +- host_fn(&scratch, reg_off, host + mem_off); +- reg_off += 1 << esz; +- reg_off = find_next_active(vg, reg_off, reg_max, esz); +- mem_off = reg_off >> diffsz; +- } while (split - mem_off >= (1 << msz)); +- continue; ++ /* ++ * At least one page includes MMIO (or watchpoints). ++ * Any bus operation can fail with cpu_transaction_failed, ++ * which for ARM will raise SyncExternal. Perform the load ++ * into scratch memory to preserve register state until the end. ++ */ ++ ARMVectorReg scratch; ++ ++ memset(&scratch, 0, reg_max); ++ mem_off = info.mem_off_first[0]; ++ reg_off = info.reg_off_first[0]; ++ reg_last = info.reg_off_last[1]; ++ if (reg_last < 0) { ++ reg_last = info.reg_off_split; ++ if (reg_last < 0) { ++ reg_last = info.reg_off_last[0]; + } + } + +- /* +- * Perform one normal read. This may fault, longjmping out to the +- * main loop in order to raise an exception. It may succeed, and +- * as a side-effect load the TLB entry for the next round. Finally, +- * in the extremely unlikely case we're performing this operation +- * on I/O memory, it may succeed but not bring in the TLB entry. +- * But even then we have still made forward progress. +- */ +- tlb_fn(env, &scratch, reg_off, addr + mem_off, retaddr); +- reg_off += 1 << esz; +- } ++ do { ++ uint64_t pg = vg[reg_off >> 6]; ++ do { ++ if ((pg >> (reg_off & 63)) & 1) { ++ tlb_fn(env, &scratch, reg_off, addr + mem_off, retaddr); ++ } ++ reg_off += 1 << esz; ++ mem_off += 1 << msz; ++ } while (reg_off & 63); ++ } while (reg_off <= reg_last); ++ ++ memcpy(vd, &scratch, reg_max); ++ return; + #endif ++ } ++ ++ /* The entire operation is in RAM, on valid pages. */ ++ ++ memset(vd, 0, reg_max); ++ mem_off = info.mem_off_first[0]; ++ reg_off = info.reg_off_first[0]; ++ reg_last = info.reg_off_last[0]; ++ host = info.page[0].host; + +- memcpy(vd, &scratch, reg_max); ++ while (reg_off <= reg_last) { ++ uint64_t pg = vg[reg_off >> 6]; ++ do { ++ if ((pg >> (reg_off & 63)) & 1) { ++ host_fn(vd, reg_off, host + mem_off); ++ } ++ reg_off += 1 << esz; ++ mem_off += 1 << msz; ++ } while (reg_off <= reg_last && (reg_off & 63)); ++ } ++ ++ /* ++ * Use the slow path to manage the cross-page misalignment. ++ * But we know this is RAM and cannot trap. ++ */ ++ mem_off = info.mem_off_split; ++ if (unlikely(mem_off >= 0)) { ++ tlb_fn(env, vd, info.reg_off_split, addr + mem_off, retaddr); ++ } ++ ++ mem_off = info.mem_off_first[1]; ++ if (unlikely(mem_off >= 0)) { ++ reg_off = info.reg_off_first[1]; ++ reg_last = info.reg_off_last[1]; ++ host = info.page[1].host; ++ ++ do { ++ uint64_t pg = vg[reg_off >> 6]; ++ do { ++ if ((pg >> (reg_off & 63)) & 1) { ++ host_fn(vd, reg_off, host + mem_off); ++ } ++ reg_off += 1 << esz; ++ mem_off += 1 << msz; ++ } while (reg_off & 63); ++ } while (reg_off <= reg_last); ++ } + } + + #define DO_LD1_1(NAME, ESZ) \ +-- +2.23.0 + diff --git a/target-arm-Use-clear_vec_high-more-effectively.patch b/target-arm-Use-clear_vec_high-more-effectively.patch new file mode 100644 index 0000000000000000000000000000000000000000..05113b4d42a9b883e7a377bc46c507944e99874f --- /dev/null +++ b/target-arm-Use-clear_vec_high-more-effectively.patch @@ -0,0 +1,147 @@ +From e1f778596ebfa8782276f4dd4651f2b285d734ff Mon Sep 17 00:00:00 2001 +From: Richard Henderson +Date: Tue, 19 May 2020 14:24:53 -0700 +Subject: [PATCH 632/709] target/arm: Use clear_vec_high more effectively +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Do not explicitly store zero to the NEON high part +when we can pass !is_q to clear_vec_high. + +Reviewed-by: Alex Bennée +Signed-off-by: Richard Henderson +Message-id: 20200519212453.28494-3-richard.henderson@linaro.org +Signed-off-by: Peter Maydell +--- + target/arm/translate-a64.c | 53 +++++++++++++++++++++++--------------- + 1 file changed, 32 insertions(+), 21 deletions(-) + +diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c +index 4f6edb2892..874f3eb4f9 100644 +--- a/target/arm/translate-a64.c ++++ b/target/arm/translate-a64.c +@@ -900,11 +900,10 @@ static void do_fp_ld(DisasContext *s, int destidx, TCGv_i64 tcg_addr, int size) + { + /* This always zero-extends and writes to a full 128 bit wide vector */ + TCGv_i64 tmplo = tcg_temp_new_i64(); +- TCGv_i64 tmphi; ++ TCGv_i64 tmphi = NULL; + + if (size < 4) { + MemOp memop = s->be_data + size; +- tmphi = tcg_const_i64(0); + tcg_gen_qemu_ld_i64(tmplo, tcg_addr, get_mem_index(s), memop); + } else { + bool be = s->be_data == MO_BE; +@@ -922,12 +921,13 @@ static void do_fp_ld(DisasContext *s, int destidx, TCGv_i64 tcg_addr, int size) + } + + tcg_gen_st_i64(tmplo, cpu_env, fp_reg_offset(s, destidx, MO_64)); +- tcg_gen_st_i64(tmphi, cpu_env, fp_reg_hi_offset(s, destidx)); +- + tcg_temp_free_i64(tmplo); +- tcg_temp_free_i64(tmphi); + +- clear_vec_high(s, true, destidx); ++ if (tmphi) { ++ tcg_gen_st_i64(tmphi, cpu_env, fp_reg_hi_offset(s, destidx)); ++ tcg_temp_free_i64(tmphi); ++ } ++ clear_vec_high(s, tmphi != NULL, destidx); + } + + /* +@@ -6934,7 +6934,6 @@ static void disas_simd_ext(DisasContext *s, uint32_t insn) + read_vec_element(s, tcg_resh, rm, 0, MO_64); + do_ext64(s, tcg_resh, tcg_resl, pos); + } +- tcg_gen_movi_i64(tcg_resh, 0); + } else { + TCGv_i64 tcg_hh; + typedef struct { +@@ -6964,9 +6963,11 @@ static void disas_simd_ext(DisasContext *s, uint32_t insn) + + write_vec_element(s, tcg_resl, rd, 0, MO_64); + tcg_temp_free_i64(tcg_resl); +- write_vec_element(s, tcg_resh, rd, 1, MO_64); ++ if (is_q) { ++ write_vec_element(s, tcg_resh, rd, 1, MO_64); ++ } + tcg_temp_free_i64(tcg_resh); +- clear_vec_high(s, true, rd); ++ clear_vec_high(s, is_q, rd); + } + + /* TBL/TBX +@@ -7003,17 +7004,21 @@ static void disas_simd_tb(DisasContext *s, uint32_t insn) + * the input. + */ + tcg_resl = tcg_temp_new_i64(); +- tcg_resh = tcg_temp_new_i64(); ++ tcg_resh = NULL; + + if (is_tblx) { + read_vec_element(s, tcg_resl, rd, 0, MO_64); + } else { + tcg_gen_movi_i64(tcg_resl, 0); + } +- if (is_tblx && is_q) { +- read_vec_element(s, tcg_resh, rd, 1, MO_64); +- } else { +- tcg_gen_movi_i64(tcg_resh, 0); ++ ++ if (is_q) { ++ tcg_resh = tcg_temp_new_i64(); ++ if (is_tblx) { ++ read_vec_element(s, tcg_resh, rd, 1, MO_64); ++ } else { ++ tcg_gen_movi_i64(tcg_resh, 0); ++ } + } + + tcg_idx = tcg_temp_new_i64(); +@@ -7033,9 +7038,12 @@ static void disas_simd_tb(DisasContext *s, uint32_t insn) + + write_vec_element(s, tcg_resl, rd, 0, MO_64); + tcg_temp_free_i64(tcg_resl); +- write_vec_element(s, tcg_resh, rd, 1, MO_64); +- tcg_temp_free_i64(tcg_resh); +- clear_vec_high(s, true, rd); ++ ++ if (is_q) { ++ write_vec_element(s, tcg_resh, rd, 1, MO_64); ++ tcg_temp_free_i64(tcg_resh); ++ } ++ clear_vec_high(s, is_q, rd); + } + + /* ZIP/UZP/TRN +@@ -7072,7 +7080,7 @@ static void disas_simd_zip_trn(DisasContext *s, uint32_t insn) + } + + tcg_resl = tcg_const_i64(0); +- tcg_resh = tcg_const_i64(0); ++ tcg_resh = is_q ? tcg_const_i64(0) : NULL; + tcg_res = tcg_temp_new_i64(); + + for (i = 0; i < elements; i++) { +@@ -7123,9 +7131,12 @@ static void disas_simd_zip_trn(DisasContext *s, uint32_t insn) + + write_vec_element(s, tcg_resl, rd, 0, MO_64); + tcg_temp_free_i64(tcg_resl); +- write_vec_element(s, tcg_resh, rd, 1, MO_64); +- tcg_temp_free_i64(tcg_resh); +- clear_vec_high(s, true, rd); ++ ++ if (is_q) { ++ write_vec_element(s, tcg_resh, rd, 1, MO_64); ++ tcg_temp_free_i64(tcg_resh); ++ } ++ clear_vec_high(s, is_q, rd); + } + + /* +-- +2.23.0 + diff --git a/target-arm-Use-correct-GDB-XML-for-M-profile-cores.patch b/target-arm-Use-correct-GDB-XML-for-M-profile-cores.patch new file mode 100644 index 0000000000000000000000000000000000000000..210705c7ed52e6f299e12ad98c2240498f7ef7f2 --- /dev/null +++ b/target-arm-Use-correct-GDB-XML-for-M-profile-cores.patch @@ -0,0 +1,142 @@ +From c888f7e0fdcc09c86004330ab5cad62bf98cc71c Mon Sep 17 00:00:00 2001 +From: Peter Maydell +Date: Thu, 7 May 2020 14:47:55 +0100 +Subject: [PATCH 418/709] target/arm: Use correct GDB XML for M-profile cores +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +GDB's remote protocol requires M-profile cores to use the feature +name 'org.gnu.gdb.arm.m-profile' instead of the 'org.gnu.gdb.arm.core' +feature used for A- and R-profile cores. We weren't doing this, which +meant GDB treated our M-profile cores like A-profile ones. This mostly +doesn't matter, but for instance means that it doesn't correctly +handle backtraces where an M-profile exception frame is involved. + +Ship a copy of GDB's arm-m-profile.xml and use it on the M-profile +cores. The integer registers have the same offsets as the +arm-core.xml, but register 25 is the M-profile XPSR rather than the +A-profile CPSR, so we need to update arm_cpu_gdb_read_register() and +arm_cpu_gdb_write_register() to handle XSPR reads and writes. + +Fixes: https://bugs.launchpad.net/qemu/+bug/1877136 +Signed-off-by: Peter Maydell +Reviewed-by: Philippe Mathieu-Daudé +Message-id: 20200507134755.13997-1-peter.maydell@linaro.org +--- + configure | 4 ++-- + gdb-xml/arm-m-profile.xml | 27 +++++++++++++++++++++++++++ + target/arm/cpu_tcg.c | 1 + + target/arm/gdbstub.c | 22 ++++++++++++++++++---- + 4 files changed, 48 insertions(+), 6 deletions(-) + create mode 100644 gdb-xml/arm-m-profile.xml + +diff --git a/configure b/configure +index c50c006b86..26084fc53a 100755 +--- a/configure ++++ b/configure +@@ -7806,14 +7806,14 @@ case "$target_name" in + TARGET_SYSTBL_ABI=common,oabi + bflt="yes" + mttcg="yes" +- gdb_xml_files="arm-core.xml arm-vfp.xml arm-vfp3.xml arm-neon.xml" ++ gdb_xml_files="arm-core.xml arm-vfp.xml arm-vfp3.xml arm-neon.xml arm-m-profile.xml" + ;; + aarch64|aarch64_be) + TARGET_ARCH=aarch64 + TARGET_BASE_ARCH=arm + bflt="yes" + mttcg="yes" +- gdb_xml_files="aarch64-core.xml aarch64-fpu.xml arm-core.xml arm-vfp.xml arm-vfp3.xml arm-neon.xml" ++ gdb_xml_files="aarch64-core.xml aarch64-fpu.xml arm-core.xml arm-vfp.xml arm-vfp3.xml arm-neon.xml arm-m-profile.xml" + ;; + cris) + ;; +diff --git a/gdb-xml/arm-m-profile.xml b/gdb-xml/arm-m-profile.xml +new file mode 100644 +index 0000000000..5319d764ee +--- /dev/null ++++ b/gdb-xml/arm-m-profile.xml +@@ -0,0 +1,27 @@ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ +diff --git a/target/arm/cpu_tcg.c b/target/arm/cpu_tcg.c +index 591baef535..00b0e08f33 100644 +--- a/target/arm/cpu_tcg.c ++++ b/target/arm/cpu_tcg.c +@@ -605,6 +605,7 @@ static void arm_v7m_class_init(ObjectClass *oc, void *data) + #endif + + cc->cpu_exec_interrupt = arm_v7m_cpu_exec_interrupt; ++ cc->gdb_core_xml_file = "arm-m-profile.xml"; + } + + static const ARMCPUInfo arm_tcg_cpus[] = { +diff --git a/target/arm/gdbstub.c b/target/arm/gdbstub.c +index 063551df23..ecfa88f8e6 100644 +--- a/target/arm/gdbstub.c ++++ b/target/arm/gdbstub.c +@@ -57,8 +57,12 @@ int arm_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n) + } + return gdb_get_reg32(mem_buf, 0); + case 25: +- /* CPSR */ +- return gdb_get_reg32(mem_buf, cpsr_read(env)); ++ /* CPSR, or XPSR for M-profile */ ++ if (arm_feature(env, ARM_FEATURE_M)) { ++ return gdb_get_reg32(mem_buf, xpsr_read(env)); ++ } else { ++ return gdb_get_reg32(mem_buf, cpsr_read(env)); ++ } + } + /* Unknown register. */ + return 0; +@@ -98,8 +102,18 @@ int arm_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n) + } + return 4; + case 25: +- /* CPSR */ +- cpsr_write(env, tmp, 0xffffffff, CPSRWriteByGDBStub); ++ /* CPSR, or XPSR for M-profile */ ++ if (arm_feature(env, ARM_FEATURE_M)) { ++ /* ++ * Don't allow writing to XPSR.Exception as it can cause ++ * a transition into or out of handler mode (it's not ++ * writeable via the MSR insn so this is a reasonable ++ * restriction). Other fields are safe to update. ++ */ ++ xpsr_write(env, tmp, ~XPSR_EXCP); ++ } else { ++ cpsr_write(env, tmp, 0xffffffff, CPSRWriteByGDBStub); ++ } + return 4; + } + /* Unknown register. */ +-- +2.23.0 + diff --git a/target-arm-Use-correct-variable-for-setting-max-cpu-.patch b/target-arm-Use-correct-variable-for-setting-max-cpu-.patch new file mode 100644 index 0000000000000000000000000000000000000000..fa7d26552a7d3cf889023a4fa242a914d5c189c7 --- /dev/null +++ b/target-arm-Use-correct-variable-for-setting-max-cpu-.patch @@ -0,0 +1,49 @@ +From 5a89dd2385a193aa954a7c9bf4e381f2ba6ae359 Mon Sep 17 00:00:00 2001 +From: Peter Maydell +Date: Thu, 23 Apr 2020 12:09:15 +0100 +Subject: [PATCH 155/709] target/arm: Use correct variable for setting 'max' + cpu's ID_AA64DFR0 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +In aarch64_max_initfn() we update both 32-bit and 64-bit ID +registers. The intended pattern is that for 64-bit ID registers we +use FIELD_DP64 and the uint64_t 't' register, while 32-bit ID +registers use FIELD_DP32 and the uint32_t 'u' register. For +ID_AA64DFR0 we accidentally used 'u', meaning that the top 32 bits of +this 64-bit ID register would end up always zero. Luckily at the +moment that's what they should be anyway, so this bug has no visible +effects. + +Use the right-sized variable. + +Fixes: 3bec78447a958d481991 +Signed-off-by: Peter Maydell +Reviewed-by: Laurent Desnogues +Reviewed-by: Philippe Mathieu-Daudé +Message-id: 20200423110915.10527-1-peter.maydell@linaro.org +--- + target/arm/cpu64.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c +index e232c0ea12..9bdf75b1ab 100644 +--- a/target/arm/cpu64.c ++++ b/target/arm/cpu64.c +@@ -710,9 +710,9 @@ static void aarch64_max_initfn(Object *obj) + u = FIELD_DP32(u, ID_MMFR4, XNX, 1); /* TTS2UXN */ + cpu->isar.id_mmfr4 = u; + +- u = cpu->isar.id_aa64dfr0; +- u = FIELD_DP64(u, ID_AA64DFR0, PMUVER, 5); /* v8.4-PMU */ +- cpu->isar.id_aa64dfr0 = u; ++ t = cpu->isar.id_aa64dfr0; ++ t = FIELD_DP64(t, ID_AA64DFR0, PMUVER, 5); /* v8.4-PMU */ ++ cpu->isar.id_aa64dfr0 = t; + + u = cpu->isar.id_dfr0; + u = FIELD_DP32(u, ID_DFR0, PERFMON, 5); /* v8.4-PMU */ +-- +2.23.0 + diff --git a/target-arm-Use-cpu_-_data_ra-for-sve_ldst_tlb_fn.patch b/target-arm-Use-cpu_-_data_ra-for-sve_ldst_tlb_fn.patch new file mode 100644 index 0000000000000000000000000000000000000000..6f6462d22b3bcd289e91f5861f0882f547fb18a4 --- /dev/null +++ b/target-arm-Use-cpu_-_data_ra-for-sve_ldst_tlb_fn.patch @@ -0,0 +1,520 @@ +From 6799ce7b0e11f4b08c5cf26d08707b829f69449c Mon Sep 17 00:00:00 2001 +From: Richard Henderson +Date: Fri, 8 May 2020 08:43:47 -0700 +Subject: [PATCH 371/709] target/arm: Use cpu_*_data_ra for sve_ldst_tlb_fn + +Use the "normal" memory access functions, rather than the +softmmu internal helper functions directly. + +Since fb901c905dc3, cpu_mem_index is now a simple extract +from env->hflags and not a large computation. Which means +that it's now more work to pass around this value than it +is to recompute it. + +This only adjusts the primitives, and does not clean up +all of the uses within sve_helper.c. + +Reviewed-by: Peter Maydell +Signed-off-by: Richard Henderson +Message-id: 20200508154359.7494-8-richard.henderson@linaro.org +Signed-off-by: Peter Maydell +--- + target/arm/sve_helper.c | 221 ++++++++++++++++------------------------ + 1 file changed, 86 insertions(+), 135 deletions(-) + +diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c +index fdfa652094..655bc9476f 100644 +--- a/target/arm/sve_helper.c ++++ b/target/arm/sve_helper.c +@@ -3991,9 +3991,8 @@ typedef intptr_t sve_ld1_host_fn(void *vd, void *vg, void *host, + * Load one element into @vd + @reg_off from (@env, @vaddr, @ra). + * The controlling predicate is known to be true. + */ +-typedef void sve_ld1_tlb_fn(CPUARMState *env, void *vd, intptr_t reg_off, +- target_ulong vaddr, TCGMemOpIdx oi, uintptr_t ra); +-typedef sve_ld1_tlb_fn sve_st1_tlb_fn; ++typedef void sve_ldst1_tlb_fn(CPUARMState *env, void *vd, intptr_t reg_off, ++ target_ulong vaddr, uintptr_t retaddr); + + /* + * Generate the above primitives. +@@ -4016,27 +4015,23 @@ static intptr_t sve_##NAME##_host(void *vd, void *vg, void *host, \ + return mem_off; \ + } + +-#ifdef CONFIG_SOFTMMU +-#define DO_LD_TLB(NAME, H, TYPEE, TYPEM, HOST, MOEND, TLB) \ ++#define DO_LD_TLB(NAME, H, TYPEE, TYPEM, TLB) \ + static void sve_##NAME##_tlb(CPUARMState *env, void *vd, intptr_t reg_off, \ +- target_ulong addr, TCGMemOpIdx oi, uintptr_t ra) \ ++ target_ulong addr, uintptr_t ra) \ + { \ +- TYPEM val = TLB(env, addr, oi, ra); \ +- *(TYPEE *)(vd + H(reg_off)) = val; \ ++ *(TYPEE *)(vd + H(reg_off)) = (TYPEM)TLB(env, addr, ra); \ + } +-#else +-#define DO_LD_TLB(NAME, H, TYPEE, TYPEM, HOST, MOEND, TLB) \ ++ ++#define DO_ST_TLB(NAME, H, TYPEE, TYPEM, TLB) \ + static void sve_##NAME##_tlb(CPUARMState *env, void *vd, intptr_t reg_off, \ +- target_ulong addr, TCGMemOpIdx oi, uintptr_t ra) \ ++ target_ulong addr, uintptr_t ra) \ + { \ +- TYPEM val = HOST(g2h(addr)); \ +- *(TYPEE *)(vd + H(reg_off)) = val; \ ++ TLB(env, addr, (TYPEM)*(TYPEE *)(vd + H(reg_off)), ra); \ + } +-#endif + + #define DO_LD_PRIM_1(NAME, H, TE, TM) \ + DO_LD_HOST(NAME, H, TE, TM, ldub_p) \ +- DO_LD_TLB(NAME, H, TE, TM, ldub_p, 0, helper_ret_ldub_mmu) ++ DO_LD_TLB(NAME, H, TE, TM, cpu_ldub_data_ra) + + DO_LD_PRIM_1(ld1bb, H1, uint8_t, uint8_t) + DO_LD_PRIM_1(ld1bhu, H1_2, uint16_t, uint8_t) +@@ -4046,39 +4041,51 @@ DO_LD_PRIM_1(ld1bss, H1_4, uint32_t, int8_t) + DO_LD_PRIM_1(ld1bdu, , uint64_t, uint8_t) + DO_LD_PRIM_1(ld1bds, , uint64_t, int8_t) + +-#define DO_LD_PRIM_2(NAME, end, MOEND, H, TE, TM, PH, PT) \ +- DO_LD_HOST(NAME##_##end, H, TE, TM, PH##_##end##_p) \ +- DO_LD_TLB(NAME##_##end, H, TE, TM, PH##_##end##_p, \ +- MOEND, helper_##end##_##PT##_mmu) ++#define DO_ST_PRIM_1(NAME, H, TE, TM) \ ++ DO_ST_TLB(st1##NAME, H, TE, TM, cpu_stb_data_ra) ++ ++DO_ST_PRIM_1(bb, H1, uint8_t, uint8_t) ++DO_ST_PRIM_1(bh, H1_2, uint16_t, uint8_t) ++DO_ST_PRIM_1(bs, H1_4, uint32_t, uint8_t) ++DO_ST_PRIM_1(bd, , uint64_t, uint8_t) + +-DO_LD_PRIM_2(ld1hh, le, MO_LE, H1_2, uint16_t, uint16_t, lduw, lduw) +-DO_LD_PRIM_2(ld1hsu, le, MO_LE, H1_4, uint32_t, uint16_t, lduw, lduw) +-DO_LD_PRIM_2(ld1hss, le, MO_LE, H1_4, uint32_t, int16_t, lduw, lduw) +-DO_LD_PRIM_2(ld1hdu, le, MO_LE, , uint64_t, uint16_t, lduw, lduw) +-DO_LD_PRIM_2(ld1hds, le, MO_LE, , uint64_t, int16_t, lduw, lduw) ++#define DO_LD_PRIM_2(NAME, H, TE, TM, LD) \ ++ DO_LD_HOST(ld1##NAME##_be, H, TE, TM, LD##_be_p) \ ++ DO_LD_HOST(ld1##NAME##_le, H, TE, TM, LD##_le_p) \ ++ DO_LD_TLB(ld1##NAME##_be, H, TE, TM, cpu_##LD##_be_data_ra) \ ++ DO_LD_TLB(ld1##NAME##_le, H, TE, TM, cpu_##LD##_le_data_ra) + +-DO_LD_PRIM_2(ld1ss, le, MO_LE, H1_4, uint32_t, uint32_t, ldl, ldul) +-DO_LD_PRIM_2(ld1sdu, le, MO_LE, , uint64_t, uint32_t, ldl, ldul) +-DO_LD_PRIM_2(ld1sds, le, MO_LE, , uint64_t, int32_t, ldl, ldul) ++#define DO_ST_PRIM_2(NAME, H, TE, TM, ST) \ ++ DO_ST_TLB(st1##NAME##_be, H, TE, TM, cpu_##ST##_be_data_ra) \ ++ DO_ST_TLB(st1##NAME##_le, H, TE, TM, cpu_##ST##_le_data_ra) + +-DO_LD_PRIM_2(ld1dd, le, MO_LE, , uint64_t, uint64_t, ldq, ldq) ++DO_LD_PRIM_2(hh, H1_2, uint16_t, uint16_t, lduw) ++DO_LD_PRIM_2(hsu, H1_4, uint32_t, uint16_t, lduw) ++DO_LD_PRIM_2(hss, H1_4, uint32_t, int16_t, lduw) ++DO_LD_PRIM_2(hdu, , uint64_t, uint16_t, lduw) ++DO_LD_PRIM_2(hds, , uint64_t, int16_t, lduw) + +-DO_LD_PRIM_2(ld1hh, be, MO_BE, H1_2, uint16_t, uint16_t, lduw, lduw) +-DO_LD_PRIM_2(ld1hsu, be, MO_BE, H1_4, uint32_t, uint16_t, lduw, lduw) +-DO_LD_PRIM_2(ld1hss, be, MO_BE, H1_4, uint32_t, int16_t, lduw, lduw) +-DO_LD_PRIM_2(ld1hdu, be, MO_BE, , uint64_t, uint16_t, lduw, lduw) +-DO_LD_PRIM_2(ld1hds, be, MO_BE, , uint64_t, int16_t, lduw, lduw) ++DO_ST_PRIM_2(hh, H1_2, uint16_t, uint16_t, stw) ++DO_ST_PRIM_2(hs, H1_4, uint32_t, uint16_t, stw) ++DO_ST_PRIM_2(hd, , uint64_t, uint16_t, stw) + +-DO_LD_PRIM_2(ld1ss, be, MO_BE, H1_4, uint32_t, uint32_t, ldl, ldul) +-DO_LD_PRIM_2(ld1sdu, be, MO_BE, , uint64_t, uint32_t, ldl, ldul) +-DO_LD_PRIM_2(ld1sds, be, MO_BE, , uint64_t, int32_t, ldl, ldul) ++DO_LD_PRIM_2(ss, H1_4, uint32_t, uint32_t, ldl) ++DO_LD_PRIM_2(sdu, , uint64_t, uint32_t, ldl) ++DO_LD_PRIM_2(sds, , uint64_t, int32_t, ldl) + +-DO_LD_PRIM_2(ld1dd, be, MO_BE, , uint64_t, uint64_t, ldq, ldq) ++DO_ST_PRIM_2(ss, H1_4, uint32_t, uint32_t, stl) ++DO_ST_PRIM_2(sd, , uint64_t, uint32_t, stl) ++ ++DO_LD_PRIM_2(dd, , uint64_t, uint64_t, ldq) ++DO_ST_PRIM_2(dd, , uint64_t, uint64_t, stq) + + #undef DO_LD_TLB ++#undef DO_ST_TLB + #undef DO_LD_HOST + #undef DO_LD_PRIM_1 ++#undef DO_ST_PRIM_1 + #undef DO_LD_PRIM_2 ++#undef DO_ST_PRIM_2 + + /* + * Skip through a sequence of inactive elements in the guarding predicate @vg, +@@ -4152,7 +4159,7 @@ static void sve_ld1_r(CPUARMState *env, void *vg, const target_ulong addr, + uint32_t desc, const uintptr_t retaddr, + const int esz, const int msz, + sve_ld1_host_fn *host_fn, +- sve_ld1_tlb_fn *tlb_fn) ++ sve_ldst1_tlb_fn *tlb_fn) + { + const TCGMemOpIdx oi = extract32(desc, SIMD_DATA_SHIFT, MEMOPIDX_SHIFT); + const int mmu_idx = get_mmuidx(oi); +@@ -4234,7 +4241,7 @@ static void sve_ld1_r(CPUARMState *env, void *vg, const target_ulong addr, + * on I/O memory, it may succeed but not bring in the TLB entry. + * But even then we have still made forward progress. + */ +- tlb_fn(env, &scratch, reg_off, addr + mem_off, oi, retaddr); ++ tlb_fn(env, &scratch, reg_off, addr + mem_off, retaddr); + reg_off += 1 << esz; + } + #endif +@@ -4293,9 +4300,8 @@ DO_LD1_2(ld1dd, 3, 3) + */ + static void sve_ld2_r(CPUARMState *env, void *vg, target_ulong addr, + uint32_t desc, int size, uintptr_t ra, +- sve_ld1_tlb_fn *tlb_fn) ++ sve_ldst1_tlb_fn *tlb_fn) + { +- const TCGMemOpIdx oi = extract32(desc, SIMD_DATA_SHIFT, MEMOPIDX_SHIFT); + const unsigned rd = extract32(desc, SIMD_DATA_SHIFT + MEMOPIDX_SHIFT, 5); + intptr_t i, oprsz = simd_oprsz(desc); + ARMVectorReg scratch[2] = { }; +@@ -4305,8 +4311,8 @@ static void sve_ld2_r(CPUARMState *env, void *vg, target_ulong addr, + uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3)); + do { + if (pg & 1) { +- tlb_fn(env, &scratch[0], i, addr, oi, ra); +- tlb_fn(env, &scratch[1], i, addr + size, oi, ra); ++ tlb_fn(env, &scratch[0], i, addr, ra); ++ tlb_fn(env, &scratch[1], i, addr + size, ra); + } + i += size, pg >>= size; + addr += 2 * size; +@@ -4321,9 +4327,8 @@ static void sve_ld2_r(CPUARMState *env, void *vg, target_ulong addr, + + static void sve_ld3_r(CPUARMState *env, void *vg, target_ulong addr, + uint32_t desc, int size, uintptr_t ra, +- sve_ld1_tlb_fn *tlb_fn) ++ sve_ldst1_tlb_fn *tlb_fn) + { +- const TCGMemOpIdx oi = extract32(desc, SIMD_DATA_SHIFT, MEMOPIDX_SHIFT); + const unsigned rd = extract32(desc, SIMD_DATA_SHIFT + MEMOPIDX_SHIFT, 5); + intptr_t i, oprsz = simd_oprsz(desc); + ARMVectorReg scratch[3] = { }; +@@ -4333,9 +4338,9 @@ static void sve_ld3_r(CPUARMState *env, void *vg, target_ulong addr, + uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3)); + do { + if (pg & 1) { +- tlb_fn(env, &scratch[0], i, addr, oi, ra); +- tlb_fn(env, &scratch[1], i, addr + size, oi, ra); +- tlb_fn(env, &scratch[2], i, addr + 2 * size, oi, ra); ++ tlb_fn(env, &scratch[0], i, addr, ra); ++ tlb_fn(env, &scratch[1], i, addr + size, ra); ++ tlb_fn(env, &scratch[2], i, addr + 2 * size, ra); + } + i += size, pg >>= size; + addr += 3 * size; +@@ -4351,9 +4356,8 @@ static void sve_ld3_r(CPUARMState *env, void *vg, target_ulong addr, + + static void sve_ld4_r(CPUARMState *env, void *vg, target_ulong addr, + uint32_t desc, int size, uintptr_t ra, +- sve_ld1_tlb_fn *tlb_fn) ++ sve_ldst1_tlb_fn *tlb_fn) + { +- const TCGMemOpIdx oi = extract32(desc, SIMD_DATA_SHIFT, MEMOPIDX_SHIFT); + const unsigned rd = extract32(desc, SIMD_DATA_SHIFT + MEMOPIDX_SHIFT, 5); + intptr_t i, oprsz = simd_oprsz(desc); + ARMVectorReg scratch[4] = { }; +@@ -4363,10 +4367,10 @@ static void sve_ld4_r(CPUARMState *env, void *vg, target_ulong addr, + uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3)); + do { + if (pg & 1) { +- tlb_fn(env, &scratch[0], i, addr, oi, ra); +- tlb_fn(env, &scratch[1], i, addr + size, oi, ra); +- tlb_fn(env, &scratch[2], i, addr + 2 * size, oi, ra); +- tlb_fn(env, &scratch[3], i, addr + 3 * size, oi, ra); ++ tlb_fn(env, &scratch[0], i, addr, ra); ++ tlb_fn(env, &scratch[1], i, addr + size, ra); ++ tlb_fn(env, &scratch[2], i, addr + 2 * size, ra); ++ tlb_fn(env, &scratch[3], i, addr + 3 * size, ra); + } + i += size, pg >>= size; + addr += 4 * size; +@@ -4459,7 +4463,7 @@ static void sve_ldff1_r(CPUARMState *env, void *vg, const target_ulong addr, + uint32_t desc, const uintptr_t retaddr, + const int esz, const int msz, + sve_ld1_host_fn *host_fn, +- sve_ld1_tlb_fn *tlb_fn) ++ sve_ldst1_tlb_fn *tlb_fn) + { + const TCGMemOpIdx oi = extract32(desc, SIMD_DATA_SHIFT, MEMOPIDX_SHIFT); + const int mmu_idx = get_mmuidx(oi); +@@ -4519,7 +4523,7 @@ static void sve_ldff1_r(CPUARMState *env, void *vg, const target_ulong addr, + * Perform one normal read, which will fault or not. + * But it is likely to bring the page into the tlb. + */ +- tlb_fn(env, vd, reg_off, addr + mem_off, oi, retaddr); ++ tlb_fn(env, vd, reg_off, addr + mem_off, retaddr); + + /* After any fault, zero any leading predicated false elts. */ + swap_memzero(vd, reg_off); +@@ -4671,60 +4675,14 @@ DO_LDFF1_LDNF1_2(dd, 3, 3) + #undef DO_LDFF1_LDNF1_1 + #undef DO_LDFF1_LDNF1_2 + +-/* +- * Store contiguous data, protected by a governing predicate. +- */ +- +-#ifdef CONFIG_SOFTMMU +-#define DO_ST_TLB(NAME, H, TYPEM, HOST, MOEND, TLB) \ +-static void sve_##NAME##_tlb(CPUARMState *env, void *vd, intptr_t reg_off, \ +- target_ulong addr, TCGMemOpIdx oi, uintptr_t ra) \ +-{ \ +- TLB(env, addr, *(TYPEM *)(vd + H(reg_off)), oi, ra); \ +-} +-#else +-#define DO_ST_TLB(NAME, H, TYPEM, HOST, MOEND, TLB) \ +-static void sve_##NAME##_tlb(CPUARMState *env, void *vd, intptr_t reg_off, \ +- target_ulong addr, TCGMemOpIdx oi, uintptr_t ra) \ +-{ \ +- HOST(g2h(addr), *(TYPEM *)(vd + H(reg_off))); \ +-} +-#endif +- +-DO_ST_TLB(st1bb, H1, uint8_t, stb_p, 0, helper_ret_stb_mmu) +-DO_ST_TLB(st1bh, H1_2, uint16_t, stb_p, 0, helper_ret_stb_mmu) +-DO_ST_TLB(st1bs, H1_4, uint32_t, stb_p, 0, helper_ret_stb_mmu) +-DO_ST_TLB(st1bd, , uint64_t, stb_p, 0, helper_ret_stb_mmu) +- +-DO_ST_TLB(st1hh_le, H1_2, uint16_t, stw_le_p, MO_LE, helper_le_stw_mmu) +-DO_ST_TLB(st1hs_le, H1_4, uint32_t, stw_le_p, MO_LE, helper_le_stw_mmu) +-DO_ST_TLB(st1hd_le, , uint64_t, stw_le_p, MO_LE, helper_le_stw_mmu) +- +-DO_ST_TLB(st1ss_le, H1_4, uint32_t, stl_le_p, MO_LE, helper_le_stl_mmu) +-DO_ST_TLB(st1sd_le, , uint64_t, stl_le_p, MO_LE, helper_le_stl_mmu) +- +-DO_ST_TLB(st1dd_le, , uint64_t, stq_le_p, MO_LE, helper_le_stq_mmu) +- +-DO_ST_TLB(st1hh_be, H1_2, uint16_t, stw_be_p, MO_BE, helper_be_stw_mmu) +-DO_ST_TLB(st1hs_be, H1_4, uint32_t, stw_be_p, MO_BE, helper_be_stw_mmu) +-DO_ST_TLB(st1hd_be, , uint64_t, stw_be_p, MO_BE, helper_be_stw_mmu) +- +-DO_ST_TLB(st1ss_be, H1_4, uint32_t, stl_be_p, MO_BE, helper_be_stl_mmu) +-DO_ST_TLB(st1sd_be, , uint64_t, stl_be_p, MO_BE, helper_be_stl_mmu) +- +-DO_ST_TLB(st1dd_be, , uint64_t, stq_be_p, MO_BE, helper_be_stq_mmu) +- +-#undef DO_ST_TLB +- + /* + * Common helpers for all contiguous 1,2,3,4-register predicated stores. + */ + static void sve_st1_r(CPUARMState *env, void *vg, target_ulong addr, + uint32_t desc, const uintptr_t ra, + const int esize, const int msize, +- sve_st1_tlb_fn *tlb_fn) ++ sve_ldst1_tlb_fn *tlb_fn) + { +- const TCGMemOpIdx oi = extract32(desc, SIMD_DATA_SHIFT, MEMOPIDX_SHIFT); + const unsigned rd = extract32(desc, SIMD_DATA_SHIFT + MEMOPIDX_SHIFT, 5); + intptr_t i, oprsz = simd_oprsz(desc); + void *vd = &env->vfp.zregs[rd]; +@@ -4734,7 +4692,7 @@ static void sve_st1_r(CPUARMState *env, void *vg, target_ulong addr, + uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3)); + do { + if (pg & 1) { +- tlb_fn(env, vd, i, addr, oi, ra); ++ tlb_fn(env, vd, i, addr, ra); + } + i += esize, pg >>= esize; + addr += msize; +@@ -4746,9 +4704,8 @@ static void sve_st1_r(CPUARMState *env, void *vg, target_ulong addr, + static void sve_st2_r(CPUARMState *env, void *vg, target_ulong addr, + uint32_t desc, const uintptr_t ra, + const int esize, const int msize, +- sve_st1_tlb_fn *tlb_fn) ++ sve_ldst1_tlb_fn *tlb_fn) + { +- const TCGMemOpIdx oi = extract32(desc, SIMD_DATA_SHIFT, MEMOPIDX_SHIFT); + const unsigned rd = extract32(desc, SIMD_DATA_SHIFT + MEMOPIDX_SHIFT, 5); + intptr_t i, oprsz = simd_oprsz(desc); + void *d1 = &env->vfp.zregs[rd]; +@@ -4759,8 +4716,8 @@ static void sve_st2_r(CPUARMState *env, void *vg, target_ulong addr, + uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3)); + do { + if (pg & 1) { +- tlb_fn(env, d1, i, addr, oi, ra); +- tlb_fn(env, d2, i, addr + msize, oi, ra); ++ tlb_fn(env, d1, i, addr, ra); ++ tlb_fn(env, d2, i, addr + msize, ra); + } + i += esize, pg >>= esize; + addr += 2 * msize; +@@ -4772,9 +4729,8 @@ static void sve_st2_r(CPUARMState *env, void *vg, target_ulong addr, + static void sve_st3_r(CPUARMState *env, void *vg, target_ulong addr, + uint32_t desc, const uintptr_t ra, + const int esize, const int msize, +- sve_st1_tlb_fn *tlb_fn) ++ sve_ldst1_tlb_fn *tlb_fn) + { +- const TCGMemOpIdx oi = extract32(desc, SIMD_DATA_SHIFT, MEMOPIDX_SHIFT); + const unsigned rd = extract32(desc, SIMD_DATA_SHIFT + MEMOPIDX_SHIFT, 5); + intptr_t i, oprsz = simd_oprsz(desc); + void *d1 = &env->vfp.zregs[rd]; +@@ -4786,9 +4742,9 @@ static void sve_st3_r(CPUARMState *env, void *vg, target_ulong addr, + uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3)); + do { + if (pg & 1) { +- tlb_fn(env, d1, i, addr, oi, ra); +- tlb_fn(env, d2, i, addr + msize, oi, ra); +- tlb_fn(env, d3, i, addr + 2 * msize, oi, ra); ++ tlb_fn(env, d1, i, addr, ra); ++ tlb_fn(env, d2, i, addr + msize, ra); ++ tlb_fn(env, d3, i, addr + 2 * msize, ra); + } + i += esize, pg >>= esize; + addr += 3 * msize; +@@ -4800,9 +4756,8 @@ static void sve_st3_r(CPUARMState *env, void *vg, target_ulong addr, + static void sve_st4_r(CPUARMState *env, void *vg, target_ulong addr, + uint32_t desc, const uintptr_t ra, + const int esize, const int msize, +- sve_st1_tlb_fn *tlb_fn) ++ sve_ldst1_tlb_fn *tlb_fn) + { +- const TCGMemOpIdx oi = extract32(desc, SIMD_DATA_SHIFT, MEMOPIDX_SHIFT); + const unsigned rd = extract32(desc, SIMD_DATA_SHIFT + MEMOPIDX_SHIFT, 5); + intptr_t i, oprsz = simd_oprsz(desc); + void *d1 = &env->vfp.zregs[rd]; +@@ -4815,10 +4770,10 @@ static void sve_st4_r(CPUARMState *env, void *vg, target_ulong addr, + uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3)); + do { + if (pg & 1) { +- tlb_fn(env, d1, i, addr, oi, ra); +- tlb_fn(env, d2, i, addr + msize, oi, ra); +- tlb_fn(env, d3, i, addr + 2 * msize, oi, ra); +- tlb_fn(env, d4, i, addr + 3 * msize, oi, ra); ++ tlb_fn(env, d1, i, addr, ra); ++ tlb_fn(env, d2, i, addr + msize, ra); ++ tlb_fn(env, d3, i, addr + 2 * msize, ra); ++ tlb_fn(env, d4, i, addr + 3 * msize, ra); + } + i += esize, pg >>= esize; + addr += 4 * msize; +@@ -4914,9 +4869,8 @@ static target_ulong off_zd_d(void *reg, intptr_t reg_ofs) + + static void sve_ld1_zs(CPUARMState *env, void *vd, void *vg, void *vm, + target_ulong base, uint32_t desc, uintptr_t ra, +- zreg_off_fn *off_fn, sve_ld1_tlb_fn *tlb_fn) ++ zreg_off_fn *off_fn, sve_ldst1_tlb_fn *tlb_fn) + { +- const TCGMemOpIdx oi = extract32(desc, SIMD_DATA_SHIFT, MEMOPIDX_SHIFT); + const int scale = extract32(desc, SIMD_DATA_SHIFT + MEMOPIDX_SHIFT, 2); + intptr_t i, oprsz = simd_oprsz(desc); + ARMVectorReg scratch = { }; +@@ -4927,7 +4881,7 @@ static void sve_ld1_zs(CPUARMState *env, void *vd, void *vg, void *vm, + do { + if (likely(pg & 1)) { + target_ulong off = off_fn(vm, i); +- tlb_fn(env, &scratch, i, base + (off << scale), oi, ra); ++ tlb_fn(env, &scratch, i, base + (off << scale), ra); + } + i += 4, pg >>= 4; + } while (i & 15); +@@ -4940,9 +4894,8 @@ static void sve_ld1_zs(CPUARMState *env, void *vd, void *vg, void *vm, + + static void sve_ld1_zd(CPUARMState *env, void *vd, void *vg, void *vm, + target_ulong base, uint32_t desc, uintptr_t ra, +- zreg_off_fn *off_fn, sve_ld1_tlb_fn *tlb_fn) ++ zreg_off_fn *off_fn, sve_ldst1_tlb_fn *tlb_fn) + { +- const TCGMemOpIdx oi = extract32(desc, SIMD_DATA_SHIFT, MEMOPIDX_SHIFT); + const int scale = extract32(desc, SIMD_DATA_SHIFT + MEMOPIDX_SHIFT, 2); + intptr_t i, oprsz = simd_oprsz(desc) / 8; + ARMVectorReg scratch = { }; +@@ -4952,7 +4905,7 @@ static void sve_ld1_zd(CPUARMState *env, void *vd, void *vg, void *vm, + uint8_t pg = *(uint8_t *)(vg + H1(i)); + if (likely(pg & 1)) { + target_ulong off = off_fn(vm, i * 8); +- tlb_fn(env, &scratch, i * 8, base + (off << scale), oi, ra); ++ tlb_fn(env, &scratch, i * 8, base + (off << scale), ra); + } + } + clear_helper_retaddr(); +@@ -5114,7 +5067,7 @@ DO_LD_NF(dd_be, , uint64_t, uint64_t, ldq_be_p) + */ + static inline void sve_ldff1_zs(CPUARMState *env, void *vd, void *vg, void *vm, + target_ulong base, uint32_t desc, uintptr_t ra, +- zreg_off_fn *off_fn, sve_ld1_tlb_fn *tlb_fn, ++ zreg_off_fn *off_fn, sve_ldst1_tlb_fn *tlb_fn, + sve_ld1_nf_fn *nonfault_fn) + { + const TCGMemOpIdx oi = extract32(desc, SIMD_DATA_SHIFT, MEMOPIDX_SHIFT); +@@ -5130,7 +5083,7 @@ static inline void sve_ldff1_zs(CPUARMState *env, void *vd, void *vg, void *vm, + set_helper_retaddr(ra); + addr = off_fn(vm, reg_off); + addr = base + (addr << scale); +- tlb_fn(env, vd, reg_off, addr, oi, ra); ++ tlb_fn(env, vd, reg_off, addr, ra); + + /* The rest of the reads will be non-faulting. */ + clear_helper_retaddr(); +@@ -5156,7 +5109,7 @@ static inline void sve_ldff1_zs(CPUARMState *env, void *vd, void *vg, void *vm, + + static inline void sve_ldff1_zd(CPUARMState *env, void *vd, void *vg, void *vm, + target_ulong base, uint32_t desc, uintptr_t ra, +- zreg_off_fn *off_fn, sve_ld1_tlb_fn *tlb_fn, ++ zreg_off_fn *off_fn, sve_ldst1_tlb_fn *tlb_fn, + sve_ld1_nf_fn *nonfault_fn) + { + const TCGMemOpIdx oi = extract32(desc, SIMD_DATA_SHIFT, MEMOPIDX_SHIFT); +@@ -5172,7 +5125,7 @@ static inline void sve_ldff1_zd(CPUARMState *env, void *vd, void *vg, void *vm, + set_helper_retaddr(ra); + addr = off_fn(vm, reg_off); + addr = base + (addr << scale); +- tlb_fn(env, vd, reg_off, addr, oi, ra); ++ tlb_fn(env, vd, reg_off, addr, ra); + + /* The rest of the reads will be non-faulting. */ + clear_helper_retaddr(); +@@ -5282,9 +5235,8 @@ DO_LDFF1_ZPZ_D(dd_be, zd) + + static void sve_st1_zs(CPUARMState *env, void *vd, void *vg, void *vm, + target_ulong base, uint32_t desc, uintptr_t ra, +- zreg_off_fn *off_fn, sve_ld1_tlb_fn *tlb_fn) ++ zreg_off_fn *off_fn, sve_ldst1_tlb_fn *tlb_fn) + { +- const TCGMemOpIdx oi = extract32(desc, SIMD_DATA_SHIFT, MEMOPIDX_SHIFT); + const int scale = extract32(desc, SIMD_DATA_SHIFT + MEMOPIDX_SHIFT, 2); + intptr_t i, oprsz = simd_oprsz(desc); + +@@ -5294,7 +5246,7 @@ static void sve_st1_zs(CPUARMState *env, void *vd, void *vg, void *vm, + do { + if (likely(pg & 1)) { + target_ulong off = off_fn(vm, i); +- tlb_fn(env, vd, i, base + (off << scale), oi, ra); ++ tlb_fn(env, vd, i, base + (off << scale), ra); + } + i += 4, pg >>= 4; + } while (i & 15); +@@ -5304,9 +5256,8 @@ static void sve_st1_zs(CPUARMState *env, void *vd, void *vg, void *vm, + + static void sve_st1_zd(CPUARMState *env, void *vd, void *vg, void *vm, + target_ulong base, uint32_t desc, uintptr_t ra, +- zreg_off_fn *off_fn, sve_ld1_tlb_fn *tlb_fn) ++ zreg_off_fn *off_fn, sve_ldst1_tlb_fn *tlb_fn) + { +- const TCGMemOpIdx oi = extract32(desc, SIMD_DATA_SHIFT, MEMOPIDX_SHIFT); + const int scale = extract32(desc, SIMD_DATA_SHIFT + MEMOPIDX_SHIFT, 2); + intptr_t i, oprsz = simd_oprsz(desc) / 8; + +@@ -5315,7 +5266,7 @@ static void sve_st1_zd(CPUARMState *env, void *vd, void *vg, void *vm, + uint8_t pg = *(uint8_t *)(vg + H1(i)); + if (likely(pg & 1)) { + target_ulong off = off_fn(vm, i * 8); +- tlb_fn(env, vd, i * 8, base + (off << scale), oi, ra); ++ tlb_fn(env, vd, i * 8, base + (off << scale), ra); + } + } + clear_helper_retaddr(); +-- +2.23.0 + diff --git a/target-arm-Use-enum-constant-in-get_phys_addr_lpae-c.patch b/target-arm-Use-enum-constant-in-get_phys_addr_lpae-c.patch new file mode 100644 index 0000000000000000000000000000000000000000..d6e58bb4d234ced49a28fcdc333fb6f59845be3f --- /dev/null +++ b/target-arm-Use-enum-constant-in-get_phys_addr_lpae-c.patch @@ -0,0 +1,37 @@ +From 59dff859cd850876df2cfa561c7bcfc4bdda4599 Mon Sep 17 00:00:00 2001 +From: Peter Maydell +Date: Mon, 30 Mar 2020 22:03:58 +0100 +Subject: [PATCH 152/709] target/arm: Use enum constant in get_phys_addr_lpae() + call + +The access_type argument to get_phys_addr_lpae() is an MMUAccessType; +use the enum constant MMU_DATA_LOAD rather than a literal 0 when we +call it in S1_ptw_translate(). + +Signed-off-by: Peter Maydell +Reviewed-by: Edgar E. Iglesias +Reviewed-by: Richard Henderson +Message-id: 20200330210400.11724-3-peter.maydell@linaro.org +--- + target/arm/helper.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/target/arm/helper.c b/target/arm/helper.c +index f785e012cd..f17841ec24 100644 +--- a/target/arm/helper.c ++++ b/target/arm/helper.c +@@ -10052,8 +10052,9 @@ static hwaddr S1_ptw_translate(CPUARMState *env, ARMMMUIdx mmu_idx, + pcacheattrs = &cacheattrs; + } + +- ret = get_phys_addr_lpae(env, addr, 0, ARMMMUIdx_Stage2, &s2pa, +- &txattrs, &s2prot, &s2size, fi, pcacheattrs); ++ ret = get_phys_addr_lpae(env, addr, MMU_DATA_LOAD, ARMMMUIdx_Stage2, ++ &s2pa, &txattrs, &s2prot, &s2size, fi, ++ pcacheattrs); + if (ret) { + assert(fi->type != ARMFault_None); + fi->s2addr = addr; +-- +2.23.0 + diff --git a/target-arm-Use-tcg_gen_gvec_5_ptr-for-sve-FMLA-FCMLA.patch b/target-arm-Use-tcg_gen_gvec_5_ptr-for-sve-FMLA-FCMLA.patch new file mode 100644 index 0000000000000000000000000000000000000000..d3ac2b327564b3122d800a8188cc34bcfc01caad --- /dev/null +++ b/target-arm-Use-tcg_gen_gvec_5_ptr-for-sve-FMLA-FCMLA.patch @@ -0,0 +1,508 @@ +From 08975da9f0bfcfa654628cae71201a351ba5449a Mon Sep 17 00:00:00 2001 +From: Richard Henderson +Date: Thu, 7 May 2020 10:23:49 -0700 +Subject: [PATCH 390/709] target/arm: Use tcg_gen_gvec_5_ptr for sve FMLA/FCMLA +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Now that we can pass 7 parameters, do not encode register +operands within simd_data. + +Reviewed-by: Alex Bennée +Reviewed-by: Taylor Simpson +Signed-off-by: Richard Henderson +Message-id: 20200507172352.15418-2-richard.henderson@linaro.org +Signed-off-by: Peter Maydell +--- + target/arm/helper-sve.h | 53 ++++++++----- + target/arm/sve_helper.c | 157 ++++++++++++++----------------------- + target/arm/translate-sve.c | 70 ++++++----------- + 3 files changed, 118 insertions(+), 162 deletions(-) + +diff --git a/target/arm/helper-sve.h b/target/arm/helper-sve.h +index 2f47279155..7a200755ac 100644 +--- a/target/arm/helper-sve.h ++++ b/target/arm/helper-sve.h +@@ -1099,25 +1099,40 @@ DEF_HELPER_FLAGS_6(sve_fcadd_s, TCG_CALL_NO_RWG, + DEF_HELPER_FLAGS_6(sve_fcadd_d, TCG_CALL_NO_RWG, + void, ptr, ptr, ptr, ptr, ptr, i32) + +-DEF_HELPER_FLAGS_3(sve_fmla_zpzzz_h, TCG_CALL_NO_RWG, void, env, ptr, i32) +-DEF_HELPER_FLAGS_3(sve_fmla_zpzzz_s, TCG_CALL_NO_RWG, void, env, ptr, i32) +-DEF_HELPER_FLAGS_3(sve_fmla_zpzzz_d, TCG_CALL_NO_RWG, void, env, ptr, i32) +- +-DEF_HELPER_FLAGS_3(sve_fmls_zpzzz_h, TCG_CALL_NO_RWG, void, env, ptr, i32) +-DEF_HELPER_FLAGS_3(sve_fmls_zpzzz_s, TCG_CALL_NO_RWG, void, env, ptr, i32) +-DEF_HELPER_FLAGS_3(sve_fmls_zpzzz_d, TCG_CALL_NO_RWG, void, env, ptr, i32) +- +-DEF_HELPER_FLAGS_3(sve_fnmla_zpzzz_h, TCG_CALL_NO_RWG, void, env, ptr, i32) +-DEF_HELPER_FLAGS_3(sve_fnmla_zpzzz_s, TCG_CALL_NO_RWG, void, env, ptr, i32) +-DEF_HELPER_FLAGS_3(sve_fnmla_zpzzz_d, TCG_CALL_NO_RWG, void, env, ptr, i32) +- +-DEF_HELPER_FLAGS_3(sve_fnmls_zpzzz_h, TCG_CALL_NO_RWG, void, env, ptr, i32) +-DEF_HELPER_FLAGS_3(sve_fnmls_zpzzz_s, TCG_CALL_NO_RWG, void, env, ptr, i32) +-DEF_HELPER_FLAGS_3(sve_fnmls_zpzzz_d, TCG_CALL_NO_RWG, void, env, ptr, i32) +- +-DEF_HELPER_FLAGS_3(sve_fcmla_zpzzz_h, TCG_CALL_NO_RWG, void, env, ptr, i32) +-DEF_HELPER_FLAGS_3(sve_fcmla_zpzzz_s, TCG_CALL_NO_RWG, void, env, ptr, i32) +-DEF_HELPER_FLAGS_3(sve_fcmla_zpzzz_d, TCG_CALL_NO_RWG, void, env, ptr, i32) ++DEF_HELPER_FLAGS_7(sve_fmla_zpzzz_h, TCG_CALL_NO_RWG, ++ void, ptr, ptr, ptr, ptr, ptr, ptr, i32) ++DEF_HELPER_FLAGS_7(sve_fmla_zpzzz_s, TCG_CALL_NO_RWG, ++ void, ptr, ptr, ptr, ptr, ptr, ptr, i32) ++DEF_HELPER_FLAGS_7(sve_fmla_zpzzz_d, TCG_CALL_NO_RWG, ++ void, ptr, ptr, ptr, ptr, ptr, ptr, i32) ++ ++DEF_HELPER_FLAGS_7(sve_fmls_zpzzz_h, TCG_CALL_NO_RWG, ++ void, ptr, ptr, ptr, ptr, ptr, ptr, i32) ++DEF_HELPER_FLAGS_7(sve_fmls_zpzzz_s, TCG_CALL_NO_RWG, ++ void, ptr, ptr, ptr, ptr, ptr, ptr, i32) ++DEF_HELPER_FLAGS_7(sve_fmls_zpzzz_d, TCG_CALL_NO_RWG, ++ void, ptr, ptr, ptr, ptr, ptr, ptr, i32) ++ ++DEF_HELPER_FLAGS_7(sve_fnmla_zpzzz_h, TCG_CALL_NO_RWG, ++ void, ptr, ptr, ptr, ptr, ptr, ptr, i32) ++DEF_HELPER_FLAGS_7(sve_fnmla_zpzzz_s, TCG_CALL_NO_RWG, ++ void, ptr, ptr, ptr, ptr, ptr, ptr, i32) ++DEF_HELPER_FLAGS_7(sve_fnmla_zpzzz_d, TCG_CALL_NO_RWG, ++ void, ptr, ptr, ptr, ptr, ptr, ptr, i32) ++ ++DEF_HELPER_FLAGS_7(sve_fnmls_zpzzz_h, TCG_CALL_NO_RWG, ++ void, ptr, ptr, ptr, ptr, ptr, ptr, i32) ++DEF_HELPER_FLAGS_7(sve_fnmls_zpzzz_s, TCG_CALL_NO_RWG, ++ void, ptr, ptr, ptr, ptr, ptr, ptr, i32) ++DEF_HELPER_FLAGS_7(sve_fnmls_zpzzz_d, TCG_CALL_NO_RWG, ++ void, ptr, ptr, ptr, ptr, ptr, ptr, i32) ++ ++DEF_HELPER_FLAGS_7(sve_fcmla_zpzzz_h, TCG_CALL_NO_RWG, ++ void, ptr, ptr, ptr, ptr, ptr, ptr, i32) ++DEF_HELPER_FLAGS_7(sve_fcmla_zpzzz_s, TCG_CALL_NO_RWG, ++ void, ptr, ptr, ptr, ptr, ptr, ptr, i32) ++DEF_HELPER_FLAGS_7(sve_fcmla_zpzzz_d, TCG_CALL_NO_RWG, ++ void, ptr, ptr, ptr, ptr, ptr, ptr, i32) + + DEF_HELPER_FLAGS_5(sve_ftmad_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32) + DEF_HELPER_FLAGS_5(sve_ftmad_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32) +diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c +index 116d535fa5..0da254d402 100644 +--- a/target/arm/sve_helper.c ++++ b/target/arm/sve_helper.c +@@ -3372,23 +3372,11 @@ DO_ZPZ_FP(sve_ucvt_dd, uint64_t, , uint64_to_float64) + + #undef DO_ZPZ_FP + +-/* 4-operand predicated multiply-add. This requires 7 operands to pass +- * "properly", so we need to encode some of the registers into DESC. +- */ +-QEMU_BUILD_BUG_ON(SIMD_DATA_SHIFT + 20 > 32); +- +-static void do_fmla_zpzzz_h(CPUARMState *env, void *vg, uint32_t desc, ++static void do_fmla_zpzzz_h(void *vd, void *vn, void *vm, void *va, void *vg, ++ float_status *status, uint32_t desc, + uint16_t neg1, uint16_t neg3) + { + intptr_t i = simd_oprsz(desc); +- unsigned rd = extract32(desc, SIMD_DATA_SHIFT, 5); +- unsigned rn = extract32(desc, SIMD_DATA_SHIFT + 5, 5); +- unsigned rm = extract32(desc, SIMD_DATA_SHIFT + 10, 5); +- unsigned ra = extract32(desc, SIMD_DATA_SHIFT + 15, 5); +- void *vd = &env->vfp.zregs[rd]; +- void *vn = &env->vfp.zregs[rn]; +- void *vm = &env->vfp.zregs[rm]; +- void *va = &env->vfp.zregs[ra]; + uint64_t *g = vg; + + do { +@@ -3401,45 +3389,42 @@ static void do_fmla_zpzzz_h(CPUARMState *env, void *vg, uint32_t desc, + e1 = *(uint16_t *)(vn + H1_2(i)) ^ neg1; + e2 = *(uint16_t *)(vm + H1_2(i)); + e3 = *(uint16_t *)(va + H1_2(i)) ^ neg3; +- r = float16_muladd(e1, e2, e3, 0, &env->vfp.fp_status_f16); ++ r = float16_muladd(e1, e2, e3, 0, status); + *(uint16_t *)(vd + H1_2(i)) = r; + } + } while (i & 63); + } while (i != 0); + } + +-void HELPER(sve_fmla_zpzzz_h)(CPUARMState *env, void *vg, uint32_t desc) ++void HELPER(sve_fmla_zpzzz_h)(void *vd, void *vn, void *vm, void *va, ++ void *vg, void *status, uint32_t desc) + { +- do_fmla_zpzzz_h(env, vg, desc, 0, 0); ++ do_fmla_zpzzz_h(vd, vn, vm, va, vg, status, desc, 0, 0); + } + +-void HELPER(sve_fmls_zpzzz_h)(CPUARMState *env, void *vg, uint32_t desc) ++void HELPER(sve_fmls_zpzzz_h)(void *vd, void *vn, void *vm, void *va, ++ void *vg, void *status, uint32_t desc) + { +- do_fmla_zpzzz_h(env, vg, desc, 0x8000, 0); ++ do_fmla_zpzzz_h(vd, vn, vm, va, vg, status, desc, 0x8000, 0); + } + +-void HELPER(sve_fnmla_zpzzz_h)(CPUARMState *env, void *vg, uint32_t desc) ++void HELPER(sve_fnmla_zpzzz_h)(void *vd, void *vn, void *vm, void *va, ++ void *vg, void *status, uint32_t desc) + { +- do_fmla_zpzzz_h(env, vg, desc, 0x8000, 0x8000); ++ do_fmla_zpzzz_h(vd, vn, vm, va, vg, status, desc, 0x8000, 0x8000); + } + +-void HELPER(sve_fnmls_zpzzz_h)(CPUARMState *env, void *vg, uint32_t desc) ++void HELPER(sve_fnmls_zpzzz_h)(void *vd, void *vn, void *vm, void *va, ++ void *vg, void *status, uint32_t desc) + { +- do_fmla_zpzzz_h(env, vg, desc, 0, 0x8000); ++ do_fmla_zpzzz_h(vd, vn, vm, va, vg, status, desc, 0, 0x8000); + } + +-static void do_fmla_zpzzz_s(CPUARMState *env, void *vg, uint32_t desc, ++static void do_fmla_zpzzz_s(void *vd, void *vn, void *vm, void *va, void *vg, ++ float_status *status, uint32_t desc, + uint32_t neg1, uint32_t neg3) + { + intptr_t i = simd_oprsz(desc); +- unsigned rd = extract32(desc, SIMD_DATA_SHIFT, 5); +- unsigned rn = extract32(desc, SIMD_DATA_SHIFT + 5, 5); +- unsigned rm = extract32(desc, SIMD_DATA_SHIFT + 10, 5); +- unsigned ra = extract32(desc, SIMD_DATA_SHIFT + 15, 5); +- void *vd = &env->vfp.zregs[rd]; +- void *vn = &env->vfp.zregs[rn]; +- void *vm = &env->vfp.zregs[rm]; +- void *va = &env->vfp.zregs[ra]; + uint64_t *g = vg; + + do { +@@ -3452,45 +3437,42 @@ static void do_fmla_zpzzz_s(CPUARMState *env, void *vg, uint32_t desc, + e1 = *(uint32_t *)(vn + H1_4(i)) ^ neg1; + e2 = *(uint32_t *)(vm + H1_4(i)); + e3 = *(uint32_t *)(va + H1_4(i)) ^ neg3; +- r = float32_muladd(e1, e2, e3, 0, &env->vfp.fp_status); ++ r = float32_muladd(e1, e2, e3, 0, status); + *(uint32_t *)(vd + H1_4(i)) = r; + } + } while (i & 63); + } while (i != 0); + } + +-void HELPER(sve_fmla_zpzzz_s)(CPUARMState *env, void *vg, uint32_t desc) ++void HELPER(sve_fmla_zpzzz_s)(void *vd, void *vn, void *vm, void *va, ++ void *vg, void *status, uint32_t desc) + { +- do_fmla_zpzzz_s(env, vg, desc, 0, 0); ++ do_fmla_zpzzz_s(vd, vn, vm, va, vg, status, desc, 0, 0); + } + +-void HELPER(sve_fmls_zpzzz_s)(CPUARMState *env, void *vg, uint32_t desc) ++void HELPER(sve_fmls_zpzzz_s)(void *vd, void *vn, void *vm, void *va, ++ void *vg, void *status, uint32_t desc) + { +- do_fmla_zpzzz_s(env, vg, desc, 0x80000000, 0); ++ do_fmla_zpzzz_s(vd, vn, vm, va, vg, status, desc, 0x80000000, 0); + } + +-void HELPER(sve_fnmla_zpzzz_s)(CPUARMState *env, void *vg, uint32_t desc) ++void HELPER(sve_fnmla_zpzzz_s)(void *vd, void *vn, void *vm, void *va, ++ void *vg, void *status, uint32_t desc) + { +- do_fmla_zpzzz_s(env, vg, desc, 0x80000000, 0x80000000); ++ do_fmla_zpzzz_s(vd, vn, vm, va, vg, status, desc, 0x80000000, 0x80000000); + } + +-void HELPER(sve_fnmls_zpzzz_s)(CPUARMState *env, void *vg, uint32_t desc) ++void HELPER(sve_fnmls_zpzzz_s)(void *vd, void *vn, void *vm, void *va, ++ void *vg, void *status, uint32_t desc) + { +- do_fmla_zpzzz_s(env, vg, desc, 0, 0x80000000); ++ do_fmla_zpzzz_s(vd, vn, vm, va, vg, status, desc, 0, 0x80000000); + } + +-static void do_fmla_zpzzz_d(CPUARMState *env, void *vg, uint32_t desc, ++static void do_fmla_zpzzz_d(void *vd, void *vn, void *vm, void *va, void *vg, ++ float_status *status, uint32_t desc, + uint64_t neg1, uint64_t neg3) + { + intptr_t i = simd_oprsz(desc); +- unsigned rd = extract32(desc, SIMD_DATA_SHIFT, 5); +- unsigned rn = extract32(desc, SIMD_DATA_SHIFT + 5, 5); +- unsigned rm = extract32(desc, SIMD_DATA_SHIFT + 10, 5); +- unsigned ra = extract32(desc, SIMD_DATA_SHIFT + 15, 5); +- void *vd = &env->vfp.zregs[rd]; +- void *vn = &env->vfp.zregs[rn]; +- void *vm = &env->vfp.zregs[rm]; +- void *va = &env->vfp.zregs[ra]; + uint64_t *g = vg; + + do { +@@ -3503,31 +3485,35 @@ static void do_fmla_zpzzz_d(CPUARMState *env, void *vg, uint32_t desc, + e1 = *(uint64_t *)(vn + i) ^ neg1; + e2 = *(uint64_t *)(vm + i); + e3 = *(uint64_t *)(va + i) ^ neg3; +- r = float64_muladd(e1, e2, e3, 0, &env->vfp.fp_status); ++ r = float64_muladd(e1, e2, e3, 0, status); + *(uint64_t *)(vd + i) = r; + } + } while (i & 63); + } while (i != 0); + } + +-void HELPER(sve_fmla_zpzzz_d)(CPUARMState *env, void *vg, uint32_t desc) ++void HELPER(sve_fmla_zpzzz_d)(void *vd, void *vn, void *vm, void *va, ++ void *vg, void *status, uint32_t desc) + { +- do_fmla_zpzzz_d(env, vg, desc, 0, 0); ++ do_fmla_zpzzz_d(vd, vn, vm, va, vg, status, desc, 0, 0); + } + +-void HELPER(sve_fmls_zpzzz_d)(CPUARMState *env, void *vg, uint32_t desc) ++void HELPER(sve_fmls_zpzzz_d)(void *vd, void *vn, void *vm, void *va, ++ void *vg, void *status, uint32_t desc) + { +- do_fmla_zpzzz_d(env, vg, desc, INT64_MIN, 0); ++ do_fmla_zpzzz_d(vd, vn, vm, va, vg, status, desc, INT64_MIN, 0); + } + +-void HELPER(sve_fnmla_zpzzz_d)(CPUARMState *env, void *vg, uint32_t desc) ++void HELPER(sve_fnmla_zpzzz_d)(void *vd, void *vn, void *vm, void *va, ++ void *vg, void *status, uint32_t desc) + { +- do_fmla_zpzzz_d(env, vg, desc, INT64_MIN, INT64_MIN); ++ do_fmla_zpzzz_d(vd, vn, vm, va, vg, status, desc, INT64_MIN, INT64_MIN); + } + +-void HELPER(sve_fnmls_zpzzz_d)(CPUARMState *env, void *vg, uint32_t desc) ++void HELPER(sve_fnmls_zpzzz_d)(void *vd, void *vn, void *vm, void *va, ++ void *vg, void *status, uint32_t desc) + { +- do_fmla_zpzzz_d(env, vg, desc, 0, INT64_MIN); ++ do_fmla_zpzzz_d(vd, vn, vm, va, vg, status, desc, 0, INT64_MIN); + } + + /* Two operand floating-point comparison controlled by a predicate. +@@ -3809,22 +3795,13 @@ void HELPER(sve_fcadd_d)(void *vd, void *vn, void *vm, void *vg, + * FP Complex Multiply + */ + +-QEMU_BUILD_BUG_ON(SIMD_DATA_SHIFT + 22 > 32); +- +-void HELPER(sve_fcmla_zpzzz_h)(CPUARMState *env, void *vg, uint32_t desc) ++void HELPER(sve_fcmla_zpzzz_h)(void *vd, void *vn, void *vm, void *va, ++ void *vg, void *status, uint32_t desc) + { + intptr_t j, i = simd_oprsz(desc); +- unsigned rd = extract32(desc, SIMD_DATA_SHIFT, 5); +- unsigned rn = extract32(desc, SIMD_DATA_SHIFT + 5, 5); +- unsigned rm = extract32(desc, SIMD_DATA_SHIFT + 10, 5); +- unsigned ra = extract32(desc, SIMD_DATA_SHIFT + 15, 5); +- unsigned rot = extract32(desc, SIMD_DATA_SHIFT + 20, 2); ++ unsigned rot = simd_data(desc); + bool flip = rot & 1; + float16 neg_imag, neg_real; +- void *vd = &env->vfp.zregs[rd]; +- void *vn = &env->vfp.zregs[rn]; +- void *vm = &env->vfp.zregs[rm]; +- void *va = &env->vfp.zregs[ra]; + uint64_t *g = vg; + + neg_imag = float16_set_sign(0, (rot & 2) != 0); +@@ -3851,32 +3828,25 @@ void HELPER(sve_fcmla_zpzzz_h)(CPUARMState *env, void *vg, uint32_t desc) + + if (likely((pg >> (i & 63)) & 1)) { + d = *(float16 *)(va + H1_2(i)); +- d = float16_muladd(e2, e1, d, 0, &env->vfp.fp_status_f16); ++ d = float16_muladd(e2, e1, d, 0, status); + *(float16 *)(vd + H1_2(i)) = d; + } + if (likely((pg >> (j & 63)) & 1)) { + d = *(float16 *)(va + H1_2(j)); +- d = float16_muladd(e4, e3, d, 0, &env->vfp.fp_status_f16); ++ d = float16_muladd(e4, e3, d, 0, status); + *(float16 *)(vd + H1_2(j)) = d; + } + } while (i & 63); + } while (i != 0); + } + +-void HELPER(sve_fcmla_zpzzz_s)(CPUARMState *env, void *vg, uint32_t desc) ++void HELPER(sve_fcmla_zpzzz_s)(void *vd, void *vn, void *vm, void *va, ++ void *vg, void *status, uint32_t desc) + { + intptr_t j, i = simd_oprsz(desc); +- unsigned rd = extract32(desc, SIMD_DATA_SHIFT, 5); +- unsigned rn = extract32(desc, SIMD_DATA_SHIFT + 5, 5); +- unsigned rm = extract32(desc, SIMD_DATA_SHIFT + 10, 5); +- unsigned ra = extract32(desc, SIMD_DATA_SHIFT + 15, 5); +- unsigned rot = extract32(desc, SIMD_DATA_SHIFT + 20, 2); ++ unsigned rot = simd_data(desc); + bool flip = rot & 1; + float32 neg_imag, neg_real; +- void *vd = &env->vfp.zregs[rd]; +- void *vn = &env->vfp.zregs[rn]; +- void *vm = &env->vfp.zregs[rm]; +- void *va = &env->vfp.zregs[ra]; + uint64_t *g = vg; + + neg_imag = float32_set_sign(0, (rot & 2) != 0); +@@ -3903,32 +3873,25 @@ void HELPER(sve_fcmla_zpzzz_s)(CPUARMState *env, void *vg, uint32_t desc) + + if (likely((pg >> (i & 63)) & 1)) { + d = *(float32 *)(va + H1_2(i)); +- d = float32_muladd(e2, e1, d, 0, &env->vfp.fp_status); ++ d = float32_muladd(e2, e1, d, 0, status); + *(float32 *)(vd + H1_2(i)) = d; + } + if (likely((pg >> (j & 63)) & 1)) { + d = *(float32 *)(va + H1_2(j)); +- d = float32_muladd(e4, e3, d, 0, &env->vfp.fp_status); ++ d = float32_muladd(e4, e3, d, 0, status); + *(float32 *)(vd + H1_2(j)) = d; + } + } while (i & 63); + } while (i != 0); + } + +-void HELPER(sve_fcmla_zpzzz_d)(CPUARMState *env, void *vg, uint32_t desc) ++void HELPER(sve_fcmla_zpzzz_d)(void *vd, void *vn, void *vm, void *va, ++ void *vg, void *status, uint32_t desc) + { + intptr_t j, i = simd_oprsz(desc); +- unsigned rd = extract32(desc, SIMD_DATA_SHIFT, 5); +- unsigned rn = extract32(desc, SIMD_DATA_SHIFT + 5, 5); +- unsigned rm = extract32(desc, SIMD_DATA_SHIFT + 10, 5); +- unsigned ra = extract32(desc, SIMD_DATA_SHIFT + 15, 5); +- unsigned rot = extract32(desc, SIMD_DATA_SHIFT + 20, 2); ++ unsigned rot = simd_data(desc); + bool flip = rot & 1; + float64 neg_imag, neg_real; +- void *vd = &env->vfp.zregs[rd]; +- void *vn = &env->vfp.zregs[rn]; +- void *vm = &env->vfp.zregs[rm]; +- void *va = &env->vfp.zregs[ra]; + uint64_t *g = vg; + + neg_imag = float64_set_sign(0, (rot & 2) != 0); +@@ -3955,12 +3918,12 @@ void HELPER(sve_fcmla_zpzzz_d)(CPUARMState *env, void *vg, uint32_t desc) + + if (likely((pg >> (i & 63)) & 1)) { + d = *(float64 *)(va + H1_2(i)); +- d = float64_muladd(e2, e1, d, 0, &env->vfp.fp_status); ++ d = float64_muladd(e2, e1, d, 0, status); + *(float64 *)(vd + H1_2(i)) = d; + } + if (likely((pg >> (j & 63)) & 1)) { + d = *(float64 *)(va + H1_2(j)); +- d = float64_muladd(e4, e3, d, 0, &env->vfp.fp_status); ++ d = float64_muladd(e4, e3, d, 0, status); + *(float64 *)(vd + H1_2(j)) = d; + } + } while (i & 63); +diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c +index 36816aafaf..8398c32362 100644 +--- a/target/arm/translate-sve.c ++++ b/target/arm/translate-sve.c +@@ -3946,42 +3946,30 @@ static bool trans_FCADD(DisasContext *s, arg_FCADD *a) + return true; + } + +-typedef void gen_helper_sve_fmla(TCGv_env, TCGv_ptr, TCGv_i32); +- +-static bool do_fmla(DisasContext *s, arg_rprrr_esz *a, gen_helper_sve_fmla *fn) ++static bool do_fmla(DisasContext *s, arg_rprrr_esz *a, ++ gen_helper_gvec_5_ptr *fn) + { +- if (fn == NULL) { ++ if (a->esz == 0) { + return false; + } +- if (!sve_access_check(s)) { +- return true; ++ if (sve_access_check(s)) { ++ unsigned vsz = vec_full_reg_size(s); ++ TCGv_ptr status = get_fpstatus_ptr(a->esz == MO_16); ++ tcg_gen_gvec_5_ptr(vec_full_reg_offset(s, a->rd), ++ vec_full_reg_offset(s, a->rn), ++ vec_full_reg_offset(s, a->rm), ++ vec_full_reg_offset(s, a->ra), ++ pred_full_reg_offset(s, a->pg), ++ status, vsz, vsz, 0, fn); ++ tcg_temp_free_ptr(status); + } +- +- unsigned vsz = vec_full_reg_size(s); +- unsigned desc; +- TCGv_i32 t_desc; +- TCGv_ptr pg = tcg_temp_new_ptr(); +- +- /* We would need 7 operands to pass these arguments "properly". +- * So we encode all the register numbers into the descriptor. +- */ +- desc = deposit32(a->rd, 5, 5, a->rn); +- desc = deposit32(desc, 10, 5, a->rm); +- desc = deposit32(desc, 15, 5, a->ra); +- desc = simd_desc(vsz, vsz, desc); +- +- t_desc = tcg_const_i32(desc); +- tcg_gen_addi_ptr(pg, cpu_env, pred_full_reg_offset(s, a->pg)); +- fn(cpu_env, pg, t_desc); +- tcg_temp_free_i32(t_desc); +- tcg_temp_free_ptr(pg); + return true; + } + + #define DO_FMLA(NAME, name) \ + static bool trans_##NAME(DisasContext *s, arg_rprrr_esz *a) \ + { \ +- static gen_helper_sve_fmla * const fns[4] = { \ ++ static gen_helper_gvec_5_ptr * const fns[4] = { \ + NULL, gen_helper_sve_##name##_h, \ + gen_helper_sve_##name##_s, gen_helper_sve_##name##_d \ + }; \ +@@ -3997,7 +3985,8 @@ DO_FMLA(FNMLS_zpzzz, fnmls_zpzzz) + + static bool trans_FCMLA_zpzzz(DisasContext *s, arg_FCMLA_zpzzz *a) + { +- static gen_helper_sve_fmla * const fns[3] = { ++ static gen_helper_gvec_5_ptr * const fns[4] = { ++ NULL, + gen_helper_sve_fcmla_zpzzz_h, + gen_helper_sve_fcmla_zpzzz_s, + gen_helper_sve_fcmla_zpzzz_d, +@@ -4008,25 +3997,14 @@ static bool trans_FCMLA_zpzzz(DisasContext *s, arg_FCMLA_zpzzz *a) + } + if (sve_access_check(s)) { + unsigned vsz = vec_full_reg_size(s); +- unsigned desc; +- TCGv_i32 t_desc; +- TCGv_ptr pg = tcg_temp_new_ptr(); +- +- /* We would need 7 operands to pass these arguments "properly". +- * So we encode all the register numbers into the descriptor. +- */ +- desc = deposit32(a->rd, 5, 5, a->rn); +- desc = deposit32(desc, 10, 5, a->rm); +- desc = deposit32(desc, 15, 5, a->ra); +- desc = deposit32(desc, 20, 2, a->rot); +- desc = sextract32(desc, 0, 22); +- desc = simd_desc(vsz, vsz, desc); +- +- t_desc = tcg_const_i32(desc); +- tcg_gen_addi_ptr(pg, cpu_env, pred_full_reg_offset(s, a->pg)); +- fns[a->esz - 1](cpu_env, pg, t_desc); +- tcg_temp_free_i32(t_desc); +- tcg_temp_free_ptr(pg); ++ TCGv_ptr status = get_fpstatus_ptr(a->esz == MO_16); ++ tcg_gen_gvec_5_ptr(vec_full_reg_offset(s, a->rd), ++ vec_full_reg_offset(s, a->rn), ++ vec_full_reg_offset(s, a->rm), ++ vec_full_reg_offset(s, a->ra), ++ pred_full_reg_offset(s, a->pg), ++ status, vsz, vsz, a->rot, fns[a->esz]); ++ tcg_temp_free_ptr(status); + } + return true; + } +-- +2.23.0 + diff --git a/target-arm-Use-tcg_gen_gvec_dup_imm.patch b/target-arm-Use-tcg_gen_gvec_dup_imm.patch new file mode 100644 index 0000000000000000000000000000000000000000..b8ca42665a700993e21489b7f933c325848d4da9 --- /dev/null +++ b/target-arm-Use-tcg_gen_gvec_dup_imm.patch @@ -0,0 +1,141 @@ +From 8711e71f9cbb692d614e6ecf5d51222372f7b77e Mon Sep 17 00:00:00 2001 +From: Richard Henderson +Date: Sat, 28 Mar 2020 15:12:52 -0700 +Subject: [PATCH 286/709] target/arm: Use tcg_gen_gvec_dup_imm +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +In a few cases, we're able to remove some manual replication. + +Reviewed-by: Alex Bennée +Signed-off-by: Richard Henderson +--- + target/arm/translate-a64.c | 10 +++++----- + target/arm/translate-sve.c | 12 +++++------- + target/arm/translate.c | 9 ++++++--- + 3 files changed, 16 insertions(+), 15 deletions(-) + +diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c +index a896f9c4b8..62e5729904 100644 +--- a/target/arm/translate-a64.c ++++ b/target/arm/translate-a64.c +@@ -502,7 +502,7 @@ static void clear_vec_high(DisasContext *s, bool is_q, int rd) + tcg_temp_free_i64(tcg_zero); + } + if (vsz > 16) { +- tcg_gen_gvec_dup8i(ofs + 16, vsz - 16, vsz - 16, 0); ++ tcg_gen_gvec_dup_imm(MO_64, ofs + 16, vsz - 16, vsz - 16, 0); + } + } + +@@ -7785,8 +7785,8 @@ static void disas_simd_mod_imm(DisasContext *s, uint32_t insn) + + if (!((cmode & 0x9) == 0x1 || (cmode & 0xd) == 0x9)) { + /* MOVI or MVNI, with MVNI negation handled above. */ +- tcg_gen_gvec_dup64i(vec_full_reg_offset(s, rd), is_q ? 16 : 8, +- vec_full_reg_size(s), imm); ++ tcg_gen_gvec_dup_imm(MO_64, vec_full_reg_offset(s, rd), is_q ? 16 : 8, ++ vec_full_reg_size(s), imm); + } else { + /* ORR or BIC, with BIC negation to AND handled above. */ + if (is_neg) { +@@ -10214,8 +10214,8 @@ static void handle_vec_simd_shri(DisasContext *s, bool is_q, bool is_u, + if (is_u) { + if (shift == 8 << size) { + /* Shift count the same size as element size produces zero. */ +- tcg_gen_gvec_dup8i(vec_full_reg_offset(s, rd), +- is_q ? 16 : 8, vec_full_reg_size(s), 0); ++ tcg_gen_gvec_dup_imm(size, vec_full_reg_offset(s, rd), ++ is_q ? 16 : 8, vec_full_reg_size(s), 0); + } else { + gen_gvec_fn2i(s, is_q, rd, rn, shift, tcg_gen_gvec_shri, size); + } +diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c +index b35bad245e..6c8bda4e4c 100644 +--- a/target/arm/translate-sve.c ++++ b/target/arm/translate-sve.c +@@ -177,7 +177,7 @@ static bool do_mov_z(DisasContext *s, int rd, int rn) + static void do_dupi_z(DisasContext *s, int rd, uint64_t word) + { + unsigned vsz = vec_full_reg_size(s); +- tcg_gen_gvec_dup64i(vec_full_reg_offset(s, rd), vsz, vsz, word); ++ tcg_gen_gvec_dup_imm(MO_64, vec_full_reg_offset(s, rd), vsz, vsz, word); + } + + /* Invoke a vector expander on two Pregs. */ +@@ -1453,7 +1453,7 @@ static bool do_predset(DisasContext *s, int esz, int rd, int pat, bool setflag) + unsigned oprsz = size_for_gvec(setsz / 8); + + if (oprsz * 8 == setsz) { +- tcg_gen_gvec_dup64i(ofs, oprsz, maxsz, word); ++ tcg_gen_gvec_dup_imm(MO_64, ofs, oprsz, maxsz, word); + goto done; + } + } +@@ -2044,7 +2044,7 @@ static bool trans_DUP_x(DisasContext *s, arg_DUP_x *a) + unsigned nofs = vec_reg_offset(s, a->rn, index, esz); + tcg_gen_gvec_dup_mem(esz, dofs, nofs, vsz, vsz); + } else { +- tcg_gen_gvec_dup64i(dofs, vsz, vsz, 0); ++ tcg_gen_gvec_dup_imm(esz, dofs, vsz, vsz, 0); + } + } + return true; +@@ -3260,9 +3260,7 @@ static bool trans_FDUP(DisasContext *s, arg_FDUP *a) + + /* Decode the VFP immediate. */ + imm = vfp_expand_imm(a->esz, a->imm); +- imm = dup_const(a->esz, imm); +- +- tcg_gen_gvec_dup64i(dofs, vsz, vsz, imm); ++ tcg_gen_gvec_dup_imm(a->esz, dofs, vsz, vsz, imm); + } + return true; + } +@@ -3276,7 +3274,7 @@ static bool trans_DUP_i(DisasContext *s, arg_DUP_i *a) + unsigned vsz = vec_full_reg_size(s); + int dofs = vec_full_reg_offset(s, a->rd); + +- tcg_gen_gvec_dup64i(dofs, vsz, vsz, dup_const(a->esz, a->imm)); ++ tcg_gen_gvec_dup_imm(a->esz, dofs, vsz, vsz, a->imm); + } + return true; + } +diff --git a/target/arm/translate.c b/target/arm/translate.c +index 025747c0bd..74fac1d09c 100644 +--- a/target/arm/translate.c ++++ b/target/arm/translate.c +@@ -5209,7 +5209,8 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn) + MIN(shift, (8 << size) - 1), + vec_size, vec_size); + } else if (shift >= 8 << size) { +- tcg_gen_gvec_dup8i(rd_ofs, vec_size, vec_size, 0); ++ tcg_gen_gvec_dup_imm(MO_8, rd_ofs, vec_size, ++ vec_size, 0); + } else { + tcg_gen_gvec_shri(size, rd_ofs, rm_ofs, shift, + vec_size, vec_size); +@@ -5260,7 +5261,8 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn) + * architecturally valid and results in zero. + */ + if (shift >= 8 << size) { +- tcg_gen_gvec_dup8i(rd_ofs, vec_size, vec_size, 0); ++ tcg_gen_gvec_dup_imm(size, rd_ofs, ++ vec_size, vec_size, 0); + } else { + tcg_gen_gvec_shli(size, rd_ofs, rm_ofs, shift, + vec_size, vec_size); +@@ -5606,7 +5608,8 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn) + } + tcg_temp_free_i64(t64); + } else { +- tcg_gen_gvec_dup32i(reg_ofs, vec_size, vec_size, imm); ++ tcg_gen_gvec_dup_imm(MO_32, reg_ofs, vec_size, ++ vec_size, imm); + } + } + } +-- +2.23.0 + diff --git a/target-arm-Use-tcg_gen_gvec_mov-for-clear_vec_high.patch b/target-arm-Use-tcg_gen_gvec_mov-for-clear_vec_high.patch new file mode 100644 index 0000000000000000000000000000000000000000..c88b808827abd07a900812ff931f02f9cb66a46f --- /dev/null +++ b/target-arm-Use-tcg_gen_gvec_mov-for-clear_vec_high.patch @@ -0,0 +1,44 @@ +From 5c27392dd08bd8534893abf25ef501f1bd8680fe Mon Sep 17 00:00:00 2001 +From: Richard Henderson +Date: Tue, 19 May 2020 14:24:52 -0700 +Subject: [PATCH 631/709] target/arm: Use tcg_gen_gvec_mov for clear_vec_high +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The 8-byte store for the end a !is_q operation can be +merged with the other stores. Use a no-op vector move +to trigger the expand_clr portion of tcg_gen_gvec_mov. + +Reviewed-by: Alex Bennée +Signed-off-by: Richard Henderson +Message-id: 20200519212453.28494-2-richard.henderson@linaro.org +Signed-off-by: Peter Maydell +--- + target/arm/translate-a64.c | 10 ++-------- + 1 file changed, 2 insertions(+), 8 deletions(-) + +diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c +index 991e451644..4f6edb2892 100644 +--- a/target/arm/translate-a64.c ++++ b/target/arm/translate-a64.c +@@ -496,14 +496,8 @@ static void clear_vec_high(DisasContext *s, bool is_q, int rd) + unsigned ofs = fp_reg_offset(s, rd, MO_64); + unsigned vsz = vec_full_reg_size(s); + +- if (!is_q) { +- TCGv_i64 tcg_zero = tcg_const_i64(0); +- tcg_gen_st_i64(tcg_zero, cpu_env, ofs + 8); +- tcg_temp_free_i64(tcg_zero); +- } +- if (vsz > 16) { +- tcg_gen_gvec_dup_imm(MO_64, ofs + 16, vsz - 16, vsz - 16, 0); +- } ++ /* Nop move, with side effect of clearing the tail. */ ++ tcg_gen_gvec_mov(MO_64, ofs, ofs, is_q ? 16 : 8, vsz); + } + + void write_fp_dreg(DisasContext *s, int reg, TCGv_i64 v) +-- +2.23.0 + diff --git a/target-arm-Use-uint64_t-for-midr-field-in-CPU-state-.patch b/target-arm-Use-uint64_t-for-midr-field-in-CPU-state-.patch new file mode 100644 index 0000000000000000000000000000000000000000..ecdf8f19fea118175b116a5488bf38ea077ae075 --- /dev/null +++ b/target-arm-Use-uint64_t-for-midr-field-in-CPU-state-.patch @@ -0,0 +1,66 @@ +From e544f80030121040c8932ff1bd4006f390266c0f Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Tue, 28 Apr 2020 19:26:34 +0200 +Subject: [PATCH 156/709] target/arm: Use uint64_t for midr field in CPU state + struct +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +MIDR_EL1 is a 64-bit system register with the top 32-bit being RES0. +Represent it in QEMU's ARMCPU struct with a uint64_t, not a +uint32_t. + +This fixes an error when compiling with -Werror=conversion +because we were manipulating the register value using a +local uint64_t variable: + + target/arm/cpu64.c: In function ‘aarch64_max_initfn’: + target/arm/cpu64.c:628:21: error: conversion from ‘uint64_t’ {aka ‘long unsigned int’} to ‘uint32_t’ {aka ‘unsigned int’} may change value [-Werror=conversion] + 628 | cpu->midr = t; + | ^ + +and future-proofs us against a possible future architecture +change using some of the top 32 bits. + +Suggested-by: Laurent Desnogues +Suggested-by: Peter Maydell +Signed-off-by: Philippe Mathieu-Daudé +Reviewed-by: Laurent Desnogues +Message-id: 20200428172634.29707-1-f4bug@amsat.org +Reviewed-by: Peter Maydell +Signed-off-by: Peter Maydell +--- + target/arm/cpu.c | 2 +- + target/arm/cpu.h | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/target/arm/cpu.c b/target/arm/cpu.c +index f588344df8..5d64adfe76 100644 +--- a/target/arm/cpu.c ++++ b/target/arm/cpu.c +@@ -2755,7 +2755,7 @@ static const ARMCPUInfo arm_cpus[] = { + static Property arm_cpu_properties[] = { + DEFINE_PROP_BOOL("start-powered-off", ARMCPU, start_powered_off, false), + DEFINE_PROP_UINT32("psci-conduit", ARMCPU, psci_conduit, 0), +- DEFINE_PROP_UINT32("midr", ARMCPU, midr, 0), ++ DEFINE_PROP_UINT64("midr", ARMCPU, midr, 0), + DEFINE_PROP_UINT64("mp-affinity", ARMCPU, + mp_affinity, ARM64_AFFINITY_INVALID), + DEFINE_PROP_INT32("node-id", ARMCPU, node_id, CPU_UNSET_NUMA_NODE_ID), +diff --git a/target/arm/cpu.h b/target/arm/cpu.h +index 9aae324d0f..8608da6b6f 100644 +--- a/target/arm/cpu.h ++++ b/target/arm/cpu.h +@@ -894,7 +894,7 @@ struct ARMCPU { + uint64_t id_aa64dfr0; + uint64_t id_aa64dfr1; + } isar; +- uint32_t midr; ++ uint64_t midr; + uint32_t revidr; + uint32_t reset_fpsid; + uint32_t ctr; +-- +2.23.0 + diff --git a/target-arm-Vectorize-SABA-UABA.patch b/target-arm-Vectorize-SABA-UABA.patch new file mode 100644 index 0000000000000000000000000000000000000000..1b41741fee3bd9d4a076e7d89408a164371a6f47 --- /dev/null +++ b/target-arm-Vectorize-SABA-UABA.patch @@ -0,0 +1,321 @@ +From cfdb2c0c95ae9205b0dd7f0f5e970cdec50fef20 Mon Sep 17 00:00:00 2001 +From: Richard Henderson +Date: Wed, 13 May 2020 09:32:45 -0700 +Subject: [PATCH 434/709] target/arm: Vectorize SABA/UABA + +Include 64-bit element size in preparation for SVE2. + +Reviewed-by: Peter Maydell +Signed-off-by: Richard Henderson +Message-id: 20200513163245.17915-17-richard.henderson@linaro.org +Signed-off-by: Peter Maydell +--- + target/arm/helper.h | 17 +++-- + target/arm/neon_helper.c | 10 --- + target/arm/translate-a64.c | 17 ++--- + target/arm/translate.c | 134 +++++++++++++++++++++++++++++++++++-- + target/arm/translate.h | 5 ++ + target/arm/vec_helper.c | 24 +++++++ + 6 files changed, 174 insertions(+), 33 deletions(-) + +diff --git a/target/arm/helper.h b/target/arm/helper.h +index 4678d3a6f4..1857f4ee46 100644 +--- a/target/arm/helper.h ++++ b/target/arm/helper.h +@@ -284,13 +284,6 @@ DEF_HELPER_2(neon_pmax_s8, i32, i32, i32) + DEF_HELPER_2(neon_pmax_u16, i32, i32, i32) + DEF_HELPER_2(neon_pmax_s16, i32, i32, i32) + +-DEF_HELPER_2(neon_abd_u8, i32, i32, i32) +-DEF_HELPER_2(neon_abd_s8, i32, i32, i32) +-DEF_HELPER_2(neon_abd_u16, i32, i32, i32) +-DEF_HELPER_2(neon_abd_s16, i32, i32, i32) +-DEF_HELPER_2(neon_abd_u32, i32, i32, i32) +-DEF_HELPER_2(neon_abd_s32, i32, i32, i32) +- + DEF_HELPER_2(neon_shl_u16, i32, i32, i32) + DEF_HELPER_2(neon_shl_s16, i32, i32, i32) + DEF_HELPER_2(neon_rshl_u8, i32, i32, i32) +@@ -741,6 +734,16 @@ DEF_HELPER_FLAGS_4(gvec_uabd_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) + DEF_HELPER_FLAGS_4(gvec_uabd_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) + DEF_HELPER_FLAGS_4(gvec_uabd_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) + ++DEF_HELPER_FLAGS_4(gvec_saba_b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) ++DEF_HELPER_FLAGS_4(gvec_saba_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) ++DEF_HELPER_FLAGS_4(gvec_saba_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) ++DEF_HELPER_FLAGS_4(gvec_saba_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) ++ ++DEF_HELPER_FLAGS_4(gvec_uaba_b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) ++DEF_HELPER_FLAGS_4(gvec_uaba_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) ++DEF_HELPER_FLAGS_4(gvec_uaba_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) ++DEF_HELPER_FLAGS_4(gvec_uaba_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) ++ + #ifdef TARGET_AARCH64 + #include "helper-a64.h" + #include "helper-sve.h" +diff --git a/target/arm/neon_helper.c b/target/arm/neon_helper.c +index 448be93fa1..2ef75e04c8 100644 +--- a/target/arm/neon_helper.c ++++ b/target/arm/neon_helper.c +@@ -576,16 +576,6 @@ NEON_POP(pmax_s16, neon_s16, 2) + NEON_POP(pmax_u16, neon_u16, 2) + #undef NEON_FN + +-#define NEON_FN(dest, src1, src2) \ +- dest = (src1 > src2) ? (src1 - src2) : (src2 - src1) +-NEON_VOP(abd_s8, neon_s8, 4) +-NEON_VOP(abd_u8, neon_u8, 4) +-NEON_VOP(abd_s16, neon_s16, 2) +-NEON_VOP(abd_u16, neon_u16, 2) +-NEON_VOP(abd_s32, neon_s32, 1) +-NEON_VOP(abd_u32, neon_u32, 1) +-#undef NEON_FN +- + #define NEON_FN(dest, src1, src2) do { \ + int8_t tmp; \ + tmp = (int8_t)src2; \ +diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c +index 54b06553a6..991e451644 100644 +--- a/target/arm/translate-a64.c ++++ b/target/arm/translate-a64.c +@@ -11197,6 +11197,13 @@ static void disas_simd_3same_int(DisasContext *s, uint32_t insn) + gen_gvec_fn3(s, is_q, rd, rn, rm, gen_gvec_sabd, size); + } + return; ++ case 0xf: /* SABA, UABA */ ++ if (u) { ++ gen_gvec_fn3(s, is_q, rd, rn, rm, gen_gvec_uaba, size); ++ } else { ++ gen_gvec_fn3(s, is_q, rd, rn, rm, gen_gvec_saba, size); ++ } ++ return; + case 0x10: /* ADD, SUB */ + if (u) { + gen_gvec_fn3(s, is_q, rd, rn, rm, tcg_gen_gvec_sub, size); +@@ -11329,16 +11336,6 @@ static void disas_simd_3same_int(DisasContext *s, uint32_t insn) + genenvfn = fns[size][u]; + break; + } +- case 0xf: /* SABA, UABA */ +- { +- static NeonGenTwoOpFn * const fns[3][2] = { +- { gen_helper_neon_abd_s8, gen_helper_neon_abd_u8 }, +- { gen_helper_neon_abd_s16, gen_helper_neon_abd_u16 }, +- { gen_helper_neon_abd_s32, gen_helper_neon_abd_u32 }, +- }; +- genfn = fns[size][u]; +- break; +- } + case 0x16: /* SQDMULH, SQRDMULH */ + { + static NeonGenTwoOpEnvFn * const fns[2][2] = { +diff --git a/target/arm/translate.c b/target/arm/translate.c +index d288721c23..e3d37ef2e9 100644 +--- a/target/arm/translate.c ++++ b/target/arm/translate.c +@@ -5222,6 +5222,124 @@ void gen_gvec_uabd(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs, + tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]); + } + ++static void gen_saba_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b) ++{ ++ TCGv_i32 t = tcg_temp_new_i32(); ++ gen_sabd_i32(t, a, b); ++ tcg_gen_add_i32(d, d, t); ++ tcg_temp_free_i32(t); ++} ++ ++static void gen_saba_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b) ++{ ++ TCGv_i64 t = tcg_temp_new_i64(); ++ gen_sabd_i64(t, a, b); ++ tcg_gen_add_i64(d, d, t); ++ tcg_temp_free_i64(t); ++} ++ ++static void gen_saba_vec(unsigned vece, TCGv_vec d, TCGv_vec a, TCGv_vec b) ++{ ++ TCGv_vec t = tcg_temp_new_vec_matching(d); ++ gen_sabd_vec(vece, t, a, b); ++ tcg_gen_add_vec(vece, d, d, t); ++ tcg_temp_free_vec(t); ++} ++ ++void gen_gvec_saba(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs, ++ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz) ++{ ++ static const TCGOpcode vecop_list[] = { ++ INDEX_op_sub_vec, INDEX_op_add_vec, ++ INDEX_op_smin_vec, INDEX_op_smax_vec, 0 ++ }; ++ static const GVecGen3 ops[4] = { ++ { .fniv = gen_saba_vec, ++ .fno = gen_helper_gvec_saba_b, ++ .opt_opc = vecop_list, ++ .load_dest = true, ++ .vece = MO_8 }, ++ { .fniv = gen_saba_vec, ++ .fno = gen_helper_gvec_saba_h, ++ .opt_opc = vecop_list, ++ .load_dest = true, ++ .vece = MO_16 }, ++ { .fni4 = gen_saba_i32, ++ .fniv = gen_saba_vec, ++ .fno = gen_helper_gvec_saba_s, ++ .opt_opc = vecop_list, ++ .load_dest = true, ++ .vece = MO_32 }, ++ { .fni8 = gen_saba_i64, ++ .fniv = gen_saba_vec, ++ .fno = gen_helper_gvec_saba_d, ++ .prefer_i64 = TCG_TARGET_REG_BITS == 64, ++ .opt_opc = vecop_list, ++ .load_dest = true, ++ .vece = MO_64 }, ++ }; ++ tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]); ++} ++ ++static void gen_uaba_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b) ++{ ++ TCGv_i32 t = tcg_temp_new_i32(); ++ gen_uabd_i32(t, a, b); ++ tcg_gen_add_i32(d, d, t); ++ tcg_temp_free_i32(t); ++} ++ ++static void gen_uaba_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b) ++{ ++ TCGv_i64 t = tcg_temp_new_i64(); ++ gen_uabd_i64(t, a, b); ++ tcg_gen_add_i64(d, d, t); ++ tcg_temp_free_i64(t); ++} ++ ++static void gen_uaba_vec(unsigned vece, TCGv_vec d, TCGv_vec a, TCGv_vec b) ++{ ++ TCGv_vec t = tcg_temp_new_vec_matching(d); ++ gen_uabd_vec(vece, t, a, b); ++ tcg_gen_add_vec(vece, d, d, t); ++ tcg_temp_free_vec(t); ++} ++ ++void gen_gvec_uaba(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs, ++ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz) ++{ ++ static const TCGOpcode vecop_list[] = { ++ INDEX_op_sub_vec, INDEX_op_add_vec, ++ INDEX_op_umin_vec, INDEX_op_umax_vec, 0 ++ }; ++ static const GVecGen3 ops[4] = { ++ { .fniv = gen_uaba_vec, ++ .fno = gen_helper_gvec_uaba_b, ++ .opt_opc = vecop_list, ++ .load_dest = true, ++ .vece = MO_8 }, ++ { .fniv = gen_uaba_vec, ++ .fno = gen_helper_gvec_uaba_h, ++ .opt_opc = vecop_list, ++ .load_dest = true, ++ .vece = MO_16 }, ++ { .fni4 = gen_uaba_i32, ++ .fniv = gen_uaba_vec, ++ .fno = gen_helper_gvec_uaba_s, ++ .opt_opc = vecop_list, ++ .load_dest = true, ++ .vece = MO_32 }, ++ { .fni8 = gen_uaba_i64, ++ .fniv = gen_uaba_vec, ++ .fno = gen_helper_gvec_uaba_d, ++ .prefer_i64 = TCG_TARGET_REG_BITS == 64, ++ .opt_opc = vecop_list, ++ .load_dest = true, ++ .vece = MO_64 }, ++ }; ++ tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]); ++} ++ + /* Translate a NEON data processing instruction. Return nonzero if the + instruction is invalid. + We process data in a mixture of 32-bit and 64-bit chunks. +@@ -5366,6 +5484,16 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn) + } + return 0; + ++ case NEON_3R_VABA: ++ if (u) { ++ gen_gvec_uaba(size, rd_ofs, rn_ofs, rm_ofs, ++ vec_size, vec_size); ++ } else { ++ gen_gvec_saba(size, rd_ofs, rn_ofs, rm_ofs, ++ vec_size, vec_size); ++ } ++ return 0; ++ + case NEON_3R_VADD_VSUB: + case NEON_3R_LOGIC: + case NEON_3R_VMAX: +@@ -5510,12 +5638,6 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn) + case NEON_3R_VQRSHL: + GEN_NEON_INTEGER_OP_ENV(qrshl); + break; +- case NEON_3R_VABA: +- GEN_NEON_INTEGER_OP(abd); +- tcg_temp_free_i32(tmp2); +- tmp2 = neon_load_reg(rd, pass); +- gen_neon_add(size, tmp, tmp2); +- break; + case NEON_3R_VPMAX: + GEN_NEON_INTEGER_OP(pmax); + break; +diff --git a/target/arm/translate.h b/target/arm/translate.h +index bbfe3d1393..c937dfe9bf 100644 +--- a/target/arm/translate.h ++++ b/target/arm/translate.h +@@ -342,6 +342,11 @@ void gen_gvec_sabd(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs, + void gen_gvec_uabd(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs, + uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz); + ++void gen_gvec_saba(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs, ++ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz); ++void gen_gvec_uaba(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs, ++ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz); ++ + /* + * Forward to the isar_feature_* tests given a DisasContext pointer. + */ +diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c +index a4972d02fc..fa33df859e 100644 +--- a/target/arm/vec_helper.c ++++ b/target/arm/vec_helper.c +@@ -1431,3 +1431,27 @@ DO_ABD(gvec_uabd_s, uint32_t) + DO_ABD(gvec_uabd_d, uint64_t) + + #undef DO_ABD ++ ++#define DO_ABA(NAME, TYPE) \ ++void HELPER(NAME)(void *vd, void *vn, void *vm, uint32_t desc) \ ++{ \ ++ intptr_t i, opr_sz = simd_oprsz(desc); \ ++ TYPE *d = vd, *n = vn, *m = vm; \ ++ \ ++ for (i = 0; i < opr_sz / sizeof(TYPE); ++i) { \ ++ d[i] += n[i] < m[i] ? m[i] - n[i] : n[i] - m[i]; \ ++ } \ ++ clear_tail(d, opr_sz, simd_maxsz(desc)); \ ++} ++ ++DO_ABA(gvec_saba_b, int8_t) ++DO_ABA(gvec_saba_h, int16_t) ++DO_ABA(gvec_saba_s, int32_t) ++DO_ABA(gvec_saba_d, int64_t) ++ ++DO_ABA(gvec_uaba_b, uint8_t) ++DO_ABA(gvec_uaba_h, uint16_t) ++DO_ABA(gvec_uaba_s, uint32_t) ++DO_ABA(gvec_uaba_d, uint64_t) ++ ++#undef DO_ABA +-- +2.23.0 + diff --git a/target-arm-Vectorize-SABD-UABD.patch b/target-arm-Vectorize-SABD-UABD.patch new file mode 100644 index 0000000000000000000000000000000000000000..80bb6988074c793a56bf815bc2c48af3958a8065 --- /dev/null +++ b/target-arm-Vectorize-SABD-UABD.patch @@ -0,0 +1,275 @@ +From 50c160d44eb059c7fc7f348ae2c3b0cb41437044 Mon Sep 17 00:00:00 2001 +From: Richard Henderson +Date: Wed, 13 May 2020 09:32:44 -0700 +Subject: [PATCH 433/709] target/arm: Vectorize SABD/UABD + +Include 64-bit element size in preparation for SVE2. + +Reviewed-by: Peter Maydell +Signed-off-by: Richard Henderson +Message-id: 20200513163245.17915-16-richard.henderson@linaro.org +Signed-off-by: Peter Maydell +--- + target/arm/helper.h | 10 +++ + target/arm/translate-a64.c | 8 ++- + target/arm/translate.c | 133 ++++++++++++++++++++++++++++++++++++- + target/arm/translate.h | 5 ++ + target/arm/vec_helper.c | 24 +++++++ + 5 files changed, 176 insertions(+), 4 deletions(-) + +diff --git a/target/arm/helper.h b/target/arm/helper.h +index aed3050965..4678d3a6f4 100644 +--- a/target/arm/helper.h ++++ b/target/arm/helper.h +@@ -731,6 +731,16 @@ DEF_HELPER_FLAGS_3(gvec_sli_h, TCG_CALL_NO_RWG, void, ptr, ptr, i32) + DEF_HELPER_FLAGS_3(gvec_sli_s, TCG_CALL_NO_RWG, void, ptr, ptr, i32) + DEF_HELPER_FLAGS_3(gvec_sli_d, TCG_CALL_NO_RWG, void, ptr, ptr, i32) + ++DEF_HELPER_FLAGS_4(gvec_sabd_b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) ++DEF_HELPER_FLAGS_4(gvec_sabd_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) ++DEF_HELPER_FLAGS_4(gvec_sabd_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) ++DEF_HELPER_FLAGS_4(gvec_sabd_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) ++ ++DEF_HELPER_FLAGS_4(gvec_uabd_b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) ++DEF_HELPER_FLAGS_4(gvec_uabd_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) ++DEF_HELPER_FLAGS_4(gvec_uabd_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) ++DEF_HELPER_FLAGS_4(gvec_uabd_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) ++ + #ifdef TARGET_AARCH64 + #include "helper-a64.h" + #include "helper-sve.h" +diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c +index 4577df3cf4..54b06553a6 100644 +--- a/target/arm/translate-a64.c ++++ b/target/arm/translate-a64.c +@@ -11190,6 +11190,13 @@ static void disas_simd_3same_int(DisasContext *s, uint32_t insn) + gen_gvec_fn3(s, is_q, rd, rn, rm, tcg_gen_gvec_smin, size); + } + return; ++ case 0xe: /* SABD, UABD */ ++ if (u) { ++ gen_gvec_fn3(s, is_q, rd, rn, rm, gen_gvec_uabd, size); ++ } else { ++ gen_gvec_fn3(s, is_q, rd, rn, rm, gen_gvec_sabd, size); ++ } ++ return; + case 0x10: /* ADD, SUB */ + if (u) { + gen_gvec_fn3(s, is_q, rd, rn, rm, tcg_gen_gvec_sub, size); +@@ -11322,7 +11329,6 @@ static void disas_simd_3same_int(DisasContext *s, uint32_t insn) + genenvfn = fns[size][u]; + break; + } +- case 0xe: /* SABD, UABD */ + case 0xf: /* SABA, UABA */ + { + static NeonGenTwoOpFn * const fns[3][2] = { +diff --git a/target/arm/translate.c b/target/arm/translate.c +index 21529a9b8f..d288721c23 100644 +--- a/target/arm/translate.c ++++ b/target/arm/translate.c +@@ -5102,6 +5102,126 @@ void gen_gvec_sqsub_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs, + rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]); + } + ++static void gen_sabd_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b) ++{ ++ TCGv_i32 t = tcg_temp_new_i32(); ++ ++ tcg_gen_sub_i32(t, a, b); ++ tcg_gen_sub_i32(d, b, a); ++ tcg_gen_movcond_i32(TCG_COND_LT, d, a, b, d, t); ++ tcg_temp_free_i32(t); ++} ++ ++static void gen_sabd_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b) ++{ ++ TCGv_i64 t = tcg_temp_new_i64(); ++ ++ tcg_gen_sub_i64(t, a, b); ++ tcg_gen_sub_i64(d, b, a); ++ tcg_gen_movcond_i64(TCG_COND_LT, d, a, b, d, t); ++ tcg_temp_free_i64(t); ++} ++ ++static void gen_sabd_vec(unsigned vece, TCGv_vec d, TCGv_vec a, TCGv_vec b) ++{ ++ TCGv_vec t = tcg_temp_new_vec_matching(d); ++ ++ tcg_gen_smin_vec(vece, t, a, b); ++ tcg_gen_smax_vec(vece, d, a, b); ++ tcg_gen_sub_vec(vece, d, d, t); ++ tcg_temp_free_vec(t); ++} ++ ++void gen_gvec_sabd(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs, ++ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz) ++{ ++ static const TCGOpcode vecop_list[] = { ++ INDEX_op_sub_vec, INDEX_op_smin_vec, INDEX_op_smax_vec, 0 ++ }; ++ static const GVecGen3 ops[4] = { ++ { .fniv = gen_sabd_vec, ++ .fno = gen_helper_gvec_sabd_b, ++ .opt_opc = vecop_list, ++ .vece = MO_8 }, ++ { .fniv = gen_sabd_vec, ++ .fno = gen_helper_gvec_sabd_h, ++ .opt_opc = vecop_list, ++ .vece = MO_16 }, ++ { .fni4 = gen_sabd_i32, ++ .fniv = gen_sabd_vec, ++ .fno = gen_helper_gvec_sabd_s, ++ .opt_opc = vecop_list, ++ .vece = MO_32 }, ++ { .fni8 = gen_sabd_i64, ++ .fniv = gen_sabd_vec, ++ .fno = gen_helper_gvec_sabd_d, ++ .prefer_i64 = TCG_TARGET_REG_BITS == 64, ++ .opt_opc = vecop_list, ++ .vece = MO_64 }, ++ }; ++ tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]); ++} ++ ++static void gen_uabd_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b) ++{ ++ TCGv_i32 t = tcg_temp_new_i32(); ++ ++ tcg_gen_sub_i32(t, a, b); ++ tcg_gen_sub_i32(d, b, a); ++ tcg_gen_movcond_i32(TCG_COND_LTU, d, a, b, d, t); ++ tcg_temp_free_i32(t); ++} ++ ++static void gen_uabd_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b) ++{ ++ TCGv_i64 t = tcg_temp_new_i64(); ++ ++ tcg_gen_sub_i64(t, a, b); ++ tcg_gen_sub_i64(d, b, a); ++ tcg_gen_movcond_i64(TCG_COND_LTU, d, a, b, d, t); ++ tcg_temp_free_i64(t); ++} ++ ++static void gen_uabd_vec(unsigned vece, TCGv_vec d, TCGv_vec a, TCGv_vec b) ++{ ++ TCGv_vec t = tcg_temp_new_vec_matching(d); ++ ++ tcg_gen_umin_vec(vece, t, a, b); ++ tcg_gen_umax_vec(vece, d, a, b); ++ tcg_gen_sub_vec(vece, d, d, t); ++ tcg_temp_free_vec(t); ++} ++ ++void gen_gvec_uabd(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs, ++ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz) ++{ ++ static const TCGOpcode vecop_list[] = { ++ INDEX_op_sub_vec, INDEX_op_umin_vec, INDEX_op_umax_vec, 0 ++ }; ++ static const GVecGen3 ops[4] = { ++ { .fniv = gen_uabd_vec, ++ .fno = gen_helper_gvec_uabd_b, ++ .opt_opc = vecop_list, ++ .vece = MO_8 }, ++ { .fniv = gen_uabd_vec, ++ .fno = gen_helper_gvec_uabd_h, ++ .opt_opc = vecop_list, ++ .vece = MO_16 }, ++ { .fni4 = gen_uabd_i32, ++ .fniv = gen_uabd_vec, ++ .fno = gen_helper_gvec_uabd_s, ++ .opt_opc = vecop_list, ++ .vece = MO_32 }, ++ { .fni8 = gen_uabd_i64, ++ .fniv = gen_uabd_vec, ++ .fno = gen_helper_gvec_uabd_d, ++ .prefer_i64 = TCG_TARGET_REG_BITS == 64, ++ .opt_opc = vecop_list, ++ .vece = MO_64 }, ++ }; ++ tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]); ++} ++ + /* Translate a NEON data processing instruction. Return nonzero if the + instruction is invalid. + We process data in a mixture of 32-bit and 64-bit chunks. +@@ -5236,6 +5356,16 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn) + } + return 1; + ++ case NEON_3R_VABD: ++ if (u) { ++ gen_gvec_uabd(size, rd_ofs, rn_ofs, rm_ofs, ++ vec_size, vec_size); ++ } else { ++ gen_gvec_sabd(size, rd_ofs, rn_ofs, rm_ofs, ++ vec_size, vec_size); ++ } ++ return 0; ++ + case NEON_3R_VADD_VSUB: + case NEON_3R_LOGIC: + case NEON_3R_VMAX: +@@ -5380,9 +5510,6 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn) + case NEON_3R_VQRSHL: + GEN_NEON_INTEGER_OP_ENV(qrshl); + break; +- case NEON_3R_VABD: +- GEN_NEON_INTEGER_OP(abd); +- break; + case NEON_3R_VABA: + GEN_NEON_INTEGER_OP(abd); + tcg_temp_free_i32(tmp2); +diff --git a/target/arm/translate.h b/target/arm/translate.h +index aea8a9759d..bbfe3d1393 100644 +--- a/target/arm/translate.h ++++ b/target/arm/translate.h +@@ -337,6 +337,11 @@ void gen_gvec_sqrdmlah_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs, + void gen_gvec_sqrdmlsh_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs, + uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz); + ++void gen_gvec_sabd(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs, ++ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz); ++void gen_gvec_uabd(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs, ++ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz); ++ + /* + * Forward to the isar_feature_* tests given a DisasContext pointer. + */ +diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c +index a483841add..a4972d02fc 100644 +--- a/target/arm/vec_helper.c ++++ b/target/arm/vec_helper.c +@@ -1407,3 +1407,27 @@ DO_CMP0(gvec_cgt0_h, int16_t, >) + DO_CMP0(gvec_cge0_h, int16_t, >=) + + #undef DO_CMP0 ++ ++#define DO_ABD(NAME, TYPE) \ ++void HELPER(NAME)(void *vd, void *vn, void *vm, uint32_t desc) \ ++{ \ ++ intptr_t i, opr_sz = simd_oprsz(desc); \ ++ TYPE *d = vd, *n = vn, *m = vm; \ ++ \ ++ for (i = 0; i < opr_sz / sizeof(TYPE); ++i) { \ ++ d[i] = n[i] < m[i] ? m[i] - n[i] : n[i] - m[i]; \ ++ } \ ++ clear_tail(d, opr_sz, simd_maxsz(desc)); \ ++} ++ ++DO_ABD(gvec_sabd_b, int8_t) ++DO_ABD(gvec_sabd_h, int16_t) ++DO_ABD(gvec_sabd_s, int32_t) ++DO_ABD(gvec_sabd_d, int64_t) ++ ++DO_ABD(gvec_uabd_b, uint8_t) ++DO_ABD(gvec_uabd_h, uint16_t) ++DO_ABD(gvec_uabd_s, uint32_t) ++DO_ABD(gvec_uabd_d, uint64_t) ++ ++#undef DO_ABD +-- +2.23.0 + diff --git a/target-arm-Vectorize-integer-comparison-vs-zero.patch b/target-arm-Vectorize-integer-comparison-vs-zero.patch new file mode 100644 index 0000000000000000000000000000000000000000..7d9a504b7dc2bca2eaea06335dfa81cbf61418c4 --- /dev/null +++ b/target-arm-Vectorize-integer-comparison-vs-zero.patch @@ -0,0 +1,550 @@ +From 6b375d3546b009d1e63e07397ec9c6af256e15e9 Mon Sep 17 00:00:00 2001 +From: Richard Henderson +Date: Sat, 18 Apr 2020 09:28:08 -0700 +Subject: [PATCH 114/709] target/arm: Vectorize integer comparison vs zero + +These instructions are often used in glibc's string routines. +They were the final uses of the 32-bit at a time neon helpers. + +Signed-off-by: Richard Henderson +Message-id: 20200418162808.4680-1-richard.henderson@linaro.org +Reviewed-by: Peter Maydell +Signed-off-by: Peter Maydell +--- + target/arm/helper.h | 27 ++-- + target/arm/neon_helper.c | 24 ---- + target/arm/translate-a64.c | 64 +++------- + target/arm/translate.c | 256 +++++++++++++++++++++++++++++++------ + target/arm/translate.h | 5 + + target/arm/vec_helper.c | 25 ++++ + 6 files changed, 278 insertions(+), 123 deletions(-) + +diff --git a/target/arm/helper.h b/target/arm/helper.h +index f37b8670a5..5817626b20 100644 +--- a/target/arm/helper.h ++++ b/target/arm/helper.h +@@ -275,19 +275,6 @@ DEF_HELPER_2(neon_hsub_u16, i32, i32, i32) + DEF_HELPER_2(neon_hsub_s32, s32, s32, s32) + DEF_HELPER_2(neon_hsub_u32, i32, i32, i32) + +-DEF_HELPER_2(neon_cgt_u8, i32, i32, i32) +-DEF_HELPER_2(neon_cgt_s8, i32, i32, i32) +-DEF_HELPER_2(neon_cgt_u16, i32, i32, i32) +-DEF_HELPER_2(neon_cgt_s16, i32, i32, i32) +-DEF_HELPER_2(neon_cgt_u32, i32, i32, i32) +-DEF_HELPER_2(neon_cgt_s32, i32, i32, i32) +-DEF_HELPER_2(neon_cge_u8, i32, i32, i32) +-DEF_HELPER_2(neon_cge_s8, i32, i32, i32) +-DEF_HELPER_2(neon_cge_u16, i32, i32, i32) +-DEF_HELPER_2(neon_cge_s16, i32, i32, i32) +-DEF_HELPER_2(neon_cge_u32, i32, i32, i32) +-DEF_HELPER_2(neon_cge_s32, i32, i32, i32) +- + DEF_HELPER_2(neon_pmin_u8, i32, i32, i32) + DEF_HELPER_2(neon_pmin_s8, i32, i32, i32) + DEF_HELPER_2(neon_pmin_u16, i32, i32, i32) +@@ -347,9 +334,6 @@ DEF_HELPER_2(neon_mul_u16, i32, i32, i32) + DEF_HELPER_2(neon_tst_u8, i32, i32, i32) + DEF_HELPER_2(neon_tst_u16, i32, i32, i32) + DEF_HELPER_2(neon_tst_u32, i32, i32, i32) +-DEF_HELPER_2(neon_ceq_u8, i32, i32, i32) +-DEF_HELPER_2(neon_ceq_u16, i32, i32, i32) +-DEF_HELPER_2(neon_ceq_u32, i32, i32, i32) + + DEF_HELPER_1(neon_clz_u8, i32, i32) + DEF_HELPER_1(neon_clz_u16, i32, i32) +@@ -686,6 +670,17 @@ DEF_HELPER_FLAGS_2(frint64_s, TCG_CALL_NO_RWG, f32, f32, ptr) + DEF_HELPER_FLAGS_2(frint32_d, TCG_CALL_NO_RWG, f64, f64, ptr) + DEF_HELPER_FLAGS_2(frint64_d, TCG_CALL_NO_RWG, f64, f64, ptr) + ++DEF_HELPER_FLAGS_3(gvec_ceq0_b, TCG_CALL_NO_RWG, void, ptr, ptr, i32) ++DEF_HELPER_FLAGS_3(gvec_ceq0_h, TCG_CALL_NO_RWG, void, ptr, ptr, i32) ++DEF_HELPER_FLAGS_3(gvec_clt0_b, TCG_CALL_NO_RWG, void, ptr, ptr, i32) ++DEF_HELPER_FLAGS_3(gvec_clt0_h, TCG_CALL_NO_RWG, void, ptr, ptr, i32) ++DEF_HELPER_FLAGS_3(gvec_cle0_b, TCG_CALL_NO_RWG, void, ptr, ptr, i32) ++DEF_HELPER_FLAGS_3(gvec_cle0_h, TCG_CALL_NO_RWG, void, ptr, ptr, i32) ++DEF_HELPER_FLAGS_3(gvec_cgt0_b, TCG_CALL_NO_RWG, void, ptr, ptr, i32) ++DEF_HELPER_FLAGS_3(gvec_cgt0_h, TCG_CALL_NO_RWG, void, ptr, ptr, i32) ++DEF_HELPER_FLAGS_3(gvec_cge0_b, TCG_CALL_NO_RWG, void, ptr, ptr, i32) ++DEF_HELPER_FLAGS_3(gvec_cge0_h, TCG_CALL_NO_RWG, void, ptr, ptr, i32) ++ + DEF_HELPER_FLAGS_4(gvec_sshl_b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) + DEF_HELPER_FLAGS_4(gvec_sshl_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) + DEF_HELPER_FLAGS_4(gvec_ushl_b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) +diff --git a/target/arm/neon_helper.c b/target/arm/neon_helper.c +index c7a8438b42..448be93fa1 100644 +--- a/target/arm/neon_helper.c ++++ b/target/arm/neon_helper.c +@@ -562,24 +562,6 @@ uint32_t HELPER(neon_hsub_u32)(uint32_t src1, uint32_t src2) + return dest; + } + +-#define NEON_FN(dest, src1, src2) dest = (src1 > src2) ? ~0 : 0 +-NEON_VOP(cgt_s8, neon_s8, 4) +-NEON_VOP(cgt_u8, neon_u8, 4) +-NEON_VOP(cgt_s16, neon_s16, 2) +-NEON_VOP(cgt_u16, neon_u16, 2) +-NEON_VOP(cgt_s32, neon_s32, 1) +-NEON_VOP(cgt_u32, neon_u32, 1) +-#undef NEON_FN +- +-#define NEON_FN(dest, src1, src2) dest = (src1 >= src2) ? ~0 : 0 +-NEON_VOP(cge_s8, neon_s8, 4) +-NEON_VOP(cge_u8, neon_u8, 4) +-NEON_VOP(cge_s16, neon_s16, 2) +-NEON_VOP(cge_u16, neon_u16, 2) +-NEON_VOP(cge_s32, neon_s32, 1) +-NEON_VOP(cge_u32, neon_u32, 1) +-#undef NEON_FN +- + #define NEON_FN(dest, src1, src2) dest = (src1 < src2) ? src1 : src2 + NEON_POP(pmin_s8, neon_s8, 4) + NEON_POP(pmin_u8, neon_u8, 4) +@@ -1135,12 +1117,6 @@ NEON_VOP(tst_u16, neon_u16, 2) + NEON_VOP(tst_u32, neon_u32, 1) + #undef NEON_FN + +-#define NEON_FN(dest, src1, src2) dest = (src1 == src2) ? -1 : 0 +-NEON_VOP(ceq_u8, neon_u8, 4) +-NEON_VOP(ceq_u16, neon_u16, 2) +-NEON_VOP(ceq_u32, neon_u32, 1) +-#undef NEON_FN +- + /* Count Leading Sign/Zero Bits. */ + static inline int do_clz8(uint8_t x) + { +diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c +index 7580e46367..efb1c4adc4 100644 +--- a/target/arm/translate-a64.c ++++ b/target/arm/translate-a64.c +@@ -594,6 +594,14 @@ static void gen_gvec_fn4(DisasContext *s, bool is_q, int rd, int rn, int rm, + is_q ? 16 : 8, vec_full_reg_size(s)); + } + ++/* Expand a 2-operand AdvSIMD vector operation using an op descriptor. */ ++static void gen_gvec_op2(DisasContext *s, bool is_q, int rd, ++ int rn, const GVecGen2 *gvec_op) ++{ ++ tcg_gen_gvec_2(vec_full_reg_offset(s, rd), vec_full_reg_offset(s, rn), ++ is_q ? 16 : 8, vec_full_reg_size(s), gvec_op); ++} ++ + /* Expand a 2-operand + immediate AdvSIMD vector operation using + * an op descriptor. + */ +@@ -12366,6 +12374,15 @@ static void disas_simd_two_reg_misc(DisasContext *s, uint32_t insn) + return; + } + break; ++ case 0x8: /* CMGT, CMGE */ ++ gen_gvec_op2(s, is_q, rd, rn, u ? &cge0_op[size] : &cgt0_op[size]); ++ return; ++ case 0x9: /* CMEQ, CMLE */ ++ gen_gvec_op2(s, is_q, rd, rn, u ? &cle0_op[size] : &ceq0_op[size]); ++ return; ++ case 0xa: /* CMLT */ ++ gen_gvec_op2(s, is_q, rd, rn, &clt0_op[size]); ++ return; + case 0xb: + if (u) { /* ABS, NEG */ + gen_gvec_fn2(s, is_q, rd, rn, tcg_gen_gvec_neg, size); +@@ -12403,29 +12420,12 @@ static void disas_simd_two_reg_misc(DisasContext *s, uint32_t insn) + for (pass = 0; pass < (is_q ? 4 : 2); pass++) { + TCGv_i32 tcg_op = tcg_temp_new_i32(); + TCGv_i32 tcg_res = tcg_temp_new_i32(); +- TCGCond cond; + + read_vec_element_i32(s, tcg_op, rn, pass, MO_32); + + if (size == 2) { + /* Special cases for 32 bit elements */ + switch (opcode) { +- case 0xa: /* CMLT */ +- /* 32 bit integer comparison against zero, result is +- * test ? (2^32 - 1) : 0. We implement via setcond(test) +- * and inverting. +- */ +- cond = TCG_COND_LT; +- do_cmop: +- tcg_gen_setcondi_i32(cond, tcg_res, tcg_op, 0); +- tcg_gen_neg_i32(tcg_res, tcg_res); +- break; +- case 0x8: /* CMGT, CMGE */ +- cond = u ? TCG_COND_GE : TCG_COND_GT; +- goto do_cmop; +- case 0x9: /* CMEQ, CMLE */ +- cond = u ? TCG_COND_LE : TCG_COND_EQ; +- goto do_cmop; + case 0x4: /* CLS */ + if (u) { + tcg_gen_clzi_i32(tcg_res, tcg_op, 32); +@@ -12522,36 +12522,6 @@ static void disas_simd_two_reg_misc(DisasContext *s, uint32_t insn) + genfn(tcg_res, cpu_env, tcg_op); + break; + } +- case 0x8: /* CMGT, CMGE */ +- case 0x9: /* CMEQ, CMLE */ +- case 0xa: /* CMLT */ +- { +- static NeonGenTwoOpFn * const fns[3][2] = { +- { gen_helper_neon_cgt_s8, gen_helper_neon_cgt_s16 }, +- { gen_helper_neon_cge_s8, gen_helper_neon_cge_s16 }, +- { gen_helper_neon_ceq_u8, gen_helper_neon_ceq_u16 }, +- }; +- NeonGenTwoOpFn *genfn; +- int comp; +- bool reverse; +- TCGv_i32 tcg_zero = tcg_const_i32(0); +- +- /* comp = index into [CMGT, CMGE, CMEQ, CMLE, CMLT] */ +- comp = (opcode - 0x8) * 2 + u; +- /* ...but LE, LT are implemented as reverse GE, GT */ +- reverse = (comp > 2); +- if (reverse) { +- comp = 4 - comp; +- } +- genfn = fns[comp][size]; +- if (reverse) { +- genfn(tcg_res, tcg_zero, tcg_op); +- } else { +- genfn(tcg_res, tcg_op, tcg_zero); +- } +- tcg_temp_free_i32(tcg_zero); +- break; +- } + case 0x4: /* CLS, CLZ */ + if (u) { + if (size == 0) { +diff --git a/target/arm/translate.c b/target/arm/translate.c +index 9f9f4e19e0..d4ad2028f1 100644 +--- a/target/arm/translate.c ++++ b/target/arm/translate.c +@@ -3917,6 +3917,205 @@ static int do_v81_helper(DisasContext *s, gen_helper_gvec_3_ptr *fn, + return 1; + } + ++static void gen_ceq0_i32(TCGv_i32 d, TCGv_i32 a) ++{ ++ tcg_gen_setcondi_i32(TCG_COND_EQ, d, a, 0); ++ tcg_gen_neg_i32(d, d); ++} ++ ++static void gen_ceq0_i64(TCGv_i64 d, TCGv_i64 a) ++{ ++ tcg_gen_setcondi_i64(TCG_COND_EQ, d, a, 0); ++ tcg_gen_neg_i64(d, d); ++} ++ ++static void gen_ceq0_vec(unsigned vece, TCGv_vec d, TCGv_vec a) ++{ ++ TCGv_vec zero = tcg_const_zeros_vec_matching(d); ++ tcg_gen_cmp_vec(TCG_COND_EQ, vece, d, a, zero); ++ tcg_temp_free_vec(zero); ++} ++ ++static const TCGOpcode vecop_list_cmp[] = { ++ INDEX_op_cmp_vec, 0 ++}; ++ ++const GVecGen2 ceq0_op[4] = { ++ { .fno = gen_helper_gvec_ceq0_b, ++ .fniv = gen_ceq0_vec, ++ .opt_opc = vecop_list_cmp, ++ .vece = MO_8 }, ++ { .fno = gen_helper_gvec_ceq0_h, ++ .fniv = gen_ceq0_vec, ++ .opt_opc = vecop_list_cmp, ++ .vece = MO_16 }, ++ { .fni4 = gen_ceq0_i32, ++ .fniv = gen_ceq0_vec, ++ .opt_opc = vecop_list_cmp, ++ .vece = MO_32 }, ++ { .fni8 = gen_ceq0_i64, ++ .fniv = gen_ceq0_vec, ++ .opt_opc = vecop_list_cmp, ++ .prefer_i64 = TCG_TARGET_REG_BITS == 64, ++ .vece = MO_64 }, ++}; ++ ++static void gen_cle0_i32(TCGv_i32 d, TCGv_i32 a) ++{ ++ tcg_gen_setcondi_i32(TCG_COND_LE, d, a, 0); ++ tcg_gen_neg_i32(d, d); ++} ++ ++static void gen_cle0_i64(TCGv_i64 d, TCGv_i64 a) ++{ ++ tcg_gen_setcondi_i64(TCG_COND_LE, d, a, 0); ++ tcg_gen_neg_i64(d, d); ++} ++ ++static void gen_cle0_vec(unsigned vece, TCGv_vec d, TCGv_vec a) ++{ ++ TCGv_vec zero = tcg_const_zeros_vec_matching(d); ++ tcg_gen_cmp_vec(TCG_COND_LE, vece, d, a, zero); ++ tcg_temp_free_vec(zero); ++} ++ ++const GVecGen2 cle0_op[4] = { ++ { .fno = gen_helper_gvec_cle0_b, ++ .fniv = gen_cle0_vec, ++ .opt_opc = vecop_list_cmp, ++ .vece = MO_8 }, ++ { .fno = gen_helper_gvec_cle0_h, ++ .fniv = gen_cle0_vec, ++ .opt_opc = vecop_list_cmp, ++ .vece = MO_16 }, ++ { .fni4 = gen_cle0_i32, ++ .fniv = gen_cle0_vec, ++ .opt_opc = vecop_list_cmp, ++ .vece = MO_32 }, ++ { .fni8 = gen_cle0_i64, ++ .fniv = gen_cle0_vec, ++ .opt_opc = vecop_list_cmp, ++ .prefer_i64 = TCG_TARGET_REG_BITS == 64, ++ .vece = MO_64 }, ++}; ++ ++static void gen_cge0_i32(TCGv_i32 d, TCGv_i32 a) ++{ ++ tcg_gen_setcondi_i32(TCG_COND_GE, d, a, 0); ++ tcg_gen_neg_i32(d, d); ++} ++ ++static void gen_cge0_i64(TCGv_i64 d, TCGv_i64 a) ++{ ++ tcg_gen_setcondi_i64(TCG_COND_GE, d, a, 0); ++ tcg_gen_neg_i64(d, d); ++} ++ ++static void gen_cge0_vec(unsigned vece, TCGv_vec d, TCGv_vec a) ++{ ++ TCGv_vec zero = tcg_const_zeros_vec_matching(d); ++ tcg_gen_cmp_vec(TCG_COND_GE, vece, d, a, zero); ++ tcg_temp_free_vec(zero); ++} ++ ++const GVecGen2 cge0_op[4] = { ++ { .fno = gen_helper_gvec_cge0_b, ++ .fniv = gen_cge0_vec, ++ .opt_opc = vecop_list_cmp, ++ .vece = MO_8 }, ++ { .fno = gen_helper_gvec_cge0_h, ++ .fniv = gen_cge0_vec, ++ .opt_opc = vecop_list_cmp, ++ .vece = MO_16 }, ++ { .fni4 = gen_cge0_i32, ++ .fniv = gen_cge0_vec, ++ .opt_opc = vecop_list_cmp, ++ .vece = MO_32 }, ++ { .fni8 = gen_cge0_i64, ++ .fniv = gen_cge0_vec, ++ .opt_opc = vecop_list_cmp, ++ .prefer_i64 = TCG_TARGET_REG_BITS == 64, ++ .vece = MO_64 }, ++}; ++ ++static void gen_clt0_i32(TCGv_i32 d, TCGv_i32 a) ++{ ++ tcg_gen_setcondi_i32(TCG_COND_LT, d, a, 0); ++ tcg_gen_neg_i32(d, d); ++} ++ ++static void gen_clt0_i64(TCGv_i64 d, TCGv_i64 a) ++{ ++ tcg_gen_setcondi_i64(TCG_COND_LT, d, a, 0); ++ tcg_gen_neg_i64(d, d); ++} ++ ++static void gen_clt0_vec(unsigned vece, TCGv_vec d, TCGv_vec a) ++{ ++ TCGv_vec zero = tcg_const_zeros_vec_matching(d); ++ tcg_gen_cmp_vec(TCG_COND_LT, vece, d, a, zero); ++ tcg_temp_free_vec(zero); ++} ++ ++const GVecGen2 clt0_op[4] = { ++ { .fno = gen_helper_gvec_clt0_b, ++ .fniv = gen_clt0_vec, ++ .opt_opc = vecop_list_cmp, ++ .vece = MO_8 }, ++ { .fno = gen_helper_gvec_clt0_h, ++ .fniv = gen_clt0_vec, ++ .opt_opc = vecop_list_cmp, ++ .vece = MO_16 }, ++ { .fni4 = gen_clt0_i32, ++ .fniv = gen_clt0_vec, ++ .opt_opc = vecop_list_cmp, ++ .vece = MO_32 }, ++ { .fni8 = gen_clt0_i64, ++ .fniv = gen_clt0_vec, ++ .opt_opc = vecop_list_cmp, ++ .prefer_i64 = TCG_TARGET_REG_BITS == 64, ++ .vece = MO_64 }, ++}; ++ ++static void gen_cgt0_i32(TCGv_i32 d, TCGv_i32 a) ++{ ++ tcg_gen_setcondi_i32(TCG_COND_GT, d, a, 0); ++ tcg_gen_neg_i32(d, d); ++} ++ ++static void gen_cgt0_i64(TCGv_i64 d, TCGv_i64 a) ++{ ++ tcg_gen_setcondi_i64(TCG_COND_GT, d, a, 0); ++ tcg_gen_neg_i64(d, d); ++} ++ ++static void gen_cgt0_vec(unsigned vece, TCGv_vec d, TCGv_vec a) ++{ ++ TCGv_vec zero = tcg_const_zeros_vec_matching(d); ++ tcg_gen_cmp_vec(TCG_COND_GT, vece, d, a, zero); ++ tcg_temp_free_vec(zero); ++} ++ ++const GVecGen2 cgt0_op[4] = { ++ { .fno = gen_helper_gvec_cgt0_b, ++ .fniv = gen_cgt0_vec, ++ .opt_opc = vecop_list_cmp, ++ .vece = MO_8 }, ++ { .fno = gen_helper_gvec_cgt0_h, ++ .fniv = gen_cgt0_vec, ++ .opt_opc = vecop_list_cmp, ++ .vece = MO_16 }, ++ { .fni4 = gen_cgt0_i32, ++ .fniv = gen_cgt0_vec, ++ .opt_opc = vecop_list_cmp, ++ .vece = MO_32 }, ++ { .fni8 = gen_cgt0_i64, ++ .fniv = gen_cgt0_vec, ++ .opt_opc = vecop_list_cmp, ++ .prefer_i64 = TCG_TARGET_REG_BITS == 64, ++ .vece = MO_64 }, ++}; ++ + static void gen_ssra8_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift) + { + tcg_gen_vec_sar8i_i64(a, a, shift); +@@ -6481,6 +6680,27 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn) + tcg_gen_gvec_abs(size, rd_ofs, rm_ofs, vec_size, vec_size); + break; + ++ case NEON_2RM_VCEQ0: ++ tcg_gen_gvec_2(rd_ofs, rm_ofs, vec_size, ++ vec_size, &ceq0_op[size]); ++ break; ++ case NEON_2RM_VCGT0: ++ tcg_gen_gvec_2(rd_ofs, rm_ofs, vec_size, ++ vec_size, &cgt0_op[size]); ++ break; ++ case NEON_2RM_VCLE0: ++ tcg_gen_gvec_2(rd_ofs, rm_ofs, vec_size, ++ vec_size, &cle0_op[size]); ++ break; ++ case NEON_2RM_VCGE0: ++ tcg_gen_gvec_2(rd_ofs, rm_ofs, vec_size, ++ vec_size, &cge0_op[size]); ++ break; ++ case NEON_2RM_VCLT0: ++ tcg_gen_gvec_2(rd_ofs, rm_ofs, vec_size, ++ vec_size, &clt0_op[size]); ++ break; ++ + default: + elementwise: + for (pass = 0; pass < (q ? 4 : 2); pass++) { +@@ -6543,42 +6763,6 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn) + default: abort(); + } + break; +- case NEON_2RM_VCGT0: case NEON_2RM_VCLE0: +- tmp2 = tcg_const_i32(0); +- switch(size) { +- case 0: gen_helper_neon_cgt_s8(tmp, tmp, tmp2); break; +- case 1: gen_helper_neon_cgt_s16(tmp, tmp, tmp2); break; +- case 2: gen_helper_neon_cgt_s32(tmp, tmp, tmp2); break; +- default: abort(); +- } +- tcg_temp_free_i32(tmp2); +- if (op == NEON_2RM_VCLE0) { +- tcg_gen_not_i32(tmp, tmp); +- } +- break; +- case NEON_2RM_VCGE0: case NEON_2RM_VCLT0: +- tmp2 = tcg_const_i32(0); +- switch(size) { +- case 0: gen_helper_neon_cge_s8(tmp, tmp, tmp2); break; +- case 1: gen_helper_neon_cge_s16(tmp, tmp, tmp2); break; +- case 2: gen_helper_neon_cge_s32(tmp, tmp, tmp2); break; +- default: abort(); +- } +- tcg_temp_free_i32(tmp2); +- if (op == NEON_2RM_VCLT0) { +- tcg_gen_not_i32(tmp, tmp); +- } +- break; +- case NEON_2RM_VCEQ0: +- tmp2 = tcg_const_i32(0); +- switch(size) { +- case 0: gen_helper_neon_ceq_u8(tmp, tmp, tmp2); break; +- case 1: gen_helper_neon_ceq_u16(tmp, tmp, tmp2); break; +- case 2: gen_helper_neon_ceq_u32(tmp, tmp, tmp2); break; +- default: abort(); +- } +- tcg_temp_free_i32(tmp2); +- break; + case NEON_2RM_VCGT0_F: + { + TCGv_ptr fpstatus = get_fpstatus_ptr(1); +diff --git a/target/arm/translate.h b/target/arm/translate.h +index d9ea0c99cc..98b319f3f6 100644 +--- a/target/arm/translate.h ++++ b/target/arm/translate.h +@@ -275,6 +275,11 @@ static inline void gen_swstep_exception(DisasContext *s, int isv, int ex) + uint64_t vfp_expand_imm(int size, uint8_t imm8); + + /* Vector operations shared between ARM and AArch64. */ ++extern const GVecGen2 ceq0_op[4]; ++extern const GVecGen2 clt0_op[4]; ++extern const GVecGen2 cgt0_op[4]; ++extern const GVecGen2 cle0_op[4]; ++extern const GVecGen2 cge0_op[4]; + extern const GVecGen3 mla_op[4]; + extern const GVecGen3 mls_op[4]; + extern const GVecGen3 cmtst_op[4]; +diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c +index 8017bd88c4..3d534188a8 100644 +--- a/target/arm/vec_helper.c ++++ b/target/arm/vec_helper.c +@@ -1257,3 +1257,28 @@ void HELPER(sve2_pmull_h)(void *vd, void *vn, void *vm, uint32_t desc) + } + } + #endif ++ ++#define DO_CMP0(NAME, TYPE, OP) \ ++void HELPER(NAME)(void *vd, void *vn, uint32_t desc) \ ++{ \ ++ intptr_t i, opr_sz = simd_oprsz(desc); \ ++ for (i = 0; i < opr_sz; i += sizeof(TYPE)) { \ ++ TYPE nn = *(TYPE *)(vn + i); \ ++ *(TYPE *)(vd + i) = -(nn OP 0); \ ++ } \ ++ clear_tail(vd, opr_sz, simd_maxsz(desc)); \ ++} ++ ++DO_CMP0(gvec_ceq0_b, int8_t, ==) ++DO_CMP0(gvec_clt0_b, int8_t, <) ++DO_CMP0(gvec_cle0_b, int8_t, <=) ++DO_CMP0(gvec_cgt0_b, int8_t, >) ++DO_CMP0(gvec_cge0_b, int8_t, >=) ++ ++DO_CMP0(gvec_ceq0_h, int16_t, ==) ++DO_CMP0(gvec_clt0_h, int16_t, <) ++DO_CMP0(gvec_cle0_h, int16_t, <=) ++DO_CMP0(gvec_cgt0_h, int16_t, >) ++DO_CMP0(gvec_cge0_h, int16_t, >=) ++ ++#undef DO_CMP0 +-- +2.23.0 + diff --git a/target-arm-cpu-Restrict-v8M-IDAU-interface-to-Aarch3.patch b/target-arm-cpu-Restrict-v8M-IDAU-interface-to-Aarch3.patch new file mode 100644 index 0000000000000000000000000000000000000000..62f08665ad16ef6dea8aba7ec581a2c8037ede6e --- /dev/null +++ b/target-arm-cpu-Restrict-v8M-IDAU-interface-to-Aarch3.patch @@ -0,0 +1,42 @@ +From fcdf0a90f791038c7e0a8546d00ca3168a7f3891 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Mon, 4 May 2020 19:24:47 +0200 +Subject: [PATCH 387/709] target/arm/cpu: Restrict v8M IDAU interface to + Aarch32 CPUs +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +As IDAU is a v8M feature, restrict it to the Aarch32 CPUs. + +Signed-off-by: Philippe Mathieu-Daudé +Reviewed-by: Richard Henderson +Message-id: 20200504172448.9402-5-philmd@redhat.com +Signed-off-by: Peter Maydell +--- + target/arm/cpu.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/target/arm/cpu.c b/target/arm/cpu.c +index b4d73dd47c..a10f8c4044 100644 +--- a/target/arm/cpu.c ++++ b/target/arm/cpu.c +@@ -2889,7 +2889,6 @@ static void arm_cpu_register_types(void) + const size_t cpu_count = ARRAY_SIZE(arm_cpus); + + type_register_static(&arm_cpu_type_info); +- type_register_static(&idau_interface_type_info); + + #ifdef CONFIG_KVM + type_register_static(&host_arm_cpu_type_info); +@@ -2898,6 +2897,7 @@ static void arm_cpu_register_types(void) + if (cpu_count) { + size_t i; + ++ type_register_static(&idau_interface_type_info); + for (i = 0; i < cpu_count; ++i) { + arm_cpu_register(&arm_cpus[i]); + } +-- +2.23.0 + diff --git a/target-arm-cpu-Update-coding-style-to-make-checkpatc.patch b/target-arm-cpu-Update-coding-style-to-make-checkpatc.patch new file mode 100644 index 0000000000000000000000000000000000000000..d524832c30db878f12cbe07c146aab7e50f2b88c --- /dev/null +++ b/target-arm-cpu-Update-coding-style-to-make-checkpatc.patch @@ -0,0 +1,57 @@ +From 51c510aa5876a681cd0059ed3bacaa17590dc2d5 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Thu, 23 Apr 2020 09:33:57 +0200 +Subject: [PATCH 119/709] target/arm/cpu: Update coding style to make + checkpatch.pl happy +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +We will move this code in the next commit. Clean it up +first to avoid checkpatch.pl errors. + +Reviewed-by: Richard Henderson +Signed-off-by: Philippe Mathieu-Daudé +Message-id: 20200423073358.27155-5-philmd@redhat.com +Signed-off-by: Peter Maydell +--- + target/arm/cpu.c | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +diff --git a/target/arm/cpu.c b/target/arm/cpu.c +index 47e35400da..141d947775 100644 +--- a/target/arm/cpu.c ++++ b/target/arm/cpu.c +@@ -582,7 +582,8 @@ static bool arm_v7m_cpu_exec_interrupt(CPUState *cs, int interrupt_request) + CPUARMState *env = &cpu->env; + bool ret = false; + +- /* ARMv7-M interrupt masking works differently than -A or -R. ++ /* ++ * ARMv7-M interrupt masking works differently than -A or -R. + * There is no FIQ/IRQ distinction. Instead of I and F bits + * masking FIQ and IRQ interrupts, an exception is taken only + * if it is higher priority than the current execution priority +@@ -1912,7 +1913,8 @@ static void arm1026_initfn(Object *obj) + static void arm1136_r2_initfn(Object *obj) + { + ARMCPU *cpu = ARM_CPU(obj); +- /* What qemu calls "arm1136_r2" is actually the 1136 r0p2, ie an ++ /* ++ * What qemu calls "arm1136_r2" is actually the 1136 r0p2, ie an + * older core than plain "arm1136". In particular this does not + * have the v6K features. + * These ID register values are correct for 1136 but may be wrong +@@ -2698,7 +2700,8 @@ static const ARMCPUInfo arm_cpus[] = { + { .name = "arm926", .initfn = arm926_initfn }, + { .name = "arm946", .initfn = arm946_initfn }, + { .name = "arm1026", .initfn = arm1026_initfn }, +- /* What QEMU calls "arm1136-r2" is actually the 1136 r0p2, i.e. an ++ /* ++ * What QEMU calls "arm1136-r2" is actually the 1136 r0p2, i.e. an + * older core than plain "arm1136". In particular this does not + * have the v6K features. + */ +-- +2.23.0 + diff --git a/target-arm-cpu-Use-ARRAY_SIZE-to-iterate-over-ARMCPU.patch b/target-arm-cpu-Use-ARRAY_SIZE-to-iterate-over-ARMCPU.patch new file mode 100644 index 0000000000000000000000000000000000000000..cef9dfc9450556d5e98d661b5009f9aca4a300bb --- /dev/null +++ b/target-arm-cpu-Use-ARRAY_SIZE-to-iterate-over-ARMCPU.patch @@ -0,0 +1,97 @@ +From 92b6a659388ab3735e5fbb17ac486923b681f57f Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Mon, 4 May 2020 19:24:46 +0200 +Subject: [PATCH 386/709] target/arm/cpu: Use ARRAY_SIZE() to iterate over + ARMCPUInfo[] +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Use ARRAY_SIZE() to iterate over ARMCPUInfo[]. + +Since on the aarch64-linux-user build, arm_cpus[] is empty, add +the cpu_count variable and only iterate when it is non-zero. + +Suggested-by: Richard Henderson +Reviewed-by: Richard Henderson +Signed-off-by: Philippe Mathieu-Daudé +Message-id: 20200504172448.9402-4-philmd@redhat.com +Signed-off-by: Peter Maydell +--- + target/arm/cpu.c | 16 +++++++++------- + target/arm/cpu64.c | 8 +++----- + 2 files changed, 12 insertions(+), 12 deletions(-) + +diff --git a/target/arm/cpu.c b/target/arm/cpu.c +index 13959cb643..b4d73dd47c 100644 +--- a/target/arm/cpu.c ++++ b/target/arm/cpu.c +@@ -2739,7 +2739,6 @@ static const ARMCPUInfo arm_cpus[] = { + { .name = "any", .initfn = arm_max_initfn }, + #endif + #endif +- { .name = NULL } + }; + + static Property arm_cpu_properties[] = { +@@ -2887,19 +2886,22 @@ static const TypeInfo idau_interface_type_info = { + + static void arm_cpu_register_types(void) + { +- const ARMCPUInfo *info = arm_cpus; ++ const size_t cpu_count = ARRAY_SIZE(arm_cpus); + + type_register_static(&arm_cpu_type_info); + type_register_static(&idau_interface_type_info); + +- while (info->name) { +- arm_cpu_register(info); +- info++; +- } +- + #ifdef CONFIG_KVM + type_register_static(&host_arm_cpu_type_info); + #endif ++ ++ if (cpu_count) { ++ size_t i; ++ ++ for (i = 0; i < cpu_count; ++i) { ++ arm_cpu_register(&arm_cpus[i]); ++ } ++ } + } + + type_init(arm_cpu_register_types) +diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c +index cbaa5ed228..f5c49ee32d 100644 +--- a/target/arm/cpu64.c ++++ b/target/arm/cpu64.c +@@ -734,7 +734,6 @@ static const ARMCPUInfo aarch64_cpus[] = { + { .name = "cortex-a53", .initfn = aarch64_a53_initfn }, + { .name = "cortex-a72", .initfn = aarch64_a72_initfn }, + { .name = "max", .initfn = aarch64_max_initfn }, +- { .name = NULL } + }; + + static bool aarch64_cpu_get_aarch64(Object *obj, Error **errp) +@@ -840,13 +839,12 @@ static const TypeInfo aarch64_cpu_type_info = { + + static void aarch64_cpu_register_types(void) + { +- const ARMCPUInfo *info = aarch64_cpus; ++ size_t i; + + type_register_static(&aarch64_cpu_type_info); + +- while (info->name) { +- aarch64_cpu_register(info); +- info++; ++ for (i = 0; i < ARRAY_SIZE(aarch64_cpus); ++i) { ++ aarch64_cpu_register(&aarch64_cpus[i]); + } + } + +-- +2.23.0 + diff --git a/target-arm-kvm-Inline-set_feature-calls.patch b/target-arm-kvm-Inline-set_feature-calls.patch new file mode 100644 index 0000000000000000000000000000000000000000..918d478e55c44679af4d1e14132af63550db9abf --- /dev/null +++ b/target-arm-kvm-Inline-set_feature-calls.patch @@ -0,0 +1,106 @@ +From f5cbb280bdd2cb5b8f44db015571591ef3c42665 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Mon, 4 May 2020 19:24:44 +0200 +Subject: [PATCH 384/709] target/arm/kvm: Inline set_feature() calls +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +We want to move the inlined declarations of set_feature() +from cpu*.c to cpu.h. To avoid clashing with the KVM +declarations, inline the few KVM calls. + +Suggested-by: Richard Henderson +Signed-off-by: Philippe Mathieu-Daudé +Message-id: 20200504172448.9402-2-philmd@redhat.com +Signed-off-by: Peter Maydell +--- + target/arm/kvm32.c | 13 ++++--------- + target/arm/kvm64.c | 22 ++++++---------------- + 2 files changed, 10 insertions(+), 25 deletions(-) + +diff --git a/target/arm/kvm32.c b/target/arm/kvm32.c +index f271181ab8..7b3a19e9ae 100644 +--- a/target/arm/kvm32.c ++++ b/target/arm/kvm32.c +@@ -22,11 +22,6 @@ + #include "internals.h" + #include "qemu/log.h" + +-static inline void set_feature(uint64_t *features, int feature) +-{ +- *features |= 1ULL << feature; +-} +- + static int read_sys_reg32(int fd, uint32_t *pret, uint64_t id) + { + struct kvm_one_reg idreg = { .id = id, .addr = (uintptr_t)pret }; +@@ -146,14 +141,14 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) + * timers; this in turn implies most of the other feature + * bits, but a few must be tested. + */ +- set_feature(&features, ARM_FEATURE_V7VE); +- set_feature(&features, ARM_FEATURE_GENERIC_TIMER); ++ features |= 1ULL << ARM_FEATURE_V7VE; ++ features |= 1ULL << ARM_FEATURE_GENERIC_TIMER; + + if (extract32(id_pfr0, 12, 4) == 1) { +- set_feature(&features, ARM_FEATURE_THUMB2EE); ++ features |= 1ULL << ARM_FEATURE_THUMB2EE; + } + if (extract32(ahcf->isar.mvfr1, 12, 4) == 1) { +- set_feature(&features, ARM_FEATURE_NEON); ++ features |= 1ULL << ARM_FEATURE_NEON; + } + + ahcf->features = features; +diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c +index be5b31c2b0..cd8ab6b8ae 100644 +--- a/target/arm/kvm64.c ++++ b/target/arm/kvm64.c +@@ -447,16 +447,6 @@ void kvm_arm_pmu_set_irq(CPUState *cs, int irq) + } + } + +-static inline void set_feature(uint64_t *features, int feature) +-{ +- *features |= 1ULL << feature; +-} +- +-static inline void unset_feature(uint64_t *features, int feature) +-{ +- *features &= ~(1ULL << feature); +-} +- + static int read_sys_reg32(int fd, uint32_t *pret, uint64_t id) + { + uint64_t ret; +@@ -648,11 +638,11 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) + * with VFPv4+Neon; this in turn implies most of the other + * feature bits. + */ +- set_feature(&features, ARM_FEATURE_V8); +- set_feature(&features, ARM_FEATURE_NEON); +- set_feature(&features, ARM_FEATURE_AARCH64); +- set_feature(&features, ARM_FEATURE_PMU); +- set_feature(&features, ARM_FEATURE_GENERIC_TIMER); ++ features |= 1ULL << ARM_FEATURE_V8; ++ features |= 1ULL << ARM_FEATURE_NEON; ++ features |= 1ULL << ARM_FEATURE_AARCH64; ++ features |= 1ULL << ARM_FEATURE_PMU; ++ features |= 1ULL << ARM_FEATURE_GENERIC_TIMER; + + ahcf->features = features; + +@@ -802,7 +792,7 @@ int kvm_arch_init_vcpu(CPUState *cs) + if (cpu->has_pmu) { + cpu->kvm_init_features[0] |= 1 << KVM_ARM_VCPU_PMU_V3; + } else { +- unset_feature(&env->features, ARM_FEATURE_PMU); ++ env->features &= ~(1ULL << ARM_FEATURE_PMU); + } + if (cpu_isar_feature(aa64_sve, cpu)) { + assert(kvm_arm_sve_supported(cs)); +-- +2.23.0 + diff --git a/target-arm-kvm64-handle-SIGBUS-signal-from-kernel-or.patch b/target-arm-kvm64-handle-SIGBUS-signal-from-kernel-or.patch new file mode 100644 index 0000000000000000000000000000000000000000..07cf86d118e4e135789aa19fd1b3415ce3bbff57 --- /dev/null +++ b/target-arm-kvm64-handle-SIGBUS-signal-from-kernel-or.patch @@ -0,0 +1,243 @@ +From e24fd076a59604c4ba3c05fe9d19ea6fc5320a12 Mon Sep 17 00:00:00 2001 +From: Dongjiu Geng +Date: Tue, 12 May 2020 11:06:08 +0800 +Subject: [PATCH 444/709] target-arm: kvm64: handle SIGBUS signal from kernel + or KVM + +Add a SIGBUS signal handler. In this handler, it checks the SIGBUS type, +translates the host VA delivered by host to guest PA, then fills this PA +to guest APEI GHES memory, then notifies guest according to the SIGBUS +type. + +When guest accesses the poisoned memory, it will generate a Synchronous +External Abort(SEA). Then host kernel gets an APEI notification and calls +memory_failure() to unmapped the affected page in stage 2, finally +returns to guest. + +Guest continues to access the PG_hwpoison page, it will trap to KVM as +stage2 fault, then a SIGBUS_MCEERR_AR synchronous signal is delivered to +Qemu, Qemu records this error address into guest APEI GHES memory and +notifes guest using Synchronous-External-Abort(SEA). + +In order to inject a vSEA, we introduce the kvm_inject_arm_sea() function +in which we can setup the type of exception and the syndrome information. +When switching to guest, the target vcpu will jump to the synchronous +external abort vector table entry. + +The ESR_ELx.DFSC is set to synchronous external abort(0x10), and the +ESR_ELx.FnV is set to not valid(0x1), which will tell guest that FAR is +not valid and hold an UNKNOWN value. These values will be set to KVM +register structures through KVM_SET_ONE_REG IOCTL. + +Signed-off-by: Dongjiu Geng +Signed-off-by: Xiang Zheng +Reviewed-by: Michael S. Tsirkin +Acked-by: Xiang Zheng +Reviewed-by: Peter Maydell +Reviewed-by: Igor Mammedov +Message-id: 20200512030609.19593-10-gengdongjiu@huawei.com +Signed-off-by: Peter Maydell +--- + include/sysemu/kvm.h | 3 +- + target/arm/cpu.h | 4 +++ + target/arm/helper.c | 2 +- + target/arm/internals.h | 5 +-- + target/arm/kvm64.c | 77 +++++++++++++++++++++++++++++++++++++++++ + target/arm/tlb_helper.c | 2 +- + target/i386/cpu.h | 2 ++ + 7 files changed, 89 insertions(+), 6 deletions(-) + +diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h +index 141342de98..3b2250471c 100644 +--- a/include/sysemu/kvm.h ++++ b/include/sysemu/kvm.h +@@ -379,8 +379,7 @@ bool kvm_vcpu_id_is_valid(int vcpu_id); + /* Returns VCPU ID to be used on KVM_CREATE_VCPU ioctl() */ + unsigned long kvm_arch_vcpu_id(CPUState *cpu); + +-#ifdef TARGET_I386 +-#define KVM_HAVE_MCE_INJECTION 1 ++#ifdef KVM_HAVE_MCE_INJECTION + void kvm_arch_on_sigbus_vcpu(CPUState *cpu, int code, void *addr); + #endif + +diff --git a/target/arm/cpu.h b/target/arm/cpu.h +index 676f216b67..5d995368d4 100644 +--- a/target/arm/cpu.h ++++ b/target/arm/cpu.h +@@ -28,6 +28,10 @@ + /* ARM processors have a weak memory model */ + #define TCG_GUEST_DEFAULT_MO (0) + ++#ifdef TARGET_AARCH64 ++#define KVM_HAVE_MCE_INJECTION 1 ++#endif ++ + #define EXCP_UDEF 1 /* undefined instruction */ + #define EXCP_SWI 2 /* software interrupt */ + #define EXCP_PREFETCH_ABORT 3 +diff --git a/target/arm/helper.c b/target/arm/helper.c +index b88d27819d..a92ae55672 100644 +--- a/target/arm/helper.c ++++ b/target/arm/helper.c +@@ -3465,7 +3465,7 @@ static uint64_t do_ats_write(CPUARMState *env, uint64_t value, + * Report exception with ESR indicating a fault due to a + * translation table walk for a cache maintenance instruction. + */ +- syn = syn_data_abort_no_iss(current_el == target_el, ++ syn = syn_data_abort_no_iss(current_el == target_el, 0, + fi.ea, 1, fi.s1ptw, 1, fsc); + env->exception.vaddress = value; + env->exception.fsr = fsr; +diff --git a/target/arm/internals.h b/target/arm/internals.h +index a833e3941d..4bdbc3a8ac 100644 +--- a/target/arm/internals.h ++++ b/target/arm/internals.h +@@ -451,13 +451,14 @@ static inline uint32_t syn_insn_abort(int same_el, int ea, int s1ptw, int fsc) + | ARM_EL_IL | (ea << 9) | (s1ptw << 7) | fsc; + } + +-static inline uint32_t syn_data_abort_no_iss(int same_el, ++static inline uint32_t syn_data_abort_no_iss(int same_el, int fnv, + int ea, int cm, int s1ptw, + int wnr, int fsc) + { + return (EC_DATAABORT << ARM_EL_EC_SHIFT) | (same_el << ARM_EL_EC_SHIFT) + | ARM_EL_IL +- | (ea << 9) | (cm << 8) | (s1ptw << 7) | (wnr << 6) | fsc; ++ | (fnv << 10) | (ea << 9) | (cm << 8) | (s1ptw << 7) ++ | (wnr << 6) | fsc; + } + + static inline uint32_t syn_data_abort_with_iss(int same_el, +diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c +index cd8ab6b8ae..f09ed9f4df 100644 +--- a/target/arm/kvm64.c ++++ b/target/arm/kvm64.c +@@ -28,6 +28,9 @@ + #include "sysemu/kvm_int.h" + #include "kvm_arm.h" + #include "internals.h" ++#include "hw/acpi/acpi.h" ++#include "hw/acpi/ghes.h" ++#include "hw/arm/virt.h" + + static bool have_guest_debug; + +@@ -883,6 +886,30 @@ int kvm_arm_cpreg_level(uint64_t regidx) + return KVM_PUT_RUNTIME_STATE; + } + ++/* Callers must hold the iothread mutex lock */ ++static void kvm_inject_arm_sea(CPUState *c) ++{ ++ ARMCPU *cpu = ARM_CPU(c); ++ CPUARMState *env = &cpu->env; ++ CPUClass *cc = CPU_GET_CLASS(c); ++ uint32_t esr; ++ bool same_el; ++ ++ c->exception_index = EXCP_DATA_ABORT; ++ env->exception.target_el = 1; ++ ++ /* ++ * Set the DFSC to synchronous external abort and set FnV to not valid, ++ * this will tell guest the FAR_ELx is UNKNOWN for this abort. ++ */ ++ same_el = arm_current_el(env) == env->exception.target_el; ++ esr = syn_data_abort_no_iss(same_el, 1, 0, 0, 0, 0, 0x10); ++ ++ env->exception.syndrome = esr; ++ ++ cc->do_interrupt(c); ++} ++ + #define AARCH64_CORE_REG(x) (KVM_REG_ARM64 | KVM_REG_SIZE_U64 | \ + KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(x)) + +@@ -1316,6 +1343,56 @@ int kvm_arch_get_registers(CPUState *cs) + return ret; + } + ++void kvm_arch_on_sigbus_vcpu(CPUState *c, int code, void *addr) ++{ ++ ram_addr_t ram_addr; ++ hwaddr paddr; ++ Object *obj = qdev_get_machine(); ++ VirtMachineState *vms = VIRT_MACHINE(obj); ++ bool acpi_enabled = virt_is_acpi_enabled(vms); ++ ++ assert(code == BUS_MCEERR_AR || code == BUS_MCEERR_AO); ++ ++ if (acpi_enabled && addr && ++ object_property_get_bool(obj, "ras", NULL)) { ++ ram_addr = qemu_ram_addr_from_host(addr); ++ if (ram_addr != RAM_ADDR_INVALID && ++ kvm_physical_memory_addr_from_host(c->kvm_state, addr, &paddr)) { ++ kvm_hwpoison_page_add(ram_addr); ++ /* ++ * If this is a BUS_MCEERR_AR, we know we have been called ++ * synchronously from the vCPU thread, so we can easily ++ * synchronize the state and inject an error. ++ * ++ * TODO: we currently don't tell the guest at all about ++ * BUS_MCEERR_AO. In that case we might either be being ++ * called synchronously from the vCPU thread, or a bit ++ * later from the main thread, so doing the injection of ++ * the error would be more complicated. ++ */ ++ if (code == BUS_MCEERR_AR) { ++ kvm_cpu_synchronize_state(c); ++ if (!acpi_ghes_record_errors(ACPI_HEST_SRC_ID_SEA, paddr)) { ++ kvm_inject_arm_sea(c); ++ } else { ++ error_report("failed to record the error"); ++ abort(); ++ } ++ } ++ return; ++ } ++ if (code == BUS_MCEERR_AO) { ++ error_report("Hardware memory error at addr %p for memory used by " ++ "QEMU itself instead of guest system!", addr); ++ } ++ } ++ ++ if (code == BUS_MCEERR_AR) { ++ error_report("Hardware memory error!"); ++ exit(1); ++ } ++} ++ + /* C6.6.29 BRK instruction */ + static const uint32_t brk_insn = 0xd4200000; + +diff --git a/target/arm/tlb_helper.c b/target/arm/tlb_helper.c +index e63f8bda29..7388494a55 100644 +--- a/target/arm/tlb_helper.c ++++ b/target/arm/tlb_helper.c +@@ -33,7 +33,7 @@ static inline uint32_t merge_syn_data_abort(uint32_t template_syn, + * ISV field. + */ + if (!(template_syn & ARM_EL_ISV) || target_el != 2 || s1ptw) { +- syn = syn_data_abort_no_iss(same_el, ++ syn = syn_data_abort_no_iss(same_el, 0, + ea, 0, s1ptw, is_write, fsc); + } else { + /* +diff --git a/target/i386/cpu.h b/target/i386/cpu.h +index e818fc712a..408392dbf6 100644 +--- a/target/i386/cpu.h ++++ b/target/i386/cpu.h +@@ -29,6 +29,8 @@ + /* The x86 has a strong memory model with some store-after-load re-ordering */ + #define TCG_GUEST_DEFAULT_MO (TCG_MO_ALL & ~TCG_MO_ST_LD) + ++#define KVM_HAVE_MCE_INJECTION 1 ++ + /* Maximum instruction code size */ + #define TARGET_MAX_INSN_SIZE 16 + +-- +2.23.0 + diff --git a/target-arm-translate-vfp.inc.c-Remove-duplicate-simd.patch b/target-arm-translate-vfp.inc.c-Remove-duplicate-simd.patch new file mode 100644 index 0000000000000000000000000000000000000000..a3f915c75680741ab83becc2cb0a49044146dd0b --- /dev/null +++ b/target-arm-translate-vfp.inc.c-Remove-duplicate-simd.patch @@ -0,0 +1,41 @@ +From 0d787cf1f3c88fa29477e054f8523f6d82d91c98 Mon Sep 17 00:00:00 2001 +From: Peter Maydell +Date: Thu, 30 Apr 2020 19:09:28 +0100 +Subject: [PATCH 168/709] target/arm/translate-vfp.inc.c: Remove duplicate + simd_r32 check +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Somewhere along theline we accidentally added a duplicate +"using D16-D31 when they don't exist" check to do_vfm_dp() +(probably an artifact of a patchseries rebase). Remove it. + +Signed-off-by: Peter Maydell +Reviewed-by: Richard Henderson +Reviewed-by: Philippe Mathieu-Daudé +Message-id: 20200430181003.21682-2-peter.maydell@linaro.org +--- + target/arm/translate-vfp.inc.c | 6 ------ + 1 file changed, 6 deletions(-) + +diff --git a/target/arm/translate-vfp.inc.c b/target/arm/translate-vfp.inc.c +index b087bbd812..e1a9017598 100644 +--- a/target/arm/translate-vfp.inc.c ++++ b/target/arm/translate-vfp.inc.c +@@ -1872,12 +1872,6 @@ static bool do_vfm_dp(DisasContext *s, arg_VFMA_dp *a, bool neg_n, bool neg_d) + return false; + } + +- /* UNDEF accesses to D16-D31 if they don't exist. */ +- if (!dc_isar_feature(aa32_simd_r32, s) && +- ((a->vd | a->vn | a->vm) & 0x10)) { +- return false; +- } +- + if (!vfp_access_check(s)) { + return true; + } +-- +2.23.0 + diff --git a/target-i386-add-MDS-NO-feature.patch b/target-i386-add-MDS-NO-feature.patch deleted file mode 100644 index 0c8ccfd98b34f8a237ad347e48af10c1910b3055..0000000000000000000000000000000000000000 --- a/target-i386-add-MDS-NO-feature.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 41e1564fb50515d7902628d25c0c8421a8516cc1 Mon Sep 17 00:00:00 2001 -From: Paolo Bonzini -Date: Thu, 6 Jun 2019 16:12:03 +0200 -Subject: [PATCH] target/i386: add MDS-NO feature - -Microarchitectural Data Sampling is a hardware vulnerability which allows -unprivileged speculative access to data which is available in various CPU -internal buffers. - -Some Intel processors use the ARCH_CAP_MDS_NO bit in the -IA32_ARCH_CAPABILITIES -MSR to report that they are not vulnerable, make it available to guests. - -Signed-off-by: Paolo Bonzini -Message-Id: <20190516185320.28340-1-pbonzini@redhat.com> -Signed-off-by: Eduardo Habkost -(cherry picked from commit 20140a82c67467f53814ca197403d5e1b561a5e5) -Signed-off-by: Oguz Bektas -Signed-off-by: Michael Roth ---- - target/i386/cpu.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/target/i386/cpu.c b/target/i386/cpu.c -index d6bb57d210..ee4b8b47e2 100644 ---- a/target/i386/cpu.c -+++ b/target/i386/cpu.c -@@ -1183,7 +1183,7 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { - .type = MSR_FEATURE_WORD, - .feat_names = { - "rdctl-no", "ibrs-all", "rsba", "skip-l1dfl-vmentry", -- "ssb-no", NULL, NULL, NULL, -+ "ssb-no", "mds-no", NULL, NULL, - NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, --- -2.19.1 - diff --git a/target-i386-define-md-clear-bit.patch b/target-i386-define-md-clear-bit.patch deleted file mode 100644 index 57289e4ac89a1390f4b0e9bfbc9062422e17d888..0000000000000000000000000000000000000000 --- a/target-i386-define-md-clear-bit.patch +++ /dev/null @@ -1,29 +0,0 @@ -From: Paolo Bonzini -Date: Wed, 15 May 2019 15:10:10 +0100 -Subject: [PATCH] target/i386: define md-clear bit - -md-clear is a new CPUID bit which is set when microcode provides the -mechanism to invoke a flush of various exploitable CPU buffers by invoking -the VERW instruction. - -Signed-off-by: Paolo Bonzini -Message-Id: <20190515141011.5315-2-berrange@redhat.com> -Signed-off-by: Eduardo Habkost -(cherry picked from commit b2ae52101fca7f9547ac2f388085dbc58f8fe1c0) ---- - target/i386/cpu.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/target/i386/cpu.c b/target/i386/cpu.c -index d6bb57d210..4ea78a4939 100644 ---- a/target/i386/cpu.c -+++ b/target/i386/cpu.c -@@ -1076,7 +1076,7 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { - .feat_names = { - NULL, NULL, "avx512-4vnniw", "avx512-4fmaps", - NULL, NULL, NULL, NULL, -- NULL, NULL, NULL, NULL, -+ NULL, NULL, "md-clear", NULL, - NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, diff --git a/target-m68k-fix-gdb-for-m68xxx.patch b/target-m68k-fix-gdb-for-m68xxx.patch new file mode 100644 index 0000000000000000000000000000000000000000..0033e51e5952775788590fd5a5c775a0a3e405cd --- /dev/null +++ b/target-m68k-fix-gdb-for-m68xxx.patch @@ -0,0 +1,171 @@ +From a976ed3ffdede7f64c89ac235d0154d048981b5f Mon Sep 17 00:00:00 2001 +From: KONRAD Frederic +Date: Thu, 30 Apr 2020 20:01:22 +0100 +Subject: [PATCH 279/709] target/m68k: fix gdb for m68xxx +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Currently "cf-core.xml" is sent to GDB when using any m68k flavor. Thing is +it uses the "org.gnu.gdb.coldfire.core" feature name and gdb 8.3 then expects +a coldfire FPU instead of the default m68881 FPU. + +This is not OK because the m68881 floats registers are 96 bits wide so it +crashes GDB with the following error message: + +(gdb) target remote localhost:7960 +Remote debugging using localhost:7960 +warning: Register "fp0" has an unsupported size (96 bits) +warning: Register "fp1" has an unsupported size (96 bits) +... +Remote 'g' packet reply is too long (expected 148 bytes, got 180 bytes): \ + 00000000000[...]0000 + +With this patch: qemu-system-m68k -M none -cpu m68020 -s -S + +(gdb) tar rem :1234 +Remote debugging using :1234 +warning: No executable has been specified and target does not support +determining executable automatically. Try using the "file" command. +0x00000000 in ?? () +(gdb) p $fp0 +$1 = nan(0xffffffffffffffff) + +Signed-off-by: KONRAD Frederic +Signed-off-by: Alex Bennée +Reviewed-by: Richard Henderson +Reviewed-by: Laurent Vivier +Message-Id: <1588094279-17913-3-git-send-email-frederic.konrad@adacore.com> +Message-Id: <20200430190122.4592-10-alex.bennee@linaro.org> +--- + configure | 2 +- + gdb-xml/m68k-core.xml | 29 ++++++++++++++++++++++++ + target/m68k/cpu.c | 52 ++++++++++++++++++++++++++++++------------- + 3 files changed, 67 insertions(+), 16 deletions(-) + create mode 100644 gdb-xml/m68k-core.xml + +diff --git a/configure b/configure +index c58787100f..0d69c360c0 100755 +--- a/configure ++++ b/configure +@@ -7825,7 +7825,7 @@ case "$target_name" in + ;; + m68k) + bflt="yes" +- gdb_xml_files="cf-core.xml cf-fp.xml m68k-fp.xml" ++ gdb_xml_files="cf-core.xml cf-fp.xml m68k-core.xml m68k-fp.xml" + TARGET_SYSTBL_ABI=common + ;; + microblaze|microblazeel) +diff --git a/gdb-xml/m68k-core.xml b/gdb-xml/m68k-core.xml +new file mode 100644 +index 0000000000..5b092d26de +--- /dev/null ++++ b/gdb-xml/m68k-core.xml +@@ -0,0 +1,29 @@ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ +diff --git a/target/m68k/cpu.c b/target/m68k/cpu.c +index 9445fcd6df..72c545149e 100644 +--- a/target/m68k/cpu.c ++++ b/target/m68k/cpu.c +@@ -292,16 +292,38 @@ static void m68k_cpu_class_init(ObjectClass *c, void *data) + cc->tcg_initialize = m68k_tcg_init; + + cc->gdb_num_core_regs = 18; +- cc->gdb_core_xml_file = "cf-core.xml"; + + dc->vmsd = &vmstate_m68k_cpu; + } + +-#define DEFINE_M68K_CPU_TYPE(cpu_model, initfn) \ +- { \ +- .name = M68K_CPU_TYPE_NAME(cpu_model), \ +- .instance_init = initfn, \ +- .parent = TYPE_M68K_CPU, \ ++static void m68k_cpu_class_init_cf_core(ObjectClass *c, void *data) ++{ ++ CPUClass *cc = CPU_CLASS(c); ++ ++ cc->gdb_core_xml_file = "cf-core.xml"; ++} ++ ++#define DEFINE_M68K_CPU_TYPE_CF(model) \ ++ { \ ++ .name = M68K_CPU_TYPE_NAME(#model), \ ++ .instance_init = model##_cpu_initfn, \ ++ .parent = TYPE_M68K_CPU, \ ++ .class_init = m68k_cpu_class_init_cf_core \ ++ } ++ ++static void m68k_cpu_class_init_m68k_core(ObjectClass *c, void *data) ++{ ++ CPUClass *cc = CPU_CLASS(c); ++ ++ cc->gdb_core_xml_file = "m68k-core.xml"; ++} ++ ++#define DEFINE_M68K_CPU_TYPE_M68K(model) \ ++ { \ ++ .name = M68K_CPU_TYPE_NAME(#model), \ ++ .instance_init = model##_cpu_initfn, \ ++ .parent = TYPE_M68K_CPU, \ ++ .class_init = m68k_cpu_class_init_m68k_core \ + } + + static const TypeInfo m68k_cpus_type_infos[] = { +@@ -314,15 +336,15 @@ static const TypeInfo m68k_cpus_type_infos[] = { + .class_size = sizeof(M68kCPUClass), + .class_init = m68k_cpu_class_init, + }, +- DEFINE_M68K_CPU_TYPE("m68000", m68000_cpu_initfn), +- DEFINE_M68K_CPU_TYPE("m68020", m68020_cpu_initfn), +- DEFINE_M68K_CPU_TYPE("m68030", m68030_cpu_initfn), +- DEFINE_M68K_CPU_TYPE("m68040", m68040_cpu_initfn), +- DEFINE_M68K_CPU_TYPE("m68060", m68060_cpu_initfn), +- DEFINE_M68K_CPU_TYPE("m5206", m5206_cpu_initfn), +- DEFINE_M68K_CPU_TYPE("m5208", m5208_cpu_initfn), +- DEFINE_M68K_CPU_TYPE("cfv4e", cfv4e_cpu_initfn), +- DEFINE_M68K_CPU_TYPE("any", any_cpu_initfn), ++ DEFINE_M68K_CPU_TYPE_M68K(m68000), ++ DEFINE_M68K_CPU_TYPE_M68K(m68020), ++ DEFINE_M68K_CPU_TYPE_M68K(m68030), ++ DEFINE_M68K_CPU_TYPE_M68K(m68040), ++ DEFINE_M68K_CPU_TYPE_M68K(m68060), ++ DEFINE_M68K_CPU_TYPE_CF(m5206), ++ DEFINE_M68K_CPU_TYPE_CF(m5208), ++ DEFINE_M68K_CPU_TYPE_CF(cfv4e), ++ DEFINE_M68K_CPU_TYPE_CF(any), + }; + + DEFINE_TYPES(m68k_cpus_type_infos) +-- +2.23.0 + diff --git a/target-microblaze-Add-MFS-Rd-EDR-translation.patch b/target-microblaze-Add-MFS-Rd-EDR-translation.patch new file mode 100644 index 0000000000000000000000000000000000000000..90b8ce475824e2ba86361ce0ba0ee105ff51e370 --- /dev/null +++ b/target-microblaze-Add-MFS-Rd-EDR-translation.patch @@ -0,0 +1,37 @@ +From 7cdae31d3a654d6487727809b27dd8e88874fd50 Mon Sep 17 00:00:00 2001 +From: Tong Ho +Date: Tue, 12 May 2020 16:36:49 +0200 +Subject: [PATCH 411/709] target/microblaze: Add MFS Rd,EDR translation + +This is to fix cpu-abort with 'qemu: fatal: unknown mfs reg d' +(in the default case) when microblaze guest issues 'MFS Rd,EDR' +instruction. + +Since embeddedsw release 2019.2, XPlm_ExceptionHandler() issues +the instruction on exception, and microblaze model aborts when +PLM firmware guest encounters an exception. + +Signed-off-by: Tong Ho +Reviewed-by: Edgar E. Iglesias +Reviewed-by: Luc Michel +Message-Id: <20200512143649.21655-2-edgar.iglesias@gmail.com> +Signed-off-by: Edgar E. Iglesias +--- + target/microblaze/translate.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/target/microblaze/translate.c b/target/microblaze/translate.c +index 20b7427811..92b3630804 100644 +--- a/target/microblaze/translate.c ++++ b/target/microblaze/translate.c +@@ -581,6 +581,7 @@ static void dec_msr(DisasContext *dc) + case SR_ESR: + case SR_FSR: + case SR_BTR: ++ case SR_EDR: + tcg_gen_extrl_i64_i32(cpu_R[dc->rd], cpu_SR[sr]); + break; + case 0x800: +-- +2.23.0 + diff --git a/target-microblaze-Add-the-div-zero-exception-propert.patch b/target-microblaze-Add-the-div-zero-exception-propert.patch new file mode 100644 index 0000000000000000000000000000000000000000..0f9141c3fc852c28d568adb683358e462454b394 --- /dev/null +++ b/target-microblaze-Add-the-div-zero-exception-propert.patch @@ -0,0 +1,74 @@ +From 622cc7305cdfe2402950d21bc2160a76646bf259 Mon Sep 17 00:00:00 2001 +From: "Edgar E. Iglesias" +Date: Wed, 30 Oct 2019 14:03:38 +0100 +Subject: [PATCH 090/709] target/microblaze: Add the div-zero-exception + property + +Add the div-zero-exception property to control if the core +traps divizions by zero. + +Reviewed-by: Alistair Francis +Reviewed-by: Luc Michel +Signed-off-by: Edgar E. Iglesias +--- + target/microblaze/cpu.c | 4 ++++ + target/microblaze/cpu.h | 1 + + target/microblaze/op_helper.c | 5 +++-- + 3 files changed, 8 insertions(+), 2 deletions(-) + +diff --git a/target/microblaze/cpu.c b/target/microblaze/cpu.c +index 2cc6b1513c..4211f50c11 100644 +--- a/target/microblaze/cpu.c ++++ b/target/microblaze/cpu.c +@@ -207,6 +207,8 @@ static void mb_cpu_realizefn(DeviceState *dev, Error **errp) + PVR2_DOPB_BUS_EXC_MASK : 0) | + (cpu->cfg.iopb_bus_exception ? + PVR2_IOPB_BUS_EXC_MASK : 0) | ++ (cpu->cfg.div_zero_exception ? ++ PVR2_DIV_ZERO_EXC_MASK : 0) | + (cpu->cfg.illegal_opcode_exception ? + PVR2_ILL_OPCODE_EXC_MASK : 0) | + (cpu->cfg.opcode_0_illegal ? +@@ -280,6 +282,8 @@ static Property mb_properties[] = { + cfg.iopb_bus_exception, false), + DEFINE_PROP_BOOL("ill-opcode-exception", MicroBlazeCPU, + cfg.illegal_opcode_exception, false), ++ DEFINE_PROP_BOOL("div-zero-exception", MicroBlazeCPU, ++ cfg.div_zero_exception, false), + DEFINE_PROP_BOOL("opcode-0x0-illegal", MicroBlazeCPU, + cfg.opcode_0_illegal, false), + DEFINE_PROP_STRING("version", MicroBlazeCPU, cfg.version), +diff --git a/target/microblaze/cpu.h b/target/microblaze/cpu.h +index 71d7317a58..3c07f9b3f7 100644 +--- a/target/microblaze/cpu.h ++++ b/target/microblaze/cpu.h +@@ -305,6 +305,7 @@ struct MicroBlazeCPU { + bool iopb_bus_exception; + bool illegal_opcode_exception; + bool opcode_0_illegal; ++ bool div_zero_exception; + char *version; + uint8_t pvr; + } cfg; +diff --git a/target/microblaze/op_helper.c b/target/microblaze/op_helper.c +index 18677ddfca..f3b17a95b3 100644 +--- a/target/microblaze/op_helper.c ++++ b/target/microblaze/op_helper.c +@@ -132,11 +132,12 @@ uint32_t helper_carry(uint32_t a, uint32_t b, uint32_t cf) + + static inline int div_prepare(CPUMBState *env, uint32_t a, uint32_t b) + { ++ MicroBlazeCPU *cpu = env_archcpu(env); ++ + if (b == 0) { + env->sregs[SR_MSR] |= MSR_DZ; + +- if ((env->sregs[SR_MSR] & MSR_EE) +- && !(env->pvr.regs[2] & PVR2_DIV_ZERO_EXC_MASK)) { ++ if ((env->sregs[SR_MSR] & MSR_EE) && cpu->cfg.div_zero_exception) { + env->sregs[SR_ESR] = ESR_EC_DIVZERO; + helper_raise_exception(env, EXCP_HW_EXCP); + } +-- +2.23.0 + diff --git a/target-microblaze-Add-the-ill-opcode-exception-prope.patch b/target-microblaze-Add-the-ill-opcode-exception-prope.patch new file mode 100644 index 0000000000000000000000000000000000000000..dcffb1d9154c05866985db3bd10d532e2c24365e --- /dev/null +++ b/target-microblaze-Add-the-ill-opcode-exception-prope.patch @@ -0,0 +1,68 @@ +From 5143fdf36f78bd4c11c4bacedfdbd44365aa5781 Mon Sep 17 00:00:00 2001 +From: "Edgar E. Iglesias" +Date: Wed, 30 Oct 2019 13:55:08 +0100 +Subject: [PATCH 089/709] target/microblaze: Add the ill-opcode-exception + property + +Add the ill-opcode-exception property to control if illegal +instructions will raise exceptions. + +Reviewed-by: Alistair Francis +Reviewed-by: Luc Michel +Signed-off-by: Edgar E. Iglesias +--- + target/microblaze/cpu.c | 4 ++++ + target/microblaze/cpu.h | 1 + + target/microblaze/translate.c | 2 +- + 3 files changed, 6 insertions(+), 1 deletion(-) + +diff --git a/target/microblaze/cpu.c b/target/microblaze/cpu.c +index 418a0cd1fa..2cc6b1513c 100644 +--- a/target/microblaze/cpu.c ++++ b/target/microblaze/cpu.c +@@ -207,6 +207,8 @@ static void mb_cpu_realizefn(DeviceState *dev, Error **errp) + PVR2_DOPB_BUS_EXC_MASK : 0) | + (cpu->cfg.iopb_bus_exception ? + PVR2_IOPB_BUS_EXC_MASK : 0) | ++ (cpu->cfg.illegal_opcode_exception ? ++ PVR2_ILL_OPCODE_EXC_MASK : 0) | + (cpu->cfg.opcode_0_illegal ? + PVR2_OPCODE_0x0_ILL_MASK : 0); + +@@ -276,6 +278,8 @@ static Property mb_properties[] = { + /* Enables bus exceptions on failed instruction fetches. */ + DEFINE_PROP_BOOL("iopb-bus-exception", MicroBlazeCPU, + cfg.iopb_bus_exception, false), ++ DEFINE_PROP_BOOL("ill-opcode-exception", MicroBlazeCPU, ++ cfg.illegal_opcode_exception, false), + DEFINE_PROP_BOOL("opcode-0x0-illegal", MicroBlazeCPU, + cfg.opcode_0_illegal, false), + DEFINE_PROP_STRING("version", MicroBlazeCPU, cfg.version), +diff --git a/target/microblaze/cpu.h b/target/microblaze/cpu.h +index d51587b342..71d7317a58 100644 +--- a/target/microblaze/cpu.h ++++ b/target/microblaze/cpu.h +@@ -303,6 +303,7 @@ struct MicroBlazeCPU { + bool endi; + bool dopb_bus_exception; + bool iopb_bus_exception; ++ bool illegal_opcode_exception; + bool opcode_0_illegal; + char *version; + uint8_t pvr; +diff --git a/target/microblaze/translate.c b/target/microblaze/translate.c +index 222632b670..b4a78551ef 100644 +--- a/target/microblaze/translate.c ++++ b/target/microblaze/translate.c +@@ -185,7 +185,7 @@ static void write_carryi(DisasContext *dc, bool carry) + static bool trap_illegal(DisasContext *dc, bool cond) + { + if (cond && (dc->tb_flags & MSR_EE_FLAG) +- && (dc->cpu->env.pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK)) { ++ && dc->cpu->cfg.illegal_opcode_exception) { + tcg_gen_movi_i64(cpu_SR[SR_ESR], ESR_EC_ILLEGAL_OP); + t_gen_raise_exception(dc, EXCP_HW_EXCP); + } +-- +2.23.0 + diff --git a/target-microblaze-Add-the-opcode-0x0-illegal-CPU-pro.patch b/target-microblaze-Add-the-opcode-0x0-illegal-CPU-pro.patch new file mode 100644 index 0000000000000000000000000000000000000000..b97a84445d1adfde76b700479a27ca928c0e9a40 --- /dev/null +++ b/target-microblaze-Add-the-opcode-0x0-illegal-CPU-pro.patch @@ -0,0 +1,70 @@ +From 1ee1bd28fcce858e6f51d2d1d6ef9048bc254b86 Mon Sep 17 00:00:00 2001 +From: "Edgar E. Iglesias" +Date: Wed, 30 Oct 2019 13:49:14 +0100 +Subject: [PATCH 088/709] target/microblaze: Add the opcode-0x0-illegal CPU + property + +Add the opcode-0x0-illegal CPU property to control if the core +should trap opcode zero as illegal. + +Reviewed-by: Alistair Francis +Reviewed-by: Luc Michel +Signed-off-by: Edgar E. Iglesias +--- + target/microblaze/cpu.c | 6 +++++- + target/microblaze/cpu.h | 1 + + target/microblaze/translate.c | 2 +- + 3 files changed, 7 insertions(+), 2 deletions(-) + +diff --git a/target/microblaze/cpu.c b/target/microblaze/cpu.c +index c9cf2364ca..418a0cd1fa 100644 +--- a/target/microblaze/cpu.c ++++ b/target/microblaze/cpu.c +@@ -206,7 +206,9 @@ static void mb_cpu_realizefn(DeviceState *dev, Error **errp) + (cpu->cfg.dopb_bus_exception ? + PVR2_DOPB_BUS_EXC_MASK : 0) | + (cpu->cfg.iopb_bus_exception ? +- PVR2_IOPB_BUS_EXC_MASK : 0); ++ PVR2_IOPB_BUS_EXC_MASK : 0) | ++ (cpu->cfg.opcode_0_illegal ? ++ PVR2_OPCODE_0x0_ILL_MASK : 0); + + env->pvr.regs[5] |= cpu->cfg.dcache_writeback ? + PVR5_DCACHE_WRITEBACK_MASK : 0; +@@ -274,6 +276,8 @@ static Property mb_properties[] = { + /* Enables bus exceptions on failed instruction fetches. */ + DEFINE_PROP_BOOL("iopb-bus-exception", MicroBlazeCPU, + cfg.iopb_bus_exception, false), ++ DEFINE_PROP_BOOL("opcode-0x0-illegal", MicroBlazeCPU, ++ cfg.opcode_0_illegal, false), + DEFINE_PROP_STRING("version", MicroBlazeCPU, cfg.version), + DEFINE_PROP_UINT8("pvr", MicroBlazeCPU, cfg.pvr, C_PVR_FULL), + DEFINE_PROP_END_OF_LIST(), +diff --git a/target/microblaze/cpu.h b/target/microblaze/cpu.h +index 1a700a880c..d51587b342 100644 +--- a/target/microblaze/cpu.h ++++ b/target/microblaze/cpu.h +@@ -303,6 +303,7 @@ struct MicroBlazeCPU { + bool endi; + bool dopb_bus_exception; + bool iopb_bus_exception; ++ bool opcode_0_illegal; + char *version; + uint8_t pvr; + } cfg; +diff --git a/target/microblaze/translate.c b/target/microblaze/translate.c +index 37a844db99..222632b670 100644 +--- a/target/microblaze/translate.c ++++ b/target/microblaze/translate.c +@@ -1573,7 +1573,7 @@ static inline void decode(DisasContext *dc, uint32_t ir) + LOG_DIS("%8.8x\t", dc->ir); + + if (ir == 0) { +- trap_illegal(dc, dc->cpu->env.pvr.regs[2] & PVR2_OPCODE_0x0_ILL_MASK); ++ trap_illegal(dc, dc->cpu->cfg.opcode_0_illegal); + /* Don't decode nop/zero instructions any further. */ + return; + } +-- +2.23.0 + diff --git a/target-microblaze-Add-the-pvr-user1-property.patch b/target-microblaze-Add-the-pvr-user1-property.patch new file mode 100644 index 0000000000000000000000000000000000000000..15656fe06803ced9c436a98dc020932dabc31f43 --- /dev/null +++ b/target-microblaze-Add-the-pvr-user1-property.patch @@ -0,0 +1,53 @@ +From c97673258c1f7e54260842cd0b01d24e82dd6220 Mon Sep 17 00:00:00 2001 +From: "Edgar E. Iglesias" +Date: Wed, 30 Oct 2019 14:15:46 +0100 +Subject: [PATCH 092/709] target/microblaze: Add the pvr-user1 property + +Add the pvr-user1 property to control the user-defined +PVR0 User1 field. + +Reviewed-by: Alistair Francis +Reviewed-by: Luc Michel +Signed-off-by: Edgar E. Iglesias +--- + target/microblaze/cpu.c | 4 +++- + target/microblaze/cpu.h | 1 + + 2 files changed, 4 insertions(+), 1 deletion(-) + +diff --git a/target/microblaze/cpu.c b/target/microblaze/cpu.c +index 585e60e817..df5ee21dd6 100644 +--- a/target/microblaze/cpu.c ++++ b/target/microblaze/cpu.c +@@ -193,7 +193,8 @@ static void mb_cpu_realizefn(DeviceState *dev, Error **errp) + (cpu->cfg.use_mmu ? PVR0_USE_MMU_MASK : 0) | + (cpu->cfg.endi ? PVR0_ENDI_MASK : 0) | + (version_code << PVR0_VERSION_SHIFT) | +- (cpu->cfg.pvr == C_PVR_FULL ? PVR0_PVR_FULL_MASK : 0); ++ (cpu->cfg.pvr == C_PVR_FULL ? PVR0_PVR_FULL_MASK : 0) | ++ cpu->cfg.pvr_user1; + + env->pvr.regs[2] |= (cpu->cfg.use_fpu ? PVR2_USE_FPU_MASK : 0) | + (cpu->cfg.use_fpu > 1 ? PVR2_USE_FPU2_MASK : 0) | +@@ -292,6 +293,7 @@ static Property mb_properties[] = { + cfg.opcode_0_illegal, false), + DEFINE_PROP_STRING("version", MicroBlazeCPU, cfg.version), + DEFINE_PROP_UINT8("pvr", MicroBlazeCPU, cfg.pvr, C_PVR_FULL), ++ DEFINE_PROP_UINT8("pvr-user1", MicroBlazeCPU, cfg.pvr_user1, 0), + DEFINE_PROP_END_OF_LIST(), + }; + +diff --git a/target/microblaze/cpu.h b/target/microblaze/cpu.h +index ef9081db40..7bb5a3d6c6 100644 +--- a/target/microblaze/cpu.h ++++ b/target/microblaze/cpu.h +@@ -307,6 +307,7 @@ struct MicroBlazeCPU { + bool opcode_0_illegal; + bool div_zero_exception; + bool unaligned_exceptions; ++ uint8_t pvr_user1; + char *version; + uint8_t pvr; + } cfg; +-- +2.23.0 + diff --git a/target-microblaze-Add-the-pvr-user2-property.patch b/target-microblaze-Add-the-pvr-user2-property.patch new file mode 100644 index 0000000000000000000000000000000000000000..3171e124238a1d1d57d6cafd09827503c2ef3c20 --- /dev/null +++ b/target-microblaze-Add-the-pvr-user2-property.patch @@ -0,0 +1,51 @@ +From 3ed43b5031ed2d7ef501bb81b87caed960218461 Mon Sep 17 00:00:00 2001 +From: "Edgar E. Iglesias" +Date: Wed, 30 Oct 2019 14:22:15 +0100 +Subject: [PATCH 093/709] target/microblaze: Add the pvr-user2 property + +Add the pvr-user2 property to control the user-defined +PVR1 User2 register. + +Reviewed-by: Alistair Francis +Reviewed-by: Luc Michel +Signed-off-by: Edgar E. Iglesias +--- + target/microblaze/cpu.c | 2 ++ + target/microblaze/cpu.h | 1 + + 2 files changed, 3 insertions(+) + +diff --git a/target/microblaze/cpu.c b/target/microblaze/cpu.c +index df5ee21dd6..aa9983069a 100644 +--- a/target/microblaze/cpu.c ++++ b/target/microblaze/cpu.c +@@ -196,6 +196,7 @@ static void mb_cpu_realizefn(DeviceState *dev, Error **errp) + (cpu->cfg.pvr == C_PVR_FULL ? PVR0_PVR_FULL_MASK : 0) | + cpu->cfg.pvr_user1; + ++ env->pvr.regs[1] = cpu->cfg.pvr_user2; + env->pvr.regs[2] |= (cpu->cfg.use_fpu ? PVR2_USE_FPU_MASK : 0) | + (cpu->cfg.use_fpu > 1 ? PVR2_USE_FPU2_MASK : 0) | + (cpu->cfg.use_hw_mul ? PVR2_USE_HW_MUL_MASK : 0) | +@@ -294,6 +295,7 @@ static Property mb_properties[] = { + DEFINE_PROP_STRING("version", MicroBlazeCPU, cfg.version), + DEFINE_PROP_UINT8("pvr", MicroBlazeCPU, cfg.pvr, C_PVR_FULL), + DEFINE_PROP_UINT8("pvr-user1", MicroBlazeCPU, cfg.pvr_user1, 0), ++ DEFINE_PROP_UINT32("pvr-user2", MicroBlazeCPU, cfg.pvr_user2, 0), + DEFINE_PROP_END_OF_LIST(), + }; + +diff --git a/target/microblaze/cpu.h b/target/microblaze/cpu.h +index 7bb5a3d6c6..a31134b65c 100644 +--- a/target/microblaze/cpu.h ++++ b/target/microblaze/cpu.h +@@ -308,6 +308,7 @@ struct MicroBlazeCPU { + bool div_zero_exception; + bool unaligned_exceptions; + uint8_t pvr_user1; ++ uint32_t pvr_user2; + char *version; + uint8_t pvr; + } cfg; +-- +2.23.0 + diff --git a/target-microblaze-Add-the-unaligned-exceptions-prope.patch b/target-microblaze-Add-the-unaligned-exceptions-prope.patch new file mode 100644 index 0000000000000000000000000000000000000000..81466d4f6dc1dc395b231d9231d4c3c14af47a38 --- /dev/null +++ b/target-microblaze-Add-the-unaligned-exceptions-prope.patch @@ -0,0 +1,77 @@ +From 1507e5f62e047fb78700f3e14c988d16a3a52ead Mon Sep 17 00:00:00 2001 +From: "Edgar E. Iglesias" +Date: Wed, 30 Oct 2019 14:09:37 +0100 +Subject: [PATCH 091/709] target/microblaze: Add the unaligned-exceptions + property + +Add the unaligned-exceptions property to control if the core +traps unaligned memory accesses. + +Reviewed-by: Alistair Francis +Reviewed-by: Luc Michel +Signed-off-by: Edgar E. Iglesias +--- + target/microblaze/cpu.c | 4 ++++ + target/microblaze/cpu.h | 1 + + target/microblaze/translate.c | 4 ++-- + 3 files changed, 7 insertions(+), 2 deletions(-) + +diff --git a/target/microblaze/cpu.c b/target/microblaze/cpu.c +index 4211f50c11..585e60e817 100644 +--- a/target/microblaze/cpu.c ++++ b/target/microblaze/cpu.c +@@ -211,6 +211,8 @@ static void mb_cpu_realizefn(DeviceState *dev, Error **errp) + PVR2_DIV_ZERO_EXC_MASK : 0) | + (cpu->cfg.illegal_opcode_exception ? + PVR2_ILL_OPCODE_EXC_MASK : 0) | ++ (cpu->cfg.unaligned_exceptions ? ++ PVR2_UNALIGNED_EXC_MASK : 0) | + (cpu->cfg.opcode_0_illegal ? + PVR2_OPCODE_0x0_ILL_MASK : 0); + +@@ -284,6 +286,8 @@ static Property mb_properties[] = { + cfg.illegal_opcode_exception, false), + DEFINE_PROP_BOOL("div-zero-exception", MicroBlazeCPU, + cfg.div_zero_exception, false), ++ DEFINE_PROP_BOOL("unaligned-exceptions", MicroBlazeCPU, ++ cfg.unaligned_exceptions, false), + DEFINE_PROP_BOOL("opcode-0x0-illegal", MicroBlazeCPU, + cfg.opcode_0_illegal, false), + DEFINE_PROP_STRING("version", MicroBlazeCPU, cfg.version), +diff --git a/target/microblaze/cpu.h b/target/microblaze/cpu.h +index 3c07f9b3f7..ef9081db40 100644 +--- a/target/microblaze/cpu.h ++++ b/target/microblaze/cpu.h +@@ -306,6 +306,7 @@ struct MicroBlazeCPU { + bool illegal_opcode_exception; + bool opcode_0_illegal; + bool div_zero_exception; ++ bool unaligned_exceptions; + char *version; + uint8_t pvr; + } cfg; +diff --git a/target/microblaze/translate.c b/target/microblaze/translate.c +index b4a78551ef..20b7427811 100644 +--- a/target/microblaze/translate.c ++++ b/target/microblaze/translate.c +@@ -995,7 +995,7 @@ static void dec_load(DisasContext *dc) + v = tcg_temp_new_i32(); + tcg_gen_qemu_ld_i32(v, addr, mem_index, mop); + +- if ((dc->cpu->env.pvr.regs[2] & PVR2_UNALIGNED_EXC_MASK) && size > 1) { ++ if (dc->cpu->cfg.unaligned_exceptions && size > 1) { + TCGv_i32 t0 = tcg_const_i32(0); + TCGv_i32 treg = tcg_const_i32(dc->rd); + TCGv_i32 tsize = tcg_const_i32(size - 1); +@@ -1110,7 +1110,7 @@ static void dec_store(DisasContext *dc) + tcg_gen_qemu_st_i32(cpu_R[dc->rd], addr, mem_index, mop); + + /* Verify alignment if needed. */ +- if ((dc->cpu->env.pvr.regs[2] & PVR2_UNALIGNED_EXC_MASK) && size > 1) { ++ if (dc->cpu->cfg.unaligned_exceptions && size > 1) { + TCGv_i32 t1 = tcg_const_i32(1); + TCGv_i32 treg = tcg_const_i32(dc->rd); + TCGv_i32 tsize = tcg_const_i32(size - 1); +-- +2.23.0 + diff --git a/target-microblaze-Fix-FPU2-instruction-check.patch b/target-microblaze-Fix-FPU2-instruction-check.patch new file mode 100644 index 0000000000000000000000000000000000000000..940bdc282e2e50b61e24c0ca494e437c8574a7ee --- /dev/null +++ b/target-microblaze-Fix-FPU2-instruction-check.patch @@ -0,0 +1,34 @@ +From 2016a6a765ad5283609183a5aa14d14285aaca6e Mon Sep 17 00:00:00 2001 +From: Joe Komlodi +Date: Mon, 11 May 2020 10:49:06 -0700 +Subject: [PATCH 412/709] target/microblaze: Fix FPU2 instruction check + +The check to see if we can use FPU2 instructions would return 0 if +cfg.use_fpu == 2, rather than returning the PVR2_USE_FPU2_MASK. + +This would cause all FPU2 instructions (fsqrt, flt, fint) to not be used. + +Signed-off-by: Joe Komlodi +Reviewed-by: Edgar E. Iglesias +Message-Id: <1589219346-106769-2-git-send-email-komlodi@xilinx.com> +Signed-off-by: Edgar E. Iglesias +--- + target/microblaze/translate.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/target/microblaze/translate.c b/target/microblaze/translate.c +index 92b3630804..8079724f32 100644 +--- a/target/microblaze/translate.c ++++ b/target/microblaze/translate.c +@@ -1392,7 +1392,7 @@ static int dec_check_fpuv2(DisasContext *dc) + tcg_gen_movi_i64(cpu_SR[SR_ESR], ESR_EC_FPU); + t_gen_raise_exception(dc, EXCP_HW_EXCP); + } +- return (dc->cpu->cfg.use_fpu == 2) ? 0 : PVR2_USE_FPU2_MASK; ++ return (dc->cpu->cfg.use_fpu == 2) ? PVR2_USE_FPU2_MASK : 0; + } + + static void dec_fpu(DisasContext *dc) +-- +2.23.0 + diff --git a/target-microblaze-gdb-Extend-the-number-of-registers.patch b/target-microblaze-gdb-Extend-the-number-of-registers.patch new file mode 100644 index 0000000000000000000000000000000000000000..390a5929d6297768c7bca698dbe34ea7f2feb61e --- /dev/null +++ b/target-microblaze-gdb-Extend-the-number-of-registers.patch @@ -0,0 +1,108 @@ +From a44e82db0c0bada34af613029cf976f8bb7859d9 Mon Sep 17 00:00:00 2001 +From: Joe Komlodi +Date: Wed, 13 May 2020 11:08:46 -0700 +Subject: [PATCH 415/709] target/microblaze: gdb: Extend the number of + registers presented to GDB + +Increase the number of Microblaze registers QEMU will report when +talking to GDB. + +Signed-off-by: Joe Komlodi +Reviewed-by: Edgar E. Iglesias +Message-Id: <1589393329-223076-2-git-send-email-komlodi@xilinx.com> +Signed-off-by: Edgar E. Iglesias +--- + target/microblaze/cpu.c | 2 +- + target/microblaze/gdbstub.c | 52 ++++++++++++++++++++++++++++++++++--- + 2 files changed, 50 insertions(+), 4 deletions(-) + +diff --git a/target/microblaze/cpu.c b/target/microblaze/cpu.c +index aa9983069a..51e5c85b10 100644 +--- a/target/microblaze/cpu.c ++++ b/target/microblaze/cpu.c +@@ -329,7 +329,7 @@ static void mb_cpu_class_init(ObjectClass *oc, void *data) + #endif + dc->vmsd = &vmstate_mb_cpu; + device_class_set_props(dc, mb_properties); +- cc->gdb_num_core_regs = 32 + 5; ++ cc->gdb_num_core_regs = 32 + 27; + + cc->disas_set_info = mb_disas_set_info; + cc->tcg_initialize = mb_tcg_init; +diff --git a/target/microblaze/gdbstub.c b/target/microblaze/gdbstub.c +index f41ebf1f33..54cc7857d1 100644 +--- a/target/microblaze/gdbstub.c ++++ b/target/microblaze/gdbstub.c +@@ -26,12 +26,37 @@ int mb_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n) + MicroBlazeCPU *cpu = MICROBLAZE_CPU(cs); + CPUMBState *env = &cpu->env; + ++ /* ++ * GDB expects registers to be reported in this order: ++ * R0-R31 ++ * PC-BTR ++ * PVR0-PVR11 ++ * EDR-TLBHI ++ * SLR-SHR ++ */ + if (n < 32) { + return gdb_get_reg32(mem_buf, env->regs[n]); + } else { +- return gdb_get_reg32(mem_buf, env->sregs[n - 32]); ++ n -= 32; ++ switch (n) { ++ case 0 ... 5: ++ return gdb_get_reg32(mem_buf, env->sregs[n]); ++ /* PVR12 is intentionally skipped */ ++ case 6 ... 17: ++ n -= 6; ++ return gdb_get_reg32(mem_buf, env->pvr.regs[n]); ++ case 18 ... 24: ++ /* Add an offset of 6 to resume where we left off with SRegs */ ++ n = n - 18 + 6; ++ return gdb_get_reg32(mem_buf, env->sregs[n]); ++ case 25: ++ return gdb_get_reg32(mem_buf, env->slr); ++ case 26: ++ return gdb_get_reg32(mem_buf, env->shr); ++ default: ++ return 0; ++ } + } +- return 0; + } + + int mb_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n) +@@ -50,7 +75,28 @@ int mb_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n) + if (n < 32) { + env->regs[n] = tmp; + } else { +- env->sregs[n - 32] = tmp; ++ n -= 32; ++ switch (n) { ++ case 0 ... 5: ++ env->sregs[n] = tmp; ++ break; ++ /* PVR12 is intentionally skipped */ ++ case 6 ... 17: ++ n -= 6; ++ env->pvr.regs[n] = tmp; ++ break; ++ case 18 ... 24: ++ /* Add an offset of 6 to resume where we left off with SRegs */ ++ n = n - 18 + 6; ++ env->sregs[n] = tmp; ++ break; ++ case 25: ++ env->slr = tmp; ++ break; ++ case 26: ++ env->shr = tmp; ++ break; ++ } + } + return 4; + } +-- +2.23.0 + diff --git a/target-microblaze-gdb-Fix-incorrect-SReg-reporting.patch b/target-microblaze-gdb-Fix-incorrect-SReg-reporting.patch new file mode 100644 index 0000000000000000000000000000000000000000..6ede4ce61640e8619ce4d268815a31e1928eb18f --- /dev/null +++ b/target-microblaze-gdb-Fix-incorrect-SReg-reporting.patch @@ -0,0 +1,129 @@ +From 201dd7d37b654621c5727e49c666cbfc56e61d58 Mon Sep 17 00:00:00 2001 +From: Joe Komlodi +Date: Wed, 13 May 2020 11:08:47 -0700 +Subject: [PATCH 416/709] target/microblaze: gdb: Fix incorrect SReg reporting + +SRegs used to be reported to GDB by iterating over the SRegs array, +however we do not store them in an order that allows them to be +reported to GDB in that way. + +To fix this, a simple map is used to map the register GDB wants to its +location in the SRegs array. + +Signed-off-by: Joe Komlodi +Reviewed-by: Edgar E. Iglesias +Message-Id: <1589393329-223076-3-git-send-email-komlodi@xilinx.com> +Signed-off-by: Edgar E. Iglesias +--- + target/microblaze/gdbstub.c | 59 ++++++++++++++++++++++++++++++------- + 1 file changed, 49 insertions(+), 10 deletions(-) + +diff --git a/target/microblaze/gdbstub.c b/target/microblaze/gdbstub.c +index 54cc7857d1..73e8973597 100644 +--- a/target/microblaze/gdbstub.c ++++ b/target/microblaze/gdbstub.c +@@ -25,6 +25,21 @@ int mb_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n) + { + MicroBlazeCPU *cpu = MICROBLAZE_CPU(cs); + CPUMBState *env = &cpu->env; ++ /* ++ * GDB expects SREGs in the following order: ++ * PC, MSR, EAR, ESR, FSR, BTR, EDR, PID, ZPR, TLBX, TLBSX, TLBLO, TLBHI. ++ * They aren't stored in this order, so make a map. ++ * PID, ZPR, TLBx, TLBsx, TLBLO, and TLBHI aren't modeled, so we don't ++ * map them to anything and return a value of 0 instead. ++ */ ++ static const uint8_t sreg_map[6] = { ++ SR_PC, ++ SR_MSR, ++ SR_EAR, ++ SR_ESR, ++ SR_FSR, ++ SR_BTR ++ }; + + /* + * GDB expects registers to be reported in this order: +@@ -40,15 +55,16 @@ int mb_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n) + n -= 32; + switch (n) { + case 0 ... 5: +- return gdb_get_reg32(mem_buf, env->sregs[n]); ++ return gdb_get_reg32(mem_buf, env->sregs[sreg_map[n]]); + /* PVR12 is intentionally skipped */ + case 6 ... 17: + n -= 6; + return gdb_get_reg32(mem_buf, env->pvr.regs[n]); +- case 18 ... 24: +- /* Add an offset of 6 to resume where we left off with SRegs */ +- n = n - 18 + 6; +- return gdb_get_reg32(mem_buf, env->sregs[n]); ++ case 18: ++ return gdb_get_reg32(mem_buf, env->sregs[SR_EDR]); ++ /* Other SRegs aren't modeled, so report a value of 0 */ ++ case 19 ... 24: ++ return gdb_get_reg32(mem_buf, 0); + case 25: + return gdb_get_reg32(mem_buf, env->slr); + case 26: +@@ -66,29 +82,52 @@ int mb_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n) + CPUMBState *env = &cpu->env; + uint32_t tmp; + ++ /* ++ * GDB expects SREGs in the following order: ++ * PC, MSR, EAR, ESR, FSR, BTR, EDR, PID, ZPR, TLBX, TLBSX, TLBLO, TLBHI. ++ * They aren't stored in this order, so make a map. ++ * PID, ZPR, TLBx, TLBsx, TLBLO, and TLBHI aren't modeled, so we don't ++ * map them to anything. ++ */ ++ static const uint8_t sreg_map[6] = { ++ SR_PC, ++ SR_MSR, ++ SR_EAR, ++ SR_ESR, ++ SR_FSR, ++ SR_BTR ++ }; ++ + if (n > cc->gdb_num_core_regs) { + return 0; + } + + tmp = ldl_p(mem_buf); + ++ /* ++ * GDB expects registers to be reported in this order: ++ * R0-R31 ++ * PC-BTR ++ * PVR0-PVR11 ++ * EDR-TLBHI ++ * SLR-SHR ++ */ + if (n < 32) { + env->regs[n] = tmp; + } else { + n -= 32; + switch (n) { + case 0 ... 5: +- env->sregs[n] = tmp; ++ env->sregs[sreg_map[n]] = tmp; + break; + /* PVR12 is intentionally skipped */ + case 6 ... 17: + n -= 6; + env->pvr.regs[n] = tmp; + break; +- case 18 ... 24: +- /* Add an offset of 6 to resume where we left off with SRegs */ +- n = n - 18 + 6; +- env->sregs[n] = tmp; ++ /* Only EDR is modeled in these indeces, so ignore the rest */ ++ case 18: ++ env->sregs[SR_EDR] = tmp; + break; + case 25: + env->slr = tmp; +-- +2.23.0 + diff --git a/target-microblaze-monitor-Increase-the-number-of-reg.patch b/target-microblaze-monitor-Increase-the-number-of-reg.patch new file mode 100644 index 0000000000000000000000000000000000000000..e404dba381ac17c745a17fef7303465e8a9ab16c --- /dev/null +++ b/target-microblaze-monitor-Increase-the-number-of-reg.patch @@ -0,0 +1,57 @@ +From 2ead1b18ca1bbc41c09a82d980e1e5f53afa08eb Mon Sep 17 00:00:00 2001 +From: Joe Komlodi +Date: Wed, 13 May 2020 11:08:48 -0700 +Subject: [PATCH 417/709] target/microblaze: monitor: Increase the number of + registers reported + +Increase the number of registers reported to match GDB. + +Registers that aren't modeled are reported as 0. + +Signed-off-by: Joe Komlodi +Reviewed-by: Edgar E. Iglesias +Message-Id: <1589393329-223076-4-git-send-email-komlodi@xilinx.com> +Signed-off-by: Edgar E. Iglesias +--- + target/microblaze/translate.c | 16 ++++++++++++++-- + 1 file changed, 14 insertions(+), 2 deletions(-) + +diff --git a/target/microblaze/translate.c b/target/microblaze/translate.c +index 8079724f32..f6ff2591c3 100644 +--- a/target/microblaze/translate.c ++++ b/target/microblaze/translate.c +@@ -1789,9 +1789,11 @@ void mb_cpu_dump_state(CPUState *cs, FILE *f, int flags) + qemu_fprintf(f, "IN: PC=%" PRIx64 " %s\n", + env->sregs[SR_PC], lookup_symbol(env->sregs[SR_PC])); + qemu_fprintf(f, "rmsr=%" PRIx64 " resr=%" PRIx64 " rear=%" PRIx64 " " +- "debug=%x imm=%x iflags=%x fsr=%" PRIx64 "\n", ++ "debug=%x imm=%x iflags=%x fsr=%" PRIx64 " " ++ "rbtr=%" PRIx64 "\n", + env->sregs[SR_MSR], env->sregs[SR_ESR], env->sregs[SR_EAR], +- env->debug, env->imm, env->iflags, env->sregs[SR_FSR]); ++ env->debug, env->imm, env->iflags, env->sregs[SR_FSR], ++ env->sregs[SR_BTR]); + qemu_fprintf(f, "btaken=%d btarget=%" PRIx64 " mode=%s(saved=%s) " + "eip=%d ie=%d\n", + env->btaken, env->btarget, +@@ -1799,7 +1801,17 @@ void mb_cpu_dump_state(CPUState *cs, FILE *f, int flags) + (env->sregs[SR_MSR] & MSR_UMS) ? "user" : "kernel", + (bool)(env->sregs[SR_MSR] & MSR_EIP), + (bool)(env->sregs[SR_MSR] & MSR_IE)); ++ for (i = 0; i < 12; i++) { ++ qemu_fprintf(f, "rpvr%2.2d=%8.8x ", i, env->pvr.regs[i]); ++ if ((i + 1) % 4 == 0) { ++ qemu_fprintf(f, "\n"); ++ } ++ } + ++ /* Registers that aren't modeled are reported as 0 */ ++ qemu_fprintf(f, "redr=%" PRIx64 " rpid=0 rzpr=0 rtlbx=0 rtlbsx=0 " ++ "rtlblo=0 rtlbhi=0\n", env->sregs[SR_EDR]); ++ qemu_fprintf(f, "slr=%x shr=%x\n", env->slr, env->shr); + for (i = 0; i < 32; i++) { + qemu_fprintf(f, "r%2.2d=%8.8x ", i, env->regs[i]); + if ((i + 1) % 4 == 0) +-- +2.23.0 + diff --git a/target-ppc-Add-support-for-Radix-partition-scoped-tr.patch b/target-ppc-Add-support-for-Radix-partition-scoped-tr.patch new file mode 100644 index 0000000000000000000000000000000000000000..95e9dccd67f08c855859d8d208efc28a6cbb64bc --- /dev/null +++ b/target-ppc-Add-support-for-Radix-partition-scoped-tr.patch @@ -0,0 +1,353 @@ +From d04ea940c597201a6610c5d1712809ed35dd77ec Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= +Date: Fri, 3 Apr 2020 16:00:56 +0200 +Subject: [PATCH 307/709] target/ppc: Add support for Radix partition-scoped + translation +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The Radix tree translation model currently supports process-scoped +translation for the PowerNV machine (Hypervisor mode) and for the +pSeries machine (Guest mode). Guests running under an emulated +Hypervisor (PowerNV machine) require a new type of Radix translation, +called partition-scoped, which is missing today. + +The Radix tree translation is a 2 steps process. The first step, +process-scoped translation, converts an effective Address to a guest +real address, and the second step, partition-scoped translation, +converts a guest real address to a host real address. + +There are difference cases to covers : + +* Hypervisor real mode access: no Radix translation. + +* Hypervisor or host application access (quadrant 0 and 3) with + relocation on: process-scoped translation. + +* Guest OS real mode access: only partition-scoped translation. + +* Guest OS real or guest application access (quadrant 0 and 3) with + relocation on: both process-scoped translation and partition-scoped + translations. + +* Hypervisor access in quadrant 1 and 2 with relocation on: both + process-scoped translation and partition-scoped translations. + +The radix tree partition-scoped translation is performed using tables +pointed to by the first double-word of the Partition Table Entries and +process-scoped translation uses tables pointed to by the Process Table +Entries (second double-word of the Partition Table Entries). + +Both partition-scoped and process-scoped translations process are +identical and thus the radix tree traversing code is largely reused. +However, errors in partition-scoped translations generate hypervisor +exceptions. + +Signed-off-by: Suraj Jitindar Singh +Signed-off-by: Greg Kurz +Signed-off-by: Cédric Le Goater +Message-Id: <20200403140056.59465-5-clg@kaod.org> +[dwg: Fixup from Greg Kurz folded in] +Signed-off-by: David Gibson +--- + target/ppc/cpu.h | 3 + + target/ppc/excp_helper.c | 3 +- + target/ppc/mmu-radix64.c | 194 +++++++++++++++++++++++++++++++++++---- + 3 files changed, 181 insertions(+), 19 deletions(-) + +diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h +index f4a5304d43..6b6dd7e483 100644 +--- a/target/ppc/cpu.h ++++ b/target/ppc/cpu.h +@@ -463,6 +463,9 @@ typedef struct ppc_v3_pate_t { + #define DSISR_AMR 0x00200000 + /* Unsupported Radix Tree Configuration */ + #define DSISR_R_BADCONFIG 0x00080000 ++#define DSISR_ATOMIC_RC 0x00040000 ++/* Unable to translate address of (guest) pde or process/page table entry */ ++#define DSISR_PRTABLE_FAULT 0x00020000 + + /* SRR1 error code fields */ + +diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c +index 1acc3786de..f052979664 100644 +--- a/target/ppc/excp_helper.c ++++ b/target/ppc/excp_helper.c +@@ -506,9 +506,10 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp) + case POWERPC_EXCP_ISEG: /* Instruction segment exception */ + case POWERPC_EXCP_TRACE: /* Trace exception */ + break; ++ case POWERPC_EXCP_HISI: /* Hypervisor instruction storage exception */ ++ msr |= env->error_code; + case POWERPC_EXCP_HDECR: /* Hypervisor decrementer exception */ + case POWERPC_EXCP_HDSI: /* Hypervisor data storage exception */ +- case POWERPC_EXCP_HISI: /* Hypervisor instruction storage exception */ + case POWERPC_EXCP_HDSEG: /* Hypervisor data segment exception */ + case POWERPC_EXCP_HISEG: /* Hypervisor instruction segment exception */ + case POWERPC_EXCP_SDOOR_HV: /* Hypervisor Doorbell interrupt */ +diff --git a/target/ppc/mmu-radix64.c b/target/ppc/mmu-radix64.c +index 2400da41e0..1404e53dec 100644 +--- a/target/ppc/mmu-radix64.c ++++ b/target/ppc/mmu-radix64.c +@@ -103,6 +103,27 @@ static void ppc_radix64_raise_si(PowerPCCPU *cpu, int rwx, vaddr eaddr, + } + } + ++static void ppc_radix64_raise_hsi(PowerPCCPU *cpu, int rwx, vaddr eaddr, ++ hwaddr g_raddr, uint32_t cause) ++{ ++ CPUState *cs = CPU(cpu); ++ CPUPPCState *env = &cpu->env; ++ ++ if (rwx == 2) { /* H Instruction Storage Interrupt */ ++ cs->exception_index = POWERPC_EXCP_HISI; ++ env->spr[SPR_ASDR] = g_raddr; ++ env->error_code = cause; ++ } else { /* H Data Storage Interrupt */ ++ cs->exception_index = POWERPC_EXCP_HDSI; ++ if (rwx == 1) { /* Write -> Store */ ++ cause |= DSISR_ISSTORE; ++ } ++ env->spr[SPR_HDSISR] = cause; ++ env->spr[SPR_HDAR] = eaddr; ++ env->spr[SPR_ASDR] = g_raddr; ++ env->error_code = 0; ++ } ++} + + static bool ppc_radix64_check_prot(PowerPCCPU *cpu, int rwx, uint64_t pte, + int *fault_cause, int *prot, +@@ -243,6 +264,37 @@ static bool validate_pate(PowerPCCPU *cpu, uint64_t lpid, ppc_v3_pate_t *pate) + return true; + } + ++static int ppc_radix64_partition_scoped_xlate(PowerPCCPU *cpu, int rwx, ++ vaddr eaddr, hwaddr g_raddr, ++ ppc_v3_pate_t pate, ++ hwaddr *h_raddr, int *h_prot, ++ int *h_page_size, bool pde_addr, ++ bool cause_excp) ++{ ++ int fault_cause = 0; ++ hwaddr pte_addr; ++ uint64_t pte; ++ ++ *h_page_size = PRTBE_R_GET_RTS(pate.dw0); ++ /* No valid pte or access denied due to protection */ ++ if (ppc_radix64_walk_tree(CPU(cpu)->as, g_raddr, pate.dw0 & PRTBE_R_RPDB, ++ pate.dw0 & PRTBE_R_RPDS, h_raddr, h_page_size, ++ &pte, &fault_cause, &pte_addr) || ++ ppc_radix64_check_prot(cpu, rwx, pte, &fault_cause, h_prot, true)) { ++ if (pde_addr) /* address being translated was that of a guest pde */ ++ fault_cause |= DSISR_PRTABLE_FAULT; ++ if (cause_excp) { ++ ppc_radix64_raise_hsi(cpu, rwx, eaddr, g_raddr, fault_cause); ++ } ++ return 1; ++ } ++ ++ /* Update Reference and Change Bits */ ++ ppc_radix64_set_rc(cpu, rwx, pte, pte_addr, h_prot); ++ ++ return 0; ++} ++ + static int ppc_radix64_process_scoped_xlate(PowerPCCPU *cpu, int rwx, + vaddr eaddr, uint64_t pid, + ppc_v3_pate_t pate, hwaddr *g_raddr, +@@ -250,9 +302,10 @@ static int ppc_radix64_process_scoped_xlate(PowerPCCPU *cpu, int rwx, + bool cause_excp) + { + CPUState *cs = CPU(cpu); +- uint64_t offset, size, prtbe_addr, prtbe0, pte; +- int fault_cause = 0; +- hwaddr pte_addr; ++ CPUPPCState *env = &cpu->env; ++ uint64_t offset, size, prtbe_addr, prtbe0, base_addr, nls, index, pte; ++ int fault_cause = 0, h_page_size, h_prot; ++ hwaddr h_raddr, pte_addr; + int ret; + + /* Index Process Table by PID to Find Corresponding Process Table Entry */ +@@ -266,18 +319,85 @@ static int ppc_radix64_process_scoped_xlate(PowerPCCPU *cpu, int rwx, + return 1; + } + prtbe_addr = (pate.dw1 & PATE1_R_PRTB) + offset; +- prtbe0 = ldq_phys(cs->as, prtbe_addr); ++ ++ if (cpu->vhyp) { ++ prtbe0 = ldq_phys(cs->as, prtbe_addr); ++ } else { ++ /* ++ * Process table addresses are subject to partition-scoped ++ * translation ++ * ++ * On a Radix host, the partition-scoped page table for LPID=0 ++ * is only used to translate the effective addresses of the ++ * process table entries. ++ */ ++ ret = ppc_radix64_partition_scoped_xlate(cpu, 0, eaddr, prtbe_addr, ++ pate, &h_raddr, &h_prot, ++ &h_page_size, 1, 1); ++ if (ret) { ++ return ret; ++ } ++ prtbe0 = ldq_phys(cs->as, h_raddr); ++ } + + /* Walk Radix Tree from Process Table Entry to Convert EA to RA */ + *g_page_size = PRTBE_R_GET_RTS(prtbe0); +- ret = ppc_radix64_walk_tree(cs->as, eaddr & R_EADDR_MASK, +- prtbe0 & PRTBE_R_RPDB, prtbe0 & PRTBE_R_RPDS, +- g_raddr, g_page_size, &pte, &fault_cause, +- &pte_addr); +- +- if (ret || +- ppc_radix64_check_prot(cpu, rwx, pte, &fault_cause, g_prot, false)) { +- /* No valid pte or access denied due to protection */ ++ base_addr = prtbe0 & PRTBE_R_RPDB; ++ nls = prtbe0 & PRTBE_R_RPDS; ++ if (msr_hv || cpu->vhyp) { ++ /* ++ * Can treat process table addresses as real addresses ++ */ ++ ret = ppc_radix64_walk_tree(cs->as, eaddr & R_EADDR_MASK, base_addr, ++ nls, g_raddr, g_page_size, &pte, ++ &fault_cause, &pte_addr); ++ if (ret) { ++ /* No valid PTE */ ++ if (cause_excp) { ++ ppc_radix64_raise_si(cpu, rwx, eaddr, fault_cause); ++ } ++ return ret; ++ } ++ } else { ++ uint64_t rpn, mask; ++ ++ index = (eaddr & R_EADDR_MASK) >> (*g_page_size - nls); /* Shift */ ++ index &= ((1UL << nls) - 1); /* Mask */ ++ pte_addr = base_addr + (index * sizeof(pte)); ++ ++ /* ++ * Each process table address is subject to a partition-scoped ++ * translation ++ */ ++ do { ++ ret = ppc_radix64_partition_scoped_xlate(cpu, 0, eaddr, pte_addr, ++ pate, &h_raddr, &h_prot, ++ &h_page_size, 1, 1); ++ if (ret) { ++ return ret; ++ } ++ ++ ret = ppc_radix64_next_level(cs->as, eaddr & R_EADDR_MASK, &h_raddr, ++ &nls, g_page_size, &pte, &fault_cause); ++ if (ret) { ++ /* No valid pte */ ++ if (cause_excp) { ++ ppc_radix64_raise_si(cpu, rwx, eaddr, fault_cause); ++ } ++ return ret; ++ } ++ pte_addr = h_raddr; ++ } while (!(pte & R_PTE_LEAF)); ++ ++ rpn = pte & R_PTE_RPN; ++ mask = (1UL << *g_page_size) - 1; ++ ++ /* Or high bits of rpn and low bits to ea to form whole real addr */ ++ *g_raddr = (rpn & ~mask) | (eaddr & mask); ++ } ++ ++ if (ppc_radix64_check_prot(cpu, rwx, pte, &fault_cause, g_prot, false)) { ++ /* Access denied due to protection */ + if (cause_excp) { + ppc_radix64_raise_si(cpu, rwx, eaddr, fault_cause); + } +@@ -289,11 +409,29 @@ static int ppc_radix64_process_scoped_xlate(PowerPCCPU *cpu, int rwx, + return 0; + } + ++/* ++ * Radix tree translation is a 2 steps translation process: ++ * ++ * 1. Process-scoped translation: Guest Eff Addr -> Guest Real Addr ++ * 2. Partition-scoped translation: Guest Real Addr -> Host Real Addr ++ * ++ * MSR[HV] ++ * +-------------+----------------+---------------+ ++ * | | HV = 0 | HV = 1 | ++ * +-------------+----------------+---------------+ ++ * | Relocation | Partition | No | ++ * | = Off | Scoped | Translation | ++ * Relocation +-------------+----------------+---------------+ ++ * | Relocation | Partition & | Process | ++ * | = On | Process Scoped | Scoped | ++ * +-------------+----------------+---------------+ ++ */ + static int ppc_radix64_xlate(PowerPCCPU *cpu, vaddr eaddr, int rwx, + bool relocation, + hwaddr *raddr, int *psizep, int *protp, + bool cause_excp) + { ++ CPUPPCState *env = &cpu->env; + uint64_t lpid = 0, pid = 0; + ppc_v3_pate_t pate; + int psize, prot; +@@ -325,11 +463,6 @@ static int ppc_radix64_xlate(PowerPCCPU *cpu, vaddr eaddr, int rwx, + } + return 1; + } +- /* We don't support guest mode yet */ +- if (lpid != 0) { +- error_report("PowerNV guest support Unimplemented"); +- exit(1); +- } + } + + *psizep = INT_MAX; +@@ -340,6 +473,8 @@ static int ppc_radix64_xlate(PowerPCCPU *cpu, vaddr eaddr, int rwx, + * + * - Translates an effective address to a host real address in + * quadrants 0 and 3 when HV=1. ++ * ++ * - Translates an effective address to a guest real address. + */ + if (relocation) { + int ret = ppc_radix64_process_scoped_xlate(cpu, rwx, eaddr, pid, +@@ -354,7 +489,30 @@ static int ppc_radix64_xlate(PowerPCCPU *cpu, vaddr eaddr, int rwx, + g_raddr = eaddr & R_EADDR_MASK; + } + +- *raddr = g_raddr; ++ if (cpu->vhyp) { ++ *raddr = g_raddr; ++ } else { ++ /* ++ * Perform partition-scoped translation if !HV or HV access to ++ * quadrants 1 or 2. Translates a guest real address to a host ++ * real address. ++ */ ++ if (lpid || !msr_hv) { ++ int ret; ++ ++ ret = ppc_radix64_partition_scoped_xlate(cpu, rwx, eaddr, g_raddr, ++ pate, raddr, &prot, &psize, ++ 0, cause_excp); ++ if (ret) { ++ return ret; ++ } ++ *psizep = MIN(*psizep, psize); ++ *protp &= prot; ++ } else { ++ *raddr = g_raddr; ++ } ++ } ++ + return 0; + } + +-- +2.23.0 + diff --git a/target-ppc-Assert-if-HV-mode-is-set-when-running-und.patch b/target-ppc-Assert-if-HV-mode-is-set-when-running-und.patch new file mode 100644 index 0000000000000000000000000000000000000000..ff2971fd26e70086b14dd0973d82ea627b08c6e1 --- /dev/null +++ b/target-ppc-Assert-if-HV-mode-is-set-when-running-und.patch @@ -0,0 +1,33 @@ +From beae5e9dc6eedc7d7fda333a3b71aa9f7e6b4a3f Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= +Date: Mon, 30 Mar 2020 11:49:42 +0200 +Subject: [PATCH 302/709] target/ppc: Assert if HV mode is set when running + under a pseries machine +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Suraj Jitindar Singh +Signed-off-by: Cédric Le Goater +Message-Id: <20200330094946.24678-4-clg@kaod.org> +Reviewed-by: Greg Kurz +Signed-off-by: David Gibson +--- + target/ppc/mmu-radix64.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/target/ppc/mmu-radix64.c b/target/ppc/mmu-radix64.c +index f6007e9565..d2422d1c54 100644 +--- a/target/ppc/mmu-radix64.c ++++ b/target/ppc/mmu-radix64.c +@@ -231,6 +231,7 @@ int ppc_radix64_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr, int rwx, + ppc_v3_pate_t pate; + bool relocation; + ++ assert(!(msr_hv && cpu->vhyp)); + assert((rwx == 0) || (rwx == 1) || (rwx == 2)); + + relocation = ((rwx == 2) && (msr_ir == 1)) || ((rwx != 2) && (msr_dr == 1)); +-- +2.23.0 + diff --git a/target-ppc-Enforce-that-the-root-page-directory-size.patch b/target-ppc-Enforce-that-the-root-page-directory-size.patch new file mode 100644 index 0000000000000000000000000000000000000000..d95ccb5c5dfce1392891526f67f962312a3f7493 --- /dev/null +++ b/target-ppc-Enforce-that-the-root-page-directory-size.patch @@ -0,0 +1,42 @@ +From 933abb9c238726c3f2862affd0d46b043a22c3e0 Mon Sep 17 00:00:00 2001 +From: Suraj Jitindar Singh +Date: Mon, 30 Mar 2020 11:49:40 +0200 +Subject: [PATCH 300/709] target/ppc: Enforce that the root page directory size + must be at least 5 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +According to the ISA the root page directory size of a radix tree for +either process- or partition-scoped translation must be >= 5. + +Thus add this to the list of conditions checked when validating the +partition table entry in validate_pate(); + +Signed-off-by: Suraj Jitindar Singh +Reviewed-by: David Gibson +Signed-off-by: Cédric Le Goater +Message-Id: <20200330094946.24678-2-clg@kaod.org> +Reviewed-by: Greg Kurz +Signed-off-by: David Gibson +--- + target/ppc/mmu-radix64.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/target/ppc/mmu-radix64.c b/target/ppc/mmu-radix64.c +index 224e646c50..9967857058 100644 +--- a/target/ppc/mmu-radix64.c ++++ b/target/ppc/mmu-radix64.c +@@ -212,6 +212,9 @@ static bool validate_pate(PowerPCCPU *cpu, uint64_t lpid, ppc_v3_pate_t *pate) + if (lpid == 0 && !msr_hv) { + return false; + } ++ if ((pate->dw0 & PATE1_R_PRTS) < 5) { ++ return false; ++ } + /* More checks ... */ + return true; + } +-- +2.23.0 + diff --git a/target-ppc-Extend-ppc_radix64_check_prot-with-a-part.patch b/target-ppc-Extend-ppc_radix64_check_prot-with-a-part.patch new file mode 100644 index 0000000000000000000000000000000000000000..3674cf6b2fc3148f4a705b9d0326abb98c6faa95 --- /dev/null +++ b/target-ppc-Extend-ppc_radix64_check_prot-with-a-part.patch @@ -0,0 +1,61 @@ +From 522ad21875ac48426c282ef2b7dfe87adb40afb4 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= +Date: Fri, 3 Apr 2020 16:00:54 +0200 +Subject: [PATCH 305/709] target/ppc: Extend ppc_radix64_check_prot() with a + 'partition_scoped' bool +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This prepares ground for partition-scoped Radix translation. + +Signed-off-by: Suraj Jitindar Singh +Signed-off-by: Cédric Le Goater +Reviewed-by: Greg Kurz +Message-Id: <20200403140056.59465-3-clg@kaod.org> +Signed-off-by: David Gibson +--- + target/ppc/mmu-radix64.c | 11 ++++++----- + 1 file changed, 6 insertions(+), 5 deletions(-) + +diff --git a/target/ppc/mmu-radix64.c b/target/ppc/mmu-radix64.c +index 4b0d0ff50a..11b3c6d48c 100644 +--- a/target/ppc/mmu-radix64.c ++++ b/target/ppc/mmu-radix64.c +@@ -105,7 +105,8 @@ static void ppc_radix64_raise_si(PowerPCCPU *cpu, int rwx, vaddr eaddr, + + + static bool ppc_radix64_check_prot(PowerPCCPU *cpu, int rwx, uint64_t pte, +- int *fault_cause, int *prot) ++ int *fault_cause, int *prot, ++ bool partition_scoped) + { + CPUPPCState *env = &cpu->env; + const int need_prot[] = { PAGE_READ, PAGE_WRITE, PAGE_EXEC }; +@@ -121,11 +122,11 @@ static bool ppc_radix64_check_prot(PowerPCCPU *cpu, int rwx, uint64_t pte, + } + + /* Determine permissions allowed by Encoded Access Authority */ +- if ((pte & R_PTE_EAA_PRIV) && msr_pr) { /* Insufficient Privilege */ ++ if (!partition_scoped && (pte & R_PTE_EAA_PRIV) && msr_pr) { + *prot = 0; +- } else if (msr_pr || (pte & R_PTE_EAA_PRIV)) { ++ } else if (msr_pr || (pte & R_PTE_EAA_PRIV) || partition_scoped) { + *prot = ppc_radix64_get_prot_eaa(pte); +- } else { /* !msr_pr && !(pte & R_PTE_EAA_PRIV) */ ++ } else { /* !msr_pr && !(pte & R_PTE_EAA_PRIV) && !partition_scoped */ + *prot = ppc_radix64_get_prot_eaa(pte); + *prot &= ppc_radix64_get_prot_amr(cpu); /* Least combined permissions */ + } +@@ -250,7 +251,7 @@ static int ppc_radix64_process_scoped_xlate(PowerPCCPU *cpu, int rwx, + g_raddr, g_page_size, &fault_cause, &pte_addr); + + if (!(pte & R_PTE_VALID) || +- ppc_radix64_check_prot(cpu, rwx, pte, &fault_cause, g_prot)) { ++ ppc_radix64_check_prot(cpu, rwx, pte, &fault_cause, g_prot, false)) { + /* No valid pte or access denied due to protection */ + if (cause_excp) { + ppc_radix64_raise_si(cpu, rwx, eaddr, fault_cause); +-- +2.23.0 + diff --git a/target-ppc-Improve-syscall-exception-logging.patch b/target-ppc-Improve-syscall-exception-logging.patch new file mode 100644 index 0000000000000000000000000000000000000000..20b1379619b9c5c6a156056c20ca051c254e308a --- /dev/null +++ b/target-ppc-Improve-syscall-exception-logging.patch @@ -0,0 +1,74 @@ +From 6dc6b557913f29e012880e381c0a3f452b415f1d Mon Sep 17 00:00:00 2001 +From: Nicholas Piggin +Date: Tue, 17 Mar 2020 15:49:17 +1000 +Subject: [PATCH 293/709] target/ppc: Improve syscall exception logging + +system calls (at least in Linux) use registers r3-r8 for inputs, so +include those registers in the dump. + +This also adds a mode for PAPR hcalls, which have a different calling +convention. + +Signed-off-by: Nicholas Piggin +Message-Id: <20200317054918.199161-1-npiggin@gmail.com> +Signed-off-by: David Gibson +--- + target/ppc/excp_helper.c | 30 ++++++++++++++++++++++++++---- + 1 file changed, 26 insertions(+), 4 deletions(-) + +diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c +index 08bc885ca6..81ee19ebae 100644 +--- a/target/ppc/excp_helper.c ++++ b/target/ppc/excp_helper.c +@@ -57,12 +57,29 @@ static void ppc_hw_interrupt(CPUPPCState *env) + #else /* defined(CONFIG_USER_ONLY) */ + static inline void dump_syscall(CPUPPCState *env) + { +- qemu_log_mask(CPU_LOG_INT, "syscall r0=%016" PRIx64 " r3=%016" PRIx64 +- " r4=%016" PRIx64 " r5=%016" PRIx64 " r6=%016" PRIx64 ++ qemu_log_mask(CPU_LOG_INT, "syscall r0=%016" PRIx64 ++ " r3=%016" PRIx64 " r4=%016" PRIx64 " r5=%016" PRIx64 ++ " r6=%016" PRIx64 " r7=%016" PRIx64 " r8=%016" PRIx64 + " nip=" TARGET_FMT_lx "\n", + ppc_dump_gpr(env, 0), ppc_dump_gpr(env, 3), + ppc_dump_gpr(env, 4), ppc_dump_gpr(env, 5), +- ppc_dump_gpr(env, 6), env->nip); ++ ppc_dump_gpr(env, 6), ppc_dump_gpr(env, 7), ++ ppc_dump_gpr(env, 8), env->nip); ++} ++ ++static inline void dump_hcall(CPUPPCState *env) ++{ ++ qemu_log_mask(CPU_LOG_INT, "hypercall r3=%016" PRIx64 ++ " r4=%016" PRIx64 " r5=%016" PRIx64 " r6=%016" PRIx64 ++ " r7=%016" PRIx64 " r8=%016" PRIx64 " r9=%016" PRIx64 ++ " r10=%016" PRIx64 " r11=%016" PRIx64 " r12=%016" PRIx64 ++ " nip=" TARGET_FMT_lx "\n", ++ ppc_dump_gpr(env, 3), ppc_dump_gpr(env, 4), ++ ppc_dump_gpr(env, 5), ppc_dump_gpr(env, 6), ++ ppc_dump_gpr(env, 7), ppc_dump_gpr(env, 8), ++ ppc_dump_gpr(env, 9), ppc_dump_gpr(env, 10), ++ ppc_dump_gpr(env, 11), ppc_dump_gpr(env, 12), ++ env->nip); + } + + static int powerpc_reset_wakeup(CPUState *cs, CPUPPCState *env, int excp, +@@ -379,9 +396,14 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp) + } + break; + case POWERPC_EXCP_SYSCALL: /* System call exception */ +- dump_syscall(env); + lev = env->error_code; + ++ if ((lev == 1) && cpu->vhyp) { ++ dump_hcall(env); ++ } else { ++ dump_syscall(env); ++ } ++ + /* + * We need to correct the NIP which in this case is supposed + * to point to the next instruction +-- +2.23.0 + diff --git a/target-ppc-Introduce-a-relocation-bool-in-ppc_radix6.patch b/target-ppc-Introduce-a-relocation-bool-in-ppc_radix6.patch new file mode 100644 index 0000000000000000000000000000000000000000..f72ebd52da4d0995534205459220468a32578316 --- /dev/null +++ b/target-ppc-Introduce-a-relocation-bool-in-ppc_radix6.patch @@ -0,0 +1,44 @@ +From f208ec7160145a77647af9b01a393615e7a9f8c6 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= +Date: Mon, 30 Mar 2020 11:49:41 +0200 +Subject: [PATCH 301/709] target/ppc: Introduce a relocation bool in + ppc_radix64_handle_mmu_fault() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +It will ease the introduction of new routines for partition-scoped +Radix translation. + +Signed-off-by: Suraj Jitindar Singh +Signed-off-by: Cédric Le Goater +Message-Id: <20200330094946.24678-3-clg@kaod.org> +Reviewed-by: Greg Kurz +Signed-off-by: David Gibson +--- + target/ppc/mmu-radix64.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/target/ppc/mmu-radix64.c b/target/ppc/mmu-radix64.c +index 9967857058..f6007e9565 100644 +--- a/target/ppc/mmu-radix64.c ++++ b/target/ppc/mmu-radix64.c +@@ -229,12 +229,13 @@ int ppc_radix64_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr, int rwx, + uint64_t lpid = 0, pid = 0, offset, size, prtbe0, pte; + int page_size, prot, fault_cause = 0; + ppc_v3_pate_t pate; ++ bool relocation; + + assert((rwx == 0) || (rwx == 1) || (rwx == 2)); + ++ relocation = ((rwx == 2) && (msr_ir == 1)) || ((rwx != 2) && (msr_dr == 1)); + /* HV or virtual hypervisor Real Mode Access */ +- if ((msr_hv || cpu->vhyp) && +- (((rwx == 2) && (msr_ir == 0)) || ((rwx != 2) && (msr_dr == 0)))) { ++ if (!relocation && (msr_hv || cpu->vhyp)) { + /* In real mode top 4 effective addr bits (mostly) ignored */ + raddr = eaddr & 0x0FFFFFFFFFFFFFFFULL; + +-- +2.23.0 + diff --git a/target-ppc-Introduce-ppc_radix64_xlate-for-Radix-tre.patch b/target-ppc-Introduce-ppc_radix64_xlate-for-Radix-tre.patch new file mode 100644 index 0000000000000000000000000000000000000000..e13c022c7efdd148c0f62bff0aa4232cea2dccee --- /dev/null +++ b/target-ppc-Introduce-ppc_radix64_xlate-for-Radix-tre.patch @@ -0,0 +1,293 @@ +From d92baf00aad9bba521c2b3cb23fe388c2067aaa0 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= +Date: Fri, 3 Apr 2020 16:00:53 +0200 +Subject: [PATCH 304/709] target/ppc: Introduce ppc_radix64_xlate() for Radix + tree translation +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This is moving code under a new ppc_radix64_xlate() routine shared by +the MMU Radix page fault handler and the 'get_phys_page_debug' PPC +callback. The difference being that 'get_phys_page_debug' does not +generate exceptions. + +The specific part of process-scoped Radix translation is moved under +ppc_radix64_process_scoped_xlate() in preparation of the future support +for partition-scoped Radix translation. Routines raising the exceptions +now take a 'cause_excp' bool to cover the 'get_phys_page_debug' case. + +It should be functionally equivalent. + +Signed-off-by: Suraj Jitindar Singh +Signed-off-by: Cédric Le Goater +Message-Id: <20200403140056.59465-2-clg@kaod.org> +Reviewed-by: Greg Kurz +Signed-off-by: David Gibson +--- + target/ppc/mmu-radix64.c | 219 ++++++++++++++++++++++----------------- + 1 file changed, 123 insertions(+), 96 deletions(-) + +diff --git a/target/ppc/mmu-radix64.c b/target/ppc/mmu-radix64.c +index d2422d1c54..4b0d0ff50a 100644 +--- a/target/ppc/mmu-radix64.c ++++ b/target/ppc/mmu-radix64.c +@@ -219,17 +219,127 @@ static bool validate_pate(PowerPCCPU *cpu, uint64_t lpid, ppc_v3_pate_t *pate) + return true; + } + ++static int ppc_radix64_process_scoped_xlate(PowerPCCPU *cpu, int rwx, ++ vaddr eaddr, uint64_t pid, ++ ppc_v3_pate_t pate, hwaddr *g_raddr, ++ int *g_prot, int *g_page_size, ++ bool cause_excp) ++{ ++ CPUState *cs = CPU(cpu); ++ uint64_t offset, size, prtbe_addr, prtbe0, pte; ++ int fault_cause = 0; ++ hwaddr pte_addr; ++ ++ /* Index Process Table by PID to Find Corresponding Process Table Entry */ ++ offset = pid * sizeof(struct prtb_entry); ++ size = 1ULL << ((pate.dw1 & PATE1_R_PRTS) + 12); ++ if (offset >= size) { ++ /* offset exceeds size of the process table */ ++ if (cause_excp) { ++ ppc_radix64_raise_si(cpu, rwx, eaddr, DSISR_NOPTE); ++ } ++ return 1; ++ } ++ prtbe_addr = (pate.dw1 & PATE1_R_PRTB) + offset; ++ prtbe0 = ldq_phys(cs->as, prtbe_addr); ++ ++ /* Walk Radix Tree from Process Table Entry to Convert EA to RA */ ++ *g_page_size = PRTBE_R_GET_RTS(prtbe0); ++ pte = ppc_radix64_walk_tree(cpu, eaddr & R_EADDR_MASK, ++ prtbe0 & PRTBE_R_RPDB, prtbe0 & PRTBE_R_RPDS, ++ g_raddr, g_page_size, &fault_cause, &pte_addr); ++ ++ if (!(pte & R_PTE_VALID) || ++ ppc_radix64_check_prot(cpu, rwx, pte, &fault_cause, g_prot)) { ++ /* No valid pte or access denied due to protection */ ++ if (cause_excp) { ++ ppc_radix64_raise_si(cpu, rwx, eaddr, fault_cause); ++ } ++ return 1; ++ } ++ ++ ppc_radix64_set_rc(cpu, rwx, pte, pte_addr, g_prot); ++ ++ return 0; ++} ++ ++static int ppc_radix64_xlate(PowerPCCPU *cpu, vaddr eaddr, int rwx, ++ bool relocation, ++ hwaddr *raddr, int *psizep, int *protp, ++ bool cause_excp) ++{ ++ uint64_t lpid = 0, pid = 0; ++ ppc_v3_pate_t pate; ++ int psize, prot; ++ hwaddr g_raddr; ++ ++ /* Virtual Mode Access - get the fully qualified address */ ++ if (!ppc_radix64_get_fully_qualified_addr(&cpu->env, eaddr, &lpid, &pid)) { ++ if (cause_excp) { ++ ppc_radix64_raise_segi(cpu, rwx, eaddr); ++ } ++ return 1; ++ } ++ ++ /* Get Process Table */ ++ if (cpu->vhyp) { ++ PPCVirtualHypervisorClass *vhc; ++ vhc = PPC_VIRTUAL_HYPERVISOR_GET_CLASS(cpu->vhyp); ++ vhc->get_pate(cpu->vhyp, &pate); ++ } else { ++ if (!ppc64_v3_get_pate(cpu, lpid, &pate)) { ++ if (cause_excp) { ++ ppc_radix64_raise_si(cpu, rwx, eaddr, DSISR_NOPTE); ++ } ++ return 1; ++ } ++ if (!validate_pate(cpu, lpid, &pate)) { ++ if (cause_excp) { ++ ppc_radix64_raise_si(cpu, rwx, eaddr, DSISR_R_BADCONFIG); ++ } ++ return 1; ++ } ++ /* We don't support guest mode yet */ ++ if (lpid != 0) { ++ error_report("PowerNV guest support Unimplemented"); ++ exit(1); ++ } ++ } ++ ++ *psizep = INT_MAX; ++ *protp = PAGE_READ | PAGE_WRITE | PAGE_EXEC; ++ ++ /* ++ * Perform process-scoped translation if relocation enabled. ++ * ++ * - Translates an effective address to a host real address in ++ * quadrants 0 and 3 when HV=1. ++ */ ++ if (relocation) { ++ int ret = ppc_radix64_process_scoped_xlate(cpu, rwx, eaddr, pid, ++ pate, &g_raddr, &prot, ++ &psize, cause_excp); ++ if (ret) { ++ return ret; ++ } ++ *psizep = MIN(*psizep, psize); ++ *protp &= prot; ++ } else { ++ g_raddr = eaddr & R_EADDR_MASK; ++ } ++ ++ *raddr = g_raddr; ++ return 0; ++} ++ + int ppc_radix64_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr, int rwx, + int mmu_idx) + { + CPUState *cs = CPU(cpu); + CPUPPCState *env = &cpu->env; +- PPCVirtualHypervisorClass *vhc; +- hwaddr raddr, pte_addr; +- uint64_t lpid = 0, pid = 0, offset, size, prtbe0, pte; +- int page_size, prot, fault_cause = 0; +- ppc_v3_pate_t pate; ++ int page_size, prot; + bool relocation; ++ hwaddr raddr; + + assert(!(msr_hv && cpu->vhyp)); + assert((rwx == 0) || (rwx == 1) || (rwx == 2)); +@@ -262,55 +372,12 @@ int ppc_radix64_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr, int rwx, + TARGET_FMT_lx "\n", env->spr[SPR_LPCR]); + } + +- /* Virtual Mode Access - get the fully qualified address */ +- if (!ppc_radix64_get_fully_qualified_addr(env, eaddr, &lpid, &pid)) { +- ppc_radix64_raise_segi(cpu, rwx, eaddr); ++ /* Translate eaddr to raddr (where raddr is addr qemu needs for access) */ ++ if (ppc_radix64_xlate(cpu, eaddr, rwx, relocation, &raddr, ++ &page_size, &prot, true)) { + return 1; + } + +- /* Get Process Table */ +- if (cpu->vhyp) { +- vhc = PPC_VIRTUAL_HYPERVISOR_GET_CLASS(cpu->vhyp); +- vhc->get_pate(cpu->vhyp, &pate); +- } else { +- if (!ppc64_v3_get_pate(cpu, lpid, &pate)) { +- ppc_radix64_raise_si(cpu, rwx, eaddr, DSISR_NOPTE); +- return 1; +- } +- if (!validate_pate(cpu, lpid, &pate)) { +- ppc_radix64_raise_si(cpu, rwx, eaddr, DSISR_R_BADCONFIG); +- } +- /* We don't support guest mode yet */ +- if (lpid != 0) { +- error_report("PowerNV guest support Unimplemented"); +- exit(1); +- } +- } +- +- /* Index Process Table by PID to Find Corresponding Process Table Entry */ +- offset = pid * sizeof(struct prtb_entry); +- size = 1ULL << ((pate.dw1 & PATE1_R_PRTS) + 12); +- if (offset >= size) { +- /* offset exceeds size of the process table */ +- ppc_radix64_raise_si(cpu, rwx, eaddr, DSISR_NOPTE); +- return 1; +- } +- prtbe0 = ldq_phys(cs->as, (pate.dw1 & PATE1_R_PRTB) + offset); +- +- /* Walk Radix Tree from Process Table Entry to Convert EA to RA */ +- page_size = PRTBE_R_GET_RTS(prtbe0); +- pte = ppc_radix64_walk_tree(cpu, eaddr & R_EADDR_MASK, +- prtbe0 & PRTBE_R_RPDB, prtbe0 & PRTBE_R_RPDS, +- &raddr, &page_size, &fault_cause, &pte_addr); +- if (!pte || ppc_radix64_check_prot(cpu, rwx, pte, &fault_cause, &prot)) { +- /* Couldn't get pte or access denied due to protection */ +- ppc_radix64_raise_si(cpu, rwx, eaddr, fault_cause); +- return 1; +- } +- +- /* Update Reference and Change Bits */ +- ppc_radix64_set_rc(cpu, rwx, pte, pte_addr, &prot); +- + tlb_set_page(cs, eaddr & TARGET_PAGE_MASK, raddr & TARGET_PAGE_MASK, + prot, mmu_idx, 1UL << page_size); + return 0; +@@ -318,58 +385,18 @@ int ppc_radix64_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr, int rwx, + + hwaddr ppc_radix64_get_phys_page_debug(PowerPCCPU *cpu, target_ulong eaddr) + { +- CPUState *cs = CPU(cpu); + CPUPPCState *env = &cpu->env; +- PPCVirtualHypervisorClass *vhc; +- hwaddr raddr, pte_addr; +- uint64_t lpid = 0, pid = 0, offset, size, prtbe0, pte; +- int page_size, fault_cause = 0; +- ppc_v3_pate_t pate; ++ int psize, prot; ++ hwaddr raddr; + + /* Handle Real Mode */ +- if (msr_dr == 0) { ++ if ((msr_dr == 0) && (msr_hv || cpu->vhyp)) { + /* In real mode top 4 effective addr bits (mostly) ignored */ + return eaddr & 0x0FFFFFFFFFFFFFFFULL; + } + +- /* Virtual Mode Access - get the fully qualified address */ +- if (!ppc_radix64_get_fully_qualified_addr(env, eaddr, &lpid, &pid)) { +- return -1; +- } +- +- /* Get Process Table */ +- if (cpu->vhyp) { +- vhc = PPC_VIRTUAL_HYPERVISOR_GET_CLASS(cpu->vhyp); +- vhc->get_pate(cpu->vhyp, &pate); +- } else { +- if (!ppc64_v3_get_pate(cpu, lpid, &pate)) { +- return -1; +- } +- if (!validate_pate(cpu, lpid, &pate)) { +- return -1; +- } +- /* We don't support guest mode yet */ +- if (lpid != 0) { +- error_report("PowerNV guest support Unimplemented"); +- exit(1); +- } +- } +- +- /* Index Process Table by PID to Find Corresponding Process Table Entry */ +- offset = pid * sizeof(struct prtb_entry); +- size = 1ULL << ((pate.dw1 & PATE1_R_PRTS) + 12); +- if (offset >= size) { +- /* offset exceeds size of the process table */ +- return -1; +- } +- prtbe0 = ldq_phys(cs->as, (pate.dw1 & PATE1_R_PRTB) + offset); +- +- /* Walk Radix Tree from Process Table Entry to Convert EA to RA */ +- page_size = PRTBE_R_GET_RTS(prtbe0); +- pte = ppc_radix64_walk_tree(cpu, eaddr & R_EADDR_MASK, +- prtbe0 & PRTBE_R_RPDB, prtbe0 & PRTBE_R_RPDS, +- &raddr, &page_size, &fault_cause, &pte_addr); +- if (!pte) { ++ if (ppc_radix64_xlate(cpu, eaddr, 0, msr_dr, &raddr, &psize, ++ &prot, false)) { + return -1; + } + +-- +2.23.0 + diff --git a/target-ppc-Rework-ppc_radix64_walk_tree-for-partitio.patch b/target-ppc-Rework-ppc_radix64_walk_tree-for-partitio.patch new file mode 100644 index 0000000000000000000000000000000000000000..e37122e4c2989d42280149b47752f20cc68033aa --- /dev/null +++ b/target-ppc-Rework-ppc_radix64_walk_tree-for-partitio.patch @@ -0,0 +1,151 @@ +From 6bffd48b9e8efcd6977c86f2ea8437771d15043c Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= +Date: Fri, 3 Apr 2020 16:00:55 +0200 +Subject: [PATCH 306/709] target/ppc: Rework ppc_radix64_walk_tree() for + partition-scoped translation +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The ppc_radix64_walk_tree() routine walks through the nested radix +tables to look for a PTE. + +Split it in two and introduce a new routine ppc_radix64_next_level() +which we will use for partition-scoped Radix translation when +translating the process tree addresses. The prototypes are slightly +change to use a 'AddressSpace *' parameter, instead of a 'PowerPCCPU *' +which is not required, and to return an error code instead of a PTE +value. It clarifies error handling in the callers. + +Signed-off-by: Suraj Jitindar Singh +Signed-off-by: Greg Kurz +Signed-off-by: Cédric Le Goater +Message-Id: <20200403140056.59465-4-clg@kaod.org> +Signed-off-by: David Gibson +--- + target/ppc/mmu-radix64.c | 79 ++++++++++++++++++++++++++-------------- + 1 file changed, 52 insertions(+), 27 deletions(-) + +diff --git a/target/ppc/mmu-radix64.c b/target/ppc/mmu-radix64.c +index 11b3c6d48c..2400da41e0 100644 +--- a/target/ppc/mmu-radix64.c ++++ b/target/ppc/mmu-radix64.c +@@ -163,44 +163,67 @@ static void ppc_radix64_set_rc(PowerPCCPU *cpu, int rwx, uint64_t pte, + } + } + +-static uint64_t ppc_radix64_walk_tree(PowerPCCPU *cpu, vaddr eaddr, +- uint64_t base_addr, uint64_t nls, +- hwaddr *raddr, int *psize, +- int *fault_cause, hwaddr *pte_addr) ++static int ppc_radix64_next_level(AddressSpace *as, vaddr eaddr, ++ uint64_t *pte_addr, uint64_t *nls, ++ int *psize, uint64_t *pte, int *fault_cause) + { +- CPUState *cs = CPU(cpu); + uint64_t index, pde; + +- if (nls < 5) { /* Directory maps less than 2**5 entries */ ++ if (*nls < 5) { /* Directory maps less than 2**5 entries */ + *fault_cause |= DSISR_R_BADCONFIG; +- return 0; ++ return 1; + } + + /* Read page entry from guest address space */ +- index = eaddr >> (*psize - nls); /* Shift */ +- index &= ((1UL << nls) - 1); /* Mask */ +- pde = ldq_phys(cs->as, base_addr + (index * sizeof(pde))); +- if (!(pde & R_PTE_VALID)) { /* Invalid Entry */ ++ pde = ldq_phys(as, *pte_addr); ++ if (!(pde & R_PTE_VALID)) { /* Invalid Entry */ + *fault_cause |= DSISR_NOPTE; +- return 0; ++ return 1; + } + +- *psize -= nls; ++ *pte = pde; ++ *psize -= *nls; ++ if (!(pde & R_PTE_LEAF)) { /* Prepare for next iteration */ ++ *nls = pde & R_PDE_NLS; ++ index = eaddr >> (*psize - *nls); /* Shift */ ++ index &= ((1UL << *nls) - 1); /* Mask */ ++ *pte_addr = (pde & R_PDE_NLB) + (index * sizeof(pde)); ++ } ++ return 0; ++} + +- /* Check if Leaf Entry -> Page Table Entry -> Stop the Search */ +- if (pde & R_PTE_LEAF) { +- uint64_t rpn = pde & R_PTE_RPN; +- uint64_t mask = (1UL << *psize) - 1; ++static int ppc_radix64_walk_tree(AddressSpace *as, vaddr eaddr, ++ uint64_t base_addr, uint64_t nls, ++ hwaddr *raddr, int *psize, uint64_t *pte, ++ int *fault_cause, hwaddr *pte_addr) ++{ ++ uint64_t index, pde, rpn , mask; + +- /* Or high bits of rpn and low bits to ea to form whole real addr */ +- *raddr = (rpn & ~mask) | (eaddr & mask); +- *pte_addr = base_addr + (index * sizeof(pde)); +- return pde; ++ if (nls < 5) { /* Directory maps less than 2**5 entries */ ++ *fault_cause |= DSISR_R_BADCONFIG; ++ return 1; + } + +- /* Next Level of Radix Tree */ +- return ppc_radix64_walk_tree(cpu, eaddr, pde & R_PDE_NLB, pde & R_PDE_NLS, +- raddr, psize, fault_cause, pte_addr); ++ index = eaddr >> (*psize - nls); /* Shift */ ++ index &= ((1UL << nls) - 1); /* Mask */ ++ *pte_addr = base_addr + (index * sizeof(pde)); ++ do { ++ int ret; ++ ++ ret = ppc_radix64_next_level(as, eaddr, pte_addr, &nls, psize, &pde, ++ fault_cause); ++ if (ret) { ++ return ret; ++ } ++ } while (!(pde & R_PTE_LEAF)); ++ ++ *pte = pde; ++ rpn = pde & R_PTE_RPN; ++ mask = (1UL << *psize) - 1; ++ ++ /* Or high bits of rpn and low bits to ea to form whole real addr */ ++ *raddr = (rpn & ~mask) | (eaddr & mask); ++ return 0; + } + + static bool validate_pate(PowerPCCPU *cpu, uint64_t lpid, ppc_v3_pate_t *pate) +@@ -230,6 +253,7 @@ static int ppc_radix64_process_scoped_xlate(PowerPCCPU *cpu, int rwx, + uint64_t offset, size, prtbe_addr, prtbe0, pte; + int fault_cause = 0; + hwaddr pte_addr; ++ int ret; + + /* Index Process Table by PID to Find Corresponding Process Table Entry */ + offset = pid * sizeof(struct prtb_entry); +@@ -246,11 +270,12 @@ static int ppc_radix64_process_scoped_xlate(PowerPCCPU *cpu, int rwx, + + /* Walk Radix Tree from Process Table Entry to Convert EA to RA */ + *g_page_size = PRTBE_R_GET_RTS(prtbe0); +- pte = ppc_radix64_walk_tree(cpu, eaddr & R_EADDR_MASK, ++ ret = ppc_radix64_walk_tree(cs->as, eaddr & R_EADDR_MASK, + prtbe0 & PRTBE_R_RPDB, prtbe0 & PRTBE_R_RPDS, +- g_raddr, g_page_size, &fault_cause, &pte_addr); ++ g_raddr, g_page_size, &pte, &fault_cause, ++ &pte_addr); + +- if (!(pte & R_PTE_VALID) || ++ if (ret || + ppc_radix64_check_prot(cpu, rwx, pte, &fault_cause, g_prot, false)) { + /* No valid pte or access denied due to protection */ + if (cause_excp) { +-- +2.23.0 + diff --git a/target-ppc-Use-tcg_gen_gvec_dup_imm.patch b/target-ppc-Use-tcg_gen_gvec_dup_imm.patch new file mode 100644 index 0000000000000000000000000000000000000000..1a9df66ccbcd302a5a4b79bc349d9aacc6671953 --- /dev/null +++ b/target-ppc-Use-tcg_gen_gvec_dup_imm.patch @@ -0,0 +1,82 @@ +From 36af59d062768d8f86c30801c4192cb4e36034b8 Mon Sep 17 00:00:00 2001 +From: Richard Henderson +Date: Sat, 28 Mar 2020 14:58:36 -0700 +Subject: [PATCH 285/709] target/ppc: Use tcg_gen_gvec_dup_imm + +We can now unify the implementation of the 3 VSPLTI instructions. + +Acked-by: David Gibson +Signed-off-by: Richard Henderson +--- + target/ppc/translate/vmx-impl.inc.c | 32 ++++++++++++++++------------- + target/ppc/translate/vsx-impl.inc.c | 2 +- + 2 files changed, 19 insertions(+), 15 deletions(-) + +diff --git a/target/ppc/translate/vmx-impl.inc.c b/target/ppc/translate/vmx-impl.inc.c +index 81d5a7a341..403ed3a01c 100644 +--- a/target/ppc/translate/vmx-impl.inc.c ++++ b/target/ppc/translate/vmx-impl.inc.c +@@ -1035,21 +1035,25 @@ GEN_VXRFORM_DUAL(vcmpbfp, PPC_ALTIVEC, PPC_NONE, \ + GEN_VXRFORM_DUAL(vcmpgtfp, PPC_ALTIVEC, PPC_NONE, \ + vcmpgtud, PPC_NONE, PPC2_ALTIVEC_207) + +-#define GEN_VXFORM_DUPI(name, tcg_op, opc2, opc3) \ +-static void glue(gen_, name)(DisasContext *ctx) \ +- { \ +- int simm; \ +- if (unlikely(!ctx->altivec_enabled)) { \ +- gen_exception(ctx, POWERPC_EXCP_VPU); \ +- return; \ +- } \ +- simm = SIMM5(ctx->opcode); \ +- tcg_op(avr_full_offset(rD(ctx->opcode)), 16, 16, simm); \ ++static void gen_vsplti(DisasContext *ctx, int vece) ++{ ++ int simm; ++ ++ if (unlikely(!ctx->altivec_enabled)) { ++ gen_exception(ctx, POWERPC_EXCP_VPU); ++ return; + } + +-GEN_VXFORM_DUPI(vspltisb, tcg_gen_gvec_dup8i, 6, 12); +-GEN_VXFORM_DUPI(vspltish, tcg_gen_gvec_dup16i, 6, 13); +-GEN_VXFORM_DUPI(vspltisw, tcg_gen_gvec_dup32i, 6, 14); ++ simm = SIMM5(ctx->opcode); ++ tcg_gen_gvec_dup_imm(vece, avr_full_offset(rD(ctx->opcode)), 16, 16, simm); ++} ++ ++#define GEN_VXFORM_VSPLTI(name, vece, opc2, opc3) \ ++static void glue(gen_, name)(DisasContext *ctx) { gen_vsplti(ctx, vece); } ++ ++GEN_VXFORM_VSPLTI(vspltisb, MO_8, 6, 12); ++GEN_VXFORM_VSPLTI(vspltish, MO_16, 6, 13); ++GEN_VXFORM_VSPLTI(vspltisw, MO_32, 6, 14); + + #define GEN_VXFORM_NOA(name, opc2, opc3) \ + static void glue(gen_, name)(DisasContext *ctx) \ +@@ -1559,7 +1563,7 @@ GEN_VXFORM_DUAL(vsldoi, PPC_ALTIVEC, PPC_NONE, + #undef GEN_VXRFORM_DUAL + #undef GEN_VXRFORM1 + #undef GEN_VXRFORM +-#undef GEN_VXFORM_DUPI ++#undef GEN_VXFORM_VSPLTI + #undef GEN_VXFORM_NOA + #undef GEN_VXFORM_UIMM + #undef GEN_VAFORM_PAIRED +diff --git a/target/ppc/translate/vsx-impl.inc.c b/target/ppc/translate/vsx-impl.inc.c +index 8287e272f5..b518de46db 100644 +--- a/target/ppc/translate/vsx-impl.inc.c ++++ b/target/ppc/translate/vsx-impl.inc.c +@@ -1579,7 +1579,7 @@ static void gen_xxspltib(DisasContext *ctx) + return; + } + } +- tcg_gen_gvec_dup8i(vsr_full_offset(rt), 16, 16, uim8); ++ tcg_gen_gvec_dup_imm(MO_8, vsr_full_offset(rt), 16, 16, uim8); + } + + static void gen_xxsldwi(DisasContext *ctx) +-- +2.23.0 + diff --git a/target-ppc-fix-rlwimi-rlwinm-rlwnm-for-Clang-9.patch b/target-ppc-fix-rlwimi-rlwinm-rlwnm-for-Clang-9.patch new file mode 100644 index 0000000000000000000000000000000000000000..0e968c7d64c09f622b02be659bc9c53f9124fc7a --- /dev/null +++ b/target-ppc-fix-rlwimi-rlwinm-rlwnm-for-Clang-9.patch @@ -0,0 +1,95 @@ +From c4f6a4a3dd5f2aa15329b8158de25f50b5ba3252 Mon Sep 17 00:00:00 2001 +From: Daniele Buono +Date: Tue, 5 May 2020 14:38:17 -0400 +Subject: [PATCH 310/709] target-ppc: fix rlwimi, rlwinm, rlwnm for Clang-9 + +Starting with Clang v9, -Wtype-limits is implemented and triggers a +few "result of comparison is always true" errors when compiling PPC32 +targets. + +The comparisons seem to be necessary only on PPC64, since the +else branch in PPC32 only has a "g_assert_not_reached();" in all cases. + +This patch restructures the code so that the actual if/else is done on a +local flag variable, that is set accordingly for PPC64, and always +true for PPC32. + +Signed-off-by: Daniele Buono +Message-Id: <20200505183818.32688-2-dbuono@linux.vnet.ibm.com> +Signed-off-by: David Gibson +--- + target/ppc/translate.c | 24 +++++++++++++++++++++--- + 1 file changed, 21 insertions(+), 3 deletions(-) + +diff --git a/target/ppc/translate.c b/target/ppc/translate.c +index 807d14faaa..338529879f 100644 +--- a/target/ppc/translate.c ++++ b/target/ppc/translate.c +@@ -1882,6 +1882,7 @@ static void gen_rlwimi(DisasContext *ctx) + tcg_gen_deposit_tl(t_ra, t_ra, t_rs, sh, me - mb + 1); + } else { + target_ulong mask; ++ bool mask_in_32b = true; + TCGv t1; + + #if defined(TARGET_PPC64) +@@ -1890,8 +1891,13 @@ static void gen_rlwimi(DisasContext *ctx) + #endif + mask = MASK(mb, me); + ++#if defined(TARGET_PPC64) ++ if (mask > 0xffffffffu) { ++ mask_in_32b = false; ++ } ++#endif + t1 = tcg_temp_new(); +- if (mask <= 0xffffffffu) { ++ if (mask_in_32b) { + TCGv_i32 t0 = tcg_temp_new_i32(); + tcg_gen_trunc_tl_i32(t0, t_rs); + tcg_gen_rotli_i32(t0, t0, sh); +@@ -1933,12 +1939,18 @@ static void gen_rlwinm(DisasContext *ctx) + tcg_gen_extract_tl(t_ra, t_rs, rsh, len); + } else { + target_ulong mask; ++ bool mask_in_32b = true; + #if defined(TARGET_PPC64) + mb += 32; + me += 32; + #endif + mask = MASK(mb, me); +- if (mask <= 0xffffffffu) { ++#if defined(TARGET_PPC64) ++ if (mask > 0xffffffffu) { ++ mask_in_32b = false; ++ } ++#endif ++ if (mask_in_32b) { + if (sh == 0) { + tcg_gen_andi_tl(t_ra, t_rs, mask); + } else { +@@ -1973,6 +1985,7 @@ static void gen_rlwnm(DisasContext *ctx) + uint32_t mb = MB(ctx->opcode); + uint32_t me = ME(ctx->opcode); + target_ulong mask; ++ bool mask_in_32b = true; + + #if defined(TARGET_PPC64) + mb += 32; +@@ -1980,7 +1993,12 @@ static void gen_rlwnm(DisasContext *ctx) + #endif + mask = MASK(mb, me); + +- if (mask <= 0xffffffffu) { ++#if defined(TARGET_PPC64) ++ if (mask > 0xffffffffu) { ++ mask_in_32b = false; ++ } ++#endif ++ if (mask_in_32b) { + TCGv_i32 t0 = tcg_temp_new_i32(); + TCGv_i32 t1 = tcg_temp_new_i32(); + tcg_gen_trunc_tl_i32(t0, t_rb); +-- +2.23.0 + diff --git a/target-riscv-Add-a-sifive-e34-cpu-type.patch b/target-riscv-Add-a-sifive-e34-cpu-type.patch new file mode 100644 index 0000000000000000000000000000000000000000..182dc3147a9c17d9c0e802fab2ccda89a7f3d6f0 --- /dev/null +++ b/target-riscv-Add-a-sifive-e34-cpu-type.patch @@ -0,0 +1,62 @@ +From d784733bf1875c1ba355c69739518f24d56f1260 Mon Sep 17 00:00:00 2001 +From: Corey Wharton +Date: Fri, 13 Mar 2020 12:34:29 -0700 +Subject: [PATCH 062/709] target/riscv: Add a sifive-e34 cpu type + +The sifive-e34 cpu type is the same as the sifive-e31 with the +single precision floating-point extension enabled. + +Signed-off-by: Corey Wharton +Reviewed-by: Alistair Francis +Reviewed-by: Bin Meng +Message-id: 20200313193429.8035-3-coreyw7@fb.com +Message-Id: <20200313193429.8035-3-coreyw7@fb.com> +Signed-off-by: Alistair Francis +--- + target/riscv/cpu.c | 10 ++++++++++ + target/riscv/cpu.h | 1 + + 2 files changed, 11 insertions(+) + +diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c +index 4e578239d3..059d71f2c7 100644 +--- a/target/riscv/cpu.c ++++ b/target/riscv/cpu.c +@@ -164,6 +164,15 @@ static void rv32imacu_nommu_cpu_init(Object *obj) + set_feature(env, RISCV_FEATURE_PMP); + } + ++static void rv32imafcu_nommu_cpu_init(Object *obj) ++{ ++ CPURISCVState *env = &RISCV_CPU(obj)->env; ++ set_misa(env, RV32 | RVI | RVM | RVA | RVF | RVC | RVU); ++ set_priv_version(env, PRIV_VERSION_1_10_0); ++ set_resetvec(env, DEFAULT_RSTVEC); ++ set_feature(env, RISCV_FEATURE_PMP); ++} ++ + #elif defined(TARGET_RISCV64) + + static void riscv_base64_cpu_init(Object *obj) +@@ -610,6 +619,7 @@ static const TypeInfo riscv_cpu_type_infos[] = { + #if defined(TARGET_RISCV32) + DEFINE_CPU(TYPE_RISCV_CPU_BASE32, riscv_base32_cpu_init), + DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_E31, rv32imacu_nommu_cpu_init), ++ DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_E34, rv32imafcu_nommu_cpu_init), + DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_U34, rv32gcsu_priv1_10_0_cpu_init), + /* Depreacted */ + DEFINE_CPU(TYPE_RISCV_CPU_RV32IMACU_NOMMU, rv32imacu_nommu_cpu_init), +diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h +index 7d21addbab..d0e7f5b9c5 100644 +--- a/target/riscv/cpu.h ++++ b/target/riscv/cpu.h +@@ -36,6 +36,7 @@ + #define TYPE_RISCV_CPU_BASE32 RISCV_CPU_TYPE_NAME("rv32") + #define TYPE_RISCV_CPU_BASE64 RISCV_CPU_TYPE_NAME("rv64") + #define TYPE_RISCV_CPU_SIFIVE_E31 RISCV_CPU_TYPE_NAME("sifive-e31") ++#define TYPE_RISCV_CPU_SIFIVE_E34 RISCV_CPU_TYPE_NAME("sifive-e34") + #define TYPE_RISCV_CPU_SIFIVE_E51 RISCV_CPU_TYPE_NAME("sifive-e51") + #define TYPE_RISCV_CPU_SIFIVE_U34 RISCV_CPU_TYPE_NAME("sifive-u34") + #define TYPE_RISCV_CPU_SIFIVE_U54 RISCV_CPU_TYPE_NAME("sifive-u54") +-- +2.23.0 + diff --git a/target-riscv-Add-kvm_riscv_get-put_regs_timer.patch b/target-riscv-Add-kvm_riscv_get-put_regs_timer.patch new file mode 100644 index 0000000000000000000000000000000000000000..8b857731139c4d3d1acf2dfcbed01a07a274911b --- /dev/null +++ b/target-riscv-Add-kvm_riscv_get-put_regs_timer.patch @@ -0,0 +1,130 @@ +From f6b13815a56cce828ea6600c5c41b3b14cc53a36 Mon Sep 17 00:00:00 2001 +From: Yifei Jiang +Date: Thu, 27 Aug 2020 10:21:19 +0800 +Subject: [PATCH 707/709] target/riscv: Add kvm_riscv_get/put_regs_timer + +Add kvm_riscv_get/put_regs_timer to synchronize virtual time context +from KVM. The frequency of virtual time is not supported by KVM_SET_ONE_REG, +So it's useless to synchronize the frequency of virtual time. + +To set register of RISCV_TIMER_REG(state) will occur a error from KVM +on kvm_timer_state == 0. It's better to adapt in KVM, but it doesn't matter +that adaping in QEMU. + +Signed-off-by: Yifei Jiang +Signed-off-by: Yipeng Yin +--- + target/riscv/cpu.h | 6 ++++ + target/riscv/kvm.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 78 insertions(+) + +diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h +index 9d2b41466e..315981ea1d 100644 +--- a/target/riscv/cpu.h ++++ b/target/riscv/cpu.h +@@ -211,6 +211,12 @@ struct CPURISCVState { + + hwaddr loader_start; + hwaddr fdt_start; ++ ++ /* kvm timer */ ++ bool kvm_timer_dirty; ++ uint64_t kvm_timer_time; ++ uint64_t kvm_timer_compare; ++ uint64_t kvm_timer_state; + }; + + #define RISCV_CPU_CLASS(klass) \ +diff --git a/target/riscv/kvm.c b/target/riscv/kvm.c +index d0d02aad5c..7466787d79 100644 +--- a/target/riscv/kvm.c ++++ b/target/riscv/kvm.c +@@ -59,6 +59,9 @@ static __u64 kvm_riscv_reg_id(__u64 type, __u64 idx) + #define RISCV_CSR_REG(name) kvm_riscv_reg_id(KVM_REG_RISCV_CSR, \ + KVM_REG_RISCV_CSR_REG(name)) + ++#define RISCV_TIMER_REG(name) kvm_riscv_reg_id(KVM_REG_RISCV_TIMER, \ ++ KVM_REG_RISCV_TIMER_REG(name)) ++ + #define RISCV_FP_F_REG(idx) kvm_riscv_reg_id(KVM_REG_RISCV_FP_F, idx) + + #define RISCV_FP_D_REG(idx) kvm_riscv_reg_id(KVM_REG_RISCV_FP_D, idx) +@@ -294,6 +297,75 @@ static int kvm_riscv_put_regs_fp(CPUState *cs) + return ret; + } + ++static void kvm_riscv_get_regs_timer(CPUState *cs) ++{ ++ int ret; ++ uint64_t reg; ++ CPURISCVState *env = &RISCV_CPU(cs)->env; ++ ++ if (env->kvm_timer_dirty) { ++ return; ++ } ++ ++ ret = kvm_get_one_reg(cs, RISCV_TIMER_REG(time), ®); ++ if (ret) { ++ abort(); ++ } ++ env->kvm_timer_time = reg; ++ ++ ret = kvm_get_one_reg(cs, RISCV_TIMER_REG(compare), ®); ++ if (ret) { ++ abort(); ++ } ++ env->kvm_timer_compare = reg; ++ ++ ret = kvm_get_one_reg(cs, RISCV_TIMER_REG(state), ®); ++ if (ret) { ++ abort(); ++ } ++ env->kvm_timer_state = reg; ++ ++ env->kvm_timer_dirty = true; ++} ++ ++static void kvm_riscv_put_regs_timer(CPUState *cs) ++{ ++ int ret; ++ uint64_t reg; ++ CPURISCVState *env = &RISCV_CPU(cs)->env; ++ ++ if (!env->kvm_timer_dirty) { ++ return; ++ } ++ ++ reg = env->kvm_timer_time; ++ ret = kvm_set_one_reg(cs, RISCV_TIMER_REG(time), ®); ++ if (ret) { ++ abort(); ++ } ++ ++ reg = env->kvm_timer_compare; ++ ret = kvm_set_one_reg(cs, RISCV_TIMER_REG(compare), ®); ++ if (ret) { ++ abort(); ++ } ++ ++ /* ++ * To set register of RISCV_TIMER_REG(state) will occur a error from KVM ++ * on env->kvm_timer_state == 0, It's better to adapt in KVM, but it ++ * doesn't matter that adaping in QEMU now. ++ * TODO If KVM changes, adapt here. ++ */ ++ if (env->kvm_timer_state) { ++ reg = env->kvm_timer_state; ++ ret = kvm_set_one_reg(cs, RISCV_TIMER_REG(state), ®); ++ if (ret) { ++ abort(); ++ } ++ } ++ ++ env->kvm_timer_dirty = false; ++} + + const KVMCapabilityInfo kvm_arch_required_capabilities[] = { + KVM_CAP_LAST_INFO +-- +2.23.0 + diff --git a/target-riscv-Add-sifive_plic-vmstate.patch b/target-riscv-Add-sifive_plic-vmstate.patch new file mode 100644 index 0000000000000000000000000000000000000000..2ba9c987fdc8085f29597fe99ffcca54fcd56d2e --- /dev/null +++ b/target-riscv-Add-sifive_plic-vmstate.patch @@ -0,0 +1,91 @@ +From 886253ae501482148a266a60ae1d9047f8aaded8 Mon Sep 17 00:00:00 2001 +From: Yifei Jiang +Date: Thu, 27 Aug 2020 10:20:50 +0800 +Subject: [PATCH 705/709] target/riscv: Add sifive_plic vmstate + +Add sifive_plic vmstate for supporting sifive_plic migration. +Current vmstate framework only supports one structure parameter +as num field to describe variable length arrays, so introduce +num_enables. + +Signed-off-by: Yifei Jiang +Signed-off-by: Yipeng Yin +--- + hw/riscv/sifive_plic.c | 24 +++++++++++++++++++++++- + include/hw/riscv/sifive_plic.h | 1 + + 2 files changed, 24 insertions(+), 1 deletion(-) + +diff --git a/hw/riscv/sifive_plic.c b/hw/riscv/sifive_plic.c +index be2fb0706e..4ed5fd43bf 100644 +--- a/hw/riscv/sifive_plic.c ++++ b/hw/riscv/sifive_plic.c +@@ -31,6 +31,7 @@ + #include "hw/riscv/sifive_plic.h" + #include "sysemu/kvm.h" + #include "kvm_riscv.h" ++#include "migration/vmstate.h" + + #define RISCV_DEBUG_PLIC 0 + +@@ -452,11 +453,12 @@ static void sifive_plic_realize(DeviceState *dev, Error **errp) + TYPE_SIFIVE_PLIC, plic->aperture_size); + parse_hart_config(plic); + plic->bitfield_words = (plic->num_sources + 31) >> 5; ++ plic->num_enables = plic->bitfield_words * plic->num_addrs; + plic->source_priority = g_new0(uint32_t, plic->num_sources); + plic->target_priority = g_new(uint32_t, plic->num_addrs); + plic->pending = g_new0(uint32_t, plic->bitfield_words); + plic->claimed = g_new0(uint32_t, plic->bitfield_words); +- plic->enable = g_new0(uint32_t, plic->bitfield_words * plic->num_addrs); ++ plic->enable = g_new0(uint32_t, plic->num_enables); + sysbus_init_mmio(SYS_BUS_DEVICE(dev), &plic->mmio); + qdev_init_gpio_in(dev, sifive_plic_irq_request, plic->num_sources); + +@@ -476,12 +478,32 @@ static void sifive_plic_realize(DeviceState *dev, Error **errp) + msi_nonbroken = true; + } + ++static const VMStateDescription vmstate_sifive_plic = { ++ .name = "riscv_sifive_plic", ++ .version_id = 1, ++ .minimum_version_id = 1, ++ .fields = (VMStateField[]) { ++ VMSTATE_VARRAY_UINT32(source_priority, SiFivePLICState, num_sources, 0, ++ vmstate_info_uint32, uint32_t), ++ VMSTATE_VARRAY_UINT32(target_priority, SiFivePLICState, num_addrs, 0, ++ vmstate_info_uint32, uint32_t), ++ VMSTATE_VARRAY_UINT32(pending, SiFivePLICState, bitfield_words, 0, ++ vmstate_info_uint32, uint32_t), ++ VMSTATE_VARRAY_UINT32(claimed, SiFivePLICState, bitfield_words, 0, ++ vmstate_info_uint32, uint32_t), ++ VMSTATE_VARRAY_UINT32(enable, SiFivePLICState, num_enables, 0, ++ vmstate_info_uint32, uint32_t), ++ VMSTATE_END_OF_LIST() ++ } ++}; ++ + static void sifive_plic_class_init(ObjectClass *klass, void *data) + { + DeviceClass *dc = DEVICE_CLASS(klass); + + device_class_set_props(dc, sifive_plic_properties); + dc->realize = sifive_plic_realize; ++ dc->vmsd = &vmstate_sifive_plic; + } + + static const TypeInfo sifive_plic_info = { +diff --git a/include/hw/riscv/sifive_plic.h b/include/hw/riscv/sifive_plic.h +index ace76d0f1b..96a792cd04 100644 +--- a/include/hw/riscv/sifive_plic.h ++++ b/include/hw/riscv/sifive_plic.h +@@ -50,6 +50,7 @@ typedef struct SiFivePLICState { + uint32_t num_addrs; + uint32_t num_harts; + uint32_t bitfield_words; ++ uint32_t num_enables; + PLICAddr *addr_config; + uint32_t *source_priority; + uint32_t *target_priority; +-- +2.23.0 + diff --git a/target-riscv-Add-target-riscv-kvm.c-to-place-the-pub.patch b/target-riscv-Add-target-riscv-kvm.c-to-place-the-pub.patch new file mode 100644 index 0000000000000000000000000000000000000000..19a4d0d4cdefefa6b8765a33d909546e44fe2a71 --- /dev/null +++ b/target-riscv-Add-target-riscv-kvm.c-to-place-the-pub.patch @@ -0,0 +1,178 @@ +From 4266c8e48eec2731f95513abb250dcdf65eb87d9 Mon Sep 17 00:00:00 2001 +From: Yifei Jiang +Date: Mon, 24 Aug 2020 20:09:32 +0800 +Subject: [PATCH 696/709] target/riscv: Add target/riscv/kvm.c to place the + public kvm interface + +Add target/riscv/kvm.c to place kvm_arch_* function needed by kvm/kvm-all.c. +Meanwhile, add kvm support in configure file. + +Signed-off-by: Yifei Jiang +Signed-off-by: Yipeng Yin +--- + configure | 1 + + target/riscv/Makefile.objs | 1 + + target/riscv/kvm.c | 128 +++++++++++++++++++++++++++++++++++++ + 3 files changed, 130 insertions(+) + create mode 100644 target/riscv/kvm.c + +diff --git a/configure b/configure +index b969dee675..10565e588a 100755 +--- a/configure ++++ b/configure +@@ -200,6 +200,7 @@ supported_kvm_target() { + x86_64:i386 | x86_64:x86_64 | x86_64:x32 | \ + mips:mips | mipsel:mips | \ + ppc:ppc | ppc64:ppc | ppc:ppc64 | ppc64:ppc64 | ppc64:ppc64le | \ ++ riscv32:riscv32 | riscv64:riscv64 | \ + s390x:s390x) + return 0 + ;; +diff --git a/target/riscv/Makefile.objs b/target/riscv/Makefile.objs +index ff651f69f6..7ea8f4c3da 100644 +--- a/target/riscv/Makefile.objs ++++ b/target/riscv/Makefile.objs +@@ -1,5 +1,6 @@ + obj-y += translate.o op_helper.o cpu_helper.o cpu.o csr.o fpu_helper.o gdbstub.o + obj-$(CONFIG_SOFTMMU) += pmp.o ++obj-$(CONFIG_KVM) += kvm.o + + ifeq ($(CONFIG_SOFTMMU),y) + obj-y += monitor.o +diff --git a/target/riscv/kvm.c b/target/riscv/kvm.c +new file mode 100644 +index 0000000000..997907dfc9 +--- /dev/null ++++ b/target/riscv/kvm.c +@@ -0,0 +1,128 @@ ++/* ++ * RISC-V implementation of KVM hooks ++ * ++ * Copyright (c) 2020 Huawei Technologies Co., Ltd ++ * ++ * 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 ++ ++#include ++ ++#include "qemu-common.h" ++#include "qemu/timer.h" ++#include "qemu/error-report.h" ++#include "qemu/main-loop.h" ++#include "sysemu/sysemu.h" ++#include "sysemu/kvm.h" ++#include "sysemu/kvm_int.h" ++#include "cpu.h" ++#include "trace.h" ++#include "hw/pci/pci.h" ++#include "exec/memattrs.h" ++#include "exec/address-spaces.h" ++#include "hw/boards.h" ++#include "hw/irq.h" ++#include "qemu/log.h" ++#include "hw/loader.h" ++ ++const KVMCapabilityInfo kvm_arch_required_capabilities[] = { ++ KVM_CAP_LAST_INFO ++}; ++ ++int kvm_arch_get_registers(CPUState *cs) ++{ ++ return 0; ++} ++ ++int kvm_arch_put_registers(CPUState *cs, int level) ++{ ++ return 0; ++} ++ ++int kvm_arch_release_virq_post(int virq) ++{ ++ return 0; ++} ++ ++int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route, ++ uint64_t address, uint32_t data, PCIDevice *dev) ++{ ++ return 0; ++} ++ ++int kvm_arch_destroy_vcpu(CPUState *cs) ++{ ++ return 0; ++} ++ ++unsigned long kvm_arch_vcpu_id(CPUState *cpu) ++{ ++ return cpu->cpu_index; ++} ++ ++void kvm_arch_init_irq_routing(KVMState *s) ++{ ++} ++ ++int kvm_arch_init_vcpu(CPUState *cs) ++{ ++ return 0; ++} ++ ++int kvm_arch_msi_data_to_gsi(uint32_t data) ++{ ++ abort(); ++} ++ ++int kvm_arch_add_msi_route_post(struct kvm_irq_routing_entry *route, ++ int vector, PCIDevice *dev) ++{ ++ return 0; ++} ++ ++int kvm_arch_init(MachineState *ms, KVMState *s) ++{ ++ return 0; ++} ++ ++int kvm_arch_irqchip_create(KVMState *s) ++{ ++ return 0; ++} ++ ++int kvm_arch_process_async_events(CPUState *cs) ++{ ++ return 0; ++} ++ ++void kvm_arch_pre_run(CPUState *cs, struct kvm_run *run) ++{ ++} ++ ++MemTxAttrs kvm_arch_post_run(CPUState *cs, struct kvm_run *run) ++{ ++ return MEMTXATTRS_UNSPECIFIED; ++} ++ ++bool kvm_arch_stop_on_emulation_error(CPUState *cs) ++{ ++ return true; ++} ++ ++int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run) ++{ ++ return 0; ++} +-- +2.23.0 + diff --git a/target-riscv-Allow-generating-hlv-hlvx-hsv-instructi.patch b/target-riscv-Allow-generating-hlv-hlvx-hsv-instructi.patch new file mode 100644 index 0000000000000000000000000000000000000000..a095ebdb9662d9b5972ff7f3a081f168538f6266 --- /dev/null +++ b/target-riscv-Allow-generating-hlv-hlvx-hsv-instructi.patch @@ -0,0 +1,558 @@ +From ac8fd27e09c2cec67738b6ee1ba5f1a225dbc5dc Mon Sep 17 00:00:00 2001 +From: Alistair Francis +Date: Fri, 3 Apr 2020 14:05:36 -0700 +Subject: [PATCH 676/709] target/riscv: Allow generating hlv/hlvx/hsv + instructions + +Signed-off-by: Alistair Francis +--- + target/riscv/cpu_bits.h | 1 + + target/riscv/helper.h | 3 + + target/riscv/insn32-64.decode | 5 + + target/riscv/insn32.decode | 11 + + target/riscv/insn_trans/trans_rvh.inc.c | 340 ++++++++++++++++++++++++ + target/riscv/op_helper.c | 114 ++++++++ + 6 files changed, 474 insertions(+) + +diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h +index f52711ac32..bb4ee3fc35 100644 +--- a/target/riscv/cpu_bits.h ++++ b/target/riscv/cpu_bits.h +@@ -428,6 +428,7 @@ + #define HSTATUS_SP2V 0x00000200 + #define HSTATUS_VTVM 0x00100000 + #define HSTATUS_VTSR 0x00400000 ++#define HSTATUS_HU 0x00000200 + + #define HSTATUS32_WPRI 0xFF8FF87E + #define HSTATUS64_WPRI 0xFFFFFFFFFF8FF87EULL +diff --git a/target/riscv/helper.h b/target/riscv/helper.h +index b36be978d5..d020d1459c 100644 +--- a/target/riscv/helper.h ++++ b/target/riscv/helper.h +@@ -80,4 +80,7 @@ DEF_HELPER_1(tlb_flush, void, env) + /* Hypervisor functions */ + #ifndef CONFIG_USER_ONLY + DEF_HELPER_1(hyp_tlb_flush, void, env) ++DEF_HELPER_4(hyp_load, tl, env, tl, tl, tl) ++DEF_HELPER_5(hyp_store, void, env, tl, tl, tl, tl) ++DEF_HELPER_4(hyp_x_load, tl, env, tl, tl, tl) + #endif +diff --git a/target/riscv/insn32-64.decode b/target/riscv/insn32-64.decode +index 380bf791bc..24feef4e0f 100644 +--- a/target/riscv/insn32-64.decode ++++ b/target/riscv/insn32-64.decode +@@ -70,3 +70,8 @@ fmv_x_d 1110001 00000 ..... 000 ..... 1010011 @r2 + fcvt_d_l 1101001 00010 ..... ... ..... 1010011 @r2_rm + fcvt_d_lu 1101001 00011 ..... ... ..... 1010011 @r2_rm + fmv_d_x 1111001 00000 ..... 000 ..... 1010011 @r2 ++ ++# *** RV32H Base Instruction Set *** ++hlv_wu 0110100 00001 ..... 100 ..... 1110011 @r2 ++hlv_d 0110110 00000 ..... 100 ..... 1110011 @r2 ++hsv_d 0110111 ..... ..... 100 00000 1110011 @r2_s +diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode +index 4c8d1215ce..18bbe08ebb 100644 +--- a/target/riscv/insn32.decode ++++ b/target/riscv/insn32.decode +@@ -62,6 +62,7 @@ + @r_rm ....... ..... ..... ... ..... ....... %rs2 %rs1 %rm %rd + @r2_rm ....... ..... ..... ... ..... ....... %rs1 %rm %rd + @r2 ....... ..... ..... ... ..... ....... %rs1 %rd ++@r2_s ....... ..... ..... ... ..... ....... %rs2 %rs1 + + @hfence_gvma ....... ..... ..... ... ..... ....... %rs2 %rs1 + @hfence_vvma ....... ..... ..... ... ..... ....... %rs2 %rs1 +@@ -207,5 +208,15 @@ fcvt_d_w 1101001 00000 ..... ... ..... 1010011 @r2_rm + fcvt_d_wu 1101001 00001 ..... ... ..... 1010011 @r2_rm + + # *** RV32H Base Instruction Set *** ++hlv_b 0110000 00000 ..... 100 ..... 1110011 @r2 ++hlv_bu 0110000 00001 ..... 100 ..... 1110011 @r2 ++hlv_h 0110010 00000 ..... 100 ..... 1110011 @r2 ++hlv_hu 0110010 00001 ..... 100 ..... 1110011 @r2 ++hlvx_hu 0110010 00011 ..... 100 ..... 1110011 @r2 ++hlv_w 0110100 00000 ..... 100 ..... 1110011 @r2 ++hlvx_wu 0110100 00011 ..... 100 ..... 1110011 @r2 ++hsv_b 0110001 ..... ..... 100 00000 1110011 @r2_s ++hsv_h 0110011 ..... ..... 100 00000 1110011 @r2_s ++hsv_w 0110101 ..... ..... 100 00000 1110011 @r2_s + hfence_gvma 0110001 ..... ..... 000 00000 1110011 @hfence_gvma + hfence_vvma 0010001 ..... ..... 000 00000 1110011 @hfence_vvma +diff --git a/target/riscv/insn_trans/trans_rvh.inc.c b/target/riscv/insn_trans/trans_rvh.inc.c +index 263b652d90..db650ae62a 100644 +--- a/target/riscv/insn_trans/trans_rvh.inc.c ++++ b/target/riscv/insn_trans/trans_rvh.inc.c +@@ -16,6 +16,346 @@ + * this program. If not, see . + */ + ++static bool trans_hlv_b(DisasContext *ctx, arg_hlv_b *a) ++{ ++ REQUIRE_EXT(ctx, RVH); ++#ifndef CONFIG_USER_ONLY ++ TCGv t0 = tcg_temp_new(); ++ TCGv t1 = tcg_temp_new(); ++ TCGv mem_idx = tcg_temp_new(); ++ TCGv memop = tcg_temp_new(); ++ ++ gen_get_gpr(t0, a->rs1); ++ tcg_gen_movi_tl(mem_idx, ctx->mem_idx); ++ tcg_gen_movi_tl(memop, MO_SB); ++ ++ gen_helper_hyp_load(t1, cpu_env, t0, mem_idx, memop); ++ gen_set_gpr(a->rd, t1); ++ ++ tcg_temp_free(t0); ++ tcg_temp_free(t1); ++ tcg_temp_free(mem_idx); ++ tcg_temp_free(memop); ++ return true; ++#else ++ return false; ++#endif ++} ++ ++static bool trans_hlv_h(DisasContext *ctx, arg_hlv_h *a) ++{ ++ REQUIRE_EXT(ctx, RVH); ++#ifndef CONFIG_USER_ONLY ++ TCGv t0 = tcg_temp_new(); ++ TCGv t1 = tcg_temp_new(); ++ TCGv mem_idx = tcg_temp_new(); ++ TCGv memop = tcg_temp_new(); ++ ++ gen_get_gpr(t0, a->rs1); ++ tcg_gen_movi_tl(mem_idx, ctx->mem_idx); ++ tcg_gen_movi_tl(memop, MO_TESW); ++ ++ gen_helper_hyp_load(t1, cpu_env, t0, mem_idx, memop); ++ gen_set_gpr(a->rd, t1); ++ ++ tcg_temp_free(t0); ++ tcg_temp_free(t1); ++ tcg_temp_free(mem_idx); ++ tcg_temp_free(memop); ++ return true; ++#else ++ return false; ++#endif ++} ++ ++static bool trans_hlv_w(DisasContext *ctx, arg_hlv_w *a) ++{ ++ REQUIRE_EXT(ctx, RVH); ++#ifndef CONFIG_USER_ONLY ++ TCGv t0 = tcg_temp_new(); ++ TCGv t1 = tcg_temp_new(); ++ TCGv mem_idx = tcg_temp_new(); ++ TCGv memop = tcg_temp_new(); ++ ++ gen_get_gpr(t0, a->rs1); ++ tcg_gen_movi_tl(mem_idx, ctx->mem_idx); ++ tcg_gen_movi_tl(memop, MO_TESL); ++ ++ gen_helper_hyp_load(t1, cpu_env, t0, mem_idx, memop); ++ gen_set_gpr(a->rd, t1); ++ ++ tcg_temp_free(t0); ++ tcg_temp_free(t1); ++ tcg_temp_free(mem_idx); ++ tcg_temp_free(memop); ++ return true; ++#else ++ return false; ++#endif ++} ++ ++static bool trans_hlv_bu(DisasContext *ctx, arg_hlv_bu *a) ++{ ++ REQUIRE_EXT(ctx, RVH); ++#ifndef CONFIG_USER_ONLY ++ TCGv t0 = tcg_temp_new(); ++ TCGv t1 = tcg_temp_new(); ++ TCGv mem_idx = tcg_temp_new(); ++ TCGv memop = tcg_temp_new(); ++ ++ gen_get_gpr(t0, a->rs1); ++ tcg_gen_movi_tl(mem_idx, ctx->mem_idx); ++ tcg_gen_movi_tl(memop, MO_UB); ++ ++ gen_helper_hyp_load(t1, cpu_env, t0, mem_idx, memop); ++ gen_set_gpr(a->rd, t1); ++ ++ tcg_temp_free(t0); ++ tcg_temp_free(t1); ++ tcg_temp_free(mem_idx); ++ tcg_temp_free(memop); ++ return true; ++#else ++ return false; ++#endif ++} ++ ++static bool trans_hlv_hu(DisasContext *ctx, arg_hlv_hu *a) ++{ ++ REQUIRE_EXT(ctx, RVH); ++#ifndef CONFIG_USER_ONLY ++ TCGv t0 = tcg_temp_new(); ++ TCGv t1 = tcg_temp_new(); ++ TCGv mem_idx = tcg_temp_new(); ++ TCGv memop = tcg_temp_new(); ++ ++ gen_get_gpr(t0, a->rs1); ++ tcg_gen_movi_tl(mem_idx, ctx->mem_idx); ++ tcg_gen_movi_tl(memop, MO_TEUW); ++ ++ gen_helper_hyp_load(t1, cpu_env, t0, mem_idx, memop); ++ gen_set_gpr(a->rd, t1); ++ ++ tcg_temp_free(t0); ++ tcg_temp_free(t1); ++ tcg_temp_free(mem_idx); ++ tcg_temp_free(memop); ++ return true; ++#else ++ return false; ++#endif ++} ++ ++static bool trans_hsv_b(DisasContext *ctx, arg_hsv_b *a) ++{ ++ REQUIRE_EXT(ctx, RVH); ++#ifndef CONFIG_USER_ONLY ++ TCGv t0 = tcg_temp_new(); ++ TCGv dat = tcg_temp_new(); ++ TCGv mem_idx = tcg_temp_new(); ++ TCGv memop = tcg_temp_new(); ++ ++ gen_get_gpr(t0, a->rs1); ++ gen_get_gpr(dat, a->rs2); ++ tcg_gen_movi_tl(mem_idx, ctx->mem_idx); ++ tcg_gen_movi_tl(memop, MO_SB); ++ ++ gen_helper_hyp_store(cpu_env, t0, dat, mem_idx, memop); ++ ++ tcg_temp_free(t0); ++ tcg_temp_free(dat); ++ tcg_temp_free(mem_idx); ++ tcg_temp_free(memop); ++ return true; ++#else ++ return false; ++#endif ++} ++ ++static bool trans_hsv_h(DisasContext *ctx, arg_hsv_h *a) ++{ ++ REQUIRE_EXT(ctx, RVH); ++#ifndef CONFIG_USER_ONLY ++ TCGv t0 = tcg_temp_new(); ++ TCGv dat = tcg_temp_new(); ++ TCGv mem_idx = tcg_temp_new(); ++ TCGv memop = tcg_temp_new(); ++ ++ gen_get_gpr(t0, a->rs1); ++ gen_get_gpr(dat, a->rs2); ++ tcg_gen_movi_tl(mem_idx, ctx->mem_idx); ++ tcg_gen_movi_tl(memop, MO_TESW); ++ ++ gen_helper_hyp_store(cpu_env, t0, dat, mem_idx, memop); ++ ++ tcg_temp_free(t0); ++ tcg_temp_free(dat); ++ tcg_temp_free(mem_idx); ++ tcg_temp_free(memop); ++ return true; ++#else ++ return false; ++#endif ++} ++ ++static bool trans_hsv_w(DisasContext *ctx, arg_hsv_w *a) ++{ ++ REQUIRE_EXT(ctx, RVH); ++#ifndef CONFIG_USER_ONLY ++ TCGv t0 = tcg_temp_new(); ++ TCGv dat = tcg_temp_new(); ++ TCGv mem_idx = tcg_temp_new(); ++ TCGv memop = tcg_temp_new(); ++ ++ gen_get_gpr(t0, a->rs1); ++ gen_get_gpr(dat, a->rs2); ++ tcg_gen_movi_tl(mem_idx, ctx->mem_idx); ++ tcg_gen_movi_tl(memop, MO_TESL); ++ ++ gen_helper_hyp_store(cpu_env, t0, dat, mem_idx, memop); ++ ++ tcg_temp_free(t0); ++ tcg_temp_free(dat); ++ tcg_temp_free(mem_idx); ++ tcg_temp_free(memop); ++ return true; ++#else ++ return false; ++#endif ++} ++ ++#ifdef TARGET_RISCV64 ++static bool trans_hlv_wu(DisasContext *ctx, arg_hlv_wu *a) ++{ ++ REQUIRE_EXT(ctx, RVH); ++#ifndef CONFIG_USER_ONLY ++ TCGv t0 = tcg_temp_new(); ++ TCGv t1 = tcg_temp_new(); ++ TCGv mem_idx = tcg_temp_new(); ++ TCGv memop = tcg_temp_new(); ++ ++ gen_get_gpr(t0, a->rs1); ++ tcg_gen_movi_tl(mem_idx, ctx->mem_idx); ++ tcg_gen_movi_tl(memop, MO_TEUL); ++ ++ gen_helper_hyp_load(t1, cpu_env, t0, mem_idx, memop); ++ gen_set_gpr(a->rd, t1); ++ ++ tcg_temp_free(t0); ++ tcg_temp_free(t1); ++ tcg_temp_free(mem_idx); ++ tcg_temp_free(memop); ++ return true; ++#else ++ return false; ++#endif ++} ++ ++static bool trans_hlv_d(DisasContext *ctx, arg_hlv_d *a) ++{ ++ REQUIRE_EXT(ctx, RVH); ++#ifndef CONFIG_USER_ONLY ++ TCGv t0 = tcg_temp_new(); ++ TCGv t1 = tcg_temp_new(); ++ TCGv mem_idx = tcg_temp_new(); ++ TCGv memop = tcg_temp_new(); ++ ++ gen_get_gpr(t0, a->rs1); ++ tcg_gen_movi_tl(mem_idx, ctx->mem_idx); ++ tcg_gen_movi_tl(memop, MO_TEQ); ++ ++ gen_helper_hyp_load(t1, cpu_env, t0, mem_idx, memop); ++ gen_set_gpr(a->rd, t1); ++ ++ tcg_temp_free(t0); ++ tcg_temp_free(t1); ++ tcg_temp_free(mem_idx); ++ tcg_temp_free(memop); ++ return true; ++#else ++ return false; ++#endif ++} ++ ++static bool trans_hsv_d(DisasContext *ctx, arg_hsv_d *a) ++{ ++ REQUIRE_EXT(ctx, RVH); ++#ifndef CONFIG_USER_ONLY ++ TCGv t0 = tcg_temp_new(); ++ TCGv dat = tcg_temp_new(); ++ TCGv mem_idx = tcg_temp_new(); ++ TCGv memop = tcg_temp_new(); ++ ++ gen_get_gpr(t0, a->rs1); ++ gen_get_gpr(dat, a->rs2); ++ tcg_gen_movi_tl(mem_idx, ctx->mem_idx); ++ tcg_gen_movi_tl(memop, MO_TEQ); ++ ++ gen_helper_hyp_store(cpu_env, t0, dat, mem_idx, memop); ++ ++ tcg_temp_free(t0); ++ tcg_temp_free(dat); ++ tcg_temp_free(mem_idx); ++ tcg_temp_free(memop); ++ return true; ++#else ++ return false; ++#endif ++} ++#endif ++ ++static bool trans_hlvx_hu(DisasContext *ctx, arg_hlvx_hu *a) ++{ ++ REQUIRE_EXT(ctx, RVH); ++#ifndef CONFIG_USER_ONLY ++ TCGv t0 = tcg_temp_new(); ++ TCGv t1 = tcg_temp_new(); ++ TCGv mem_idx = tcg_temp_new(); ++ TCGv memop = tcg_temp_new(); ++ ++ gen_get_gpr(t0, a->rs1); ++ tcg_gen_movi_tl(mem_idx, ctx->mem_idx); ++ tcg_gen_movi_tl(memop, MO_TEUW); ++ ++ gen_helper_hyp_x_load(t1, cpu_env, t0, mem_idx, memop); ++ gen_set_gpr(a->rd, t1); ++ ++ tcg_temp_free(t0); ++ tcg_temp_free(t1); ++ tcg_temp_free(mem_idx); ++ tcg_temp_free(memop); ++ return true; ++#else ++ return false; ++#endif ++} ++ ++static bool trans_hlvx_wu(DisasContext *ctx, arg_hlvx_wu *a) ++{ ++ REQUIRE_EXT(ctx, RVH); ++#ifndef CONFIG_USER_ONLY ++ TCGv t0 = tcg_temp_new(); ++ TCGv t1 = tcg_temp_new(); ++ TCGv mem_idx = tcg_temp_new(); ++ TCGv memop = tcg_temp_new(); ++ ++ gen_get_gpr(t0, a->rs1); ++ tcg_gen_movi_tl(mem_idx, ctx->mem_idx); ++ tcg_gen_movi_tl(memop, MO_TEUL); ++ ++ gen_helper_hyp_x_load(t1, cpu_env, t0, mem_idx, memop); ++ gen_set_gpr(a->rd, t1); ++ ++ tcg_temp_free(t0); ++ tcg_temp_free(t1); ++ tcg_temp_free(mem_idx); ++ tcg_temp_free(memop); ++ return true; ++#else ++ return false; ++#endif ++} ++ + static bool trans_hfence_gvma(DisasContext *ctx, arg_sfence_vma *a) + { + REQUIRE_EXT(ctx, RVH); +diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c +index 7cccd42a1e..e0053699cc 100644 +--- a/target/riscv/op_helper.c ++++ b/target/riscv/op_helper.c +@@ -207,4 +207,118 @@ void helper_hyp_tlb_flush(CPURISCVState *env) + riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC()); + } + ++target_ulong helper_hyp_load(CPURISCVState *env, target_ulong address, ++ target_ulong attrs, target_ulong memop) ++{ ++ if (env->priv == PRV_M || ++ (env->priv == PRV_S && !riscv_cpu_virt_enabled(env)) || ++ (env->priv == PRV_U && !riscv_cpu_virt_enabled(env) && ++ get_field(env->hstatus, HSTATUS_HU))) { ++ target_ulong pte; ++ ++ riscv_cpu_set_two_stage_lookup(env, true); ++ ++ switch (memop) { ++ case MO_SB: ++ pte = cpu_ldsb_data(env, address); ++ break; ++ case MO_UB: ++ pte = cpu_ldub_data(env, address); ++ break; ++ case MO_TESW: ++ pte = cpu_ldsw_data(env, address); ++ break; ++ case MO_TEUW: ++ pte = cpu_lduw_data(env, address); ++ break; ++ case MO_TESL: ++ pte = cpu_ldl_data(env, address); ++ break; ++ case MO_TEUL: ++ pte = cpu_ldl_data(env, address); ++ break; ++ case MO_TEQ: ++ pte = cpu_ldq_data(env, address); ++ break; ++ default: ++ g_assert_not_reached(); ++ } ++ ++ riscv_cpu_set_two_stage_lookup(env, false); ++ ++ return pte; ++ } ++ ++ riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC()); ++ return 0; ++} ++ ++void helper_hyp_store(CPURISCVState *env, target_ulong address, ++ target_ulong val, target_ulong attrs, target_ulong memop) ++{ ++ if (env->priv == PRV_M || ++ (env->priv == PRV_S && !riscv_cpu_virt_enabled(env)) || ++ (env->priv == PRV_U && !riscv_cpu_virt_enabled(env) && ++ get_field(env->hstatus, HSTATUS_HU))) { ++ riscv_cpu_set_two_stage_lookup(env, true); ++ ++ switch (memop) { ++ case MO_SB: ++ case MO_UB: ++ cpu_stb_data(env, address, val); ++ break; ++ case MO_TESW: ++ case MO_TEUW: ++ cpu_stw_data(env, address, val); ++ break; ++ case MO_TESL: ++ case MO_TEUL: ++ cpu_stl_data(env, address, val); ++ break; ++ case MO_TEQ: ++ cpu_stq_data(env, address, val); ++ break; ++ default: ++ g_assert_not_reached(); ++ } ++ ++ riscv_cpu_set_two_stage_lookup(env, false); ++ ++ return; ++ } ++ ++ riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC()); ++} ++ ++target_ulong helper_hyp_x_load(CPURISCVState *env, target_ulong address, ++ target_ulong attrs, target_ulong memop) ++{ ++ if (env->priv == PRV_M || ++ (env->priv == PRV_S && !riscv_cpu_virt_enabled(env)) || ++ (env->priv == PRV_U && !riscv_cpu_virt_enabled(env) && ++ get_field(env->hstatus, HSTATUS_HU))) { ++ target_ulong pte; ++ ++ riscv_cpu_set_two_stage_lookup(env, true); ++ ++ switch (memop) { ++ case MO_TEUL: ++ pte = cpu_ldub_data(env, address); ++ break; ++ case MO_TEUW: ++ pte = cpu_lduw_data(env, address); ++ break; ++ default: ++ g_assert_not_reached(); ++ } ++ ++ riscv_cpu_set_two_stage_lookup(env, false); ++ ++ return pte; ++ } ++ ++ riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC()); ++ return 0; ++} ++ + #endif /* !CONFIG_USER_ONLY */ +-- +2.23.0 + diff --git a/target-riscv-Allow-setting-a-two-stage-lookup-in-the.patch b/target-riscv-Allow-setting-a-two-stage-lookup-in-the.patch new file mode 100644 index 0000000000000000000000000000000000000000..9f0268b96e9f9e0b7513c8515b6e533980088a13 --- /dev/null +++ b/target-riscv-Allow-setting-a-two-stage-lookup-in-the.patch @@ -0,0 +1,70 @@ +From 4c00f3a41227aa3a1d3ddace9e03332fedec9ad6 Mon Sep 17 00:00:00 2001 +From: Alistair Francis +Date: Tue, 7 Apr 2020 11:05:02 -0700 +Subject: [PATCH 675/709] target/riscv: Allow setting a two-stage lookup in the + virt status + +Signed-off-by: Alistair Francis +--- + target/riscv/cpu.h | 2 ++ + target/riscv/cpu_bits.h | 1 + + target/riscv/cpu_helper.c | 18 ++++++++++++++++++ + 3 files changed, 21 insertions(+) + +diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h +index c022539012..1bb5271511 100644 +--- a/target/riscv/cpu.h ++++ b/target/riscv/cpu.h +@@ -294,6 +294,8 @@ bool riscv_cpu_virt_enabled(CPURISCVState *env); + void riscv_cpu_set_virt_enabled(CPURISCVState *env, bool enable); + bool riscv_cpu_force_hs_excep_enabled(CPURISCVState *env); + void riscv_cpu_set_force_hs_excep(CPURISCVState *env, bool enable); ++bool riscv_cpu_two_stage_lookup(CPURISCVState *env); ++void riscv_cpu_set_two_stage_lookup(CPURISCVState *env, bool enable); + int riscv_cpu_mmu_index(CPURISCVState *env, bool ifetch); + hwaddr riscv_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr); + void riscv_cpu_do_unaligned_access(CPUState *cs, vaddr addr, +diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h +index 7f64ee1174..f52711ac32 100644 +--- a/target/riscv/cpu_bits.h ++++ b/target/riscv/cpu_bits.h +@@ -452,6 +452,7 @@ + * page table fault. + */ + #define FORCE_HS_EXCEP 2 ++#define HS_TWO_STAGE 4 + + /* RV32 satp CSR field masks */ + #define SATP32_MODE 0x80000000 +diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c +index 75d2ae3434..68abccc993 100644 +--- a/target/riscv/cpu_helper.c ++++ b/target/riscv/cpu_helper.c +@@ -220,6 +220,24 @@ void riscv_cpu_set_force_hs_excep(CPURISCVState *env, bool enable) + env->virt = set_field(env->virt, FORCE_HS_EXCEP, enable); + } + ++bool riscv_cpu_two_stage_lookup(CPURISCVState *env) ++{ ++ if (!riscv_has_ext(env, RVH)) { ++ return false; ++ } ++ ++ return get_field(env->virt, HS_TWO_STAGE); ++} ++ ++void riscv_cpu_set_two_stage_lookup(CPURISCVState *env, bool enable) ++{ ++ if (!riscv_has_ext(env, RVH)) { ++ return; ++ } ++ ++ env->virt = set_field(env->virt, HS_TWO_STAGE, enable); ++} ++ + int riscv_cpu_claim_interrupts(RISCVCPU *cpu, uint32_t interrupts) + { + CPURISCVState *env = &cpu->env; +-- +2.23.0 + diff --git a/target-riscv-Convert-MSTATUS-MTL-to-GVA.patch b/target-riscv-Convert-MSTATUS-MTL-to-GVA.patch new file mode 100644 index 0000000000000000000000000000000000000000..ccf19d7cd7dc8f12d9906e5ad789cbe62b645ec9 --- /dev/null +++ b/target-riscv-Convert-MSTATUS-MTL-to-GVA.patch @@ -0,0 +1,114 @@ +From 6f1f8b0ed898412a2ccc5ffa23c110c64bc9dab8 Mon Sep 17 00:00:00 2001 +From: Alistair Francis +Date: Mon, 6 Apr 2020 15:24:54 -0700 +Subject: [PATCH 679/709] target/riscv: Convert MSTATUS MTL to GVA + +Signed-off-by: Alistair Francis +--- + target/riscv/cpu_bits.h | 5 +++-- + target/riscv/cpu_helper.c | 20 ++++++++++++++++---- + target/riscv/csr.c | 6 +++--- + 3 files changed, 22 insertions(+), 9 deletions(-) + +diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h +index bb4ee3fc35..028e268faa 100644 +--- a/target/riscv/cpu_bits.h ++++ b/target/riscv/cpu_bits.h +@@ -364,10 +364,10 @@ + #define MSTATUS_TW 0x20000000 /* since: priv-1.10 */ + #define MSTATUS_TSR 0x40000000 /* since: priv-1.10 */ + #if defined(TARGET_RISCV64) +-#define MSTATUS_MTL 0x4000000000ULL ++#define MSTATUS_GVA 0x4000000000ULL + #define MSTATUS_MPV 0x8000000000ULL + #elif defined(TARGET_RISCV32) +-#define MSTATUS_MTL 0x00000040 ++#define MSTATUS_GVA 0x00000040 + #define MSTATUS_MPV 0x00000080 + #endif + +@@ -429,6 +429,7 @@ + #define HSTATUS_VTVM 0x00100000 + #define HSTATUS_VTSR 0x00400000 + #define HSTATUS_HU 0x00000200 ++#define HSTATUS_GVA 0x00000040 + + #define HSTATUS32_WPRI 0xFF8FF87E + #define HSTATUS64_WPRI 0xFFFFFFFFFF8FF87EULL +diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c +index 1521c14b72..3b1a2f75ca 100644 +--- a/target/riscv/cpu_helper.c ++++ b/target/riscv/cpu_helper.c +@@ -892,6 +892,15 @@ void riscv_cpu_do_interrupt(CPUState *cs) + if (riscv_has_ext(env, RVH)) { + target_ulong hdeleg = async ? env->hideleg : env->hedeleg; + ++ if (riscv_cpu_virt_enabled(env) && tval) { ++ /* ++ * If we are writing a guest virtual address to stval, set ++ * this to 1. If we are trapping to VS we will set this to 0 ++ * later. ++ */ ++ env->hstatus = set_field(env->hstatus, HSTATUS_GVA, 1); ++ } ++ + if (riscv_cpu_virt_enabled(env) && ((hdeleg >> cause) & 1) && + !force_hs_execp) { + /* +@@ -902,6 +911,7 @@ void riscv_cpu_do_interrupt(CPUState *cs) + cause == IRQ_VS_EXT) + cause = cause - 1; + /* Trap to VS mode */ ++ env->hstatus = set_field(env->hstatus, HSTATUS_GVA, 0); + } else if (riscv_cpu_virt_enabled(env)) { + /* Trap into HS mode, from virt */ + riscv_cpu_swap_hypervisor_regs(env); +@@ -950,13 +960,15 @@ void riscv_cpu_do_interrupt(CPUState *cs) + #ifdef TARGET_RISCV32 + env->mstatush = set_field(env->mstatush, MSTATUS_MPV, + riscv_cpu_virt_enabled(env)); +- env->mstatush = set_field(env->mstatush, MSTATUS_MTL, +- riscv_cpu_force_hs_excep_enabled(env)); ++ if (riscv_cpu_virt_enabled(env) && tval) { ++ env->mstatush = set_field(env->mstatush, MSTATUS_GVA, 1); ++ } + #else + env->mstatus = set_field(env->mstatus, MSTATUS_MPV, + riscv_cpu_virt_enabled(env)); +- env->mstatus = set_field(env->mstatus, MSTATUS_MTL, +- riscv_cpu_force_hs_excep_enabled(env)); ++ if (riscv_cpu_virt_enabled(env) && tval) { ++ env->mstatus = set_field(env->mstatus, MSTATUS_GVA, 1); ++ } + #endif + + mtval2 = env->guest_phys_fault_addr; +diff --git a/target/riscv/csr.c b/target/riscv/csr.c +index 53665b0985..69a3c8379c 100644 +--- a/target/riscv/csr.c ++++ b/target/riscv/csr.c +@@ -335,10 +335,10 @@ static int write_mstatus(CPURISCVState *env, int csrno, target_ulong val) + MSTATUS_TW; + #if defined(TARGET_RISCV64) + /* +- * RV32: MPV and MTL are not in mstatus. The current plan is to ++ * RV32: MPV and GVA are not in mstatus. The current plan is to + * add them to mstatush. For now, we just don't support it. + */ +- mask |= MSTATUS_MTL | MSTATUS_MPV; ++ mask |= MSTATUS_MPV | MSTATUS_GVA; + #endif + + mstatus = (mstatus & ~mask) | (val & mask); +@@ -364,7 +364,7 @@ static int write_mstatush(CPURISCVState *env, int csrno, target_ulong val) + tlb_flush(env_cpu(env)); + } + +- val &= MSTATUS_MPV | MSTATUS_MTL; ++ val &= MSTATUS_MPV | MSTATUS_GVA; + + env->mstatush = val; + +-- +2.23.0 + diff --git a/target-riscv-Do-two-stage-lookups-on-hlv-hlvx-hsv-in.patch b/target-riscv-Do-two-stage-lookups-on-hlv-hlvx-hsv-in.patch new file mode 100644 index 0000000000000000000000000000000000000000..465ea17278ade235fc20c0b1644c98a680d4b7b9 --- /dev/null +++ b/target-riscv-Do-two-stage-lookups-on-hlv-hlvx-hsv-in.patch @@ -0,0 +1,109 @@ +From 4180ff83c74006d1ea2e69d535aee5891cb9676a Mon Sep 17 00:00:00 2001 +From: Alistair Francis +Date: Mon, 6 Apr 2020 13:56:46 -0700 +Subject: [PATCH 677/709] target/riscv: Do two-stage lookups on hlv/hlvx/hsv + instructions + +Signed-off-by: Alistair Francis +--- + target/riscv/cpu_helper.c | 54 +++++++++++++++------------------------ + 1 file changed, 21 insertions(+), 33 deletions(-) + +diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c +index 68abccc993..1521c14b72 100644 +--- a/target/riscv/cpu_helper.c ++++ b/target/riscv/cpu_helper.c +@@ -340,22 +340,13 @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical, + * was called. Background registers will be used if the guest has + * forced a two stage translation to be on (in HS or M mode). + */ ++ if (riscv_cpu_two_stage_lookup(env) && access_type != MMU_INST_FETCH) { ++ use_background = true; ++ } ++ + if (mode == PRV_M && access_type != MMU_INST_FETCH) { + if (get_field(env->mstatus, MSTATUS_MPRV)) { + mode = get_field(env->mstatus, MSTATUS_MPP); +- +- if (riscv_has_ext(env, RVH) && +- MSTATUS_MPV_ISSET(env)) { +- use_background = true; +- } +- } +- } +- +- if (mode == PRV_S && access_type != MMU_INST_FETCH && +- riscv_has_ext(env, RVH) && !riscv_cpu_virt_enabled(env)) { +- if (get_field(env->hstatus, HSTATUS_SPRV)) { +- mode = get_field(env->mstatus, SSTATUS_SPP); +- use_background = true; + } + } + +@@ -705,8 +696,6 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size, + hwaddr pa = 0; + int prot, prot2; + bool pmp_violation = false; +- bool m_mode_two_stage = false; +- bool hs_mode_two_stage = false; + bool first_stage_error = true; + int ret = TRANSLATE_FAIL; + int mode = mmu_idx; +@@ -716,30 +705,21 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size, + qemu_log_mask(CPU_LOG_MMU, "%s ad %" VADDR_PRIx " rw %d mmu_idx %d\n", + __func__, address, access_type, mmu_idx); + +- /* +- * Determine if we are in M mode and MPRV is set or in HS mode and SPRV is +- * set and we want to access a virtulisation address. +- */ +- if (riscv_has_ext(env, RVH)) { +- m_mode_two_stage = env->priv == PRV_M && +- access_type != MMU_INST_FETCH && +- get_field(env->mstatus, MSTATUS_MPRV) && +- MSTATUS_MPV_ISSET(env); +- +- hs_mode_two_stage = env->priv == PRV_S && +- !riscv_cpu_virt_enabled(env) && +- access_type != MMU_INST_FETCH && +- get_field(env->hstatus, HSTATUS_SPRV) && +- get_field(env->hstatus, HSTATUS_SPV); +- } +- + if (mode == PRV_M && access_type != MMU_INST_FETCH) { + if (get_field(env->mstatus, MSTATUS_MPRV)) { + mode = get_field(env->mstatus, MSTATUS_MPP); + } + } + +- if (riscv_cpu_virt_enabled(env) || m_mode_two_stage || hs_mode_two_stage) { ++ if (riscv_has_ext(env, RVH) && env->priv == PRV_M && ++ access_type != MMU_INST_FETCH && ++ get_field(env->mstatus, MSTATUS_MPRV) && ++ MSTATUS_MPV_ISSET(env)) { ++ riscv_cpu_set_two_stage_lookup(env, true); ++ } ++ ++ if (riscv_cpu_virt_enabled(env) || ++ (riscv_cpu_two_stage_lookup(env) && access_type != MMU_INST_FETCH)) { + /* Two stage lookup */ + ret = get_physical_address(env, &pa, &prot, address, access_type, + mmu_idx, true, true); +@@ -791,6 +771,14 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size, + __func__, address, ret, pa, prot); + } + ++ /* We did the two stage lookup based on MPRV, unset the lookup */ ++ if (riscv_has_ext(env, RVH) && env->priv == PRV_M && ++ access_type != MMU_INST_FETCH && ++ get_field(env->mstatus, MSTATUS_MPRV) && ++ MSTATUS_MPV_ISSET(env)) { ++ riscv_cpu_set_two_stage_lookup(env, false); ++ } ++ + if (riscv_feature(env, RISCV_FEATURE_PMP) && + (ret == TRANSLATE_SUCCESS) && + !pmp_hart_has_privs(env, pa, size, 1 << access_type, mode)) { +-- +2.23.0 + diff --git a/target-riscv-Don-t-allow-guest-to-write-to-htinst.patch b/target-riscv-Don-t-allow-guest-to-write-to-htinst.patch new file mode 100644 index 0000000000000000000000000000000000000000..3052e1b922c6cf3271cec755821f50b388dfb2f5 --- /dev/null +++ b/target-riscv-Don-t-allow-guest-to-write-to-htinst.patch @@ -0,0 +1,25 @@ +From 5f611396ff603241329958d647af716f4273f49b Mon Sep 17 00:00:00 2001 +From: Alistair Francis +Date: Mon, 6 Apr 2020 15:00:49 -0700 +Subject: [PATCH 678/709] target/riscv: Don't allow guest to write to htinst + +Signed-off-by: Alistair Francis +--- + target/riscv/csr.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/target/riscv/csr.c b/target/riscv/csr.c +index 383be0a955..53665b0985 100644 +--- a/target/riscv/csr.c ++++ b/target/riscv/csr.c +@@ -854,7 +854,6 @@ static int read_htinst(CPURISCVState *env, int csrno, target_ulong *val) + + static int write_htinst(CPURISCVState *env, int csrno, target_ulong val) + { +- env->htinst = val; + return 0; + } + +-- +2.23.0 + diff --git a/target-riscv-Drop-support-for-ISA-spec-version-1.09..patch b/target-riscv-Drop-support-for-ISA-spec-version-1.09..patch new file mode 100644 index 0000000000000000000000000000000000000000..5b3a9c2f2db1afa39f30b22ced34bf47fb7b6137 --- /dev/null +++ b/target-riscv-Drop-support-for-ISA-spec-version-1.09..patch @@ -0,0 +1,557 @@ +From 81775222a69e421d8f53f3dce4837380086e03d0 Mon Sep 17 00:00:00 2001 +From: Alistair Francis +Date: Tue, 5 May 2020 13:04:50 -0700 +Subject: [PATCH 669/709] target/riscv: Drop support for ISA spec version + 1.09.1 + +The RISC-V ISA spec version 1.09.1 has been deprecated in QEMU since +4.1. It's not commonly used so let's remove support for it. + +Signed-off-by: Alistair Francis +--- + target/riscv/cpu.c | 2 - + target/riscv/cpu.h | 1 - + target/riscv/cpu_helper.c | 82 ++++------- + target/riscv/csr.c | 138 ++++-------------- + .../riscv/insn_trans/trans_privileged.inc.c | 18 +-- + target/riscv/monitor.c | 5 - + target/riscv/op_helper.c | 17 +-- + 7 files changed, 63 insertions(+), 200 deletions(-) + +diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c +index 112f2e3a2f..eeb91f8513 100644 +--- a/target/riscv/cpu.c ++++ b/target/riscv/cpu.c +@@ -368,8 +368,6 @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp) + priv_version = PRIV_VERSION_1_11_0; + } else if (!g_strcmp0(cpu->cfg.priv_spec, "v1.10.0")) { + priv_version = PRIV_VERSION_1_10_0; +- } else if (!g_strcmp0(cpu->cfg.priv_spec, "v1.9.1")) { +- priv_version = PRIV_VERSION_1_09_1; + } else { + error_setg(errp, + "Unsupported privilege spec version '%s'", +diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h +index 76b98d7a33..c022539012 100644 +--- a/target/riscv/cpu.h ++++ b/target/riscv/cpu.h +@@ -73,7 +73,6 @@ enum { + RISCV_FEATURE_MISA + }; + +-#define PRIV_VERSION_1_09_1 0x00010901 + #define PRIV_VERSION_1_10_0 0x00011000 + #define PRIV_VERSION_1_11_0 0x00011100 + +diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c +index bc80aa87cf..62fe1ecc8f 100644 +--- a/target/riscv/cpu_helper.c ++++ b/target/riscv/cpu_helper.c +@@ -364,57 +364,36 @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical, + mxr = get_field(env->vsstatus, MSTATUS_MXR); + } + +- if (env->priv_ver >= PRIV_VERSION_1_10_0) { +- if (first_stage == true) { +- if (use_background) { +- base = (hwaddr)get_field(env->vsatp, SATP_PPN) << PGSHIFT; +- vm = get_field(env->vsatp, SATP_MODE); +- } else { +- base = (hwaddr)get_field(env->satp, SATP_PPN) << PGSHIFT; +- vm = get_field(env->satp, SATP_MODE); +- } +- widened = 0; ++ if (first_stage == true) { ++ if (use_background) { ++ base = (hwaddr)get_field(env->vsatp, SATP_PPN) << PGSHIFT; ++ vm = get_field(env->vsatp, SATP_MODE); + } else { +- base = (hwaddr)get_field(env->hgatp, HGATP_PPN) << PGSHIFT; +- vm = get_field(env->hgatp, HGATP_MODE); +- widened = 2; +- } +- sum = get_field(env->mstatus, MSTATUS_SUM); +- switch (vm) { +- case VM_1_10_SV32: +- levels = 2; ptidxbits = 10; ptesize = 4; break; +- case VM_1_10_SV39: +- levels = 3; ptidxbits = 9; ptesize = 8; break; +- case VM_1_10_SV48: +- levels = 4; ptidxbits = 9; ptesize = 8; break; +- case VM_1_10_SV57: +- levels = 5; ptidxbits = 9; ptesize = 8; break; +- case VM_1_10_MBARE: +- *physical = addr; +- *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC; +- return TRANSLATE_SUCCESS; +- default: +- g_assert_not_reached(); ++ base = (hwaddr)get_field(env->satp, SATP_PPN) << PGSHIFT; ++ vm = get_field(env->satp, SATP_MODE); + } +- } else { + widened = 0; +- base = (hwaddr)(env->sptbr) << PGSHIFT; +- sum = !get_field(env->mstatus, MSTATUS_PUM); +- vm = get_field(env->mstatus, MSTATUS_VM); +- switch (vm) { +- case VM_1_09_SV32: +- levels = 2; ptidxbits = 10; ptesize = 4; break; +- case VM_1_09_SV39: +- levels = 3; ptidxbits = 9; ptesize = 8; break; +- case VM_1_09_SV48: +- levels = 4; ptidxbits = 9; ptesize = 8; break; +- case VM_1_09_MBARE: +- *physical = addr; +- *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC; +- return TRANSLATE_SUCCESS; +- default: +- g_assert_not_reached(); +- } ++ } else { ++ base = (hwaddr)get_field(env->hgatp, HGATP_PPN) << PGSHIFT; ++ vm = get_field(env->hgatp, HGATP_MODE); ++ widened = 2; ++ } ++ sum = get_field(env->mstatus, MSTATUS_SUM); ++ switch (vm) { ++ case VM_1_10_SV32: ++ levels = 2; ptidxbits = 10; ptesize = 4; break; ++ case VM_1_10_SV39: ++ levels = 3; ptidxbits = 9; ptesize = 8; break; ++ case VM_1_10_SV48: ++ levels = 4; ptidxbits = 9; ptesize = 8; break; ++ case VM_1_10_SV57: ++ levels = 5; ptidxbits = 9; ptesize = 8; break; ++ case VM_1_10_MBARE: ++ *physical = addr; ++ *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC; ++ return TRANSLATE_SUCCESS; ++ default: ++ g_assert_not_reached(); + } + + CPUState *cs = env_cpu(env); +@@ -588,7 +567,6 @@ static void raise_mmu_exception(CPURISCVState *env, target_ulong address, + int page_fault_exceptions; + if (first_stage) { + page_fault_exceptions = +- (env->priv_ver >= PRIV_VERSION_1_10_0) && + get_field(env->satp, SATP_MODE) != VM_1_10_MBARE && + !pmp_violation; + } else { +@@ -941,8 +919,7 @@ void riscv_cpu_do_interrupt(CPUState *cs) + } + + s = env->mstatus; +- s = set_field(s, MSTATUS_SPIE, env->priv_ver >= PRIV_VERSION_1_10_0 ? +- get_field(s, MSTATUS_SIE) : get_field(s, MSTATUS_UIE << env->priv)); ++ s = set_field(s, MSTATUS_SPIE, get_field(s, MSTATUS_SIE)); + s = set_field(s, MSTATUS_SPP, env->priv); + s = set_field(s, MSTATUS_SIE, 0); + env->mstatus = s; +@@ -979,8 +956,7 @@ void riscv_cpu_do_interrupt(CPUState *cs) + } + + s = env->mstatus; +- s = set_field(s, MSTATUS_MPIE, env->priv_ver >= PRIV_VERSION_1_10_0 ? +- get_field(s, MSTATUS_MIE) : get_field(s, MSTATUS_UIE << env->priv)); ++ s = set_field(s, MSTATUS_MPIE, get_field(s, MSTATUS_MIE)); + s = set_field(s, MSTATUS_MPP, env->priv); + s = set_field(s, MSTATUS_MIE, 0); + env->mstatus = s; +diff --git a/target/riscv/csr.c b/target/riscv/csr.c +index 11d184cd16..383be0a955 100644 +--- a/target/riscv/csr.c ++++ b/target/riscv/csr.c +@@ -58,31 +58,11 @@ static int ctr(CPURISCVState *env, int csrno) + #if !defined(CONFIG_USER_ONLY) + CPUState *cs = env_cpu(env); + RISCVCPU *cpu = RISCV_CPU(cs); +- uint32_t ctr_en = ~0u; + + if (!cpu->cfg.ext_counters) { + /* The Counters extensions is not enabled */ + return -1; + } +- +- /* +- * The counters are always enabled at run time on newer priv specs, as the +- * CSR has changed from controlling that the counters can be read to +- * controlling that the counters increment. +- */ +- if (env->priv_ver > PRIV_VERSION_1_09_1) { +- return 0; +- } +- +- if (env->priv < PRV_M) { +- ctr_en &= env->mcounteren; +- } +- if (env->priv < PRV_S) { +- ctr_en &= env->scounteren; +- } +- if (!(ctr_en & (1u << (csrno & 31)))) { +- return -1; +- } + #endif + return 0; + } +@@ -293,9 +273,6 @@ static const target_ulong delegable_excps = + (1ULL << (RISCV_EXCP_INST_GUEST_PAGE_FAULT)) | + (1ULL << (RISCV_EXCP_LOAD_GUEST_ACCESS_FAULT)) | + (1ULL << (RISCV_EXCP_STORE_GUEST_AMO_ACCESS_FAULT)); +-static const target_ulong sstatus_v1_9_mask = SSTATUS_SIE | SSTATUS_SPIE | +- SSTATUS_UIE | SSTATUS_UPIE | SSTATUS_SPP | SSTATUS_FS | SSTATUS_XS | +- SSTATUS_SUM | SSTATUS_SD; + 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_SD; +@@ -304,20 +281,11 @@ static const target_ulong hip_writable_mask = MIP_VSSIP | MIP_VSTIP | MIP_VSEIP; + static const target_ulong vsip_writable_mask = MIP_VSSIP; + + #if defined(TARGET_RISCV32) +-static const char valid_vm_1_09[16] = { +- [VM_1_09_MBARE] = 1, +- [VM_1_09_SV32] = 1, +-}; + static const char valid_vm_1_10[16] = { + [VM_1_10_MBARE] = 1, + [VM_1_10_SV32] = 1 + }; + #elif defined(TARGET_RISCV64) +-static const char valid_vm_1_09[16] = { +- [VM_1_09_MBARE] = 1, +- [VM_1_09_SV39] = 1, +- [VM_1_09_SV48] = 1, +-}; + static const char valid_vm_1_10[16] = { + [VM_1_10_MBARE] = 1, + [VM_1_10_SV39] = 1, +@@ -347,8 +315,7 @@ static int read_mstatus(CPURISCVState *env, int csrno, target_ulong *val) + + static int validate_vm(CPURISCVState *env, target_ulong vm) + { +- return (env->priv_ver >= PRIV_VERSION_1_10_0) ? +- valid_vm_1_10[vm & 0xf] : valid_vm_1_09[vm & 0xf]; ++ return valid_vm_1_10[vm & 0xf]; + } + + static int write_mstatus(CPURISCVState *env, int csrno, target_ulong val) +@@ -358,34 +325,21 @@ static int write_mstatus(CPURISCVState *env, int csrno, target_ulong val) + int dirty; + + /* flush tlb on mstatus fields that affect VM */ +- if (env->priv_ver <= PRIV_VERSION_1_09_1) { +- if ((val ^ mstatus) & (MSTATUS_MXR | MSTATUS_MPP | +- MSTATUS_MPRV | MSTATUS_SUM | MSTATUS_VM)) { +- tlb_flush(env_cpu(env)); +- } +- mask = MSTATUS_SIE | MSTATUS_SPIE | MSTATUS_MIE | MSTATUS_MPIE | +- MSTATUS_SPP | MSTATUS_FS | MSTATUS_MPRV | MSTATUS_SUM | +- MSTATUS_MPP | MSTATUS_MXR | +- (validate_vm(env, get_field(val, MSTATUS_VM)) ? +- MSTATUS_VM : 0); ++ if ((val ^ mstatus) & (MSTATUS_MXR | MSTATUS_MPP | MSTATUS_MPV | ++ MSTATUS_MPRV | MSTATUS_SUM)) { ++ tlb_flush(env_cpu(env)); + } +- if (env->priv_ver >= PRIV_VERSION_1_10_0) { +- if ((val ^ mstatus) & (MSTATUS_MXR | MSTATUS_MPP | MSTATUS_MPV | +- MSTATUS_MPRV | MSTATUS_SUM)) { +- tlb_flush(env_cpu(env)); +- } +- mask = MSTATUS_SIE | MSTATUS_SPIE | MSTATUS_MIE | MSTATUS_MPIE | +- MSTATUS_SPP | MSTATUS_FS | MSTATUS_MPRV | MSTATUS_SUM | +- MSTATUS_MPP | MSTATUS_MXR | MSTATUS_TVM | MSTATUS_TSR | +- MSTATUS_TW; ++ mask = MSTATUS_SIE | MSTATUS_SPIE | MSTATUS_MIE | MSTATUS_MPIE | ++ MSTATUS_SPP | MSTATUS_FS | MSTATUS_MPRV | MSTATUS_SUM | ++ MSTATUS_MPP | MSTATUS_MXR | MSTATUS_TVM | MSTATUS_TSR | ++ MSTATUS_TW; + #if defined(TARGET_RISCV64) +- /* +- * RV32: MPV and MTL are not in mstatus. The current plan is to +- * add them to mstatush. For now, we just don't support it. +- */ +- mask |= MSTATUS_MTL | MSTATUS_MPV; ++ /* ++ * RV32: MPV and MTL are not in mstatus. The current plan is to ++ * add them to mstatush. For now, we just don't support it. ++ */ ++ mask |= MSTATUS_MTL | MSTATUS_MPV; + #endif +- } + + mstatus = (mstatus & ~mask) | (val & mask); + +@@ -534,18 +488,12 @@ static int write_mtvec(CPURISCVState *env, int csrno, target_ulong val) + + static int read_mcounteren(CPURISCVState *env, int csrno, target_ulong *val) + { +- if (env->priv_ver < PRIV_VERSION_1_10_0) { +- return -1; +- } + *val = env->mcounteren; + return 0; + } + + static int write_mcounteren(CPURISCVState *env, int csrno, target_ulong val) + { +- if (env->priv_ver < PRIV_VERSION_1_10_0) { +- return -1; +- } + env->mcounteren = val; + return 0; + } +@@ -553,8 +501,7 @@ static int write_mcounteren(CPURISCVState *env, int csrno, target_ulong val) + /* This regiser is replaced with CSR_MCOUNTINHIBIT in 1.11.0 */ + static int read_mscounteren(CPURISCVState *env, int csrno, target_ulong *val) + { +- if (env->priv_ver > PRIV_VERSION_1_09_1 +- && env->priv_ver < PRIV_VERSION_1_11_0) { ++ if (env->priv_ver < PRIV_VERSION_1_11_0) { + return -1; + } + *val = env->mcounteren; +@@ -564,32 +511,13 @@ static int read_mscounteren(CPURISCVState *env, int csrno, target_ulong *val) + /* This regiser is replaced with CSR_MCOUNTINHIBIT in 1.11.0 */ + static int write_mscounteren(CPURISCVState *env, int csrno, target_ulong val) + { +- if (env->priv_ver > PRIV_VERSION_1_09_1 +- && env->priv_ver < PRIV_VERSION_1_11_0) { ++ if (env->priv_ver < PRIV_VERSION_1_11_0) { + return -1; + } + env->mcounteren = val; + return 0; + } + +-static int read_mucounteren(CPURISCVState *env, int csrno, target_ulong *val) +-{ +- if (env->priv_ver > PRIV_VERSION_1_09_1) { +- return -1; +- } +- *val = env->scounteren; +- return 0; +-} +- +-static int write_mucounteren(CPURISCVState *env, int csrno, target_ulong val) +-{ +- if (env->priv_ver > PRIV_VERSION_1_09_1) { +- return -1; +- } +- env->scounteren = val; +- return 0; +-} +- + /* Machine Trap Handling */ + static int read_mscratch(CPURISCVState *env, int csrno, target_ulong *val) + { +@@ -663,16 +591,14 @@ static int rmw_mip(CPURISCVState *env, int csrno, target_ulong *ret_value, + /* Supervisor Trap Setup */ + static int read_sstatus(CPURISCVState *env, int csrno, target_ulong *val) + { +- target_ulong mask = ((env->priv_ver >= PRIV_VERSION_1_10_0) ? +- sstatus_v1_10_mask : sstatus_v1_9_mask); ++ target_ulong mask = (sstatus_v1_10_mask); + *val = env->mstatus & mask; + return 0; + } + + static int write_sstatus(CPURISCVState *env, int csrno, target_ulong val) + { +- target_ulong mask = ((env->priv_ver >= PRIV_VERSION_1_10_0) ? +- sstatus_v1_10_mask : sstatus_v1_9_mask); ++ target_ulong mask = (sstatus_v1_10_mask); + target_ulong newval = (env->mstatus & ~mask) | (val & mask); + return write_mstatus(env, CSR_MSTATUS, newval); + } +@@ -722,18 +648,12 @@ static int write_stvec(CPURISCVState *env, int csrno, target_ulong val) + + static int read_scounteren(CPURISCVState *env, int csrno, target_ulong *val) + { +- if (env->priv_ver < PRIV_VERSION_1_10_0) { +- return -1; +- } + *val = env->scounteren; + return 0; + } + + static int write_scounteren(CPURISCVState *env, int csrno, target_ulong val) + { +- if (env->priv_ver < PRIV_VERSION_1_10_0) { +- return -1; +- } + env->scounteren = val; + return 0; + } +@@ -812,15 +732,15 @@ static int read_satp(CPURISCVState *env, int csrno, target_ulong *val) + { + if (!riscv_feature(env, RISCV_FEATURE_MMU)) { + *val = 0; +- } else if (env->priv_ver >= PRIV_VERSION_1_10_0) { +- if (env->priv == PRV_S && get_field(env->mstatus, MSTATUS_TVM)) { +- return -1; +- } else { +- *val = env->satp; +- } ++ return 0; ++ } ++ ++ if (env->priv == PRV_S && get_field(env->mstatus, MSTATUS_TVM)) { ++ return -1; + } else { +- *val = env->sptbr; ++ *val = env->satp; + } ++ + return 0; + } + +@@ -829,13 +749,7 @@ static int write_satp(CPURISCVState *env, int csrno, target_ulong val) + if (!riscv_feature(env, RISCV_FEATURE_MMU)) { + return 0; + } +- if (env->priv_ver <= PRIV_VERSION_1_09_1 && (val ^ env->sptbr)) { +- tlb_flush(env_cpu(env)); +- env->sptbr = val & (((target_ulong) +- 1 << (TARGET_PHYS_ADDR_SPACE_BITS - PGSHIFT)) - 1); +- } +- if (env->priv_ver >= PRIV_VERSION_1_10_0 && +- validate_vm(env, get_field(val, SATP_MODE)) && ++ if (validate_vm(env, get_field(val, SATP_MODE)) && + ((val ^ env->satp) & (SATP_MODE | SATP_ASID | SATP_PPN))) + { + if (env->priv == PRV_S && get_field(env->mstatus, MSTATUS_TVM)) { +@@ -1313,8 +1227,6 @@ static riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = { + [CSR_MSTATUSH] = { any, read_mstatush, write_mstatush }, + #endif + +- /* Legacy Counter Setup (priv v1.9.1) */ +- [CSR_MUCOUNTEREN] = { any, read_mucounteren, write_mucounteren }, + [CSR_MSCOUNTEREN] = { any, read_mscounteren, write_mscounteren }, + + /* Machine Trap Handling */ +diff --git a/target/riscv/insn_trans/trans_privileged.inc.c b/target/riscv/insn_trans/trans_privileged.inc.c +index 76c2fad71c..5f26e0f5ea 100644 +--- a/target/riscv/insn_trans/trans_privileged.inc.c ++++ b/target/riscv/insn_trans/trans_privileged.inc.c +@@ -85,30 +85,21 @@ static bool trans_wfi(DisasContext *ctx, arg_wfi *a) + static bool trans_sfence_vma(DisasContext *ctx, arg_sfence_vma *a) + { + #ifndef CONFIG_USER_ONLY +- if (ctx->priv_ver >= PRIV_VERSION_1_10_0) { +- gen_helper_tlb_flush(cpu_env); +- return true; +- } ++ gen_helper_tlb_flush(cpu_env); ++ return true; + #endif + return false; + } + + static bool trans_sfence_vm(DisasContext *ctx, arg_sfence_vm *a) + { +-#ifndef CONFIG_USER_ONLY +- if (ctx->priv_ver <= PRIV_VERSION_1_09_1) { +- gen_helper_tlb_flush(cpu_env); +- return true; +- } +-#endif + return false; + } + + static bool trans_hfence_gvma(DisasContext *ctx, arg_sfence_vma *a) + { + #ifndef CONFIG_USER_ONLY +- if (ctx->priv_ver >= PRIV_VERSION_1_10_0 && +- has_ext(ctx, RVH)) { ++ if (has_ext(ctx, RVH)) { + /* Hpervisor extensions exist */ + /* + * if (env->priv == PRV_M || +@@ -127,8 +118,7 @@ static bool trans_hfence_gvma(DisasContext *ctx, arg_sfence_vma *a) + static bool trans_hfence_bvma(DisasContext *ctx, arg_sfence_vma *a) + { + #ifndef CONFIG_USER_ONLY +- if (ctx->priv_ver >= PRIV_VERSION_1_10_0 && +- has_ext(ctx, RVH)) { ++ if (has_ext(ctx, RVH)) { + /* Hpervisor extensions exist */ + /* + * if (env->priv == PRV_M || +diff --git a/target/riscv/monitor.c b/target/riscv/monitor.c +index d725a7a36e..b569f08387 100644 +--- a/target/riscv/monitor.c ++++ b/target/riscv/monitor.c +@@ -215,11 +215,6 @@ void hmp_info_mem(Monitor *mon, const QDict *qdict) + return; + } + +- if (env->priv_ver < PRIV_VERSION_1_10_0) { +- monitor_printf(mon, "Privileged mode < 1.10 unsupported\n"); +- return; +- } +- + if (!(env->satp & SATP_MODE)) { + monitor_printf(mon, "No translation or protection\n"); + return; +diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c +index c6412f680c..b0c49efc4a 100644 +--- a/target/riscv/op_helper.c ++++ b/target/riscv/op_helper.c +@@ -84,8 +84,7 @@ target_ulong helper_sret(CPURISCVState *env, target_ulong cpu_pc_deb) + riscv_raise_exception(env, RISCV_EXCP_INST_ADDR_MIS, GETPC()); + } + +- if (env->priv_ver >= PRIV_VERSION_1_10_0 && +- get_field(env->mstatus, MSTATUS_TSR) && !(env->priv >= PRV_M)) { ++ if (get_field(env->mstatus, MSTATUS_TSR) && !(env->priv >= PRV_M)) { + riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC()); + } + +@@ -119,10 +118,8 @@ target_ulong helper_sret(CPURISCVState *env, target_ulong cpu_pc_deb) + } else { + prev_priv = get_field(mstatus, MSTATUS_SPP); + +- mstatus = set_field(mstatus, +- env->priv_ver >= PRIV_VERSION_1_10_0 ? +- MSTATUS_SIE : MSTATUS_UIE << prev_priv, +- get_field(mstatus, MSTATUS_SPIE)); ++ mstatus = set_field(mstatus, MSTATUS_SIE, ++ get_field(mstatus, MSTATUS_SPIE)); + mstatus = set_field(mstatus, MSTATUS_SPIE, 1); + mstatus = set_field(mstatus, MSTATUS_SPP, PRV_U); + env->mstatus = mstatus; +@@ -147,10 +144,8 @@ target_ulong helper_mret(CPURISCVState *env, target_ulong cpu_pc_deb) + target_ulong mstatus = env->mstatus; + target_ulong prev_priv = get_field(mstatus, MSTATUS_MPP); + target_ulong prev_virt = MSTATUS_MPV_ISSET(env); +- mstatus = set_field(mstatus, +- env->priv_ver >= PRIV_VERSION_1_10_0 ? +- MSTATUS_MIE : MSTATUS_UIE << prev_priv, +- get_field(mstatus, MSTATUS_MPIE)); ++ mstatus = set_field(mstatus, MSTATUS_MIE, ++ get_field(mstatus, MSTATUS_MPIE)); + mstatus = set_field(mstatus, MSTATUS_MPIE, 1); + mstatus = set_field(mstatus, MSTATUS_MPP, PRV_U); + #ifdef TARGET_RISCV32 +@@ -177,7 +172,6 @@ void helper_wfi(CPURISCVState *env) + CPUState *cs = env_cpu(env); + + if ((env->priv == PRV_S && +- env->priv_ver >= PRIV_VERSION_1_10_0 && + get_field(env->mstatus, MSTATUS_TW)) || + riscv_cpu_virt_enabled(env)) { + riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC()); +@@ -193,7 +187,6 @@ void helper_tlb_flush(CPURISCVState *env) + CPUState *cs = env_cpu(env); + if (!(env->priv >= PRV_S) || + (env->priv == PRV_S && +- env->priv_ver >= PRIV_VERSION_1_10_0 && + get_field(env->mstatus, MSTATUS_TVM))) { + riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC()); + } else { +-- +2.23.0 + diff --git a/target-riscv-Fix-HSV-HLV-implementation.patch b/target-riscv-Fix-HSV-HLV-implementation.patch new file mode 100644 index 0000000000000000000000000000000000000000..d192dc66992288c123f92efb6d12d647a794c434 --- /dev/null +++ b/target-riscv-Fix-HSV-HLV-implementation.patch @@ -0,0 +1,148 @@ +From cf23f35b8fe0dde589578f52626045b2c6c6ca77 Mon Sep 17 00:00:00 2001 +From: Anup Patel +Date: Sat, 6 Jun 2020 11:58:44 +0530 +Subject: [PATCH 689/709] target/riscv: Fix HSV/HLV implementation + +The page faults for HSV/HLV instruction are not being generated +correctly. This patch fixes it. + +DO NOT UPSTREAM !!!!! + +Signed-off-by: Anup Patel +--- + target/riscv/cpu_helper.c | 18 ++++++++++++------ + target/riscv/op_helper.c | 26 +++++++++++++------------- + 2 files changed, 25 insertions(+), 19 deletions(-) + +diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c +index c4085e5870..eccd80cfef 100644 +--- a/target/riscv/cpu_helper.c ++++ b/target/riscv/cpu_helper.c +@@ -598,7 +598,7 @@ static void raise_mmu_exception(CPURISCVState *env, target_ulong address, + } + break; + case MMU_DATA_LOAD: +- if (riscv_cpu_virt_enabled(env) && !first_stage) { ++ if ((riscv_cpu_virt_enabled(env) || riscv_cpu_two_stage_lookup(env)) && !first_stage) { + cs->exception_index = RISCV_EXCP_LOAD_GUEST_ACCESS_FAULT; + } else { + cs->exception_index = page_fault_exceptions ? +@@ -606,7 +606,7 @@ static void raise_mmu_exception(CPURISCVState *env, target_ulong address, + } + break; + case MMU_DATA_STORE: +- if (riscv_cpu_virt_enabled(env) && !first_stage) { ++ if ((riscv_cpu_virt_enabled(env) || riscv_cpu_two_stage_lookup(env)) && !first_stage) { + cs->exception_index = RISCV_EXCP_STORE_GUEST_AMO_ACCESS_FAULT; + } else { + cs->exception_index = page_fault_exceptions ? +@@ -892,13 +892,17 @@ void riscv_cpu_do_interrupt(CPUState *cs) + if (riscv_has_ext(env, RVH)) { + target_ulong hdeleg = async ? env->hideleg : env->hedeleg; + +- if (riscv_cpu_virt_enabled(env) && tval) { ++ if ((riscv_cpu_virt_enabled(env) || ++ riscv_cpu_two_stage_lookup(env)) && tval) { + /* + * If we are writing a guest virtual address to stval, set + * this to 1. If we are trapping to VS we will set this to 0 + * later. + */ + env->hstatus = set_field(env->hstatus, HSTATUS_GVA, 1); ++ } else { ++ /* For other HS-mode traps, we set this to 0. */ ++ env->hstatus = set_field(env->hstatus, HSTATUS_GVA, 0); + } + + if (riscv_cpu_virt_enabled(env) && ((hdeleg >> cause) & 1) && +@@ -927,9 +931,11 @@ void riscv_cpu_do_interrupt(CPUState *cs) + riscv_cpu_set_force_hs_excep(env, 0); + } else { + /* Trap into HS mode */ +- env->hstatus = set_field(env->hstatus, HSTATUS_SPV, +- riscv_cpu_virt_enabled(env)); +- ++ if (!riscv_cpu_two_stage_lookup(env)) { ++ env->hstatus = set_field(env->hstatus, HSTATUS_SPV, ++ riscv_cpu_virt_enabled(env)); ++ } ++ riscv_cpu_set_two_stage_lookup(env, false); + htval = env->guest_phys_fault_addr; + } + } +diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c +index dc1e403397..d7d9d212fc 100644 +--- a/target/riscv/op_helper.c ++++ b/target/riscv/op_helper.c +@@ -244,25 +244,25 @@ target_ulong helper_hyp_load(CPURISCVState *env, target_ulong address, + + switch (memop) { + case MO_SB: +- pte = cpu_ldsb_data(env, address); ++ pte = cpu_ldsb_data_ra(env, address, GETPC()); + break; + case MO_UB: +- pte = cpu_ldub_data(env, address); ++ pte = cpu_ldub_data_ra(env, address, GETPC()); + break; + case MO_TESW: +- pte = cpu_ldsw_data(env, address); ++ pte = cpu_ldsw_data_ra(env, address, GETPC()); + break; + case MO_TEUW: +- pte = cpu_lduw_data(env, address); ++ pte = cpu_lduw_data_ra(env, address, GETPC()); + break; + case MO_TESL: +- pte = cpu_ldl_data(env, address); ++ pte = cpu_ldl_data_ra(env, address, GETPC()); + break; + case MO_TEUL: +- pte = cpu_ldl_data(env, address); ++ pte = cpu_ldl_data_ra(env, address, GETPC()); + break; + case MO_TEQ: +- pte = cpu_ldq_data(env, address); ++ pte = cpu_ldq_data_ra(env, address, GETPC()); + break; + default: + g_assert_not_reached(); +@@ -293,18 +293,18 @@ void helper_hyp_store(CPURISCVState *env, target_ulong address, + switch (memop) { + case MO_SB: + case MO_UB: +- cpu_stb_data(env, address, val); ++ cpu_stb_data_ra(env, address, val, GETPC()); + break; + case MO_TESW: + case MO_TEUW: +- cpu_stw_data(env, address, val); ++ cpu_stw_data_ra(env, address, val, GETPC()); + break; + case MO_TESL: + case MO_TEUL: +- cpu_stl_data(env, address, val); ++ cpu_stl_data_ra(env, address, val, GETPC()); + break; + case MO_TEQ: +- cpu_stq_data(env, address, val); ++ cpu_stq_data_ra(env, address, val, GETPC()); + break; + default: + g_assert_not_reached(); +@@ -335,10 +335,10 @@ target_ulong helper_hyp_x_load(CPURISCVState *env, target_ulong address, + + switch (memop) { + case MO_TEUL: +- pte = cpu_ldub_data(env, address); ++ pte = cpu_ldub_data_ra(env, address, GETPC()); + break; + case MO_TEUW: +- pte = cpu_lduw_data(env, address); ++ pte = cpu_lduw_data_ra(env, address, GETPC()); + break; + default: + g_assert_not_reached(); +-- +2.23.0 + diff --git a/target-riscv-Fix-the-interrupt-cause-code.patch b/target-riscv-Fix-the-interrupt-cause-code.patch new file mode 100644 index 0000000000000000000000000000000000000000..780b629adb1ae43735d862112b9437f3e5e2e0db --- /dev/null +++ b/target-riscv-Fix-the-interrupt-cause-code.patch @@ -0,0 +1,35 @@ +From c6424e4dcab0cfb229054b4d15a7262258416cd7 Mon Sep 17 00:00:00 2001 +From: Alistair Francis +Date: Mon, 6 Apr 2020 15:30:46 -0700 +Subject: [PATCH 680/709] target/riscv: Fix the interrupt cause code + +Signed-off-by: Alistair Francis +--- + target/riscv/cpu_helper.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c +index 3b1a2f75ca..4ea39d5641 100644 +--- a/target/riscv/cpu_helper.c ++++ b/target/riscv/cpu_helper.c +@@ -903,14 +903,15 @@ void riscv_cpu_do_interrupt(CPUState *cs) + + if (riscv_cpu_virt_enabled(env) && ((hdeleg >> cause) & 1) && + !force_hs_execp) { ++ /* Trap to VS mode */ + /* + * See if we need to adjust cause. Yes if its VS mode interrupt + * no if hypervisor has delegated one of hs mode's interrupt + */ + if (cause == IRQ_VS_TIMER || cause == IRQ_VS_SOFT || +- cause == IRQ_VS_EXT) ++ cause == IRQ_VS_EXT) { + cause = cause - 1; +- /* Trap to VS mode */ ++ } + env->hstatus = set_field(env->hstatus, HSTATUS_GVA, 0); + } else if (riscv_cpu_virt_enabled(env)) { + /* Trap into HS mode, from virt */ +-- +2.23.0 + diff --git a/target-riscv-Handler-KVM_EXIT_RISCV_SBI-exit.patch b/target-riscv-Handler-KVM_EXIT_RISCV_SBI-exit.patch new file mode 100644 index 0000000000000000000000000000000000000000..aa28f454a2f490459b7582ff4d8d68e6e1786514 --- /dev/null +++ b/target-riscv-Handler-KVM_EXIT_RISCV_SBI-exit.patch @@ -0,0 +1,162 @@ +From ce7cf415ce371ff10d9de60c5e009531f1989d05 Mon Sep 17 00:00:00 2001 +From: Yifei Jiang +Date: Mon, 24 Aug 2020 20:25:16 +0800 +Subject: [PATCH 702/709] target/riscv: Handler KVM_EXIT_RISCV_SBI exit + +Use char-fe handler console sbi call, which implement early +console io while apply 'earlycon=sbi' into kernel parameters. + +The common SBI interface sbi_ecall_interface.h is introduced from +https://github.com/riscv/opensbi/blob/master/include/sbi/sbi_ecall_interface.h. + +Signed-off-by: Yifei Jiang +Signed-off-by: Yipeng Yin +--- + target/riscv/kvm.c | 42 ++++++++++++++++- + target/riscv/sbi_ecall_interface.h | 72 ++++++++++++++++++++++++++++++ + 2 files changed, 113 insertions(+), 1 deletion(-) + create mode 100644 target/riscv/sbi_ecall_interface.h + +diff --git a/target/riscv/kvm.c b/target/riscv/kvm.c +index 6460746b2d..d0d02aad5c 100644 +--- a/target/riscv/kvm.c ++++ b/target/riscv/kvm.c +@@ -38,6 +38,8 @@ + #include "qemu/log.h" + #include "hw/loader.h" + #include "kvm_riscv.h" ++#include "sbi_ecall_interface.h" ++#include "chardev/char-fe.h" + + static __u64 kvm_riscv_reg_id(__u64 type, __u64 idx) + { +@@ -423,9 +425,47 @@ bool kvm_arch_stop_on_emulation_error(CPUState *cs) + return true; + } + ++static int kvm_riscv_handle_sbi(struct kvm_run *run) ++{ ++ int ret = 0; ++ unsigned char ch; ++ switch (run->riscv_sbi.extension_id) { ++ case SBI_EXT_0_1_CONSOLE_PUTCHAR: ++ ch = run->riscv_sbi.args[0]; ++ qemu_chr_fe_write(serial_hd(0)->be, &ch, sizeof(ch)); ++ break; ++ case SBI_EXT_0_1_CONSOLE_GETCHAR: ++ ret = qemu_chr_fe_read_all(serial_hd(0)->be, &ch, sizeof(ch)); ++ if (ret == sizeof(ch)) { ++ run->riscv_sbi.args[0] = ch; ++ } else { ++ run->riscv_sbi.args[0] = -1; ++ } ++ break; ++ default: ++ qemu_log_mask(LOG_UNIMP, ++ "%s: un-handled SBI EXIT, specific reasons is %lu\n", ++ __func__, run->riscv_sbi.extension_id); ++ ret = -1; ++ break; ++ } ++ return ret; ++} ++ + int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run) + { +- return 0; ++ int ret = 0; ++ switch (run->exit_reason) { ++ case KVM_EXIT_RISCV_SBI: ++ ret = kvm_riscv_handle_sbi(run); ++ break; ++ default: ++ qemu_log_mask(LOG_UNIMP, "%s: un-handled exit reason %d\n", ++ __func__, run->exit_reason); ++ ret = -1; ++ break; ++ } ++ return ret; + } + + void kvm_riscv_reset_vcpu(RISCVCPU *cpu) +diff --git a/target/riscv/sbi_ecall_interface.h b/target/riscv/sbi_ecall_interface.h +new file mode 100644 +index 0000000000..d8f3cb3ba5 +--- /dev/null ++++ b/target/riscv/sbi_ecall_interface.h +@@ -0,0 +1,72 @@ ++/* ++ * SPDX-License-Identifier: BSD-2-Clause ++ * ++ * Copyright (c) 2019 Western Digital Corporation or its affiliates. ++ * ++ * Authors: ++ * Anup Patel +Date: Fri, 3 Apr 2020 15:54:59 -0700 +Subject: [PATCH 674/709] target/riscv: Implement checks for hfence + +Call the helper_hyp_tlb_flush() function on hfence instructions which +will generate an illegal insruction execption if we don't have +permission to flush the Hypervisor level TLBs. + +Signed-off-by: Alistair Francis +--- + target/riscv/helper.h | 5 ++++ + target/riscv/insn_trans/trans_rvh.inc.c | 32 +++++-------------------- + target/riscv/op_helper.c | 13 ++++++++++ + 3 files changed, 24 insertions(+), 26 deletions(-) + +diff --git a/target/riscv/helper.h b/target/riscv/helper.h +index debb22a480..b36be978d5 100644 +--- a/target/riscv/helper.h ++++ b/target/riscv/helper.h +@@ -76,3 +76,8 @@ DEF_HELPER_2(mret, tl, env, tl) + DEF_HELPER_1(wfi, void, env) + DEF_HELPER_1(tlb_flush, void, env) + #endif ++ ++/* Hypervisor functions */ ++#ifndef CONFIG_USER_ONLY ++DEF_HELPER_1(hyp_tlb_flush, void, env) ++#endif +diff --git a/target/riscv/insn_trans/trans_rvh.inc.c b/target/riscv/insn_trans/trans_rvh.inc.c +index 2c0359819d..263b652d90 100644 +--- a/target/riscv/insn_trans/trans_rvh.inc.c ++++ b/target/riscv/insn_trans/trans_rvh.inc.c +@@ -18,40 +18,20 @@ + + static bool trans_hfence_gvma(DisasContext *ctx, arg_sfence_vma *a) + { ++ REQUIRE_EXT(ctx, RVH); + #ifndef CONFIG_USER_ONLY +- if (ctx->priv_ver >= PRIV_VERSION_1_10_0 && +- has_ext(ctx, RVH)) { +- /* Hpervisor extensions exist */ +- /* +- * if (env->priv == PRV_M || +- * (env->priv == PRV_S && +- * !riscv_cpu_virt_enabled(env) && +- * get_field(ctx->mstatus_fs, MSTATUS_TVM))) { +- */ +- gen_helper_tlb_flush(cpu_env); +- return true; +- /* } */ +- } ++ gen_helper_hyp_tlb_flush(cpu_env); ++ return true; + #endif + return false; + } + + static bool trans_hfence_vvma(DisasContext *ctx, arg_sfence_vma *a) + { ++ REQUIRE_EXT(ctx, RVH); + #ifndef CONFIG_USER_ONLY +- if (ctx->priv_ver >= PRIV_VERSION_1_10_0 && +- has_ext(ctx, RVH)) { +- /* Hpervisor extensions exist */ +- /* +- * if (env->priv == PRV_M || +- * (env->priv == PRV_S && +- * !riscv_cpu_virt_enabled(env) && +- * get_field(ctx->mstatus_fs, MSTATUS_TVM))) { +- */ +- gen_helper_tlb_flush(cpu_env); +- return true; +- /* } */ +- } ++ gen_helper_hyp_tlb_flush(cpu_env); ++ return true; + #endif + return false; + } +diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c +index b0c49efc4a..7cccd42a1e 100644 +--- a/target/riscv/op_helper.c ++++ b/target/riscv/op_helper.c +@@ -194,4 +194,17 @@ void helper_tlb_flush(CPURISCVState *env) + } + } + ++void helper_hyp_tlb_flush(CPURISCVState *env) ++{ ++ CPUState *cs = env_cpu(env); ++ ++ if (env->priv == PRV_M || ++ (env->priv == PRV_S && !riscv_cpu_virt_enabled(env))) { ++ tlb_flush(cs); ++ return; ++ } ++ ++ riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC()); ++} ++ + #endif /* !CONFIG_USER_ONLY */ +-- +2.23.0 + diff --git a/target-riscv-Implement-function-kvm_arch_init_vcpu.patch b/target-riscv-Implement-function-kvm_arch_init_vcpu.patch new file mode 100644 index 0000000000000000000000000000000000000000..d06435f5672f92932e856a471973aa13b1c5d2cb --- /dev/null +++ b/target-riscv-Implement-function-kvm_arch_init_vcpu.patch @@ -0,0 +1,60 @@ +From f933f3a4b5d1a41ce04fd1e22d0347d1012d2b96 Mon Sep 17 00:00:00 2001 +From: Yifei Jiang +Date: Mon, 24 Aug 2020 20:09:46 +0800 +Subject: [PATCH 697/709] target/riscv: Implement function kvm_arch_init_vcpu + +Get isa info from kvm while kvm init. + +Signed-off-by: Yifei Jiang +Signed-off-by: Yipeng Yin +--- + target/riscv/kvm.c | 26 +++++++++++++++++++++++++- + 1 file changed, 25 insertions(+), 1 deletion(-) + +diff --git a/target/riscv/kvm.c b/target/riscv/kvm.c +index 997907dfc9..4ead8c0151 100644 +--- a/target/riscv/kvm.c ++++ b/target/riscv/kvm.c +@@ -38,6 +38,18 @@ + #include "qemu/log.h" + #include "hw/loader.h" + ++static __u64 kvm_riscv_reg_id(__u64 type, __u64 idx) ++{ ++ __u64 id = KVM_REG_RISCV | type | idx; ++ ++#if defined(TARGET_RISCV32) ++ id |= KVM_REG_SIZE_U32; ++#elif defined(TARGET_RISCV64) ++ id |= KVM_REG_SIZE_U64; ++#endif ++ return id; ++} ++ + const KVMCapabilityInfo kvm_arch_required_capabilities[] = { + KVM_CAP_LAST_INFO + }; +@@ -79,7 +91,19 @@ void kvm_arch_init_irq_routing(KVMState *s) + + int kvm_arch_init_vcpu(CPUState *cs) + { +- return 0; ++ int ret = 0; ++ target_ulong isa; ++ RISCVCPU *cpu = RISCV_CPU(cs); ++ __u64 id; ++ ++ id = kvm_riscv_reg_id(KVM_REG_RISCV_CONFIG, KVM_REG_RISCV_CONFIG_REG(isa)); ++ ret = kvm_get_one_reg(cs, id, &isa); ++ if (ret) { ++ return ret; ++ } ++ cpu->env.misa = isa; ++ ++ return ret; + } + + int kvm_arch_msi_data_to_gsi(uint32_t data) +-- +2.23.0 + diff --git a/target-riscv-Implement-kvm_arch_get_registers.patch b/target-riscv-Implement-kvm_arch_get_registers.patch new file mode 100644 index 0000000000000000000000000000000000000000..7d00f251e5d6df3b58753f48c9f92a72fe8de748 --- /dev/null +++ b/target-riscv-Implement-kvm_arch_get_registers.patch @@ -0,0 +1,177 @@ +From 08f53a38ff3e319943cf49a88360994a8ef7c988 Mon Sep 17 00:00:00 2001 +From: Yifei Jiang +Date: Mon, 24 Aug 2020 20:09:59 +0800 +Subject: [PATCH 698/709] target/riscv: Implement kvm_arch_get_registers + +Get GPR CSR and FP registers from kvm by KVM_GET_ONE_REG ioctl. + +Signed-off-by: Yifei Jiang +Signed-off-by: Yipeng Yin +--- + target/riscv/kvm.c | 144 ++++++++++++++++++++++++++++++++++++++++++++- + 1 file changed, 143 insertions(+), 1 deletion(-) + +diff --git a/target/riscv/kvm.c b/target/riscv/kvm.c +index 4ead8c0151..5ec2bb99ba 100644 +--- a/target/riscv/kvm.c ++++ b/target/riscv/kvm.c +@@ -50,13 +50,155 @@ static __u64 kvm_riscv_reg_id(__u64 type, __u64 idx) + return id; + } + ++#define RISCV_CORE_REG(name) kvm_riscv_reg_id(KVM_REG_RISCV_CORE, \ ++ KVM_REG_RISCV_CORE_REG(name)) ++ ++#define RISCV_CSR_REG(name) kvm_riscv_reg_id(KVM_REG_RISCV_CSR, \ ++ KVM_REG_RISCV_CSR_REG(name)) ++ ++#define RISCV_FP_F_REG(idx) kvm_riscv_reg_id(KVM_REG_RISCV_FP_F, idx) ++ ++#define RISCV_FP_D_REG(idx) kvm_riscv_reg_id(KVM_REG_RISCV_FP_D, idx) ++ ++static int kvm_riscv_get_regs_core(CPUState *cs) ++{ ++ int ret = 0; ++ int i; ++ target_ulong reg; ++ CPURISCVState *env = &RISCV_CPU(cs)->env; ++ ++ ret = kvm_get_one_reg(cs, RISCV_CORE_REG(regs.pc), ®); ++ if (ret) { ++ return ret; ++ } ++ env->pc = reg; ++ ++ for (i = 1; i < 32; i++) { ++ __u64 id = kvm_riscv_reg_id(KVM_REG_RISCV_CORE, i); ++ ret = kvm_get_one_reg(cs, id, ®); ++ if (ret) { ++ return ret; ++ } ++ env->gpr[i] = reg; ++ } ++ ++ return ret; ++} ++ ++static int kvm_riscv_get_regs_csr(CPUState *cs) ++{ ++ int ret = 0; ++ target_ulong reg; ++ CPURISCVState *env = &RISCV_CPU(cs)->env; ++ ++ ret = kvm_get_one_reg(cs, RISCV_CSR_REG(sstatus), ®); ++ if (ret) { ++ return ret; ++ } ++ env->mstatus = reg; ++ ++ ret = kvm_get_one_reg(cs, RISCV_CSR_REG(sie), ®); ++ if (ret) { ++ return ret; ++ } ++ env->mie = reg; ++ ++ ret = kvm_get_one_reg(cs, RISCV_CSR_REG(stvec), ®); ++ if (ret) { ++ return ret; ++ } ++ env->stvec = reg; ++ ++ ret = kvm_get_one_reg(cs, RISCV_CSR_REG(sscratch), ®); ++ if (ret) { ++ return ret; ++ } ++ env->sscratch = reg; ++ ++ ret = kvm_get_one_reg(cs, RISCV_CSR_REG(sepc), ®); ++ if (ret) { ++ return ret; ++ } ++ env->sepc = reg; ++ ++ ret = kvm_get_one_reg(cs, RISCV_CSR_REG(scause), ®); ++ if (ret) { ++ return ret; ++ } ++ env->scause = reg; ++ ++ ret = kvm_get_one_reg(cs, RISCV_CSR_REG(sip), ®); ++ if (ret) { ++ return ret; ++ } ++ env->mip = reg; ++ ++ ret = kvm_get_one_reg(cs, RISCV_CSR_REG(satp), ®); ++ if (ret) { ++ return ret; ++ } ++ env->satp = reg; ++ ++ return ret; ++} ++ ++static int kvm_riscv_get_regs_fp(CPUState *cs) ++{ ++ int ret = 0; ++ int i; ++ CPURISCVState *env = &RISCV_CPU(cs)->env; ++ ++ if (riscv_has_ext(env, RVD)) { ++ uint64_t reg; ++ for (i = 0; i < 32; i++) { ++ ret = kvm_get_one_reg(cs, RISCV_FP_D_REG(i), ®); ++ if (ret) { ++ return ret; ++ } ++ env->fpr[i] = reg; ++ } ++ return ret; ++ } ++ ++ if (riscv_has_ext(env, RVF)) { ++ uint32_t reg; ++ for (i = 0; i < 32; i++) { ++ ret = kvm_get_one_reg(cs, RISCV_FP_F_REG(i), ®); ++ if (ret) { ++ return ret; ++ } ++ env->fpr[i] = reg; ++ } ++ return ret; ++ } ++ ++ return ret; ++} ++ + const KVMCapabilityInfo kvm_arch_required_capabilities[] = { + KVM_CAP_LAST_INFO + }; + + int kvm_arch_get_registers(CPUState *cs) + { +- return 0; ++ int ret = 0; ++ ++ ret = kvm_riscv_get_regs_core(cs); ++ if (ret) { ++ return ret; ++ } ++ ++ ret = kvm_riscv_get_regs_csr(cs); ++ if (ret) { ++ return ret; ++ } ++ ++ ret = kvm_riscv_get_regs_fp(cs); ++ if (ret) { ++ return ret; ++ } ++ ++ return ret; + } + + int kvm_arch_put_registers(CPUState *cs, int level) +-- +2.23.0 + diff --git a/target-riscv-Implement-kvm_arch_put_registers.patch b/target-riscv-Implement-kvm_arch_put_registers.patch new file mode 100644 index 0000000000000000000000000000000000000000..49d6a48153384fa4b61ed73d16a8758b8e7bc897 --- /dev/null +++ b/target-riscv-Implement-kvm_arch_put_registers.patch @@ -0,0 +1,184 @@ +From e4e6aac0930a4b8eb7b73dc2a1f85ab07390a8b5 Mon Sep 17 00:00:00 2001 +From: Yifei Jiang +Date: Mon, 24 Aug 2020 20:10:09 +0800 +Subject: [PATCH 699/709] target/riscv: Implement kvm_arch_put_registers + +Put GPR CSR and FP registers to kvm by KVM_SET_ONE_REG ioctl + +Signed-off-by: Yifei Jiang +Signed-off-by: Yipeng Yin +--- + target/riscv/kvm.c | 136 ++++++++++++++++++++++++++++++++++++++++++++- + 1 file changed, 135 insertions(+), 1 deletion(-) + +diff --git a/target/riscv/kvm.c b/target/riscv/kvm.c +index 5ec2bb99ba..9810a02b49 100644 +--- a/target/riscv/kvm.c ++++ b/target/riscv/kvm.c +@@ -85,6 +85,31 @@ static int kvm_riscv_get_regs_core(CPUState *cs) + return ret; + } + ++static int kvm_riscv_put_regs_core(CPUState *cs) ++{ ++ int ret = 0; ++ int i; ++ target_ulong reg; ++ CPURISCVState *env = &RISCV_CPU(cs)->env; ++ ++ reg = env->pc; ++ ret = kvm_set_one_reg(cs, RISCV_CORE_REG(regs.pc), ®); ++ if (ret) { ++ return ret; ++ } ++ ++ for (i = 1; i < 32; i++) { ++ __u64 id = kvm_riscv_reg_id(KVM_REG_RISCV_CORE, i); ++ reg = env->gpr[i]; ++ ret = kvm_set_one_reg(cs, id, ®); ++ if (ret) { ++ return ret; ++ } ++ } ++ ++ return ret; ++} ++ + static int kvm_riscv_get_regs_csr(CPUState *cs) + { + int ret = 0; +@@ -142,6 +167,64 @@ static int kvm_riscv_get_regs_csr(CPUState *cs) + return ret; + } + ++static int kvm_riscv_put_regs_csr(CPUState *cs) ++{ ++ int ret = 0; ++ target_ulong reg; ++ CPURISCVState *env = &RISCV_CPU(cs)->env; ++ ++ reg = env->mstatus; ++ ret = kvm_set_one_reg(cs, RISCV_CSR_REG(sstatus), ®); ++ if (ret) { ++ return ret; ++ } ++ ++ reg = env->mie; ++ ret = kvm_set_one_reg(cs, RISCV_CSR_REG(sie), ®); ++ if (ret) { ++ return ret; ++ } ++ ++ reg = env->stvec; ++ ret = kvm_set_one_reg(cs, RISCV_CSR_REG(stvec), ®); ++ if (ret) { ++ return ret; ++ } ++ ++ reg = env->sscratch; ++ ret = kvm_set_one_reg(cs, RISCV_CSR_REG(sscratch), ®); ++ if (ret) { ++ return ret; ++ } ++ ++ reg = env->sepc; ++ ret = kvm_set_one_reg(cs, RISCV_CSR_REG(sepc), ®); ++ if (ret) { ++ return ret; ++ } ++ ++ reg = env->scause; ++ ret = kvm_set_one_reg(cs, RISCV_CSR_REG(scause), ®); ++ if (ret) { ++ return ret; ++ } ++ ++ reg = env->mip; ++ ret = kvm_set_one_reg(cs, RISCV_CSR_REG(sip), ®); ++ if (ret) { ++ return ret; ++ } ++ ++ reg = env->satp; ++ ret = kvm_set_one_reg(cs, RISCV_CSR_REG(satp), ®); ++ if (ret) { ++ return ret; ++ } ++ ++ return ret; ++} ++ ++ + static int kvm_riscv_get_regs_fp(CPUState *cs) + { + int ret = 0; +@@ -175,6 +258,40 @@ static int kvm_riscv_get_regs_fp(CPUState *cs) + return ret; + } + ++static int kvm_riscv_put_regs_fp(CPUState *cs) ++{ ++ int ret = 0; ++ int i; ++ CPURISCVState *env = &RISCV_CPU(cs)->env; ++ ++ if (riscv_has_ext(env, RVD)) { ++ uint64_t reg; ++ for (i = 0; i < 32; i++) { ++ reg = env->fpr[i]; ++ ret = kvm_set_one_reg(cs, RISCV_FP_D_REG(i), ®); ++ if (ret) { ++ return ret; ++ } ++ } ++ return ret; ++ } ++ ++ if (riscv_has_ext(env, RVF)) { ++ uint32_t reg; ++ for (i = 0; i < 32; i++) { ++ reg = env->fpr[i]; ++ ret = kvm_set_one_reg(cs, RISCV_FP_F_REG(i), ®); ++ if (ret) { ++ return ret; ++ } ++ } ++ return ret; ++ } ++ ++ return ret; ++} ++ ++ + const KVMCapabilityInfo kvm_arch_required_capabilities[] = { + KVM_CAP_LAST_INFO + }; +@@ -203,7 +320,24 @@ int kvm_arch_get_registers(CPUState *cs) + + int kvm_arch_put_registers(CPUState *cs, int level) + { +- return 0; ++ int ret = 0; ++ ++ ret = kvm_riscv_put_regs_core(cs); ++ if (ret) { ++ return ret; ++ } ++ ++ ret = kvm_riscv_put_regs_csr(cs); ++ if (ret) { ++ return ret; ++ } ++ ++ ret = kvm_riscv_put_regs_fp(cs); ++ if (ret) { ++ return ret; ++ } ++ ++ return ret; + } + + int kvm_arch_release_virq_post(int virq) +-- +2.23.0 + diff --git a/target-riscv-Implement-virtual-time-adjusting-with-v.patch b/target-riscv-Implement-virtual-time-adjusting-with-v.patch new file mode 100644 index 0000000000000000000000000000000000000000..fc2c79942766e20c80532a93f12302a3c76bbdc0 --- /dev/null +++ b/target-riscv-Implement-virtual-time-adjusting-with-v.patch @@ -0,0 +1,59 @@ +From c49c21386ea36d130eeae7723baab373532764ab Mon Sep 17 00:00:00 2001 +From: Yifei Jiang +Date: Thu, 27 Aug 2020 10:21:46 +0800 +Subject: [PATCH 708/709] target/riscv: Implement virtual time adjusting with + vm state changing + +We hope that virtual time adjusts with vm state changing. When a vm +is stopped, guest virtual time should stop counting and kvm_timer +should be stopped. When the vm is resumed, guest virtual time should +continue to count and kvm_timer should be restored. + +Signed-off-by: Yifei Jiang +Signed-off-by: Yipeng Yin +--- + target/riscv/kvm.c | 14 ++++++++++++++ + 1 file changed, 14 insertions(+) + +diff --git a/target/riscv/kvm.c b/target/riscv/kvm.c +index 7466787d79..0ab5de43d3 100644 +--- a/target/riscv/kvm.c ++++ b/target/riscv/kvm.c +@@ -40,6 +40,7 @@ + #include "kvm_riscv.h" + #include "sbi_ecall_interface.h" + #include "chardev/char-fe.h" ++#include "sysemu/runstate.h" + + static __u64 kvm_riscv_reg_id(__u64 type, __u64 idx) + { +@@ -436,6 +437,17 @@ unsigned long kvm_arch_vcpu_id(CPUState *cpu) + return cpu->cpu_index; + } + ++static void kvm_riscv_vm_state_change(void *opaque, int running, RunState state) ++{ ++ CPUState *cs = opaque; ++ ++ if (running) { ++ kvm_riscv_put_regs_timer(cs); ++ } else { ++ kvm_riscv_get_regs_timer(cs); ++ } ++} ++ + void kvm_arch_init_irq_routing(KVMState *s) + { + } +@@ -447,6 +459,8 @@ int kvm_arch_init_vcpu(CPUState *cs) + RISCVCPU *cpu = RISCV_CPU(cs); + __u64 id; + ++ qemu_add_vm_change_state_handler(kvm_riscv_vm_state_change, cs); ++ + id = kvm_riscv_reg_id(KVM_REG_RISCV_CONFIG, KVM_REG_RISCV_CONFIG_REG(isa)); + ret = kvm_get_one_reg(cs, id, &isa); + if (ret) { +-- +2.23.0 + diff --git a/target-riscv-Move-the-hfence-instructions-to-the-rvh.patch b/target-riscv-Move-the-hfence-instructions-to-the-rvh.patch new file mode 100644 index 0000000000000000000000000000000000000000..5b3e3813ff38eb70b624f3d8463ba6883c2081f0 --- /dev/null +++ b/target-riscv-Move-the-hfence-instructions-to-the-rvh.patch @@ -0,0 +1,171 @@ +From b93340857e1eff346fe181426736f66054d596c4 Mon Sep 17 00:00:00 2001 +From: Alistair Francis +Date: Fri, 3 Apr 2020 14:05:01 -0700 +Subject: [PATCH 673/709] target/riscv: Move the hfence instructions to the rvh + decode + +Also correct the name of the VVMA instruction. + +Signed-off-by: Alistair Francis +--- + target/riscv/insn32.decode | 8 ++- + .../riscv/insn_trans/trans_privileged.inc.c | 38 ------------- + target/riscv/insn_trans/trans_rvh.inc.c | 57 +++++++++++++++++++ + target/riscv/translate.c | 1 + + 4 files changed, 63 insertions(+), 41 deletions(-) + create mode 100644 target/riscv/insn_trans/trans_rvh.inc.c + +diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode +index b883672e63..4c8d1215ce 100644 +--- a/target/riscv/insn32.decode ++++ b/target/riscv/insn32.decode +@@ -64,7 +64,7 @@ + @r2 ....... ..... ..... ... ..... ....... %rs1 %rd + + @hfence_gvma ....... ..... ..... ... ..... ....... %rs2 %rs1 +-@hfence_bvma ....... ..... ..... ... ..... ....... %rs2 %rs1 ++@hfence_vvma ....... ..... ..... ... ..... ....... %rs2 %rs1 + + @sfence_vma ....... ..... ..... ... ..... ....... %rs2 %rs1 + @sfence_vm ....... ..... ..... ... ..... ....... %rs1 +@@ -77,8 +77,6 @@ uret 0000000 00010 00000 000 00000 1110011 + sret 0001000 00010 00000 000 00000 1110011 + mret 0011000 00010 00000 000 00000 1110011 + wfi 0001000 00101 00000 000 00000 1110011 +-hfence_gvma 0110001 ..... ..... 000 00000 1110011 @hfence_gvma +-hfence_bvma 0010001 ..... ..... 000 00000 1110011 @hfence_bvma + sfence_vma 0001001 ..... ..... 000 00000 1110011 @sfence_vma + sfence_vm 0001000 00100 ..... 000 00000 1110011 @sfence_vm + +@@ -207,3 +205,7 @@ fcvt_w_d 1100001 00000 ..... ... ..... 1010011 @r2_rm + fcvt_wu_d 1100001 00001 ..... ... ..... 1010011 @r2_rm + fcvt_d_w 1101001 00000 ..... ... ..... 1010011 @r2_rm + fcvt_d_wu 1101001 00001 ..... ... ..... 1010011 @r2_rm ++ ++# *** RV32H Base Instruction Set *** ++hfence_gvma 0110001 ..... ..... 000 00000 1110011 @hfence_gvma ++hfence_vvma 0010001 ..... ..... 000 00000 1110011 @hfence_vvma +diff --git a/target/riscv/insn_trans/trans_privileged.inc.c b/target/riscv/insn_trans/trans_privileged.inc.c +index 5f26e0f5ea..2a61a853bf 100644 +--- a/target/riscv/insn_trans/trans_privileged.inc.c ++++ b/target/riscv/insn_trans/trans_privileged.inc.c +@@ -95,41 +95,3 @@ static bool trans_sfence_vm(DisasContext *ctx, arg_sfence_vm *a) + { + return false; + } +- +-static bool trans_hfence_gvma(DisasContext *ctx, arg_sfence_vma *a) +-{ +-#ifndef CONFIG_USER_ONLY +- if (has_ext(ctx, RVH)) { +- /* Hpervisor extensions exist */ +- /* +- * if (env->priv == PRV_M || +- * (env->priv == PRV_S && +- * !riscv_cpu_virt_enabled(env) && +- * get_field(ctx->mstatus_fs, MSTATUS_TVM))) { +- */ +- gen_helper_tlb_flush(cpu_env); +- return true; +- /* } */ +- } +-#endif +- return false; +-} +- +-static bool trans_hfence_bvma(DisasContext *ctx, arg_sfence_vma *a) +-{ +-#ifndef CONFIG_USER_ONLY +- if (has_ext(ctx, RVH)) { +- /* Hpervisor extensions exist */ +- /* +- * if (env->priv == PRV_M || +- * (env->priv == PRV_S && +- * !riscv_cpu_virt_enabled(env) && +- * get_field(ctx->mstatus_fs, MSTATUS_TVM))) { +- */ +- gen_helper_tlb_flush(cpu_env); +- return true; +- /* } */ +- } +-#endif +- return false; +-} +diff --git a/target/riscv/insn_trans/trans_rvh.inc.c b/target/riscv/insn_trans/trans_rvh.inc.c +new file mode 100644 +index 0000000000..2c0359819d +--- /dev/null ++++ b/target/riscv/insn_trans/trans_rvh.inc.c +@@ -0,0 +1,57 @@ ++/* ++ * RISC-V translation routines for the RVXI Base Integer Instruction Set. ++ * ++ * Copyright (c) 2020 Western Digital ++ * ++ * 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 . ++ */ ++ ++static bool trans_hfence_gvma(DisasContext *ctx, arg_sfence_vma *a) ++{ ++#ifndef CONFIG_USER_ONLY ++ if (ctx->priv_ver >= PRIV_VERSION_1_10_0 && ++ has_ext(ctx, RVH)) { ++ /* Hpervisor extensions exist */ ++ /* ++ * if (env->priv == PRV_M || ++ * (env->priv == PRV_S && ++ * !riscv_cpu_virt_enabled(env) && ++ * get_field(ctx->mstatus_fs, MSTATUS_TVM))) { ++ */ ++ gen_helper_tlb_flush(cpu_env); ++ return true; ++ /* } */ ++ } ++#endif ++ return false; ++} ++ ++static bool trans_hfence_vvma(DisasContext *ctx, arg_sfence_vma *a) ++{ ++#ifndef CONFIG_USER_ONLY ++ if (ctx->priv_ver >= PRIV_VERSION_1_10_0 && ++ has_ext(ctx, RVH)) { ++ /* Hpervisor extensions exist */ ++ /* ++ * if (env->priv == PRV_M || ++ * (env->priv == PRV_S && ++ * !riscv_cpu_virt_enabled(env) && ++ * get_field(ctx->mstatus_fs, MSTATUS_TVM))) { ++ */ ++ gen_helper_tlb_flush(cpu_env); ++ return true; ++ /* } */ ++ } ++#endif ++ return false; ++} +diff --git a/target/riscv/translate.c b/target/riscv/translate.c +index 43bf7e39a6..ce71ca7a92 100644 +--- a/target/riscv/translate.c ++++ b/target/riscv/translate.c +@@ -711,6 +711,7 @@ static bool gen_shift(DisasContext *ctx, arg_r *a, + #include "insn_trans/trans_rva.inc.c" + #include "insn_trans/trans_rvf.inc.c" + #include "insn_trans/trans_rvd.inc.c" ++#include "insn_trans/trans_rvh.inc.c" + #include "insn_trans/trans_privileged.inc.c" + + /* Include the auto-generated decoder for 16 bit insn */ +-- +2.23.0 + diff --git a/target-riscv-Only-support-a-single-VSXL-length.patch b/target-riscv-Only-support-a-single-VSXL-length.patch new file mode 100644 index 0000000000000000000000000000000000000000..ff29d8b51908291567779883f6cd261c828826c4 --- /dev/null +++ b/target-riscv-Only-support-a-single-VSXL-length.patch @@ -0,0 +1,39 @@ +From 715b9c1849d4deffe9723535acb2943987ebf175 Mon Sep 17 00:00:00 2001 +From: Alistair Francis +Date: Mon, 6 Apr 2020 13:53:47 -0700 +Subject: [PATCH 683/709] target/riscv: Only support a single VSXL length + +Signed-off-by: Alistair Francis +--- + target/riscv/csr.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/target/riscv/csr.c b/target/riscv/csr.c +index 69a3c8379c..973404d0aa 100644 +--- a/target/riscv/csr.c ++++ b/target/riscv/csr.c +@@ -768,12 +768,21 @@ static int write_satp(CPURISCVState *env, int csrno, target_ulong val) + static int read_hstatus(CPURISCVState *env, int csrno, target_ulong *val) + { + *val = env->hstatus; ++#ifdef TARGET_RISCV64 ++ /* We only support 64-bit VSXL */ ++ *val = set_field(*val, HSTATUS_VSXL, 2); ++#endif + return 0; + } + + static int write_hstatus(CPURISCVState *env, int csrno, target_ulong val) + { + env->hstatus = val; ++#ifdef TARGET_RISCV64 ++ if (get_field(val, HSTATUS_VSXL) != 2) { ++ qemu_log_mask(LOG_UNIMP, "QEMU does not support mixed HSXLEN options."); ++ } ++#endif + return 0; + } + +-- +2.23.0 + diff --git a/target-riscv-Only-support-little-endian-guests.patch b/target-riscv-Only-support-little-endian-guests.patch new file mode 100644 index 0000000000000000000000000000000000000000..039bbcb9d897db74515f73fcf1e578d7a38ca476 --- /dev/null +++ b/target-riscv-Only-support-little-endian-guests.patch @@ -0,0 +1,36 @@ +From d20ab804f1ff8f1dca2390d6c245c5219c39b696 Mon Sep 17 00:00:00 2001 +From: Alistair Francis +Date: Mon, 6 Apr 2020 14:14:36 -0700 +Subject: [PATCH 684/709] target/riscv: Only support little endian guests + +Signed-off-by: Alistair Francis +--- + target/riscv/csr.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/target/riscv/csr.c b/target/riscv/csr.c +index 973404d0aa..5b64539efb 100644 +--- a/target/riscv/csr.c ++++ b/target/riscv/csr.c +@@ -772,6 +772,8 @@ static int read_hstatus(CPURISCVState *env, int csrno, target_ulong *val) + /* We only support 64-bit VSXL */ + *val = set_field(*val, HSTATUS_VSXL, 2); + #endif ++ /* We only support little endian */ ++ *val = set_field(*val, HSTATUS_VSBE, 0); + return 0; + } + +@@ -783,6 +785,9 @@ static int write_hstatus(CPURISCVState *env, int csrno, target_ulong val) + qemu_log_mask(LOG_UNIMP, "QEMU does not support mixed HSXLEN options."); + } + #endif ++ if (get_field(val, HSTATUS_VSBE) != 0) { ++ qemu_log_mask(LOG_UNIMP, "QEMU does not support big endian guests."); ++ } + return 0; + } + +-- +2.23.0 + diff --git a/target-riscv-Remove-the-deprecated-CPUs.patch b/target-riscv-Remove-the-deprecated-CPUs.patch new file mode 100644 index 0000000000000000000000000000000000000000..c3e030451670f9c2fed29b914351bbf15a15f692 --- /dev/null +++ b/target-riscv-Remove-the-deprecated-CPUs.patch @@ -0,0 +1,106 @@ +From b6e3a0c4df58bc6800808dac0ccbb64e8628c4d2 Mon Sep 17 00:00:00 2001 +From: Alistair Francis +Date: Wed, 6 May 2020 13:03:25 -0700 +Subject: [PATCH 668/709] target/riscv: Remove the deprecated CPUs + +Signed-off-by: Alistair Francis +Reviewed-by: Bin Meng +--- + target/riscv/cpu.c | 28 ---------------------------- + target/riscv/cpu.h | 7 ------- + tests/qtest/machine-none-test.c | 4 ++-- + 3 files changed, 2 insertions(+), 37 deletions(-) + +diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c +index 059d71f2c7..112f2e3a2f 100644 +--- a/target/riscv/cpu.c ++++ b/target/riscv/cpu.c +@@ -135,16 +135,6 @@ static void riscv_base32_cpu_init(Object *obj) + set_misa(env, 0); + } + +-static void rv32gcsu_priv1_09_1_cpu_init(Object *obj) +-{ +- CPURISCVState *env = &RISCV_CPU(obj)->env; +- set_misa(env, RV32 | RVI | RVM | RVA | RVF | RVD | RVC | RVS | RVU); +- set_priv_version(env, PRIV_VERSION_1_09_1); +- set_resetvec(env, DEFAULT_RSTVEC); +- set_feature(env, RISCV_FEATURE_MMU); +- set_feature(env, RISCV_FEATURE_PMP); +-} +- + static void rv32gcsu_priv1_10_0_cpu_init(Object *obj) + { + CPURISCVState *env = &RISCV_CPU(obj)->env; +@@ -182,16 +172,6 @@ static void riscv_base64_cpu_init(Object *obj) + set_misa(env, 0); + } + +-static void rv64gcsu_priv1_09_1_cpu_init(Object *obj) +-{ +- CPURISCVState *env = &RISCV_CPU(obj)->env; +- set_misa(env, RV64 | RVI | RVM | RVA | RVF | RVD | RVC | RVS | RVU); +- set_priv_version(env, PRIV_VERSION_1_09_1); +- set_resetvec(env, DEFAULT_RSTVEC); +- set_feature(env, RISCV_FEATURE_MMU); +- set_feature(env, RISCV_FEATURE_PMP); +-} +- + static void rv64gcsu_priv1_10_0_cpu_init(Object *obj) + { + CPURISCVState *env = &RISCV_CPU(obj)->env; +@@ -621,18 +601,10 @@ static const TypeInfo riscv_cpu_type_infos[] = { + DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_E31, rv32imacu_nommu_cpu_init), + DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_E34, rv32imafcu_nommu_cpu_init), + DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_U34, rv32gcsu_priv1_10_0_cpu_init), +- /* Depreacted */ +- DEFINE_CPU(TYPE_RISCV_CPU_RV32IMACU_NOMMU, rv32imacu_nommu_cpu_init), +- DEFINE_CPU(TYPE_RISCV_CPU_RV32GCSU_V1_09_1, rv32gcsu_priv1_09_1_cpu_init), +- DEFINE_CPU(TYPE_RISCV_CPU_RV32GCSU_V1_10_0, rv32gcsu_priv1_10_0_cpu_init) + #elif defined(TARGET_RISCV64) + DEFINE_CPU(TYPE_RISCV_CPU_BASE64, riscv_base64_cpu_init), + DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_E51, rv64imacu_nommu_cpu_init), + DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_U54, rv64gcsu_priv1_10_0_cpu_init), +- /* Deprecated */ +- DEFINE_CPU(TYPE_RISCV_CPU_RV64IMACU_NOMMU, rv64imacu_nommu_cpu_init), +- DEFINE_CPU(TYPE_RISCV_CPU_RV64GCSU_V1_09_1, rv64gcsu_priv1_09_1_cpu_init), +- DEFINE_CPU(TYPE_RISCV_CPU_RV64GCSU_V1_10_0, rv64gcsu_priv1_10_0_cpu_init) + #endif + }; + +diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h +index d0e7f5b9c5..76b98d7a33 100644 +--- a/target/riscv/cpu.h ++++ b/target/riscv/cpu.h +@@ -40,13 +40,6 @@ + #define TYPE_RISCV_CPU_SIFIVE_E51 RISCV_CPU_TYPE_NAME("sifive-e51") + #define TYPE_RISCV_CPU_SIFIVE_U34 RISCV_CPU_TYPE_NAME("sifive-u34") + #define TYPE_RISCV_CPU_SIFIVE_U54 RISCV_CPU_TYPE_NAME("sifive-u54") +-/* Deprecated */ +-#define TYPE_RISCV_CPU_RV32IMACU_NOMMU RISCV_CPU_TYPE_NAME("rv32imacu-nommu") +-#define TYPE_RISCV_CPU_RV32GCSU_V1_09_1 RISCV_CPU_TYPE_NAME("rv32gcsu-v1.9.1") +-#define TYPE_RISCV_CPU_RV32GCSU_V1_10_0 RISCV_CPU_TYPE_NAME("rv32gcsu-v1.10.0") +-#define TYPE_RISCV_CPU_RV64IMACU_NOMMU RISCV_CPU_TYPE_NAME("rv64imacu-nommu") +-#define TYPE_RISCV_CPU_RV64GCSU_V1_09_1 RISCV_CPU_TYPE_NAME("rv64gcsu-v1.9.1") +-#define TYPE_RISCV_CPU_RV64GCSU_V1_10_0 RISCV_CPU_TYPE_NAME("rv64gcsu-v1.10.0") + + #define RV32 ((target_ulong)1 << (TARGET_LONG_BITS - 2)) + #define RV64 ((target_ulong)2 << (TARGET_LONG_BITS - 2)) +diff --git a/tests/qtest/machine-none-test.c b/tests/qtest/machine-none-test.c +index 8bb54a6360..b52311ec2e 100644 +--- a/tests/qtest/machine-none-test.c ++++ b/tests/qtest/machine-none-test.c +@@ -54,8 +54,8 @@ static struct arch2cpu cpus_map[] = { + { "xtensa", "dc233c" }, + { "xtensaeb", "fsf" }, + { "hppa", "hppa" }, +- { "riscv64", "rv64gcsu-v1.10.0" }, +- { "riscv32", "rv32gcsu-v1.9.1" }, ++ { "riscv64", "sifive-u54" }, ++ { "riscv32", "sifive-u34" }, + { "rx", "rx62n" }, + }; + +-- +2.23.0 + diff --git a/target-riscv-Report-errors-validating-2nd-stage-PTEs.patch b/target-riscv-Report-errors-validating-2nd-stage-PTEs.patch new file mode 100644 index 0000000000000000000000000000000000000000..98777edf7e25ef4d47eb4747878f01e822ffd224 --- /dev/null +++ b/target-riscv-Report-errors-validating-2nd-stage-PTEs.patch @@ -0,0 +1,33 @@ +From 240dcfea8b1afff563709fb22b2a6c7e6906a876 Mon Sep 17 00:00:00 2001 +From: Alistair Francis +Date: Fri, 27 Mar 2020 12:54:45 -0700 +Subject: [PATCH 672/709] target/riscv: Report errors validating 2nd-stage PTEs + +Signed-off-by: Alistair Francis +--- + target/riscv/cpu_helper.c | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c +index eda7057663..75d2ae3434 100644 +--- a/target/riscv/cpu_helper.c ++++ b/target/riscv/cpu_helper.c +@@ -435,8 +435,13 @@ restart: + hwaddr vbase; + + /* Do the second stage translation on the base PTE address. */ +- get_physical_address(env, &vbase, &vbase_prot, base, MMU_DATA_LOAD, +- mmu_idx, false, true); ++ int vbase_ret = get_physical_address(env, &vbase, &vbase_prot, ++ base, MMU_DATA_LOAD, ++ mmu_idx, false, true); ++ ++ if (vbase_ret != TRANSLATE_SUCCESS) { ++ return vbase_ret; ++ } + + pte_addr = vbase + idx * ptesize; + } else { +-- +2.23.0 + diff --git a/target-riscv-Return-the-exception-from-invalid-CSR-a.patch b/target-riscv-Return-the-exception-from-invalid-CSR-a.patch new file mode 100644 index 0000000000000000000000000000000000000000..2cf134eb1f95f8ad2167e369f420462e734f032c --- /dev/null +++ b/target-riscv-Return-the-exception-from-invalid-CSR-a.patch @@ -0,0 +1,268 @@ +From 7ec9b0ec20d8af5a100ff3012f6ebceb6bfacb71 Mon Sep 17 00:00:00 2001 +From: Alistair Francis +Date: Wed, 27 May 2020 15:44:37 -0700 +Subject: [PATCH 686/709] target/riscv: Return the exception from invalid CSR + accesses + +When performing a CSR access let's return a negative exception value on +an error instead of -1. This will allow us to specify the exception in +future patches. + +Signed-off-by: Alistair Francis +--- + target/riscv/csr.c | 46 ++++++++++++++++++++-------------------- + target/riscv/op_helper.c | 18 ++++++++++------ + 2 files changed, 35 insertions(+), 29 deletions(-) + +diff --git a/target/riscv/csr.c b/target/riscv/csr.c +index 9990a0dd09..0c53438605 100644 +--- a/target/riscv/csr.c ++++ b/target/riscv/csr.c +@@ -47,7 +47,7 @@ static int fs(CPURISCVState *env, int csrno) + { + #if !defined(CONFIG_USER_ONLY) + if (!env->debugger && !riscv_cpu_fp_enabled(env)) { +- return -1; ++ return -RISCV_EXCP_ILLEGAL_INST; + } + #endif + return 0; +@@ -61,7 +61,7 @@ static int ctr(CPURISCVState *env, int csrno) + + if (!cpu->cfg.ext_counters) { + /* The Counters extensions is not enabled */ +- return -1; ++ return -RISCV_EXCP_ILLEGAL_INST; + } + #endif + return 0; +@@ -89,7 +89,7 @@ static int hmode(CPURISCVState *env, int csrno) + } + } + +- return -1; ++ return -RISCV_EXCP_ILLEGAL_INST; + } + + static int pmp(CPURISCVState *env, int csrno) +@@ -103,7 +103,7 @@ static int read_fflags(CPURISCVState *env, int csrno, target_ulong *val) + { + #if !defined(CONFIG_USER_ONLY) + if (!env->debugger && !riscv_cpu_fp_enabled(env)) { +- return -1; ++ return -RISCV_EXCP_ILLEGAL_INST; + } + #endif + *val = riscv_cpu_get_fflags(env); +@@ -114,7 +114,7 @@ static int write_fflags(CPURISCVState *env, int csrno, target_ulong val) + { + #if !defined(CONFIG_USER_ONLY) + if (!env->debugger && !riscv_cpu_fp_enabled(env)) { +- return -1; ++ return -RISCV_EXCP_ILLEGAL_INST; + } + env->mstatus |= MSTATUS_FS; + #endif +@@ -126,7 +126,7 @@ static int read_frm(CPURISCVState *env, int csrno, target_ulong *val) + { + #if !defined(CONFIG_USER_ONLY) + if (!env->debugger && !riscv_cpu_fp_enabled(env)) { +- return -1; ++ return -RISCV_EXCP_ILLEGAL_INST; + } + #endif + *val = env->frm; +@@ -137,7 +137,7 @@ static int write_frm(CPURISCVState *env, int csrno, target_ulong val) + { + #if !defined(CONFIG_USER_ONLY) + if (!env->debugger && !riscv_cpu_fp_enabled(env)) { +- return -1; ++ return -RISCV_EXCP_ILLEGAL_INST; + } + env->mstatus |= MSTATUS_FS; + #endif +@@ -149,7 +149,7 @@ static int read_fcsr(CPURISCVState *env, int csrno, target_ulong *val) + { + #if !defined(CONFIG_USER_ONLY) + if (!env->debugger && !riscv_cpu_fp_enabled(env)) { +- return -1; ++ return -RISCV_EXCP_ILLEGAL_INST; + } + #endif + *val = (riscv_cpu_get_fflags(env) << FSR_AEXC_SHIFT) +@@ -161,7 +161,7 @@ static int write_fcsr(CPURISCVState *env, int csrno, target_ulong val) + { + #if !defined(CONFIG_USER_ONLY) + if (!env->debugger && !riscv_cpu_fp_enabled(env)) { +- return -1; ++ return -RISCV_EXCP_ILLEGAL_INST; + } + env->mstatus |= MSTATUS_FS; + #endif +@@ -223,7 +223,7 @@ static int read_time(CPURISCVState *env, int csrno, target_ulong *val) + uint64_t delta = riscv_cpu_virt_enabled(env) ? env->htimedelta : 0; + + if (!env->rdtime_fn) { +- return -1; ++ return -RISCV_EXCP_ILLEGAL_INST; + } + + *val = env->rdtime_fn() + delta; +@@ -236,7 +236,7 @@ static int read_timeh(CPURISCVState *env, int csrno, target_ulong *val) + uint64_t delta = riscv_cpu_virt_enabled(env) ? env->htimedelta : 0; + + if (!env->rdtime_fn) { +- return -1; ++ return -RISCV_EXCP_ILLEGAL_INST; + } + + *val = (env->rdtime_fn() + delta) >> 32; +@@ -502,7 +502,7 @@ static int write_mcounteren(CPURISCVState *env, int csrno, target_ulong val) + static int read_mscounteren(CPURISCVState *env, int csrno, target_ulong *val) + { + if (env->priv_ver < PRIV_VERSION_1_11_0) { +- return -1; ++ return -RISCV_EXCP_ILLEGAL_INST; + } + *val = env->mcounteren; + return 0; +@@ -512,7 +512,7 @@ static int read_mscounteren(CPURISCVState *env, int csrno, target_ulong *val) + static int write_mscounteren(CPURISCVState *env, int csrno, target_ulong val) + { + if (env->priv_ver < PRIV_VERSION_1_11_0) { +- return -1; ++ return -RISCV_EXCP_ILLEGAL_INST; + } + env->mcounteren = val; + return 0; +@@ -736,7 +736,7 @@ static int read_satp(CPURISCVState *env, int csrno, target_ulong *val) + } + + if (env->priv == PRV_S && get_field(env->mstatus, MSTATUS_TVM)) { +- return -1; ++ return -RISCV_EXCP_ILLEGAL_INST; + } else { + *val = env->satp; + } +@@ -753,7 +753,7 @@ static int write_satp(CPURISCVState *env, int csrno, target_ulong val) + ((val ^ env->satp) & (SATP_MODE | SATP_ASID | SATP_PPN))) + { + if (env->priv == PRV_S && get_field(env->mstatus, MSTATUS_TVM)) { +- return -1; ++ return -RISCV_EXCP_ILLEGAL_INST; + } else { + if((val ^ env->satp) & SATP_ASID) { + tlb_flush(env_cpu(env)); +@@ -923,7 +923,7 @@ static int write_hgatp(CPURISCVState *env, int csrno, target_ulong val) + static int read_htimedelta(CPURISCVState *env, int csrno, target_ulong *val) + { + if (!env->rdtime_fn) { +- return -1; ++ return -RISCV_EXCP_ILLEGAL_INST; + } + + #if defined(TARGET_RISCV32) +@@ -937,7 +937,7 @@ static int read_htimedelta(CPURISCVState *env, int csrno, target_ulong *val) + static int write_htimedelta(CPURISCVState *env, int csrno, target_ulong val) + { + if (!env->rdtime_fn) { +- return -1; ++ return -RISCV_EXCP_ILLEGAL_INST; + } + + #if defined(TARGET_RISCV32) +@@ -952,7 +952,7 @@ static int write_htimedelta(CPURISCVState *env, int csrno, target_ulong val) + static int read_htimedeltah(CPURISCVState *env, int csrno, target_ulong *val) + { + if (!env->rdtime_fn) { +- return -1; ++ return -RISCV_EXCP_ILLEGAL_INST; + } + + *val = env->htimedelta >> 32; +@@ -962,7 +962,7 @@ static int read_htimedeltah(CPURISCVState *env, int csrno, target_ulong *val) + static int write_htimedeltah(CPURISCVState *env, int csrno, target_ulong val) + { + if (!env->rdtime_fn) { +- return -1; ++ return -RISCV_EXCP_ILLEGAL_INST; + } + + env->htimedelta = deposit64(env->htimedelta, 32, 32, (uint64_t)val); +@@ -1160,18 +1160,18 @@ int riscv_csrrw(CPURISCVState *env, int csrno, target_ulong *ret_value, + + if ((write_mask && read_only) || + (!env->debugger && (effective_priv < get_field(csrno, 0x300)))) { +- return -1; ++ return -RISCV_EXCP_ILLEGAL_INST; + } + #endif + + /* ensure the CSR extension is enabled. */ + if (!cpu->cfg.ext_icsr) { +- return -1; ++ return -RISCV_EXCP_ILLEGAL_INST; + } + + /* check predicate */ + if (!csr_ops[csrno].predicate || csr_ops[csrno].predicate(env, csrno) < 0) { +- return -1; ++ return -RISCV_EXCP_ILLEGAL_INST; + } + + /* execute combined read/write operation if it exists */ +@@ -1181,7 +1181,7 @@ int riscv_csrrw(CPURISCVState *env, int csrno, target_ulong *ret_value, + + /* if no accessor exists then return failure */ + if (!csr_ops[csrno].read) { +- return -1; ++ return -RISCV_EXCP_ILLEGAL_INST; + } + + /* read old value */ +diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c +index efc2d854eb..80d632777b 100644 +--- a/target/riscv/op_helper.c ++++ b/target/riscv/op_helper.c +@@ -43,8 +43,10 @@ target_ulong helper_csrrw(CPURISCVState *env, target_ulong src, + target_ulong csr) + { + target_ulong val = 0; +- if (riscv_csrrw(env, csr, &val, src, -1) < 0) { +- riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC()); ++ int ret = riscv_csrrw(env, csr, &val, src, -1); ++ ++ if (ret < 0) { ++ riscv_raise_exception(env, -ret, GETPC()); + } + return val; + } +@@ -53,8 +55,10 @@ target_ulong helper_csrrs(CPURISCVState *env, target_ulong src, + target_ulong csr, target_ulong rs1_pass) + { + target_ulong val = 0; +- if (riscv_csrrw(env, csr, &val, -1, rs1_pass ? src : 0) < 0) { +- riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC()); ++ int ret = riscv_csrrw(env, csr, &val, -1, rs1_pass ? src : 0); ++ ++ if (ret < 0) { ++ riscv_raise_exception(env, -ret, GETPC()); + } + return val; + } +@@ -63,8 +67,10 @@ target_ulong helper_csrrc(CPURISCVState *env, target_ulong src, + target_ulong csr, target_ulong rs1_pass) + { + target_ulong val = 0; +- if (riscv_csrrw(env, csr, &val, 0, rs1_pass ? src : 0) < 0) { +- riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC()); ++ int ret = riscv_csrrw(env, csr, &val, 0, rs1_pass ? src : 0); ++ ++ if (ret < 0) { ++ riscv_raise_exception(env, -ret, GETPC()); + } + return val; + } +-- +2.23.0 + diff --git a/target-riscv-Set-access-as-data_load-when-validating.patch b/target-riscv-Set-access-as-data_load-when-validating.patch new file mode 100644 index 0000000000000000000000000000000000000000..0669043acf3bcff75016002d1ccf92c246a88d86 --- /dev/null +++ b/target-riscv-Set-access-as-data_load-when-validating.patch @@ -0,0 +1,27 @@ +From 112747976d1fb5c97147e387b59a826070ccccb1 Mon Sep 17 00:00:00 2001 +From: Alistair Francis +Date: Fri, 27 Mar 2020 12:53:40 -0700 +Subject: [PATCH 671/709] target/riscv: Set access as data_load when validating + stage-2 PTEs + +Signed-off-by: Alistair Francis +--- + target/riscv/cpu_helper.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c +index 62fe1ecc8f..eda7057663 100644 +--- a/target/riscv/cpu_helper.c ++++ b/target/riscv/cpu_helper.c +@@ -435,7 +435,7 @@ restart: + hwaddr vbase; + + /* Do the second stage translation on the base PTE address. */ +- get_physical_address(env, &vbase, &vbase_prot, base, access_type, ++ get_physical_address(env, &vbase, &vbase_prot, base, MMU_DATA_LOAD, + mmu_idx, false, true); + + pte_addr = vbase + idx * ptesize; +-- +2.23.0 + diff --git a/target-riscv-Support-riscv-cpu-vmstate.patch b/target-riscv-Support-riscv-cpu-vmstate.patch new file mode 100644 index 0000000000000000000000000000000000000000..3b0917f88d3f8727a47a3f3c8212e9c5442b3f0a --- /dev/null +++ b/target-riscv-Support-riscv-cpu-vmstate.patch @@ -0,0 +1,54 @@ +From 889be311eb7999ff1261d100a70483e876c56e6f Mon Sep 17 00:00:00 2001 +From: Yifei Jiang +Date: Thu, 27 Aug 2020 10:21:06 +0800 +Subject: [PATCH 706/709] target/riscv: Support riscv cpu vmstate + +Describe gpr, fpr and csr in vmstate_riscv_cpu. + +Signed-off-by: Yifei Jiang +Signed-off-by: Yipeng Yin +--- + target/riscv/cpu.c | 20 ++++++++++++++++++-- + 1 file changed, 18 insertions(+), 2 deletions(-) + +diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c +index b7de444fbf..bbc9726a20 100644 +--- a/target/riscv/cpu.c ++++ b/target/riscv/cpu.c +@@ -26,7 +26,7 @@ + #include "qapi/error.h" + #include "qemu/error-report.h" + #include "hw/qdev-properties.h" +-#include "migration/vmstate.h" ++#include "migration/cpu.h" + #include "fpu/softfloat-helpers.h" + #include "kvm_riscv.h" + +@@ -473,7 +473,23 @@ static void riscv_cpu_init(Object *obj) + + static const VMStateDescription vmstate_riscv_cpu = { + .name = "cpu", +- .unmigratable = 1, ++ .version_id = 1, ++ .minimum_version_id = 1, ++ .fields = (VMStateField[]) { ++ VMSTATE_UINTTL_ARRAY(env.gpr, RISCVCPU, 32), ++ VMSTATE_UINT64_ARRAY(env.fpr, RISCVCPU, 32), ++ VMSTATE_UINTTL(env.pc, RISCVCPU), ++ VMSTATE_UINTTL(env.mstatus, RISCVCPU), ++ VMSTATE_UINTTL(env.mie, RISCVCPU), ++ VMSTATE_UINTTL(env.stvec, RISCVCPU), ++ VMSTATE_UINTTL(env.sscratch, RISCVCPU), ++ VMSTATE_UINTTL(env.sepc, RISCVCPU), ++ VMSTATE_UINTTL(env.scause, RISCVCPU), ++ VMSTATE_UINTTL(env.sbadaddr, RISCVCPU), ++ VMSTATE_UINTTL(env.mip, RISCVCPU), ++ VMSTATE_UINTTL(env.satp, RISCVCPU), ++ VMSTATE_END_OF_LIST() ++ } + }; + + static Property riscv_cpu_properties[] = { +-- +2.23.0 + diff --git a/target-riscv-Support-start-kernel-directly-by-KVM.patch b/target-riscv-Support-start-kernel-directly-by-KVM.patch new file mode 100644 index 0000000000000000000000000000000000000000..a1dedd2484900335cf929cc3861d8fcca0bce004 --- /dev/null +++ b/target-riscv-Support-start-kernel-directly-by-KVM.patch @@ -0,0 +1,167 @@ +From 3d2254fd1a9705add074dd8849f761cf9bea7ced Mon Sep 17 00:00:00 2001 +From: Yifei Jiang +Date: Mon, 24 Aug 2020 20:10:15 +0800 +Subject: [PATCH 700/709] target/riscv: Support start kernel directly by KVM + +Get kernel and fdt start address in virt.c, and pass them to KVM +when cpu reset. In addition, add kvm_riscv.h to place riscv specific +interface. + +Signed-off-by: Yifei Jiang +Signed-off-by: Yipeng Yin +--- + hw/riscv/virt.c | 15 +++++++++++++-- + target/riscv/cpu.c | 4 ++++ + target/riscv/cpu.h | 3 +++ + target/riscv/kvm.c | 13 +++++++++++++ + target/riscv/kvm_riscv.h | 24 ++++++++++++++++++++++++ + 5 files changed, 57 insertions(+), 2 deletions(-) + create mode 100644 target/riscv/kvm_riscv.h + +diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c +index e01925ff3d..270c4a8876 100644 +--- a/hw/riscv/virt.c ++++ b/hw/riscv/virt.c +@@ -43,6 +43,7 @@ + #include "exec/address-spaces.h" + #include "hw/pci/pci.h" + #include "hw/pci-host/gpex.h" ++#include "sysemu/kvm.h" + + #include + +@@ -498,6 +499,9 @@ static void riscv_virt_board_init(MachineState *machine) + target_ulong start_addr = memmap[VIRT_DRAM].base; + DeviceState *mmio_plic, *virtio_plic, *pcie_plic; + int i, j, base_hartid, hart_count; ++ uint64_t kernel_entry = 0; ++ hwaddr start_fdt; ++ CPUState *cs; + + /* Check socket count limit */ + if (VIRT_SOCKETS_MAX < riscv_socket_count(machine)) { +@@ -607,7 +611,7 @@ static void riscv_virt_board_init(MachineState *machine) + memmap[VIRT_DRAM].base, NULL); + + if (machine->kernel_filename) { +- uint64_t kernel_entry = riscv_load_kernel(machine->kernel_filename, ++ kernel_entry = riscv_load_kernel(machine->kernel_filename, + NULL); + + if (machine->initrd_filename) { +@@ -661,10 +665,17 @@ static void riscv_virt_board_init(MachineState *machine) + exit(1); + } + qemu_fdt_dumpdtb(s->fdt, fdt_totalsize(s->fdt)); ++ start_fdt = memmap[VIRT_MROM].base + sizeof(reset_vec); + rom_add_blob_fixed_as("mrom.fdt", s->fdt, fdt_totalsize(s->fdt), +- memmap[VIRT_MROM].base + sizeof(reset_vec), ++ start_fdt, + &address_space_memory); + ++ for (cs = first_cpu; cs; cs = CPU_NEXT(cs)) { ++ RISCVCPU *riscv_cpu = RISCV_CPU(cs); ++ riscv_cpu->env.loader_start = kernel_entry; ++ riscv_cpu->env.fdt_start = start_fdt; ++ } ++ + /* SiFive Test MMIO device */ + sifive_test_create(memmap[VIRT_TEST].base); + +diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c +index eeb91f8513..73af94efbd 100644 +--- a/target/riscv/cpu.c ++++ b/target/riscv/cpu.c +@@ -28,6 +28,7 @@ + #include "hw/qdev-properties.h" + #include "migration/vmstate.h" + #include "fpu/softfloat-helpers.h" ++#include "kvm_riscv.h" + + /* RISC-V CPU definitions */ + +@@ -336,6 +337,9 @@ static void riscv_cpu_reset(DeviceState *dev) + cs->exception_index = EXCP_NONE; + env->load_res = -1; + set_default_nan_mode(1, &env->fp_status); ++#ifdef CONFIG_KVM ++ kvm_riscv_reset_vcpu(cpu); ++#endif + } + + static void riscv_cpu_disas_set_info(CPUState *s, disassemble_info *info) +diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h +index 1bb5271511..df6d95b162 100644 +--- a/target/riscv/cpu.h ++++ b/target/riscv/cpu.h +@@ -206,6 +206,9 @@ struct CPURISCVState { + + /* Fields from here on are preserved across CPU reset. */ + QEMUTimer *timer; /* Internal timer */ ++ ++ hwaddr loader_start; ++ hwaddr fdt_start; + }; + + #define RISCV_CPU_CLASS(klass) \ +diff --git a/target/riscv/kvm.c b/target/riscv/kvm.c +index 9810a02b49..8cc9daaba9 100644 +--- a/target/riscv/kvm.c ++++ b/target/riscv/kvm.c +@@ -37,6 +37,7 @@ + #include "hw/irq.h" + #include "qemu/log.h" + #include "hw/loader.h" ++#include "kvm_riscv.h" + + static __u64 kvm_riscv_reg_id(__u64 type, __u64 idx) + { +@@ -426,3 +427,15 @@ int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run) + { + return 0; + } ++ ++void kvm_riscv_reset_vcpu(RISCVCPU *cpu) ++{ ++ CPURISCVState *env = &cpu->env; ++ ++ if (!kvm_enabled()) { ++ return; ++ } ++ env->pc = cpu->env.loader_start; ++ env->gpr[10] = kvm_arch_vcpu_id(CPU(cpu)); /* a0 */ ++ env->gpr[11] = cpu->env.fdt_start; /* a1 */ ++} +diff --git a/target/riscv/kvm_riscv.h b/target/riscv/kvm_riscv.h +new file mode 100644 +index 0000000000..80a4ee721a +--- /dev/null ++++ b/target/riscv/kvm_riscv.h +@@ -0,0 +1,24 @@ ++/* ++ * QEMU KVM support -- RISC-V specific functions. ++ * ++ * Copyright (c) 2020 Huawei Technologies Co., Ltd ++ * ++ * 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 QEMU_KVM_RISCV_H ++#define QEMU_KVM_RISCV_H ++ ++void kvm_riscv_reset_vcpu(RISCVCPU *cpu); ++ ++#endif +-- +2.23.0 + diff --git a/target-riscv-Support-the-Virtual-Instruction-fault.patch b/target-riscv-Support-the-Virtual-Instruction-fault.patch new file mode 100644 index 0000000000000000000000000000000000000000..3911d6e84956a83e9d950b214a24939b8e6ab00b --- /dev/null +++ b/target-riscv-Support-the-Virtual-Instruction-fault.patch @@ -0,0 +1,258 @@ +From eafe094196fb3ea52cbb016aa590379c8681f32f Mon Sep 17 00:00:00 2001 +From: Alistair Francis +Date: Wed, 27 May 2020 17:34:45 -0700 +Subject: [PATCH 687/709] target/riscv: Support the Virtual Instruction fault + +Signed-off-by: Alistair Francis +--- + target/riscv/cpu_bits.h | 6 +++ + target/riscv/csr.c | 56 ++++++++++++++++++++++++- + target/riscv/helper.h | 1 + + target/riscv/insn_trans/trans_rvh.inc.c | 2 +- + target/riscv/op_helper.c | 42 +++++++++++++++++-- + 5 files changed, 101 insertions(+), 6 deletions(-) + +diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h +index 690f327828..30fa746d10 100644 +--- a/target/riscv/cpu_bits.h ++++ b/target/riscv/cpu_bits.h +@@ -446,6 +446,11 @@ + #define HSTATUS_WPRI HSTATUS64_WPRI + #endif + ++#define HCOUNTEREN_CY (1 << 0) ++#define HCOUNTEREN_TM (1 << 1) ++#define HCOUNTEREN_IR (1 << 2) ++#define HCOUNTEREN_HPM3 (1 << 3) ++ + /* Privilege modes */ + #define PRV_U 0 + #define PRV_S 1 +@@ -538,6 +543,7 @@ + #define RISCV_EXCP_STORE_PAGE_FAULT 0xf /* since: priv-1.10.0 */ + #define RISCV_EXCP_INST_GUEST_PAGE_FAULT 0x14 + #define RISCV_EXCP_LOAD_GUEST_ACCESS_FAULT 0x15 ++#define RISCV_EXCP_VIRT_INSTRUCTION_FAULT 0x16 + #define RISCV_EXCP_STORE_GUEST_AMO_ACCESS_FAULT 0x17 + + #define RISCV_EXCP_INT_FLAG 0x80000000 +diff --git a/target/riscv/csr.c b/target/riscv/csr.c +index 0c53438605..f985b85de4 100644 +--- a/target/riscv/csr.c ++++ b/target/riscv/csr.c +@@ -63,6 +63,53 @@ static int ctr(CPURISCVState *env, int csrno) + /* The Counters extensions is not enabled */ + return -RISCV_EXCP_ILLEGAL_INST; + } ++ ++ if (riscv_cpu_virt_enabled(env)) { ++ switch (csrno) { ++ case CSR_CYCLE: ++ if (!get_field(env->hcounteren, HCOUNTEREN_CY)) { ++ return -RISCV_EXCP_VIRT_INSTRUCTION_FAULT; ++ } ++ break; ++ case CSR_TIME: ++ if (!get_field(env->hcounteren, HCOUNTEREN_TM)) { ++ return -RISCV_EXCP_VIRT_INSTRUCTION_FAULT; ++ } ++ break; ++ case CSR_INSTRET: ++ if (!get_field(env->hcounteren, HCOUNTEREN_IR)) { ++ return -RISCV_EXCP_VIRT_INSTRUCTION_FAULT; ++ } ++ break; ++ case CSR_HPMCOUNTER3...CSR_HPMCOUNTER31: ++ if (!get_field(env->hcounteren, 1 << (csrno - CSR_HPMCOUNTER3))) { ++ return -RISCV_EXCP_VIRT_INSTRUCTION_FAULT; ++ } ++ break; ++#if defined(TARGET_RISCV32) ++ case CSR_CYCLEH: ++ if (!get_field(env->hcounteren, HCOUNTEREN_CY)) { ++ return -RISCV_EXCP_VIRT_INSTRUCTION_FAULT; ++ } ++ break; ++ case CSR_TIMEH: ++ if (!get_field(env->hcounteren, HCOUNTEREN_TM)) { ++ return -RISCV_EXCP_VIRT_INSTRUCTION_FAULT; ++ } ++ break; ++ case CSR_INSTRETH: ++ if (!get_field(env->hcounteren, HCOUNTEREN_IR)) { ++ return -RISCV_EXCP_VIRT_INSTRUCTION_FAULT; ++ } ++ break; ++ case CSR_HPMCOUNTER3H...CSR_HPMCOUNTER31H: ++ if (!get_field(env->hcounteren, 1 << (csrno - CSR_HPMCOUNTER3H))) { ++ return -RISCV_EXCP_VIRT_INSTRUCTION_FAULT; ++ } ++ break; ++#endif ++ } ++ } + #endif + return 0; + } +@@ -86,6 +133,8 @@ static int hmode(CPURISCVState *env, int csrno) + if ((env->priv == PRV_S && !riscv_cpu_virt_enabled(env)) || + env->priv == PRV_M) { + return 0; ++ } else { ++ return -RISCV_EXCP_VIRT_INSTRUCTION_FAULT; + } + } + +@@ -272,6 +321,7 @@ static const target_ulong delegable_excps = + (1ULL << (RISCV_EXCP_STORE_PAGE_FAULT)) | + (1ULL << (RISCV_EXCP_INST_GUEST_PAGE_FAULT)) | + (1ULL << (RISCV_EXCP_LOAD_GUEST_ACCESS_FAULT)) | ++ (1ULL << (RISCV_EXCP_VIRT_INSTRUCTION_FAULT)) | + (1ULL << (RISCV_EXCP_STORE_GUEST_AMO_ACCESS_FAULT)); + static const target_ulong sstatus_v1_10_mask = SSTATUS_SIE | SSTATUS_SPIE | + SSTATUS_UIE | SSTATUS_UPIE | SSTATUS_SPP | SSTATUS_FS | SSTATUS_XS | +@@ -1170,9 +1220,13 @@ int riscv_csrrw(CPURISCVState *env, int csrno, target_ulong *ret_value, + } + + /* check predicate */ +- if (!csr_ops[csrno].predicate || csr_ops[csrno].predicate(env, csrno) < 0) { ++ if (!csr_ops[csrno].predicate) { + return -RISCV_EXCP_ILLEGAL_INST; + } ++ ret = csr_ops[csrno].predicate(env, csrno); ++ if (ret < 0) { ++ return ret; ++ } + + /* execute combined read/write operation if it exists */ + if (csr_ops[csrno].op) { +diff --git a/target/riscv/helper.h b/target/riscv/helper.h +index d020d1459c..2df7e09766 100644 +--- a/target/riscv/helper.h ++++ b/target/riscv/helper.h +@@ -80,6 +80,7 @@ DEF_HELPER_1(tlb_flush, void, env) + /* Hypervisor functions */ + #ifndef CONFIG_USER_ONLY + DEF_HELPER_1(hyp_tlb_flush, void, env) ++DEF_HELPER_1(hyp_gvma_tlb_flush, void, env) + DEF_HELPER_4(hyp_load, tl, env, tl, tl, tl) + DEF_HELPER_5(hyp_store, void, env, tl, tl, tl, tl) + DEF_HELPER_4(hyp_x_load, tl, env, tl, tl, tl) +diff --git a/target/riscv/insn_trans/trans_rvh.inc.c b/target/riscv/insn_trans/trans_rvh.inc.c +index db650ae62a..881c9ef4d2 100644 +--- a/target/riscv/insn_trans/trans_rvh.inc.c ++++ b/target/riscv/insn_trans/trans_rvh.inc.c +@@ -360,7 +360,7 @@ static bool trans_hfence_gvma(DisasContext *ctx, arg_sfence_vma *a) + { + REQUIRE_EXT(ctx, RVH); + #ifndef CONFIG_USER_ONLY +- gen_helper_hyp_tlb_flush(cpu_env); ++ gen_helper_hyp_gvma_tlb_flush(cpu_env); + return true; + #endif + return false; +diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c +index 80d632777b..dc1e403397 100644 +--- a/target/riscv/op_helper.c ++++ b/target/riscv/op_helper.c +@@ -94,6 +94,11 @@ target_ulong helper_sret(CPURISCVState *env, target_ulong cpu_pc_deb) + riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC()); + } + ++ if (riscv_has_ext(env, RVH) && riscv_cpu_virt_enabled(env) && ++ get_field(env->hstatus, HSTATUS_VTSR)) { ++ riscv_raise_exception(env, RISCV_EXCP_VIRT_INSTRUCTION_FAULT, GETPC()); ++ } ++ + mstatus = env->mstatus; + + if (riscv_has_ext(env, RVH) && !riscv_cpu_virt_enabled(env)) { +@@ -176,7 +181,7 @@ void helper_wfi(CPURISCVState *env) + if ((env->priv == PRV_S && + get_field(env->mstatus, MSTATUS_TW)) || + riscv_cpu_virt_enabled(env)) { +- riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC()); ++ riscv_raise_exception(env, RISCV_EXCP_VIRT_INSTRUCTION_FAULT, GETPC()); + } else { + cs->halted = 1; + cs->exception_index = EXCP_HLT; +@@ -191,6 +196,9 @@ void helper_tlb_flush(CPURISCVState *env) + (env->priv == PRV_S && + get_field(env->mstatus, MSTATUS_TVM))) { + riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC()); ++ } else if (riscv_has_ext(env, RVH) && riscv_cpu_virt_enabled(env) && ++ get_field(env->hstatus, HSTATUS_VTVM)) { ++ riscv_raise_exception(env, RISCV_EXCP_VIRT_INSTRUCTION_FAULT, GETPC()); + } else { + tlb_flush(cs); + } +@@ -200,6 +208,10 @@ void helper_hyp_tlb_flush(CPURISCVState *env) + { + CPUState *cs = env_cpu(env); + ++ if (env->priv == PRV_S && riscv_cpu_virt_enabled(env)){ ++ riscv_raise_exception(env, RISCV_EXCP_VIRT_INSTRUCTION_FAULT, GETPC()); ++ } ++ + if (env->priv == PRV_M || + (env->priv == PRV_S && !riscv_cpu_virt_enabled(env))) { + tlb_flush(cs); +@@ -209,6 +221,16 @@ void helper_hyp_tlb_flush(CPURISCVState *env) + riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC()); + } + ++void helper_hyp_gvma_tlb_flush(CPURISCVState *env) ++{ ++ if (env->priv == PRV_S && !riscv_cpu_virt_enabled(env) && ++ get_field(env->mstatus, MSTATUS_TVM)) { ++ riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC()); ++ } ++ ++ helper_hyp_tlb_flush(env); ++} ++ + target_ulong helper_hyp_load(CPURISCVState *env, target_ulong address, + target_ulong attrs, target_ulong memop) + { +@@ -251,7 +273,11 @@ target_ulong helper_hyp_load(CPURISCVState *env, target_ulong address, + return pte; + } + +- riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC()); ++ if (riscv_cpu_virt_enabled(env)) { ++ riscv_raise_exception(env, RISCV_EXCP_VIRT_INSTRUCTION_FAULT, GETPC()); ++ } else { ++ riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC()); ++ } + return 0; + } + +@@ -289,7 +315,11 @@ void helper_hyp_store(CPURISCVState *env, target_ulong address, + return; + } + +- riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC()); ++ if (riscv_cpu_virt_enabled(env)) { ++ riscv_raise_exception(env, RISCV_EXCP_VIRT_INSTRUCTION_FAULT, GETPC()); ++ } else { ++ riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC()); ++ } + } + + target_ulong helper_hyp_x_load(CPURISCVState *env, target_ulong address, +@@ -319,7 +349,11 @@ target_ulong helper_hyp_x_load(CPURISCVState *env, target_ulong address, + return pte; + } + +- riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC()); ++ if (riscv_cpu_virt_enabled(env)) { ++ riscv_raise_exception(env, RISCV_EXCP_VIRT_INSTRUCTION_FAULT, GETPC()); ++ } else { ++ riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC()); ++ } + return 0; + } + +-- +2.23.0 + diff --git a/target-riscv-Support-the-v0.6-Hypervisor-extension-C.patch b/target-riscv-Support-the-v0.6-Hypervisor-extension-C.patch new file mode 100644 index 0000000000000000000000000000000000000000..6ab716999bd96985e97c27df57b2208b8ce1b2af --- /dev/null +++ b/target-riscv-Support-the-v0.6-Hypervisor-extension-C.patch @@ -0,0 +1,115 @@ +From c27da0530a155334ab901ae14e7bbb1206221622 Mon Sep 17 00:00:00 2001 +From: Alistair Francis +Date: Mon, 6 Apr 2020 15:58:29 -0700 +Subject: [PATCH 685/709] target/riscv: Support the v0.6 Hypervisor extension + CRSs + +Signed-off-by: Alistair Francis +--- + target/riscv/cpu_bits.h | 3 +++ + target/riscv/csr.c | 40 ++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 43 insertions(+) + +diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h +index 8a145e0a32..690f327828 100644 +--- a/target/riscv/cpu_bits.h ++++ b/target/riscv/cpu_bits.h +@@ -182,9 +182,12 @@ + #define CSR_HIDELEG 0x603 + #define CSR_HIE 0x604 + #define CSR_HCOUNTEREN 0x606 ++#define CSR_HGEIE 0x607 + #define CSR_HTVAL 0x643 ++#define CSR_HVIP 0x645 + #define CSR_HIP 0x644 + #define CSR_HTINST 0x64A ++#define CSR_HGEIP 0xE12 + #define CSR_HGATP 0x680 + #define CSR_HTIMEDELTA 0x605 + #define CSR_HTIMEDELTAH 0x615 +diff --git a/target/riscv/csr.c b/target/riscv/csr.c +index 5b64539efb..9990a0dd09 100644 +--- a/target/riscv/csr.c ++++ b/target/riscv/csr.c +@@ -815,12 +815,25 @@ static int write_hideleg(CPURISCVState *env, int csrno, target_ulong val) + return 0; + } + ++static int rmw_hvip(CPURISCVState *env, int csrno, target_ulong *ret_value, ++ target_ulong new_value, target_ulong write_mask) ++{ ++ int ret = rmw_mip(env, 0, ret_value, new_value, ++ write_mask & hip_writable_mask); ++ ++ *ret_value &= hip_writable_mask; ++ ++ return ret; ++} ++ + static int rmw_hip(CPURISCVState *env, int csrno, target_ulong *ret_value, + target_ulong new_value, target_ulong write_mask) + { + int ret = rmw_mip(env, 0, ret_value, new_value, + write_mask & hip_writable_mask); + ++ *ret_value &= hip_writable_mask; ++ + return ret; + } + +@@ -848,6 +861,18 @@ static int write_hcounteren(CPURISCVState *env, int csrno, target_ulong val) + return 0; + } + ++static int read_hgeie(CPURISCVState *env, int csrno, target_ulong *val) ++{ ++ qemu_log_mask(LOG_UNIMP, "No support for a non-zero GEILEN."); ++ return 0; ++} ++ ++static int write_hgeie(CPURISCVState *env, int csrno, target_ulong val) ++{ ++ qemu_log_mask(LOG_UNIMP, "No support for a non-zero GEILEN."); ++ return 0; ++} ++ + static int read_htval(CPURISCVState *env, int csrno, target_ulong *val) + { + *val = env->htval; +@@ -871,6 +896,18 @@ static int write_htinst(CPURISCVState *env, int csrno, target_ulong val) + return 0; + } + ++static int read_hgeip(CPURISCVState *env, int csrno, target_ulong *val) ++{ ++ qemu_log_mask(LOG_UNIMP, "No support for a non-zero GEILEN."); ++ return 0; ++} ++ ++static int write_hgeip(CPURISCVState *env, int csrno, target_ulong val) ++{ ++ qemu_log_mask(LOG_UNIMP, "No support for a non-zero GEILEN."); ++ return 0; ++} ++ + static int read_hgatp(CPURISCVState *env, int csrno, target_ulong *val) + { + *val = env->hgatp; +@@ -1268,11 +1305,14 @@ static riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = { + [CSR_HSTATUS] = { hmode, read_hstatus, write_hstatus }, + [CSR_HEDELEG] = { hmode, read_hedeleg, write_hedeleg }, + [CSR_HIDELEG] = { hmode, read_hideleg, write_hideleg }, ++ [CSR_HVIP] = { hmode, NULL, NULL, rmw_hvip }, + [CSR_HIP] = { hmode, NULL, NULL, rmw_hip }, + [CSR_HIE] = { hmode, read_hie, write_hie }, + [CSR_HCOUNTEREN] = { hmode, read_hcounteren, write_hcounteren }, ++ [CSR_HGEIE] = { hmode, read_hgeie, write_hgeie }, + [CSR_HTVAL] = { hmode, read_htval, write_htval }, + [CSR_HTINST] = { hmode, read_htinst, write_htinst }, ++ [CSR_HGEIP] = { hmode, read_hgeip, write_hgeip }, + [CSR_HGATP] = { hmode, read_hgatp, write_hgatp }, + [CSR_HTIMEDELTA] = { hmode, read_htimedelta, write_htimedelta }, + #if defined(TARGET_RISCV32) +-- +2.23.0 + diff --git a/target-riscv-Support-virtual-time-context-synchroniz.patch b/target-riscv-Support-virtual-time-context-synchroniz.patch new file mode 100644 index 0000000000000000000000000000000000000000..338904b1bf1b69b2dcf5367c81084a5b6dcdc8bb --- /dev/null +++ b/target-riscv-Support-virtual-time-context-synchroniz.patch @@ -0,0 +1,51 @@ +From 9ba2d924c2e65cf43337c0f4507408c56b8fa807 Mon Sep 17 00:00:00 2001 +From: Yifei Jiang +Date: Thu, 27 Aug 2020 10:21:53 +0800 +Subject: [PATCH 709/709] target/riscv: Support virtual time context + synchronization + +Add virtual time context description to vmstate_riscv_cpu. After cpu being +loaded, virtual time context is updated to KVM. + +Signed-off-by: Yifei Jiang +Signed-off-by: Yipeng Yin +--- + target/riscv/cpu.c | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c +index bbc9726a20..9891d4012b 100644 +--- a/target/riscv/cpu.c ++++ b/target/riscv/cpu.c +@@ -471,10 +471,18 @@ static void riscv_cpu_init(Object *obj) + cpu_set_cpustate_pointers(cpu); + } + ++static int cpu_post_load(void *opaque, int version_id) ++{ ++ RISCVCPU *cpu = opaque; ++ cpu->env.kvm_timer_dirty = true; ++ return 0; ++} ++ + static const VMStateDescription vmstate_riscv_cpu = { + .name = "cpu", + .version_id = 1, + .minimum_version_id = 1, ++ .post_load = cpu_post_load, + .fields = (VMStateField[]) { + VMSTATE_UINTTL_ARRAY(env.gpr, RISCVCPU, 32), + VMSTATE_UINT64_ARRAY(env.fpr, RISCVCPU, 32), +@@ -488,6 +496,9 @@ static const VMStateDescription vmstate_riscv_cpu = { + VMSTATE_UINTTL(env.sbadaddr, RISCVCPU), + VMSTATE_UINTTL(env.mip, RISCVCPU), + VMSTATE_UINTTL(env.satp, RISCVCPU), ++ VMSTATE_UINT64(env.kvm_timer_time, RISCVCPU), ++ VMSTATE_UINT64(env.kvm_timer_compare, RISCVCPU), ++ VMSTATE_UINT64(env.kvm_timer_state, RISCVCPU), + VMSTATE_END_OF_LIST() + } + }; +-- +2.23.0 + diff --git a/target-riscv-Update-the-CSRs-to-the-v0.6-Hyp-extensi.patch b/target-riscv-Update-the-CSRs-to-the-v0.6-Hyp-extensi.patch new file mode 100644 index 0000000000000000000000000000000000000000..cff10486973e2b3d7a6fd7497af7578bf7e0a364 --- /dev/null +++ b/target-riscv-Update-the-CSRs-to-the-v0.6-Hyp-extensi.patch @@ -0,0 +1,42 @@ +From dd75d3c445b5bee4657ffbf5caf127c6be4f5679 Mon Sep 17 00:00:00 2001 +From: Alistair Francis +Date: Mon, 6 Apr 2020 15:32:02 -0700 +Subject: [PATCH 682/709] target/riscv: Update the CSRs to the v0.6 Hyp + extension + +Signed-off-by: Alistair Francis +--- + target/riscv/cpu_bits.h | 14 ++++++++------ + 1 file changed, 8 insertions(+), 6 deletions(-) + +diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h +index 6b97c27711..8a145e0a32 100644 +--- a/target/riscv/cpu_bits.h ++++ b/target/riscv/cpu_bits.h +@@ -422,15 +422,17 @@ + #endif + + /* hstatus CSR bits */ +-#define HSTATUS_SPRV 0x00000001 ++#define HSTATUS_VSBE 0x00000020 ++#define HSTATUS_GVA 0x00000040 + #define HSTATUS_SPV 0x00000080 +-#define HSTATUS_SP2P 0x00000100 +-#define HSTATUS_SP2V 0x00000200 ++#define HSTATUS_SPVP 0x00000100 ++#define HSTATUS_HU 0x00000200 ++#define HSTATUS_VGEIN 0x0003F000 + #define HSTATUS_VTVM 0x00100000 + #define HSTATUS_VTSR 0x00400000 +-#define HSTATUS_HU 0x00000200 +-#define HSTATUS_GVA 0x00000040 +-#define HSTATUS_SPVP 0x00000100 ++#if defined(TARGET_RISCV64) ++#define HSTATUS_VSXL 0x300000000 ++#endif + + #define HSTATUS32_WPRI 0xFF8FF87E + #define HSTATUS64_WPRI 0xFFFFFFFFFF8FF87EULL +-- +2.23.0 + diff --git a/target-riscv-Update-the-Hypervisor-trap-return-entry.patch b/target-riscv-Update-the-Hypervisor-trap-return-entry.patch new file mode 100644 index 0000000000000000000000000000000000000000..f07ea317abc629862705a1eef3ae0260c3c9738f --- /dev/null +++ b/target-riscv-Update-the-Hypervisor-trap-return-entry.patch @@ -0,0 +1,94 @@ +From 10980f1bc6479994d8eac9f4a567eacd7dc4f855 Mon Sep 17 00:00:00 2001 +From: Alistair Francis +Date: Mon, 6 Apr 2020 15:31:33 -0700 +Subject: [PATCH 681/709] target/riscv: Update the Hypervisor trap return/entry + +Signed-off-by: Alistair Francis +--- + target/riscv/cpu_bits.h | 1 + + target/riscv/cpu_helper.c | 8 +------- + target/riscv/op_helper.c | 8 ++------ + target/riscv/translate.c | 10 ---------- + 4 files changed, 4 insertions(+), 23 deletions(-) + +diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h +index 028e268faa..6b97c27711 100644 +--- a/target/riscv/cpu_bits.h ++++ b/target/riscv/cpu_bits.h +@@ -430,6 +430,7 @@ + #define HSTATUS_VTSR 0x00400000 + #define HSTATUS_HU 0x00000200 + #define HSTATUS_GVA 0x00000040 ++#define HSTATUS_SPVP 0x00000100 + + #define HSTATUS32_WPRI 0xFF8FF87E + #define HSTATUS64_WPRI 0xFFFFFFFFFF8FF87EULL +diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c +index 4ea39d5641..c4085e5870 100644 +--- a/target/riscv/cpu_helper.c ++++ b/target/riscv/cpu_helper.c +@@ -916,9 +916,7 @@ void riscv_cpu_do_interrupt(CPUState *cs) + } else if (riscv_cpu_virt_enabled(env)) { + /* Trap into HS mode, from virt */ + riscv_cpu_swap_hypervisor_regs(env); +- env->hstatus = set_field(env->hstatus, HSTATUS_SP2V, +- get_field(env->hstatus, HSTATUS_SPV)); +- env->hstatus = set_field(env->hstatus, HSTATUS_SP2P, ++ env->hstatus = set_field(env->hstatus, HSTATUS_SPVP, + get_field(env->mstatus, SSTATUS_SPP)); + env->hstatus = set_field(env->hstatus, HSTATUS_SPV, + riscv_cpu_virt_enabled(env)); +@@ -929,10 +927,6 @@ void riscv_cpu_do_interrupt(CPUState *cs) + riscv_cpu_set_force_hs_excep(env, 0); + } else { + /* Trap into HS mode */ +- env->hstatus = set_field(env->hstatus, HSTATUS_SP2V, +- get_field(env->hstatus, HSTATUS_SPV)); +- env->hstatus = set_field(env->hstatus, HSTATUS_SP2P, +- get_field(env->mstatus, SSTATUS_SPP)); + env->hstatus = set_field(env->hstatus, HSTATUS_SPV, + riscv_cpu_virt_enabled(env)); + +diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c +index e0053699cc..efc2d854eb 100644 +--- a/target/riscv/op_helper.c ++++ b/target/riscv/op_helper.c +@@ -97,12 +97,8 @@ target_ulong helper_sret(CPURISCVState *env, target_ulong cpu_pc_deb) + prev_priv = get_field(mstatus, MSTATUS_SPP); + prev_virt = get_field(hstatus, HSTATUS_SPV); + +- hstatus = set_field(hstatus, HSTATUS_SPV, +- get_field(hstatus, HSTATUS_SP2V)); +- mstatus = set_field(mstatus, MSTATUS_SPP, +- get_field(hstatus, HSTATUS_SP2P)); +- hstatus = set_field(hstatus, HSTATUS_SP2V, 0); +- hstatus = set_field(hstatus, HSTATUS_SP2P, 0); ++ hstatus = set_field(hstatus, HSTATUS_SPV, 0); ++ mstatus = set_field(mstatus, MSTATUS_SPP, 0); + mstatus = set_field(mstatus, SSTATUS_SIE, + get_field(mstatus, SSTATUS_SPIE)); + mstatus = set_field(mstatus, SSTATUS_SPIE, 1); +diff --git a/target/riscv/translate.c b/target/riscv/translate.c +index ce71ca7a92..1d973b62e9 100644 +--- a/target/riscv/translate.c ++++ b/target/riscv/translate.c +@@ -754,16 +754,6 @@ static void riscv_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs) + #if !defined(CONFIG_USER_ONLY) + if (riscv_has_ext(env, RVH)) { + ctx->virt_enabled = riscv_cpu_virt_enabled(env); +- if (env->priv_ver == PRV_M && +- get_field(env->mstatus, MSTATUS_MPRV) && +- MSTATUS_MPV_ISSET(env)) { +- ctx->virt_enabled = true; +- } else if (env->priv == PRV_S && +- !riscv_cpu_virt_enabled(env) && +- get_field(env->hstatus, HSTATUS_SPRV) && +- get_field(env->hstatus, HSTATUS_SPV)) { +- ctx->virt_enabled = true; +- } + } else { + ctx->virt_enabled = false; + } +-- +2.23.0 + diff --git a/target-riscv-add-host-cpu-type.patch b/target-riscv-add-host-cpu-type.patch new file mode 100644 index 0000000000000000000000000000000000000000..0f8da2a1c458e742cf85e73c2b05a009c7d63832 --- /dev/null +++ b/target-riscv-add-host-cpu-type.patch @@ -0,0 +1,57 @@ +From fdc56eacffd92ae69b5d72a044bc6b6067fe4a23 Mon Sep 17 00:00:00 2001 +From: Yifei Jiang +Date: Mon, 24 Aug 2020 20:25:41 +0800 +Subject: [PATCH 703/709] target/riscv: add host cpu type + +Currently, host cpu is inherited simply. + +Signed-off-by: Yifei Jiang +Signed-off-by: Yipeng Yin +--- + target/riscv/cpu.c | 6 ++++++ + target/riscv/cpu.h | 1 + + 2 files changed, 7 insertions(+) + +diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c +index 73af94efbd..b7de444fbf 100644 +--- a/target/riscv/cpu.c ++++ b/target/riscv/cpu.c +@@ -192,6 +192,10 @@ static void rv64imacu_nommu_cpu_init(Object *obj) + set_feature(env, RISCV_FEATURE_PMP); + } + ++static void riscv_host_cpu_init(Object *obj) ++{ ++} ++ + #endif + + static ObjectClass *riscv_cpu_class_by_name(const char *cpu_model) +@@ -603,10 +607,12 @@ static const TypeInfo riscv_cpu_type_infos[] = { + DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_E31, rv32imacu_nommu_cpu_init), + DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_E34, rv32imafcu_nommu_cpu_init), + DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_U34, rv32gcsu_priv1_10_0_cpu_init), ++ DEFINE_CPU(TYPE_RISCV_CPU_HOST, riscv_host_cpu_init), + #elif defined(TARGET_RISCV64) + DEFINE_CPU(TYPE_RISCV_CPU_BASE64, riscv_base64_cpu_init), + DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_E51, rv64imacu_nommu_cpu_init), + DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_U54, rv64gcsu_priv1_10_0_cpu_init), ++ DEFINE_CPU(TYPE_RISCV_CPU_HOST, riscv_host_cpu_init), + #endif + }; + +diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h +index df6d95b162..f69f38df75 100644 +--- a/target/riscv/cpu.h ++++ b/target/riscv/cpu.h +@@ -40,6 +40,7 @@ + #define TYPE_RISCV_CPU_SIFIVE_E51 RISCV_CPU_TYPE_NAME("sifive-e51") + #define TYPE_RISCV_CPU_SIFIVE_U34 RISCV_CPU_TYPE_NAME("sifive-u34") + #define TYPE_RISCV_CPU_SIFIVE_U54 RISCV_CPU_TYPE_NAME("sifive-u54") ++#define TYPE_RISCV_CPU_HOST RISCV_CPU_TYPE_NAME("host") + + #define RV32 ((target_ulong)1 << (TARGET_LONG_BITS - 2)) + #define RV64 ((target_ulong)2 << (TARGET_LONG_BITS - 2)) +-- +2.23.0 + diff --git a/target-riscv-raise-exception-to-HS-mode-at-get_physi.patch b/target-riscv-raise-exception-to-HS-mode-at-get_physi.patch new file mode 100644 index 0000000000000000000000000000000000000000..cedbbd05551322d7304964bc85d6e287d3bc71b7 --- /dev/null +++ b/target-riscv-raise-exception-to-HS-mode-at-get_physi.patch @@ -0,0 +1,71 @@ +From 0288d20406fc810ee6ccfcc168e3e3af8aec219a Mon Sep 17 00:00:00 2001 +From: Yifei Jiang +Date: Thu, 27 Aug 2020 10:20:30 +0800 +Subject: [PATCH 704/709] target/riscv: raise exception to HS-mode at + get_physical_address + +VS-stage translation at get_physical_address needs to translate pte +address by G-stage translation. But the G-stage translation error +can not be distinguished from VS-stage translation error in +riscv_cpu_tlb_fill. On migration, destination needs to rebuild pte, +and this G-stage translation error must be handled by HS-mode. So +introduce TRANSLATE_STAGE2_FAIL so that riscv_cpu_tlb_fill could +distinguish and raise it to HS-mode. + +Signed-off-by: Yifei Jiang +Signed-off-by: Yipeng Yin +--- + target/riscv/cpu.h | 1 + + target/riscv/cpu_helper.c | 12 ++++++++++-- + 2 files changed, 11 insertions(+), 2 deletions(-) + +diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h +index f69f38df75..9d2b41466e 100644 +--- a/target/riscv/cpu.h ++++ b/target/riscv/cpu.h +@@ -81,6 +81,7 @@ enum { + #define TRANSLATE_FAIL 1 + #define TRANSLATE_SUCCESS 0 + #define MMU_USER_IDX 3 ++#define TRANSLATE_G_STAGE_FAIL 4 + + #define MAX_RISCV_PMPS (16) + +diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c +index eccd80cfef..821cea0293 100644 +--- a/target/riscv/cpu_helper.c ++++ b/target/riscv/cpu_helper.c +@@ -449,7 +449,10 @@ restart: + mmu_idx, false, true); + + if (vbase_ret != TRANSLATE_SUCCESS) { +- return vbase_ret; ++ env->guest_phys_fault_addr = (base | ++ (addr & ++ (TARGET_PAGE_SIZE - 1))) >> 2; ++ return TRANSLATE_G_STAGE_FAIL; + } + + pte_addr = vbase + idx * ptesize; +@@ -724,12 +727,17 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size, + ret = get_physical_address(env, &pa, &prot, address, access_type, + mmu_idx, true, true); + ++ if (ret == TRANSLATE_G_STAGE_FAIL) { ++ first_stage_error = false; ++ access_type = MMU_DATA_LOAD; ++ } ++ + qemu_log_mask(CPU_LOG_MMU, + "%s 1st-stage address=%" VADDR_PRIx " ret %d physical " + TARGET_FMT_plx " prot %d\n", + __func__, address, ret, pa, prot); + +- if (ret != TRANSLATE_FAIL) { ++ if (ret != TRANSLATE_FAIL && ret != TRANSLATE_G_STAGE_FAIL) { + /* Second stage lookup */ + im_address = pa; + +-- +2.23.0 + diff --git a/target-s390x-Use-tcg_gen_gvec_dup_imm.patch b/target-s390x-Use-tcg_gen_gvec_dup_imm.patch new file mode 100644 index 0000000000000000000000000000000000000000..9dea393a3af1f60537aca21b443cd2068ad2d2d4 --- /dev/null +++ b/target-s390x-Use-tcg_gen_gvec_dup_imm.patch @@ -0,0 +1,118 @@ +From 8703cfbf98b5d4adea4e715a76b1c79a7a09e060 Mon Sep 17 00:00:00 2001 +From: Richard Henderson +Date: Sat, 28 Mar 2020 14:42:19 -0700 +Subject: [PATCH 284/709] target/s390x: Use tcg_gen_gvec_dup_imm +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The gen_gvec_dupi switch is unnecessary with the new function. +Replace it with a local gen_gvec_dup_imm that takes care of the +register to offset conversion and length arguments. + +Drop zero_vec and use use gen_gvec_dup_imm with 0. + +Reviewed-by: David Hildenbrand +Reviewed-by: Alex Bennée +Signed-off-by: Richard Henderson +--- + target/s390x/translate_vx.inc.c | 41 +++++++-------------------------- + 1 file changed, 8 insertions(+), 33 deletions(-) + +diff --git a/target/s390x/translate_vx.inc.c b/target/s390x/translate_vx.inc.c +index 24558cce80..12347f8a03 100644 +--- a/target/s390x/translate_vx.inc.c ++++ b/target/s390x/translate_vx.inc.c +@@ -231,8 +231,8 @@ static void get_vec_element_ptr_i64(TCGv_ptr ptr, uint8_t reg, TCGv_i64 enr, + #define gen_gvec_mov(v1, v2) \ + tcg_gen_gvec_mov(0, vec_full_reg_offset(v1), vec_full_reg_offset(v2), 16, \ + 16) +-#define gen_gvec_dup64i(v1, c) \ +- tcg_gen_gvec_dup64i(vec_full_reg_offset(v1), 16, 16, c) ++#define gen_gvec_dup_imm(es, v1, c) \ ++ tcg_gen_gvec_dup_imm(es, vec_full_reg_offset(v1), 16, 16, c); + #define gen_gvec_fn_2(fn, es, v1, v2) \ + tcg_gen_gvec_##fn(es, vec_full_reg_offset(v1), vec_full_reg_offset(v2), \ + 16, 16) +@@ -316,31 +316,6 @@ static void gen_gvec128_4_i64(gen_gvec128_4_i64_fn fn, uint8_t d, uint8_t a, + tcg_temp_free_i64(cl); + } + +-static void gen_gvec_dupi(uint8_t es, uint8_t reg, uint64_t c) +-{ +- switch (es) { +- case ES_8: +- tcg_gen_gvec_dup8i(vec_full_reg_offset(reg), 16, 16, c); +- break; +- case ES_16: +- tcg_gen_gvec_dup16i(vec_full_reg_offset(reg), 16, 16, c); +- break; +- case ES_32: +- tcg_gen_gvec_dup32i(vec_full_reg_offset(reg), 16, 16, c); +- break; +- case ES_64: +- gen_gvec_dup64i(reg, c); +- break; +- default: +- g_assert_not_reached(); +- } +-} +- +-static void zero_vec(uint8_t reg) +-{ +- tcg_gen_gvec_dup8i(vec_full_reg_offset(reg), 16, 16, 0); +-} +- + static void gen_addi2_i64(TCGv_i64 dl, TCGv_i64 dh, TCGv_i64 al, TCGv_i64 ah, + uint64_t b) + { +@@ -396,8 +371,8 @@ static DisasJumpType op_vgbm(DisasContext *s, DisasOps *o) + * Masks for both 64 bit elements of the vector are the same. + * Trust tcg to produce a good constant loading. + */ +- gen_gvec_dup64i(get_field(s, v1), +- generate_byte_mask(i2 & 0xff)); ++ gen_gvec_dup_imm(ES_64, get_field(s, v1), ++ generate_byte_mask(i2 & 0xff)); + } else { + TCGv_i64 t = tcg_temp_new_i64(); + +@@ -432,7 +407,7 @@ static DisasJumpType op_vgm(DisasContext *s, DisasOps *o) + } + } + +- gen_gvec_dupi(es, get_field(s, v1), mask); ++ gen_gvec_dup_imm(es, get_field(s, v1), mask); + return DISAS_NEXT; + } + +@@ -585,7 +560,7 @@ static DisasJumpType op_vllez(DisasContext *s, DisasOps *o) + + t = tcg_temp_new_i64(); + tcg_gen_qemu_ld_i64(t, o->addr1, get_mem_index(s), MO_TE | es); +- zero_vec(get_field(s, v1)); ++ gen_gvec_dup_imm(es, get_field(s, v1), 0); + write_vec_element_i64(t, get_field(s, v1), enr, es); + tcg_temp_free_i64(t); + return DISAS_NEXT; +@@ -892,7 +867,7 @@ static DisasJumpType op_vrepi(DisasContext *s, DisasOps *o) + return DISAS_NORETURN; + } + +- gen_gvec_dupi(es, get_field(s, v1), data); ++ gen_gvec_dup_imm(es, get_field(s, v1), data); + return DISAS_NEXT; + } + +@@ -1372,7 +1347,7 @@ static DisasJumpType op_vcksm(DisasContext *s, DisasOps *o) + read_vec_element_i32(tmp, get_field(s, v2), i, ES_32); + tcg_gen_add2_i32(tmp, sum, sum, sum, tmp, tmp); + } +- zero_vec(get_field(s, v1)); ++ gen_gvec_dup_imm(ES_32, get_field(s, v1), 0); + write_vec_element_i32(sum, get_field(s, v1), 1, ES_32); + + tcg_temp_free_i32(tmp); +-- +2.23.0 + diff --git a/tcg-Add-load_dest-parameter-to-GVecGen2.patch b/tcg-Add-load_dest-parameter-to-GVecGen2.patch new file mode 100644 index 0000000000000000000000000000000000000000..686b3bf95ac046074e1709de539d0f0cd7bfb78e --- /dev/null +++ b/tcg-Add-load_dest-parameter-to-GVecGen2.patch @@ -0,0 +1,151 @@ +From ac09ae627e9a2c65c8a452b69c3dac33c29d0719 Mon Sep 17 00:00:00 2001 +From: Richard Henderson +Date: Wed, 8 Apr 2020 15:22:47 -0700 +Subject: [PATCH 291/709] tcg: Add load_dest parameter to GVecGen2 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +We have this same parameter for GVecGen2i, GVecGen3, +and GVecGen3i. This will make some SVE2 insns easier +to parameterize. + +Reviewed-by: Alex Bennée +Signed-off-by: Richard Henderson +--- + include/tcg/tcg-op-gvec.h | 2 ++ + tcg/tcg-op-gvec.c | 45 ++++++++++++++++++++++++++++----------- + 2 files changed, 34 insertions(+), 13 deletions(-) + +diff --git a/include/tcg/tcg-op-gvec.h b/include/tcg/tcg-op-gvec.h +index d89f91f40e..cea6497341 100644 +--- a/include/tcg/tcg-op-gvec.h ++++ b/include/tcg/tcg-op-gvec.h +@@ -109,6 +109,8 @@ typedef struct { + uint8_t vece; + /* Prefer i64 to v64. */ + bool prefer_i64; ++ /* Load dest as a 2nd source operand. */ ++ bool load_dest; + } GVecGen2; + + typedef struct { +diff --git a/tcg/tcg-op-gvec.c b/tcg/tcg-op-gvec.c +index 43cac1a0bf..049a55e700 100644 +--- a/tcg/tcg-op-gvec.c ++++ b/tcg/tcg-op-gvec.c +@@ -663,17 +663,22 @@ static void expand_clr(uint32_t dofs, uint32_t maxsz) + + /* Expand OPSZ bytes worth of two-operand operations using i32 elements. */ + static void expand_2_i32(uint32_t dofs, uint32_t aofs, uint32_t oprsz, +- void (*fni)(TCGv_i32, TCGv_i32)) ++ bool load_dest, void (*fni)(TCGv_i32, TCGv_i32)) + { + TCGv_i32 t0 = tcg_temp_new_i32(); ++ TCGv_i32 t1 = tcg_temp_new_i32(); + uint32_t i; + + for (i = 0; i < oprsz; i += 4) { + tcg_gen_ld_i32(t0, cpu_env, aofs + i); +- fni(t0, t0); +- tcg_gen_st_i32(t0, cpu_env, dofs + i); ++ if (load_dest) { ++ tcg_gen_ld_i32(t1, cpu_env, dofs + i); ++ } ++ fni(t1, t0); ++ tcg_gen_st_i32(t1, cpu_env, dofs + i); + } + tcg_temp_free_i32(t0); ++ tcg_temp_free_i32(t1); + } + + static void expand_2i_i32(uint32_t dofs, uint32_t aofs, uint32_t oprsz, +@@ -793,17 +798,22 @@ static void expand_4_i32(uint32_t dofs, uint32_t aofs, uint32_t bofs, + + /* Expand OPSZ bytes worth of two-operand operations using i64 elements. */ + static void expand_2_i64(uint32_t dofs, uint32_t aofs, uint32_t oprsz, +- void (*fni)(TCGv_i64, TCGv_i64)) ++ bool load_dest, void (*fni)(TCGv_i64, TCGv_i64)) + { + TCGv_i64 t0 = tcg_temp_new_i64(); ++ TCGv_i64 t1 = tcg_temp_new_i64(); + uint32_t i; + + for (i = 0; i < oprsz; i += 8) { + tcg_gen_ld_i64(t0, cpu_env, aofs + i); +- fni(t0, t0); +- tcg_gen_st_i64(t0, cpu_env, dofs + i); ++ if (load_dest) { ++ tcg_gen_ld_i64(t1, cpu_env, dofs + i); ++ } ++ fni(t1, t0); ++ tcg_gen_st_i64(t1, cpu_env, dofs + i); + } + tcg_temp_free_i64(t0); ++ tcg_temp_free_i64(t1); + } + + static void expand_2i_i64(uint32_t dofs, uint32_t aofs, uint32_t oprsz, +@@ -924,17 +934,23 @@ static void expand_4_i64(uint32_t dofs, uint32_t aofs, uint32_t bofs, + /* Expand OPSZ bytes worth of two-operand operations using host vectors. */ + static void expand_2_vec(unsigned vece, uint32_t dofs, uint32_t aofs, + uint32_t oprsz, uint32_t tysz, TCGType type, ++ bool load_dest, + void (*fni)(unsigned, TCGv_vec, TCGv_vec)) + { + TCGv_vec t0 = tcg_temp_new_vec(type); ++ TCGv_vec t1 = tcg_temp_new_vec(type); + uint32_t i; + + for (i = 0; i < oprsz; i += tysz) { + tcg_gen_ld_vec(t0, cpu_env, aofs + i); +- fni(vece, t0, t0); +- tcg_gen_st_vec(t0, cpu_env, dofs + i); ++ if (load_dest) { ++ tcg_gen_ld_vec(t1, cpu_env, dofs + i); ++ } ++ fni(vece, t1, t0); ++ tcg_gen_st_vec(t1, cpu_env, dofs + i); + } + tcg_temp_free_vec(t0); ++ tcg_temp_free_vec(t1); + } + + /* Expand OPSZ bytes worth of two-vector operands and an immediate operand +@@ -1088,7 +1104,8 @@ void tcg_gen_gvec_2(uint32_t dofs, uint32_t aofs, + * that e.g. size == 80 would be expanded with 2x32 + 1x16. + */ + some = QEMU_ALIGN_DOWN(oprsz, 32); +- expand_2_vec(g->vece, dofs, aofs, some, 32, TCG_TYPE_V256, g->fniv); ++ expand_2_vec(g->vece, dofs, aofs, some, 32, TCG_TYPE_V256, ++ g->load_dest, g->fniv); + if (some == oprsz) { + break; + } +@@ -1098,17 +1115,19 @@ void tcg_gen_gvec_2(uint32_t dofs, uint32_t aofs, + maxsz -= some; + /* fallthru */ + case TCG_TYPE_V128: +- expand_2_vec(g->vece, dofs, aofs, oprsz, 16, TCG_TYPE_V128, g->fniv); ++ expand_2_vec(g->vece, dofs, aofs, oprsz, 16, TCG_TYPE_V128, ++ g->load_dest, g->fniv); + break; + case TCG_TYPE_V64: +- expand_2_vec(g->vece, dofs, aofs, oprsz, 8, TCG_TYPE_V64, g->fniv); ++ expand_2_vec(g->vece, dofs, aofs, oprsz, 8, TCG_TYPE_V64, ++ g->load_dest, g->fniv); + break; + + case 0: + if (g->fni8 && check_size_impl(oprsz, 8)) { +- expand_2_i64(dofs, aofs, oprsz, g->fni8); ++ expand_2_i64(dofs, aofs, oprsz, g->load_dest, g->fni8); + } else if (g->fni4 && check_size_impl(oprsz, 4)) { +- expand_2_i32(dofs, aofs, oprsz, g->fni4); ++ expand_2_i32(dofs, aofs, oprsz, g->load_dest, g->fni4); + } else { + assert(g->fno != NULL); + tcg_gen_gvec_2_ool(dofs, aofs, oprsz, maxsz, g->data, g->fno); +-- +2.23.0 + diff --git a/tcg-Add-tcg_gen_gvec_dup_imm.patch b/tcg-Add-tcg_gen_gvec_dup_imm.patch new file mode 100644 index 0000000000000000000000000000000000000000..08b5aecfbc67cbef1462f478c2284ebd615f5a70 --- /dev/null +++ b/tcg-Add-tcg_gen_gvec_dup_imm.patch @@ -0,0 +1,56 @@ +From 44c94677febd15488f9190b11eaa4a08e8ac696b Mon Sep 17 00:00:00 2001 +From: Richard Henderson +Date: Sat, 28 Mar 2020 14:17:11 -0700 +Subject: [PATCH 283/709] tcg: Add tcg_gen_gvec_dup_imm +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Add a version of tcg_gen_dup_* that takes both immediate and +a vector element size operand. This will replace the set of +tcg_gen_gvec_dup{8,16,32,64}i functions that encode the element +size within the function name. + +Reviewed-by: LIU Zhiwei +Reviewed-by: David Hildenbrand +Reviewed-by: Alex Bennée +Signed-off-by: Richard Henderson +--- + include/tcg/tcg-op-gvec.h | 2 ++ + tcg/tcg-op-gvec.c | 7 +++++++ + 2 files changed, 9 insertions(+) + +diff --git a/include/tcg/tcg-op-gvec.h b/include/tcg/tcg-op-gvec.h +index 74534e2480..eb0d47a42b 100644 +--- a/include/tcg/tcg-op-gvec.h ++++ b/include/tcg/tcg-op-gvec.h +@@ -313,6 +313,8 @@ void tcg_gen_gvec_ors(unsigned vece, uint32_t dofs, uint32_t aofs, + + void tcg_gen_gvec_dup_mem(unsigned vece, uint32_t dofs, uint32_t aofs, + uint32_t s, uint32_t m); ++void tcg_gen_gvec_dup_imm(unsigned vece, uint32_t dofs, uint32_t s, ++ uint32_t m, uint64_t imm); + void tcg_gen_gvec_dup_i32(unsigned vece, uint32_t dofs, uint32_t s, + uint32_t m, TCGv_i32); + void tcg_gen_gvec_dup_i64(unsigned vece, uint32_t dofs, uint32_t s, +diff --git a/tcg/tcg-op-gvec.c b/tcg/tcg-op-gvec.c +index 327d9588e0..593bb4542e 100644 +--- a/tcg/tcg-op-gvec.c ++++ b/tcg/tcg-op-gvec.c +@@ -1569,6 +1569,13 @@ void tcg_gen_gvec_dup8i(uint32_t dofs, uint32_t oprsz, + do_dup(MO_8, dofs, oprsz, maxsz, NULL, NULL, x); + } + ++void tcg_gen_gvec_dup_imm(unsigned vece, uint32_t dofs, uint32_t oprsz, ++ uint32_t maxsz, uint64_t x) ++{ ++ check_size_align(oprsz, maxsz, dofs); ++ do_dup(vece, dofs, oprsz, maxsz, NULL, NULL, x); ++} ++ + void tcg_gen_gvec_not(unsigned vece, uint32_t dofs, uint32_t aofs, + uint32_t oprsz, uint32_t maxsz) + { +-- +2.23.0 + diff --git a/tcg-Add-tcg_gen_gvec_dup_tl.patch b/tcg-Add-tcg_gen_gvec_dup_tl.patch new file mode 100644 index 0000000000000000000000000000000000000000..1d7aa96f4c5281cdcfabbf02007897e9aba6ce1c --- /dev/null +++ b/tcg-Add-tcg_gen_gvec_dup_tl.patch @@ -0,0 +1,39 @@ +From 0f039e3ad9131966d9fe509c231b756868b015e2 Mon Sep 17 00:00:00 2001 +From: Richard Henderson +Date: Sat, 28 Mar 2020 16:17:45 -0700 +Subject: [PATCH 289/709] tcg: Add tcg_gen_gvec_dup_tl +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +For use when a target needs to pass a configure-specific +target_ulong value to duplicate. + +Reviewed-by: LIU Zhiwei +Reviewed-by: David Hildenbrand +Reviewed-by: Alex Bennée +Signed-off-by: Richard Henderson +--- + include/tcg/tcg-op-gvec.h | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/include/tcg/tcg-op-gvec.h b/include/tcg/tcg-op-gvec.h +index fa8a0c8d03..d89f91f40e 100644 +--- a/include/tcg/tcg-op-gvec.h ++++ b/include/tcg/tcg-op-gvec.h +@@ -320,6 +320,12 @@ void tcg_gen_gvec_dup_i32(unsigned vece, uint32_t dofs, uint32_t s, + void tcg_gen_gvec_dup_i64(unsigned vece, uint32_t dofs, uint32_t s, + uint32_t m, TCGv_i64); + ++#if TARGET_LONG_BITS == 64 ++# define tcg_gen_gvec_dup_tl tcg_gen_gvec_dup_i64 ++#else ++# define tcg_gen_gvec_dup_tl tcg_gen_gvec_dup_i32 ++#endif ++ + void tcg_gen_gvec_shli(unsigned vece, uint32_t dofs, uint32_t aofs, + int64_t shift, uint32_t oprsz, uint32_t maxsz); + void tcg_gen_gvec_shri(unsigned vece, uint32_t dofs, uint32_t aofs, +-- +2.23.0 + diff --git a/tcg-Fix-integral-argument-type-to-tcg_gen_rot-rl-i_i.patch b/tcg-Fix-integral-argument-type-to-tcg_gen_rot-rl-i_i.patch new file mode 100644 index 0000000000000000000000000000000000000000..d6f16ad43b585bb87f5b9bded6d487f23e2f145c --- /dev/null +++ b/tcg-Fix-integral-argument-type-to-tcg_gen_rot-rl-i_i.patch @@ -0,0 +1,106 @@ +From 07dada0336a83002dfa8673a9220a88e13d9a45c Mon Sep 17 00:00:00 2001 +From: Richard Henderson +Date: Sun, 19 Apr 2020 17:58:23 -0700 +Subject: [PATCH 292/709] tcg: Fix integral argument type to + tcg_gen_rot[rl]i_i{32,64} +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +For the benefit of compatibility of function pointer types, +we have standardized on int32_t and int64_t as the integral +argument to tcg expanders. + +We converted most of them in 474b2e8f0f7, but missed the rotates. + +Reviewed-by: Alex Bennée +Reviewed-by: Philippe Mathieu-Daudé +Signed-off-by: Richard Henderson +--- + include/tcg/tcg-op.h | 8 ++++---- + tcg/tcg-op.c | 16 ++++++++-------- + 2 files changed, 12 insertions(+), 12 deletions(-) + +diff --git a/include/tcg/tcg-op.h b/include/tcg/tcg-op.h +index 230db6e022..e3399d6a5e 100644 +--- a/include/tcg/tcg-op.h ++++ b/include/tcg/tcg-op.h +@@ -297,9 +297,9 @@ void tcg_gen_ctzi_i32(TCGv_i32 ret, TCGv_i32 arg1, uint32_t arg2); + void tcg_gen_clrsb_i32(TCGv_i32 ret, TCGv_i32 arg); + void tcg_gen_ctpop_i32(TCGv_i32 a1, TCGv_i32 a2); + void tcg_gen_rotl_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2); +-void tcg_gen_rotli_i32(TCGv_i32 ret, TCGv_i32 arg1, unsigned arg2); ++void tcg_gen_rotli_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2); + void tcg_gen_rotr_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2); +-void tcg_gen_rotri_i32(TCGv_i32 ret, TCGv_i32 arg1, unsigned arg2); ++void tcg_gen_rotri_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2); + void tcg_gen_deposit_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2, + unsigned int ofs, unsigned int len); + void tcg_gen_deposit_z_i32(TCGv_i32 ret, TCGv_i32 arg, +@@ -493,9 +493,9 @@ void tcg_gen_ctzi_i64(TCGv_i64 ret, TCGv_i64 arg1, uint64_t arg2); + void tcg_gen_clrsb_i64(TCGv_i64 ret, TCGv_i64 arg); + void tcg_gen_ctpop_i64(TCGv_i64 a1, TCGv_i64 a2); + void tcg_gen_rotl_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2); +-void tcg_gen_rotli_i64(TCGv_i64 ret, TCGv_i64 arg1, unsigned arg2); ++void tcg_gen_rotli_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2); + void tcg_gen_rotr_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2); +-void tcg_gen_rotri_i64(TCGv_i64 ret, TCGv_i64 arg1, unsigned arg2); ++void tcg_gen_rotri_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2); + void tcg_gen_deposit_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2, + unsigned int ofs, unsigned int len); + void tcg_gen_deposit_z_i64(TCGv_i64 ret, TCGv_i64 arg, +diff --git a/tcg/tcg-op.c b/tcg/tcg-op.c +index e2e25ebf7d..e60b74fb82 100644 +--- a/tcg/tcg-op.c ++++ b/tcg/tcg-op.c +@@ -540,9 +540,9 @@ void tcg_gen_rotl_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) + } + } + +-void tcg_gen_rotli_i32(TCGv_i32 ret, TCGv_i32 arg1, unsigned arg2) ++void tcg_gen_rotli_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2) + { +- tcg_debug_assert(arg2 < 32); ++ tcg_debug_assert(arg2 >= 0 && arg2 < 32); + /* some cases can be optimized here */ + if (arg2 == 0) { + tcg_gen_mov_i32(ret, arg1); +@@ -580,9 +580,9 @@ void tcg_gen_rotr_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) + } + } + +-void tcg_gen_rotri_i32(TCGv_i32 ret, TCGv_i32 arg1, unsigned arg2) ++void tcg_gen_rotri_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2) + { +- tcg_debug_assert(arg2 < 32); ++ tcg_debug_assert(arg2 >= 0 && arg2 < 32); + /* some cases can be optimized here */ + if (arg2 == 0) { + tcg_gen_mov_i32(ret, arg1); +@@ -1962,9 +1962,9 @@ void tcg_gen_rotl_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) + } + } + +-void tcg_gen_rotli_i64(TCGv_i64 ret, TCGv_i64 arg1, unsigned arg2) ++void tcg_gen_rotli_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2) + { +- tcg_debug_assert(arg2 < 64); ++ tcg_debug_assert(arg2 >= 0 && arg2 < 64); + /* some cases can be optimized here */ + if (arg2 == 0) { + tcg_gen_mov_i64(ret, arg1); +@@ -2001,9 +2001,9 @@ void tcg_gen_rotr_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) + } + } + +-void tcg_gen_rotri_i64(TCGv_i64 ret, TCGv_i64 arg1, unsigned arg2) ++void tcg_gen_rotri_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2) + { +- tcg_debug_assert(arg2 < 64); ++ tcg_debug_assert(arg2 >= 0 && arg2 < 64); + /* some cases can be optimized here */ + if (arg2 == 0) { + tcg_gen_mov_i64(ret, arg1); +-- +2.23.0 + diff --git a/tcg-Improve-vector-tail-clearing.patch b/tcg-Improve-vector-tail-clearing.patch new file mode 100644 index 0000000000000000000000000000000000000000..193ade435f3e59cb89b1a8b0c9ec0c5374e71513 --- /dev/null +++ b/tcg-Improve-vector-tail-clearing.patch @@ -0,0 +1,130 @@ +From f47db80cc073c0a7a22136c8296b5eca20c0e199 Mon Sep 17 00:00:00 2001 +From: Richard Henderson +Date: Sat, 28 Mar 2020 19:47:07 -0700 +Subject: [PATCH 290/709] tcg: Improve vector tail clearing +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Better handling of non-power-of-2 tails as seen with Arm 8-byte +vector operations. + +Reviewed-by: Alex Bennée +Signed-off-by: Richard Henderson +--- + tcg/tcg-op-gvec.c | 84 ++++++++++++++++++++++++++++++++++++----------- + 1 file changed, 64 insertions(+), 20 deletions(-) + +diff --git a/tcg/tcg-op-gvec.c b/tcg/tcg-op-gvec.c +index 5a6cc19812..43cac1a0bf 100644 +--- a/tcg/tcg-op-gvec.c ++++ b/tcg/tcg-op-gvec.c +@@ -326,11 +326,34 @@ void tcg_gen_gvec_5_ptr(uint32_t dofs, uint32_t aofs, uint32_t bofs, + in units of LNSZ. This limits the expansion of inline code. */ + static inline bool check_size_impl(uint32_t oprsz, uint32_t lnsz) + { +- if (oprsz % lnsz == 0) { +- uint32_t lnct = oprsz / lnsz; +- return lnct >= 1 && lnct <= MAX_UNROLL; ++ uint32_t q, r; ++ ++ if (oprsz < lnsz) { ++ return false; + } +- return false; ++ ++ q = oprsz / lnsz; ++ r = oprsz % lnsz; ++ tcg_debug_assert((r & 7) == 0); ++ ++ if (lnsz < 16) { ++ /* For sizes below 16, accept no remainder. */ ++ if (r != 0) { ++ return false; ++ } ++ } else { ++ /* ++ * Recall that ARM SVE allows vector sizes that are not a ++ * power of 2, but always a multiple of 16. The intent is ++ * that e.g. size == 80 would be expanded with 2x32 + 1x16. ++ * In addition, expand_clr needs to handle a multiple of 8. ++ * Thus we can handle the tail with one more operation per ++ * diminishing power of 2. ++ */ ++ q += ctpop32(r); ++ } ++ ++ return q <= MAX_UNROLL; + } + + static void expand_clr(uint32_t dofs, uint32_t maxsz); +@@ -402,22 +425,31 @@ static void gen_dup_i64(unsigned vece, TCGv_i64 out, TCGv_i64 in) + static TCGType choose_vector_type(const TCGOpcode *list, unsigned vece, + uint32_t size, bool prefer_i64) + { +- if (TCG_TARGET_HAS_v256 && check_size_impl(size, 32)) { +- /* +- * Recall that ARM SVE allows vector sizes that are not a +- * power of 2, but always a multiple of 16. The intent is +- * that e.g. size == 80 would be expanded with 2x32 + 1x16. +- * It is hard to imagine a case in which v256 is supported +- * but v128 is not, but check anyway. +- */ +- if (tcg_can_emit_vecop_list(list, TCG_TYPE_V256, vece) +- && (size % 32 == 0 +- || tcg_can_emit_vecop_list(list, TCG_TYPE_V128, vece))) { +- return TCG_TYPE_V256; +- } +- } +- if (TCG_TARGET_HAS_v128 && check_size_impl(size, 16) +- && tcg_can_emit_vecop_list(list, TCG_TYPE_V128, vece)) { ++ /* ++ * Recall that ARM SVE allows vector sizes that are not a ++ * power of 2, but always a multiple of 16. The intent is ++ * that e.g. size == 80 would be expanded with 2x32 + 1x16. ++ * It is hard to imagine a case in which v256 is supported ++ * but v128 is not, but check anyway. ++ * In addition, expand_clr needs to handle a multiple of 8. ++ */ ++ if (TCG_TARGET_HAS_v256 && ++ check_size_impl(size, 32) && ++ tcg_can_emit_vecop_list(list, TCG_TYPE_V256, vece) && ++ (!(size & 16) || ++ (TCG_TARGET_HAS_v128 && ++ tcg_can_emit_vecop_list(list, TCG_TYPE_V128, vece))) && ++ (!(size & 8) || ++ (TCG_TARGET_HAS_v64 && ++ tcg_can_emit_vecop_list(list, TCG_TYPE_V64, vece)))) { ++ return TCG_TYPE_V256; ++ } ++ if (TCG_TARGET_HAS_v128 && ++ check_size_impl(size, 16) && ++ tcg_can_emit_vecop_list(list, TCG_TYPE_V128, vece) && ++ (!(size & 8) || ++ (TCG_TARGET_HAS_v64 && ++ tcg_can_emit_vecop_list(list, TCG_TYPE_V64, vece)))) { + return TCG_TYPE_V128; + } + if (TCG_TARGET_HAS_v64 && !prefer_i64 && check_size_impl(size, 8) +@@ -432,6 +464,18 @@ static void do_dup_store(TCGType type, uint32_t dofs, uint32_t oprsz, + { + uint32_t i = 0; + ++ tcg_debug_assert(oprsz >= 8); ++ ++ /* ++ * This may be expand_clr for the tail of an operation, e.g. ++ * oprsz == 8 && maxsz == 64. The first 8 bytes of this store ++ * are misaligned wrt the maximum vector size, so do that first. ++ */ ++ if (dofs & 8) { ++ tcg_gen_stl_vec(t_vec, cpu_env, dofs + i, TCG_TYPE_V64); ++ i += 8; ++ } ++ + switch (type) { + case TCG_TYPE_V256: + /* +-- +2.23.0 + diff --git a/tcg-Remove-tcg_gen_gvec_dup-8-16-32-64-i.patch b/tcg-Remove-tcg_gen_gvec_dup-8-16-32-64-i.patch new file mode 100644 index 0000000000000000000000000000000000000000..a0aebaad3a08a63c2aee98274785ffdf218607df --- /dev/null +++ b/tcg-Remove-tcg_gen_gvec_dup-8-16-32-64-i.patch @@ -0,0 +1,77 @@ +From 398f21412aeec158338963e3f71c9313bc126a71 Mon Sep 17 00:00:00 2001 +From: Richard Henderson +Date: Sat, 28 Mar 2020 16:10:51 -0700 +Subject: [PATCH 288/709] tcg: Remove tcg_gen_gvec_dup{8,16,32,64}i +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +These interfaces are now unused. + +Reviewed-by: LIU Zhiwei +Reviewed-by: David Hildenbrand +Reviewed-by: Alex Bennée +Signed-off-by: Richard Henderson +--- + include/tcg/tcg-op-gvec.h | 5 ----- + tcg/tcg-op-gvec.c | 28 ---------------------------- + 2 files changed, 33 deletions(-) + +diff --git a/include/tcg/tcg-op-gvec.h b/include/tcg/tcg-op-gvec.h +index eb0d47a42b..fa8a0c8d03 100644 +--- a/include/tcg/tcg-op-gvec.h ++++ b/include/tcg/tcg-op-gvec.h +@@ -320,11 +320,6 @@ void tcg_gen_gvec_dup_i32(unsigned vece, uint32_t dofs, uint32_t s, + void tcg_gen_gvec_dup_i64(unsigned vece, uint32_t dofs, uint32_t s, + uint32_t m, TCGv_i64); + +-void tcg_gen_gvec_dup8i(uint32_t dofs, uint32_t s, uint32_t m, uint8_t x); +-void tcg_gen_gvec_dup16i(uint32_t dofs, uint32_t s, uint32_t m, uint16_t x); +-void tcg_gen_gvec_dup32i(uint32_t dofs, uint32_t s, uint32_t m, uint32_t x); +-void tcg_gen_gvec_dup64i(uint32_t dofs, uint32_t s, uint32_t m, uint64_t x); +- + void tcg_gen_gvec_shli(unsigned vece, uint32_t dofs, uint32_t aofs, + int64_t shift, uint32_t oprsz, uint32_t maxsz); + void tcg_gen_gvec_shri(unsigned vece, uint32_t dofs, uint32_t aofs, +diff --git a/tcg/tcg-op-gvec.c b/tcg/tcg-op-gvec.c +index de16c027b3..5a6cc19812 100644 +--- a/tcg/tcg-op-gvec.c ++++ b/tcg/tcg-op-gvec.c +@@ -1541,34 +1541,6 @@ void tcg_gen_gvec_dup_mem(unsigned vece, uint32_t dofs, uint32_t aofs, + } + } + +-void tcg_gen_gvec_dup64i(uint32_t dofs, uint32_t oprsz, +- uint32_t maxsz, uint64_t x) +-{ +- check_size_align(oprsz, maxsz, dofs); +- do_dup(MO_64, dofs, oprsz, maxsz, NULL, NULL, x); +-} +- +-void tcg_gen_gvec_dup32i(uint32_t dofs, uint32_t oprsz, +- uint32_t maxsz, uint32_t x) +-{ +- check_size_align(oprsz, maxsz, dofs); +- do_dup(MO_32, dofs, oprsz, maxsz, NULL, NULL, x); +-} +- +-void tcg_gen_gvec_dup16i(uint32_t dofs, uint32_t oprsz, +- uint32_t maxsz, uint16_t x) +-{ +- check_size_align(oprsz, maxsz, dofs); +- do_dup(MO_16, dofs, oprsz, maxsz, NULL, NULL, x); +-} +- +-void tcg_gen_gvec_dup8i(uint32_t dofs, uint32_t oprsz, +- uint32_t maxsz, uint8_t x) +-{ +- check_size_align(oprsz, maxsz, dofs); +- do_dup(MO_8, dofs, oprsz, maxsz, NULL, NULL, x); +-} +- + void tcg_gen_gvec_dup_imm(unsigned vece, uint32_t dofs, uint32_t oprsz, + uint32_t maxsz, uint64_t x) + { +-- +2.23.0 + diff --git a/tcg-Use-tcg_gen_gvec_dup_imm-in-logical-simplificati.patch b/tcg-Use-tcg_gen_gvec_dup_imm-in-logical-simplificati.patch new file mode 100644 index 0000000000000000000000000000000000000000..88321ddbe985c7fdef3be39ec6fd7a39ce91ab98 --- /dev/null +++ b/tcg-Use-tcg_gen_gvec_dup_imm-in-logical-simplificati.patch @@ -0,0 +1,61 @@ +From 03ddb6f315ca6d02dfdba0aecc43aa97c728c428 Mon Sep 17 00:00:00 2001 +From: Richard Henderson +Date: Sat, 28 Mar 2020 16:10:42 -0700 +Subject: [PATCH 287/709] tcg: Use tcg_gen_gvec_dup_imm in logical + simplifications +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Replace the outgoing interface. + +Reviewed-by: LIU Zhiwei +Reviewed-by: Alex Bennée +Signed-off-by: Richard Henderson +--- + tcg/tcg-op-gvec.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/tcg/tcg-op-gvec.c b/tcg/tcg-op-gvec.c +index 593bb4542e..de16c027b3 100644 +--- a/tcg/tcg-op-gvec.c ++++ b/tcg/tcg-op-gvec.c +@@ -2326,7 +2326,7 @@ void tcg_gen_gvec_xor(unsigned vece, uint32_t dofs, uint32_t aofs, + }; + + if (aofs == bofs) { +- tcg_gen_gvec_dup8i(dofs, oprsz, maxsz, 0); ++ tcg_gen_gvec_dup_imm(MO_64, dofs, oprsz, maxsz, 0); + } else { + tcg_gen_gvec_3(dofs, aofs, bofs, oprsz, maxsz, &g); + } +@@ -2343,7 +2343,7 @@ void tcg_gen_gvec_andc(unsigned vece, uint32_t dofs, uint32_t aofs, + }; + + if (aofs == bofs) { +- tcg_gen_gvec_dup8i(dofs, oprsz, maxsz, 0); ++ tcg_gen_gvec_dup_imm(MO_64, dofs, oprsz, maxsz, 0); + } else { + tcg_gen_gvec_3(dofs, aofs, bofs, oprsz, maxsz, &g); + } +@@ -2360,7 +2360,7 @@ void tcg_gen_gvec_orc(unsigned vece, uint32_t dofs, uint32_t aofs, + }; + + if (aofs == bofs) { +- tcg_gen_gvec_dup8i(dofs, oprsz, maxsz, -1); ++ tcg_gen_gvec_dup_imm(MO_64, dofs, oprsz, maxsz, -1); + } else { + tcg_gen_gvec_3(dofs, aofs, bofs, oprsz, maxsz, &g); + } +@@ -2411,7 +2411,7 @@ void tcg_gen_gvec_eqv(unsigned vece, uint32_t dofs, uint32_t aofs, + }; + + if (aofs == bofs) { +- tcg_gen_gvec_dup8i(dofs, oprsz, maxsz, -1); ++ tcg_gen_gvec_dup_imm(MO_64, dofs, oprsz, maxsz, -1); + } else { + tcg_gen_gvec_3(dofs, aofs, bofs, oprsz, maxsz, &g); + } +-- +2.23.0 + diff --git a/test-qemu-opts-Simplify-test_has_help_option-after-b.patch b/test-qemu-opts-Simplify-test_has_help_option-after-b.patch new file mode 100644 index 0000000000000000000000000000000000000000..b05bd71565a003c04ed8b77dc93159742f56b471 --- /dev/null +++ b/test-qemu-opts-Simplify-test_has_help_option-after-b.patch @@ -0,0 +1,80 @@ +From 59d27ebc446baec4a972cc146df732910b5aa2de Mon Sep 17 00:00:00 2001 +From: Markus Armbruster +Date: Wed, 15 Apr 2020 09:49:23 +0200 +Subject: [PATCH 009/709] test-qemu-opts: Simplify test_has_help_option() after + bug fix + +Signed-off-by: Markus Armbruster +Reviewed-by: Eric Blake +Reviewed-by: Kevin Wolf +Message-Id: <20200415074927.19897-6-armbru@redhat.com> +--- + tests/test-qemu-opts.c | 36 +++++++++++++++++------------------- + 1 file changed, 17 insertions(+), 19 deletions(-) + +diff --git a/tests/test-qemu-opts.c b/tests/test-qemu-opts.c +index 77c944c4aa..2a0f42a09b 100644 +--- a/tests/test-qemu-opts.c ++++ b/tests/test-qemu-opts.c +@@ -732,41 +732,39 @@ static void test_has_help_option(void) + { + static const struct { + const char *params; +- /* expected value of has_help_option() */ +- bool expect_has_help_option; + /* expected value of qemu_opt_has_help_opt() with implied=false */ +- bool expect_opt_has_help_opt; ++ bool expect; + /* expected value of qemu_opt_has_help_opt() with implied=true */ +- bool expect_opt_has_help_opt_implied; ++ bool expect_implied; + } test[] = { +- { "help", true, true, false }, +- { "?", true, true, false }, +- { "helpme", false, false, false }, +- { "?me", false, false, false }, +- { "a,help", true, true, true }, +- { "a,?", true, true, true }, +- { "a=0,help,b", true, true, true }, +- { "a=0,?,b", true, true, true }, +- { "help,b=1", true, true, false }, +- { "?,b=1", true, true, false }, +- { "a,b,,help", true, true, true }, +- { "a,b,,?", true, true, true }, ++ { "help", true, false }, ++ { "?", true, false }, ++ { "helpme", false, false }, ++ { "?me", false, false }, ++ { "a,help", true, true }, ++ { "a,?", true, true }, ++ { "a=0,help,b", true, true }, ++ { "a=0,?,b", true, true }, ++ { "help,b=1", true, false }, ++ { "?,b=1", true, false }, ++ { "a,b,,help", true, true }, ++ { "a,b,,?", true, true }, + }; + int i; + QemuOpts *opts; + + for (i = 0; i < ARRAY_SIZE(test); i++) { + g_assert_cmpint(has_help_option(test[i].params), +- ==, test[i].expect_has_help_option); ++ ==, test[i].expect); + opts = qemu_opts_parse(&opts_list_03, test[i].params, false, + &error_abort); + g_assert_cmpint(qemu_opt_has_help_opt(opts), +- ==, test[i].expect_opt_has_help_opt); ++ ==, test[i].expect); + qemu_opts_del(opts); + opts = qemu_opts_parse(&opts_list_03, test[i].params, true, + &error_abort); + g_assert_cmpint(qemu_opt_has_help_opt(opts), +- ==, test[i].expect_opt_has_help_opt_implied); ++ ==, test[i].expect_implied); + qemu_opts_del(opts); + } + } +-- +2.23.0 + diff --git a/tests-Update-ACPI-tables-list-for-upcoming-arm-virt-.patch b/tests-Update-ACPI-tables-list-for-upcoming-arm-virt-.patch new file mode 100644 index 0000000000000000000000000000000000000000..7cc8410159dd78460171c6cfbddcbb2433fdc478 --- /dev/null +++ b/tests-Update-ACPI-tables-list-for-upcoming-arm-virt-.patch @@ -0,0 +1,46 @@ +From 122752d267cb43ee29b5f0acac1057198797c45c Mon Sep 17 00:00:00 2001 +From: Shameer Kolothum +Date: Tue, 21 Apr 2020 13:59:32 +0100 +Subject: [PATCH 222/709] tests: Update ACPI tables list for upcoming arm/virt + test changes + +This is in preparation to update test_acpi_virt_tcg_memhp() +with pc-dimm and nvdimm. Update the bios-tables-test-allowed-diff.h +with the affected ACPI tables so that "make check" doesn't fail. + +Also add empty files for new tables required for new test. + +Signed-off-by: Shameer Kolothum +Message-Id: <20200421125934.14952-6-shameerali.kolothum.thodi@huawei.com> +Acked-by: Peter Maydell +Tested-by: Eric Auger +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +--- + tests/data/acpi/virt/NFIT.memhp | 0 + tests/data/acpi/virt/SSDT.memhp | 0 + tests/qtest/bios-tables-test-allowed-diff.h | 3 +++ + 3 files changed, 3 insertions(+) + create mode 100644 tests/data/acpi/virt/NFIT.memhp + create mode 100644 tests/data/acpi/virt/SSDT.memhp + +diff --git a/tests/data/acpi/virt/NFIT.memhp b/tests/data/acpi/virt/NFIT.memhp +new file mode 100644 +index 0000000000..e69de29bb2 +diff --git a/tests/data/acpi/virt/SSDT.memhp b/tests/data/acpi/virt/SSDT.memhp +new file mode 100644 +index 0000000000..e69de29bb2 +diff --git a/tests/qtest/bios-tables-test-allowed-diff.h b/tests/qtest/bios-tables-test-allowed-diff.h +index eb8bae1407..862c49e675 100644 +--- a/tests/qtest/bios-tables-test-allowed-diff.h ++++ b/tests/qtest/bios-tables-test-allowed-diff.h +@@ -1,3 +1,6 @@ + /* List of comma-separated changed AML files to ignore */ + "tests/data/acpi/pc/SSDT.dimmpxm", + "tests/data/acpi/q35/SSDT.dimmpxm", ++"tests/data/acpi/virt/DSDT.memhp", ++"tests/data/acpi/virt/SSDT.memhp", ++"tests/data/acpi/virt/NFIT.memhp", +-- +2.23.0 + diff --git a/tests-Use-child_of_bds-instead-of-child_file.patch b/tests-Use-child_of_bds-instead-of-child_file.patch new file mode 100644 index 0000000000000000000000000000000000000000..353a9a3f2b0823ebe15f6536f88e7b3e60bead5d --- /dev/null +++ b/tests-Use-child_of_bds-instead-of-child_file.patch @@ -0,0 +1,133 @@ +From a16be3cdfce2379b5fb0a17a3017a6c59d73388d Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Wed, 13 May 2020 13:05:38 +0200 +Subject: [PATCH 560/709] tests: Use child_of_bds instead of child_file + +Signed-off-by: Max Reitz +Reviewed-by: Eric Blake +Message-Id: <20200513110544.176672-29-mreitz@redhat.com> +Signed-off-by: Kevin Wolf +--- + tests/test-bdrv-drain.c | 29 +++++++++++++++++------------ + tests/test-bdrv-graph-mod.c | 6 ++++-- + 2 files changed, 21 insertions(+), 14 deletions(-) + +diff --git a/tests/test-bdrv-drain.c b/tests/test-bdrv-drain.c +index 15393a0140..91567ca97d 100644 +--- a/tests/test-bdrv-drain.c ++++ b/tests/test-bdrv-drain.c +@@ -97,7 +97,7 @@ static void bdrv_test_child_perm(BlockDriverState *bs, BdrvChild *c, + * detach_by_driver_cb_parent as one of them. + */ + if (child_class != &child_file && child_class != &child_of_bds) { +- child_class = &child_file; ++ child_class = &child_of_bds; + } + + bdrv_format_default_perms(bs, c, child_class, role, reopen_queue, +@@ -1203,7 +1203,8 @@ static void do_test_delete_by_drain(bool detach_instead_of_delete, + + null_bs = bdrv_open("null-co://", NULL, NULL, BDRV_O_RDWR | BDRV_O_PROTOCOL, + &error_abort); +- bdrv_attach_child(bs, null_bs, "null-child", &child_file, 0, &error_abort); ++ bdrv_attach_child(bs, null_bs, "null-child", &child_of_bds, ++ BDRV_CHILD_DATA, &error_abort); + + /* This child will be the one to pass to requests through to, and + * it will stall until a drain occurs */ +@@ -1211,14 +1212,17 @@ static void do_test_delete_by_drain(bool detach_instead_of_delete, + &error_abort); + child_bs->total_sectors = 65536 >> BDRV_SECTOR_BITS; + /* Takes our reference to child_bs */ +- tts->wait_child = bdrv_attach_child(bs, child_bs, "wait-child", &child_file, +- 0, &error_abort); ++ tts->wait_child = bdrv_attach_child(bs, child_bs, "wait-child", ++ &child_of_bds, ++ BDRV_CHILD_DATA | BDRV_CHILD_PRIMARY, ++ &error_abort); + + /* This child is just there to be deleted + * (for detach_instead_of_delete == true) */ + null_bs = bdrv_open("null-co://", NULL, NULL, BDRV_O_RDWR | BDRV_O_PROTOCOL, + &error_abort); +- bdrv_attach_child(bs, null_bs, "null-child", &child_file, 0, &error_abort); ++ bdrv_attach_child(bs, null_bs, "null-child", &child_of_bds, BDRV_CHILD_DATA, ++ &error_abort); + + blk = blk_new(qemu_get_aio_context(), BLK_PERM_ALL, BLK_PERM_ALL); + blk_insert_bs(blk, bs, &error_abort); +@@ -1315,7 +1319,8 @@ static void detach_indirect_bh(void *opaque) + + bdrv_ref(data->c); + data->child_c = bdrv_attach_child(data->parent_b, data->c, "PB-C", +- &child_file, 0, &error_abort); ++ &child_of_bds, BDRV_CHILD_DATA, ++ &error_abort); + } + + static void detach_by_parent_aio_cb(void *opaque, int ret) +@@ -1332,7 +1337,7 @@ static void detach_by_driver_cb_drained_begin(BdrvChild *child) + { + aio_bh_schedule_oneshot(qemu_get_current_aio_context(), + detach_indirect_bh, &detach_by_parent_data); +- child_file.drained_begin(child); ++ child_of_bds.drained_begin(child); + } + + static BdrvChildClass detach_by_driver_cb_class; +@@ -1367,7 +1372,7 @@ static void test_detach_indirect(bool by_parent_cb) + QEMUIOVector qiov = QEMU_IOVEC_INIT_BUF(qiov, NULL, 0); + + if (!by_parent_cb) { +- detach_by_driver_cb_class = child_file; ++ detach_by_driver_cb_class = child_of_bds; + detach_by_driver_cb_class.drained_begin = + detach_by_driver_cb_drained_begin; + } +@@ -1397,15 +1402,15 @@ static void test_detach_indirect(bool by_parent_cb) + /* Set child relationships */ + bdrv_ref(b); + bdrv_ref(a); +- child_b = bdrv_attach_child(parent_b, b, "PB-B", &child_file, 0, +- &error_abort); ++ child_b = bdrv_attach_child(parent_b, b, "PB-B", &child_of_bds, ++ BDRV_CHILD_DATA, &error_abort); + child_a = bdrv_attach_child(parent_b, a, "PB-A", &child_of_bds, + BDRV_CHILD_COW, &error_abort); + + bdrv_ref(a); + bdrv_attach_child(parent_a, a, "PA-A", +- by_parent_cb ? &child_file : &detach_by_driver_cb_class, +- 0, &error_abort); ++ by_parent_cb ? &child_of_bds : &detach_by_driver_cb_class, ++ BDRV_CHILD_DATA, &error_abort); + + g_assert_cmpint(parent_a->refcnt, ==, 1); + g_assert_cmpint(parent_b->refcnt, ==, 1); +diff --git a/tests/test-bdrv-graph-mod.c b/tests/test-bdrv-graph-mod.c +index 3707e2533c..6ae91ff171 100644 +--- a/tests/test-bdrv-graph-mod.c ++++ b/tests/test-bdrv-graph-mod.c +@@ -112,7 +112,8 @@ static void test_update_perm_tree(void) + + blk_insert_bs(root, bs, &error_abort); + +- bdrv_attach_child(filter, bs, "child", &child_file, 0, &error_abort); ++ bdrv_attach_child(filter, bs, "child", &child_of_bds, ++ BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY, &error_abort); + + bdrv_append(filter, bs, &local_err); + +@@ -178,7 +179,8 @@ static void test_should_update_child(void) + bdrv_set_backing_hd(target, bs, &error_abort); + + g_assert(target->backing->bs == bs); +- bdrv_attach_child(filter, target, "target", &child_file, 0, &error_abort); ++ bdrv_attach_child(filter, target, "target", &child_of_bds, ++ BDRV_CHILD_DATA, &error_abort); + bdrv_append(filter, bs, &error_abort); + g_assert(target->backing->bs == bs); + +-- +2.23.0 + diff --git a/tests-acceptance-Add-a-test-for-the-canon-a1100-mach.patch b/tests-acceptance-Add-a-test-for-the-canon-a1100-mach.patch new file mode 100644 index 0000000000000000000000000000000000000000..c8671977edeaa3d26c67289d2e537a6db9feb39e --- /dev/null +++ b/tests-acceptance-Add-a-test-for-the-canon-a1100-mach.patch @@ -0,0 +1,86 @@ +From 56c2c59252deb5676f63faf69a1b5fb97372b551 Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Thu, 14 May 2020 21:04:22 +0200 +Subject: [PATCH 606/709] tests/acceptance: Add a test for the canon-a1100 + machine +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The canon-a1100 machine can be used with the Barebox firmware. The +QEMU Advent Calendar 2018 features a pre-compiled image which we +can use for testing. + +Reviewed-by: Philippe Mathieu-Daudé +Tested-by: Philippe Mathieu-Daudé +Reviewed-by: Wainer dos Santos Moschetta +Tested-by: Wainer dos Santos Moschetta +Signed-off-by: Thomas Huth +Signed-off-by: Philippe Mathieu-Daudé +Message-id: 20200514190422.23645-1-f4bug@amsat.org +Message-Id: <20200129090420.13954-1-thuth@redhat.com> +[PMD: Rebased MAINTAINERS] +Signed-off-by: Philippe Mathieu-Daudé +Signed-off-by: Peter Maydell +--- + MAINTAINERS | 1 + + tests/acceptance/machine_arm_canona1100.py | 35 ++++++++++++++++++++++ + 2 files changed, 36 insertions(+) + create mode 100644 tests/acceptance/machine_arm_canona1100.py + +diff --git a/MAINTAINERS b/MAINTAINERS +index 87a412c229..1e006c98fa 100644 +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -608,6 +608,7 @@ S: Odd Fixes + F: include/hw/arm/digic.h + F: hw/*/digic* + F: include/hw/*/digic* ++F: tests/acceptance/machine_arm_canona1100.py + + Goldfish RTC + M: Anup Patel +diff --git a/tests/acceptance/machine_arm_canona1100.py b/tests/acceptance/machine_arm_canona1100.py +new file mode 100644 +index 0000000000..0e5c43dbcf +--- /dev/null ++++ b/tests/acceptance/machine_arm_canona1100.py +@@ -0,0 +1,35 @@ ++# Functional test that boots the canon-a1100 machine with firmware ++# ++# Copyright (c) 2020 Red Hat, Inc. ++# ++# Author: ++# Thomas Huth ++# ++# This work is licensed under the terms of the GNU GPL, version 2 or ++# later. See the COPYING file in the top-level directory. ++ ++from avocado_qemu import Test ++from avocado_qemu import wait_for_console_pattern ++from avocado.utils import archive ++ ++class CanonA1100Machine(Test): ++ """Boots the barebox firmware and checks that the console is operational""" ++ ++ timeout = 90 ++ ++ def test_arm_canona1100(self): ++ """ ++ :avocado: tags=arch:arm ++ :avocado: tags=machine:canon-a1100 ++ :avocado: tags=device:pflash_cfi02 ++ """ ++ tar_url = ('https://www.qemu-advent-calendar.org' ++ '/2018/download/day18.tar.xz') ++ tar_hash = '068b5fc4242b29381acee94713509f8a876e9db6' ++ file_path = self.fetch_asset(tar_url, asset_hash=tar_hash) ++ archive.extract(file_path, self.workdir) ++ self.vm.set_console() ++ self.vm.add_args('-bios', ++ self.workdir + '/day18/barebox.canon-a1100.bin') ++ self.vm.launch() ++ wait_for_console_pattern(self, 'running /env/bin/init') +-- +2.23.0 + diff --git a/tests-acpi-add-expected-tables-for-bios-tables-test.patch b/tests-acpi-add-expected-tables-for-bios-tables-test.patch new file mode 100644 index 0000000000000000000000000000000000000000..5e2387232f4c426be06cca85911ed0b143501f7d --- /dev/null +++ b/tests-acpi-add-expected-tables-for-bios-tables-test.patch @@ -0,0 +1,35 @@ +From e302bb3da6b59ad22c2157bbaac299a301780ba1 Mon Sep 17 00:00:00 2001 +From: Shameer Kolothum +Date: Tue, 21 Apr 2020 13:59:34 +0100 +Subject: [PATCH 224/709] tests/acpi: add expected tables for bios-tables-test + +Because of the following changes, the expeacted tables for bios-tables-test +needs to be updated. + +1. Changed NVDIM DSM output buffer AML code. +2. Updated arm/virt test_acpi_virt_tcg_memhp() to add pc-dimm/nvdimm + +Signed-off-by: Shameer Kolothum +Message-Id: <20200421125934.14952-8-shameerali.kolothum.thodi@huawei.com> +Acked-by: Peter Maydell +Tested-by: Eric Auger +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +--- + tests/qtest/bios-tables-test-allowed-diff.h | 5 ----- + 1 files changed, 5 deletions(-) + +diff --git a/tests/qtest/bios-tables-test-allowed-diff.h b/tests/qtest/bios-tables-test-allowed-diff.h +index 862c49e675..dfb8523c8b 100644 +--- a/tests/qtest/bios-tables-test-allowed-diff.h ++++ b/tests/qtest/bios-tables-test-allowed-diff.h +@@ -1,6 +1 @@ + /* List of comma-separated changed AML files to ignore */ +-"tests/data/acpi/pc/SSDT.dimmpxm", +-"tests/data/acpi/q35/SSDT.dimmpxm", +-"tests/data/acpi/virt/DSDT.memhp", +-"tests/data/acpi/virt/SSDT.memhp", +-"tests/data/acpi/virt/NFIT.memhp", +-- +2.23.0 + diff --git a/tests-boot_linux_console-Add-ethernet-test-to-SmartF.patch b/tests-boot_linux_console-Add-ethernet-test-to-SmartF.patch new file mode 100644 index 0000000000000000000000000000000000000000..16c53d7ee5e11cd90b7bc160aa9d01ae1bee645b --- /dev/null +++ b/tests-boot_linux_console-Add-ethernet-test-to-SmartF.patch @@ -0,0 +1,60 @@ +From 70d7857f935ab3fd6a5c0ff8b7586d0aef20f8b0 Mon Sep 17 00:00:00 2001 +From: Subbaraya Sundeep +Date: Thu, 16 Apr 2020 20:24:51 +0530 +Subject: [PATCH 101/709] tests/boot_linux_console: Add ethernet test to + SmartFusion2 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +In addition to simple serial test this patch uses ping +to test the ethernet block modelled in SmartFusion2 SoC. + +Signed-off-by: Subbaraya Sundeep +Reviewed-by: Philippe Mathieu-Daudé +Tested-by: Philippe Mathieu-Daudé +Message-id: 1587048891-30493-4-git-send-email-sundeep.lkml@gmail.com +Signed-off-by: Peter Maydell +--- + tests/acceptance/boot_linux_console.py | 15 ++++++++++----- + 1 file changed, 10 insertions(+), 5 deletions(-) + +diff --git a/tests/acceptance/boot_linux_console.py b/tests/acceptance/boot_linux_console.py +index f825cd9ef5..c6b06a1a13 100644 +--- a/tests/acceptance/boot_linux_console.py ++++ b/tests/acceptance/boot_linux_console.py +@@ -336,13 +336,13 @@ class BootLinuxConsole(Test): + """ + uboot_url = ('https://raw.githubusercontent.com/' + 'Subbaraya-Sundeep/qemu-test-binaries/' +- 'fa030bd77a014a0b8e360d3b7011df89283a2f0b/u-boot') +- uboot_hash = 'abba5d9c24cdd2d49cdc2a8aa92976cf20737eff' ++ 'fe371d32e50ca682391e1e70ab98c2942aeffb01/u-boot') ++ uboot_hash = 'cbb8cbab970f594bf6523b9855be209c08374ae2' + uboot_path = self.fetch_asset(uboot_url, asset_hash=uboot_hash) + spi_url = ('https://raw.githubusercontent.com/' + 'Subbaraya-Sundeep/qemu-test-binaries/' +- 'fa030bd77a014a0b8e360d3b7011df89283a2f0b/spi.bin') +- spi_hash = '85f698329d38de63aea6e884a86fbde70890a78a' ++ 'fe371d32e50ca682391e1e70ab98c2942aeffb01/spi.bin') ++ spi_hash = '65523a1835949b6f4553be96dec1b6a38fb05501' + spi_path = self.fetch_asset(spi_url, asset_hash=spi_hash) + + self.vm.set_console() +@@ -352,7 +352,12 @@ class BootLinuxConsole(Test): + '-drive', 'file=' + spi_path + ',if=mtd,format=raw', + '-no-reboot') + self.vm.launch() +- self.wait_for_console_pattern('init started: BusyBox') ++ self.wait_for_console_pattern('Enter \'help\' for a list') ++ ++ exec_command_and_wait_for_pattern(self, 'ifconfig eth0 10.0.2.15', ++ 'eth0: link becomes ready') ++ exec_command_and_wait_for_pattern(self, 'ping -c 3 10.0.2.2', ++ '3 packets transmitted, 3 packets received, 0% packet loss') + + def do_test_arm_raspi2(self, uart_id): + """ +-- +2.23.0 + diff --git a/tests-check-qom-proplist-Improve-iterator-coverage.patch b/tests-check-qom-proplist-Improve-iterator-coverage.patch new file mode 100644 index 0000000000000000000000000000000000000000..3912898d83208b41125a26213d4c3edd66cceedc --- /dev/null +++ b/tests-check-qom-proplist-Improve-iterator-coverage.patch @@ -0,0 +1,122 @@ +From 48942138177a89c920d0a01397ccbc4040090e5e Mon Sep 17 00:00:00 2001 +From: Markus Armbruster +Date: Tue, 5 May 2020 17:29:16 +0200 +Subject: [PATCH 470/709] tests/check-qom-proplist: Improve iterator coverage + +The tests' "qemu-dummy" device has only class properties. Turn one of +them into an instance property. test_dummy_class_iterator() expects +one fewer property than test_dummy_iterator(). Rewrite +test_dummy_prop_iterator() to take expected properties as argument. + +Signed-off-by: Markus Armbruster +Reviewed-by: Eric Blake +Reviewed-by: Paolo Bonzini +Message-Id: <20200505152926.18877-9-armbru@redhat.com> +--- + tests/check-qom-proplist.c | 51 +++++++++++++++++++------------------- + 1 file changed, 26 insertions(+), 25 deletions(-) + +diff --git a/tests/check-qom-proplist.c b/tests/check-qom-proplist.c +index a8b2958e6e..140d56439a 100644 +--- a/tests/check-qom-proplist.c ++++ b/tests/check-qom-proplist.c +@@ -130,17 +130,18 @@ static void dummy_init(Object *obj) + object_property_add_bool(obj, "bv", + dummy_get_bv, + dummy_set_bv, +- &err); ++ NULL); ++ /* duplicate: */ ++ object_property_add_str(obj, "sv", ++ dummy_get_sv, ++ dummy_set_sv, ++ &err); + error_free_or_abort(&err); + } + + + static void dummy_class_init(ObjectClass *cls, void *data) + { +- object_class_property_add_bool(cls, "bv", +- dummy_get_bv, +- dummy_set_bv, +- NULL); + object_class_property_add_str(cls, "sv", + dummy_get_sv, + dummy_set_sv, +@@ -520,34 +521,33 @@ static void test_dummy_getenum(void) + } + + +-static void test_dummy_prop_iterator(ObjectPropertyIterator *iter) ++static void test_dummy_prop_iterator(ObjectPropertyIterator *iter, ++ const char *expected[], int n) + { +- bool seenbv = false, seensv = false, seenav = false, seentype = false; + ObjectProperty *prop; ++ int i; + + while ((prop = object_property_iter_next(iter))) { +- if (!seenbv && g_str_equal(prop->name, "bv")) { +- seenbv = true; +- } else if (!seensv && g_str_equal(prop->name, "sv")) { +- seensv = true; +- } else if (!seenav && g_str_equal(prop->name, "av")) { +- seenav = true; +- } else if (!seentype && g_str_equal(prop->name, "type")) { +- /* This prop comes from the base Object class */ +- seentype = true; +- } else { +- g_printerr("Found prop '%s'\n", prop->name); +- g_assert_not_reached(); ++ for (i = 0; i < n; i++) { ++ if (!g_strcmp0(prop->name, expected[i])) { ++ break; ++ } + } ++ g_assert(i < n); ++ expected[i] = NULL; ++ } ++ ++ for (i = 0; i < n; i++) { ++ g_assert(!expected[i]); + } +- g_assert(seenbv); +- g_assert(seenav); +- g_assert(seensv); +- g_assert(seentype); + } + + static void test_dummy_iterator(void) + { ++ const char *expected[] = { ++ "type", /* inherited from TYPE_OBJECT */ ++ "sv", "av", /* class properties */ ++ "bv"}; /* instance property */ + Object *parent = object_get_objects_root(); + DummyObject *dobj = DUMMY_OBJECT( + object_new_with_props(TYPE_DUMMY, +@@ -561,17 +561,18 @@ static void test_dummy_iterator(void) + ObjectPropertyIterator iter; + + object_property_iter_init(&iter, OBJECT(dobj)); +- test_dummy_prop_iterator(&iter); ++ test_dummy_prop_iterator(&iter, expected, ARRAY_SIZE(expected)); + object_unparent(OBJECT(dobj)); + } + + static void test_dummy_class_iterator(void) + { ++ const char *expected[] = { "type", "av", "sv" }; + ObjectPropertyIterator iter; + ObjectClass *klass = object_class_by_name(TYPE_DUMMY); + + object_class_property_iter_init(&iter, klass); +- test_dummy_prop_iterator(&iter); ++ test_dummy_prop_iterator(&iter, expected, ARRAY_SIZE(expected)); + } + + static void test_dummy_delchild(void) +-- +2.23.0 + diff --git a/tests-fuzz-Add-missing-space-in-test-description.patch b/tests-fuzz-Add-missing-space-in-test-description.patch new file mode 100644 index 0000000000000000000000000000000000000000..829527c695f34c308630aaa73b46db8c65f68490 --- /dev/null +++ b/tests-fuzz-Add-missing-space-in-test-description.patch @@ -0,0 +1,49 @@ +From 73ee6da45d22c82275042f7e84426e647246a56d Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Thu, 14 May 2020 16:34:30 +0200 +Subject: [PATCH 486/709] tests/fuzz: Add missing space in test description +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Philippe Mathieu-Daudé +Message-id: 20200514143433.18569-4-philmd@redhat.com +Signed-off-by: Stefan Hajnoczi +--- + tests/qtest/fuzz/i440fx_fuzz.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/tests/qtest/fuzz/i440fx_fuzz.c b/tests/qtest/fuzz/i440fx_fuzz.c +index ab5f112584..96fed9ff12 100644 +--- a/tests/qtest/fuzz/i440fx_fuzz.c ++++ b/tests/qtest/fuzz/i440fx_fuzz.c +@@ -159,7 +159,7 @@ static void register_pci_fuzz_targets(void) + /* Uses simple qtest commands and reboots to reset state */ + fuzz_add_target(&(FuzzTarget){ + .name = "i440fx-qtest-reboot-fuzz", +- .description = "Fuzz the i440fx using raw qtest commands and" ++ .description = "Fuzz the i440fx using raw qtest commands and " + "rebooting after each run", + .get_init_cmdline = i440fx_argv, + .fuzz = i440fx_fuzz_qtest}); +@@ -167,7 +167,7 @@ static void register_pci_fuzz_targets(void) + /* Uses libqos and forks to prevent state leakage */ + fuzz_add_qos_target(&(FuzzTarget){ + .name = "i440fx-qos-fork-fuzz", +- .description = "Fuzz the i440fx using raw qtest commands and" ++ .description = "Fuzz the i440fx using raw qtest commands and " + "rebooting after each run", + .pre_vm_init = &fork_init, + .fuzz = i440fx_fuzz_qos_fork,}, +@@ -182,7 +182,7 @@ static void register_pci_fuzz_targets(void) + */ + fuzz_add_qos_target(&(FuzzTarget){ + .name = "i440fx-qos-noreset-fuzz", +- .description = "Fuzz the i440fx using raw qtest commands and" ++ .description = "Fuzz the i440fx using raw qtest commands and " + "rebooting after each run", + .fuzz = i440fx_fuzz_qos,}, + "i440FX-pcihost", +-- +2.23.0 + diff --git a/tests-fuzz-Extract-ioport_fuzz_qtest-method.patch b/tests-fuzz-Extract-ioport_fuzz_qtest-method.patch new file mode 100644 index 0000000000000000000000000000000000000000..759f2eb00a9fb85980390a57ff1990c91cc7c33f --- /dev/null +++ b/tests-fuzz-Extract-ioport_fuzz_qtest-method.patch @@ -0,0 +1,54 @@ +From 6fb5f0842aab0f744eebfabefb447b3a3a1af7cc Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Thu, 14 May 2020 16:34:33 +0200 +Subject: [PATCH 489/709] tests/fuzz: Extract ioport_fuzz_qtest() method +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Extract generic ioport_fuzz_qtest() method from +i440fx_fuzz_qtest(). This will help to write tests +not specific to the i440FX controller. + +Signed-off-by: Philippe Mathieu-Daudé +Message-id: 20200514143433.18569-7-philmd@redhat.com +Signed-off-by: Stefan Hajnoczi +--- + tests/qtest/fuzz/i440fx_fuzz.c | 11 +++++++++-- + 1 file changed, 9 insertions(+), 2 deletions(-) + +diff --git a/tests/qtest/fuzz/i440fx_fuzz.c b/tests/qtest/fuzz/i440fx_fuzz.c +index 558fa17c93..bcd6769b4c 100644 +--- a/tests/qtest/fuzz/i440fx_fuzz.c ++++ b/tests/qtest/fuzz/i440fx_fuzz.c +@@ -39,7 +39,7 @@ enum action_id { + ACTION_MAX + }; + +-static void i440fx_fuzz_qtest(QTestState *s, ++static void ioport_fuzz_qtest(QTestState *s, + const unsigned char *Data, size_t Size) { + /* + * loop over the Data, breaking it up into actions. each action has an +@@ -84,10 +84,17 @@ static void i440fx_fuzz_qtest(QTestState *s, + flush_events(s); + } + ++static void i440fx_fuzz_qtest(QTestState *s, ++ const unsigned char *Data, ++ size_t Size) ++{ ++ ioport_fuzz_qtest(s, Data, Size); ++} ++ + static void pciconfig_fuzz_qos(QTestState *s, QPCIBus *bus, + const unsigned char *Data, size_t Size) { + /* +- * Same as i440fx_fuzz_qtest, but using QOS. devfn is incorporated into the ++ * Same as ioport_fuzz_qtest, but using QOS. devfn is incorporated into the + * value written over Port IO + */ + struct { +-- +2.23.0 + diff --git a/tests-fuzz-Extract-pciconfig_fuzz_qos-method.patch b/tests-fuzz-Extract-pciconfig_fuzz_qos-method.patch new file mode 100644 index 0000000000000000000000000000000000000000..8fe4da5b8bf20db89c633ae168980f51815922a8 --- /dev/null +++ b/tests-fuzz-Extract-pciconfig_fuzz_qos-method.patch @@ -0,0 +1,67 @@ +From 84cb0a6d20c94abab6bc868e0e92044fcebdb1d7 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Thu, 14 May 2020 16:34:32 +0200 +Subject: [PATCH 488/709] tests/fuzz: Extract pciconfig_fuzz_qos() method +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Extract the generic pciconfig_fuzz_qos() method from +i440fx_fuzz_qos(). This will help to write tests not +specific to the i440FX controller. + +Signed-off-by: Philippe Mathieu-Daudé +Message-id: 20200514143433.18569-6-philmd@redhat.com +Signed-off-by: Stefan Hajnoczi +--- + tests/qtest/fuzz/i440fx_fuzz.c | 20 ++++++++++++++------ + 1 file changed, 14 insertions(+), 6 deletions(-) + +diff --git a/tests/qtest/fuzz/i440fx_fuzz.c b/tests/qtest/fuzz/i440fx_fuzz.c +index c197b026db..558fa17c93 100644 +--- a/tests/qtest/fuzz/i440fx_fuzz.c ++++ b/tests/qtest/fuzz/i440fx_fuzz.c +@@ -84,7 +84,7 @@ static void i440fx_fuzz_qtest(QTestState *s, + flush_events(s); + } + +-static void i440fx_fuzz_qos(QTestState *s, ++static void pciconfig_fuzz_qos(QTestState *s, QPCIBus *bus, + const unsigned char *Data, size_t Size) { + /* + * Same as i440fx_fuzz_qtest, but using QOS. devfn is incorporated into the +@@ -97,11 +97,6 @@ static void i440fx_fuzz_qos(QTestState *s, + uint32_t value; + } a; + +- static QPCIBus *bus; +- if (!bus) { +- bus = qpci_new_pc(s, fuzz_qos_alloc); +- } +- + while (Size >= sizeof(a)) { + memcpy(&a, Data, sizeof(a)); + switch (a.opcode % ACTION_MAX) { +@@ -130,6 +125,19 @@ static void i440fx_fuzz_qos(QTestState *s, + flush_events(s); + } + ++static void i440fx_fuzz_qos(QTestState *s, ++ const unsigned char *Data, ++ size_t Size) ++{ ++ static QPCIBus *bus; ++ ++ if (!bus) { ++ bus = qpci_new_pc(s, fuzz_qos_alloc); ++ } ++ ++ pciconfig_fuzz_qos(s, bus, Data, Size); ++} ++ + static void i440fx_fuzz_qos_fork(QTestState *s, + const unsigned char *Data, size_t Size) { + if (fork() == 0) { +-- +2.23.0 + diff --git a/tests-fuzz-Makefile-Do-not-link-code-using-unavailab.patch b/tests-fuzz-Makefile-Do-not-link-code-using-unavailab.patch new file mode 100644 index 0000000000000000000000000000000000000000..d28f4a2f42e2db66939fc3cf8187ce0af00ec74b --- /dev/null +++ b/tests-fuzz-Makefile-Do-not-link-code-using-unavailab.patch @@ -0,0 +1,40 @@ +From a1dcdda8275e15ab919bcec012e9e662283b6a7d Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Thu, 14 May 2020 16:34:28 +0200 +Subject: [PATCH 484/709] tests/fuzz/Makefile: Do not link code using + unavailable devices +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Some devices availability depends on CONFIG options. +Use these options to only link tests when requested device +is available. + +Signed-off-by: Philippe Mathieu-Daudé +Message-id: 20200514143433.18569-2-philmd@redhat.com +Signed-off-by: Stefan Hajnoczi +--- + tests/qtest/fuzz/Makefile.include | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/tests/qtest/fuzz/Makefile.include b/tests/qtest/fuzz/Makefile.include +index cde3e9636c..f259d866c9 100644 +--- a/tests/qtest/fuzz/Makefile.include ++++ b/tests/qtest/fuzz/Makefile.include +@@ -7,9 +7,9 @@ fuzz-obj-y += tests/qtest/fuzz/fork_fuzz.o + fuzz-obj-y += tests/qtest/fuzz/qos_fuzz.o + + # Targets +-fuzz-obj-y += tests/qtest/fuzz/i440fx_fuzz.o +-fuzz-obj-y += tests/qtest/fuzz/virtio_net_fuzz.o +-fuzz-obj-y += tests/qtest/fuzz/virtio_scsi_fuzz.o ++fuzz-obj-$(CONFIG_PCI_I440FX) += tests/qtest/fuzz/i440fx_fuzz.o ++fuzz-obj-$(CONFIG_VIRTIO_NET) += tests/qtest/fuzz/virtio_net_fuzz.o ++fuzz-obj-$(CONFIG_SCSI) += tests/qtest/fuzz/virtio_scsi_fuzz.o + + FUZZ_CFLAGS += -I$(SRC_PATH)/tests -I$(SRC_PATH)/tests/qtest + +-- +2.23.0 + diff --git a/tests-fuzz-Remove-unuseful-unused-typedefs.patch b/tests-fuzz-Remove-unuseful-unused-typedefs.patch new file mode 100644 index 0000000000000000000000000000000000000000..ba8f1c7d09940e1221313adce51a43bb304ca777 --- /dev/null +++ b/tests-fuzz-Remove-unuseful-unused-typedefs.patch @@ -0,0 +1,62 @@ +From 79e18a60ab456764eaa974b67b9c54281a5156db Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Thu, 14 May 2020 16:34:31 +0200 +Subject: [PATCH 487/709] tests/fuzz: Remove unuseful/unused typedefs +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +These typedefs are not used. Use a simple structure, +remote the typedefs. + +Signed-off-by: Philippe Mathieu-Daudé +Message-id: 20200514143433.18569-5-philmd@redhat.com +Signed-off-by: Stefan Hajnoczi +--- + tests/qtest/fuzz/i440fx_fuzz.c | 10 ++++------ + 1 file changed, 4 insertions(+), 6 deletions(-) + +diff --git a/tests/qtest/fuzz/i440fx_fuzz.c b/tests/qtest/fuzz/i440fx_fuzz.c +index 96fed9ff12..c197b026db 100644 +--- a/tests/qtest/fuzz/i440fx_fuzz.c ++++ b/tests/qtest/fuzz/i440fx_fuzz.c +@@ -45,12 +45,11 @@ static void i440fx_fuzz_qtest(QTestState *s, + * loop over the Data, breaking it up into actions. each action has an + * opcode, address offset and value + */ +- typedef struct QTestFuzzAction { ++ struct { + uint8_t opcode; + uint8_t addr; + uint32_t value; +- } QTestFuzzAction; +- QTestFuzzAction a; ++ } a; + + while (Size >= sizeof(a)) { + /* make a copy of the action so we can normalize the values in-place */ +@@ -91,19 +90,18 @@ static void i440fx_fuzz_qos(QTestState *s, + * Same as i440fx_fuzz_qtest, but using QOS. devfn is incorporated into the + * value written over Port IO + */ +- typedef struct QOSFuzzAction { ++ struct { + uint8_t opcode; + uint8_t offset; + int devfn; + uint32_t value; +- } QOSFuzzAction; ++ } a; + + static QPCIBus *bus; + if (!bus) { + bus = qpci_new_pc(s, fuzz_qos_alloc); + } + +- QOSFuzzAction a; + while (Size >= sizeof(a)) { + memcpy(&a, Data, sizeof(a)); + switch (a.opcode % ACTION_MAX) { +-- +2.23.0 + diff --git a/tests-guest-debug-catch-hanging-guests.patch b/tests-guest-debug-catch-hanging-guests.patch new file mode 100644 index 0000000000000000000000000000000000000000..db7b24b2f04ccc6b5f5fb6b0b396fcf5418a1c67 --- /dev/null +++ b/tests-guest-debug-catch-hanging-guests.patch @@ -0,0 +1,35 @@ +From b03e4ffffb1e4a34cb0985f5f5c4a2cfb272e697 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Alex=20Benn=C3=A9e?= +Date: Wed, 13 May 2020 18:51:25 +0100 +Subject: [PATCH 490/709] tests/guest-debug: catch hanging guests +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +If gdb never actually connected with the guest we need to catch that +and clean-up after ourselves. + +Signed-off-by: Alex Bennée +Message-Id: <20200513175134.19619-2-alex.bennee@linaro.org> +--- + tests/guest-debug/run-test.py | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/tests/guest-debug/run-test.py b/tests/guest-debug/run-test.py +index d9af9573b9..71c5569054 100755 +--- a/tests/guest-debug/run-test.py ++++ b/tests/guest-debug/run-test.py +@@ -80,4 +80,10 @@ if __name__ == '__main__': + print("GDB crashed? SKIPPING") + exit(0) + ++ try: ++ inferior.wait(2) ++ except subprocess.TimeoutExpired: ++ print("GDB never connected? Killed guest") ++ inferior.kill() ++ + exit(result) +-- +2.23.0 + diff --git a/tests-guest-debug-use-the-unix-socket-for-linux-user.patch b/tests-guest-debug-use-the-unix-socket-for-linux-user.patch new file mode 100644 index 0000000000000000000000000000000000000000..d0d34084d2a6f694a75f6e1bf1234300235c5091 --- /dev/null +++ b/tests-guest-debug-use-the-unix-socket-for-linux-user.patch @@ -0,0 +1,63 @@ +From b0dc2a8ba5709fe10a57e1ff5ee7d6004942e614 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Alex=20Benn=C3=A9e?= +Date: Thu, 30 Apr 2020 20:01:20 +0100 +Subject: [PATCH 277/709] tests/guest-debug: use the unix socket for linux-user + tests +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Now we have support for debugging over a unix socket for linux-user +lets use it in our test harness. + +Signed-off-by: Alex Bennée +Message-Id: <20200430190122.4592-8-alex.bennee@linaro.org> +--- + tests/guest-debug/run-test.py | 13 +++++++++++-- + 1 file changed, 11 insertions(+), 2 deletions(-) + +diff --git a/tests/guest-debug/run-test.py b/tests/guest-debug/run-test.py +index 2bbb8fbaa3..d9af9573b9 100755 +--- a/tests/guest-debug/run-test.py ++++ b/tests/guest-debug/run-test.py +@@ -15,6 +15,8 @@ import argparse + import subprocess + import shutil + import shlex ++import os ++from tempfile import TemporaryDirectory + + def get_args(): + parser = argparse.ArgumentParser(description="A gdbstub test runner") +@@ -41,11 +43,15 @@ if __name__ == '__main__': + print("We need gdb to run the test") + exit(-1) + ++ socket_dir = TemporaryDirectory("qemu-gdbstub") ++ socket_name = os.path.join(socket_dir.name, "gdbstub.socket") ++ + # Launch QEMU with binary + if "system" in args.qemu: + cmd = "%s %s %s -s -S" % (args.qemu, args.qargs, args.binary) + else: +- cmd = "%s %s -g 1234 %s" % (args.qemu, args.qargs, args.binary) ++ cmd = "%s %s -g %s %s" % (args.qemu, args.qargs, socket_name, ++ args.binary) + + inferior = subprocess.Popen(shlex.split(cmd)) + +@@ -56,7 +62,10 @@ if __name__ == '__main__': + # disable prompts in case of crash + gdb_cmd += " -ex 'set confirm off'" + # connect to remote +- gdb_cmd += " -ex 'target remote localhost:1234'" ++ if "system" in args.qemu: ++ gdb_cmd += " -ex 'target remote localhost:1234'" ++ else: ++ gdb_cmd += " -ex 'target remote %s'" % (socket_name) + # finally the test script itself + gdb_cmd += " -x %s" % (args.test) + +-- +2.23.0 + diff --git a/tests-qemu-opts-Cover-has_help_option-qemu_opt_has_h.patch b/tests-qemu-opts-Cover-has_help_option-qemu_opt_has_h.patch new file mode 100644 index 0000000000000000000000000000000000000000..3a9b348bf596bfafd8b459a4e334bbada5c2ab51 --- /dev/null +++ b/tests-qemu-opts-Cover-has_help_option-qemu_opt_has_h.patch @@ -0,0 +1,81 @@ +From 32c2dcf5e87bf05153df92e49de75f72d4466e4e Mon Sep 17 00:00:00 2001 +From: Markus Armbruster +Date: Wed, 15 Apr 2020 09:49:19 +0200 +Subject: [PATCH 005/709] tests-qemu-opts: Cover has_help_option(), + qemu_opt_has_help_opt() + +The two turn out to be inconsistent for "a,b,,help". Test case +marked /* BUG */. + +Signed-off-by: Markus Armbruster +Message-Id: <20200415074927.19897-2-armbru@redhat.com> +Reviewed-by: Eric Blake +--- + tests/test-qemu-opts.c | 44 ++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 44 insertions(+) + +diff --git a/tests/test-qemu-opts.c b/tests/test-qemu-opts.c +index ef96e84aed..88a3e7bdf4 100644 +--- a/tests/test-qemu-opts.c ++++ b/tests/test-qemu-opts.c +@@ -728,6 +728,49 @@ static void test_opts_parse_size(void) + qemu_opts_reset(&opts_list_02); + } + ++static void test_has_help_option(void) ++{ ++ static const struct { ++ const char *params; ++ /* expected value of has_help_option() */ ++ bool expect_has_help_option; ++ /* expected value of qemu_opt_has_help_opt() with implied=false */ ++ bool expect_opt_has_help_opt; ++ /* expected value of qemu_opt_has_help_opt() with implied=true */ ++ bool expect_opt_has_help_opt_implied; ++ } test[] = { ++ { "help", true, true, false }, ++ { "?", true, true, false }, ++ { "helpme", false, false, false }, ++ { "?me", false, false, false }, ++ { "a,help", true, true, true }, ++ { "a,?", true, true, true }, ++ { "a=0,help,b", true, true, true }, ++ { "a=0,?,b", true, true, true }, ++ { "help,b=1", true, true, false }, ++ { "?,b=1", true, true, false }, ++ { "a,b,,help", false /* BUG */, true, true }, ++ { "a,b,,?", false /* BUG */, true, true }, ++ }; ++ int i; ++ QemuOpts *opts; ++ ++ for (i = 0; i < ARRAY_SIZE(test); i++) { ++ g_assert_cmpint(has_help_option(test[i].params), ++ ==, test[i].expect_has_help_option); ++ opts = qemu_opts_parse(&opts_list_03, test[i].params, false, ++ &error_abort); ++ g_assert_cmpint(qemu_opt_has_help_opt(opts), ++ ==, test[i].expect_opt_has_help_opt); ++ qemu_opts_del(opts); ++ opts = qemu_opts_parse(&opts_list_03, test[i].params, true, ++ &error_abort); ++ g_assert_cmpint(qemu_opt_has_help_opt(opts), ++ ==, test[i].expect_opt_has_help_opt_implied); ++ qemu_opts_del(opts); ++ } ++} ++ + static void append_verify_list_01(QemuOptDesc *desc, bool with_overlapping) + { + int i = 0; +@@ -990,6 +1033,7 @@ int main(int argc, char *argv[]) + g_test_add_func("/qemu-opts/opts_parse/bool", test_opts_parse_bool); + g_test_add_func("/qemu-opts/opts_parse/number", test_opts_parse_number); + g_test_add_func("/qemu-opts/opts_parse/size", test_opts_parse_size); ++ g_test_add_func("/qemu-opts/has_help_option", test_has_help_option); + g_test_add_func("/qemu-opts/append_to_null", test_opts_append_to_null); + g_test_add_func("/qemu-opts/append", test_opts_append); + g_test_add_func("/qemu-opts/to_qdict/basic", test_opts_to_qdict_basic); +-- +2.23.0 + diff --git a/tests-tcg-add-a-multiarch-linux-user-gdb-test.patch b/tests-tcg-add-a-multiarch-linux-user-gdb-test.patch new file mode 100644 index 0000000000000000000000000000000000000000..67eb1b28bfe2c00f256f92f674a1ed1c2f5470d6 --- /dev/null +++ b/tests-tcg-add-a-multiarch-linux-user-gdb-test.patch @@ -0,0 +1,172 @@ +From df3ca22318c01428e82cbe4d2777cdf97c9c1f06 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Alex=20Benn=C3=A9e?= +Date: Thu, 30 Apr 2020 20:01:21 +0100 +Subject: [PATCH 278/709] tests/tcg: add a multiarch linux-user gdb test +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +When the gdbstub code was converted to the new API we missed a few +snafus in the various guests. Add a simple gdb test script which can +be used on all our linux-user guests to check for obvious failures. + +Signed-off-by: Alex Bennée +Reviewed-by: Richard Henderson +Message-Id: <20200430190122.4592-9-alex.bennee@linaro.org> +--- + tests/tcg/aarch64/Makefile.target | 5 +- + tests/tcg/cris/Makefile.target | 1 + + tests/tcg/multiarch/Makefile.target | 14 +++++ + tests/tcg/multiarch/gdbstub/sha1.py | 81 +++++++++++++++++++++++++++++ + 4 files changed, 98 insertions(+), 3 deletions(-) + create mode 100644 tests/tcg/multiarch/gdbstub/sha1.py + +diff --git a/tests/tcg/aarch64/Makefile.target b/tests/tcg/aarch64/Makefile.target +index d99b2a9ece..312f36cde5 100644 +--- a/tests/tcg/aarch64/Makefile.target ++++ b/tests/tcg/aarch64/Makefile.target +@@ -54,9 +54,6 @@ sve-ioctls: CFLAGS+=-march=armv8.1-a+sve + ifneq ($(HAVE_GDB_BIN),) + GDB_SCRIPT=$(SRC_PATH)/tests/guest-debug/run-test.py + +-AARCH64_TESTS += gdbstub-sysregs gdbstub-sve-ioctls +- +-.PHONY: gdbstub-sysregs gdbstub-sve-ioctls + run-gdbstub-sysregs: sysregs + $(call run-test, $@, $(GDB_SCRIPT) \ + --gdb $(HAVE_GDB_BIN) \ +@@ -70,6 +67,8 @@ run-gdbstub-sve-ioctls: sve-ioctls + --qemu $(QEMU) --qargs "$(QEMU_OPTS)" \ + --bin $< --test $(AARCH64_SRC)/gdbstub/test-sve-ioctl.py, \ + "basic gdbstub SVE ZLEN support") ++ ++EXTRA_RUNS += run-gdbstub-sysregs run-gdbstub-sve-ioctls + endif + + endif +diff --git a/tests/tcg/cris/Makefile.target b/tests/tcg/cris/Makefile.target +index 24c7f2e761..e72d3cbdb2 100644 +--- a/tests/tcg/cris/Makefile.target ++++ b/tests/tcg/cris/Makefile.target +@@ -23,6 +23,7 @@ CRIS_RUNS = $(patsubst %, run-%, $(CRIS_USABLE_TESTS)) + + # override the list of tests, as we can't build the multiarch tests + TESTS = $(CRIS_USABLE_TESTS) ++EXTRA_RUNS = + VPATH = $(CRIS_SRC) + + AS = $(CC) -x assembler-with-cpp +diff --git a/tests/tcg/multiarch/Makefile.target b/tests/tcg/multiarch/Makefile.target +index 035b09c853..51fb75ecfd 100644 +--- a/tests/tcg/multiarch/Makefile.target ++++ b/tests/tcg/multiarch/Makefile.target +@@ -42,5 +42,19 @@ run-test-mmap-%: test-mmap + $(call run-test, test-mmap-$*, $(QEMU) -p $* $<,\ + "$< ($* byte pages) on $(TARGET_NAME)") + ++ifneq ($(HAVE_GDB_BIN),) ++GDB_SCRIPT=$(SRC_PATH)/tests/guest-debug/run-test.py ++ ++run-gdbstub-sha1: sha1 ++ $(call run-test, $@, $(GDB_SCRIPT) \ ++ --gdb $(HAVE_GDB_BIN) \ ++ --qemu $(QEMU) --qargs "$(QEMU_OPTS)" \ ++ --bin $< --test $(MULTIARCH_SRC)/gdbstub/sha1.py, \ ++ "basic gdbstub support") ++ ++EXTRA_RUNS += run-gdbstub-sha1 ++endif ++ ++ + # Update TESTS + TESTS += $(MULTIARCH_TESTS) +diff --git a/tests/tcg/multiarch/gdbstub/sha1.py b/tests/tcg/multiarch/gdbstub/sha1.py +new file mode 100644 +index 0000000000..734553b98b +--- /dev/null ++++ b/tests/tcg/multiarch/gdbstub/sha1.py +@@ -0,0 +1,81 @@ ++from __future__ import print_function ++# ++# A very simple smoke test for debugging the SHA1 userspace test on ++# each target. ++# ++# This is launched via tests/guest-debug/run-test.py ++# ++ ++import gdb ++import sys ++ ++initial_vlen = 0 ++failcount = 0 ++ ++def report(cond, msg): ++ "Report success/fail of test" ++ if cond: ++ print("PASS: %s" % (msg)) ++ else: ++ print("FAIL: %s" % (msg)) ++ global failcount ++ failcount += 1 ++ ++def check_break(sym_name): ++ "Setup breakpoint, continue and check we stopped." ++ sym, ok = gdb.lookup_symbol(sym_name) ++ bp = gdb.Breakpoint(sym_name) ++ ++ gdb.execute("c") ++ ++ # hopefully we came back ++ end_pc = gdb.parse_and_eval('$pc') ++ report(bp.hit_count == 1, ++ "break @ %s (%s %d hits)" % (end_pc, sym.value(), bp.hit_count)) ++ ++ bp.delete() ++ ++def run_test(): ++ "Run through the tests one by one" ++ ++ check_break("SHA1Init") ++ ++ # check step and inspect values ++ gdb.execute("next") ++ val_ctx = gdb.parse_and_eval("context->state[0]") ++ exp_ctx = 0x67452301 ++ report(int(val_ctx) == exp_ctx, "context->state[0] == %x" % exp_ctx); ++ ++ gdb.execute("next") ++ val_ctx = gdb.parse_and_eval("context->state[1]") ++ exp_ctx = 0xEFCDAB89 ++ report(int(val_ctx) == exp_ctx, "context->state[1] == %x" % exp_ctx); ++ ++ # finally check we don't barf inspecting registers ++ gdb.execute("info registers") ++ ++# ++# This runs as the script it sourced (via -x, via run-test.py) ++# ++try: ++ inferior = gdb.selected_inferior() ++ arch = inferior.architecture() ++ print("ATTACHED: %s" % arch.name()) ++except (gdb.error, AttributeError): ++ print("SKIPPING (not connected)", file=sys.stderr) ++ exit(0) ++ ++try: ++ # These are not very useful in scripts ++ gdb.execute("set pagination off") ++ gdb.execute("set confirm off") ++ ++ # Run the actual tests ++ run_test() ++except (gdb.error): ++ print ("GDB Exception: %s" % (sys.exc_info()[0])) ++ failcount += 1 ++ pass ++ ++print("All tests complete: %d failures" % failcount) ++exit(failcount) +-- +2.23.0 + diff --git a/tests-tcg-better-trap-gdb-failures.patch b/tests-tcg-better-trap-gdb-failures.patch new file mode 100644 index 0000000000000000000000000000000000000000..15347c9a41266a9ac658d21bfc8f28c68e7c5510 --- /dev/null +++ b/tests-tcg-better-trap-gdb-failures.patch @@ -0,0 +1,82 @@ +From d2fefdedd3a65eaf22d8546835c225c3661e23d8 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Alex=20Benn=C3=A9e?= +Date: Thu, 30 Apr 2020 20:01:16 +0100 +Subject: [PATCH 273/709] tests/tcg: better trap gdb failures +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +It seems older and non-multiarach aware GDBs might not fail gracefully +when faced with something they don't know. For example when faced with +a target XML for s390x the Ubuntu 18.04 gdb will generate an internal +fault and prompt for a core dump. + +Work around this by invoking GDB in a more batch orientated way and +then trying to filter out between test failures and gdb failures. + +Signed-off-by: Alex Bennée +Message-Id: <20200430190122.4592-4-alex.bennee@linaro.org> +--- + tests/guest-debug/run-test.py | 19 ++++++++++++++++++- + tests/tcg/aarch64/gdbstub/test-sve-ioctl.py | 1 - + tests/tcg/aarch64/gdbstub/test-sve.py | 1 - + 3 files changed, 18 insertions(+), 3 deletions(-) + +diff --git a/tests/guest-debug/run-test.py b/tests/guest-debug/run-test.py +index 8c49ee2f22..2bbb8fbaa3 100755 +--- a/tests/guest-debug/run-test.py ++++ b/tests/guest-debug/run-test.py +@@ -50,8 +50,25 @@ if __name__ == '__main__': + inferior = subprocess.Popen(shlex.split(cmd)) + + # Now launch gdb with our test and collect the result +- gdb_cmd = "%s %s -ex 'target remote localhost:1234' -x %s" % (args.gdb, args.binary, args.test) ++ gdb_cmd = "%s %s" % (args.gdb, args.binary) ++ # run quietly and ignore .gdbinit ++ gdb_cmd += " -q -n -batch" ++ # disable prompts in case of crash ++ gdb_cmd += " -ex 'set confirm off'" ++ # connect to remote ++ gdb_cmd += " -ex 'target remote localhost:1234'" ++ # finally the test script itself ++ gdb_cmd += " -x %s" % (args.test) ++ ++ print("GDB CMD: %s" % (gdb_cmd)) + + result = subprocess.call(gdb_cmd, shell=True); + ++ # A negative result is the result of an internal gdb failure like ++ # a crash. We force a return of 0 so we don't fail the test on ++ # account of broken external tools. ++ if result < 0: ++ print("GDB crashed? SKIPPING") ++ exit(0) ++ + exit(result) +diff --git a/tests/tcg/aarch64/gdbstub/test-sve-ioctl.py b/tests/tcg/aarch64/gdbstub/test-sve-ioctl.py +index 984fbeb277..387b2fc20a 100644 +--- a/tests/tcg/aarch64/gdbstub/test-sve-ioctl.py ++++ b/tests/tcg/aarch64/gdbstub/test-sve-ioctl.py +@@ -70,7 +70,6 @@ except (gdb.error, AttributeError): + try: + # These are not very useful in scripts + gdb.execute("set pagination off") +- gdb.execute("set confirm off") + + # Run the actual tests + run_test() +diff --git a/tests/tcg/aarch64/gdbstub/test-sve.py b/tests/tcg/aarch64/gdbstub/test-sve.py +index dbe7f2aa93..5995689625 100644 +--- a/tests/tcg/aarch64/gdbstub/test-sve.py ++++ b/tests/tcg/aarch64/gdbstub/test-sve.py +@@ -71,7 +71,6 @@ except (gdb.error, AttributeError): + try: + # These are not very useful in scripts + gdb.execute("set pagination off") +- gdb.execute("set confirm off") + + # Run the actual tests + run_test() +-- +2.23.0 + diff --git a/tests-tcg-drop-inferior.was_attached-test.patch b/tests-tcg-drop-inferior.was_attached-test.patch new file mode 100644 index 0000000000000000000000000000000000000000..10b6a10b8e33886a24881adf9a3bcf72191e41e8 --- /dev/null +++ b/tests-tcg-drop-inferior.was_attached-test.patch @@ -0,0 +1,51 @@ +From 744f1b0f6888b07c9870329ae9f40b8e641db0ce Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Alex=20Benn=C3=A9e?= +Date: Thu, 30 Apr 2020 20:01:17 +0100 +Subject: [PATCH 274/709] tests/tcg: drop inferior.was_attached() test +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This test seems flaky and reports attachment even when we failed to +negotiate the architecture. However the fetching of the guest +architecture will fail tripping up the gdb AttributeError which will +trigger our early no error status exit from the test + +Signed-off-by: Alex Bennée +Message-Id: <20200430190122.4592-5-alex.bennee@linaro.org> +--- + tests/tcg/aarch64/gdbstub/test-sve-ioctl.py | 3 --- + tests/tcg/aarch64/gdbstub/test-sve.py | 3 --- + 2 files changed, 6 deletions(-) + +diff --git a/tests/tcg/aarch64/gdbstub/test-sve-ioctl.py b/tests/tcg/aarch64/gdbstub/test-sve-ioctl.py +index 387b2fc20a..972cf73c31 100644 +--- a/tests/tcg/aarch64/gdbstub/test-sve-ioctl.py ++++ b/tests/tcg/aarch64/gdbstub/test-sve-ioctl.py +@@ -58,9 +58,6 @@ def run_test(): + # + try: + inferior = gdb.selected_inferior() +- if inferior.was_attached == False: +- print("SKIPPING (failed to attach)", file=sys.stderr) +- exit(0) + arch = inferior.architecture() + report(arch.name() == "aarch64", "connected to aarch64") + except (gdb.error, AttributeError): +diff --git a/tests/tcg/aarch64/gdbstub/test-sve.py b/tests/tcg/aarch64/gdbstub/test-sve.py +index 5995689625..b96bdbb99a 100644 +--- a/tests/tcg/aarch64/gdbstub/test-sve.py ++++ b/tests/tcg/aarch64/gdbstub/test-sve.py +@@ -59,9 +59,6 @@ def run_test(): + # + try: + inferior = gdb.selected_inferior() +- if inferior.was_attached == False: +- print("SKIPPING (failed to attach)", file=sys.stderr) +- exit(0) + arch = inferior.architecture() + report(arch.name() == "aarch64", "connected to aarch64") + except (gdb.error, AttributeError): +-- +2.23.0 + diff --git a/tests-test-logging-Fix-test-for-dfilter-0.0xffffffff.patch b/tests-test-logging-Fix-test-for-dfilter-0.0xffffffff.patch new file mode 100644 index 0000000000000000000000000000000000000000..00029903907f6b9702116562985c58e035b688b9 --- /dev/null +++ b/tests-test-logging-Fix-test-for-dfilter-0.0xffffffff.patch @@ -0,0 +1,37 @@ +From 131889924bb31a6a371ed9300efb2036edd6b40b Mon Sep 17 00:00:00 2001 +From: Markus Armbruster +Date: Wed, 22 Apr 2020 15:07:17 +0200 +Subject: [PATCH 025/709] tests/test-logging: Fix test for -dfilter + 0..0xffffffffffffffff +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Fixes: 58e19e6e7914354242a67442d0006f9e31684d1a +Signed-off-by: Markus Armbruster +Message-Id: <20200422130719.28225-13-armbru@redhat.com> +Reviewed-by: Philippe Mathieu-Daudé +--- + tests/test-logging.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/tests/test-logging.c b/tests/test-logging.c +index 6387e4933f..8580b82420 100644 +--- a/tests/test-logging.c ++++ b/tests/test-logging.c +@@ -73,10 +73,10 @@ static void test_parse_range(void) + g_assert(qemu_log_in_addr_range(UINT64_MAX)); + g_assert_false(qemu_log_in_addr_range(UINT64_MAX - 1)); + +- qemu_set_dfilter_ranges("0..0xffffffffffffffff", &err); ++ qemu_set_dfilter_ranges("0..0xffffffffffffffff", &error_abort); + g_assert(qemu_log_in_addr_range(0)); + g_assert(qemu_log_in_addr_range(UINT64_MAX)); +- ++ + qemu_set_dfilter_ranges("2..1", &err); + error_free_or_abort(&err); + +-- +2.23.0 + diff --git a/tests-util-sockets-add-abstract-unix-socket-cases.patch b/tests-util-sockets-add-abstract-unix-socket-cases.patch new file mode 100644 index 0000000000000000000000000000000000000000..c143cab7bd72c8482a7c6e14afe642be9c953873 --- /dev/null +++ b/tests-util-sockets-add-abstract-unix-socket-cases.patch @@ -0,0 +1,129 @@ +From 4d3a329af59ef8acd076f99f05e82531d8129b34 Mon Sep 17 00:00:00 2001 +From: xiaoqiang zhao +Date: Sat, 16 May 2020 11:13:26 +0800 +Subject: [PATCH 604/709] tests/util-sockets: add abstract unix socket cases +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +add cases to test tight and non-tight for abstract address type + +Signed-off-by: xiaoqiang zhao +Signed-off-by: Daniel P. Berrangé +--- + tests/test-util-sockets.c | 92 +++++++++++++++++++++++++++++++++++++++ + 1 file changed, 92 insertions(+) + +diff --git a/tests/test-util-sockets.c b/tests/test-util-sockets.c +index 5fd947c7bf..2ca1e99f17 100644 +--- a/tests/test-util-sockets.c ++++ b/tests/test-util-sockets.c +@@ -227,6 +227,93 @@ static void test_socket_fd_pass_num_nocli(void) + g_free(addr.u.fd.str); + } + ++#ifdef __linux__ ++static gchar *abstract_sock_name; ++ ++static gpointer unix_server_thread_func(gpointer user_data) ++{ ++ SocketAddress addr; ++ Error *err = NULL; ++ int fd = -1; ++ int connfd = -1; ++ struct sockaddr_un un; ++ socklen_t len = sizeof(un); ++ ++ addr.type = SOCKET_ADDRESS_TYPE_UNIX; ++ addr.u.q_unix.path = abstract_sock_name; ++ addr.u.q_unix.tight = user_data != NULL; ++ addr.u.q_unix.abstract = true; ++ ++ fd = socket_listen(&addr, 1, &err); ++ g_assert_cmpint(fd, >=, 0); ++ g_assert(fd_is_socket(fd)); ++ ++ connfd = accept(fd, (struct sockaddr *)&un, &len); ++ g_assert_cmpint(connfd, !=, -1); ++ ++ close(fd); ++ ++ return NULL; ++} ++ ++static gpointer unix_client_thread_func(gpointer user_data) ++{ ++ SocketAddress addr; ++ Error *err = NULL; ++ int fd = -1; ++ ++ addr.type = SOCKET_ADDRESS_TYPE_UNIX; ++ addr.u.q_unix.path = abstract_sock_name; ++ addr.u.q_unix.tight = user_data != NULL; ++ addr.u.q_unix.abstract = true; ++ ++ fd = socket_connect(&addr, &err); ++ ++ g_assert_cmpint(fd, >=, 0); ++ ++ close(fd); ++ ++ return NULL; ++} ++ ++static void test_socket_unix_abstract_good(void) ++{ ++ GRand *r = g_rand_new(); ++ ++ abstract_sock_name = g_strdup_printf("unix-%d-%d", getpid(), ++ g_rand_int_range(r, 100, 1000)); ++ ++ /* non tight socklen serv and cli */ ++ GThread *serv = g_thread_new("abstract_unix_server", ++ unix_server_thread_func, ++ NULL); ++ ++ sleep(1); ++ ++ GThread *cli = g_thread_new("abstract_unix_client", ++ unix_client_thread_func, ++ NULL); ++ ++ g_thread_join(cli); ++ g_thread_join(serv); ++ ++ /* tight socklen serv and cli */ ++ serv = g_thread_new("abstract_unix_server", ++ unix_server_thread_func, ++ (gpointer)1); ++ ++ sleep(1); ++ ++ cli = g_thread_new("abstract_unix_client", ++ unix_client_thread_func, ++ (gpointer)1); ++ ++ g_thread_join(cli); ++ g_thread_join(serv); ++ ++ g_free(abstract_sock_name); ++} ++#endif + + int main(int argc, char **argv) + { +@@ -265,6 +352,11 @@ int main(int argc, char **argv) + test_socket_fd_pass_num_nocli); + } + ++#ifdef __linux__ ++ g_test_add_func("/util/socket/unix-abstract/good", ++ test_socket_unix_abstract_good); ++#endif ++ + end: + return g_test_run(); + } +-- +2.23.0 + diff --git a/timer-exynos4210_mct-Remove-redundant-statement-in-e.patch b/timer-exynos4210_mct-Remove-redundant-statement-in-e.patch new file mode 100644 index 0000000000000000000000000000000000000000..81283c018369cfb36899d8b975b32436019a8e06 --- /dev/null +++ b/timer-exynos4210_mct-Remove-redundant-statement-in-e.patch @@ -0,0 +1,63 @@ +From 237d8f09635e01ff2c4e4c8ca28d14b92dfcd8bf Mon Sep 17 00:00:00 2001 +From: Chen Qun +Date: Wed, 25 Mar 2020 10:59:19 +0800 +Subject: [PATCH 148/709] timer/exynos4210_mct: Remove redundant statement in + exynos4210_mct_write() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Clang static code analyzer show warning: +hw/timer/exynos4210_mct.c:1370:9: warning: Value stored to 'index' is never read + index = GET_L_TIMER_CNT_REG_IDX(offset, lt_i); + ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +hw/timer/exynos4210_mct.c:1399:9: warning: Value stored to 'index' is never read + index = GET_L_TIMER_CNT_REG_IDX(offset, lt_i); + ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +hw/timer/exynos4210_mct.c:1441:9: warning: Value stored to 'index' is never read + index = GET_L_TIMER_CNT_REG_IDX(offset, lt_i); + ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Reported-by: Euler Robot +Signed-off-by: Chen Qun +Reviewed-by: Laurent Vivier +Reviewed-by: Alistair Francis +Reviewed-by: Philippe Mathieu-Daudé +Message-Id: <20200325025919.21316-4-kuhn.chenqun@huawei.com> +Signed-off-by: Laurent Vivier +--- + hw/timer/exynos4210_mct.c | 4 ---- + 1 file changed, 4 deletions(-) + +diff --git a/hw/timer/exynos4210_mct.c b/hw/timer/exynos4210_mct.c +index 944120aea5..570cf7075b 100644 +--- a/hw/timer/exynos4210_mct.c ++++ b/hw/timer/exynos4210_mct.c +@@ -1367,7 +1367,6 @@ static void exynos4210_mct_write(void *opaque, hwaddr offset, + + case L0_TCNTB: case L1_TCNTB: + lt_i = GET_L_TIMER_IDX(offset); +- index = GET_L_TIMER_CNT_REG_IDX(offset, lt_i); + + /* + * TCNTB is updated to internal register only after CNT expired. +@@ -1396,7 +1395,6 @@ static void exynos4210_mct_write(void *opaque, hwaddr offset, + + case L0_ICNTB: case L1_ICNTB: + lt_i = GET_L_TIMER_IDX(offset); +- index = GET_L_TIMER_CNT_REG_IDX(offset, lt_i); + + s->l_timer[lt_i].reg.wstat |= L_WSTAT_ICNTB_WRITE; + s->l_timer[lt_i].reg.cnt[L_REG_CNT_ICNTB] = value & +@@ -1438,8 +1436,6 @@ static void exynos4210_mct_write(void *opaque, hwaddr offset, + + case L0_FRCNTB: case L1_FRCNTB: + lt_i = GET_L_TIMER_IDX(offset); +- index = GET_L_TIMER_CNT_REG_IDX(offset, lt_i); +- + DPRINTF("local timer[%d] FRCNTB write %llx\n", lt_i, value); + + s->l_timer[lt_i].reg.wstat |= L_WSTAT_FRCCNTB_WRITE; +-- +2.23.0 + diff --git a/tools-Fix-use-of-fcntl-F_SETFD-during-socket-activat.patch b/tools-Fix-use-of-fcntl-F_SETFD-during-socket-activat.patch new file mode 100644 index 0000000000000000000000000000000000000000..f66c2bec721183ec77747e655222e64a8e9a1f87 --- /dev/null +++ b/tools-Fix-use-of-fcntl-F_SETFD-during-socket-activat.patch @@ -0,0 +1,47 @@ +From 474a6e64f2c3c17718b853b9d70e054ee8d26f37 Mon Sep 17 00:00:00 2001 +From: Eric Blake +Date: Mon, 20 Apr 2020 12:53:08 -0500 +Subject: [PATCH 237/709] tools: Fix use of fcntl(F_SETFD) during socket + activation + +Blindly setting FD_CLOEXEC without a read-modify-write will +inadvertently clear any other intentionally-set bits, such as a +proposed new bit for designating a fd that must behave in 32-bit mode. +However, we cannot use our wrapper qemu_set_cloexec(), because that +wrapper intentionally abort()s on failure, whereas the probe here +intentionally tolerates failure to deal with incorrect socket +activation gracefully. Instead, fix the code to do the proper +read-modify-write. + +Signed-off-by: Eric Blake +Message-Id: <20200420175309.75894-3-eblake@redhat.com> +Reviewed-by: Peter Maydell +--- + util/systemd.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/util/systemd.c b/util/systemd.c +index 1dd0367d9a..5bcac9b401 100644 +--- a/util/systemd.c ++++ b/util/systemd.c +@@ -23,6 +23,7 @@ unsigned int check_socket_activation(void) + unsigned long nr_fds; + unsigned int i; + int fd; ++ int f; + int err; + + s = getenv("LISTEN_PID"); +@@ -54,7 +55,8 @@ unsigned int check_socket_activation(void) + /* So the file descriptors don't leak into child processes. */ + for (i = 0; i < nr_fds; ++i) { + fd = FIRST_SOCKET_ACTIVATION_FD + i; +- if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1) { ++ f = fcntl(fd, F_GETFD); ++ if (f == -1 || fcntl(fd, F_SETFD, f | FD_CLOEXEC) == -1) { + /* If we cannot set FD_CLOEXEC then it probably means the file + * descriptor is invalid, so socket activation has gone wrong + * and we should exit. +-- +2.23.0 + diff --git a/tpm-tpm-tis-device-set-PPI-to-false-by-default.patch b/tpm-tpm-tis-device-set-PPI-to-false-by-default.patch new file mode 100644 index 0000000000000000000000000000000000000000..191058ff107a9824af9801ab2b6b1ff508228822 --- /dev/null +++ b/tpm-tpm-tis-device-set-PPI-to-false-by-default.patch @@ -0,0 +1,35 @@ +From ca14ba5b9af493471e10eaebb86709e98cfcd897 Mon Sep 17 00:00:00 2001 +From: Eric Auger +Date: Mon, 27 Apr 2020 16:31:44 +0200 +Subject: [PATCH 280/709] tpm: tpm-tis-device: set PPI to false by default + +The tpm-tis-device device does not support PPI. Let's +change the default value for the corresponding property +instead of tricking this latter in the mach-virt machine. + +Signed-off-by: Eric Auger +Reviewed-by: Cornelia Huck +Reviewed-by: Stefan Berger +Reviewed-by: Peter Maydell +Signed-off-by: Stefan Berger +Message-id: 20200427143145.16251-2-eric.auger@redhat.com +--- + hw/tpm/tpm_tis_sysbus.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/hw/tpm/tpm_tis_sysbus.c b/hw/tpm/tpm_tis_sysbus.c +index 18c02aed67..eced1fc843 100644 +--- a/hw/tpm/tpm_tis_sysbus.c ++++ b/hw/tpm/tpm_tis_sysbus.c +@@ -91,7 +91,7 @@ static void tpm_tis_sysbus_reset(DeviceState *dev) + static Property tpm_tis_sysbus_properties[] = { + DEFINE_PROP_UINT32("irq", TPMStateSysBus, state.irq_num, TPM_TIS_IRQ), + DEFINE_PROP_TPMBE("tpmdev", TPMStateSysBus, state.be_driver), +- DEFINE_PROP_BOOL("ppi", TPMStateSysBus, state.ppi_enabled, true), ++ DEFINE_PROP_BOOL("ppi", TPMStateSysBus, state.ppi_enabled, false), + DEFINE_PROP_END_OF_LIST(), + }; + +-- +2.23.0 + diff --git a/translate-all-include-guest-address-in-out_asm-outpu.patch b/translate-all-include-guest-address-in-out_asm-outpu.patch new file mode 100644 index 0000000000000000000000000000000000000000..3e41310a24459c11a559721ae4ef350e9debb829 --- /dev/null +++ b/translate-all-include-guest-address-in-out_asm-outpu.patch @@ -0,0 +1,88 @@ +From 5f0df0333b20be816ae54a3fa6476f79f9da160e Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Alex=20Benn=C3=A9e?= +Date: Wed, 13 May 2020 18:51:34 +0100 +Subject: [PATCH 498/709] translate-all: include guest address in out_asm + output +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +We already have information about where each guest instructions +representation starts stored in the tcg_ctx->gen_insn_data so we can +rectify the PC for faults. We can re-use this information to annotate +the out_asm output with guest instruction address which makes it a bit +easier to work out where you are especially with longer blocks. A +minor wrinkle is that some instructions get optimised away so we have +to scan forward until we find some actual generated code. + +Signed-off-by: Alex Bennée + +Message-Id: <20200513175134.19619-11-alex.bennee@linaro.org> +--- + accel/tcg/translate-all.c | 39 +++++++++++++++++++++++++++++++++------ + 1 file changed, 33 insertions(+), 6 deletions(-) + +diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c +index cdf58bb420..42ce1dfcff 100644 +--- a/accel/tcg/translate-all.c ++++ b/accel/tcg/translate-all.c +@@ -1794,14 +1794,43 @@ TranslationBlock *tb_gen_code(CPUState *cpu, + if (qemu_loglevel_mask(CPU_LOG_TB_OUT_ASM) && + qemu_log_in_addr_range(tb->pc)) { + FILE *logfile = qemu_log_lock(); ++ int code_size, data_size = 0; ++ g_autoptr(GString) note = g_string_new("[tb header & initial instruction]"); ++ size_t chunk_start = 0; ++ int insn = 0; + qemu_log("OUT: [size=%d]\n", gen_code_size); + if (tcg_ctx->data_gen_ptr) { +- size_t code_size = tcg_ctx->data_gen_ptr - tb->tc.ptr; +- size_t data_size = gen_code_size - code_size; +- size_t i; ++ code_size = tcg_ctx->data_gen_ptr - tb->tc.ptr; ++ data_size = gen_code_size - code_size; ++ } else { ++ code_size = gen_code_size; ++ } + +- log_disas(tb->tc.ptr, code_size, NULL); ++ /* Dump header and the first instruction */ ++ chunk_start = tcg_ctx->gen_insn_end_off[insn]; ++ log_disas(tb->tc.ptr, chunk_start, note->str); + ++ /* ++ * Dump each instruction chunk, wrapping up empty chunks into ++ * the next instruction. The whole array is offset so the ++ * first entry is the beginning of the 2nd instruction. ++ */ ++ while (insn <= tb->icount && chunk_start < code_size) { ++ size_t chunk_end = tcg_ctx->gen_insn_end_off[insn]; ++ if (chunk_end > chunk_start) { ++ g_string_printf(note, "[guest addr: " TARGET_FMT_lx "]", ++ tcg_ctx->gen_insn_data[insn][0]); ++ log_disas(tb->tc.ptr + chunk_start, chunk_end - chunk_start, ++ note->str); ++ chunk_start = chunk_end; ++ } ++ insn++; ++ } ++ ++ /* Finally dump any data we may have after the block */ ++ if (data_size) { ++ int i; ++ qemu_log(" data: [size=%d]\n", data_size); + for (i = 0; i < data_size; i += sizeof(tcg_target_ulong)) { + if (sizeof(tcg_target_ulong) == 8) { + qemu_log("0x%08" PRIxPTR ": .quad 0x%016" PRIx64 "\n", +@@ -1813,8 +1842,6 @@ TranslationBlock *tb_gen_code(CPUState *cpu, + *(uint32_t *)(tcg_ctx->data_gen_ptr + i)); + } + } +- } else { +- log_disas(tb->tc.ptr, gen_code_size, NULL); + } + qemu_log("\n"); + qemu_log_flush(); +-- +2.23.0 + diff --git a/travis.yml-Improve-the-disable-tcg-test-on-s390x.patch b/travis.yml-Improve-the-disable-tcg-test-on-s390x.patch new file mode 100644 index 0000000000000000000000000000000000000000..43059e969b12fbb975c10f4cc3cc6451ff2d9744 --- /dev/null +++ b/travis.yml-Improve-the-disable-tcg-test-on-s390x.patch @@ -0,0 +1,70 @@ +From aae8b87e9c1658261f6c58ded9928d9ed24bdbef Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Wed, 13 May 2020 18:51:26 +0100 +Subject: [PATCH 491/709] travis.yml: Improve the --disable-tcg test on s390x +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Since the s390x containers do not allow KVM, we only compile-test +the --disable-tcg build on s390x and do not run the qtests. Thus, +it does not make sense to install genisoimage here, and it also does +not make sense to build the s390-ccw.img here again - it is simply +not used without the qtests. +On the other hand, if we do not build the s390-ccw.img anymore, we +can also compile with Clang - so let's use that compiler here to +get some additional test coverage. + +Signed-off-by: Thomas Huth +Reviewed-by: Philippe Mathieu-Daudé +Reviewed-by: Cornelia Huck +Signed-off-by: Alex Bennée +Message-Id: <20200512133849.10624-1-thuth@redhat.com> +Message-Id: <20200513175134.19619-3-alex.bennee@linaro.org> +--- + .travis.yml | 18 ++++-------------- + 1 file changed, 4 insertions(+), 14 deletions(-) + +diff --git a/.travis.yml b/.travis.yml +index fe708792ca..1ec8a7b465 100644 +--- a/.travis.yml ++++ b/.travis.yml +@@ -502,9 +502,10 @@ jobs: + $(exit $BUILD_RC); + fi + +- - name: "[s390x] GCC check (KVM)" ++ - name: "[s390x] Clang (disable-tcg)" + arch: s390x + dist: bionic ++ compiler: clang + addons: + apt_packages: + - libaio-dev +@@ -528,21 +529,10 @@ jobs: + - libusb-1.0-0-dev + - libvdeplug-dev + - libvte-2.91-dev +- # Tests dependencies +- - genisoimage + env: + - TEST_CMD="make check-unit" +- - CONFIG="--disable-containers --disable-tcg --enable-kvm --disable-tools" +- script: +- - ( cd ${SRC_DIR} ; git submodule update --init roms/SLOF ) +- - BUILD_RC=0 && make -j${JOBS} || BUILD_RC=$? +- - | +- if [ "$BUILD_RC" -eq 0 ] ; then +- mv pc-bios/s390-ccw/*.img pc-bios/ ; +- ${TEST_CMD} ; +- else +- $(exit $BUILD_RC); +- fi ++ - CONFIG="--disable-containers --disable-tcg --enable-kvm ++ --disable-tools --host-cc=clang --cxx=clang++" + + # Release builds + # The make-release script expect a QEMU version, so our tag must start with a 'v'. +-- +2.23.0 + diff --git a/travis.yml-drop-MacOSX.patch b/travis.yml-drop-MacOSX.patch new file mode 100644 index 0000000000000000000000000000000000000000..677658480940a09e8419e9ec465cefafc79c2ed8 --- /dev/null +++ b/travis.yml-drop-MacOSX.patch @@ -0,0 +1,70 @@ +From 22a231950c50d339fb699c09d81ab9c2b5a28279 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Alex=20Benn=C3=A9e?= +Date: Fri, 1 May 2020 12:15:03 +0100 +Subject: [PATCH 267/709] .travis.yml: drop MacOSX +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This keeps breaking on Travis so lets just fall back to the Cirrus CI +builds which seem to be better maintained. Fix up the comments while +we are doing this as we never had a windows build. + +Signed-off-by: Alex Bennée +Reviewed-by: Philippe Mathieu-Daudé +Acked-by: Richard Henderson +Message-Id: <20200501111505.4225-3-alex.bennee@linaro.org> +--- + .travis.yml | 28 +--------------------------- + 1 file changed, 1 insertion(+), 27 deletions(-) + +diff --git a/.travis.yml b/.travis.yml +index a4c3c6c805..49267b73b3 100644 +--- a/.travis.yml ++++ b/.travis.yml +@@ -9,9 +9,8 @@ compiler: + cache: + # There is one cache per branch and compiler version. + # characteristics of each job are used to identify the cache: +- # - OS name (currently, linux, osx, or windows) ++ # - OS name (currently only linux) + # - OS distribution (for Linux, xenial, trusty, or precise) +- # - macOS image name (e.g., xcode7.2) + # - Names and values of visible environment variables set in .travis.yml or Settings panel + timeout: 1200 + ccache: true +@@ -271,31 +270,6 @@ jobs: + - TEST_CMD="" + + +- # MacOSX builds - cirrus.yml also tests some MacOS builds including latest Xcode +- +- - name: "OSX Xcode 10.3" +- env: +- - BASE_CONFIG="--disable-docs --enable-tools" +- - CONFIG="--target-list=i386-softmmu,ppc-softmmu,ppc64-softmmu,m68k-softmmu,x86_64-softmmu" +- os: osx +- osx_image: xcode10.3 +- compiler: clang +- addons: +- homebrew: +- packages: +- - ccache +- - glib +- - pixman +- - gnu-sed +- - python +- update: true +- before_script: +- - brew link --overwrite python +- - export PATH="/usr/local/opt/ccache/libexec:$PATH" +- - mkdir -p ${BUILD_DIR} && cd ${BUILD_DIR} +- - ${SRC_DIR}/configure ${BASE_CONFIG} ${CONFIG} || { cat config.log && exit 1; } +- +- + # Python builds + - name: "GCC Python 3.5 (x86_64-softmmu)" + env: +-- +2.23.0 + diff --git a/travis.yml-reduce-the-load-on-ppc64-GCC-check-tcg.patch b/travis.yml-reduce-the-load-on-ppc64-GCC-check-tcg.patch new file mode 100644 index 0000000000000000000000000000000000000000..921ff45002d260cad28d7e644bd5e6ed69c65edd --- /dev/null +++ b/travis.yml-reduce-the-load-on-ppc64-GCC-check-tcg.patch @@ -0,0 +1,34 @@ +From daee97f618e1831e38fec01c47bf2881ecf5bded Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Alex=20Benn=C3=A9e?= +Date: Fri, 1 May 2020 12:15:05 +0100 +Subject: [PATCH 270/709] .travis.yml: reduce the load on [ppc64] GCC check-tcg +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This seems to be timing out quite often and occasionally running out +of disk space. Relegate it to light duties. + +Signed-off-by: Alex Bennée +Reviewed-by: Richard Henderson +Message-Id: <20200501111505.4225-5-alex.bennee@linaro.org> +--- + .travis.yml | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/.travis.yml b/.travis.yml +index 49267b73b3..fe708792ca 100644 +--- a/.travis.yml ++++ b/.travis.yml +@@ -458,7 +458,7 @@ jobs: + - genisoimage + env: + - TEST_CMD="make check check-tcg V=1" +- - CONFIG="--disable-containers --target-list=${MAIN_SOFTMMU_TARGETS},ppc64le-linux-user" ++ - CONFIG="--disable-containers --target-list=ppc64-softmmu,ppc64le-linux-user" + + - name: "[s390x] GCC check-tcg" + arch: s390x +-- +2.23.0 + diff --git a/travis.yml-show-free-disk-space-at-end-of-run.patch b/travis.yml-show-free-disk-space-at-end-of-run.patch new file mode 100644 index 0000000000000000000000000000000000000000..d368b40eb77cfd6cbae1299345ed4845ed435785 --- /dev/null +++ b/travis.yml-show-free-disk-space-at-end-of-run.patch @@ -0,0 +1,30 @@ +From 4f8bde527626930421675411c58e9603bf205f3f Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Alex=20Benn=C3=A9e?= +Date: Fri, 1 May 2020 12:15:02 +0100 +Subject: [PATCH 266/709] .travis.yml: show free disk space at end of run +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Alex Bennée +Reviewed-by: Philippe Mathieu-Daudé +Message-Id: <20200501111505.4225-2-alex.bennee@linaro.org> +--- + .travis.yml | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/.travis.yml b/.travis.yml +index 2fd63eceaa..a4c3c6c805 100644 +--- a/.travis.yml ++++ b/.travis.yml +@@ -113,6 +113,7 @@ script: + $(exit $BUILD_RC); + fi + after_script: ++ - df -h + - if command -v ccache ; then ccache --show-stats ; fi + + +-- +2.23.0 + diff --git a/ui-gkt-release-all-keys-on-grab-broken-event.patch b/ui-gkt-release-all-keys-on-grab-broken-event.patch new file mode 100644 index 0000000000000000000000000000000000000000..ef3f91bee7ce15dbfa729a3310b49bdb3ff21e67 --- /dev/null +++ b/ui-gkt-release-all-keys-on-grab-broken-event.patch @@ -0,0 +1,62 @@ +From 0c4b1a7dc597499814d6222da4c95cbf9de68ba6 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Volker=20R=C3=BCmelin?= +Date: Sat, 16 May 2020 09:20:06 +0200 +Subject: [PATCH 577/709] ui/gkt: release all keys on grab-broken-event +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +There is no way to grab the Ctrl-Alt-Del key combination on +Windows. This key combination will leave all three keys in a +stuck condition. This patch uses the grab-broken-event to +release the keys. + +Signed-off-by: Volker Rümelin +Message-id: 20200516072014.7766-3-vr_qemu@t-online.de +Signed-off-by: Gerd Hoffmann +--- + ui/gtk.c | 21 +++++++++++++++++++++ + 1 file changed, 21 insertions(+) + +diff --git a/ui/gtk.c b/ui/gtk.c +index a0b10a1403..655b26de38 100644 +--- a/ui/gtk.c ++++ b/ui/gtk.c +@@ -1142,6 +1142,25 @@ static gboolean gd_key_event(GtkWidget *widget, GdkEventKey *key, void *opaque) + return TRUE; + } + ++static gboolean gd_grab_broken_event(GtkWidget *widget, ++ GdkEventGrabBroken *event, void *opaque) ++{ ++#ifdef CONFIG_WIN32 ++ /* ++ * On Windows the Ctrl-Alt-Del key combination can't be grabbed. This ++ * key combination leaves all three keys in a stuck condition. We use ++ * the grab-broken-event to release all keys. ++ */ ++ if (event->keyboard) { ++ VirtualConsole *vc = opaque; ++ GtkDisplayState *s = vc->s; ++ ++ gtk_release_modifiers(s); ++ } ++#endif ++ return TRUE; ++} ++ + static gboolean gd_event(GtkWidget *widget, GdkEvent *event, void *opaque) + { + if (event->type == GDK_MOTION_NOTIFY) { +@@ -1910,6 +1929,8 @@ static void gd_connect_vc_gfx_signals(VirtualConsole *vc) + G_CALLBACK(gd_focus_out_event), vc); + g_signal_connect(vc->gfx.drawing_area, "configure-event", + G_CALLBACK(gd_configure), vc); ++ g_signal_connect(vc->gfx.drawing_area, "grab-broken-event", ++ G_CALLBACK(gd_grab_broken_event), vc); + } else { + g_signal_connect(vc->gfx.drawing_area, "key-press-event", + G_CALLBACK(gd_text_key_down), vc); +-- +2.23.0 + diff --git a/ui-gtk-don-t-pass-on-win-keys-without-keyboard-grab.patch b/ui-gtk-don-t-pass-on-win-keys-without-keyboard-grab.patch new file mode 100644 index 0000000000000000000000000000000000000000..97f4456aba4ca29c1318ecec84a15b5248bead59 --- /dev/null +++ b/ui-gtk-don-t-pass-on-win-keys-without-keyboard-grab.patch @@ -0,0 +1,48 @@ +From d3953bf7978521b6373cb8101f594cc44b0efa9e Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Volker=20R=C3=BCmelin?= +Date: Sat, 16 May 2020 09:20:12 +0200 +Subject: [PATCH 583/709] ui/gtk: don't pass on win keys without keyboard grab +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Without keyboard grab Windows currently handles the two win keys +and the key events are also sent to the guest. This is undesir- +able. Only one program should handle key events. This patch ap- +plies commit c68f74b02e "win32: do not handle win keys when the +keyboard is not grabbed" from project spice-gtk to ui/gtk.c to +fix this problem. + +Signed-off-by: Volker Rümelin +Message-id: 20200516072014.7766-9-vr_qemu@t-online.de +Signed-off-by: Gerd Hoffmann +--- + ui/gtk.c | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +diff --git a/ui/gtk.c b/ui/gtk.c +index 354dd90e18..1d51e14bb5 100644 +--- a/ui/gtk.c ++++ b/ui/gtk.c +@@ -1095,10 +1095,17 @@ static gboolean gd_key_event(GtkWidget *widget, GdkEventKey *key, void *opaque) + VirtualConsole *vc = opaque; + int qcode; + +-#ifdef WIN32 ++#ifdef G_OS_WIN32 + /* on windows, we ought to ignore the reserved key event? */ + if (key->hardware_keycode == 0xff) + return false; ++ ++ if (!vc->s->kbd_owner) { ++ if (key->hardware_keycode == VK_LWIN || ++ key->hardware_keycode == VK_RWIN) { ++ return FALSE; ++ } ++ } + #endif + + if (key->keyval == GDK_KEY_Pause +-- +2.23.0 + diff --git a/ui-gtk-fix-handling-of-AltGr-key-on-Windows.patch b/ui-gtk-fix-handling-of-AltGr-key-on-Windows.patch new file mode 100644 index 0000000000000000000000000000000000000000..f3cdc14f236aca1668ba010998877efdcfa79608 --- /dev/null +++ b/ui-gtk-fix-handling-of-AltGr-key-on-Windows.patch @@ -0,0 +1,102 @@ +From bd593d2cd9932ea20593c4e6960d84fd59854130 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Volker=20R=C3=BCmelin?= +Date: Sat, 16 May 2020 09:20:05 +0200 +Subject: [PATCH 576/709] ui/gtk: fix handling of AltGr key on Windows +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Wire up the keyboard hooking code on Windows to fix the AltGr +key and improve keyboard grabbing. + +Signed-off-by: Volker Rümelin +Message-id: 20200516072014.7766-2-vr_qemu@t-online.de +Signed-off-by: Gerd Hoffmann +--- + ui/gtk.c | 30 +++++++++++++++++++++++++++++- + 1 file changed, 29 insertions(+), 1 deletion(-) + +diff --git a/ui/gtk.c b/ui/gtk.c +index 83f2f5d49b..a0b10a1403 100644 +--- a/ui/gtk.c ++++ b/ui/gtk.c +@@ -38,6 +38,10 @@ + + #include "ui/console.h" + #include "ui/gtk.h" ++#ifdef G_OS_WIN32 ++#include ++#endif ++#include "ui/win32-kbd-hook.h" + + #include + #include +@@ -428,6 +432,16 @@ static void gd_widget_reparent(GtkWidget *from, GtkWidget *to, + g_object_unref(G_OBJECT(widget)); + } + ++static void *gd_win32_get_hwnd(VirtualConsole *vc) ++{ ++#ifdef G_OS_WIN32 ++ return gdk_win32_window_get_impl_hwnd( ++ gtk_widget_get_window(vc->window ? vc->window : vc->s->window)); ++#else ++ return NULL; ++#endif ++} ++ + /** DisplayState Callbacks **/ + + static void gd_update(DisplayChangeListener *dcl, +@@ -1451,6 +1465,7 @@ static void gd_grab_keyboard(VirtualConsole *vc, const char *reason) + } + } + ++ win32_kbd_set_grab(true); + #if GTK_CHECK_VERSION(3, 20, 0) + gd_grab_update(vc, true, vc->s->ptr_owner == vc); + #else +@@ -1472,6 +1487,7 @@ static void gd_ungrab_keyboard(GtkDisplayState *s) + } + s->kbd_owner = NULL; + ++ win32_kbd_set_grab(false); + #if GTK_CHECK_VERSION(3, 20, 0) + gd_grab_update(vc, false, vc->s->ptr_owner == vc); + #else +@@ -1614,12 +1630,22 @@ static gboolean gd_leave_event(GtkWidget *widget, GdkEventCrossing *crossing, + return TRUE; + } + ++static gboolean gd_focus_in_event(GtkWidget *widget, ++ GdkEventFocus *event, gpointer opaque) ++{ ++ VirtualConsole *vc = opaque; ++ ++ win32_kbd_set_window(gd_win32_get_hwnd(vc)); ++ return TRUE; ++} ++ + static gboolean gd_focus_out_event(GtkWidget *widget, +- GdkEventCrossing *crossing, gpointer opaque) ++ GdkEventFocus *event, gpointer opaque) + { + VirtualConsole *vc = opaque; + GtkDisplayState *s = vc->s; + ++ win32_kbd_set_window(NULL); + gtk_release_modifiers(s); + return TRUE; + } +@@ -1878,6 +1904,8 @@ static void gd_connect_vc_gfx_signals(VirtualConsole *vc) + G_CALLBACK(gd_enter_event), vc); + g_signal_connect(vc->gfx.drawing_area, "leave-notify-event", + G_CALLBACK(gd_leave_event), vc); ++ g_signal_connect(vc->gfx.drawing_area, "focus-in-event", ++ G_CALLBACK(gd_focus_in_event), vc); + g_signal_connect(vc->gfx.drawing_area, "focus-out-event", + G_CALLBACK(gd_focus_out_event), vc); + g_signal_connect(vc->gfx.drawing_area, "configure-event", +-- +2.23.0 + diff --git a/ui-gtk-remove-unused-code.patch b/ui-gtk-remove-unused-code.patch new file mode 100644 index 0000000000000000000000000000000000000000..790a3440e2e1c6412a149aa7837d69417a9d2955 --- /dev/null +++ b/ui-gtk-remove-unused-code.patch @@ -0,0 +1,42 @@ +From 9ef99eccb10002d785279d1fd1dc5b0f4c295bef Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Volker=20R=C3=BCmelin?= +Date: Sat, 16 May 2020 09:20:07 +0200 +Subject: [PATCH 578/709] ui/gtk: remove unused code +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This code was last used before commit 2ec78706d1 "ui: convert +GTK and SDL1 frontends to keycodemapdb". + +Reviewed-by: Philippe Mathieu-Daudé +Signed-off-by: Volker Rümelin +Message-id: 20200516072014.7766-4-vr_qemu@t-online.de +Signed-off-by: Gerd Hoffmann +--- + ui/gtk.c | 9 --------- + 1 file changed, 9 deletions(-) + +diff --git a/ui/gtk.c b/ui/gtk.c +index 655b26de38..0e9503a0d1 100644 +--- a/ui/gtk.c ++++ b/ui/gtk.c +@@ -112,15 +112,6 @@ + # define VTE_CHECK_VERSION(a, b, c) 0 + #endif + +-/* Some older mingw versions lack this constant or have +- * it conditionally defined */ +-#ifdef _WIN32 +-# ifndef MAPVK_VK_TO_VSC +-# define MAPVK_VK_TO_VSC 0 +-# endif +-#endif +- +- + #define HOTKEY_MODIFIERS (GDK_CONTROL_MASK | GDK_MOD1_MASK) + + static const guint16 *keycode_map; +-- +2.23.0 + diff --git a/ui-gtk-remove-unused-variable-ignore_keys.patch b/ui-gtk-remove-unused-variable-ignore_keys.patch new file mode 100644 index 0000000000000000000000000000000000000000..52aba90b3439c6a3b2de1145a43f1e030eadac83 --- /dev/null +++ b/ui-gtk-remove-unused-variable-ignore_keys.patch @@ -0,0 +1,60 @@ +From fd7c1bea17e4aaea45c00b37b7a2af5dd72b17f8 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Volker=20R=C3=BCmelin?= +Date: Sat, 16 May 2020 09:20:08 +0200 +Subject: [PATCH 579/709] ui/gtk: remove unused variable ignore_keys +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Since the removal of GTK2 code in commit 89d85cde75 the code +around ignore_keys is unused. See commit 1a01716a30 "gtk: Avoid +accel key leakage into guest on console switch" why it was only +needed for GTK2. + +Reviewed-by: Philippe Mathieu-Daudé +Signed-off-by: Volker Rümelin +Message-id: 20200516072014.7766-5-vr_qemu@t-online.de +Signed-off-by: Gerd Hoffmann +--- + ui/gtk.c | 9 --------- + 1 file changed, 9 deletions(-) + +diff --git a/ui/gtk.c b/ui/gtk.c +index 0e9503a0d1..354dd90e18 100644 +--- a/ui/gtk.c ++++ b/ui/gtk.c +@@ -168,8 +168,6 @@ struct GtkDisplayState { + + bool external_pause_update; + +- bool ignore_keys; +- + DisplayOptions *opts; + }; + +@@ -1095,14 +1093,8 @@ static gboolean gd_text_key_down(GtkWidget *widget, + static gboolean gd_key_event(GtkWidget *widget, GdkEventKey *key, void *opaque) + { + VirtualConsole *vc = opaque; +- GtkDisplayState *s = vc->s; + int qcode; + +- if (s->ignore_keys) { +- s->ignore_keys = (key->type == GDK_KEY_PRESS); +- return TRUE; +- } +- + #ifdef WIN32 + /* on windows, we ought to ignore the reserved key event? */ + if (key->hardware_keycode == 0xff) +@@ -1204,7 +1196,6 @@ static void gd_menu_switch_vc(GtkMenuItem *item, void *opaque) + gtk_notebook_set_current_page(nb, page); + gtk_widget_grab_focus(vc->focus); + } +- s->ignore_keys = false; + } + + static void gd_accel_switch_vc(void *opaque) +-- +2.23.0 + diff --git a/ui-gtk-use-native-keyboard-scancodes-on-Windows.patch b/ui-gtk-use-native-keyboard-scancodes-on-Windows.patch new file mode 100644 index 0000000000000000000000000000000000000000..4869719cb9f8477e837ca4da535235c62787b16c --- /dev/null +++ b/ui-gtk-use-native-keyboard-scancodes-on-Windows.patch @@ -0,0 +1,101 @@ +From 145419274621f846385d35e609c051d4cbdd39a7 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Volker=20R=C3=BCmelin?= +Date: Sat, 16 May 2020 09:20:13 +0200 +Subject: [PATCH 584/709] ui/gtk: use native keyboard scancodes on Windows +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Since GTK 3.22 the function gdk_event_get_scancode() is +available. On Windows this function returns keyboard scancodes +and some extended flags. These raw keyboard scancodes are much +better suited for this use case than the half-cooked win32 +virtual-key codes because scancodes report the key position on +the keyboard and the positions are independent of national +language settings. + +Signed-off-by: Volker Rümelin +Message-id: 20200516072014.7766-10-vr_qemu@t-online.de +Signed-off-by: Gerd Hoffmann +--- + ui/gtk.c | 33 +++++++++++++++++++++++++++++---- + 1 file changed, 29 insertions(+), 4 deletions(-) + +diff --git a/ui/gtk.c b/ui/gtk.c +index 1d51e14bb5..68a5b901c7 100644 +--- a/ui/gtk.c ++++ b/ui/gtk.c +@@ -1026,8 +1026,13 @@ static const guint16 *gd_get_keymap(size_t *maplen) + #ifdef GDK_WINDOWING_WIN32 + if (GDK_IS_WIN32_DISPLAY(dpy)) { + trace_gd_keymap_windowing("win32"); ++#if GTK_CHECK_VERSION(3, 22, 0) ++ *maplen = qemu_input_map_atset1_to_qcode_len; ++ return qemu_input_map_atset1_to_qcode; ++#else + *maplen = qemu_input_map_win32_to_qcode_len; + return qemu_input_map_win32_to_qcode; ++#endif + } + #endif + +@@ -1073,6 +1078,25 @@ static int gd_map_keycode(int scancode) + return keycode_map[scancode]; + } + ++static int gd_get_keycode(GdkEventKey *key) ++{ ++#if defined G_OS_WIN32 && GTK_CHECK_VERSION(3, 22, 0) ++ int scancode = gdk_event_get_scancode((GdkEvent *)key); ++ ++ /* translate Windows native scancodes to atset1 keycodes */ ++ switch (scancode & (KF_EXTENDED | 0xff)) { ++ case 0x145: /* NUMLOCK */ ++ return scancode & 0xff; ++ } ++ ++ return scancode & KF_EXTENDED ? ++ 0xe000 | (scancode & 0xff) : scancode & 0xff; ++ ++#else ++ return key->hardware_keycode; ++#endif ++} ++ + static gboolean gd_text_key_down(GtkWidget *widget, + GdkEventKey *key, void *opaque) + { +@@ -1084,7 +1108,7 @@ static gboolean gd_text_key_down(GtkWidget *widget, + } else if (key->length) { + kbd_put_string_console(con, key->string, key->length); + } else { +- int qcode = gd_map_keycode(key->hardware_keycode); ++ int qcode = gd_map_keycode(gd_get_keycode(key)); + kbd_put_qcode_console(con, qcode, false); + } + return TRUE; +@@ -1093,7 +1117,7 @@ static gboolean gd_text_key_down(GtkWidget *widget, + static gboolean gd_key_event(GtkWidget *widget, GdkEventKey *key, void *opaque) + { + VirtualConsole *vc = opaque; +- int qcode; ++ int keycode, qcode; + + #ifdef G_OS_WIN32 + /* on windows, we ought to ignore the reserved key event? */ +@@ -1121,9 +1145,10 @@ static gboolean gd_key_event(GtkWidget *widget, GdkEventKey *key, void *opaque) + return TRUE; + } + +- qcode = gd_map_keycode(key->hardware_keycode); ++ keycode = gd_get_keycode(key); ++ qcode = gd_map_keycode(keycode); + +- trace_gd_key_event(vc->label, key->hardware_keycode, qcode, ++ trace_gd_key_event(vc->label, keycode, qcode, + (key->type == GDK_KEY_PRESS) ? "down" : "up"); + + qkbd_state_key_event(vc->gfx.kbd, qcode, +-- +2.23.0 + diff --git a/ui-improve-show-cursor-deprecation-message.patch b/ui-improve-show-cursor-deprecation-message.patch new file mode 100644 index 0000000000000000000000000000000000000000..b54840de2abac1b7ad66804ee2fed8e4edc99a0e --- /dev/null +++ b/ui-improve-show-cursor-deprecation-message.patch @@ -0,0 +1,34 @@ +From df2ac3cc12d251dcdd268038682fd27882e91bb2 Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann +Date: Tue, 7 Apr 2020 11:36:17 +0200 +Subject: [PATCH 413/709] ui: improve -show-cursor deprecation message + +Specifically explain what users should do in case they don't use +-display yet and depend on the qemu picking the ui for them. + +Signed-off-by: Gerd Hoffmann +Message-id: 20200407093617.10058-1-kraxel@redhat.com +--- + softmmu/vl.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/softmmu/vl.c b/softmmu/vl.c +index afd2615fb3..63eeb6ae1b 100644 +--- a/softmmu/vl.c ++++ b/softmmu/vl.c +@@ -3531,8 +3531,10 @@ void qemu_init(int argc, char **argv, char **envp) + no_shutdown = 1; + break; + case QEMU_OPTION_show_cursor: +- warn_report("The -show-cursor option is deprecated, " +- "use -display {sdl,gtk},show-cursor=on instead"); ++ warn_report("The -show-cursor option is deprecated. Please " ++ "add show-cursor=on to your -display options."); ++ warn_report("When using the default display you can use " ++ "-display default,show-cursor=on"); + dpy.has_show_cursor = true; + dpy.show_cursor = true; + break; +-- +2.23.0 + diff --git a/ui-increase-min-required-GTK-version-to-3.22.0.patch b/ui-increase-min-required-GTK-version-to-3.22.0.patch new file mode 100644 index 0000000000000000000000000000000000000000..96f4475c2641c7e354a976b2da13d3cd815fad8a --- /dev/null +++ b/ui-increase-min-required-GTK-version-to-3.22.0.patch @@ -0,0 +1,235 @@ +From 7b23d121f913709306e678a3289edc813f3a7463 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Volker=20R=C3=BCmelin?= +Date: Sat, 16 May 2020 09:20:14 +0200 +Subject: [PATCH 585/709] ui: increase min required GTK version to 3.22.0 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Based on a mail on the qemu-devel mailing list at +https://lists.nongnu.org/archive/html/qemu-devel/2020-05/msg02909.html +and some internet research the GTK3 versions on supported +platforms are: + + RHEL-7.4: 3.22.10 + RHEL-7.5: 3.22.26 + Debian (Stretch): 3.22.11 + Debian (Buster): 3.24.5 + OpenBSD (Ports): 3.22.30 + FreeBSD (Ports): 3.22.29 + OpenSUSE Leap 15: 3.22.30 + SLE12-SP2: Unknown + SLE15: 3.22.30 + Ubuntu (Bionic): 3.22.30 + Ubuntu (Focal): 3.24.18 + macOS (Homebrew): 3.22.30 + +This justifies increasing the minimum required GTK version in +QEMU to 3.22.0. + +Signed-off-by: Volker Rümelin +Message-id: 20200516072014.7766-11-vr_qemu@t-online.de +Signed-off-by: Gerd Hoffmann +--- + configure | 2 +- + ui/gtk.c | 91 +++++-------------------------------------------------- + 2 files changed, 9 insertions(+), 84 deletions(-) + +diff --git a/configure b/configure +index 26084fc53a..2fc05c4465 100755 +--- a/configure ++++ b/configure +@@ -2897,7 +2897,7 @@ fi + if test "$gtk" != "no"; then + gtkpackage="gtk+-3.0" + gtkx11package="gtk+-x11-3.0" +- gtkversion="3.14.0" ++ gtkversion="3.22.0" + if $pkg_config --exists "$gtkpackage >= $gtkversion"; then + gtk_cflags=$($pkg_config --cflags $gtkpackage) + gtk_libs=$($pkg_config --libs $gtkpackage) +diff --git a/ui/gtk.c b/ui/gtk.c +index 68a5b901c7..d4b49bd7da 100644 +--- a/ui/gtk.c ++++ b/ui/gtk.c +@@ -490,12 +490,7 @@ static void gd_refresh(DisplayChangeListener *dcl) + + static GdkDevice *gd_get_pointer(GdkDisplay *dpy) + { +-#if GTK_CHECK_VERSION(3, 20, 0) + return gdk_seat_get_pointer(gdk_display_get_default_seat(dpy)); +-#else +- return gdk_device_manager_get_client_pointer( +- gdk_display_get_device_manager(dpy)); +-#endif + } + + static void gd_mouse_set(DisplayChangeListener *dcl, +@@ -877,27 +872,18 @@ static gboolean gd_motion_event(GtkWidget *widget, GdkEventMotion *motion, + + if (!qemu_input_is_absolute() && s->ptr_owner == vc) { + GdkScreen *screen = gtk_widget_get_screen(vc->gfx.drawing_area); ++ GdkDisplay *dpy = gtk_widget_get_display(widget); ++ GdkWindow *win = gtk_widget_get_window(widget); ++ GdkMonitor *monitor = gdk_display_get_monitor_at_window(dpy, win); ++ GdkRectangle geometry; + int screen_width, screen_height; + + int x = (int)motion->x_root; + int y = (int)motion->y_root; + +-#if GTK_CHECK_VERSION(3, 22, 0) +- { +- GdkDisplay *dpy = gtk_widget_get_display(widget); +- GdkWindow *win = gtk_widget_get_window(widget); +- GdkMonitor *monitor = gdk_display_get_monitor_at_window(dpy, win); +- GdkRectangle geometry; +- gdk_monitor_get_geometry(monitor, &geometry); +- screen_width = geometry.width; +- screen_height = geometry.height; +- } +-#else +- { +- screen_width = gdk_screen_get_width(screen); +- screen_height = gdk_screen_get_height(screen); +- } +-#endif ++ gdk_monitor_get_geometry(monitor, &geometry); ++ screen_width = geometry.width; ++ screen_height = geometry.height; + + /* In relative mode check to see if client pointer hit + * one of the screen edges, and if so move it back by +@@ -1026,13 +1012,8 @@ static const guint16 *gd_get_keymap(size_t *maplen) + #ifdef GDK_WINDOWING_WIN32 + if (GDK_IS_WIN32_DISPLAY(dpy)) { + trace_gd_keymap_windowing("win32"); +-#if GTK_CHECK_VERSION(3, 22, 0) + *maplen = qemu_input_map_atset1_to_qcode_len; + return qemu_input_map_atset1_to_qcode; +-#else +- *maplen = qemu_input_map_win32_to_qcode_len; +- return qemu_input_map_win32_to_qcode; +-#endif + } + #endif + +@@ -1080,7 +1061,7 @@ static int gd_map_keycode(int scancode) + + static int gd_get_keycode(GdkEventKey *key) + { +-#if defined G_OS_WIN32 && GTK_CHECK_VERSION(3, 22, 0) ++#ifdef G_OS_WIN32 + int scancode = gdk_event_get_scancode((GdkEvent *)key); + + /* translate Windows native scancodes to atset1 keycodes */ +@@ -1437,7 +1418,6 @@ static void gd_menu_zoom_fit(GtkMenuItem *item, void *opaque) + gd_update_full_redraw(vc); + } + +-#if GTK_CHECK_VERSION(3, 20, 0) + static void gd_grab_update(VirtualConsole *vc, bool kbd, bool ptr) + { + GdkDisplay *display = gtk_widget_get_display(vc->gfx.drawing_area); +@@ -1461,32 +1441,6 @@ static void gd_grab_update(VirtualConsole *vc, bool kbd, bool ptr) + gdk_seat_ungrab(seat); + } + } +-#else +-static void gd_grab_devices(VirtualConsole *vc, bool grab, +- GdkInputSource source, GdkEventMask mask, +- GdkCursor *cursor) +-{ +- GdkDisplay *display = gtk_widget_get_display(vc->gfx.drawing_area); +- GdkDeviceManager *mgr = gdk_display_get_device_manager(display); +- GList *devs = gdk_device_manager_list_devices(mgr, GDK_DEVICE_TYPE_MASTER); +- GList *tmp = devs; +- +- for (tmp = devs; tmp; tmp = tmp->next) { +- GdkDevice *dev = tmp->data; +- if (gdk_device_get_source(dev) != source) { +- continue; +- } +- if (grab) { +- GdkWindow *win = gtk_widget_get_window(vc->gfx.drawing_area); +- gdk_device_grab(dev, win, GDK_OWNERSHIP_NONE, FALSE, +- mask, cursor, GDK_CURRENT_TIME); +- } else { +- gdk_device_ungrab(dev, GDK_CURRENT_TIME); +- } +- } +- g_list_free(devs); +-} +-#endif + + static void gd_grab_keyboard(VirtualConsole *vc, const char *reason) + { +@@ -1499,13 +1453,7 @@ static void gd_grab_keyboard(VirtualConsole *vc, const char *reason) + } + + win32_kbd_set_grab(true); +-#if GTK_CHECK_VERSION(3, 20, 0) + gd_grab_update(vc, true, vc->s->ptr_owner == vc); +-#else +- gd_grab_devices(vc, true, GDK_SOURCE_KEYBOARD, +- GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK, +- NULL); +-#endif + vc->s->kbd_owner = vc; + gd_update_caption(vc->s); + trace_gd_grab(vc->label, "kbd", reason); +@@ -1521,11 +1469,7 @@ static void gd_ungrab_keyboard(GtkDisplayState *s) + s->kbd_owner = NULL; + + win32_kbd_set_grab(false); +-#if GTK_CHECK_VERSION(3, 20, 0) + gd_grab_update(vc, false, vc->s->ptr_owner == vc); +-#else +- gd_grab_devices(vc, false, GDK_SOURCE_KEYBOARD, 0, NULL); +-#endif + gd_update_caption(s); + trace_gd_ungrab(vc->label, "kbd"); + } +@@ -1542,21 +1486,9 @@ static void gd_grab_pointer(VirtualConsole *vc, const char *reason) + } + } + +-#if GTK_CHECK_VERSION(3, 20, 0) + gd_grab_update(vc, vc->s->kbd_owner == vc, true); + gdk_device_get_position(gd_get_pointer(display), + NULL, &vc->s->grab_x_root, &vc->s->grab_y_root); +-#else +- gd_grab_devices(vc, true, GDK_SOURCE_MOUSE, +- GDK_POINTER_MOTION_MASK | +- GDK_BUTTON_PRESS_MASK | +- GDK_BUTTON_RELEASE_MASK | +- GDK_BUTTON_MOTION_MASK | +- GDK_SCROLL_MASK, +- vc->s->null_cursor); +- gdk_device_get_position(gd_get_pointer(display), +- NULL, &vc->s->grab_x_root, &vc->s->grab_y_root); +-#endif + vc->s->ptr_owner = vc; + gd_update_caption(vc->s); + trace_gd_grab(vc->label, "ptr", reason); +@@ -1573,17 +1505,10 @@ static void gd_ungrab_pointer(GtkDisplayState *s) + s->ptr_owner = NULL; + + display = gtk_widget_get_display(vc->gfx.drawing_area); +-#if GTK_CHECK_VERSION(3, 20, 0) + gd_grab_update(vc, vc->s->kbd_owner == vc, false); + gdk_device_warp(gd_get_pointer(display), + gtk_widget_get_screen(vc->gfx.drawing_area), + vc->s->grab_x_root, vc->s->grab_y_root); +-#else +- gd_grab_devices(vc, false, GDK_SOURCE_MOUSE, 0, NULL); +- gdk_device_warp(gd_get_pointer(display), +- gtk_widget_get_screen(vc->gfx.drawing_area), +- vc->s->grab_x_root, vc->s->grab_y_root); +-#endif + gd_update_caption(s); + trace_gd_ungrab(vc->label, "ptr"); + } +-- +2.23.0 + diff --git a/ui-sdl2-fix-handling-of-AltGr-key-on-Windows.patch b/ui-sdl2-fix-handling-of-AltGr-key-on-Windows.patch new file mode 100644 index 0000000000000000000000000000000000000000..96bd8cceabcaa0369b994a219b6831338a63d8f9 --- /dev/null +++ b/ui-sdl2-fix-handling-of-AltGr-key-on-Windows.patch @@ -0,0 +1,91 @@ +From 830473455fb94e7362c464a9b7667dca1004a5a4 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Volker=20R=C3=BCmelin?= +Date: Sat, 16 May 2020 09:20:09 +0200 +Subject: [PATCH 580/709] ui/sdl2: fix handling of AltGr key on Windows +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Wire up the keyboard hooking code on Windows to fix the AltGr +key and improve keyboard grabbing. + +Signed-off-by: Volker Rümelin +Message-id: 20200516072014.7766-6-vr_qemu@t-online.de +Signed-off-by: Gerd Hoffmann +--- + ui/sdl2.c | 24 ++++++++++++++++++++++++ + 1 file changed, 24 insertions(+) + +diff --git a/ui/sdl2.c b/ui/sdl2.c +index 61c7956da3..79c1ea29d2 100644 +--- a/ui/sdl2.c ++++ b/ui/sdl2.c +@@ -30,6 +30,7 @@ + #include "ui/sdl2.h" + #include "sysemu/runstate.h" + #include "sysemu/sysemu.h" ++#include "ui/win32-kbd-hook.h" + + static int sdl2_num_outputs; + static struct sdl2_console *sdl2_console; +@@ -220,6 +221,7 @@ static void sdl_grab_start(struct sdl2_console *scon) + } + SDL_SetWindowGrab(scon->real_window, SDL_TRUE); + gui_grab = 1; ++ win32_kbd_set_grab(true); + sdl_update_caption(scon); + } + +@@ -227,6 +229,7 @@ static void sdl_grab_end(struct sdl2_console *scon) + { + SDL_SetWindowGrab(scon->real_window, SDL_FALSE); + gui_grab = 0; ++ win32_kbd_set_grab(false); + sdl_show_cursor(scon); + sdl_update_caption(scon); + } +@@ -325,6 +328,19 @@ static int get_mod_state(void) + } + } + ++static void *sdl2_win32_get_hwnd(struct sdl2_console *scon) ++{ ++#ifdef CONFIG_WIN32 ++ SDL_SysWMinfo info; ++ ++ SDL_VERSION(&info.version); ++ if (SDL_GetWindowWMInfo(scon->real_window, &info)) { ++ return info.info.win.window; ++ } ++#endif ++ return NULL; ++} ++ + static void handle_keydown(SDL_Event *ev) + { + int win; +@@ -544,6 +560,11 @@ static void handle_windowevent(SDL_Event *ev) + sdl2_redraw(scon); + break; + case SDL_WINDOWEVENT_FOCUS_GAINED: ++ win32_kbd_set_grab(gui_grab); ++ if (qemu_console_is_graphic(scon->dcl.con)) { ++ win32_kbd_set_window(sdl2_win32_get_hwnd(scon)); ++ } ++ /* fall through */ + case SDL_WINDOWEVENT_ENTER: + if (!gui_grab && (qemu_input_is_absolute() || absolute_enabled)) { + absolute_mouse_grab(scon); +@@ -558,6 +579,9 @@ static void handle_windowevent(SDL_Event *ev) + scon->ignore_hotkeys = get_mod_state(); + break; + case SDL_WINDOWEVENT_FOCUS_LOST: ++ if (qemu_console_is_graphic(scon->dcl.con)) { ++ win32_kbd_set_window(NULL); ++ } + if (gui_grab && !gui_fullscreen) { + sdl_grab_end(scon); + } +-- +2.23.0 + diff --git a/ui-sdl2-fix-segment-fault-caused-by-null-pointer-der.patch b/ui-sdl2-fix-segment-fault-caused-by-null-pointer-der.patch new file mode 100644 index 0000000000000000000000000000000000000000..21dcf3ec5a888c2e884e23508b5d951c9ac23ff7 --- /dev/null +++ b/ui-sdl2-fix-segment-fault-caused-by-null-pointer-der.patch @@ -0,0 +1,57 @@ +From 32ec9839d89d2b814ada20b041b25feae23596bc Mon Sep 17 00:00:00 2001 +From: Changbin Du +Date: Mon, 27 Apr 2020 21:24:12 +0800 +Subject: [PATCH 414/709] ui/sdl2: fix segment fault caused by null pointer + dereference + +I found SDL_GetWindowFromID() sometimes return NULL when I start qemu via +ssh forwarding even the window has been crated already. I am not sure +whether this is a bug of SDL, but we'd better check it carefully. + +Signed-off-by: Changbin Du +Message-id: 20200427132412.17909-1-changbin.du@gmail.com +Signed-off-by: Gerd Hoffmann +--- + ui/sdl2.c | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +diff --git a/ui/sdl2.c b/ui/sdl2.c +index 3c9424eb42..61c7956da3 100644 +--- a/ui/sdl2.c ++++ b/ui/sdl2.c +@@ -332,6 +332,10 @@ static void handle_keydown(SDL_Event *ev) + int gui_key_modifier_pressed = get_mod_state(); + int gui_keysym = 0; + ++ if (!scon) { ++ return; ++ } ++ + if (!scon->ignore_hotkeys && gui_key_modifier_pressed && !ev->key.repeat) { + switch (ev->key.keysym.scancode) { + case SDL_SCANCODE_2: +@@ -412,6 +416,10 @@ static void handle_keyup(SDL_Event *ev) + { + struct sdl2_console *scon = get_scon_from_window(ev->key.windowID); + ++ if (!scon) { ++ return; ++ } ++ + scon->ignore_hotkeys = false; + sdl2_process_key(scon, &ev->key); + } +@@ -421,6 +429,10 @@ static void handle_textinput(SDL_Event *ev) + struct sdl2_console *scon = get_scon_from_window(ev->text.windowID); + QemuConsole *con = scon ? scon->dcl.con : NULL; + ++ if (!con) { ++ return; ++ } ++ + if (qemu_console_is_graphic(con)) { + return; + } +-- +2.23.0 + diff --git a/ui-sdl2-input-use-trace-events-to-debug-key-events.patch b/ui-sdl2-input-use-trace-events-to-debug-key-events.patch new file mode 100644 index 0000000000000000000000000000000000000000..b7bd07a74d904a4b6fda9a14887e13598948926f --- /dev/null +++ b/ui-sdl2-input-use-trace-events-to-debug-key-events.patch @@ -0,0 +1,55 @@ +From 20a37f2fa3873ad62c31b40f55f2218ec9ff470b Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Volker=20R=C3=BCmelin?= +Date: Sat, 16 May 2020 09:20:11 +0200 +Subject: [PATCH 582/709] ui/sdl2-input: use trace-events to debug key events +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Reviewed-by: Philippe Mathieu-Daudé +Signed-off-by: Volker Rümelin +Message-id: 20200516072014.7766-8-vr_qemu@t-online.de +Signed-off-by: Gerd Hoffmann +--- + ui/sdl2-input.c | 3 +++ + ui/trace-events | 3 +++ + 2 files changed, 6 insertions(+) + +diff --git a/ui/sdl2-input.c b/ui/sdl2-input.c +index 1f9fe831b3..f068382209 100644 +--- a/ui/sdl2-input.c ++++ b/ui/sdl2-input.c +@@ -27,6 +27,7 @@ + #include "ui/console.h" + #include "ui/input.h" + #include "ui/sdl2.h" ++#include "trace.h" + + void sdl2_process_key(struct sdl2_console *scon, + SDL_KeyboardEvent *ev) +@@ -38,6 +39,8 @@ void sdl2_process_key(struct sdl2_console *scon, + return; + } + qcode = qemu_input_map_usb_to_qcode[ev->keysym.scancode]; ++ trace_sdl2_process_key(ev->keysym.scancode, qcode, ++ ev->type == SDL_KEYDOWN ? "down" : "up"); + qkbd_state_key_event(scon->kbd, qcode, ev->type == SDL_KEYDOWN); + + if (!qemu_console_is_graphic(con)) { +diff --git a/ui/trace-events b/ui/trace-events +index 0dcda393c1..5367fd3f16 100644 +--- a/ui/trace-events ++++ b/ui/trace-events +@@ -75,6 +75,9 @@ input_event_abs(int conidx, const char *axis, int value) "con %d, axis %s, value + input_event_sync(void) "" + input_mouse_mode(int absolute) "absolute %d" + ++# sdl2-input.c ++sdl2_process_key(int sdl_scancode, int qcode, const char *action) "translated SDL scancode %d to QKeyCode %d (%s)" ++ + # spice-display.c + qemu_spice_add_memslot(int qid, uint32_t slot_id, unsigned long virt_start, unsigned long virt_end, int async) "%d %u: host virt 0x%lx - 0x%lx async=%d" + qemu_spice_del_memslot(int qid, uint32_t gid, uint32_t slot_id) "%d gid=%u sid=%u" +-- +2.23.0 + diff --git a/ui-sdl2-start-in-full-screen-with-grab-enabled.patch b/ui-sdl2-start-in-full-screen-with-grab-enabled.patch new file mode 100644 index 0000000000000000000000000000000000000000..0c9b669f24db220070bf7ed7bbe9f5be4855583a --- /dev/null +++ b/ui-sdl2-start-in-full-screen-with-grab-enabled.patch @@ -0,0 +1,50 @@ +From 7dafc6793a5b1806bec4b1f233561b809c5cc649 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Volker=20R=C3=BCmelin?= +Date: Sat, 16 May 2020 09:20:10 +0200 +Subject: [PATCH 581/709] ui/sdl2: start in full screen with grab enabled +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +QEMU with SDL 1.2 display used to enable keyboard and mouse grab- +bing when started in full screen. The SDL 2.0 code tries to do +the same but fails to enable grabbing because sdl_grab_start(0) +returns early. To do it's work the sdl_grab_start() function +needs a pointer to a sdl2_console structure. + +Signed-off-by: Volker Rümelin +Message-id: 20200516072014.7766-7-vr_qemu@t-online.de +Signed-off-by: Gerd Hoffmann +--- + ui/sdl2.c | 9 ++++----- + 1 file changed, 4 insertions(+), 5 deletions(-) + +diff --git a/ui/sdl2.c b/ui/sdl2.c +index 79c1ea29d2..b23a8f0a8e 100644 +--- a/ui/sdl2.c ++++ b/ui/sdl2.c +@@ -881,17 +881,16 @@ static void sdl2_display_init(DisplayState *ds, DisplayOptions *o) + SDL_SetWindowIcon(sdl2_console[0].real_window, icon); + } + +- gui_grab = 0; +- if (gui_fullscreen) { +- sdl_grab_start(0); +- } +- + mouse_mode_notifier.notify = sdl_mouse_mode_change; + qemu_add_mouse_mode_change_notifier(&mouse_mode_notifier); + + sdl_cursor_hidden = SDL_CreateCursor(&data, &data, 8, 1, 0, 0); + sdl_cursor_normal = SDL_GetCursor(); + ++ if (gui_fullscreen) { ++ sdl_grab_start(&sdl2_console[0]); ++ } ++ + atexit(sdl_cleanup); + } + +-- +2.23.0 + diff --git a/ui-win32-kbd-hook-handle-AltGr-in-a-hook-procedure.patch b/ui-win32-kbd-hook-handle-AltGr-in-a-hook-procedure.patch new file mode 100644 index 0000000000000000000000000000000000000000..1b37df3dda9a548933a905413a4bcadf3c401666 --- /dev/null +++ b/ui-win32-kbd-hook-handle-AltGr-in-a-hook-procedure.patch @@ -0,0 +1,213 @@ +From 2df9f5718df7722924699a3754f99165e2f4ae35 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Volker=20R=C3=BCmelin?= +Date: Sat, 16 May 2020 09:20:04 +0200 +Subject: [PATCH 575/709] ui/win32-kbd-hook: handle AltGr in a hook procedure +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Import win32 keyboard hooking code from project spice-gtk. This +patch removes the extra left control key up/down input events +inserted by Windows for the right alt key up/down input events +with international keyboard layouts. Additionally there's some +code to grab the keyboard. + +The next patches will use this code. + +Only Windows needs this. + +Signed-off-by: Volker Rümelin +Message-id: 20200516072014.7766-1-vr_qemu@t-online.de +Signed-off-by: Gerd Hoffmann +--- + include/ui/win32-kbd-hook.h | 14 +++++ + stubs/Makefile.objs | 1 + + stubs/win32-kbd-hook.c | 18 +++++++ + ui/Makefile.objs | 3 ++ + ui/win32-kbd-hook.c | 102 ++++++++++++++++++++++++++++++++++++ + 5 files changed, 138 insertions(+) + create mode 100644 include/ui/win32-kbd-hook.h + create mode 100644 stubs/win32-kbd-hook.c + create mode 100644 ui/win32-kbd-hook.c + +diff --git a/include/ui/win32-kbd-hook.h b/include/ui/win32-kbd-hook.h +new file mode 100644 +index 0000000000..4bd9f00f97 +--- /dev/null ++++ b/include/ui/win32-kbd-hook.h +@@ -0,0 +1,14 @@ ++/* ++ * SPDX-License-Identifier: GPL-2.0-or-later ++ * ++ * This work is licensed under the terms of the GNU GPL, version 2 or later. ++ * See the COPYING file in the top-level directory. ++ */ ++ ++#ifndef UI_WIN32_KBD_HOOK_H ++#define UI_WIN32_KBD_HOOK_H ++ ++void win32_kbd_set_window(void *hwnd); ++void win32_kbd_set_grab(bool grab); ++ ++#endif +diff --git a/stubs/Makefile.objs b/stubs/Makefile.objs +index 45be5dc0ed..6a9e3135e8 100644 +--- a/stubs/Makefile.objs ++++ b/stubs/Makefile.objs +@@ -32,6 +32,7 @@ stub-obj-y += trace-control.o + stub-obj-y += uuid.o + stub-obj-y += vm-stop.o + stub-obj-y += vmstate.o ++stub-obj-y += win32-kbd-hook.o + stub-obj-y += fd-register.o + stub-obj-y += qmp_memory_device.o + stub-obj-y += target-monitor-defs.o +diff --git a/stubs/win32-kbd-hook.c b/stubs/win32-kbd-hook.c +new file mode 100644 +index 0000000000..1a084b081a +--- /dev/null ++++ b/stubs/win32-kbd-hook.c +@@ -0,0 +1,18 @@ ++/* ++ * Win32 keyboard hook stubs ++ * ++ * 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 "ui/win32-kbd-hook.h" ++ ++void win32_kbd_set_window(void *hwnd) ++{ ++} ++ ++void win32_kbd_set_grab(bool grab) ++{ ++} +diff --git a/ui/Makefile.objs b/ui/Makefile.objs +index e6da6ff047..504b196479 100644 +--- a/ui/Makefile.objs ++++ b/ui/Makefile.objs +@@ -15,6 +15,9 @@ common-obj-$(CONFIG_SPICE) += spice-core.o spice-input.o spice-display.o + common-obj-$(CONFIG_COCOA) += cocoa.o + common-obj-$(CONFIG_VNC) += $(vnc-obj-y) + common-obj-$(call lnot,$(CONFIG_VNC)) += vnc-stubs.o ++ifneq (,$(findstring m,$(CONFIG_SDL)$(CONFIG_GTK))) ++common-obj-$(CONFIG_WIN32) += win32-kbd-hook.o ++endif + + # ui-sdl module + common-obj-$(CONFIG_SDL) += sdl.mo +diff --git a/ui/win32-kbd-hook.c b/ui/win32-kbd-hook.c +new file mode 100644 +index 0000000000..1ac237db9e +--- /dev/null ++++ b/ui/win32-kbd-hook.c +@@ -0,0 +1,102 @@ ++/* ++ * 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. ++ * ++ * The win32 keyboard hooking code was imported from project spice-gtk. ++ */ ++ ++#include "qemu/osdep.h" ++#include "sysemu/sysemu.h" ++#include "ui/win32-kbd-hook.h" ++ ++static Notifier win32_unhook_notifier; ++static HHOOK win32_keyboard_hook; ++static HWND win32_window; ++static DWORD win32_grab; ++ ++static LRESULT CALLBACK keyboard_hook_cb(int code, WPARAM wparam, LPARAM lparam) ++{ ++ if (win32_window && code == HC_ACTION && win32_window == GetFocus()) { ++ KBDLLHOOKSTRUCT *hooked = (KBDLLHOOKSTRUCT *)lparam; ++ ++ if (wparam != WM_KEYUP) { ++ DWORD dwmsg = (hooked->flags << 24) | ++ ((hooked->scanCode & 0xff) << 16) | 1; ++ ++ switch (hooked->vkCode) { ++ case VK_CAPITAL: ++ /* fall through */ ++ case VK_SCROLL: ++ /* fall through */ ++ case VK_NUMLOCK: ++ /* fall through */ ++ case VK_LSHIFT: ++ /* fall through */ ++ case VK_RSHIFT: ++ /* fall through */ ++ case VK_RCONTROL: ++ /* fall through */ ++ case VK_LMENU: ++ /* fall through */ ++ case VK_RMENU: ++ break; ++ ++ case VK_LCONTROL: ++ /* ++ * When pressing AltGr, an extra VK_LCONTROL with a special ++ * scancode with bit 9 set is sent. Let's ignore the extra ++ * VK_LCONTROL, as that will make AltGr misbehave. ++ */ ++ if (hooked->scanCode & 0x200) { ++ return 1; ++ } ++ break; ++ ++ default: ++ if (win32_grab) { ++ SendMessage(win32_window, wparam, hooked->vkCode, dwmsg); ++ return 1; ++ } ++ break; ++ } ++ ++ } else { ++ switch (hooked->vkCode) { ++ case VK_LCONTROL: ++ if (hooked->scanCode & 0x200) { ++ return 1; ++ } ++ break; ++ } ++ } ++ } ++ ++ return CallNextHookEx(NULL, code, wparam, lparam); ++} ++ ++static void keyboard_hook_unhook(Notifier *n, void *data) ++{ ++ UnhookWindowsHookEx(win32_keyboard_hook); ++ win32_keyboard_hook = NULL; ++} ++ ++void win32_kbd_set_window(void *hwnd) ++{ ++ if (hwnd && !win32_keyboard_hook) { ++ /* note: the installing thread must have a message loop */ ++ win32_keyboard_hook = SetWindowsHookEx(WH_KEYBOARD_LL, keyboard_hook_cb, ++ GetModuleHandle(NULL), 0); ++ if (win32_keyboard_hook) { ++ win32_unhook_notifier.notify = keyboard_hook_unhook; ++ qemu_add_exit_notifier(&win32_unhook_notifier); ++ } ++ } ++ ++ win32_window = hwnd; ++} ++ ++void win32_kbd_set_grab(bool grab) ++{ ++ win32_grab = grab; ++} +-- +2.23.0 + diff --git a/usb-tablet-fix-serial-compat-property.patch b/usb-tablet-fix-serial-compat-property.patch deleted file mode 100644 index 6397f61fb463cf11f9805bdb4b51cf68d05c7349..0000000000000000000000000000000000000000 --- a/usb-tablet-fix-serial-compat-property.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 665218cc085c5c1ec871d8af6986903313638fbf Mon Sep 17 00:00:00 2001 -From: Gerd Hoffmann -Date: Mon, 20 May 2019 10:18:05 +0200 -Subject: [PATCH] usb-tablet: fix serial compat property -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -s/kbd/tablet/, fixes cut+paste bug. - -Cc: qemu-stable@nongnu.org -Reported-by: Dr. David Alan Gilbert -Signed-off-by: Gerd Hoffmann -Reviewed-by: Dr. David Alan Gilbert -Reviewed-by: Laurent Vivier -Reviewed-by: Philippe Mathieu-Daudé -Message-id: 20190520081805.15019-1-kraxel@redhat.com -(cherry picked from commit 442bac16a6cd708a9f87adb0a263f9d833f03ed5) -Signed-off-by: Michael Roth ---- - hw/core/machine.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/hw/core/machine.c b/hw/core/machine.c -index 743fef2898..b6766632d9 100644 ---- a/hw/core/machine.c -+++ b/hw/core/machine.c -@@ -33,7 +33,7 @@ GlobalProperty hw_compat_3_1[] = { - { "tpm-tis", "ppi", "false" }, - { "usb-kbd", "serial", "42" }, - { "usb-mouse", "serial", "42" }, -- { "usb-kbd", "serial", "42" }, -+ { "usb-tablet", "serial", "42" }, - { "virtio-blk-device", "discard", "false" }, - { "virtio-blk-device", "write-zeroes", "false" }, - }; --- -2.19.1 - diff --git a/usbredir-fix-buffer-overflow-on-vmload.patch b/usbredir-fix-buffer-overflow-on-vmload.patch deleted file mode 100644 index 2fec639d85b838f30c87aebde7075fd34de65427..0000000000000000000000000000000000000000 --- a/usbredir-fix-buffer-overflow-on-vmload.patch +++ /dev/null @@ -1,55 +0,0 @@ -From e86e620656becb37890a6d91e0148c74f3e43f3d Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= -Date: Wed, 7 Aug 2019 12:40:48 +0400 -Subject: [PATCH] usbredir: fix buffer-overflow on vmload -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -If interface_count is NO_INTERFACE_INFO, let's not access the arrays -out-of-bounds. - -==994==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x625000243930 at pc 0x5642068086a8 bp 0x7f0b6f9ffa50 sp 0x7f0b6f9ffa40 -READ of size 1 at 0x625000243930 thread T0 - #0 0x5642068086a7 in usbredir_check_bulk_receiving /home/elmarco/src/qemu/hw/usb/redirect.c:1503 - #1 0x56420681301c in usbredir_post_load /home/elmarco/src/qemu/hw/usb/redirect.c:2154 - #2 0x5642068a56c2 in vmstate_load_state /home/elmarco/src/qemu/migration/vmstate.c:168 - #3 0x56420688e2ac in vmstate_load /home/elmarco/src/qemu/migration/savevm.c:829 - #4 0x5642068980cb in qemu_loadvm_section_start_full /home/elmarco/src/qemu/migration/savevm.c:2211 - #5 0x564206899645 in qemu_loadvm_state_main /home/elmarco/src/qemu/migration/savevm.c:2395 - #6 0x5642068998cf in qemu_loadvm_state /home/elmarco/src/qemu/migration/savevm.c:2467 - #7 0x56420685f3e9 in process_incoming_migration_co /home/elmarco/src/qemu/migration/migration.c:449 - #8 0x564207106c47 in coroutine_trampoline /home/elmarco/src/qemu/util/coroutine-ucontext.c:115 - #9 0x7f0c0604e37f (/lib64/libc.so.6+0x4d37f) - -Signed-off-by: Marc-André Lureau -Reviewed-by: Liam Merwick -Reviewed-by: Li Qiang -Reviewed-by: Philippe Mathieu-Daudé -Message-id: 20190807084048.4258-1-marcandre.lureau@redhat.com -Signed-off-by: Gerd Hoffmann -(cherry picked from commit 7b84b90966568da0e05655ecaa78c209300aae6e) -Signed-off-by: Michael Roth ---- - hw/usb/redirect.c | 5 +++++ - 1 file changed, 5 insertions(+) - -diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c -index 7cb6b120d4..586c7db025 100644 ---- a/hw/usb/redirect.c -+++ b/hw/usb/redirect.c -@@ -1494,6 +1494,11 @@ static void usbredir_check_bulk_receiving(USBRedirDevice *dev) - for (i = EP2I(USB_DIR_IN); i < MAX_ENDPOINTS; i++) { - dev->endpoint[i].bulk_receiving_enabled = 0; - } -+ -+ if (dev->interface_info.interface_count == NO_INTERFACE_INFO) { -+ return; -+ } -+ - for (i = 0; i < dev->interface_info.interface_count; i++) { - quirks = usb_get_quirks(dev->device_info.vendor_id, - dev->device_info.product_id, --- -2.19.1 - diff --git a/util-async-hold-AioContext-ref-to-prevent-use-after-free.patch b/util-async-hold-AioContext-ref-to-prevent-use-after-free.patch deleted file mode 100644 index da4403c4ec7757c4860023b2a8e0018c3bf23b9d..0000000000000000000000000000000000000000 --- a/util-async-hold-AioContext-ref-to-prevent-use-after-free.patch +++ /dev/null @@ -1,63 +0,0 @@ -From e965bc6c633921ab238b1f5ea64055975b24e2bb Mon Sep 17 00:00:00 2001 -From: Stefan Hajnoczi -Date: Tue, 23 Jul 2019 20:06:23 +0100 -Subject: [PATCH 4/5] util/async: hold AioContext ref to prevent use-after-free - -The tests/test-bdrv-drain /bdrv-drain/iothread/drain test case does the -following: - -1. The preadv coroutine calls aio_bh_schedule_oneshot() and then yields. -2. The one-shot BH executes in another AioContext. All it does is call - aio_co_wakeup(preadv_co). -3. The preadv coroutine is re-entered and returns. - -There is a race condition in aio_co_wake() where the preadv coroutine -returns and the test case destroys the preadv IOThread. aio_co_wake() -can still be running in the other AioContext and it performs an access -to the freed IOThread AioContext. - -Here is the race in aio_co_schedule(): - - QSLIST_INSERT_HEAD_ATOMIC(&ctx->scheduled_coroutines, - co, co_scheduled_next); - <-- race: co may execute before we invoke qemu_bh_schedule()! - qemu_bh_schedule(ctx->co_schedule_bh); - -So if co causes ctx to be freed then we're in trouble. Fix this problem -by holding a reference to ctx. - -Signed-off-by: Stefan Hajnoczi -Reviewed-by: Paolo Bonzini -Message-id: 20190723190623.21537-1-stefanha@redhat.com -Message-Id: <20190723190623.21537-1-stefanha@redhat.com> -Signed-off-by: Stefan Hajnoczi -(cherry-picked from commit f0f81002873c06fdef9bb2a272ddfd26af65b851) ---- - util/async.c | 8 ++++++++ - 1 file changed, 8 insertions(+) - -diff --git a/util/async.c b/util/async.c -index c10642a..afc17fb 100644 ---- a/util/async.c -+++ b/util/async.c -@@ -460,9 +460,17 @@ void aio_co_schedule(AioContext *ctx, Coroutine *co) - abort(); - } - -+ /* The coroutine might run and release the last ctx reference before we -+ * invoke qemu_bh_schedule(). Take a reference to keep ctx alive until -+ * we're done. -+ */ -+ aio_context_ref(ctx); -+ - QSLIST_INSERT_HEAD_ATOMIC(&ctx->scheduled_coroutines, - co, co_scheduled_next); - qemu_bh_schedule(ctx->co_schedule_bh); -+ -+ aio_context_unref(ctx); - } - - void aio_co_wake(struct Coroutine *co) --- -1.8.3.1 - diff --git a/util-hbitmap-update-orig_size-on-truncate.patch b/util-hbitmap-update-orig_size-on-truncate.patch deleted file mode 100644 index 137d8b9c5cdb3574b25b2cad905740dff4e79d7b..0000000000000000000000000000000000000000 --- a/util-hbitmap-update-orig_size-on-truncate.patch +++ /dev/null @@ -1,48 +0,0 @@ -From fc5c701636127a0b90cd7ab564da0354d06809dc Mon Sep 17 00:00:00 2001 -From: Vladimir Sementsov-Ogievskiy -Date: Mon, 5 Aug 2019 15:01:20 +0300 -Subject: [PATCH] util/hbitmap: update orig_size on truncate - -Without this, hbitmap_next_zero and hbitmap_next_dirty_area are broken -after truncate. So, orig_size is broken since it's introduction in -76d570dc495c56bb. - -Fixes: 76d570dc495c56bb -Signed-off-by: Vladimir Sementsov-Ogievskiy -Message-id: 20190805120120.23585-1-vsementsov@virtuozzo.com -Reviewed-by: Max Reitz -Cc: qemu-stable@nongnu.org -Signed-off-by: Max Reitz -(cherry picked from commit 4e4de222799634d8159ee7b9303b9e1b45c6be2c) -Signed-off-by: Michael Roth ---- - util/hbitmap.c | 6 +++++- - 1 file changed, 5 insertions(+), 1 deletion(-) - -diff --git a/util/hbitmap.c b/util/hbitmap.c -index 7905212a8b..bcc0acdc6a 100644 ---- a/util/hbitmap.c -+++ b/util/hbitmap.c -@@ -53,7 +53,9 @@ - */ - - struct HBitmap { -- /* Size of the bitmap, as requested in hbitmap_alloc. */ -+ /* -+ * Size of the bitmap, as requested in hbitmap_alloc or in hbitmap_truncate. -+ */ - uint64_t orig_size; - - /* Number of total bits in the bottom level. */ -@@ -732,6 +734,8 @@ void hbitmap_truncate(HBitmap *hb, uint64_t size) - uint64_t num_elements = size; - uint64_t old; - -+ hb->orig_size = size; -+ - /* Size comes in as logical elements, adjust for granularity. */ - size = (size + (1ULL << hb->granularity) - 1) >> hb->granularity; - assert(size <= ((uint64_t)1 << HBITMAP_LOG_MAX_SIZE)); --- -2.19.1 - diff --git a/various-Remove-suspicious-character-outside-of-defin.patch b/various-Remove-suspicious-character-outside-of-defin.patch new file mode 100644 index 0000000000000000000000000000000000000000..6e98a94d7f2316a5db5f28355b8704ff4f455044 --- /dev/null +++ b/various-Remove-suspicious-character-outside-of-defin.patch @@ -0,0 +1,268 @@ +From 78ee6bd04821847036a805cb4bdd46464e1d3098 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Mon, 13 Apr 2020 00:35:56 +0200 +Subject: [PATCH 004/709] various: Remove suspicious '\' character outside of + #define in C code +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Fixes the following coccinelle warnings: + + $ spatch --sp-file --verbose-parsing ... \ + scripts/coccinelle/remove_local_err.cocci + ... + SUSPICIOUS: a \ character appears outside of a #define at ./target/ppc/translate_init.inc.c:5213 + SUSPICIOUS: a \ character appears outside of a #define at ./target/ppc/translate_init.inc.c:5261 + SUSPICIOUS: a \ character appears outside of a #define at ./target/microblaze/cpu.c:166 + SUSPICIOUS: a \ character appears outside of a #define at ./target/microblaze/cpu.c:167 + SUSPICIOUS: a \ character appears outside of a #define at ./target/microblaze/cpu.c:169 + SUSPICIOUS: a \ character appears outside of a #define at ./target/microblaze/cpu.c:170 + SUSPICIOUS: a \ character appears outside of a #define at ./target/microblaze/cpu.c:171 + SUSPICIOUS: a \ character appears outside of a #define at ./target/microblaze/cpu.c:172 + SUSPICIOUS: a \ character appears outside of a #define at ./target/microblaze/cpu.c:173 + SUSPICIOUS: a \ character appears outside of a #define at ./target/i386/cpu.c:5787 + SUSPICIOUS: a \ character appears outside of a #define at ./target/i386/cpu.c:5789 + SUSPICIOUS: a \ character appears outside of a #define at ./target/i386/cpu.c:5800 + SUSPICIOUS: a \ character appears outside of a #define at ./target/i386/cpu.c:5801 + SUSPICIOUS: a \ character appears outside of a #define at ./target/i386/cpu.c:5802 + SUSPICIOUS: a \ character appears outside of a #define at ./target/i386/cpu.c:5804 + SUSPICIOUS: a \ character appears outside of a #define at ./target/i386/cpu.c:5805 + SUSPICIOUS: a \ character appears outside of a #define at ./target/i386/cpu.c:5806 + SUSPICIOUS: a \ character appears outside of a #define at ./target/i386/cpu.c:6329 + SUSPICIOUS: a \ character appears outside of a #define at ./hw/sd/sdhci.c:1133 + SUSPICIOUS: a \ character appears outside of a #define at ./hw/scsi/scsi-disk.c:3081 + SUSPICIOUS: a \ character appears outside of a #define at ./hw/net/virtio-net.c:1529 + SUSPICIOUS: a \ character appears outside of a #define at ./hw/riscv/sifive_u.c:468 + SUSPICIOUS: a \ character appears outside of a #define at ./dump/dump.c:1895 + SUSPICIOUS: a \ character appears outside of a #define at ./block/vhdx.c:2209 + SUSPICIOUS: a \ character appears outside of a #define at ./block/vhdx.c:2215 + SUSPICIOUS: a \ character appears outside of a #define at ./block/vhdx.c:2221 + SUSPICIOUS: a \ character appears outside of a #define at ./block/vhdx.c:2222 + SUSPICIOUS: a \ character appears outside of a #define at ./block/replication.c:172 + SUSPICIOUS: a \ character appears outside of a #define at ./block/replication.c:173 + +Reviewed-by: Marc-André Lureau +Signed-off-by: Philippe Mathieu-Daudé +Message-Id: <20200412223619.11284-2-f4bug@amsat.org> +Reviewed-by: Alistair Francis +Acked-by: David Gibson +Signed-off-by: Markus Armbruster +--- + block/replication.c | 4 ++-- + block/vhdx.c | 8 ++++---- + dump/dump.c | 2 +- + hw/net/virtio-net.c | 2 +- + hw/riscv/sifive_u.c | 2 +- + hw/scsi/scsi-disk.c | 2 +- + hw/sd/sdhci.c | 2 +- + target/i386/cpu.c | 18 +++++++++--------- + target/microblaze/cpu.c | 14 +++++++------- + target/ppc/translate_init.inc.c | 4 ++-- + 10 files changed, 29 insertions(+), 29 deletions(-) + +diff --git a/block/replication.c b/block/replication.c +index da013c2041..971f0fe266 100644 +--- a/block/replication.c ++++ b/block/replication.c +@@ -172,8 +172,8 @@ static void replication_child_perm(BlockDriverState *bs, BdrvChild *c, + if ((bs->open_flags & (BDRV_O_INACTIVE | BDRV_O_RDWR)) == BDRV_O_RDWR) { + *nperm |= BLK_PERM_WRITE; + } +- *nshared = BLK_PERM_CONSISTENT_READ \ +- | BLK_PERM_WRITE \ ++ *nshared = BLK_PERM_CONSISTENT_READ ++ | BLK_PERM_WRITE + | BLK_PERM_WRITE_UNCHANGED; + return; + } +diff --git a/block/vhdx.c b/block/vhdx.c +index 33e57cd656..e16fdc2f2d 100644 +--- a/block/vhdx.c ++++ b/block/vhdx.c +@@ -2206,20 +2206,20 @@ static QemuOptsList vhdx_create_opts = { + .name = VHDX_BLOCK_OPT_BLOCK_SIZE, + .type = QEMU_OPT_SIZE, + .def_value_str = stringify(0), +- .help = "Block Size; min 1MB, max 256MB. " \ ++ .help = "Block Size; min 1MB, max 256MB. " + "0 means auto-calculate based on image size." + }, + { + .name = BLOCK_OPT_SUBFMT, + .type = QEMU_OPT_STRING, +- .help = "VHDX format type, can be either 'dynamic' or 'fixed'. "\ ++ .help = "VHDX format type, can be either 'dynamic' or 'fixed'. " + "Default is 'dynamic'." + }, + { + .name = VHDX_BLOCK_OPT_ZERO, + .type = QEMU_OPT_BOOL, +- .help = "Force use of payload blocks of type 'ZERO'. "\ +- "Non-standard, but default. Do not set to 'off' when "\ ++ .help = "Force use of payload blocks of type 'ZERO'. " ++ "Non-standard, but default. Do not set to 'off' when " + "using 'qemu-img convert' with subformat=dynamic." + }, + { NULL } +diff --git a/dump/dump.c b/dump/dump.c +index 22ed1d3b0d..248ea06370 100644 +--- a/dump/dump.c ++++ b/dump/dump.c +@@ -1892,7 +1892,7 @@ static void dump_process(DumpState *s, Error **errp) + result = qmp_query_dump(NULL); + /* should never fail */ + assert(result); +- qapi_event_send_dump_completed(result, !!local_err, (local_err ? \ ++ qapi_event_send_dump_completed(result, !!local_err, (local_err ? + error_get_pretty(local_err) : NULL)); + qapi_free_DumpQueryResult(result); + +diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c +index a46e3b37a7..eddfa7f923 100644 +--- a/hw/net/virtio-net.c ++++ b/hw/net/virtio-net.c +@@ -1526,7 +1526,7 @@ static void virtio_net_rsc_extract_unit6(VirtioNetRscChain *chain, + + sizeof(struct eth_header)); + unit->ip = ip6; + unit->ip_plen = &(ip6->ip6_ctlun.ip6_un1.ip6_un1_plen); +- unit->tcp = (struct tcp_header *)(((uint8_t *)unit->ip)\ ++ unit->tcp = (struct tcp_header *)(((uint8_t *)unit->ip) + + sizeof(struct ip6_header)); + unit->tcp_hdrlen = (htons(unit->tcp->th_offset_flags) & 0xF000) >> 10; + +diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c +index 56351c4faa..998666c91f 100644 +--- a/hw/riscv/sifive_u.c ++++ b/hw/riscv/sifive_u.c +@@ -465,7 +465,7 @@ static void riscv_sifive_u_machine_instance_init(Object *obj) + object_property_add_bool(obj, "start-in-flash", sifive_u_get_start_in_flash, + sifive_u_set_start_in_flash, NULL); + object_property_set_description(obj, "start-in-flash", +- "Set on to tell QEMU's ROM to jump to " \ ++ "Set on to tell QEMU's ROM to jump to " + "flash. Otherwise QEMU will jump to DRAM", + NULL); + } +diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c +index 1c0cb63a6f..e5bcd0baf8 100644 +--- a/hw/scsi/scsi-disk.c ++++ b/hw/scsi/scsi-disk.c +@@ -3078,7 +3078,7 @@ static const TypeInfo scsi_cd_info = { + + #ifdef __linux__ + static Property scsi_block_properties[] = { +- DEFINE_BLOCK_ERROR_PROPERTIES(SCSIDiskState, qdev.conf), \ ++ DEFINE_BLOCK_ERROR_PROPERTIES(SCSIDiskState, qdev.conf), + DEFINE_PROP_DRIVE("drive", SCSIDiskState, qdev.conf.blk), + DEFINE_PROP_BOOL("share-rw", SCSIDiskState, qdev.conf.share_rw, false), + DEFINE_PROP_UINT16("rotation_rate", SCSIDiskState, rotation_rate, 0), +diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c +index de63ffb037..70531ad360 100644 +--- a/hw/sd/sdhci.c ++++ b/hw/sd/sdhci.c +@@ -1130,7 +1130,7 @@ sdhci_write(void *opaque, hwaddr offset, uint64_t val, unsigned size) + + /* Limit block size to the maximum buffer size */ + if (extract32(s->blksize, 0, 12) > s->buf_maxsz) { +- qemu_log_mask(LOG_GUEST_ERROR, "%s: Size 0x%x is larger than " \ ++ qemu_log_mask(LOG_GUEST_ERROR, "%s: Size 0x%x is larger than " + "the maximum buffer 0x%x", __func__, s->blksize, + s->buf_maxsz); + +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index 90ffc5f3b1..9c256ab159 100644 +--- a/target/i386/cpu.c ++++ b/target/i386/cpu.c +@@ -5784,9 +5784,9 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, + host_cpuid(index, 0, eax, ebx, ecx, edx); + break; + } +- *eax = (L1_DTLB_2M_ASSOC << 24) | (L1_DTLB_2M_ENTRIES << 16) | \ ++ *eax = (L1_DTLB_2M_ASSOC << 24) | (L1_DTLB_2M_ENTRIES << 16) | + (L1_ITLB_2M_ASSOC << 8) | (L1_ITLB_2M_ENTRIES); +- *ebx = (L1_DTLB_4K_ASSOC << 24) | (L1_DTLB_4K_ENTRIES << 16) | \ ++ *ebx = (L1_DTLB_4K_ASSOC << 24) | (L1_DTLB_4K_ENTRIES << 16) | + (L1_ITLB_4K_ASSOC << 8) | (L1_ITLB_4K_ENTRIES); + *ecx = encode_cache_cpuid80000005(env->cache_info_amd.l1d_cache); + *edx = encode_cache_cpuid80000005(env->cache_info_amd.l1i_cache); +@@ -5797,13 +5797,13 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, + host_cpuid(index, 0, eax, ebx, ecx, edx); + break; + } +- *eax = (AMD_ENC_ASSOC(L2_DTLB_2M_ASSOC) << 28) | \ +- (L2_DTLB_2M_ENTRIES << 16) | \ +- (AMD_ENC_ASSOC(L2_ITLB_2M_ASSOC) << 12) | \ ++ *eax = (AMD_ENC_ASSOC(L2_DTLB_2M_ASSOC) << 28) | ++ (L2_DTLB_2M_ENTRIES << 16) | ++ (AMD_ENC_ASSOC(L2_ITLB_2M_ASSOC) << 12) | + (L2_ITLB_2M_ENTRIES); +- *ebx = (AMD_ENC_ASSOC(L2_DTLB_4K_ASSOC) << 28) | \ +- (L2_DTLB_4K_ENTRIES << 16) | \ +- (AMD_ENC_ASSOC(L2_ITLB_4K_ASSOC) << 12) | \ ++ *ebx = (AMD_ENC_ASSOC(L2_DTLB_4K_ASSOC) << 28) | ++ (L2_DTLB_4K_ENTRIES << 16) | ++ (AMD_ENC_ASSOC(L2_ITLB_4K_ASSOC) << 12) | + (L2_ITLB_4K_ENTRIES); + encode_cache_cpuid80000006(env->cache_info_amd.l2_cache, + cpu->enable_l3_cache ? +@@ -6326,7 +6326,7 @@ static void x86_cpu_expand_features(X86CPU *cpu, Error **errp) + */ + env->features[w] |= + x86_cpu_get_supported_feature_word(w, cpu->migratable) & +- ~env->user_features[w] & \ ++ ~env->user_features[w] & + ~feature_word_info[w].no_autoenable_flags; + } + } +diff --git a/target/microblaze/cpu.c b/target/microblaze/cpu.c +index a2c2f271df..c9cf2364ca 100644 +--- a/target/microblaze/cpu.c ++++ b/target/microblaze/cpu.c +@@ -163,14 +163,14 @@ static void mb_cpu_realizefn(DeviceState *dev, Error **errp) + + qemu_init_vcpu(cs); + +- env->pvr.regs[0] = PVR0_USE_EXC_MASK \ +- | PVR0_USE_ICACHE_MASK \ ++ env->pvr.regs[0] = PVR0_USE_EXC_MASK ++ | PVR0_USE_ICACHE_MASK + | PVR0_USE_DCACHE_MASK; +- env->pvr.regs[2] = PVR2_D_OPB_MASK \ +- | PVR2_D_LMB_MASK \ +- | PVR2_I_OPB_MASK \ +- | PVR2_I_LMB_MASK \ +- | PVR2_FPU_EXC_MASK \ ++ env->pvr.regs[2] = PVR2_D_OPB_MASK ++ | PVR2_D_LMB_MASK ++ | PVR2_I_OPB_MASK ++ | PVR2_I_LMB_MASK ++ | PVR2_FPU_EXC_MASK + | 0; + + version = cpu->cfg.version ? cpu->cfg.version : DEFAULT_CPU_VERSION; +diff --git a/target/ppc/translate_init.inc.c b/target/ppc/translate_init.inc.c +index e853164a86..fd763e588e 100644 +--- a/target/ppc/translate_init.inc.c ++++ b/target/ppc/translate_init.inc.c +@@ -5210,7 +5210,7 @@ POWERPC_FAMILY(e5500)(ObjectClass *oc, void *data) + PPC_FLOAT_STFIWX | PPC_WAIT | + PPC_MEM_TLBSYNC | PPC_TLBIVAX | PPC_MEM_SYNC | + PPC_64B | PPC_POPCNTB | PPC_POPCNTWD; +- pcc->insns_flags2 = PPC2_BOOKE206 | PPC2_PRCNTL | PPC2_PERM_ISA206 | \ ++ pcc->insns_flags2 = PPC2_BOOKE206 | PPC2_PRCNTL | PPC2_PERM_ISA206 | + PPC2_FP_CVT_S64; + pcc->msr_mask = (1ull << MSR_CM) | + (1ull << MSR_GS) | +@@ -5258,7 +5258,7 @@ POWERPC_FAMILY(e6500)(ObjectClass *oc, void *data) + PPC_FLOAT_STFIWX | PPC_WAIT | + PPC_MEM_TLBSYNC | PPC_TLBIVAX | PPC_MEM_SYNC | + PPC_64B | PPC_POPCNTB | PPC_POPCNTWD | PPC_ALTIVEC; +- pcc->insns_flags2 = PPC2_BOOKE206 | PPC2_PRCNTL | PPC2_PERM_ISA206 | \ ++ pcc->insns_flags2 = PPC2_BOOKE206 | PPC2_PRCNTL | PPC2_PERM_ISA206 | + PPC2_FP_CVT_S64 | PPC2_ATOMIC_ISA206; + pcc->msr_mask = (1ull << MSR_CM) | + (1ull << MSR_GS) | +-- +2.23.0 + diff --git a/various-Remove-unnecessary-OBJECT-cast.patch b/various-Remove-unnecessary-OBJECT-cast.patch new file mode 100644 index 0000000000000000000000000000000000000000..62a4184e091f3146d9269fec4d9e8feb24381735 --- /dev/null +++ b/various-Remove-unnecessary-OBJECT-cast.patch @@ -0,0 +1,160 @@ +From 688ffbb4f72bf9a75c7ff3a899a9617de61d5fd6 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Tue, 12 May 2020 09:00:19 +0200 +Subject: [PATCH 482/709] various: Remove unnecessary OBJECT() cast +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The OBJECT() macro is defined as: + + #define OBJECT(obj) ((Object *)(obj)) + +Remove the unnecessary OBJECT() casts when we already know the +pointer is of Object type. + +Patch created mechanically using spatch with this script: + + @@ + typedef Object; + Object *o; + @@ + - OBJECT(o) + + o + +Acked-by: Cornelia Huck +Acked-by: Corey Minyard +Acked-by: John Snow +Reviewed-by: Richard Henderson +Signed-off-by: Philippe Mathieu-Daudé +Message-Id: <20200512070020.22782-3-f4bug@amsat.org> +[Trivial rebase conflict in hw/s390x/sclp.c resolved] +--- + hw/core/bus.c | 2 +- + hw/ide/ahci-allwinner.c | 2 +- + hw/ipmi/smbus_ipmi.c | 2 +- + hw/microblaze/petalogix_ml605_mmu.c | 8 ++++---- + hw/s390x/sclp.c | 2 +- + monitor/misc.c | 3 +-- + qom/object.c | 4 ++-- + 7 files changed, 11 insertions(+), 12 deletions(-) + +diff --git a/hw/core/bus.c b/hw/core/bus.c +index a9e4118d3c..50924793ac 100644 +--- a/hw/core/bus.c ++++ b/hw/core/bus.c +@@ -25,7 +25,7 @@ + + void qbus_set_hotplug_handler(BusState *bus, Object *handler, Error **errp) + { +- object_property_set_link(OBJECT(bus), OBJECT(handler), ++ object_property_set_link(OBJECT(bus), handler, + QDEV_HOTPLUG_HANDLER_PROPERTY, errp); + } + +diff --git a/hw/ide/ahci-allwinner.c b/hw/ide/ahci-allwinner.c +index bb8393d2b6..8536b9eb5a 100644 +--- a/hw/ide/ahci-allwinner.c ++++ b/hw/ide/ahci-allwinner.c +@@ -90,7 +90,7 @@ static void allwinner_ahci_init(Object *obj) + SysbusAHCIState *s = SYSBUS_AHCI(obj); + AllwinnerAHCIState *a = ALLWINNER_AHCI(obj); + +- memory_region_init_io(&a->mmio, OBJECT(obj), &allwinner_ahci_mem_ops, a, ++ memory_region_init_io(&a->mmio, obj, &allwinner_ahci_mem_ops, a, + "allwinner-ahci", ALLWINNER_AHCI_MMIO_SIZE); + memory_region_add_subregion(&s->ahci.mem, ALLWINNER_AHCI_MMIO_OFF, + &a->mmio); +diff --git a/hw/ipmi/smbus_ipmi.c b/hw/ipmi/smbus_ipmi.c +index 2a9470d9df..f1a0148755 100644 +--- a/hw/ipmi/smbus_ipmi.c ++++ b/hw/ipmi/smbus_ipmi.c +@@ -329,7 +329,7 @@ static void smbus_ipmi_init(Object *obj) + { + SMBusIPMIDevice *sid = SMBUS_IPMI(obj); + +- ipmi_bmc_find_and_link(OBJECT(obj), (Object **) &sid->bmc); ++ ipmi_bmc_find_and_link(obj, (Object **) &sid->bmc); + } + + static void smbus_ipmi_get_fwinfo(struct IPMIInterface *ii, IPMIFwInfo *info) +diff --git a/hw/microblaze/petalogix_ml605_mmu.c b/hw/microblaze/petalogix_ml605_mmu.c +index 536571db7f..05a5614a04 100644 +--- a/hw/microblaze/petalogix_ml605_mmu.c ++++ b/hw/microblaze/petalogix_ml605_mmu.c +@@ -148,9 +148,9 @@ petalogix_ml605_init(MachineState *machine) + qdev_set_nic_properties(eth0, &nd_table[0]); + qdev_prop_set_uint32(eth0, "rxmem", 0x1000); + qdev_prop_set_uint32(eth0, "txmem", 0x1000); +- object_property_set_link(OBJECT(eth0), OBJECT(ds), ++ object_property_set_link(OBJECT(eth0), ds, + "axistream-connected", &error_abort); +- object_property_set_link(OBJECT(eth0), OBJECT(cs), ++ object_property_set_link(OBJECT(eth0), cs, + "axistream-control-connected", &error_abort); + qdev_init_nofail(eth0); + sysbus_mmio_map(SYS_BUS_DEVICE(eth0), 0, AXIENET_BASEADDR); +@@ -161,9 +161,9 @@ petalogix_ml605_init(MachineState *machine) + cs = object_property_get_link(OBJECT(eth0), + "axistream-control-connected-target", NULL); + qdev_prop_set_uint32(dma, "freqhz", 100 * 1000000); +- object_property_set_link(OBJECT(dma), OBJECT(ds), ++ object_property_set_link(OBJECT(dma), ds, + "axistream-connected", &error_abort); +- object_property_set_link(OBJECT(dma), OBJECT(cs), ++ object_property_set_link(OBJECT(dma), cs, + "axistream-control-connected", &error_abort); + qdev_init_nofail(dma); + sysbus_mmio_map(SYS_BUS_DEVICE(dma), 0, AXIDMA_BASEADDR); +diff --git a/hw/s390x/sclp.c b/hw/s390x/sclp.c +index 43cc1e0a41..20aca30ac4 100644 +--- a/hw/s390x/sclp.c ++++ b/hw/s390x/sclp.c +@@ -321,7 +321,7 @@ void s390_sclp_init(void) + Object *new = object_new(TYPE_SCLP); + + object_property_add_child(qdev_get_machine(), TYPE_SCLP, new); +- object_unref(OBJECT(new)); ++ object_unref(new); + qdev_init_nofail(DEVICE(new)); + } + +diff --git a/monitor/misc.c b/monitor/misc.c +index 9723b466cd..f5207cd242 100644 +--- a/monitor/misc.c ++++ b/monitor/misc.c +@@ -1837,8 +1837,7 @@ void object_add_completion(ReadLineState *rs, int nb_args, const char *str) + static int qdev_add_hotpluggable_device(Object *obj, void *opaque) + { + GSList **list = opaque; +- DeviceState *dev = (DeviceState *)object_dynamic_cast(OBJECT(obj), +- TYPE_DEVICE); ++ DeviceState *dev = (DeviceState *)object_dynamic_cast(obj, TYPE_DEVICE); + + if (dev == NULL) { + return 0; +diff --git a/qom/object.c b/qom/object.c +index e89ffbe3d1..d0be42c8d6 100644 +--- a/qom/object.c ++++ b/qom/object.c +@@ -756,7 +756,7 @@ Object *object_new_with_propv(const char *typename, + } + } + +- object_unref(OBJECT(obj)); ++ object_unref(obj); + return obj; + + error: +@@ -1650,7 +1650,7 @@ object_property_add_child(Object *obj, const char *name, + + assert(!child->parent); + +- type = g_strdup_printf("child<%s>", object_get_typename(OBJECT(child))); ++ type = g_strdup_printf("child<%s>", object_get_typename(child)); + + op = object_property_add(obj, name, type, object_get_child_property, NULL, + object_finalize_child_property, child); +-- +2.23.0 + diff --git a/vhdx-Rework-truncation-logic.patch b/vhdx-Rework-truncation-logic.patch new file mode 100644 index 0000000000000000000000000000000000000000..7cef6e61f9fefb006a84879c07ed871d59512509 --- /dev/null +++ b/vhdx-Rework-truncation-logic.patch @@ -0,0 +1,154 @@ +From dbc636e791ad04b6bcdec982d2b9c45d7182e037 Mon Sep 17 00:00:00 2001 +From: Eric Blake +Date: Tue, 28 Apr 2020 15:29:04 -0500 +Subject: [PATCH 356/709] vhdx: Rework truncation logic + +The vhdx driver uses truncation for image growth, with a special case +for blocks that already read as zero but which are only being +partially written. But with a bit of rearranging, it's just as easy +to defer the decision on whether truncation resulted in zeroes to the +actual allocation attempt, reducing the number of places that still +use bdrv_has_zero_init_truncate. + +Signed-off-by: Eric Blake +Message-Id: <20200428202905.770727-9-eblake@redhat.com> +Signed-off-by: Kevin Wolf +--- + block/vhdx.c | 89 ++++++++++++++++++++++++++++++---------------------- + 1 file changed, 51 insertions(+), 38 deletions(-) + +diff --git a/block/vhdx.c b/block/vhdx.c +index e11fb7413a..53e756438a 100644 +--- a/block/vhdx.c ++++ b/block/vhdx.c +@@ -1240,12 +1240,16 @@ exit: + /* + * Allocate a new payload block at the end of the file. + * +- * Allocation will happen at 1MB alignment inside the file ++ * Allocation will happen at 1MB alignment inside the file. ++ * ++ * If @need_zero is set on entry but not cleared on return, then truncation ++ * could not guarantee that the new portion reads as zero, and the caller ++ * will take care of it instead. + * + * Returns the file offset start of the new payload block + */ + static int vhdx_allocate_block(BlockDriverState *bs, BDRVVHDXState *s, +- uint64_t *new_offset) ++ uint64_t *new_offset, bool *need_zero) + { + int64_t current_len; + +@@ -1262,6 +1266,17 @@ static int vhdx_allocate_block(BlockDriverState *bs, BDRVVHDXState *s, + return -EINVAL; + } + ++ if (*need_zero) { ++ int ret; ++ ++ ret = bdrv_truncate(bs->file, *new_offset + s->block_size, false, ++ PREALLOC_MODE_OFF, BDRV_REQ_ZERO_WRITE, NULL); ++ if (ret != -ENOTSUP) { ++ *need_zero = false; ++ return ret; ++ } ++ } ++ + return bdrv_truncate(bs->file, *new_offset + s->block_size, false, + PREALLOC_MODE_OFF, 0, NULL); + } +@@ -1355,18 +1370,38 @@ static coroutine_fn int vhdx_co_writev(BlockDriverState *bs, int64_t sector_num, + /* in this case, we need to preserve zero writes for + * data that is not part of this write, so we must pad + * the rest of the buffer to zeroes */ +- +- /* if we are on a posix system with ftruncate() that extends +- * a file, then it is zero-filled for us. On Win32, the raw +- * layer uses SetFilePointer and SetFileEnd, which does not +- * zero fill AFAIK */ +- +- /* Queue another write of zero buffers if the underlying file +- * does not zero-fill on file extension */ +- +- if (bdrv_has_zero_init_truncate(bs->file->bs) == 0) { +- use_zero_buffers = true; +- ++ use_zero_buffers = true; ++ /* fall through */ ++ case PAYLOAD_BLOCK_NOT_PRESENT: /* fall through */ ++ case PAYLOAD_BLOCK_UNMAPPED: ++ case PAYLOAD_BLOCK_UNMAPPED_v095: ++ case PAYLOAD_BLOCK_UNDEFINED: ++ bat_prior_offset = sinfo.file_offset; ++ ret = vhdx_allocate_block(bs, s, &sinfo.file_offset, ++ &use_zero_buffers); ++ if (ret < 0) { ++ goto exit; ++ } ++ /* ++ * once we support differencing files, this may also be ++ * partially present ++ */ ++ /* update block state to the newly specified state */ ++ vhdx_update_bat_table_entry(bs, s, &sinfo, &bat_entry, ++ &bat_entry_offset, ++ PAYLOAD_BLOCK_FULLY_PRESENT); ++ bat_update = true; ++ /* ++ * Since we just allocated a block, file_offset is the ++ * beginning of the payload block. It needs to be the ++ * write address, which includes the offset into the ++ * block, unless the entire block needs to read as ++ * zeroes but truncation was not able to provide them, ++ * in which case we need to fill in the rest. ++ */ ++ if (!use_zero_buffers) { ++ sinfo.file_offset += sinfo.block_offset; ++ } else { + /* zero fill the front, if any */ + if (sinfo.block_offset) { + iov1.iov_len = sinfo.block_offset; +@@ -1378,7 +1413,7 @@ static coroutine_fn int vhdx_co_writev(BlockDriverState *bs, int64_t sector_num, + } + + /* our actual data */ +- qemu_iovec_concat(&hd_qiov, qiov, bytes_done, ++ qemu_iovec_concat(&hd_qiov, qiov, bytes_done, + sinfo.bytes_avail); + + /* zero fill the back, if any */ +@@ -1393,29 +1428,7 @@ static coroutine_fn int vhdx_co_writev(BlockDriverState *bs, int64_t sector_num, + sectors_to_write += iov2.iov_len >> BDRV_SECTOR_BITS; + } + } +- /* fall through */ +- case PAYLOAD_BLOCK_NOT_PRESENT: /* fall through */ +- case PAYLOAD_BLOCK_UNMAPPED: +- case PAYLOAD_BLOCK_UNMAPPED_v095: +- case PAYLOAD_BLOCK_UNDEFINED: +- bat_prior_offset = sinfo.file_offset; +- ret = vhdx_allocate_block(bs, s, &sinfo.file_offset); +- if (ret < 0) { +- goto exit; +- } +- /* once we support differencing files, this may also be +- * partially present */ +- /* update block state to the newly specified state */ +- vhdx_update_bat_table_entry(bs, s, &sinfo, &bat_entry, +- &bat_entry_offset, +- PAYLOAD_BLOCK_FULLY_PRESENT); +- bat_update = true; +- /* since we just allocated a block, file_offset is the +- * beginning of the payload block. It needs to be the +- * write address, which includes the offset into the block */ +- if (!use_zero_buffers) { +- sinfo.file_offset += sinfo.block_offset; +- } ++ + /* fall through */ + case PAYLOAD_BLOCK_FULLY_PRESENT: + /* if the file offset address is in the header zone, +-- +2.23.0 + diff --git a/vhost-cancel-migration-when-vhost-user-restarted.patch b/vhost-cancel-migration-when-vhost-user-restarted.patch deleted file mode 100644 index 38557753ce28b7120f23d21bc4f87fae22160d44..0000000000000000000000000000000000000000 --- a/vhost-cancel-migration-when-vhost-user-restarted.patch +++ /dev/null @@ -1,60 +0,0 @@ -From 750328e01afe4776eaddacde406063978dbf1291 Mon Sep 17 00:00:00 2001 -From: Ying Fang -Date: Mon, 29 Jul 2019 16:22:12 +0800 -Subject: [PATCH] vhost: cancel migration when vhost-user restarted during - migraiton - -Qemu will abort when vhost-user process is restarted during migration -when vhost_log_global_start/stop is called. The reason is clear that -vhost_dev_set_log returns -1 because network connection is temporarily -lost. Let's cancel migraiton and report it to user in this abnormal -situation. - -Signed-off-by: Ying Fang -Reviewed-by: Gonglei ---- - hw/virtio/vhost.c | 9 +++++++-- - 1 file changed, 7 insertions(+), 2 deletions(-) - -diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c -index 7f61018f..f302c506 100644 ---- a/hw/virtio/vhost.c -+++ b/hw/virtio/vhost.c -@@ -26,6 +26,7 @@ - #include "hw/virtio/virtio-bus.h" - #include "hw/virtio/virtio-access.h" - #include "migration/blocker.h" -+#include "migration/migration.h" - #include "sysemu/dma.h" - #include "trace.h" - -@@ -808,20 +809,24 @@ static int vhost_migration_log(MemoryListener *listener, int enable) - static void vhost_log_global_start(MemoryListener *listener) - { - int r; -+ Error *errp = NULL; - - r = vhost_migration_log(listener, true); - if (r < 0) { -- abort(); -+ error_setg(&errp, "Failed to start vhost migration log"); -+ migrate_fd_error(migrate_get_current(), errp); - } - } - - static void vhost_log_global_stop(MemoryListener *listener) - { - int r; -+ Error *errp = NULL; - - r = vhost_migration_log(listener, false); - if (r < 0) { -- abort(); -+ error_setg(&errp, "Failed to stop vhost migration log"); -+ migrate_fd_error(migrate_get_current(), errp); - } - } - --- -2.19.1 - diff --git a/vhost-fix-vhost_log-size-overflow-during-migration.patch b/vhost-fix-vhost_log-size-overflow-during-migration.patch deleted file mode 100644 index 2111f2aee55847dd6e58049aa2b4c399e97f9d82..0000000000000000000000000000000000000000 --- a/vhost-fix-vhost_log-size-overflow-during-migration.patch +++ /dev/null @@ -1,69 +0,0 @@ -From 240e647a14df9677b3a501f7b8b870e40aac3fd5 Mon Sep 17 00:00:00 2001 -From: Li Hangjing -Date: Mon, 3 Jun 2019 14:15:24 +0800 -Subject: [PATCH] vhost: fix vhost_log size overflow during migration - -When a guest which doesn't support multiqueue is migrated with a multi queues -vhost-user-blk deivce, a crash will occur like: - -0 qemu_memfd_alloc (name=, size=562949953421312, seals=, fd=0x7f87171fe8b4, errp=0x7f87171fe8a8) at util/memfd.c:153 -1 0x00007f883559d7cf in vhost_log_alloc (size=70368744177664, share=true) at hw/virtio/vhost.c:186 -2 0x00007f88355a0758 in vhost_log_get (listener=0x7f8838bd7940, enable=1) at qemu-2-12/hw/virtio/vhost.c:211 -3 vhost_dev_log_resize (listener=0x7f8838bd7940, enable=1) at hw/virtio/vhost.c:263 -4 vhost_migration_log (listener=0x7f8838bd7940, enable=1) at hw/virtio/vhost.c:787 -5 0x00007f88355463d6 in memory_global_dirty_log_start () at memory.c:2503 -6 0x00007f8835550577 in ram_init_bitmaps (f=0x7f88384ce600, opaque=0x7f8836024098) at migration/ram.c:2173 -7 ram_init_all (f=0x7f88384ce600, opaque=0x7f8836024098) at migration/ram.c:2192 -8 ram_save_setup (f=0x7f88384ce600, opaque=0x7f8836024098) at migration/ram.c:2219 -9 0x00007f88357a419d in qemu_savevm_state_setup (f=0x7f88384ce600) at migration/savevm.c:1002 -10 0x00007f883579fc3e in migration_thread (opaque=0x7f8837530400) at migration/migration.c:2382 -11 0x00007f8832447893 in start_thread () from /lib64/libpthread.so.0 -12 0x00007f8832178bfd in clone () from /lib64/libc.so.6 - -This is because vhost_get_log_size() returns a overflowed vhost-log size. -In this function, it uses the uninitialized variable vqs->used_phys and -vqs->used_size to get the vhost-log size. - -Signed-off-by: Li Hangjing -Reviewed-by: Xie Yongji -Reviewed-by: Chai Wen -Message-Id: <20190603061524.24076-1-lihangjing@baidu.com> -Cc: qemu-stable@nongnu.org -Reviewed-by: Michael S. Tsirkin -Signed-off-by: Michael S. Tsirkin -(cherry-pick from commit 240e647a14df9677b3a501f7b8b870e40aac3fd5) ---- - hw/virtio/vhost.c | 10 ++++++++++ - 1 file changed, 10 insertions(+) - -diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c -index 60747a6f93..bc899fc60e 100644 ---- a/hw/virtio/vhost.c -+++ b/hw/virtio/vhost.c -@@ -131,6 +131,11 @@ static int vhost_sync_dirty_bitmap(struct vhost_dev *dev, - } - for (i = 0; i < dev->nvqs; ++i) { - struct vhost_virtqueue *vq = dev->vqs + i; -+ -+ if (!vq->used_phys && !vq->used_size) { -+ continue; -+ } -+ - vhost_dev_sync_region(dev, section, start_addr, end_addr, vq->used_phys, - range_get_last(vq->used_phys, vq->used_size)); - } -@@ -168,6 +173,11 @@ static uint64_t vhost_get_log_size(struct vhost_dev *dev) - } - for (i = 0; i < dev->nvqs; ++i) { - struct vhost_virtqueue *vq = dev->vqs + i; -+ -+ if (!vq->used_phys && !vq->used_size) { -+ continue; -+ } -+ - uint64_t last = vq->used_phys + vq->used_size - 1; - log_size = MAX(log_size, last / VHOST_LOG_CHUNK + 1); - } --- -2.19.1 - diff --git a/vhost-user-blk-fix-invalid-memory-access.patch b/vhost-user-blk-fix-invalid-memory-access.patch new file mode 100644 index 0000000000000000000000000000000000000000..8244e455a306a8692f9cfb62fbb6d000f7702d9e --- /dev/null +++ b/vhost-user-blk-fix-invalid-memory-access.patch @@ -0,0 +1,127 @@ +From 0ac2e63575b5af918e333cc687bbd8e1ab7bb6fe Mon Sep 17 00:00:00 2001 +From: Li Feng +Date: Fri, 17 Apr 2020 18:17:07 +0800 +Subject: [PATCH 214/709] vhost-user-blk: fix invalid memory access + +when s->inflight is freed, vhost_dev_free_inflight may try to access +s->inflight->addr, it will retrigger the following issue. + +==7309==ERROR: AddressSanitizer: heap-use-after-free on address 0x604001020d18 at pc 0x555555ce948a bp 0x7fffffffb170 sp 0x7fffffffb160 +READ of size 8 at 0x604001020d18 thread T0 + #0 0x555555ce9489 in vhost_dev_free_inflight /root/smartx/qemu-el7/qemu-test/hw/virtio/vhost.c:1473 + #1 0x555555cd86eb in virtio_reset /root/smartx/qemu-el7/qemu-test/hw/virtio/virtio.c:1214 + #2 0x5555560d3eff in virtio_pci_reset hw/virtio/virtio-pci.c:1859 + #3 0x555555f2ac53 in device_set_realized hw/core/qdev.c:893 + #4 0x5555561d572c in property_set_bool qom/object.c:1925 + #5 0x5555561de8de in object_property_set_qobject qom/qom-qobject.c:27 + #6 0x5555561d99f4 in object_property_set_bool qom/object.c:1188 + #7 0x555555e50ae7 in qdev_device_add /root/smartx/qemu-el7/qemu-test/qdev-monitor.c:626 + #8 0x555555e51213 in qmp_device_add /root/smartx/qemu-el7/qemu-test/qdev-monitor.c:806 + #9 0x555555e8ff40 in hmp_device_add /root/smartx/qemu-el7/qemu-test/hmp.c:1951 + #10 0x555555be889a in handle_hmp_command /root/smartx/qemu-el7/qemu-test/monitor.c:3404 + #11 0x555555beac8b in monitor_command_cb /root/smartx/qemu-el7/qemu-test/monitor.c:4296 + #12 0x555556433eb7 in readline_handle_byte util/readline.c:393 + #13 0x555555be89ec in monitor_read /root/smartx/qemu-el7/qemu-test/monitor.c:4279 + #14 0x5555563285cc in tcp_chr_read chardev/char-socket.c:470 + #15 0x7ffff670b968 in g_main_context_dispatch (/lib64/libglib-2.0.so.0+0x4a968) + #16 0x55555640727c in glib_pollfds_poll util/main-loop.c:215 + #17 0x55555640727c in os_host_main_loop_wait util/main-loop.c:238 + #18 0x55555640727c in main_loop_wait util/main-loop.c:497 + #19 0x555555b2d0bf in main_loop /root/smartx/qemu-el7/qemu-test/vl.c:2013 + #20 0x555555b2d0bf in main /root/smartx/qemu-el7/qemu-test/vl.c:4776 + #21 0x7fffdd2eb444 in __libc_start_main (/lib64/libc.so.6+0x22444) + #22 0x555555b3767a (/root/smartx/qemu-el7/qemu-test/x86_64-softmmu/qemu-system-x86_64+0x5e367a) + +0x604001020d18 is located 8 bytes inside of 40-byte region [0x604001020d10,0x604001020d38) +freed by thread T0 here: + #0 0x7ffff6f00508 in __interceptor_free (/lib64/libasan.so.4+0xde508) + #1 0x7ffff671107d in g_free (/lib64/libglib-2.0.so.0+0x5007d) + +previously allocated by thread T0 here: + #0 0x7ffff6f00a88 in __interceptor_calloc (/lib64/libasan.so.4+0xdea88) + #1 0x7ffff6710fc5 in g_malloc0 (/lib64/libglib-2.0.so.0+0x4ffc5) + +SUMMARY: AddressSanitizer: heap-use-after-free /root/smartx/qemu-el7/qemu-test/hw/virtio/vhost.c:1473 in vhost_dev_free_inflight +Shadow bytes around the buggy address: + 0x0c08801fc150: fa fa 00 00 00 00 04 fa fa fa fd fd fd fd fd fa + 0x0c08801fc160: fa fa fd fd fd fd fd fd fa fa 00 00 00 00 04 fa + 0x0c08801fc170: fa fa 00 00 00 00 00 01 fa fa 00 00 00 00 04 fa + 0x0c08801fc180: fa fa 00 00 00 00 00 01 fa fa 00 00 00 00 00 01 + 0x0c08801fc190: fa fa 00 00 00 00 00 fa fa fa 00 00 00 00 04 fa +=>0x0c08801fc1a0: fa fa fd[fd]fd fd fd fa fa fa fd fd fd fd fd fa + 0x0c08801fc1b0: fa fa fd fd fd fd fd fa fa fa fd fd fd fd fd fa + 0x0c08801fc1c0: fa fa 00 00 00 00 00 fa fa fa fd fd fd fd fd fd + 0x0c08801fc1d0: fa fa 00 00 00 00 00 01 fa fa fd fd fd fd fd fa + 0x0c08801fc1e0: fa fa fd fd fd fd fd fa fa fa fd fd fd fd fd fd + 0x0c08801fc1f0: fa fa 00 00 00 00 00 01 fa fa fd fd fd fd fd fa +Shadow byte legend (one shadow byte represents 8 application bytes): + Addressable: 00 + Partially addressable: 01 02 03 04 05 06 07 + Heap left redzone: fa + Freed heap region: fd + Stack left redzone: f1 + Stack mid redzone: f2 + Stack right redzone: f3 + Stack after return: f5 + Stack use after scope: f8 + Global redzone: f9 + Global init order: f6 + Poisoned by user: f7 + Container overflow: fc + Array cookie: ac + Intra object redzone: bb + ASan internal: fe + Left alloca redzone: ca + Right alloca redzone: cb +==7309==ABORTING + +Signed-off-by: Li Feng +Message-Id: <20200417101707.14467-1-fengli@smartx.com> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +Reviewed-by: Raphael Norwitz +--- + hw/block/vhost-user-blk.c | 4 ++++ + hw/virtio/vhost.c | 2 +- + 2 files changed, 5 insertions(+), 1 deletion(-) + +diff --git a/hw/block/vhost-user-blk.c b/hw/block/vhost-user-blk.c +index 17df5338e7..6c485d1c9e 100644 +--- a/hw/block/vhost-user-blk.c ++++ b/hw/block/vhost-user-blk.c +@@ -441,7 +441,9 @@ reconnect: + + virtio_err: + g_free(s->vhost_vqs); ++ s->vhost_vqs = NULL; + g_free(s->inflight); ++ s->inflight = NULL; + for (i = 0; i < s->num_queues; i++) { + virtio_delete_queue(s->virtqs[i]); + } +@@ -462,7 +464,9 @@ static void vhost_user_blk_device_unrealize(DeviceState *dev, Error **errp) + vhost_dev_cleanup(&s->dev); + vhost_dev_free_inflight(s->inflight); + g_free(s->vhost_vqs); ++ s->vhost_vqs = NULL; + g_free(s->inflight); ++ s->inflight = NULL; + + for (i = 0; i < s->num_queues; i++) { + virtio_delete_queue(s->virtqs[i]); +diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c +index 01ebe12f28..aff98a0ede 100644 +--- a/hw/virtio/vhost.c ++++ b/hw/virtio/vhost.c +@@ -1514,7 +1514,7 @@ void vhost_dev_set_config_notifier(struct vhost_dev *hdev, + + void vhost_dev_free_inflight(struct vhost_inflight *inflight) + { +- if (inflight->addr) { ++ if (inflight && inflight->addr) { + qemu_memfd_free(inflight->addr, inflight->size, inflight->fd); + inflight->addr = NULL; + inflight->fd = -1; +-- +2.23.0 + diff --git a/vhost-user-scsi-prevent-using-uninitialized-vqs.patch b/vhost-user-scsi-prevent-using-uninitialized-vqs.patch deleted file mode 100644 index 9c4f92316d4da5e9e53ddc17e9915427e3cd9c36..0000000000000000000000000000000000000000 --- a/vhost-user-scsi-prevent-using-uninitialized-vqs.patch +++ /dev/null @@ -1,43 +0,0 @@ -From 19d56f560879081de411f359417eaaa2998c9e3a Mon Sep 17 00:00:00 2001 -From: Raphael Norwitz -Date: Tue, 11 Jun 2019 17:35:17 -0700 -Subject: [PATCH 5/5] vhost-user-scsi: prevent using uninitialized vqs - -Of the 3 virtqueues, seabios only sets cmd, leaving ctrl -and event without a physical address. This can cause -vhost_verify_ring_part_mapping to return ENOMEM, causing -the following logs: - -qemu-system-x86_64: Unable to map available ring for ring 0 -qemu-system-x86_64: Verify ring failure on region 0 - -The qemu commit e6cc11d64fc998c11a4dfcde8fda3fc33a74d844 -has already resolved the issue for vhost scsi devices but -the fix was never applied to vhost-user scsi devices. - -Signed-off-by: Raphael Norwitz -Reviewed-by: Stefan Hajnoczi -Message-id: 1560299717-177734-1-git-send-email-raphael.norwitz@nutanix.com -Message-Id: <1560299717-177734-1-git-send-email-raphael.norwitz@nutanix.com> -Signed-off-by: Stefan Hajnoczi -(cherry-picked from commit 5d4c1ed3d46d7e2010b389fe5f3376f605182ab0) ---- - hw/scsi/vhost-user-scsi.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/hw/scsi/vhost-user-scsi.c b/hw/scsi/vhost-user-scsi.c -index 8b1e687..241631f 100644 ---- a/hw/scsi/vhost-user-scsi.c -+++ b/hw/scsi/vhost-user-scsi.c -@@ -90,7 +90,7 @@ static void vhost_user_scsi_realize(DeviceState *dev, Error **errp) - } - - vsc->dev.nvqs = 2 + vs->conf.num_queues; -- vsc->dev.vqs = g_new(struct vhost_virtqueue, vsc->dev.nvqs); -+ vsc->dev.vqs = g_new0(struct vhost_virtqueue, vsc->dev.nvqs); - vsc->dev.vq_index = 0; - vsc->dev.backend_features = 0; - --- -1.8.3.1 - diff --git a/virtio-balloon-Better-names-for-offset-variables.patch b/virtio-balloon-Better-names-for-offset-variables.patch deleted file mode 100644 index 7f9d3a99432e80a2bd11f04f0eea79a00b7ef7b4..0000000000000000000000000000000000000000 --- a/virtio-balloon-Better-names-for-offset-variables.patch +++ /dev/null @@ -1,113 +0,0 @@ -From e6129b271b9dccca22c84870e313c315f2c70063 Mon Sep 17 00:00:00 2001 -From: David Hildenbrand -Date: Mon, 22 Jul 2019 15:41:06 +0200 -Subject: [PATCH] virtio-balloon: Better names for offset variables in - inflate/deflate code - -"host_page_base" is really confusing, let's make this clearer, also -rename the other offsets to indicate to which base they apply. - -offset -> mr_offset -ram_offset -> rb_offset -host_page_base -> rb_aligned_offset - -While at it, use QEMU_ALIGN_DOWN() instead of a handcrafted computation -and move the computation to the place where it is needed. - -Acked-by: David Gibson -Signed-off-by: David Hildenbrand -Message-Id: <20190722134108.22151-5-david@redhat.com> -Reviewed-by: Michael S. Tsirkin -Signed-off-by: Michael S. Tsirkin -(cherry-picked from commit e6129b271b9dccca22c84870e313c315f2c70063) ---- - hw/virtio/virtio-balloon.c | 26 +++++++++++++------------- - 1 file changed, 13 insertions(+), 13 deletions(-) - -diff --git a/hw/virtio/virtio-balloon.c b/hw/virtio/virtio-balloon.c -index 04a7e6c772..f206cc8bf7 100644 ---- a/hw/virtio/virtio-balloon.c -+++ b/hw/virtio/virtio-balloon.c -@@ -41,24 +41,23 @@ struct PartiallyBalloonedPage { - }; - - static void balloon_inflate_page(VirtIOBalloon *balloon, -- MemoryRegion *mr, hwaddr offset) -+ MemoryRegion *mr, hwaddr mr_offset) - { -- void *addr = memory_region_get_ram_ptr(mr) + offset; -+ void *addr = memory_region_get_ram_ptr(mr) + mr_offset; -+ ram_addr_t rb_offset, rb_aligned_offset; - RAMBlock *rb; - size_t rb_page_size; - int subpages; -- ram_addr_t ram_offset, host_page_base; - - /* XXX is there a better way to get to the RAMBlock than via a - * host address? */ -- rb = qemu_ram_block_from_host(addr, false, &ram_offset); -+ rb = qemu_ram_block_from_host(addr, false, &rb_offset); - rb_page_size = qemu_ram_pagesize(rb); -- host_page_base = ram_offset & ~(rb_page_size - 1); - - if (rb_page_size == BALLOON_PAGE_SIZE) { - /* Easy case */ - -- ram_block_discard_range(rb, ram_offset, rb_page_size); -+ ram_block_discard_range(rb, rb_offset, rb_page_size); - /* We ignore errors from ram_block_discard_range(), because it - * has already reported them, and failing to discard a balloon - * page is not fatal */ -@@ -74,11 +73,12 @@ static void balloon_inflate_page(VirtIOBalloon *balloon, - warn_report_once( - "Balloon used with backing page size > 4kiB, this may not be reliable"); - -+ rb_aligned_offset = QEMU_ALIGN_DOWN(rb_offset, rb_page_size); - subpages = rb_page_size / BALLOON_PAGE_SIZE; - - if (balloon->pbp - && (rb != balloon->pbp->rb -- || host_page_base != balloon->pbp->base)) { -+ || rb_aligned_offset != balloon->pbp->base)) { - /* We've partially ballooned part of a host page, but now - * we're trying to balloon part of a different one. Too hard, - * give up on the old partial page */ -@@ -91,10 +91,10 @@ static void balloon_inflate_page(VirtIOBalloon *balloon, - size_t bitlen = BITS_TO_LONGS(subpages) * sizeof(unsigned long); - balloon->pbp = g_malloc0(sizeof(PartiallyBalloonedPage) + bitlen); - balloon->pbp->rb = rb; -- balloon->pbp->base = host_page_base; -+ balloon->pbp->base = rb_aligned_offset; - } - -- set_bit((ram_offset - balloon->pbp->base) / BALLOON_PAGE_SIZE, -+ set_bit((rb_offset - balloon->pbp->base) / BALLOON_PAGE_SIZE, - balloon->pbp->bitmap); - - if (bitmap_full(balloon->pbp->bitmap, subpages)) { -@@ -112,18 +112,18 @@ static void balloon_inflate_page(VirtIOBalloon *balloon, - } - - static void balloon_deflate_page(VirtIOBalloon *balloon, -- MemoryRegion *mr, hwaddr offset) -+ MemoryRegion *mr, hwaddr mr_offset) - { -- void *addr = memory_region_get_ram_ptr(mr) + offset; -+ void *addr = memory_region_get_ram_ptr(mr) + mr_offset; -+ ram_addr_t rb_offset; - RAMBlock *rb; - size_t rb_page_size; -- ram_addr_t ram_offset; - void *host_addr; - int ret; - - /* XXX is there a better way to get to the RAMBlock than via a - * host address? */ -- rb = qemu_ram_block_from_host(addr, false, &ram_offset); -+ rb = qemu_ram_block_from_host(addr, false, &rb_offset); - rb_page_size = qemu_ram_pagesize(rb); - - if (balloon->pbp) { --- -2.19.1 - diff --git a/virtio-balloon-Fix-QEMU-crashes-on-pagesize-BALLOON_.patch b/virtio-balloon-Fix-QEMU-crashes-on-pagesize-BALLOON_.patch deleted file mode 100644 index 7507b9c3234e2c57f77d1f806ebb4ba02503f404..0000000000000000000000000000000000000000 --- a/virtio-balloon-Fix-QEMU-crashes-on-pagesize-BALLOON_.patch +++ /dev/null @@ -1,64 +0,0 @@ -From 483f13524bb2a08b7ff6a7560b846564ed3b0c33 Mon Sep 17 00:00:00 2001 -From: David Hildenbrand -Date: Mon, 22 Jul 2019 15:41:04 +0200 -Subject: [PATCH] virtio-balloon: Fix QEMU crashes on pagesize > - BALLOON_PAGE_SIZE - -We are using the wrong functions to set/clear bits, effectively touching -multiple bits, writing out of range of the bitmap, resulting in memory -corruptions. We have to use set_bit()/clear_bit() instead. - -Can easily be reproduced by starting a qemu guest on hugetlbfs memory, -inflating the balloon. QEMU crashes. This never could have worked -properly - especially, also pages would have been discarded when the -first sub-page would be inflated (the whole bitmap would be set). - -While testing I realized, that on hugetlbfs it is pretty much impossible -to discard a page - the guest just frees the 4k sub-pages in random order -most of the time. I was only able to discard a hugepage a handful of -times - so I hope that now works correctly. - -Fixes: ed48c59875b6 ("virtio-balloon: Safely handle BALLOON_PAGE_SIZE < host page size") -Fixes: b27b32391404 ("virtio-balloon: Fix possible guest memory corruption with inflates & deflates") -Cc: qemu-stable@nongnu.org #v4.0.0 -Acked-by: David Gibson -Signed-off-by: David Hildenbrand -Message-Id: <20190722134108.22151-3-david@redhat.com> -Reviewed-by: Michael S. Tsirkin -Signed-off-by: Michael S. Tsirkin -(cherry-pick from commit 483f13524bb2a08b7ff6a7560b846564ed3b0c33) ---- - hw/virtio/virtio-balloon.c | 10 ++++------ - 1 file changed, 4 insertions(+), 6 deletions(-) - -diff --git a/hw/virtio/virtio-balloon.c b/hw/virtio/virtio-balloon.c -index 515abf6553..a78d2d2184 100644 ---- a/hw/virtio/virtio-balloon.c -+++ b/hw/virtio/virtio-balloon.c -@@ -94,9 +94,8 @@ static void balloon_inflate_page(VirtIOBalloon *balloon, - balloon->pbp->base = host_page_base; - } - -- bitmap_set(balloon->pbp->bitmap, -- (ram_offset - balloon->pbp->base) / BALLOON_PAGE_SIZE, -- subpages); -+ set_bit((ram_offset - balloon->pbp->base) / BALLOON_PAGE_SIZE, -+ balloon->pbp->bitmap); - - if (bitmap_full(balloon->pbp->bitmap, subpages)) { - /* We've accumulated a full host page, we can actually discard -@@ -140,9 +139,8 @@ static void balloon_deflate_page(VirtIOBalloon *balloon, - * for a guest to do this in practice, but handle it anyway, - * since getting it wrong could mean discarding memory the - * guest is still using. */ -- bitmap_clear(balloon->pbp->bitmap, -- (ram_offset - balloon->pbp->base) / BALLOON_PAGE_SIZE, -- subpages); -+ clear_bit((ram_offset - balloon->pbp->base) / BALLOON_PAGE_SIZE, -+ balloon->pbp->bitmap); - - if (bitmap_empty(balloon->pbp->bitmap, subpages)) { - g_free(balloon->pbp); --- -2.19.1 - diff --git a/virtio-balloon-Fix-wrong-sign-extension-of-PFNs.patch b/virtio-balloon-Fix-wrong-sign-extension-of-PFNs.patch deleted file mode 100644 index 25497995573f8d5ae90f54398631736aa9f244f6..0000000000000000000000000000000000000000 --- a/virtio-balloon-Fix-wrong-sign-extension-of-PFNs.patch +++ /dev/null @@ -1,41 +0,0 @@ -From ffa207d08253ffffb3993a1dbe09e40af4fc91f1 Mon Sep 17 00:00:00 2001 -From: David Hildenbrand -Date: Mon, 22 Jul 2019 15:41:03 +0200 -Subject: [PATCH] virtio-balloon: Fix wrong sign extension of PFNs - -If we directly cast from int to uint64_t, we will first sign-extend to -an int64_t, which is wrong. We actually want to treat the PFNs like -unsigned values. - -As far as I can see, this dates back to the initial virtio-balloon -commit, but wasn't triggered as fairly big guests would be required. - -Cc: qemu-stable@nongnu.org -Reported-by: Michael S. Tsirkin -Signed-off-by: David Hildenbrand -Message-Id: <20190722134108.22151-2-david@redhat.com> -Reviewed-by: Michael S. Tsirkin -Signed-off-by: Michael S. Tsirkin -Reviewed-by: David Gibson -(cherry-picked from commit ffa207d08253ffffb3993a1dbe09e40af4fc91f1) ---- - hw/virtio/virtio-balloon.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/hw/virtio/virtio-balloon.c b/hw/virtio/virtio-balloon.c -index e85d1c0d5c..515abf6553 100644 ---- a/hw/virtio/virtio-balloon.c -+++ b/hw/virtio/virtio-balloon.c -@@ -343,8 +343,8 @@ static void virtio_balloon_handle_output(VirtIODevice *vdev, VirtQueue *vq) - } - - while (iov_to_buf(elem->out_sg, elem->out_num, offset, &pfn, 4) == 4) { -+ unsigned int p = virtio_ldl_p(vdev, &pfn); - hwaddr pa; -- int p = virtio_ldl_p(vdev, &pfn); - - pa = (hwaddr) p << VIRTIO_BALLOON_PFN_SHIFT; - offset += 4; --- -2.19.1 - diff --git a/virtio-balloon-Rework-pbp-tracking-data.patch b/virtio-balloon-Rework-pbp-tracking-data.patch deleted file mode 100644 index 1930ac131b30118df7a5cb00441495ccb0f2ec9e..0000000000000000000000000000000000000000 --- a/virtio-balloon-Rework-pbp-tracking-data.patch +++ /dev/null @@ -1,144 +0,0 @@ -From 1c5cfc2b7153dd72bf4b8ddc456408eb2b9b66d8 Mon Sep 17 00:00:00 2001 -From: David Hildenbrand -Date: Mon, 22 Jul 2019 15:41:07 +0200 -Subject: [PATCH] virtio-balloon: Rework pbp tracking data - -Using the address of a RAMBlock to test for a matching pbp is not really -safe. Instead, let's use the guest physical address of the base page -along with the page size (via the number of subpages). - -Also, let's allocate the bitmap separately. This makes the code -easier to read and maintain - we can reuse bitmap_new(). - -Prepare the code to move the PBP out of the device. - -Fixes: ed48c59875b6 ("virtio-balloon: Safely handle BALLOON_PAGE_SIZE < host page size") -Fixes: b27b32391404 ("virtio-balloon: Fix possible guest memory corruption with inflates & deflates") -Cc: qemu-stable@nongnu.org #v4.0.0 -Signed-off-by: David Hildenbrand -Message-Id: <20190722134108.22151-6-david@redhat.com> -Reviewed-by: Michael S. Tsirkin -Signed-off-by: Michael S. Tsirkin -(cherry-picked from commit 1c5cfc2b7153dd72bf4b8ddc456408eb2b9b66d8) ---- - hw/virtio/virtio-balloon.c | 69 +++++++++++++++++++++++++------------- - 1 file changed, 46 insertions(+), 23 deletions(-) - -diff --git a/hw/virtio/virtio-balloon.c b/hw/virtio/virtio-balloon.c -index f206cc8bf7..40d493a31a 100644 ---- a/hw/virtio/virtio-balloon.c -+++ b/hw/virtio/virtio-balloon.c -@@ -35,16 +35,44 @@ - #define BALLOON_PAGE_SIZE (1 << VIRTIO_BALLOON_PFN_SHIFT) - - struct PartiallyBalloonedPage { -- RAMBlock *rb; -- ram_addr_t base; -- unsigned long bitmap[]; -+ ram_addr_t base_gpa; -+ long subpages; -+ unsigned long *bitmap; - }; - -+static void virtio_balloon_pbp_free(PartiallyBalloonedPage *pbp) -+{ -+ if (!pbp) { -+ return; -+ } -+ g_free(pbp->bitmap); -+ g_free(pbp); -+} -+ -+static PartiallyBalloonedPage *virtio_balloon_pbp_alloc(ram_addr_t base_gpa, -+ long subpages) -+{ -+ PartiallyBalloonedPage *pbp = g_new0(PartiallyBalloonedPage, 1); -+ -+ pbp->base_gpa = base_gpa; -+ pbp->subpages = subpages; -+ pbp->bitmap = bitmap_new(subpages); -+ -+ return pbp; -+} -+ -+static bool virtio_balloon_pbp_matches(PartiallyBalloonedPage *pbp, -+ ram_addr_t base_gpa, long subpages) -+{ -+ return pbp->subpages == subpages && pbp->base_gpa == base_gpa; -+} -+ - static void balloon_inflate_page(VirtIOBalloon *balloon, - MemoryRegion *mr, hwaddr mr_offset) - { - void *addr = memory_region_get_ram_ptr(mr) + mr_offset; -- ram_addr_t rb_offset, rb_aligned_offset; -+ ram_addr_t rb_offset, rb_aligned_offset, base_gpa; -+ PartiallyBalloonedPage **pbp = &balloon->pbp; - RAMBlock *rb; - size_t rb_page_size; - int subpages; -@@ -75,39 +103,34 @@ static void balloon_inflate_page(VirtIOBalloon *balloon, - - rb_aligned_offset = QEMU_ALIGN_DOWN(rb_offset, rb_page_size); - subpages = rb_page_size / BALLOON_PAGE_SIZE; -+ base_gpa = memory_region_get_ram_addr(mr) + mr_offset - -+ (rb_offset - rb_aligned_offset); - -- if (balloon->pbp -- && (rb != balloon->pbp->rb -- || rb_aligned_offset != balloon->pbp->base)) { -+ if (*pbp && !virtio_balloon_pbp_matches(*pbp, base_gpa, subpages)) { - /* We've partially ballooned part of a host page, but now - * we're trying to balloon part of a different one. Too hard, - * give up on the old partial page */ -- g_free(balloon->pbp); -- balloon->pbp = NULL; -+ virtio_balloon_pbp_free(*pbp); -+ *pbp = NULL; - } - -- if (!balloon->pbp) { -- /* Starting on a new host page */ -- size_t bitlen = BITS_TO_LONGS(subpages) * sizeof(unsigned long); -- balloon->pbp = g_malloc0(sizeof(PartiallyBalloonedPage) + bitlen); -- balloon->pbp->rb = rb; -- balloon->pbp->base = rb_aligned_offset; -+ if (!*pbp) { -+ *pbp = virtio_balloon_pbp_alloc(base_gpa, subpages); - } - -- set_bit((rb_offset - balloon->pbp->base) / BALLOON_PAGE_SIZE, -- balloon->pbp->bitmap); -+ set_bit((rb_offset - rb_aligned_offset) / BALLOON_PAGE_SIZE, -+ (*pbp)->bitmap); - -- if (bitmap_full(balloon->pbp->bitmap, subpages)) { -+ if (bitmap_full((*pbp)->bitmap, subpages)) { - /* We've accumulated a full host page, we can actually discard - * it now */ - -- ram_block_discard_range(rb, balloon->pbp->base, rb_page_size); -+ ram_block_discard_range(rb, rb_aligned_offset, rb_page_size); - /* We ignore errors from ram_block_discard_range(), because it - * has already reported them, and failing to discard a balloon - * page is not fatal */ -- -- g_free(balloon->pbp); -- balloon->pbp = NULL; -+ virtio_balloon_pbp_free(*pbp); -+ *pbp = NULL; - } - } - -@@ -128,7 +151,7 @@ static void balloon_deflate_page(VirtIOBalloon *balloon, - - if (balloon->pbp) { - /* Let's play safe and always reset the pbp on deflation requests. */ -- g_free(balloon->pbp); -+ virtio_balloon_pbp_free(balloon->pbp); - balloon->pbp = NULL; - } - --- -2.19.1 - diff --git a/virtio-balloon-Simplify-deflate-with-pbp.patch b/virtio-balloon-Simplify-deflate-with-pbp.patch deleted file mode 100644 index 673ae1dd4b097cd9273eb6bc312f2effaac8cba4..0000000000000000000000000000000000000000 --- a/virtio-balloon-Simplify-deflate-with-pbp.patch +++ /dev/null @@ -1,67 +0,0 @@ -From 2ffc49eea1bbd454913a88a0ad872c2649b36950 Mon Sep 17 00:00:00 2001 -From: David Hildenbrand -Date: Mon, 22 Jul 2019 15:41:05 +0200 -Subject: [PATCH] virtio-balloon: Simplify deflate with pbp - -Let's simplify this - the case we are optimizing for is very hard to -trigger and not worth the effort. If we're switching from inflation to -deflation, let's reset the pbp. - -Acked-by: David Gibson -Signed-off-by: David Hildenbrand -Message-Id: <20190722134108.22151-4-david@redhat.com> -Reviewed-by: Michael S. Tsirkin -Signed-off-by: Michael S. Tsirkin -(cherry-picked from commit 2ffc49eea1bbd454913a88a0ad872c2649b36950) ---- - hw/virtio/virtio-balloon.c | 26 +++++--------------------- - 1 file changed, 5 insertions(+), 21 deletions(-) - -diff --git a/hw/virtio/virtio-balloon.c b/hw/virtio/virtio-balloon.c -index a78d2d2184..04a7e6c772 100644 ---- a/hw/virtio/virtio-balloon.c -+++ b/hw/virtio/virtio-balloon.c -@@ -117,7 +117,7 @@ static void balloon_deflate_page(VirtIOBalloon *balloon, - void *addr = memory_region_get_ram_ptr(mr) + offset; - RAMBlock *rb; - size_t rb_page_size; -- ram_addr_t ram_offset, host_page_base; -+ ram_addr_t ram_offset; - void *host_addr; - int ret; - -@@ -125,27 +125,11 @@ static void balloon_deflate_page(VirtIOBalloon *balloon, - * host address? */ - rb = qemu_ram_block_from_host(addr, false, &ram_offset); - rb_page_size = qemu_ram_pagesize(rb); -- host_page_base = ram_offset & ~(rb_page_size - 1); -- -- if (balloon->pbp -- && rb == balloon->pbp->rb -- && host_page_base == balloon->pbp->base) { -- int subpages = rb_page_size / BALLOON_PAGE_SIZE; - -- /* -- * This means the guest has asked to discard some of the 4kiB -- * subpages of a host page, but then changed its mind and -- * asked to keep them after all. It's exceedingly unlikely -- * for a guest to do this in practice, but handle it anyway, -- * since getting it wrong could mean discarding memory the -- * guest is still using. */ -- clear_bit((ram_offset - balloon->pbp->base) / BALLOON_PAGE_SIZE, -- balloon->pbp->bitmap); -- -- if (bitmap_empty(balloon->pbp->bitmap, subpages)) { -- g_free(balloon->pbp); -- balloon->pbp = NULL; -- } -+ if (balloon->pbp) { -+ /* Let's play safe and always reset the pbp on deflation requests. */ -+ g_free(balloon->pbp); -+ balloon->pbp = NULL; - } - - host_addr = (void *)((uintptr_t)addr & ~(rb_page_size - 1)); --- -2.19.1 - diff --git a/virtio-balloon-Use-temporary-PBP-only.patch b/virtio-balloon-Use-temporary-PBP-only.patch deleted file mode 100644 index 9d0a8cda0b48d706cddda9d75b74bcfb366a60fe..0000000000000000000000000000000000000000 --- a/virtio-balloon-Use-temporary-PBP-only.patch +++ /dev/null @@ -1,136 +0,0 @@ -From 8e20acad634e38f29afd54b951c42eec113288bc Mon Sep 17 00:00:00 2001 -From: David Hildenbrand -Date: Mon, 22 Jul 2019 15:41:08 +0200 -Subject: [PATCH] virtio-balloon: Use temporary PBP only - -We still have multiple issues in the current code -- The PBP is not freed during unrealize() -- The PBP is not reset on device resets: After a reset, the PBP is stale. -- We are not indicating VIRTIO_BALLOON_F_MUST_TELL_HOST, therefore - guests (esp. legacy guests) will reuse pages without deflating, - turning the PBP stale. Adding that would require compat handling. - -Instead, let's use the PBP only temporarily, when processing one bulk of -inflation requests. This will keep guest_page_size > 4k working (with -Linux guests). There is nothing to do for deflation requests anymore. -The pbp is only used for a limited amount of time. - -Fixes: ed48c59875b6 ("virtio-balloon: Safely handle BALLOON_PAGE_SIZE < host page size") -Cc: qemu-stable@nongnu.org #v4.0.0 -Suggested-by: Michael S. Tsirkin -Signed-off-by: David Hildenbrand -Message-Id: <20190722134108.22151-7-david@redhat.com> -Reviewed-by: Michael S. Tsirkin -Signed-off-by: Michael S. Tsirkin -Acked-by: David Gibson -(cherry picked from commit a8cd64d488325f3be5c4ddec4bf07efb3b8c7330) -Signed-off-by: Michael Roth ---- - hw/virtio/virtio-balloon.c | 21 +++++++++------------ - include/hw/virtio/virtio-balloon.h | 3 --- - 2 files changed, 9 insertions(+), 15 deletions(-) - -diff --git a/hw/virtio/virtio-balloon.c b/hw/virtio/virtio-balloon.c -index 49999d0bbe..bd54e302de 100644 ---- a/hw/virtio/virtio-balloon.c -+++ b/hw/virtio/virtio-balloon.c -@@ -34,11 +34,11 @@ - - #define BALLOON_PAGE_SIZE (1 << VIRTIO_BALLOON_PFN_SHIFT) - --struct PartiallyBalloonedPage { -+typedef struct PartiallyBalloonedPage { - ram_addr_t base_gpa; - long subpages; - unsigned long *bitmap; --}; -+} PartiallyBalloonedPage; - - static void virtio_balloon_pbp_free(PartiallyBalloonedPage *pbp) - { -@@ -68,11 +68,11 @@ static bool virtio_balloon_pbp_matches(PartiallyBalloonedPage *pbp, - } - - static void balloon_inflate_page(VirtIOBalloon *balloon, -- MemoryRegion *mr, hwaddr mr_offset) -+ MemoryRegion *mr, hwaddr mr_offset, -+ PartiallyBalloonedPage **pbp) - { - void *addr = memory_region_get_ram_ptr(mr) + mr_offset; - ram_addr_t rb_offset, rb_aligned_offset, base_gpa; -- PartiallyBalloonedPage **pbp = &balloon->pbp; - RAMBlock *rb; - size_t rb_page_size; - int subpages; -@@ -149,12 +149,6 @@ static void balloon_deflate_page(VirtIOBalloon *balloon, - rb = qemu_ram_block_from_host(addr, false, &rb_offset); - rb_page_size = qemu_ram_pagesize(rb); - -- if (balloon->pbp) { -- /* Let's play safe and always reset the pbp on deflation requests. */ -- virtio_balloon_pbp_free(balloon->pbp); -- balloon->pbp = NULL; -- } -- - host_addr = (void *)((uintptr_t)addr & ~(rb_page_size - 1)); - - /* When a page is deflated, we hint the whole host page it lives -@@ -336,6 +330,7 @@ static void balloon_stats_set_poll_interval(Object *obj, Visitor *v, - static void virtio_balloon_handle_output(VirtIODevice *vdev, VirtQueue *vq) - { - VirtIOBalloon *s = VIRTIO_BALLOON(vdev); -+ PartiallyBalloonedPage *pbp = NULL; - VirtQueueElement *elem; - MemoryRegionSection section; - -@@ -344,7 +339,7 @@ static void virtio_balloon_handle_output(VirtIODevice *vdev, VirtQueue *vq) - uint32_t pfn; - elem = virtqueue_pop(vq, sizeof(VirtQueueElement)); - if (!elem) { -- return; -+ break; - } - - while (iov_to_buf(elem->out_sg, elem->out_num, offset, &pfn, 4) == 4) { -@@ -373,7 +368,7 @@ static void virtio_balloon_handle_output(VirtIODevice *vdev, VirtQueue *vq) - if (!qemu_balloon_is_inhibited()) { - if (vq == s->ivq) { - balloon_inflate_page(s, section.mr, -- section.offset_within_region); -+ section.offset_within_region, &pbp); - } else if (vq == s->dvq) { - balloon_deflate_page(s, section.mr, section.offset_within_region); - } else { -@@ -387,6 +382,8 @@ static void virtio_balloon_handle_output(VirtIODevice *vdev, VirtQueue *vq) - virtio_notify(vdev, vq); - g_free(elem); - } -+ -+ virtio_balloon_pbp_free(pbp); - } - - static void virtio_balloon_receive_stats(VirtIODevice *vdev, VirtQueue *vq) -diff --git a/include/hw/virtio/virtio-balloon.h b/include/hw/virtio/virtio-balloon.h -index 5a99293a45..d1c968d237 100644 ---- a/include/hw/virtio/virtio-balloon.h -+++ b/include/hw/virtio/virtio-balloon.h -@@ -33,8 +33,6 @@ typedef struct virtio_balloon_stat_modern { - uint64_t val; - } VirtIOBalloonStatModern; - --typedef struct PartiallyBalloonedPage PartiallyBalloonedPage; -- - enum virtio_balloon_free_page_report_status { - FREE_PAGE_REPORT_S_STOP = 0, - FREE_PAGE_REPORT_S_REQUESTED = 1, -@@ -70,7 +68,6 @@ typedef struct VirtIOBalloon { - int64_t stats_last_update; - int64_t stats_poll_interval; - uint32_t host_features; -- PartiallyBalloonedPage *pbp; - - bool qemu_4_0_config_size; - } VirtIOBalloon; --- -2.19.1 - diff --git a/virtio-balloon-don-t-track-subpages-for-the-PBP.patch b/virtio-balloon-don-t-track-subpages-for-the-PBP.patch deleted file mode 100644 index 942eb762b2bef00bb7b76eaa7c83287b6aeaddeb..0000000000000000000000000000000000000000 --- a/virtio-balloon-don-t-track-subpages-for-the-PBP.patch +++ /dev/null @@ -1,62 +0,0 @@ -From 9a7ca8a7c920360db9dcaf616ca6f1440c025043 Mon Sep 17 00:00:00 2001 -From: David Hildenbrand -Date: Thu, 25 Jul 2019 13:36:38 +0200 -Subject: [PATCH] virtio-balloon: don't track subpages for the PBP - -As ramblocks cannot get removed/readded while we are processing a bulk -of inflation requests, there is no more need to track the page size -in form of the number of subpages. - -Suggested-by: David Gibson -Signed-off-by: David Hildenbrand -Message-Id: <20190725113638.4702-8-david@redhat.com> -Reviewed-by: Michael S. Tsirkin -Signed-off-by: Michael S. Tsirkin -(cherry-picked from commit 9a7ca8a7c920360db9dcaf616ca6f1440c025043) ---- - hw/virtio/virtio-balloon.c | 8 +++----- - 1 file changed, 3 insertions(+), 5 deletions(-) - -diff --git a/hw/virtio/virtio-balloon.c b/hw/virtio/virtio-balloon.c -index a6282d58d4..fe9664e42c 100644 ---- a/hw/virtio/virtio-balloon.c -+++ b/hw/virtio/virtio-balloon.c -@@ -36,7 +36,6 @@ - - typedef struct PartiallyBalloonedPage { - ram_addr_t base_gpa; -- long subpages; - unsigned long *bitmap; - } PartiallyBalloonedPage; - -@@ -55,16 +54,15 @@ static PartiallyBalloonedPage *virtio_balloon_pbp_alloc(ram_addr_t base_gpa, - PartiallyBalloonedPage *pbp = g_new0(PartiallyBalloonedPage, 1); - - pbp->base_gpa = base_gpa; -- pbp->subpages = subpages; - pbp->bitmap = bitmap_new(subpages); - - return pbp; - } - - static bool virtio_balloon_pbp_matches(PartiallyBalloonedPage *pbp, -- ram_addr_t base_gpa, long subpages) -+ ram_addr_t base_gpa) - { -- return pbp->subpages == subpages && pbp->base_gpa == base_gpa; -+ return pbp->base_gpa == base_gpa; - } - - static void balloon_inflate_page(VirtIOBalloon *balloon, -@@ -106,7 +104,7 @@ static void balloon_inflate_page(VirtIOBalloon *balloon, - base_gpa = memory_region_get_ram_addr(mr) + mr_offset - - (rb_offset - rb_aligned_offset); - -- if (*pbp && !virtio_balloon_pbp_matches(*pbp, base_gpa, subpages)) { -+ if (*pbp && !virtio_balloon_pbp_matches(*pbp, base_gpa)) { - /* We've partially ballooned part of a host page, but now - * we're trying to balloon part of a different one. Too hard, - * give up on the old partial page */ --- -2.19.1 - diff --git a/virtio-balloon-fix-QEMU-4.0-config-size-migration-in.patch b/virtio-balloon-fix-QEMU-4.0-config-size-migration-in.patch deleted file mode 100644 index be4a77b758b75bfde52359fad57868a4a882d18f..0000000000000000000000000000000000000000 --- a/virtio-balloon-fix-QEMU-4.0-config-size-migration-in.patch +++ /dev/null @@ -1,148 +0,0 @@ -From a6fe4a3aa8007524ffe4758109c08f3ac102c628 Mon Sep 17 00:00:00 2001 -From: Stefan Hajnoczi -Date: Wed, 10 Jul 2019 16:14:40 +0200 -Subject: [PATCH] virtio-balloon: fix QEMU 4.0 config size migration - incompatibility - -The virtio-balloon config size changed in QEMU 4.0 even for existing -machine types. Migration from QEMU 3.1 to 4.0 can fail in some -circumstances with the following error: - - qemu-system-x86_64: get_pci_config_device: Bad config data: i=0x10 read: a1 device: 1 cmask: ff wmask: c0 w1cmask:0 - -This happens because the virtio-balloon config size affects the VIRTIO -Legacy I/O Memory PCI BAR size. - -Introduce a qdev property called "qemu-4-0-config-size" and enable it -only for the QEMU 4.0 machine types. This way <4.0 machine types use -the old size, 4.0 uses the larger size, and >4.0 machine types use the -appropriate size depending on enabled virtio-balloon features. - -Live migration to and from old QEMUs to QEMU 4.1 works again as long as -a versioned machine type is specified (do not use just "pc"!). - -Originally-by: Wolfgang Bumiller -Signed-off-by: Stefan Hajnoczi -Message-Id: <20190710141440.27635-1-stefanha@redhat.com> -Reviewed-by: Dr. David Alan Gilbert -Tested-by: Dr. David Alan Gilbert -Tested-by: Wolfgang Bumiller -Reviewed-by: Michael S. Tsirkin -Signed-off-by: Michael S. Tsirkin -(cherry picked from commit 2bbadb08ce272d65e1f78621002008b07d1e0f03) - Conflicts: - hw/core/machine.c -* drop context dep. on 0a71966253c -Signed-off-by: Michael Roth ---- - hw/core/machine.c | 5 ++++- - hw/virtio/virtio-balloon.c | 28 +++++++++++++++++++++++++--- - include/hw/virtio/virtio-balloon.h | 2 ++ - 3 files changed, 31 insertions(+), 4 deletions(-) - -diff --git a/hw/core/machine.c b/hw/core/machine.c -index eb34f53a85..55b08f1466 100644 ---- a/hw/core/machine.c -+++ b/hw/core/machine.c -@@ -24,7 +24,9 @@ - #include "hw/pci/pci.h" - #include "hw/mem/nvdimm.h" - --GlobalProperty hw_compat_4_0[] = {}; -+GlobalProperty hw_compat_4_0[] = { -+ { "virtio-balloon-device", "qemu-4-0-config-size", "true" }, -+}; - const size_t hw_compat_4_0_len = G_N_ELEMENTS(hw_compat_4_0); - - GlobalProperty hw_compat_3_1[] = { -@@ -39,6 +41,7 @@ GlobalProperty hw_compat_3_1[] = { - { "usb-tablet", "serial", "42" }, - { "virtio-blk-device", "discard", "false" }, - { "virtio-blk-device", "write-zeroes", "false" }, -+ { "virtio-balloon-device", "qemu-4-0-config-size", "false" }, - }; - const size_t hw_compat_3_1_len = G_N_ELEMENTS(hw_compat_3_1); - -diff --git a/hw/virtio/virtio-balloon.c b/hw/virtio/virtio-balloon.c -index 2112874055..5579260fd4 100644 ---- a/hw/virtio/virtio-balloon.c -+++ b/hw/virtio/virtio-balloon.c -@@ -615,6 +615,22 @@ virtio_balloon_free_page_report_notify(NotifierWithReturn *n, void *data) - return 0; - } - -+static size_t virtio_balloon_config_size(VirtIOBalloon *s) -+{ -+ uint64_t features = s->host_features; -+ -+ if (s->qemu_4_0_config_size) { -+ return sizeof(struct virtio_balloon_config); -+ } -+ if (virtio_has_feature(features, VIRTIO_BALLOON_F_PAGE_POISON)) { -+ return sizeof(struct virtio_balloon_config); -+ } -+ if (virtio_has_feature(features, VIRTIO_BALLOON_F_FREE_PAGE_HINT)) { -+ return offsetof(struct virtio_balloon_config, poison_val); -+ } -+ return offsetof(struct virtio_balloon_config, free_page_report_cmd_id); -+} -+ - static void virtio_balloon_get_config(VirtIODevice *vdev, uint8_t *config_data) - { - VirtIOBalloon *dev = VIRTIO_BALLOON(vdev); -@@ -635,7 +651,7 @@ static void virtio_balloon_get_config(VirtIODevice *vdev, uint8_t *config_data) - } - - trace_virtio_balloon_get_config(config.num_pages, config.actual); -- memcpy(config_data, &config, sizeof(struct virtio_balloon_config)); -+ memcpy(config_data, &config, virtio_balloon_config_size(dev)); - } - - static int build_dimm_list(Object *obj, void *opaque) -@@ -679,7 +695,7 @@ static void virtio_balloon_set_config(VirtIODevice *vdev, - uint32_t oldactual = dev->actual; - ram_addr_t vm_ram_size = get_current_ram_size(); - -- memcpy(&config, config_data, sizeof(struct virtio_balloon_config)); -+ memcpy(&config, config_data, virtio_balloon_config_size(dev)); - dev->actual = le32_to_cpu(config.actual); - if (dev->actual != oldactual) { - qapi_event_send_balloon_change(vm_ram_size - -@@ -766,7 +782,7 @@ static void virtio_balloon_device_realize(DeviceState *dev, Error **errp) - int ret; - - virtio_init(vdev, "virtio-balloon", VIRTIO_ID_BALLOON, -- sizeof(struct virtio_balloon_config)); -+ virtio_balloon_config_size(s)); - - ret = qemu_add_balloon_handler(virtio_balloon_to_target, - virtio_balloon_stat, s); -@@ -897,6 +913,12 @@ static Property virtio_balloon_properties[] = { - VIRTIO_BALLOON_F_DEFLATE_ON_OOM, false), - DEFINE_PROP_BIT("free-page-hint", VirtIOBalloon, host_features, - VIRTIO_BALLOON_F_FREE_PAGE_HINT, false), -+ /* QEMU 4.0 accidentally changed the config size even when free-page-hint -+ * is disabled, resulting in QEMU 3.1 migration incompatibility. This -+ * property retains this quirk for QEMU 4.1 machine types. -+ */ -+ DEFINE_PROP_BOOL("qemu-4-0-config-size", VirtIOBalloon, -+ qemu_4_0_config_size, false), - DEFINE_PROP_LINK("iothread", VirtIOBalloon, iothread, TYPE_IOTHREAD, - IOThread *), - DEFINE_PROP_END_OF_LIST(), -diff --git a/include/hw/virtio/virtio-balloon.h b/include/hw/virtio/virtio-balloon.h -index 1afafb12f6..5a99293a45 100644 ---- a/include/hw/virtio/virtio-balloon.h -+++ b/include/hw/virtio/virtio-balloon.h -@@ -71,6 +71,8 @@ typedef struct VirtIOBalloon { - int64_t stats_poll_interval; - uint32_t host_features; - PartiallyBalloonedPage *pbp; -+ -+ bool qemu_4_0_config_size; - } VirtIOBalloon; - - #endif --- -2.19.1 - diff --git a/virtio-balloon-free-pbp-more-aggressively.patch b/virtio-balloon-free-pbp-more-aggressively.patch deleted file mode 100644 index 8ba4bcd66b81dc5ce5a7c015b4b33287a9599249..0000000000000000000000000000000000000000 --- a/virtio-balloon-free-pbp-more-aggressively.patch +++ /dev/null @@ -1,130 +0,0 @@ -From 1b47b37c33ec01ae1efc527f4c97f97f93723bc4 Mon Sep 17 00:00:00 2001 -From: "Michael S. Tsirkin" -Date: Thu, 25 Jul 2019 07:54:25 -0400 -Subject: [PATCH] virtio-balloon: free pbp more aggressively - -Previous patches switched to a temporary pbp but that does not go far -enough: after device uses a buffer, guest is free to reuse it, so -tracking the page and freeing it later is wrong. - -Free and reset the pbp after we push each element. - -Fixes: ed48c59875b6 ("virtio-balloon: Safely handle BALLOON_PAGE_SIZE < host page size") -Cc: qemu-stable@nongnu.org #v4.0.0 -Cc: David Hildenbrand -Signed-off-by: Michael S. Tsirkin -(cherry-picked from commit 1b47b37c33ec01ae1efc527f4c97f97f93723bc4) ---- - hw/virtio/virtio-balloon.c | 37 ++++++++++++++++--------------------- - 1 file changed, 16 insertions(+), 21 deletions(-) - -diff --git a/hw/virtio/virtio-balloon.c b/hw/virtio/virtio-balloon.c -index fe9664e42c..25de154307 100644 ---- a/hw/virtio/virtio-balloon.c -+++ b/hw/virtio/virtio-balloon.c -@@ -41,22 +41,19 @@ typedef struct PartiallyBalloonedPage { - - static void virtio_balloon_pbp_free(PartiallyBalloonedPage *pbp) - { -- if (!pbp) { -+ if (!pbp->bitmap) { - return; - } - g_free(pbp->bitmap); -- g_free(pbp); -+ pbp->bitmap = NULL; - } - --static PartiallyBalloonedPage *virtio_balloon_pbp_alloc(ram_addr_t base_gpa, -- long subpages) -+static void virtio_balloon_pbp_alloc(PartiallyBalloonedPage *pbp, -+ ram_addr_t base_gpa, -+ long subpages) - { -- PartiallyBalloonedPage *pbp = g_new0(PartiallyBalloonedPage, 1); -- - pbp->base_gpa = base_gpa; - pbp->bitmap = bitmap_new(subpages); -- -- return pbp; - } - - static bool virtio_balloon_pbp_matches(PartiallyBalloonedPage *pbp, -@@ -67,7 +64,7 @@ static bool virtio_balloon_pbp_matches(PartiallyBalloonedPage *pbp, - - static void balloon_inflate_page(VirtIOBalloon *balloon, - MemoryRegion *mr, hwaddr mr_offset, -- PartiallyBalloonedPage **pbp) -+ PartiallyBalloonedPage *pbp) - { - void *addr = memory_region_get_ram_ptr(mr) + mr_offset; - ram_addr_t rb_offset, rb_aligned_offset, base_gpa; -@@ -104,22 +101,21 @@ static void balloon_inflate_page(VirtIOBalloon *balloon, - base_gpa = memory_region_get_ram_addr(mr) + mr_offset - - (rb_offset - rb_aligned_offset); - -- if (*pbp && !virtio_balloon_pbp_matches(*pbp, base_gpa)) { -+ if (pbp->bitmap && !virtio_balloon_pbp_matches(pbp, base_gpa)) { - /* We've partially ballooned part of a host page, but now - * we're trying to balloon part of a different one. Too hard, - * give up on the old partial page */ -- virtio_balloon_pbp_free(*pbp); -- *pbp = NULL; -+ virtio_balloon_pbp_free(pbp); - } - -- if (!*pbp) { -- *pbp = virtio_balloon_pbp_alloc(base_gpa, subpages); -+ if (!pbp->bitmap) { -+ virtio_balloon_pbp_alloc(pbp, base_gpa, subpages); - } - - set_bit((rb_offset - rb_aligned_offset) / BALLOON_PAGE_SIZE, -- (*pbp)->bitmap); -+ pbp->bitmap); - -- if (bitmap_full((*pbp)->bitmap, subpages)) { -+ if (bitmap_full(pbp->bitmap, subpages)) { - /* We've accumulated a full host page, we can actually discard - * it now */ - -@@ -127,8 +123,7 @@ static void balloon_inflate_page(VirtIOBalloon *balloon, - /* We ignore errors from ram_block_discard_range(), because it - * has already reported them, and failing to discard a balloon - * page is not fatal */ -- virtio_balloon_pbp_free(*pbp); -- *pbp = NULL; -+ virtio_balloon_pbp_free(pbp); - } - } - -@@ -328,13 +323,14 @@ static void balloon_stats_set_poll_interval(Object *obj, Visitor *v, - static void virtio_balloon_handle_output(VirtIODevice *vdev, VirtQueue *vq) - { - VirtIOBalloon *s = VIRTIO_BALLOON(vdev); -- PartiallyBalloonedPage *pbp = NULL; - VirtQueueElement *elem; - MemoryRegionSection section; - - for (;;) { -+ PartiallyBalloonedPage pbp = {}; - size_t offset = 0; - uint32_t pfn; -+ - elem = virtqueue_pop(vq, sizeof(VirtQueueElement)); - if (!elem) { - break; -@@ -379,9 +375,8 @@ static void virtio_balloon_handle_output(VirtIODevice *vdev, VirtQueue *vq) - virtqueue_push(vq, elem, offset); - virtio_notify(vdev, vq); - g_free(elem); -+ virtio_balloon_pbp_free(&pbp); - } -- -- virtio_balloon_pbp_free(pbp); - } - - static void virtio_balloon_receive_stats(VirtIODevice *vdev, VirtQueue *vq) --- -2.19.1 - diff --git a/virtio-net-Fix-duplex-.-and-speed-.-error-handling.patch b/virtio-net-Fix-duplex-.-and-speed-.-error-handling.patch new file mode 100644 index 0000000000000000000000000000000000000000..13c94c008bd60d515aa0a47fe392bcc54ad7df4d --- /dev/null +++ b/virtio-net-Fix-duplex-.-and-speed-.-error-handling.patch @@ -0,0 +1,91 @@ +From 843c4cfcf445fc3d6458ff31136c44e03dda8866 Mon Sep 17 00:00:00 2001 +From: Markus Armbruster +Date: Wed, 22 Apr 2020 15:07:13 +0200 +Subject: [PATCH 021/709] virtio-net: Fix duplex=... and speed=... error + handling +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +virtio_net_device_realize() rejects invalid duplex and speed values. +The error handling is broken: + + $ ../qemu/bld-sani/x86_64-softmmu/qemu-system-x86_64 -S -display none -monitor stdio + QEMU 4.2.93 monitor - type 'help' for more information + (qemu) device_add virtio-net,duplex=x + Error: 'duplex' must be 'half' or 'full' + (qemu) c + ================================================================= + ==15654==ERROR: AddressSanitizer: heap-use-after-free on address 0x62e000014590 at pc 0x560b75c8dc13 bp 0x7fffdf1a6950 sp 0x7fffdf1a6940 + READ of size 8 at 0x62e000014590 thread T0 + #0 0x560b75c8dc12 in object_dynamic_cast_assert /work/armbru/qemu/qom/object.c:826 + #1 0x560b74c38ac0 in virtio_vmstate_change /work/armbru/qemu/hw/virtio/virtio.c:3210 + #2 0x560b74d9765e in vm_state_notify /work/armbru/qemu/softmmu/vl.c:1271 + #3 0x560b7494ba72 in vm_prepare_start /work/armbru/qemu/cpus.c:2156 + #4 0x560b7494bacd in vm_start /work/armbru/qemu/cpus.c:2162 + #5 0x560b75a7d890 in qmp_cont /work/armbru/qemu/monitor/qmp-cmds.c:160 + #6 0x560b75a8d70a in hmp_cont /work/armbru/qemu/monitor/hmp-cmds.c:1043 + #7 0x560b75a799f2 in handle_hmp_command /work/armbru/qemu/monitor/hmp.c:1082 + [...] + + 0x62e000014590 is located 33168 bytes inside of 42288-byte region [0x62e00000c400,0x62e000016930) + freed by thread T1 here: + #0 0x7feadd39491f in __interceptor_free (/lib64/libasan.so.5+0x10d91f) + #1 0x7feadcebcd7c in g_free (/lib64/libglib-2.0.so.0+0x55d7c) + #2 0x560b75c8fd40 in object_unref /work/armbru/qemu/qom/object.c:1128 + #3 0x560b7498a625 in memory_region_unref /work/armbru/qemu/memory.c:1762 + #4 0x560b74999fa4 in do_address_space_destroy /work/armbru/qemu/memory.c:2788 + #5 0x560b762362fc in call_rcu_thread /work/armbru/qemu/util/rcu.c:283 + #6 0x560b761c8884 in qemu_thread_start /work/armbru/qemu/util/qemu-thread-posix.c:519 + #7 0x7fead9be34bf in start_thread (/lib64/libpthread.so.0+0x84bf) + + previously allocated by thread T0 here: + #0 0x7feadd394d18 in __interceptor_malloc (/lib64/libasan.so.5+0x10dd18) + #1 0x7feadcebcc88 in g_malloc (/lib64/libglib-2.0.so.0+0x55c88) + #2 0x560b75c8cf8a in object_new /work/armbru/qemu/qom/object.c:699 + #3 0x560b75010ad9 in qdev_device_add /work/armbru/qemu/qdev-monitor.c:654 + #4 0x560b750120c2 in qmp_device_add /work/armbru/qemu/qdev-monitor.c:805 + #5 0x560b75012c1b in hmp_device_add /work/armbru/qemu/qdev-monitor.c:905 + [...] + ==15654==ABORTING + +Cause: virtio_net_device_realize() neglects to bail out after setting +the error. Fix that. + +Fixes: 9473939ed7addcaaeb8fde5c093918fb7fa0919c +Cc: "Michael S. Tsirkin" +Cc: Jason Wang +Signed-off-by: Markus Armbruster +Reviewed-by: Philippe Mathieu-Daudé +Message-Id: <20200422130719.28225-9-armbru@redhat.com> +Acked-by: Michael S. Tsirkin +--- + hw/net/virtio-net.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c +index eddfa7f923..65bb6886c7 100644 +--- a/hw/net/virtio-net.c ++++ b/hw/net/virtio-net.c +@@ -2947,6 +2947,7 @@ static void virtio_net_device_realize(DeviceState *dev, Error **errp) + n->net_conf.duplex = DUPLEX_FULL; + } else { + error_setg(errp, "'duplex' must be 'half' or 'full'"); ++ return; + } + n->host_features |= (1ULL << VIRTIO_NET_F_SPEED_DUPLEX); + } else { +@@ -2955,7 +2956,9 @@ static void virtio_net_device_realize(DeviceState *dev, Error **errp) + + if (n->net_conf.speed < SPEED_UNKNOWN) { + error_setg(errp, "'speed' must be between 0 and INT_MAX"); +- } else if (n->net_conf.speed >= 0) { ++ return; ++ } ++ if (n->net_conf.speed >= 0) { + n->host_features |= (1ULL << VIRTIO_NET_F_SPEED_DUPLEX); + } + +-- +2.23.0 + diff --git a/virtio-net-fix-rsc_ext-compat-handling.patch b/virtio-net-fix-rsc_ext-compat-handling.patch new file mode 100644 index 0000000000000000000000000000000000000000..fd36068bc5a579cc7ae3d893dc2c3b13660f58a3 --- /dev/null +++ b/virtio-net-fix-rsc_ext-compat-handling.patch @@ -0,0 +1,40 @@ +From 9904adfaca139581d6b03947a7e23c7e2cb64339 Mon Sep 17 00:00:00 2001 +From: Cornelia Huck +Date: Mon, 27 Apr 2020 12:24:13 +0200 +Subject: [PATCH 001/709] virtio-net: fix rsc_ext compat handling + +virtio_net_rsc_ext_num_{packets,dupacks} needs to be available +independently of the presence of VIRTIO_NET_HDR_F_RSC_INFO. + +Fixes: 2974e916df87 ("virtio-net: support RSC v4/v6 tcp traffic for Windows HCK") +Signed-off-by: Cornelia Huck +Message-Id: <20200427102415.10915-2-cohuck@redhat.com> +--- + hw/net/virtio-net.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c +index a46e3b37a7..e85d902588 100644 +--- a/hw/net/virtio-net.c ++++ b/hw/net/virtio-net.c +@@ -83,6 +83,8 @@ + #define VIRTIO_NET_HDR_F_RSC_INFO 4 /* rsc_ext data in csum_ fields */ + #define VIRTIO_NET_F_RSC_EXT 61 + ++#endif ++ + static inline __virtio16 *virtio_net_rsc_ext_num_packets( + struct virtio_net_hdr *hdr) + { +@@ -95,8 +97,6 @@ static inline __virtio16 *virtio_net_rsc_ext_num_dupacks( + return &hdr->csum_offset; + } + +-#endif +- + static VirtIOFeature feature_sizes[] = { + {.flags = 1ULL << VIRTIO_NET_F_MAC, + .end = endof(struct virtio_net_config, mac)}, +-- +2.23.0 + diff --git a/virtio-pci-fix-missing-device-properties.patch b/virtio-pci-fix-missing-device-properties.patch deleted file mode 100644 index 3281d0404913f65bb5d68cb1f74ec021fb11d479..0000000000000000000000000000000000000000 --- a/virtio-pci-fix-missing-device-properties.patch +++ /dev/null @@ -1,101 +0,0 @@ -From b728ea5f2597f97088db8517576caa2877118cb0 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= -Date: Mon, 5 Aug 2019 16:04:40 +0800 -Subject: [PATCH] virtio-pci: fix missing device properties -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Since commit a4ee4c8baa37154 ("virtio: Helper for registering virtio -device types"), virtio-gpu-pci, virtio-vga, and virtio-crypto-pci lost -some properties: "ioeventfd" and "vectors". This may cause various -issues, such as failing migration or invalid properties. - -Since those VirtioPCI devices do not have a base name, their class are -initialized with virtio_pci_generic_base_class_init(). However, if the -VirtioPCIDeviceTypeInfo provided a class_init which sets dc->props, -the properties were overwritten by virtio_pci_generic_class_init(). - -Instead, introduce an intermediary base-type to register the generic -properties. - -Fixes: a4ee4c8baa37154f42b4dc6a13fee79268d15238 -Cc: qemu-stable@nongnu.org -Signed-off-by: Marc-André Lureau -Message-Id: <20190625232333.30752-1-marcandre.lureau@redhat.com> -(cherry-pick from commit 683c1d89efd1eeb111c129a9a91f629b94d90d45) ---- - hw/virtio/virtio-pci.c | 28 ++++++++++++++-------------- - 1 file changed, 14 insertions(+), 14 deletions(-) - -diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c -index cb44e19b..497092e8 100644 ---- a/hw/virtio/virtio-pci.c -+++ b/hw/virtio/virtio-pci.c -@@ -1905,13 +1905,6 @@ static void virtio_pci_generic_class_init(ObjectClass *klass, void *data) - dc->props = virtio_pci_generic_properties; - } - --/* Used when the generic type and the base type is the same */ --static void virtio_pci_generic_base_class_init(ObjectClass *klass, void *data) --{ -- virtio_pci_base_class_init(klass, data); -- virtio_pci_generic_class_init(klass, NULL); --} -- - static void virtio_pci_transitional_instance_init(Object *obj) - { - VirtIOPCIProxy *proxy = VIRTIO_PCI(obj); -@@ -1930,14 +1923,13 @@ static void virtio_pci_non_transitional_instance_init(Object *obj) - - void virtio_pci_types_register(const VirtioPCIDeviceTypeInfo *t) - { -+ char *base_name = NULL; - TypeInfo base_type_info = { - .name = t->base_name, - .parent = t->parent ? t->parent : TYPE_VIRTIO_PCI, - .instance_size = t->instance_size, - .instance_init = t->instance_init, - .class_size = t->class_size, -- .class_init = virtio_pci_base_class_init, -- .class_data = (void *)t, - .abstract = true, - }; - TypeInfo generic_type_info = { -@@ -1953,13 +1945,20 @@ void virtio_pci_types_register(const VirtioPCIDeviceTypeInfo *t) - - if (!base_type_info.name) { - /* No base type -> register a single generic device type */ -- base_type_info.name = t->generic_name; -- base_type_info.class_init = virtio_pci_generic_base_class_init; -- base_type_info.interfaces = generic_type_info.interfaces; -- base_type_info.abstract = false; -- generic_type_info.name = NULL; -+ /* use intermediate %s-base-type to add generic device props */ -+ base_name = g_strdup_printf("%s-base-type", t->generic_name); -+ base_type_info.name = base_name; -+ base_type_info.class_init = virtio_pci_generic_class_init; -+ -+ generic_type_info.parent = base_name; -+ generic_type_info.class_init = virtio_pci_base_class_init; -+ generic_type_info.class_data = (void *)t; -+ - assert(!t->non_transitional_name); - assert(!t->transitional_name); -+ } else { -+ base_type_info.class_init = virtio_pci_base_class_init; -+ base_type_info.class_data = (void *)t; - } - - type_register(&base_type_info); -@@ -1997,6 +1996,7 @@ void virtio_pci_types_register(const VirtioPCIDeviceTypeInfo *t) - }; - type_register(&transitional_type_info); - } -+ g_free(base_name); - } - - /* virtio-pci-bus */ --- -2.19.1 - diff --git a/virtio-pci-update-virtio-pci-bar-layout-documentatio.patch b/virtio-pci-update-virtio-pci-bar-layout-documentatio.patch new file mode 100644 index 0000000000000000000000000000000000000000..1d2ce87e35f50c288b0e3864a4aad2e74c460e3f --- /dev/null +++ b/virtio-pci-update-virtio-pci-bar-layout-documentatio.patch @@ -0,0 +1,32 @@ +From e6779156a44846053f662157a12ed366568c2cff Mon Sep 17 00:00:00 2001 +From: Anthoine Bourgeois +Date: Wed, 22 Apr 2020 23:54:55 +0200 +Subject: [PATCH 213/709] virtio-pci: update virtio pci bar layout + documentation + +The modern io bar was never documented. + +Signed-off-by: Anthoine Bourgeois +Message-Id: <20200422215455.10244-2-anthoine.bourgeois@gmail.com> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +Reviewed-by: Gerd Hoffmann +--- + hw/virtio/virtio-pci.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c +index 4cb784389c..d028c17c24 100644 +--- a/hw/virtio/virtio-pci.c ++++ b/hw/virtio/virtio-pci.c +@@ -1705,6 +1705,7 @@ static void virtio_pci_realize(PCIDevice *pci_dev, Error **errp) + * + * region 0 -- virtio legacy io bar + * region 1 -- msi-x bar ++ * region 2 -- virtio modern io bar (off by default) + * region 4+5 -- virtio modern memory (64bit) bar + * + */ +-- +2.23.0 + diff --git a/virtio-vga-fix-virtio-vga-bar-ordering.patch b/virtio-vga-fix-virtio-vga-bar-ordering.patch new file mode 100644 index 0000000000000000000000000000000000000000..ab2ba7e02671bcf81185d78f1009d1f6d078c974 --- /dev/null +++ b/virtio-vga-fix-virtio-vga-bar-ordering.patch @@ -0,0 +1,38 @@ +From 15138b5e6ff28a8e68a2e1cb6f4ca2fb7e5b057c Mon Sep 17 00:00:00 2001 +From: Anthoine Bourgeois +Date: Wed, 22 Apr 2020 23:54:54 +0200 +Subject: [PATCH 212/709] virtio-vga: fix virtio-vga bar ordering + +With virtio-vga, pci bar are reordered. Bar #2 is used for compatibility +with stdvga. By default, bar #2 is used by virtio modern io bar. +This bar is the last one introduce in the virtio pci bar layout and it's +crushed by the virtio-vga reordering. So virtio-vga and +modern-pio-notify are incompatible because virtio-vga failed to +initialize with this option. + +This fix sets the modern io bar to the bar #5 to avoid conflict. + +Signed-off-by: Anthoine Bourgeois +Message-Id: <20200422215455.10244-1-anthoine.bourgeois@gmail.com> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +Reviewed-by: Gerd Hoffmann +--- + hw/display/virtio-vga.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/hw/display/virtio-vga.c b/hw/display/virtio-vga.c +index 2b4c2aa126..95757a6619 100644 +--- a/hw/display/virtio-vga.c ++++ b/hw/display/virtio-vga.c +@@ -114,6 +114,7 @@ static void virtio_vga_base_realize(VirtIOPCIProxy *vpci_dev, Error **errp) + */ + vpci_dev->modern_mem_bar_idx = 2; + vpci_dev->msix_bar_idx = 4; ++ vpci_dev->modern_io_bar_idx = 5; + + if (!(vpci_dev->flags & VIRTIO_PCI_FLAG_PAGE_PER_VQ)) { + /* +-- +2.23.0 + diff --git a/virtiofsd-Show-submounts.patch b/virtiofsd-Show-submounts.patch new file mode 100644 index 0000000000000000000000000000000000000000..c229087342c6186c70b0d93848e21d50de4d2be3 --- /dev/null +++ b/virtiofsd-Show-submounts.patch @@ -0,0 +1,37 @@ +From ace0829c0d08f0e5f1451e402e94495bc2166772 Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Fri, 24 Apr 2020 15:35:16 +0200 +Subject: [PATCH 142/709] virtiofsd: Show submounts + +Currently, setup_mounts() bind-mounts the shared directory without +MS_REC. This makes all submounts disappear. + +Pass MS_REC so that the guest can see submounts again. + +Fixes: 5baa3b8e95064c2434bd9e2f312edd5e9ae275dc +Signed-off-by: Max Reitz +Message-Id: <20200424133516.73077-1-mreitz@redhat.com> +Reviewed-by: Dr. David Alan Gilbert +Signed-off-by: Dr. David Alan Gilbert + Changed Fixes to point to the commit with the problem rather than + the commit that turned it on +--- + tools/virtiofsd/passthrough_ll.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tools/virtiofsd/passthrough_ll.c b/tools/virtiofsd/passthrough_ll.c +index d7a6474b6e..7873692168 100644 +--- a/tools/virtiofsd/passthrough_ll.c ++++ b/tools/virtiofsd/passthrough_ll.c +@@ -2666,7 +2666,7 @@ static void setup_mounts(const char *source) + int oldroot; + int newroot; + +- if (mount(source, source, NULL, MS_BIND, NULL) < 0) { ++ if (mount(source, source, NULL, MS_BIND | MS_REC, NULL) < 0) { + fuse_log(FUSE_LOG_ERR, "mount(%s, %s, MS_BIND): %m\n", source, source); + exit(1); + } +-- +2.23.0 + diff --git a/virtiofsd-add-rlimit-nofile-NUM-option.patch b/virtiofsd-add-rlimit-nofile-NUM-option.patch new file mode 100644 index 0000000000000000000000000000000000000000..8985006680fd65548d67105eba8a3ac3b55a7d00 --- /dev/null +++ b/virtiofsd-add-rlimit-nofile-NUM-option.patch @@ -0,0 +1,147 @@ +From 6dbb716877728ce4eb51619885ef6ef4ada9565f Mon Sep 17 00:00:00 2001 +From: Stefan Hajnoczi +Date: Fri, 1 May 2020 15:06:43 +0100 +Subject: [PATCH 139/709] virtiofsd: add --rlimit-nofile=NUM option + +Make it possible to specify the RLIMIT_NOFILE on the command-line. +Users running multiple virtiofsd processes should allocate a certain +number to each process so that the system-wide limit can never be +exhausted. + +When this option is set to 0 the rlimit is left at its current value. +This is useful when a management tool wants to configure the rlimit +itself. + +The default behavior remains unchanged: try to set the limit to +1,000,000 file descriptors if the current rlimit is lower. + +Signed-off-by: Stefan Hajnoczi +Reviewed-by: Dr. David Alan Gilbert +Message-Id: <20200501140644.220940-2-stefanha@redhat.com> +Signed-off-by: Dr. David Alan Gilbert +--- + tools/virtiofsd/fuse_lowlevel.h | 1 + + tools/virtiofsd/helper.c | 23 +++++++++++++++++++++++ + tools/virtiofsd/passthrough_ll.c | 22 ++++++++-------------- + 3 files changed, 32 insertions(+), 14 deletions(-) + +diff --git a/tools/virtiofsd/fuse_lowlevel.h b/tools/virtiofsd/fuse_lowlevel.h +index 8f6d705b5c..562fd5241e 100644 +--- a/tools/virtiofsd/fuse_lowlevel.h ++++ b/tools/virtiofsd/fuse_lowlevel.h +@@ -1777,6 +1777,7 @@ struct fuse_cmdline_opts { + int syslog; + int log_level; + unsigned int max_idle_threads; ++ unsigned long rlimit_nofile; + }; + + /** +diff --git a/tools/virtiofsd/helper.c b/tools/virtiofsd/helper.c +index 819c2bc13c..dc59f38af0 100644 +--- a/tools/virtiofsd/helper.c ++++ b/tools/virtiofsd/helper.c +@@ -23,6 +23,8 @@ + #include + #include + #include ++#include ++#include + #include + + #define FUSE_HELPER_OPT(t, p) \ +@@ -53,6 +55,7 @@ static const struct fuse_opt fuse_helper_opts[] = { + FUSE_HELPER_OPT("subtype=", nodefault_subtype), + FUSE_OPT_KEY("subtype=", FUSE_OPT_KEY_KEEP), + FUSE_HELPER_OPT("max_idle_threads=%u", max_idle_threads), ++ FUSE_HELPER_OPT("--rlimit-nofile=%lu", rlimit_nofile), + FUSE_HELPER_OPT("--syslog", syslog), + FUSE_HELPER_OPT_VALUE("log_level=debug", log_level, FUSE_LOG_DEBUG), + FUSE_HELPER_OPT_VALUE("log_level=info", log_level, FUSE_LOG_INFO), +@@ -171,6 +174,9 @@ void fuse_cmdline_help(void) + " default: no_writeback\n" + " -o xattr|no_xattr enable/disable xattr\n" + " default: no_xattr\n" ++ " --rlimit-nofile= set maximum number of file descriptors\n" ++ " (0 leaves rlimit unchanged)\n" ++ " default: 1,000,000 if the current rlimit is lower\n" + ); + } + +@@ -191,11 +197,28 @@ static int fuse_helper_opt_proc(void *data, const char *arg, int key, + } + } + ++static unsigned long get_default_rlimit_nofile(void) ++{ ++ rlim_t max_fds = 1000000; /* our default RLIMIT_NOFILE target */ ++ struct rlimit rlim; ++ ++ if (getrlimit(RLIMIT_NOFILE, &rlim) < 0) { ++ fuse_log(FUSE_LOG_ERR, "getrlimit(RLIMIT_NOFILE): %m\n"); ++ exit(1); ++ } ++ ++ if (rlim.rlim_cur >= max_fds) { ++ return 0; /* we have more fds available than required! */ ++ } ++ return max_fds; ++} ++ + int fuse_parse_cmdline(struct fuse_args *args, struct fuse_cmdline_opts *opts) + { + memset(opts, 0, sizeof(struct fuse_cmdline_opts)); + + opts->max_idle_threads = 10; ++ opts->rlimit_nofile = get_default_rlimit_nofile(); + opts->foreground = 1; + + if (fuse_opt_parse(args, opts, fuse_helper_opts, fuse_helper_opt_proc) == +diff --git a/tools/virtiofsd/passthrough_ll.c b/tools/virtiofsd/passthrough_ll.c +index 4c35c95b25..f7b9c1d20c 100644 +--- a/tools/virtiofsd/passthrough_ll.c ++++ b/tools/virtiofsd/passthrough_ll.c +@@ -2707,24 +2707,18 @@ static void setup_sandbox(struct lo_data *lo, struct fuse_session *se, + setup_seccomp(enable_syslog); + } + +-/* Raise the maximum number of open file descriptors */ +-static void setup_nofile_rlimit(void) ++/* Set the maximum number of open file descriptors */ ++static void setup_nofile_rlimit(unsigned long rlimit_nofile) + { +- const rlim_t max_fds = 1000000; +- struct rlimit rlim; +- +- if (getrlimit(RLIMIT_NOFILE, &rlim) < 0) { +- fuse_log(FUSE_LOG_ERR, "getrlimit(RLIMIT_NOFILE): %m\n"); +- exit(1); +- } ++ struct rlimit rlim = { ++ .rlim_cur = rlimit_nofile, ++ .rlim_max = rlimit_nofile, ++ }; + +- if (rlim.rlim_cur >= max_fds) { ++ if (rlimit_nofile == 0) { + return; /* nothing to do */ + } + +- rlim.rlim_cur = max_fds; +- rlim.rlim_max = max_fds; +- + if (setrlimit(RLIMIT_NOFILE, &rlim) < 0) { + /* Ignore SELinux denials */ + if (errno == EPERM) { +@@ -2977,7 +2971,7 @@ int main(int argc, char *argv[]) + + fuse_daemonize(opts.foreground); + +- setup_nofile_rlimit(); ++ setup_nofile_rlimit(opts.rlimit_nofile); + + /* Must be before sandbox since it wants /proc */ + setup_capng(); +-- +2.23.0 + diff --git a/virtiofsd-drop-all-capabilities-in-the-wait-parent-p.patch b/virtiofsd-drop-all-capabilities-in-the-wait-parent-p.patch new file mode 100644 index 0000000000000000000000000000000000000000..de51bd7e54c9e1c4abe440ee378e876f0ddad418 --- /dev/null +++ b/virtiofsd-drop-all-capabilities-in-the-wait-parent-p.patch @@ -0,0 +1,53 @@ +From 66502bbca37ca7a3bfa57e82cfc03b89a7a11eae Mon Sep 17 00:00:00 2001 +From: Stefan Hajnoczi +Date: Thu, 16 Apr 2020 17:49:07 +0100 +Subject: [PATCH 144/709] virtiofsd: drop all capabilities in the wait parent + process +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +All this process does is wait for its child. No capabilities are +needed. + +Signed-off-by: Stefan Hajnoczi +Reviewed-by: Philippe Mathieu-Daudé +Signed-off-by: Dr. David Alan Gilbert +--- + tools/virtiofsd/passthrough_ll.c | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +diff --git a/tools/virtiofsd/passthrough_ll.c b/tools/virtiofsd/passthrough_ll.c +index e49650b63d..3ba1d90984 100644 +--- a/tools/virtiofsd/passthrough_ll.c ++++ b/tools/virtiofsd/passthrough_ll.c +@@ -2530,6 +2530,17 @@ static void print_capabilities(void) + printf("}\n"); + } + ++/* ++ * Drop all Linux capabilities because the wait parent process only needs to ++ * sit in waitpid(2) and terminate. ++ */ ++static void setup_wait_parent_capabilities(void) ++{ ++ capng_setpid(syscall(SYS_gettid)); ++ capng_clear(CAPNG_SELECT_BOTH); ++ capng_apply(CAPNG_SELECT_BOTH); ++} ++ + /* + * Move to a new mount, net, and pid namespaces to isolate this process. + */ +@@ -2563,6 +2574,8 @@ static void setup_namespaces(struct lo_data *lo, struct fuse_session *se) + pid_t waited; + int wstatus; + ++ setup_wait_parent_capabilities(); ++ + /* The parent waits for the child */ + do { + waited = waitpid(child, &wstatus, 0); +-- +2.23.0 + diff --git a/virtiofsd-jail-lo-proc_self_fd.patch b/virtiofsd-jail-lo-proc_self_fd.patch new file mode 100644 index 0000000000000000000000000000000000000000..e3258d705a891295db1e98bf42c9b567b5c58e3d --- /dev/null +++ b/virtiofsd-jail-lo-proc_self_fd.patch @@ -0,0 +1,72 @@ +From 397ae982f4df46e7d4b2625c431062c9146f3b83 Mon Sep 17 00:00:00 2001 +From: Miklos Szeredi +Date: Wed, 29 Apr 2020 14:47:33 +0200 +Subject: [PATCH 141/709] virtiofsd: jail lo->proc_self_fd + +While it's not possible to escape the proc filesystem through +lo->proc_self_fd, it is possible to escape to the root of the proc +filesystem itself through "../..". + +Use a temporary mount for opening lo->proc_self_fd, that has it's root at +/proc/self/fd/, preventing access to the ancestor directories. + +Signed-off-by: Miklos Szeredi +Message-Id: <20200429124733.22488-1-mszeredi@redhat.com> +Reviewed-by: Stefan Hajnoczi +Signed-off-by: Dr. David Alan Gilbert +--- + tools/virtiofsd/passthrough_ll.c | 27 +++++++++++++++++++++++++-- + 1 file changed, 25 insertions(+), 2 deletions(-) + +diff --git a/tools/virtiofsd/passthrough_ll.c b/tools/virtiofsd/passthrough_ll.c +index f7b9c1d20c..d7a6474b6e 100644 +--- a/tools/virtiofsd/passthrough_ll.c ++++ b/tools/virtiofsd/passthrough_ll.c +@@ -2536,6 +2536,8 @@ static void print_capabilities(void) + static void setup_namespaces(struct lo_data *lo, struct fuse_session *se) + { + pid_t child; ++ char template[] = "virtiofsd-XXXXXX"; ++ char *tmpdir; + + /* + * Create a new pid namespace for *child* processes. We'll have to +@@ -2597,12 +2599,33 @@ static void setup_namespaces(struct lo_data *lo, struct fuse_session *se) + exit(1); + } + ++ tmpdir = mkdtemp(template); ++ if (!tmpdir) { ++ fuse_log(FUSE_LOG_ERR, "tmpdir(%s): %m\n", template); ++ exit(1); ++ } ++ ++ if (mount("/proc/self/fd", tmpdir, NULL, MS_BIND, NULL) < 0) { ++ fuse_log(FUSE_LOG_ERR, "mount(/proc/self/fd, %s, MS_BIND): %m\n", ++ tmpdir); ++ exit(1); ++ } ++ + /* Now we can get our /proc/self/fd directory file descriptor */ +- lo->proc_self_fd = open("/proc/self/fd", O_PATH); ++ lo->proc_self_fd = open(tmpdir, O_PATH); + if (lo->proc_self_fd == -1) { +- fuse_log(FUSE_LOG_ERR, "open(/proc/self/fd, O_PATH): %m\n"); ++ fuse_log(FUSE_LOG_ERR, "open(%s, O_PATH): %m\n", tmpdir); + exit(1); + } ++ ++ if (umount2(tmpdir, MNT_DETACH) < 0) { ++ fuse_log(FUSE_LOG_ERR, "umount2(%s, MNT_DETACH): %m\n", tmpdir); ++ exit(1); ++ } ++ ++ if (rmdir(tmpdir) < 0) { ++ fuse_log(FUSE_LOG_ERR, "rmdir(%s): %m\n", tmpdir); ++ } + } + + /* +-- +2.23.0 + diff --git a/virtiofsd-only-retain-file-system-capabilities.patch b/virtiofsd-only-retain-file-system-capabilities.patch new file mode 100644 index 0000000000000000000000000000000000000000..1373ba99dacaca4b442e3cc4dcd95992e34ca6be --- /dev/null +++ b/virtiofsd-only-retain-file-system-capabilities.patch @@ -0,0 +1,99 @@ +From a59feb483b8fae24d043569ccfcc97ea23d54a02 Mon Sep 17 00:00:00 2001 +From: Stefan Hajnoczi +Date: Thu, 16 Apr 2020 17:49:06 +0100 +Subject: [PATCH 143/709] virtiofsd: only retain file system capabilities + +virtiofsd runs as root but only needs a subset of root's Linux +capabilities(7). As a file server its purpose is to create and access +files on behalf of a client. It needs to be able to access files with +arbitrary uid/gid owners. It also needs to be create device nodes. + +Introduce a Linux capabilities(7) whitelist and drop all capabilities +that we don't need, making the virtiofsd process less powerful than a +regular uid root process. + + # cat /proc/PID/status + ... + Before After + CapInh: 0000000000000000 0000000000000000 + CapPrm: 0000003fffffffff 00000000880000df + CapEff: 0000003fffffffff 00000000880000df + CapBnd: 0000003fffffffff 0000000000000000 + CapAmb: 0000000000000000 0000000000000000 + +Note that file capabilities cannot be used to achieve the same effect on +the virtiofsd executable because mount is used during sandbox setup. +Therefore we drop capabilities programmatically at the right point +during startup. + +This patch only affects the sandboxed child process. The parent process +that sits in waitpid(2) still has full root capabilities and will be +addressed in the next patch. + +Signed-off-by: Stefan Hajnoczi +Message-Id: <20200416164907.244868-2-stefanha@redhat.com> +Reviewed-by: Dr. David Alan Gilbert +Signed-off-by: Dr. David Alan Gilbert +--- + tools/virtiofsd/passthrough_ll.c | 38 ++++++++++++++++++++++++++++++++ + 1 file changed, 38 insertions(+) + +diff --git a/tools/virtiofsd/passthrough_ll.c b/tools/virtiofsd/passthrough_ll.c +index 7873692168..e49650b63d 100644 +--- a/tools/virtiofsd/passthrough_ll.c ++++ b/tools/virtiofsd/passthrough_ll.c +@@ -2718,6 +2718,43 @@ static void setup_mounts(const char *source) + close(oldroot); + } + ++/* ++ * Only keep whitelisted capabilities that are needed for file system operation ++ */ ++static void setup_capabilities(void) ++{ ++ pthread_mutex_lock(&cap.mutex); ++ capng_restore_state(&cap.saved); ++ ++ /* ++ * Whitelist file system-related capabilities that are needed for a file ++ * server to act like root. Drop everything else like networking and ++ * sysadmin capabilities. ++ * ++ * Exclusions: ++ * 1. CAP_LINUX_IMMUTABLE is not included because it's only used via ioctl ++ * and we don't support that. ++ * 2. CAP_MAC_OVERRIDE is not included because it only seems to be ++ * used by the Smack LSM. Omit it until there is demand for it. ++ */ ++ capng_setpid(syscall(SYS_gettid)); ++ capng_clear(CAPNG_SELECT_BOTH); ++ capng_updatev(CAPNG_ADD, CAPNG_PERMITTED | CAPNG_EFFECTIVE, ++ CAP_CHOWN, ++ CAP_DAC_OVERRIDE, ++ CAP_DAC_READ_SEARCH, ++ CAP_FOWNER, ++ CAP_FSETID, ++ CAP_SETGID, ++ CAP_SETUID, ++ CAP_MKNOD, ++ CAP_SETFCAP); ++ capng_apply(CAPNG_SELECT_BOTH); ++ ++ cap.saved = capng_save_state(); ++ pthread_mutex_unlock(&cap.mutex); ++} ++ + /* + * Lock down this process to prevent access to other processes or files outside + * source directory. This reduces the impact of arbitrary code execution bugs. +@@ -2728,6 +2765,7 @@ static void setup_sandbox(struct lo_data *lo, struct fuse_session *se, + setup_namespaces(lo, se); + setup_mounts(lo->source); + setup_seccomp(enable_syslog); ++ setup_capabilities(); + } + + /* Set the maximum number of open file descriptors */ +-- +2.23.0 + diff --git a/virtiofsd-stay-below-fs.file-max-sysctl-value-CVE-20.patch b/virtiofsd-stay-below-fs.file-max-sysctl-value-CVE-20.patch new file mode 100644 index 0000000000000000000000000000000000000000..b1b15e5a634d1d792e8591056baf55b5d15c4bb5 --- /dev/null +++ b/virtiofsd-stay-below-fs.file-max-sysctl-value-CVE-20.patch @@ -0,0 +1,75 @@ +From 8c1d353d107b4fc344e27f2f08ea7fa25de2eea2 Mon Sep 17 00:00:00 2001 +From: Stefan Hajnoczi +Date: Fri, 1 May 2020 15:06:44 +0100 +Subject: [PATCH 140/709] virtiofsd: stay below fs.file-max sysctl value + (CVE-2020-10717) + +The system-wide fs.file-max sysctl value determines how many files can +be open. It defaults to a value calculated based on the machine's RAM +size. Previously virtiofsd would try to set RLIMIT_NOFILE to 1,000,000 +and this allowed the FUSE client to exhaust the number of open files +system-wide on Linux hosts with less than 10 GB of RAM! + +Take fs.file-max into account when choosing the default RLIMIT_NOFILE +value. + +Fixes: CVE-2020-10717 +Reported-by: Yuval Avrahami +Signed-off-by: Stefan Hajnoczi +Reviewed-by: Dr. David Alan Gilbert +Message-Id: <20200501140644.220940-3-stefanha@redhat.com> +Signed-off-by: Dr. David Alan Gilbert +--- + tools/virtiofsd/helper.c | 26 +++++++++++++++++++++++++- + 1 file changed, 25 insertions(+), 1 deletion(-) + +diff --git a/tools/virtiofsd/helper.c b/tools/virtiofsd/helper.c +index dc59f38af0..00a1ef666a 100644 +--- a/tools/virtiofsd/helper.c ++++ b/tools/virtiofsd/helper.c +@@ -176,7 +176,8 @@ void fuse_cmdline_help(void) + " default: no_xattr\n" + " --rlimit-nofile= set maximum number of file descriptors\n" + " (0 leaves rlimit unchanged)\n" +- " default: 1,000,000 if the current rlimit is lower\n" ++ " default: min(1000000, fs.file-max - 16384)\n" ++ " if the current rlimit is lower\n" + ); + } + +@@ -199,9 +200,32 @@ static int fuse_helper_opt_proc(void *data, const char *arg, int key, + + static unsigned long get_default_rlimit_nofile(void) + { ++ g_autofree gchar *file_max_str = NULL; ++ const rlim_t reserved_fds = 16384; /* leave at least this many fds free */ + rlim_t max_fds = 1000000; /* our default RLIMIT_NOFILE target */ ++ rlim_t file_max; + struct rlimit rlim; + ++ /* ++ * Reduce max_fds below the system-wide maximum, if necessary. This ++ * ensures there are fds available for other processes so we don't ++ * cause resource exhaustion. ++ */ ++ if (!g_file_get_contents("/proc/sys/fs/file-max", &file_max_str, ++ NULL, NULL)) { ++ fuse_log(FUSE_LOG_ERR, "can't read /proc/sys/fs/file-max\n"); ++ exit(1); ++ } ++ file_max = g_ascii_strtoull(file_max_str, NULL, 10); ++ if (file_max < 2 * reserved_fds) { ++ fuse_log(FUSE_LOG_ERR, ++ "The fs.file-max sysctl is too low (%lu) to allow a " ++ "reasonable number of open files.\n", ++ (unsigned long)file_max); ++ exit(1); ++ } ++ max_fds = MIN(file_max - reserved_fds, max_fds); ++ + if (getrlimit(RLIMIT_NOFILE, &rlim) < 0) { + fuse_log(FUSE_LOG_ERR, "getrlimit(RLIMIT_NOFILE): %m\n"); + exit(1); +-- +2.23.0 + diff --git a/vl-Fix-drive-blockdev-persistent-reservation-management.patch b/vl-Fix-drive-blockdev-persistent-reservation-management.patch deleted file mode 100644 index d05c3001b5135816bcafd86f2fb650555afee655..0000000000000000000000000000000000000000 --- a/vl-Fix-drive-blockdev-persistent-reservation-management.patch +++ /dev/null @@ -1,55 +0,0 @@ -From 9ea18ed25a36527167e9676f25d983df5e7f76e6 Mon Sep 17 00:00:00 2001 -From: Markus Armbruster -Date: Tue, 4 Jun 2019 17:12:50 +0200 -Subject: [PATCH] vl: Fix -drive / -blockdev persistent reservation management - -qemu-system-FOO's main() acts on command line arguments in its own -idiosyncratic order. There's not much method to its madness. -Whenever we find a case where one kind of command line argument needs -to refer to something created for another kind later, we rejigger the -order. - -Recent commit cda4aa9a5a "vl: Create block backends before setting -machine properties" was such a rejigger. Block backends are now -created before "delayed" objects. This broke persistent reservation -management. Reproducer: - - $ qemu-system-x86_64 -object pr-manager-helper,id=pr-helper0,path=/tmp/pr-helper0.sock-drive -drive file=/dev/mapper/crypt,file.pr-manager=pr-helper0,format=raw,if=none,id=drive-scsi0-0-0-2 - qemu-system-x86_64: -drive file=/dev/mapper/crypt,file.pr-manager=pr-helper0,format=raw,if=none,id=drive-scsi0-0-0-2: No persistent reservation manager with id 'pr-helper0' - -The delayed pr-manager-helper object is created too late for use by --drive or -blockdev. Normal objects are still created in time. - -pr-manager-helper has always been a delayed object (commit 7c9e527659 -"scsi, file-posix: add support for persistent reservation -management"). Turns out there's no real reason for that. Make it a -normal object. - -Fixes: cda4aa9a5a08777cf13e164c0543bd4888b8adce -Signed-off-by: Markus Armbruster -Message-Id: <20190604151251.9903-2-armbru@redhat.com> -Reviewed-by: Michal Privoznik -Cc: qemu-stable@nongnu.org -Signed-off-by: Paolo Bonzini -(cherry-picked from commit 9ea18ed25a36527167e9676f25d983df5e7f76e6) ---- - vl.c | 3 +-- - 1 file changed, 1 insertion(+), 2 deletions(-) - -diff --git a/vl.c b/vl.c -index f023a8ca73..cc6246d2af 100644 ---- a/vl.c -+++ b/vl.c -@@ -2751,8 +2751,7 @@ static bool object_create_initial(const char *type, QemuOpts *opts) - exit(0); - } - -- if (g_str_equal(type, "rng-egd") || -- g_str_has_prefix(type, "pr-manager-")) { -+ if (g_str_equal(type, "rng-egd")) { - return false; - } - --- -2.19.1 - diff --git a/vmdk-Don-t-update-L2-table-for-zero-write-on-zero-cl.patch b/vmdk-Don-t-update-L2-table-for-zero-write-on-zero-cl.patch new file mode 100644 index 0000000000000000000000000000000000000000..09468c98aa788c1170856ea16856fbd4e2be4550 --- /dev/null +++ b/vmdk-Don-t-update-L2-table-for-zero-write-on-zero-cl.patch @@ -0,0 +1,33 @@ +From 78cae78dbcf94a151203ab5c6e418d9d9094a59e Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Thu, 30 Apr 2020 15:30:05 +0200 +Subject: [PATCH 340/709] vmdk: Don't update L2 table for zero write on zero + cluster + +If a cluster is already zeroed, we don't have to call vmdk_L2update(), +which is rather slow because it flushes the image file. + +Signed-off-by: Kevin Wolf +Message-Id: <20200430133007.170335-5-kwolf@redhat.com> +Reviewed-by: Eric Blake +Signed-off-by: Kevin Wolf +--- + block/vmdk.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/block/vmdk.c b/block/vmdk.c +index ab8eec1f27..2880d88dea 100644 +--- a/block/vmdk.c ++++ b/block/vmdk.c +@@ -2013,7 +2013,7 @@ static int vmdk_pwritev(BlockDriverState *bs, uint64_t offset, + offset_in_cluster == 0 && + n_bytes >= extent->cluster_sectors * BDRV_SECTOR_SIZE) { + n_bytes = extent->cluster_sectors * BDRV_SECTOR_SIZE; +- if (!zero_dry_run) { ++ if (!zero_dry_run && ret != VMDK_ZEROED) { + /* update L2 tables */ + if (vmdk_L2update(extent, &m_data, VMDK_GTE_ZEROED) + != VMDK_OK) { +-- +2.23.0 + diff --git a/vmdk-Fix-partial-overwrite-of-zero-cluster.patch b/vmdk-Fix-partial-overwrite-of-zero-cluster.patch new file mode 100644 index 0000000000000000000000000000000000000000..d0da1e75f5df7238fbdaad1ad789561599a100b6 --- /dev/null +++ b/vmdk-Fix-partial-overwrite-of-zero-cluster.patch @@ -0,0 +1,86 @@ +From 4823cde58eb507fcdcc0225b087343439a6cb43c Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Thu, 30 Apr 2020 15:30:04 +0200 +Subject: [PATCH 339/709] vmdk: Fix partial overwrite of zero cluster + +When overwriting a zero cluster, we must not perform copy-on-write from +the backing file, but from a zeroed buffer. + +Signed-off-by: Kevin Wolf +Message-Id: <20200430133007.170335-4-kwolf@redhat.com> +Reviewed-by: Eric Blake +Signed-off-by: Kevin Wolf +--- + block/vmdk.c | 18 ++++++++++++------ + 1 file changed, 12 insertions(+), 6 deletions(-) + +diff --git a/block/vmdk.c b/block/vmdk.c +index fcd6b38d64..ab8eec1f27 100644 +--- a/block/vmdk.c ++++ b/block/vmdk.c +@@ -1340,7 +1340,9 @@ static void vmdk_refresh_limits(BlockDriverState *bs, Error **errp) + * get_whole_cluster + * + * Copy backing file's cluster that covers @sector_num, otherwise write zero, +- * to the cluster at @cluster_sector_num. ++ * to the cluster at @cluster_sector_num. If @zeroed is true, we're overwriting ++ * a zeroed cluster in the current layer and must not copy data from the ++ * backing file. + * + * If @skip_start_sector < @skip_end_sector, the relative range + * [@skip_start_sector, @skip_end_sector) is not copied or written, and leave +@@ -1351,18 +1353,21 @@ static int get_whole_cluster(BlockDriverState *bs, + uint64_t cluster_offset, + uint64_t offset, + uint64_t skip_start_bytes, +- uint64_t skip_end_bytes) ++ uint64_t skip_end_bytes, ++ bool zeroed) + { + int ret = VMDK_OK; + int64_t cluster_bytes; + uint8_t *whole_grain; ++ bool copy_from_backing; + + /* For COW, align request sector_num to cluster start */ + cluster_bytes = extent->cluster_sectors << BDRV_SECTOR_BITS; + offset = QEMU_ALIGN_DOWN(offset, cluster_bytes); + whole_grain = qemu_blockalign(bs, cluster_bytes); ++ copy_from_backing = bs->backing && !zeroed; + +- if (!bs->backing) { ++ if (!copy_from_backing) { + memset(whole_grain, 0, skip_start_bytes); + memset(whole_grain + skip_end_bytes, 0, cluster_bytes - skip_end_bytes); + } +@@ -1377,7 +1382,7 @@ static int get_whole_cluster(BlockDriverState *bs, + + /* Read backing data before skip range */ + if (skip_start_bytes > 0) { +- if (bs->backing) { ++ if (copy_from_backing) { + /* qcow2 emits this on bs->file instead of bs->backing */ + BLKDBG_EVENT(extent->file, BLKDBG_COW_READ); + ret = bdrv_pread(bs->backing, offset, whole_grain, +@@ -1397,7 +1402,7 @@ static int get_whole_cluster(BlockDriverState *bs, + } + /* Read backing data after skip range */ + if (skip_end_bytes < cluster_bytes) { +- if (bs->backing) { ++ if (copy_from_backing) { + /* qcow2 emits this on bs->file instead of bs->backing */ + BLKDBG_EVENT(extent->file, BLKDBG_COW_READ); + ret = bdrv_pread(bs->backing, offset + skip_end_bytes, +@@ -1631,7 +1636,8 @@ static int get_cluster_offset(BlockDriverState *bs, + * or inappropriate VM shutdown. + */ + ret = get_whole_cluster(bs, extent, cluster_sector * BDRV_SECTOR_SIZE, +- offset, skip_start_bytes, skip_end_bytes); ++ offset, skip_start_bytes, skip_end_bytes, ++ zeroed); + if (ret) { + return ret; + } +-- +2.23.0 + diff --git a/vmdk-Fix-zero-cluster-allocation.patch b/vmdk-Fix-zero-cluster-allocation.patch new file mode 100644 index 0000000000000000000000000000000000000000..65624d21df9c991162adaaea5e8ab47f477d5251 --- /dev/null +++ b/vmdk-Fix-zero-cluster-allocation.patch @@ -0,0 +1,61 @@ +From 2821c1cc0f8cbfcc332387e83be746af6f27cb4f Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Thu, 30 Apr 2020 15:30:03 +0200 +Subject: [PATCH 338/709] vmdk: Fix zero cluster allocation + +m_data must contain valid data even for zero clusters when no cluster +was allocated in the image file. Without this, zero writes segfault with +images that have zeroed_grain=on. + +For zero writes, we don't want to allocate a cluster in the image file +even in compressed files. + +Fixes: 524089bce43fd1cd3daaca979872451efa2cf7c6 +Signed-off-by: Kevin Wolf +Message-Id: <20200430133007.170335-3-kwolf@redhat.com> +Reviewed-by: Eric Blake +Signed-off-by: Kevin Wolf +--- + block/vmdk.c | 12 +++++++----- + 1 file changed, 7 insertions(+), 5 deletions(-) + +diff --git a/block/vmdk.c b/block/vmdk.c +index ecfb4a86d2..fcd6b38d64 100644 +--- a/block/vmdk.c ++++ b/block/vmdk.c +@@ -1572,6 +1572,12 @@ static int get_cluster_offset(BlockDriverState *bs, + extent->l2_cache_counts[min_index] = 1; + found: + l2_index = ((offset >> 9) / extent->cluster_sectors) % extent->l2_size; ++ if (m_data) { ++ m_data->l1_index = l1_index; ++ m_data->l2_index = l2_index; ++ m_data->l2_offset = l2_offset; ++ m_data->l2_cache_entry = ((uint32_t *)l2_table) + l2_index; ++ } + + if (extent->sesparse) { + cluster_sector = le64_to_cpu(((uint64_t *)l2_table)[l2_index]); +@@ -1631,10 +1637,6 @@ static int get_cluster_offset(BlockDriverState *bs, + } + if (m_data) { + m_data->new_allocation = true; +- m_data->l1_index = l1_index; +- m_data->l2_index = l2_index; +- m_data->l2_offset = l2_offset; +- m_data->l2_cache_entry = ((uint32_t *)l2_table) + l2_index; + } + } + *cluster_offset = cluster_sector << BDRV_SECTOR_BITS; +@@ -1990,7 +1992,7 @@ static int vmdk_pwritev(BlockDriverState *bs, uint64_t offset, + error_report("Could not write to allocated cluster" + " for streamOptimized"); + return -EIO; +- } else { ++ } else if (!zeroed) { + /* allocate */ + ret = get_cluster_offset(bs, extent, &m_data, offset, + true, &cluster_offset, 0, 0); +-- +2.23.0 + diff --git a/vmdk-Flush-only-once-in-vmdk_L2update.patch b/vmdk-Flush-only-once-in-vmdk_L2update.patch new file mode 100644 index 0000000000000000000000000000000000000000..2a98a26d3d9f59e90641e166142f8a753008ef1b --- /dev/null +++ b/vmdk-Flush-only-once-in-vmdk_L2update.patch @@ -0,0 +1,51 @@ +From 2758be056ba814cd5a878b71c231af79a863b058 Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Thu, 30 Apr 2020 15:30:06 +0200 +Subject: [PATCH 341/709] vmdk: Flush only once in vmdk_L2update() + +If we have a backup L2 table, we currently flush once after writing to +the active L2 table and again after writing to the backup table. A +single flush is enough and makes things a little less slow. + +Signed-off-by: Kevin Wolf +Message-Id: <20200430133007.170335-6-kwolf@redhat.com> +Reviewed-by: Eric Blake +Signed-off-by: Kevin Wolf +--- + block/vmdk.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/block/vmdk.c b/block/vmdk.c +index 2880d88dea..b18f128816 100644 +--- a/block/vmdk.c ++++ b/block/vmdk.c +@@ -1435,7 +1435,7 @@ static int vmdk_L2update(VmdkExtent *extent, VmdkMetaData *m_data, + offset = cpu_to_le32(offset); + /* update L2 table */ + BLKDBG_EVENT(extent->file, BLKDBG_L2_UPDATE); +- if (bdrv_pwrite_sync(extent->file, ++ if (bdrv_pwrite(extent->file, + ((int64_t)m_data->l2_offset * 512) + + (m_data->l2_index * sizeof(offset)), + &offset, sizeof(offset)) < 0) { +@@ -1444,13 +1444,16 @@ static int vmdk_L2update(VmdkExtent *extent, VmdkMetaData *m_data, + /* update backup L2 table */ + if (extent->l1_backup_table_offset != 0) { + m_data->l2_offset = extent->l1_backup_table[m_data->l1_index]; +- if (bdrv_pwrite_sync(extent->file, ++ if (bdrv_pwrite(extent->file, + ((int64_t)m_data->l2_offset * 512) + + (m_data->l2_index * sizeof(offset)), + &offset, sizeof(offset)) < 0) { + return VMDK_ERROR; + } + } ++ if (bdrv_flush(extent->file->bs) < 0) { ++ return VMDK_ERROR; ++ } + if (m_data->l2_cache_entry) { + *m_data->l2_cache_entry = offset; + } +-- +2.23.0 + diff --git a/vmdk-Rename-VmdkMetaData.valid-to-new_allocation.patch b/vmdk-Rename-VmdkMetaData.valid-to-new_allocation.patch new file mode 100644 index 0000000000000000000000000000000000000000..b0bfda45da3a32400766556d4fd8b296d8f5107a --- /dev/null +++ b/vmdk-Rename-VmdkMetaData.valid-to-new_allocation.patch @@ -0,0 +1,62 @@ +From 4dc20e6465eccd2466a449d3fb49539f5d9f53dd Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Thu, 30 Apr 2020 15:30:02 +0200 +Subject: [PATCH 337/709] vmdk: Rename VmdkMetaData.valid to new_allocation + +m_data is used for zero clusters even though valid == 0. It really only +means that a new cluster was allocated in the image file. Rename it to +reflect this. + +While at it, change it from int to bool, too. + +Signed-off-by: Kevin Wolf +Message-Id: <20200430133007.170335-2-kwolf@redhat.com> +Reviewed-by: Eric Blake +Signed-off-by: Kevin Wolf +--- + block/vmdk.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/block/vmdk.c b/block/vmdk.c +index b02fdd14b2..ecfb4a86d2 100644 +--- a/block/vmdk.c ++++ b/block/vmdk.c +@@ -180,7 +180,7 @@ typedef struct VmdkMetaData { + unsigned int l1_index; + unsigned int l2_index; + unsigned int l2_offset; +- int valid; ++ bool new_allocation; + uint32_t *l2_cache_entry; + } VmdkMetaData; + +@@ -1492,7 +1492,7 @@ static int get_cluster_offset(BlockDriverState *bs, + unsigned int l2_size_bytes = extent->l2_size * extent->entry_size; + + if (m_data) { +- m_data->valid = 0; ++ m_data->new_allocation = false; + } + if (extent->flat) { + *cluster_offset = extent->flat_start_offset; +@@ -1630,7 +1630,7 @@ static int get_cluster_offset(BlockDriverState *bs, + return ret; + } + if (m_data) { +- m_data->valid = 1; ++ m_data->new_allocation = true; + m_data->l1_index = l1_index; + m_data->l2_index = l2_index; + m_data->l2_offset = l2_offset; +@@ -2021,7 +2021,7 @@ static int vmdk_pwritev(BlockDriverState *bs, uint64_t offset, + if (ret) { + return ret; + } +- if (m_data.valid) { ++ if (m_data.new_allocation) { + /* update L2 tables */ + if (vmdk_L2update(extent, &m_data, + cluster_offset >> BDRV_SECTOR_BITS) +-- +2.23.0 + diff --git a/vnc-fix-memory-leak-when-vnc-disconnect.patch b/vnc-fix-memory-leak-when-vnc-disconnect.patch deleted file mode 100644 index 3eddde4aafc1a213623db042b0cc94a7942e9574..0000000000000000000000000000000000000000 --- a/vnc-fix-memory-leak-when-vnc-disconnect.patch +++ /dev/null @@ -1,1014 +0,0 @@ -From 6bf21f3d83e95bcc4ba35a7a07cc6655e8b010b0 Mon Sep 17 00:00:00 2001 -From: Li Qiang -Date: Sat, 31 Aug 2019 08:39:22 -0700 -Subject: [PATCH] vnc: fix memory leak when vnc disconnect - -Currently when qemu receives a vnc connect, it creates a 'VncState' to -represent this connection. In 'vnc_worker_thread_loop' it creates a -local 'VncState'. The connection 'VcnState' and local 'VncState' exchange -data in 'vnc_async_encoding_start' and 'vnc_async_encoding_end'. -In 'zrle_compress_data' it calls 'deflateInit2' to allocate the libz library -opaque data. The 'VncState' used in 'zrle_compress_data' is the local -'VncState'. In 'vnc_zrle_clear' it calls 'deflateEnd' to free the libz -library opaque data. The 'VncState' used in 'vnc_zrle_clear' is the connection -'VncState'. In currently implementation there will be a memory leak when the -vnc disconnect. Following is the asan output backtrack: - -Direct leak of 29760 byte(s) in 5 object(s) allocated from: - 0 0xffffa67ef3c3 in __interceptor_calloc (/lib64/libasan.so.4+0xd33c3) - 1 0xffffa65071cb in g_malloc0 (/lib64/libglib-2.0.so.0+0x571cb) - 2 0xffffa5e968f7 in deflateInit2_ (/lib64/libz.so.1+0x78f7) - 3 0xaaaacec58613 in zrle_compress_data ui/vnc-enc-zrle.c:87 - 4 0xaaaacec58613 in zrle_send_framebuffer_update ui/vnc-enc-zrle.c:344 - 5 0xaaaacec34e77 in vnc_send_framebuffer_update ui/vnc.c:919 - 6 0xaaaacec5e023 in vnc_worker_thread_loop ui/vnc-jobs.c:271 - 7 0xaaaacec5e5e7 in vnc_worker_thread ui/vnc-jobs.c:340 - 8 0xaaaacee4d3c3 in qemu_thread_start util/qemu-thread-posix.c:502 - 9 0xffffa544e8bb in start_thread (/lib64/libpthread.so.0+0x78bb) - 10 0xffffa53965cb in thread_start (/lib64/libc.so.6+0xd55cb) - -This is because the opaque allocated in 'deflateInit2' is not freed in -'deflateEnd'. The reason is that the 'deflateEnd' calls 'deflateStateCheck' -and in the latter will check whether 's->strm != strm'(libz's data structure). -This check will be true so in 'deflateEnd' it just return 'Z_STREAM_ERROR' and -not free the data allocated in 'deflateInit2'. - -The reason this happens is that the 'VncState' contains the whole 'VncZrle', -so when calling 'deflateInit2', the 's->strm' will be the local address. -So 's->strm != strm' will be true. - -To fix this issue, we need to make 'zrle' of 'VncState' to be a pointer. -Then the connection 'VncState' and local 'VncState' exchange mechanism will -work as expection. The 'tight' of 'VncState' has the same issue, let's also turn -it to a pointer. - -Reported-by: Ying Fang -Signed-off-by: Li Qiang -Message-id: 20190831153922.121308-1-liq3ea@163.com -Signed-off-by: Gerd Hoffmann ---- - ui/vnc-enc-tight.c | 219 +++++++++++++++++++++++++------------------------- - ui/vnc-enc-zlib.c | 11 +-- - ui/vnc-enc-zrle.c | 68 ++++++++-------- - ui/vnc-enc-zrle.inc.c | 2 +- - ui/vnc.c | 28 ++++--- - ui/vnc.h | 4 +- - 6 files changed, 170 insertions(+), 162 deletions(-) - -diff --git a/ui/vnc-enc-tight.c b/ui/vnc-enc-tight.c -index 9084c22..1e08518 100644 ---- a/ui/vnc-enc-tight.c -+++ b/ui/vnc-enc-tight.c -@@ -116,7 +116,7 @@ static int send_png_rect(VncState *vs, int x, int y, int w, int h, - - static bool tight_can_send_png_rect(VncState *vs, int w, int h) - { -- if (vs->tight.type != VNC_ENCODING_TIGHT_PNG) { -+ if (vs->tight->type != VNC_ENCODING_TIGHT_PNG) { - return false; - } - -@@ -144,7 +144,7 @@ tight_detect_smooth_image24(VncState *vs, int w, int h) - int pixels = 0; - int pix, left[3]; - unsigned int errors; -- unsigned char *buf = vs->tight.tight.buffer; -+ unsigned char *buf = vs->tight->tight.buffer; - - /* - * If client is big-endian, color samples begin from the second -@@ -215,7 +215,7 @@ tight_detect_smooth_image24(VncState *vs, int w, int h) - int pixels = 0; \ - int sample, sum, left[3]; \ - unsigned int errors; \ -- unsigned char *buf = vs->tight.tight.buffer; \ -+ unsigned char *buf = vs->tight->tight.buffer; \ - \ - endian = 0; /* FIXME */ \ - \ -@@ -296,8 +296,8 @@ static int - tight_detect_smooth_image(VncState *vs, int w, int h) - { - unsigned int errors; -- int compression = vs->tight.compression; -- int quality = vs->tight.quality; -+ int compression = vs->tight->compression; -+ int quality = vs->tight->quality; - - if (!vs->vd->lossy) { - return 0; -@@ -309,7 +309,7 @@ tight_detect_smooth_image(VncState *vs, int w, int h) - return 0; - } - -- if (vs->tight.quality != (uint8_t)-1) { -+ if (vs->tight->quality != (uint8_t)-1) { - if (w * h < VNC_TIGHT_JPEG_MIN_RECT_SIZE) { - return 0; - } -@@ -320,9 +320,9 @@ tight_detect_smooth_image(VncState *vs, int w, int h) - } - - if (vs->client_pf.bytes_per_pixel == 4) { -- if (vs->tight.pixel24) { -+ if (vs->tight->pixel24) { - errors = tight_detect_smooth_image24(vs, w, h); -- if (vs->tight.quality != (uint8_t)-1) { -+ if (vs->tight->quality != (uint8_t)-1) { - return (errors < tight_conf[quality].jpeg_threshold24); - } - return (errors < tight_conf[compression].gradient_threshold24); -@@ -352,7 +352,7 @@ tight_detect_smooth_image(VncState *vs, int w, int h) - uint##bpp##_t c0, c1, ci; \ - int i, n0, n1; \ - \ -- data = (uint##bpp##_t *)vs->tight.tight.buffer; \ -+ data = (uint##bpp##_t *)vs->tight->tight.buffer; \ - \ - c0 = data[0]; \ - i = 1; \ -@@ -423,9 +423,9 @@ static int tight_fill_palette(VncState *vs, int x, int y, - { - int max; - -- max = count / tight_conf[vs->tight.compression].idx_max_colors_divisor; -+ max = count / tight_conf[vs->tight->compression].idx_max_colors_divisor; - if (max < 2 && -- count >= tight_conf[vs->tight.compression].mono_min_rect_size) { -+ count >= tight_conf[vs->tight->compression].mono_min_rect_size) { - max = 2; - } - if (max >= 256) { -@@ -558,7 +558,7 @@ tight_filter_gradient24(VncState *vs, uint8_t *buf, int w, int h) - int x, y, c; - - buf32 = (uint32_t *)buf; -- memset(vs->tight.gradient.buffer, 0, w * 3 * sizeof(int)); -+ memset(vs->tight->gradient.buffer, 0, w * 3 * sizeof(int)); - - if (1 /* FIXME */) { - shift[0] = vs->client_pf.rshift; -@@ -575,7 +575,7 @@ tight_filter_gradient24(VncState *vs, uint8_t *buf, int w, int h) - upper[c] = 0; - here[c] = 0; - } -- prev = (int *)vs->tight.gradient.buffer; -+ prev = (int *)vs->tight->gradient.buffer; - for (x = 0; x < w; x++) { - pix32 = *buf32++; - for (c = 0; c < 3; c++) { -@@ -615,7 +615,7 @@ tight_filter_gradient24(VncState *vs, uint8_t *buf, int w, int h) - int prediction; \ - int x, y, c; \ - \ -- memset (vs->tight.gradient.buffer, 0, w * 3 * sizeof(int)); \ -+ memset(vs->tight->gradient.buffer, 0, w * 3 * sizeof(int)); \ - \ - endian = 0; /* FIXME */ \ - \ -@@ -631,7 +631,7 @@ tight_filter_gradient24(VncState *vs, uint8_t *buf, int w, int h) - upper[c] = 0; \ - here[c] = 0; \ - } \ -- prev = (int *)vs->tight.gradient.buffer; \ -+ prev = (int *)vs->tight->gradient.buffer; \ - for (x = 0; x < w; x++) { \ - pix = *buf; \ - if (endian) { \ -@@ -785,7 +785,7 @@ static void extend_solid_area(VncState *vs, int x, int y, int w, int h, - static int tight_init_stream(VncState *vs, int stream_id, - int level, int strategy) - { -- z_streamp zstream = &vs->tight.stream[stream_id]; -+ z_streamp zstream = &vs->tight->stream[stream_id]; - - if (zstream->opaque == NULL) { - int err; -@@ -803,15 +803,15 @@ static int tight_init_stream(VncState *vs, int stream_id, - return -1; - } - -- vs->tight.levels[stream_id] = level; -+ vs->tight->levels[stream_id] = level; - zstream->opaque = vs; - } - -- if (vs->tight.levels[stream_id] != level) { -+ if (vs->tight->levels[stream_id] != level) { - if (deflateParams(zstream, level, strategy) != Z_OK) { - return -1; - } -- vs->tight.levels[stream_id] = level; -+ vs->tight->levels[stream_id] = level; - } - return 0; - } -@@ -839,11 +839,11 @@ static void tight_send_compact_size(VncState *vs, size_t len) - static int tight_compress_data(VncState *vs, int stream_id, size_t bytes, - int level, int strategy) - { -- z_streamp zstream = &vs->tight.stream[stream_id]; -+ z_streamp zstream = &vs->tight->stream[stream_id]; - int previous_out; - - if (bytes < VNC_TIGHT_MIN_TO_COMPRESS) { -- vnc_write(vs, vs->tight.tight.buffer, vs->tight.tight.offset); -+ vnc_write(vs, vs->tight->tight.buffer, vs->tight->tight.offset); - return bytes; - } - -@@ -852,13 +852,13 @@ static int tight_compress_data(VncState *vs, int stream_id, size_t bytes, - } - - /* reserve memory in output buffer */ -- buffer_reserve(&vs->tight.zlib, bytes + 64); -+ buffer_reserve(&vs->tight->zlib, bytes + 64); - - /* set pointers */ -- zstream->next_in = vs->tight.tight.buffer; -- zstream->avail_in = vs->tight.tight.offset; -- zstream->next_out = vs->tight.zlib.buffer + vs->tight.zlib.offset; -- zstream->avail_out = vs->tight.zlib.capacity - vs->tight.zlib.offset; -+ zstream->next_in = vs->tight->tight.buffer; -+ zstream->avail_in = vs->tight->tight.offset; -+ zstream->next_out = vs->tight->zlib.buffer + vs->tight->zlib.offset; -+ zstream->avail_out = vs->tight->zlib.capacity - vs->tight->zlib.offset; - previous_out = zstream->avail_out; - zstream->data_type = Z_BINARY; - -@@ -868,14 +868,14 @@ static int tight_compress_data(VncState *vs, int stream_id, size_t bytes, - return -1; - } - -- vs->tight.zlib.offset = vs->tight.zlib.capacity - zstream->avail_out; -+ vs->tight->zlib.offset = vs->tight->zlib.capacity - zstream->avail_out; - /* ...how much data has actually been produced by deflate() */ - bytes = previous_out - zstream->avail_out; - - tight_send_compact_size(vs, bytes); -- vnc_write(vs, vs->tight.zlib.buffer, bytes); -+ vnc_write(vs, vs->tight->zlib.buffer, bytes); - -- buffer_reset(&vs->tight.zlib); -+ buffer_reset(&vs->tight->zlib); - - return bytes; - } -@@ -927,16 +927,17 @@ static int send_full_color_rect(VncState *vs, int x, int y, int w, int h) - - vnc_write_u8(vs, stream << 4); /* no flushing, no filter */ - -- if (vs->tight.pixel24) { -- tight_pack24(vs, vs->tight.tight.buffer, w * h, &vs->tight.tight.offset); -+ if (vs->tight->pixel24) { -+ tight_pack24(vs, vs->tight->tight.buffer, w * h, -+ &vs->tight->tight.offset); - bytes = 3; - } else { - bytes = vs->client_pf.bytes_per_pixel; - } - - bytes = tight_compress_data(vs, stream, w * h * bytes, -- tight_conf[vs->tight.compression].raw_zlib_level, -- Z_DEFAULT_STRATEGY); -+ tight_conf[vs->tight->compression].raw_zlib_level, -+ Z_DEFAULT_STRATEGY); - - return (bytes >= 0); - } -@@ -947,14 +948,14 @@ static int send_solid_rect(VncState *vs) - - vnc_write_u8(vs, VNC_TIGHT_FILL << 4); /* no flushing, no filter */ - -- if (vs->tight.pixel24) { -- tight_pack24(vs, vs->tight.tight.buffer, 1, &vs->tight.tight.offset); -+ if (vs->tight->pixel24) { -+ tight_pack24(vs, vs->tight->tight.buffer, 1, &vs->tight->tight.offset); - bytes = 3; - } else { - bytes = vs->client_pf.bytes_per_pixel; - } - -- vnc_write(vs, vs->tight.tight.buffer, bytes); -+ vnc_write(vs, vs->tight->tight.buffer, bytes); - return 1; - } - -@@ -963,7 +964,7 @@ static int send_mono_rect(VncState *vs, int x, int y, - { - ssize_t bytes; - int stream = 1; -- int level = tight_conf[vs->tight.compression].mono_zlib_level; -+ int level = tight_conf[vs->tight->compression].mono_zlib_level; - - #ifdef CONFIG_VNC_PNG - if (tight_can_send_png_rect(vs, w, h)) { -@@ -991,26 +992,26 @@ static int send_mono_rect(VncState *vs, int x, int y, - uint32_t buf[2] = {bg, fg}; - size_t ret = sizeof (buf); - -- if (vs->tight.pixel24) { -+ if (vs->tight->pixel24) { - tight_pack24(vs, (unsigned char*)buf, 2, &ret); - } - vnc_write(vs, buf, ret); - -- tight_encode_mono_rect32(vs->tight.tight.buffer, w, h, bg, fg); -+ tight_encode_mono_rect32(vs->tight->tight.buffer, w, h, bg, fg); - break; - } - case 2: - vnc_write(vs, &bg, 2); - vnc_write(vs, &fg, 2); -- tight_encode_mono_rect16(vs->tight.tight.buffer, w, h, bg, fg); -+ tight_encode_mono_rect16(vs->tight->tight.buffer, w, h, bg, fg); - break; - default: - vnc_write_u8(vs, bg); - vnc_write_u8(vs, fg); -- tight_encode_mono_rect8(vs->tight.tight.buffer, w, h, bg, fg); -+ tight_encode_mono_rect8(vs->tight->tight.buffer, w, h, bg, fg); - break; - } -- vs->tight.tight.offset = bytes; -+ vs->tight->tight.offset = bytes; - - bytes = tight_compress_data(vs, stream, bytes, level, Z_DEFAULT_STRATEGY); - return (bytes >= 0); -@@ -1040,7 +1041,7 @@ static void write_palette(int idx, uint32_t color, void *opaque) - static bool send_gradient_rect(VncState *vs, int x, int y, int w, int h) - { - int stream = 3; -- int level = tight_conf[vs->tight.compression].gradient_zlib_level; -+ int level = tight_conf[vs->tight->compression].gradient_zlib_level; - ssize_t bytes; - - if (vs->client_pf.bytes_per_pixel == 1) { -@@ -1050,23 +1051,23 @@ static bool send_gradient_rect(VncState *vs, int x, int y, int w, int h) - vnc_write_u8(vs, (stream | VNC_TIGHT_EXPLICIT_FILTER) << 4); - vnc_write_u8(vs, VNC_TIGHT_FILTER_GRADIENT); - -- buffer_reserve(&vs->tight.gradient, w * 3 * sizeof (int)); -+ buffer_reserve(&vs->tight->gradient, w * 3 * sizeof(int)); - -- if (vs->tight.pixel24) { -- tight_filter_gradient24(vs, vs->tight.tight.buffer, w, h); -+ if (vs->tight->pixel24) { -+ tight_filter_gradient24(vs, vs->tight->tight.buffer, w, h); - bytes = 3; - } else if (vs->client_pf.bytes_per_pixel == 4) { -- tight_filter_gradient32(vs, (uint32_t *)vs->tight.tight.buffer, w, h); -+ tight_filter_gradient32(vs, (uint32_t *)vs->tight->tight.buffer, w, h); - bytes = 4; - } else { -- tight_filter_gradient16(vs, (uint16_t *)vs->tight.tight.buffer, w, h); -+ tight_filter_gradient16(vs, (uint16_t *)vs->tight->tight.buffer, w, h); - bytes = 2; - } - -- buffer_reset(&vs->tight.gradient); -+ buffer_reset(&vs->tight->gradient); - - bytes = w * h * bytes; -- vs->tight.tight.offset = bytes; -+ vs->tight->tight.offset = bytes; - - bytes = tight_compress_data(vs, stream, bytes, - level, Z_FILTERED); -@@ -1077,7 +1078,7 @@ static int send_palette_rect(VncState *vs, int x, int y, - int w, int h, VncPalette *palette) - { - int stream = 2; -- int level = tight_conf[vs->tight.compression].idx_zlib_level; -+ int level = tight_conf[vs->tight->compression].idx_zlib_level; - int colors; - ssize_t bytes; - -@@ -1104,12 +1105,12 @@ static int send_palette_rect(VncState *vs, int x, int y, - palette_iter(palette, write_palette, &priv); - vnc_write(vs, header, sizeof(header)); - -- if (vs->tight.pixel24) { -+ if (vs->tight->pixel24) { - tight_pack24(vs, vs->output.buffer + old_offset, colors, &offset); - vs->output.offset = old_offset + offset; - } - -- tight_encode_indexed_rect32(vs->tight.tight.buffer, w * h, palette); -+ tight_encode_indexed_rect32(vs->tight->tight.buffer, w * h, palette); - break; - } - case 2: -@@ -1119,7 +1120,7 @@ static int send_palette_rect(VncState *vs, int x, int y, - - palette_iter(palette, write_palette, &priv); - vnc_write(vs, header, sizeof(header)); -- tight_encode_indexed_rect16(vs->tight.tight.buffer, w * h, palette); -+ tight_encode_indexed_rect16(vs->tight->tight.buffer, w * h, palette); - break; - } - default: -@@ -1127,7 +1128,7 @@ static int send_palette_rect(VncState *vs, int x, int y, - break; - } - bytes = w * h; -- vs->tight.tight.offset = bytes; -+ vs->tight->tight.offset = bytes; - - bytes = tight_compress_data(vs, stream, bytes, - level, Z_DEFAULT_STRATEGY); -@@ -1146,7 +1147,7 @@ static int send_palette_rect(VncState *vs, int x, int y, - static void jpeg_init_destination(j_compress_ptr cinfo) - { - VncState *vs = cinfo->client_data; -- Buffer *buffer = &vs->tight.jpeg; -+ Buffer *buffer = &vs->tight->jpeg; - - cinfo->dest->next_output_byte = (JOCTET *)buffer->buffer + buffer->offset; - cinfo->dest->free_in_buffer = (size_t)(buffer->capacity - buffer->offset); -@@ -1156,7 +1157,7 @@ static void jpeg_init_destination(j_compress_ptr cinfo) - static boolean jpeg_empty_output_buffer(j_compress_ptr cinfo) - { - VncState *vs = cinfo->client_data; -- Buffer *buffer = &vs->tight.jpeg; -+ Buffer *buffer = &vs->tight->jpeg; - - buffer->offset = buffer->capacity; - buffer_reserve(buffer, 2048); -@@ -1168,7 +1169,7 @@ static boolean jpeg_empty_output_buffer(j_compress_ptr cinfo) - static void jpeg_term_destination(j_compress_ptr cinfo) - { - VncState *vs = cinfo->client_data; -- Buffer *buffer = &vs->tight.jpeg; -+ Buffer *buffer = &vs->tight->jpeg; - - buffer->offset = buffer->capacity - cinfo->dest->free_in_buffer; - } -@@ -1187,7 +1188,7 @@ static int send_jpeg_rect(VncState *vs, int x, int y, int w, int h, int quality) - return send_full_color_rect(vs, x, y, w, h); - } - -- buffer_reserve(&vs->tight.jpeg, 2048); -+ buffer_reserve(&vs->tight->jpeg, 2048); - - cinfo.err = jpeg_std_error(&jerr); - jpeg_create_compress(&cinfo); -@@ -1222,9 +1223,9 @@ static int send_jpeg_rect(VncState *vs, int x, int y, int w, int h, int quality) - - vnc_write_u8(vs, VNC_TIGHT_JPEG << 4); - -- tight_send_compact_size(vs, vs->tight.jpeg.offset); -- vnc_write(vs, vs->tight.jpeg.buffer, vs->tight.jpeg.offset); -- buffer_reset(&vs->tight.jpeg); -+ tight_send_compact_size(vs, vs->tight->jpeg.offset); -+ vnc_write(vs, vs->tight->jpeg.buffer, vs->tight->jpeg.offset); -+ buffer_reset(&vs->tight->jpeg); - - return 1; - } -@@ -1240,7 +1241,7 @@ static void write_png_palette(int idx, uint32_t pix, void *opaque) - VncState *vs = priv->vs; - png_colorp color = &priv->png_palette[idx]; - -- if (vs->tight.pixel24) -+ if (vs->tight->pixel24) - { - color->red = (pix >> vs->client_pf.rshift) & vs->client_pf.rmax; - color->green = (pix >> vs->client_pf.gshift) & vs->client_pf.gmax; -@@ -1267,10 +1268,10 @@ static void png_write_data(png_structp png_ptr, png_bytep data, - { - VncState *vs = png_get_io_ptr(png_ptr); - -- buffer_reserve(&vs->tight.png, vs->tight.png.offset + length); -- memcpy(vs->tight.png.buffer + vs->tight.png.offset, data, length); -+ buffer_reserve(&vs->tight->png, vs->tight->png.offset + length); -+ memcpy(vs->tight->png.buffer + vs->tight->png.offset, data, length); - -- vs->tight.png.offset += length; -+ vs->tight->png.offset += length; - } - - static void png_flush_data(png_structp png_ptr) -@@ -1295,8 +1296,8 @@ static int send_png_rect(VncState *vs, int x, int y, int w, int h, - png_infop info_ptr; - png_colorp png_palette = NULL; - pixman_image_t *linebuf; -- int level = tight_png_conf[vs->tight.compression].png_zlib_level; -- int filters = tight_png_conf[vs->tight.compression].png_filters; -+ int level = tight_png_conf[vs->tight->compression].png_zlib_level; -+ int filters = tight_png_conf[vs->tight->compression].png_filters; - uint8_t *buf; - int dy; - -@@ -1340,21 +1341,23 @@ static int send_png_rect(VncState *vs, int x, int y, int w, int h, - png_set_PLTE(png_ptr, info_ptr, png_palette, palette_size(palette)); - - if (vs->client_pf.bytes_per_pixel == 4) { -- tight_encode_indexed_rect32(vs->tight.tight.buffer, w * h, palette); -+ tight_encode_indexed_rect32(vs->tight->tight.buffer, w * h, -+ palette); - } else { -- tight_encode_indexed_rect16(vs->tight.tight.buffer, w * h, palette); -+ tight_encode_indexed_rect16(vs->tight->tight.buffer, w * h, -+ palette); - } - } - - png_write_info(png_ptr, info_ptr); - -- buffer_reserve(&vs->tight.png, 2048); -+ buffer_reserve(&vs->tight->png, 2048); - linebuf = qemu_pixman_linebuf_create(PIXMAN_BE_r8g8b8, w); - buf = (uint8_t *)pixman_image_get_data(linebuf); - for (dy = 0; dy < h; dy++) - { - if (color_type == PNG_COLOR_TYPE_PALETTE) { -- memcpy(buf, vs->tight.tight.buffer + (dy * w), w); -+ memcpy(buf, vs->tight->tight.buffer + (dy * w), w); - } else { - qemu_pixman_linebuf_fill(linebuf, vs->vd->server, w, x, y + dy); - } -@@ -1372,27 +1375,27 @@ static int send_png_rect(VncState *vs, int x, int y, int w, int h, - - vnc_write_u8(vs, VNC_TIGHT_PNG << 4); - -- tight_send_compact_size(vs, vs->tight.png.offset); -- vnc_write(vs, vs->tight.png.buffer, vs->tight.png.offset); -- buffer_reset(&vs->tight.png); -+ tight_send_compact_size(vs, vs->tight->png.offset); -+ vnc_write(vs, vs->tight->png.buffer, vs->tight->png.offset); -+ buffer_reset(&vs->tight->png); - return 1; - } - #endif /* CONFIG_VNC_PNG */ - - static void vnc_tight_start(VncState *vs) - { -- buffer_reset(&vs->tight.tight); -+ buffer_reset(&vs->tight->tight); - - // make the output buffer be the zlib buffer, so we can compress it later -- vs->tight.tmp = vs->output; -- vs->output = vs->tight.tight; -+ vs->tight->tmp = vs->output; -+ vs->output = vs->tight->tight; - } - - static void vnc_tight_stop(VncState *vs) - { - // switch back to normal output/zlib buffers -- vs->tight.tight = vs->output; -- vs->output = vs->tight.tmp; -+ vs->tight->tight = vs->output; -+ vs->output = vs->tight->tmp; - } - - static int send_sub_rect_nojpeg(VncState *vs, int x, int y, int w, int h, -@@ -1426,9 +1429,9 @@ static int send_sub_rect_jpeg(VncState *vs, int x, int y, int w, int h, - int ret; - - if (colors == 0) { -- if (force || (tight_jpeg_conf[vs->tight.quality].jpeg_full && -+ if (force || (tight_jpeg_conf[vs->tight->quality].jpeg_full && - tight_detect_smooth_image(vs, w, h))) { -- int quality = tight_conf[vs->tight.quality].jpeg_quality; -+ int quality = tight_conf[vs->tight->quality].jpeg_quality; - - ret = send_jpeg_rect(vs, x, y, w, h, quality); - } else { -@@ -1440,9 +1443,9 @@ static int send_sub_rect_jpeg(VncState *vs, int x, int y, int w, int h, - ret = send_mono_rect(vs, x, y, w, h, bg, fg); - } else if (colors <= 256) { - if (force || (colors > 96 && -- tight_jpeg_conf[vs->tight.quality].jpeg_idx && -+ tight_jpeg_conf[vs->tight->quality].jpeg_idx && - tight_detect_smooth_image(vs, w, h))) { -- int quality = tight_conf[vs->tight.quality].jpeg_quality; -+ int quality = tight_conf[vs->tight->quality].jpeg_quality; - - ret = send_jpeg_rect(vs, x, y, w, h, quality); - } else { -@@ -1480,20 +1483,20 @@ static int send_sub_rect(VncState *vs, int x, int y, int w, int h) - qemu_thread_atexit_add(&vnc_tight_cleanup_notifier); - } - -- vnc_framebuffer_update(vs, x, y, w, h, vs->tight.type); -+ vnc_framebuffer_update(vs, x, y, w, h, vs->tight->type); - - vnc_tight_start(vs); - vnc_raw_send_framebuffer_update(vs, x, y, w, h); - vnc_tight_stop(vs); - - #ifdef CONFIG_VNC_JPEG -- if (!vs->vd->non_adaptive && vs->tight.quality != (uint8_t)-1) { -+ if (!vs->vd->non_adaptive && vs->tight->quality != (uint8_t)-1) { - double freq = vnc_update_freq(vs, x, y, w, h); - -- if (freq < tight_jpeg_conf[vs->tight.quality].jpeg_freq_min) { -+ if (freq < tight_jpeg_conf[vs->tight->quality].jpeg_freq_min) { - allow_jpeg = false; - } -- if (freq >= tight_jpeg_conf[vs->tight.quality].jpeg_freq_threshold) { -+ if (freq >= tight_jpeg_conf[vs->tight->quality].jpeg_freq_threshold) { - force_jpeg = true; - vnc_sent_lossy_rect(vs, x, y, w, h); - } -@@ -1503,7 +1506,7 @@ static int send_sub_rect(VncState *vs, int x, int y, int w, int h) - colors = tight_fill_palette(vs, x, y, w * h, &bg, &fg, color_count_palette); - - #ifdef CONFIG_VNC_JPEG -- if (allow_jpeg && vs->tight.quality != (uint8_t)-1) { -+ if (allow_jpeg && vs->tight->quality != (uint8_t)-1) { - ret = send_sub_rect_jpeg(vs, x, y, w, h, bg, fg, colors, - color_count_palette, force_jpeg); - } else { -@@ -1520,7 +1523,7 @@ static int send_sub_rect(VncState *vs, int x, int y, int w, int h) - - static int send_sub_rect_solid(VncState *vs, int x, int y, int w, int h) - { -- vnc_framebuffer_update(vs, x, y, w, h, vs->tight.type); -+ vnc_framebuffer_update(vs, x, y, w, h, vs->tight->type); - - vnc_tight_start(vs); - vnc_raw_send_framebuffer_update(vs, x, y, w, h); -@@ -1538,8 +1541,8 @@ static int send_rect_simple(VncState *vs, int x, int y, int w, int h, - int rw, rh; - int n = 0; - -- max_size = tight_conf[vs->tight.compression].max_rect_size; -- max_width = tight_conf[vs->tight.compression].max_rect_width; -+ max_size = tight_conf[vs->tight->compression].max_rect_size; -+ max_width = tight_conf[vs->tight->compression].max_rect_width; - - if (split && (w > max_width || w * h > max_size)) { - max_sub_width = (w > max_width) ? max_width : w; -@@ -1648,16 +1651,16 @@ static int tight_send_framebuffer_update(VncState *vs, int x, int y, - - if (vs->client_pf.bytes_per_pixel == 4 && vs->client_pf.rmax == 0xFF && - vs->client_pf.bmax == 0xFF && vs->client_pf.gmax == 0xFF) { -- vs->tight.pixel24 = true; -+ vs->tight->pixel24 = true; - } else { -- vs->tight.pixel24 = false; -+ vs->tight->pixel24 = false; - } - - #ifdef CONFIG_VNC_JPEG -- if (vs->tight.quality != (uint8_t)-1) { -+ if (vs->tight->quality != (uint8_t)-1) { - double freq = vnc_update_freq(vs, x, y, w, h); - -- if (freq > tight_jpeg_conf[vs->tight.quality].jpeg_freq_threshold) { -+ if (freq > tight_jpeg_conf[vs->tight->quality].jpeg_freq_threshold) { - return send_rect_simple(vs, x, y, w, h, false); - } - } -@@ -1669,8 +1672,8 @@ static int tight_send_framebuffer_update(VncState *vs, int x, int y, - - /* Calculate maximum number of rows in one non-solid rectangle. */ - -- max_rows = tight_conf[vs->tight.compression].max_rect_size; -- max_rows /= MIN(tight_conf[vs->tight.compression].max_rect_width, w); -+ max_rows = tight_conf[vs->tight->compression].max_rect_size; -+ max_rows /= MIN(tight_conf[vs->tight->compression].max_rect_width, w); - - return find_large_solid_color_rect(vs, x, y, w, h, max_rows); - } -@@ -1678,33 +1681,33 @@ static int tight_send_framebuffer_update(VncState *vs, int x, int y, - int vnc_tight_send_framebuffer_update(VncState *vs, int x, int y, - int w, int h) - { -- vs->tight.type = VNC_ENCODING_TIGHT; -+ vs->tight->type = VNC_ENCODING_TIGHT; - return tight_send_framebuffer_update(vs, x, y, w, h); - } - - int vnc_tight_png_send_framebuffer_update(VncState *vs, int x, int y, - int w, int h) - { -- vs->tight.type = VNC_ENCODING_TIGHT_PNG; -+ vs->tight->type = VNC_ENCODING_TIGHT_PNG; - return tight_send_framebuffer_update(vs, x, y, w, h); - } - - void vnc_tight_clear(VncState *vs) - { - int i; -- for (i=0; itight.stream); i++) { -- if (vs->tight.stream[i].opaque) { -- deflateEnd(&vs->tight.stream[i]); -+ for (i = 0; i < ARRAY_SIZE(vs->tight->stream); i++) { -+ if (vs->tight->stream[i].opaque) { -+ deflateEnd(&vs->tight->stream[i]); - } - } - -- buffer_free(&vs->tight.tight); -- buffer_free(&vs->tight.zlib); -- buffer_free(&vs->tight.gradient); -+ buffer_free(&vs->tight->tight); -+ buffer_free(&vs->tight->zlib); -+ buffer_free(&vs->tight->gradient); - #ifdef CONFIG_VNC_JPEG -- buffer_free(&vs->tight.jpeg); -+ buffer_free(&vs->tight->jpeg); - #endif - #ifdef CONFIG_VNC_PNG -- buffer_free(&vs->tight.png); -+ buffer_free(&vs->tight->png); - #endif - } -diff --git a/ui/vnc-enc-zlib.c b/ui/vnc-enc-zlib.c -index 33e9df2..900ae5b 100644 ---- a/ui/vnc-enc-zlib.c -+++ b/ui/vnc-enc-zlib.c -@@ -76,7 +76,8 @@ static int vnc_zlib_stop(VncState *vs) - zstream->zalloc = vnc_zlib_zalloc; - zstream->zfree = vnc_zlib_zfree; - -- err = deflateInit2(zstream, vs->tight.compression, Z_DEFLATED, MAX_WBITS, -+ err = deflateInit2(zstream, vs->tight->compression, Z_DEFLATED, -+ MAX_WBITS, - MAX_MEM_LEVEL, Z_DEFAULT_STRATEGY); - - if (err != Z_OK) { -@@ -84,16 +85,16 @@ static int vnc_zlib_stop(VncState *vs) - return -1; - } - -- vs->zlib.level = vs->tight.compression; -+ vs->zlib.level = vs->tight->compression; - zstream->opaque = vs; - } - -- if (vs->tight.compression != vs->zlib.level) { -- if (deflateParams(zstream, vs->tight.compression, -+ if (vs->tight->compression != vs->zlib.level) { -+ if (deflateParams(zstream, vs->tight->compression, - Z_DEFAULT_STRATEGY) != Z_OK) { - return -1; - } -- vs->zlib.level = vs->tight.compression; -+ vs->zlib.level = vs->tight->compression; - } - - // reserve memory in output buffer -diff --git a/ui/vnc-enc-zrle.c b/ui/vnc-enc-zrle.c -index 7493a84..17fd28a 100644 ---- a/ui/vnc-enc-zrle.c -+++ b/ui/vnc-enc-zrle.c -@@ -37,18 +37,18 @@ static const int bits_per_packed_pixel[] = { - - static void vnc_zrle_start(VncState *vs) - { -- buffer_reset(&vs->zrle.zrle); -+ buffer_reset(&vs->zrle->zrle); - - /* make the output buffer be the zlib buffer, so we can compress it later */ -- vs->zrle.tmp = vs->output; -- vs->output = vs->zrle.zrle; -+ vs->zrle->tmp = vs->output; -+ vs->output = vs->zrle->zrle; - } - - static void vnc_zrle_stop(VncState *vs) - { - /* switch back to normal output/zlib buffers */ -- vs->zrle.zrle = vs->output; -- vs->output = vs->zrle.tmp; -+ vs->zrle->zrle = vs->output; -+ vs->output = vs->zrle->tmp; - } - - static void *zrle_convert_fb(VncState *vs, int x, int y, int w, int h, -@@ -56,24 +56,24 @@ static void *zrle_convert_fb(VncState *vs, int x, int y, int w, int h, - { - Buffer tmp; - -- buffer_reset(&vs->zrle.fb); -- buffer_reserve(&vs->zrle.fb, w * h * bpp + bpp); -+ buffer_reset(&vs->zrle->fb); -+ buffer_reserve(&vs->zrle->fb, w * h * bpp + bpp); - - tmp = vs->output; -- vs->output = vs->zrle.fb; -+ vs->output = vs->zrle->fb; - - vnc_raw_send_framebuffer_update(vs, x, y, w, h); - -- vs->zrle.fb = vs->output; -+ vs->zrle->fb = vs->output; - vs->output = tmp; -- return vs->zrle.fb.buffer; -+ return vs->zrle->fb.buffer; - } - - static int zrle_compress_data(VncState *vs, int level) - { -- z_streamp zstream = &vs->zrle.stream; -+ z_streamp zstream = &vs->zrle->stream; - -- buffer_reset(&vs->zrle.zlib); -+ buffer_reset(&vs->zrle->zlib); - - if (zstream->opaque != vs) { - int err; -@@ -93,13 +93,13 @@ static int zrle_compress_data(VncState *vs, int level) - } - - /* reserve memory in output buffer */ -- buffer_reserve(&vs->zrle.zlib, vs->zrle.zrle.offset + 64); -+ buffer_reserve(&vs->zrle->zlib, vs->zrle->zrle.offset + 64); - - /* set pointers */ -- zstream->next_in = vs->zrle.zrle.buffer; -- zstream->avail_in = vs->zrle.zrle.offset; -- zstream->next_out = vs->zrle.zlib.buffer + vs->zrle.zlib.offset; -- zstream->avail_out = vs->zrle.zlib.capacity - vs->zrle.zlib.offset; -+ zstream->next_in = vs->zrle->zrle.buffer; -+ zstream->avail_in = vs->zrle->zrle.offset; -+ zstream->next_out = vs->zrle->zlib.buffer + vs->zrle->zlib.offset; -+ zstream->avail_out = vs->zrle->zlib.capacity - vs->zrle->zlib.offset; - zstream->data_type = Z_BINARY; - - /* start encoding */ -@@ -108,8 +108,8 @@ static int zrle_compress_data(VncState *vs, int level) - return -1; - } - -- vs->zrle.zlib.offset = vs->zrle.zlib.capacity - zstream->avail_out; -- return vs->zrle.zlib.offset; -+ vs->zrle->zlib.offset = vs->zrle->zlib.capacity - zstream->avail_out; -+ return vs->zrle->zlib.offset; - } - - /* Try to work out whether to use RLE and/or a palette. We do this by -@@ -259,14 +259,14 @@ static int zrle_send_framebuffer_update(VncState *vs, int x, int y, - size_t bytes; - int zywrle_level; - -- if (vs->zrle.type == VNC_ENCODING_ZYWRLE) { -- if (!vs->vd->lossy || vs->tight.quality == (uint8_t)-1 -- || vs->tight.quality == 9) { -+ if (vs->zrle->type == VNC_ENCODING_ZYWRLE) { -+ if (!vs->vd->lossy || vs->tight->quality == (uint8_t)-1 -+ || vs->tight->quality == 9) { - zywrle_level = 0; -- vs->zrle.type = VNC_ENCODING_ZRLE; -- } else if (vs->tight.quality < 3) { -+ vs->zrle->type = VNC_ENCODING_ZRLE; -+ } else if (vs->tight->quality < 3) { - zywrle_level = 3; -- } else if (vs->tight.quality < 6) { -+ } else if (vs->tight->quality < 6) { - zywrle_level = 2; - } else { - zywrle_level = 1; -@@ -337,30 +337,30 @@ static int zrle_send_framebuffer_update(VncState *vs, int x, int y, - - vnc_zrle_stop(vs); - bytes = zrle_compress_data(vs, Z_DEFAULT_COMPRESSION); -- vnc_framebuffer_update(vs, x, y, w, h, vs->zrle.type); -+ vnc_framebuffer_update(vs, x, y, w, h, vs->zrle->type); - vnc_write_u32(vs, bytes); -- vnc_write(vs, vs->zrle.zlib.buffer, vs->zrle.zlib.offset); -+ vnc_write(vs, vs->zrle->zlib.buffer, vs->zrle->zlib.offset); - return 1; - } - - int vnc_zrle_send_framebuffer_update(VncState *vs, int x, int y, int w, int h) - { -- vs->zrle.type = VNC_ENCODING_ZRLE; -+ vs->zrle->type = VNC_ENCODING_ZRLE; - return zrle_send_framebuffer_update(vs, x, y, w, h); - } - - int vnc_zywrle_send_framebuffer_update(VncState *vs, int x, int y, int w, int h) - { -- vs->zrle.type = VNC_ENCODING_ZYWRLE; -+ vs->zrle->type = VNC_ENCODING_ZYWRLE; - return zrle_send_framebuffer_update(vs, x, y, w, h); - } - - void vnc_zrle_clear(VncState *vs) - { -- if (vs->zrle.stream.opaque) { -- deflateEnd(&vs->zrle.stream); -+ if (vs->zrle->stream.opaque) { -+ deflateEnd(&vs->zrle->stream); - } -- buffer_free(&vs->zrle.zrle); -- buffer_free(&vs->zrle.fb); -- buffer_free(&vs->zrle.zlib); -+ buffer_free(&vs->zrle->zrle); -+ buffer_free(&vs->zrle->fb); -+ buffer_free(&vs->zrle->zlib); - } -diff --git a/ui/vnc-enc-zrle.inc.c b/ui/vnc-enc-zrle.inc.c -index abf6b86..c107d8a 100644 ---- a/ui/vnc-enc-zrle.inc.c -+++ b/ui/vnc-enc-zrle.inc.c -@@ -96,7 +96,7 @@ static void ZRLE_ENCODE(VncState *vs, int x, int y, int w, int h, - static void ZRLE_ENCODE_TILE(VncState *vs, ZRLE_PIXEL *data, int w, int h, - int zywrle_level) - { -- VncPalette *palette = &vs->zrle.palette; -+ VncPalette *palette = &vs->zrle->palette; - - int runs = 0; - int single_pixels = 0; -diff --git a/ui/vnc.c b/ui/vnc.c -index bc43c4c..87b8045 100644 ---- a/ui/vnc.c -+++ b/ui/vnc.c -@@ -1307,6 +1307,8 @@ void vnc_disconnect_finish(VncState *vs) - object_unref(OBJECT(vs->sioc)); - vs->sioc = NULL; - vs->magic = 0; -+ g_free(vs->zrle); -+ g_free(vs->tight); - g_free(vs); - } - -@@ -2058,8 +2060,8 @@ static void set_encodings(VncState *vs, int32_t *encodings, size_t n_encodings) - - vs->features = 0; - vs->vnc_encoding = 0; -- vs->tight.compression = 9; -- vs->tight.quality = -1; /* Lossless by default */ -+ vs->tight->compression = 9; -+ vs->tight->quality = -1; /* Lossless by default */ - vs->absolute = -1; - - /* -@@ -2127,11 +2129,11 @@ static void set_encodings(VncState *vs, int32_t *encodings, size_t n_encodings) - vs->features |= VNC_FEATURE_LED_STATE_MASK; - break; - case VNC_ENCODING_COMPRESSLEVEL0 ... VNC_ENCODING_COMPRESSLEVEL0 + 9: -- vs->tight.compression = (enc & 0x0F); -+ vs->tight->compression = (enc & 0x0F); - break; - case VNC_ENCODING_QUALITYLEVEL0 ... VNC_ENCODING_QUALITYLEVEL0 + 9: - if (vs->vd->lossy) { -- vs->tight.quality = (enc & 0x0F); -+ vs->tight->quality = (enc & 0x0F); - } - break; - default: -@@ -3034,6 +3036,8 @@ static void vnc_connect(VncDisplay *vd, QIOChannelSocket *sioc, - int i; - - trace_vnc_client_connect(vs, sioc); -+ vs->zrle = g_new0(VncZrle, 1); -+ vs->tight = g_new0(VncTight, 1); - vs->magic = VNC_MAGIC; - vs->sioc = sioc; - object_ref(OBJECT(vs->sioc)); -@@ -3045,19 +3049,19 @@ static void vnc_connect(VncDisplay *vd, QIOChannelSocket *sioc, - buffer_init(&vs->output, "vnc-output/%p", sioc); - buffer_init(&vs->jobs_buffer, "vnc-jobs_buffer/%p", sioc); - -- buffer_init(&vs->tight.tight, "vnc-tight/%p", sioc); -- buffer_init(&vs->tight.zlib, "vnc-tight-zlib/%p", sioc); -- buffer_init(&vs->tight.gradient, "vnc-tight-gradient/%p", sioc); -+ buffer_init(&vs->tight->tight, "vnc-tight/%p", sioc); -+ buffer_init(&vs->tight->zlib, "vnc-tight-zlib/%p", sioc); -+ buffer_init(&vs->tight->gradient, "vnc-tight-gradient/%p", sioc); - #ifdef CONFIG_VNC_JPEG -- buffer_init(&vs->tight.jpeg, "vnc-tight-jpeg/%p", sioc); -+ buffer_init(&vs->tight->jpeg, "vnc-tight-jpeg/%p", sioc); - #endif - #ifdef CONFIG_VNC_PNG -- buffer_init(&vs->tight.png, "vnc-tight-png/%p", sioc); -+ buffer_init(&vs->tight->png, "vnc-tight-png/%p", sioc); - #endif - buffer_init(&vs->zlib.zlib, "vnc-zlib/%p", sioc); -- buffer_init(&vs->zrle.zrle, "vnc-zrle/%p", sioc); -- buffer_init(&vs->zrle.fb, "vnc-zrle-fb/%p", sioc); -- buffer_init(&vs->zrle.zlib, "vnc-zrle-zlib/%p", sioc); -+ buffer_init(&vs->zrle->zrle, "vnc-zrle/%p", sioc); -+ buffer_init(&vs->zrle->fb, "vnc-zrle-fb/%p", sioc); -+ buffer_init(&vs->zrle->zlib, "vnc-zrle-zlib/%p", sioc); - - if (skipauth) { - vs->auth = VNC_AUTH_NONE; -diff --git a/ui/vnc.h b/ui/vnc.h -index 8643860..fea79c2 100644 ---- a/ui/vnc.h -+++ b/ui/vnc.h -@@ -338,10 +338,10 @@ struct VncState - /* Encoding specific, if you add something here, don't forget to - * update vnc_async_encoding_start() - */ -- VncTight tight; -+ VncTight *tight; - VncZlib zlib; - VncHextile hextile; -- VncZrle zrle; -+ VncZrle *zrle; - VncZywrle zywrle; - - Notifier mouse_mode_notifier; --- -1.8.3.1 - diff --git a/xen-9pfs-Fix-log-messages-of-reply-errors.patch b/xen-9pfs-Fix-log-messages-of-reply-errors.patch new file mode 100644 index 0000000000000000000000000000000000000000..9abc55e3726607c32a4256409cbb75026612cb64 --- /dev/null +++ b/xen-9pfs-Fix-log-messages-of-reply-errors.patch @@ -0,0 +1,48 @@ +From 9bbb7e0fe081efff2e41f8517c256b72a284fe9b Mon Sep 17 00:00:00 2001 +From: Christian Schoenebeck +Date: Thu, 14 May 2020 08:06:43 +0200 +Subject: [PATCH 401/709] xen-9pfs: Fix log messages of reply errors + +If delivery of some 9pfs response fails for some reason, log the +error message by mentioning the 9P protocol reply type, not by +client's request type. The latter could be misleading that the +error occurred already when handling the request input. + +Signed-off-by: Christian Schoenebeck +Acked-by: Stefano Stabellini +Message-Id: +Signed-off-by: Greg Kurz +--- + hw/9pfs/xen-9p-backend.c | 9 +++++---- + 1 file changed, 5 insertions(+), 4 deletions(-) + +diff --git a/hw/9pfs/xen-9p-backend.c b/hw/9pfs/xen-9p-backend.c +index 18fe5b7c92..f04caabfe5 100644 +--- a/hw/9pfs/xen-9p-backend.c ++++ b/hw/9pfs/xen-9p-backend.c +@@ -137,7 +137,8 @@ static ssize_t xen_9pfs_pdu_vmarshal(V9fsPDU *pdu, + ret = v9fs_iov_vmarshal(in_sg, num, offset, 0, fmt, ap); + if (ret < 0) { + xen_pv_printf(&xen_9pfs->xendev, 0, +- "Failed to encode VirtFS request type %d\n", pdu->id + 1); ++ "Failed to encode VirtFS reply type %d\n", ++ pdu->id + 1); + xen_be_set_state(&xen_9pfs->xendev, XenbusStateClosing); + xen_9pfs_disconnect(&xen_9pfs->xendev); + } +@@ -201,9 +202,9 @@ static void xen_9pfs_init_in_iov_from_pdu(V9fsPDU *pdu, + + buf_size = iov_size(ring->sg, num); + if (buf_size < P9_IOHDRSZ) { +- xen_pv_printf(&xen_9pfs->xendev, 0, "Xen 9pfs request type %d" +- "needs %zu bytes, buffer has %zu, less than minimum\n", +- pdu->id, *size, buf_size); ++ xen_pv_printf(&xen_9pfs->xendev, 0, "Xen 9pfs reply type %d needs " ++ "%zu bytes, buffer has %zu, less than minimum\n", ++ pdu->id + 1, *size, buf_size); + xen_be_set_state(&xen_9pfs->xendev, XenbusStateClosing); + xen_9pfs_disconnect(&xen_9pfs->xendev); + } +-- +2.23.0 + diff --git a/xen-9pfs-increase-max-ring-order-to-9.patch b/xen-9pfs-increase-max-ring-order-to-9.patch new file mode 100644 index 0000000000000000000000000000000000000000..4a81a2475a39a14e64130f8293b8c8c4270630a8 --- /dev/null +++ b/xen-9pfs-increase-max-ring-order-to-9.patch @@ -0,0 +1,32 @@ +From 84af75577cceb195b044e2d5ba6d940206b169ca Mon Sep 17 00:00:00 2001 +From: Stefano Stabellini +Date: Thu, 21 May 2020 12:26:27 -0700 +Subject: [PATCH 647/709] xen/9pfs: increase max ring order to 9 + +The max order allowed by the protocol is 9. Increase the max order +supported by QEMU to 9 to increase performance. + +Signed-off-by: Stefano Stabellini +Reviewed-by: Christian Schoenebeck +Message-Id: <20200521192627.15259-3-sstabellini@kernel.org> +Signed-off-by: Greg Kurz +--- + hw/9pfs/xen-9p-backend.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/hw/9pfs/xen-9p-backend.c b/hw/9pfs/xen-9p-backend.c +index 3c84c86ab8..a969fcc54c 100644 +--- a/hw/9pfs/xen-9p-backend.c ++++ b/hw/9pfs/xen-9p-backend.c +@@ -21,7 +21,7 @@ + + #define VERSIONS "1" + #define MAX_RINGS 8 +-#define MAX_RING_ORDER 8 ++#define MAX_RING_ORDER 9 + + typedef struct Xen9pfsRing { + struct Xen9pfsDev *priv; +-- +2.23.0 + diff --git a/xen-9pfs-yield-when-there-isn-t-enough-room-on-the-r.patch b/xen-9pfs-yield-when-there-isn-t-enough-room-on-the-r.patch new file mode 100644 index 0000000000000000000000000000000000000000..a55f09844c7bdbf29bb1f071d51ea022e57c8200 --- /dev/null +++ b/xen-9pfs-yield-when-there-isn-t-enough-room-on-the-r.patch @@ -0,0 +1,90 @@ +From a4c4d462729466c4756bac8a0a8d77eb63b21ef7 Mon Sep 17 00:00:00 2001 +From: Stefano Stabellini +Date: Thu, 21 May 2020 12:26:26 -0700 +Subject: [PATCH 646/709] xen/9pfs: yield when there isn't enough room on the + ring + +Instead of truncating replies, which is problematic, wait until the +client reads more data and frees bytes on the reply ring. + +Do that by calling qemu_coroutine_yield(). The corresponding +qemu_coroutine_enter_if_inactive() is called from xen_9pfs_bh upon +receiving the next notification from the client. + +We need to be careful to avoid races in case xen_9pfs_bh and the +coroutine are both active at the same time. In xen_9pfs_bh, wait until +either the critical section is over (ring->co == NULL) or until the +coroutine becomes inactive (qemu_coroutine_yield() was called) before +continuing. Then, simply wake up the coroutine if it is inactive. + +Signed-off-by: Stefano Stabellini +Reviewed-by: Christian Schoenebeck +Message-Id: <20200521192627.15259-2-sstabellini@kernel.org> +Signed-off-by: Greg Kurz +--- + hw/9pfs/xen-9p-backend.c | 31 +++++++++++++++++++++++++------ + 1 file changed, 25 insertions(+), 6 deletions(-) + +diff --git a/hw/9pfs/xen-9p-backend.c b/hw/9pfs/xen-9p-backend.c +index fc197f6c8a..3c84c86ab8 100644 +--- a/hw/9pfs/xen-9p-backend.c ++++ b/hw/9pfs/xen-9p-backend.c +@@ -37,6 +37,7 @@ typedef struct Xen9pfsRing { + + struct iovec *sg; + QEMUBH *bh; ++ Coroutine *co; + + /* local copies, so that we can read/write PDU data directly from + * the ring */ +@@ -198,16 +199,20 @@ static void xen_9pfs_init_in_iov_from_pdu(V9fsPDU *pdu, + g_free(ring->sg); + + ring->sg = g_new0(struct iovec, 2); +- xen_9pfs_in_sg(ring, ring->sg, &num, pdu->idx, size); ++ ring->co = qemu_coroutine_self(); ++ /* make sure other threads see ring->co changes before continuing */ ++ smp_wmb(); + ++again: ++ xen_9pfs_in_sg(ring, ring->sg, &num, pdu->idx, size); + buf_size = iov_size(ring->sg, num); + if (buf_size < size) { +- xen_pv_printf(&xen_9pfs->xendev, 0, "Xen 9pfs request type %d" +- "needs %zu bytes, buffer has %zu\n", pdu->id, size, +- buf_size); +- xen_be_set_state(&xen_9pfs->xendev, XenbusStateClosing); +- xen_9pfs_disconnect(&xen_9pfs->xendev); ++ qemu_coroutine_yield(); ++ goto again; + } ++ ring->co = NULL; ++ /* make sure other threads see ring->co changes before continuing */ ++ smp_wmb(); + + *piov = ring->sg; + *pniov = num; +@@ -292,6 +297,20 @@ static int xen_9pfs_receive(Xen9pfsRing *ring) + static void xen_9pfs_bh(void *opaque) + { + Xen9pfsRing *ring = opaque; ++ bool wait; ++ ++again: ++ wait = ring->co != NULL && qemu_coroutine_entered(ring->co); ++ /* paired with the smb_wmb barriers in xen_9pfs_init_in_iov_from_pdu */ ++ smp_rmb(); ++ if (wait) { ++ cpu_relax(); ++ goto again; ++ } ++ ++ if (ring->co != NULL) { ++ qemu_coroutine_enter_if_inactive(ring->co); ++ } + xen_9pfs_receive(ring); + } + +-- +2.23.0 + diff --git a/xen-pt-Fix-flawed-conversion-to-realize.patch b/xen-pt-Fix-flawed-conversion-to-realize.patch new file mode 100644 index 0000000000000000000000000000000000000000..89adcd4004553a7cbe717531f2987533406a70ae --- /dev/null +++ b/xen-pt-Fix-flawed-conversion-to-realize.patch @@ -0,0 +1,64 @@ +From c61d1d9e4976d127a73bec14376d8e828491f62c Mon Sep 17 00:00:00 2001 +From: Markus Armbruster +Date: Wed, 22 Apr 2020 15:07:14 +0200 +Subject: [PATCH 022/709] xen/pt: Fix flawed conversion to realize() + +The conversion of xen_pt_initfn() to xen_pt_realize() blindly replaced +XEN_PT_ERR() by error_setg(). Several error conditions that did not +fail xen_pt_initfn() now fail xen_pt_realize(). Unsurprisingly, the +cleanup on these errors looks highly suspicious. + +Revert the inappropriate replacements. + +Fixes: 5a11d0f7549e24a10e178a9dc8ff5e698031d9a6 +Cc: Stefano Stabellini +Cc: Anthony Perard +Cc: Paul Durrant +Cc: xen-devel@lists.xenproject.org +Signed-off-by: Markus Armbruster +Reviewed-by: Paul Durrant +Message-Id: <20200422130719.28225-10-armbru@redhat.com> +--- + hw/xen/xen_pt.c | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +diff --git a/hw/xen/xen_pt.c b/hw/xen/xen_pt.c +index b91082cb8b..81d5ad8da7 100644 +--- a/hw/xen/xen_pt.c ++++ b/hw/xen/xen_pt.c +@@ -858,8 +858,8 @@ static void xen_pt_realize(PCIDevice *d, Error **errp) + + rc = xc_physdev_map_pirq(xen_xc, xen_domid, machine_irq, &pirq); + if (rc < 0) { +- error_setg_errno(errp, errno, "Mapping machine irq %u to" +- " pirq %i failed", machine_irq, pirq); ++ XEN_PT_ERR(d, "Mapping machine irq %u to pirq %i failed, (err: %d)\n", ++ machine_irq, pirq, errno); + + /* Disable PCI intx assertion (turn on bit10 of devctl) */ + cmd |= PCI_COMMAND_INTX_DISABLE; +@@ -880,8 +880,8 @@ static void xen_pt_realize(PCIDevice *d, Error **errp) + PCI_SLOT(d->devfn), + e_intx); + if (rc < 0) { +- error_setg_errno(errp, errno, "Binding of interrupt %u failed", +- e_intx); ++ XEN_PT_ERR(d, "Binding of interrupt %i failed! (err: %d)\n", ++ e_intx, errno); + + /* Disable PCI intx assertion (turn on bit10 of devctl) */ + cmd |= PCI_COMMAND_INTX_DISABLE; +@@ -889,8 +889,8 @@ static void xen_pt_realize(PCIDevice *d, Error **errp) + + if (xen_pt_mapped_machine_irq[machine_irq] == 0) { + if (xc_physdev_unmap_pirq(xen_xc, xen_domid, machine_irq)) { +- error_setg_errno(errp, errno, "Unmapping of machine" +- " interrupt %u failed", machine_irq); ++ XEN_PT_ERR(d, "Unmapping of machine interrupt %i failed!" ++ " (err: %d)\n", machine_irq, errno); + } + } + s->machine_irq = 0; +-- +2.23.0 + diff --git a/xhci-Fix-memory-leak-in-xhci_address_slot.patch b/xhci-Fix-memory-leak-in-xhci_address_slot.patch deleted file mode 100644 index 1d0f858f3e6ea2975aff0a7e89a155083a9695b7..0000000000000000000000000000000000000000 --- a/xhci-Fix-memory-leak-in-xhci_address_slot.patch +++ /dev/null @@ -1,47 +0,0 @@ -From c0de0a04d03183f524c2f60cda8ae1e886197a7d Mon Sep 17 00:00:00 2001 -From: Ying Fang -Date: Tue, 27 Aug 2019 10:54:48 +0800 -Subject: [PATCH] xhci: Fix memory leak in xhci_address_slot - -Address Sanitizer shows memory leak in xhci_address_slot -hw/usb/hcd-xhci.c:2156 and the stack is as bellow: - -Direct leak of 64 byte(s) in 4 object(s) allocated from: - #0 0xffff91c6f5ab in realloc (/lib64/libasan.so.4+0xd35ab) - #1 0xffff91987243 in g_realloc (/lib64/libglib-2.0.so.0+0x57243) - #2 0xaaaab0b26a1f in qemu_iovec_add util/iov.c:296 - #3 0xaaaab07e5ce3 in xhci_address_slot hw/usb/hcd-xhci.c:2156 - #4 0xaaaab07e5ce3 in xhci_process_commands hw/usb/hcd-xhci.c:2493 - #5 0xaaaab00058d7 in memory_region_write_accessor qemu/memory.c:507 - #6 0xaaaab0000d87 in access_with_adjusted_size memory.c:573 - #7 0xaaaab000abcf in memory_region_dispatch_write memory.c:1516 - #8 0xaaaaaff59947 in flatview_write_continue exec.c:3367 - #9 0xaaaaaff59c33 in flatview_write exec.c:3406 - #10 0xaaaaaff63b3b in address_space_write exec.c:3496 - #11 0xaaaab002f263 in kvm_cpu_exec accel/kvm/kvm-all.c:2288 - #12 0xaaaaaffee427 in qemu_kvm_cpu_thread_fn cpus.c:1290 - #13 0xaaaab0b1a943 in qemu_thread_start util/qemu-thread-posix.c:502 - #14 0xffff908ce8bb in start_thread (/lib64/libpthread.so.0+0x78bb) - #15 0xffff908165cb in thread_start (/lib64/libc.so.6+0xd55cb) - -Cc: zhanghailiang -Signed-off-by: Ying Fang ---- - hw/usb/hcd-xhci.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c -index f578264948..471759cd4c 100644 ---- a/hw/usb/hcd-xhci.c -+++ b/hw/usb/hcd-xhci.c -@@ -2161,6 +2161,7 @@ static TRBCCode xhci_address_slot(XHCIState *xhci, unsigned int slotid, - DeviceOutRequest | USB_REQ_SET_ADDRESS, - slotid, 0, 0, NULL); - assert(p.status != USB_RET_ASYNC); -+ usb_packet_cleanup(&p); - } - - res = xhci_enable_ep(xhci, slotid, 1, octx+32, ep0_ctx); --- -2.19.1 - diff --git a/xhci-Fix-memory-leak-in-xhci_kick_epctx-when-poweroff.patch b/xhci-Fix-memory-leak-in-xhci_kick_epctx-when-poweroff.patch deleted file mode 100644 index 9679374ef65c0b98cd31ff40b117b9f34296992d..0000000000000000000000000000000000000000 --- a/xhci-Fix-memory-leak-in-xhci_kick_epctx-when-poweroff.patch +++ /dev/null @@ -1,56 +0,0 @@ -From cf859d444770243fa184019fd4eab135b2653390 Mon Sep 17 00:00:00 2001 -From: Chen Qun -Date: Fri, 10 Jan 2020 18:36:24 +0800 -Subject: [PATCH] xhci: Fix memory leak in xhci_kick_epctx when poweroff - GuestOS -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -start vm with libvirt, when GuestOS running, enter poweroff command using -the xhci keyboard, then ASAN shows memory leak stack: - -Direct leak of 80 byte(s) in 5 object(s) allocated from: - #0 0xfffd1e6431cb in __interceptor_malloc (/lib64/libasan.so.4+0xd31cb) - #1 0xfffd1e107163 in g_malloc (/lib64/libglib-2.0.so.0+0x57163) - #2 0xaaad39051367 in qemu_sglist_init /qemu/dma-helpers.c:43 - #3 0xaaad3947c407 in pci_dma_sglist_init /qemu/include/hw/pci/pci.h:842 - #4 0xaaad3947c407 in xhci_xfer_create_sgl /qemu/hw/usb/hcd-xhci.c:1446 - #5 0xaaad3947c407 in xhci_setup_packet /qemu/hw/usb/hcd-xhci.c:1618 - #6 0xaaad3948625f in xhci_submit /qemu/hw/usb/hcd-xhci.c:1827 - #7 0xaaad3948625f in xhci_fire_transfer /qemu/hw/usb/hcd-xhci.c:1839 - #8 0xaaad3948625f in xhci_kick_epctx /qemu/hw/usb/hcd-xhci.c:1991 - #9 0xaaad3948f537 in xhci_doorbell_write /qemu/hw/usb/hcd-xhci.c:3158 - #10 0xaaad38bcbfc7 in memory_region_write_accessor /qemu/memory.c:483 - #11 0xaaad38bc654f in access_with_adjusted_size /qemu/memory.c:544 - #12 0xaaad38bd1877 in memory_region_dispatch_write /qemu/memory.c:1482 - #13 0xaaad38b1c77f in flatview_write_continue /qemu/exec.c:3167 - #14 0xaaad38b1ca83 in flatview_write /qemu/exec.c:3207 - #15 0xaaad38b268db in address_space_write /qemu/exec.c:3297 - #16 0xaaad38bf909b in kvm_cpu_exec /qemu/accel/kvm/kvm-all.c:2383 - #17 0xaaad38bb063f in qemu_kvm_cpu_thread_fn /qemu/cpus.c:1246 - #18 0xaaad39821c93 in qemu_thread_start /qemu/util/qemu-thread-posix.c:519 - #19 0xfffd1c8378bb (/lib64/libpthread.so.0+0x78bb) - #20 0xfffd1c77616b (/lib64/libc.so.6+0xd616b) - -Reported-by: Euler Robot -Signed-off-by: Chen Qun running_retry) { - DPRINTF("xhci: xfer nacked, stopping schedule\n"); - epctx->retry = xfer; -+ xhci_xfer_unmap(xfer); - break; - } - if (count++ > TRANSFER_LIMIT) { --- -2.23.0 - diff --git a/xhci-Fix-memory-leak-in-xhci_kick_epctx.patch b/xhci-Fix-memory-leak-in-xhci_kick_epctx.patch deleted file mode 100644 index 398b1bcdd6e784cf1ecd87f41d0f1066d2780c6c..0000000000000000000000000000000000000000 --- a/xhci-Fix-memory-leak-in-xhci_kick_epctx.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 2212f37e0e477d8da0cff02cfc8b7a921ca11bef Mon Sep 17 00:00:00 2001 -From: fangying -Date: Wed, 28 Aug 2019 14:02:22 +0800 -Subject: [PATCH] xhci: Fix memory leak in xhci_kick_epctx - -Address Sanitizer shows memory leak in xhci_kick_epctx hw/usb/hcd-xhci.c:1912. -A sglist is leaked when a packet is retired and returns USB_RET_NAK status. -The leak stack is as bellow: - -Direct leak of 2688 byte(s) in 168 object(s) allocated from: - #0 0xffffae8b11db in __interceptor_malloc (/lib64/libasan.so.4+0xd31db) - #1 0xffffae5c9163 in g_malloc (/lib64/libglib-2.0.so.0+0x57163) - #2 0xaaaabb6fb3f7 in qemu_sglist_init dma-helpers.c:43 - #3 0xaaaabba705a7 in pci_dma_sglist_init include/hw/pci/pci.h:837 - #4 0xaaaabba705a7 in xhci_xfer_create_sgl hw/usb/hcd-xhci.c:1443 - #5 0xaaaabba705a7 in xhci_setup_packet hw/usb/hcd-xhci.c:1615 - #6 0xaaaabba77a6f in xhci_kick_epctx hw/usb/hcd-xhci.c:1912 - #7 0xaaaabbdaad27 in timerlist_run_timers util/qemu-timer.c:592 - #8 0xaaaabbdab19f in qemu_clock_run_timers util/qemu-timer.c:606 - #9 0xaaaabbdab19f in qemu_clock_run_all_timers util/qemu-timer.c:692 - #10 0xaaaabbdab9a3 in main_loop_wait util/main-loop.c:524 - #11 0xaaaabb6ff5e7 in main_loop vl.c:1806 - #12 0xaaaabb1e1453 in main vl.c:4488 - -Signed-off-by: Ying Fang ---- - hw/usb/hcd-xhci.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c -index 6e1ec786..e10fbd3d 100644 ---- a/hw/usb/hcd-xhci.c -+++ b/hw/usb/hcd-xhci.c -@@ -1911,6 +1911,7 @@ static void xhci_kick_epctx(XHCIEPContext *epctx, unsigned int streamid) - } - usb_handle_packet(xfer->packet.ep->dev, &xfer->packet); - if (xfer->packet.status == USB_RET_NAK) { -+ xhci_xfer_unmap(xfer); - return; - } - xhci_try_complete_packet(xfer); --- -2.19.1 -