From 62c5bc348e39f8b715fb2eac414749ee7e630043 Mon Sep 17 00:00:00 2001 From: Daniel Henrique Barboza Date: Mon, 6 Feb 2023 11:00:20 -0300 Subject: [PATCH 001/129] hw/riscv: handle 32 bit CPUs kernel_entry in riscv_load_kernel() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Next patch will move all calls to riscv_load_initrd() to riscv_load_kernel(). Machines that want to load initrd will be able to do via an extra flag to riscv_load_kernel(). This change will expose a sign-extend behavior that is happening in load_elf_ram_sym() when running 32 bit guests [1]. This is currently obscured by the fact that riscv_load_initrd() is using the return of riscv_load_kernel(), defined as target_ulong, and this return type will crop the higher 32 bits that would be padded with 1s by the sign extension when running in 32 bit targets. The changes to be done will force riscv_load_initrd() to use an uint64_t instead, exposing it to the padding when dealing with 32 bit CPUs. There is a discussion about whether load_elf_ram_sym() should or should not sign extend the value returned by 'lowaddr'. What we can do is to prevent the behavior change that the next patch will end up doing. riscv_load_initrd() wasn't dealing with 64 bit kernel entries when running 32 bit CPUs, and we want to keep it that way. One way of doing it is to use target_ulong in 'kernel_entry' in riscv_load_kernel() and rely on the fact that this var will not be sign extended for 32 bit targets. Another way is to explictly clear the higher 32 bits when running 32 bit CPUs for all possibilities of kernel_entry. We opted for the later. This will allow us to be clear about the design choices made in the function, while also allowing us to add a small comment about what load_elf_ram_sym() is doing. With this change, the consolation patch can do its job without worrying about unintended behavioral changes. [1] https://lists.gnu.org/archive/html/qemu-devel/2023-01/msg02281.html Signed-off-by: Daniel Henrique Barboza Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Alistair Francis Message-Id: <20230206140022.2748401-2-dbarboza@ventanamicro.com> Signed-off-by: Alistair Francis Signed-off-by: Palmer Dabbelt --- hw/riscv/boot.c | 20 +++++++++++++++++--- hw/riscv/microchip_pfsoc.c | 3 ++- hw/riscv/opentitan.c | 3 ++- hw/riscv/sifive_e.c | 3 ++- hw/riscv/sifive_u.c | 3 ++- hw/riscv/spike.c | 3 ++- hw/riscv/virt.c | 3 ++- include/hw/riscv/boot.h | 1 + 8 files changed, 30 insertions(+), 9 deletions(-) diff --git a/hw/riscv/boot.c b/hw/riscv/boot.c index c7e0e50bd8..df6b4a1fba 100644 --- a/hw/riscv/boot.c +++ b/hw/riscv/boot.c @@ -174,6 +174,7 @@ target_ulong riscv_load_firmware(const char *firmware_filename, } target_ulong riscv_load_kernel(MachineState *machine, + RISCVHartArrayState *harts, target_ulong kernel_start_addr, symbol_fn_t sym_cb) { @@ -192,21 +193,34 @@ target_ulong riscv_load_kernel(MachineState *machine, if (load_elf_ram_sym(kernel_filename, NULL, NULL, NULL, NULL, &kernel_load_base, NULL, NULL, 0, EM_RISCV, 1, 0, NULL, true, sym_cb) > 0) { - return kernel_load_base; + kernel_entry = kernel_load_base; + goto out; } if (load_uimage_as(kernel_filename, &kernel_entry, NULL, NULL, NULL, NULL, NULL) > 0) { - return kernel_entry; + goto out; } if (load_image_targphys_as(kernel_filename, kernel_start_addr, current_machine->ram_size, NULL) > 0) { - return kernel_start_addr; + kernel_entry = kernel_start_addr; + goto out; } error_report("could not load kernel '%s'", kernel_filename); exit(1); + +out: + /* + * For 32 bit CPUs 'kernel_entry' can be sign-extended by + * load_elf_ram_sym(). + */ + if (riscv_is_32bit(harts)) { + kernel_entry = extract64(kernel_entry, 0, 32); + } + + return kernel_entry; } void riscv_load_initrd(MachineState *machine, uint64_t kernel_entry) diff --git a/hw/riscv/microchip_pfsoc.c b/hw/riscv/microchip_pfsoc.c index 2b91e49561..712625d2a4 100644 --- a/hw/riscv/microchip_pfsoc.c +++ b/hw/riscv/microchip_pfsoc.c @@ -629,7 +629,8 @@ static void microchip_icicle_kit_machine_init(MachineState *machine) kernel_start_addr = riscv_calc_kernel_start_addr(&s->soc.u_cpus, firmware_end_addr); - kernel_entry = riscv_load_kernel(machine, kernel_start_addr, NULL); + kernel_entry = riscv_load_kernel(machine, &s->soc.u_cpus, + kernel_start_addr, NULL); if (machine->initrd_filename) { riscv_load_initrd(machine, kernel_entry); diff --git a/hw/riscv/opentitan.c b/hw/riscv/opentitan.c index 353f030d80..7fe4fb5628 100644 --- a/hw/riscv/opentitan.c +++ b/hw/riscv/opentitan.c @@ -101,7 +101,8 @@ static void opentitan_board_init(MachineState *machine) } if (machine->kernel_filename) { - riscv_load_kernel(machine, memmap[IBEX_DEV_RAM].base, NULL); + riscv_load_kernel(machine, &s->soc.cpus, + memmap[IBEX_DEV_RAM].base, NULL); } } diff --git a/hw/riscv/sifive_e.c b/hw/riscv/sifive_e.c index 3e3f4b0088..1a7d381514 100644 --- a/hw/riscv/sifive_e.c +++ b/hw/riscv/sifive_e.c @@ -114,7 +114,8 @@ static void sifive_e_machine_init(MachineState *machine) memmap[SIFIVE_E_DEV_MROM].base, &address_space_memory); if (machine->kernel_filename) { - riscv_load_kernel(machine, memmap[SIFIVE_E_DEV_DTIM].base, NULL); + riscv_load_kernel(machine, &s->soc.cpus, + memmap[SIFIVE_E_DEV_DTIM].base, NULL); } } diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c index d3ab7a9cda..71be442a50 100644 --- a/hw/riscv/sifive_u.c +++ b/hw/riscv/sifive_u.c @@ -598,7 +598,8 @@ static void sifive_u_machine_init(MachineState *machine) kernel_start_addr = riscv_calc_kernel_start_addr(&s->soc.u_cpus, firmware_end_addr); - kernel_entry = riscv_load_kernel(machine, kernel_start_addr, NULL); + kernel_entry = riscv_load_kernel(machine, &s->soc.u_cpus, + kernel_start_addr, NULL); if (machine->initrd_filename) { riscv_load_initrd(machine, kernel_entry); diff --git a/hw/riscv/spike.c b/hw/riscv/spike.c index cc3f6dac17..1fa91167ab 100644 --- a/hw/riscv/spike.c +++ b/hw/riscv/spike.c @@ -305,7 +305,8 @@ static void spike_board_init(MachineState *machine) kernel_start_addr = riscv_calc_kernel_start_addr(&s->soc[0], firmware_end_addr); - kernel_entry = riscv_load_kernel(machine, kernel_start_addr, + kernel_entry = riscv_load_kernel(machine, &s->soc[0], + kernel_start_addr, htif_symbol_callback); if (machine->initrd_filename) { diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c index b81081c70b..797c6084b6 100644 --- a/hw/riscv/virt.c +++ b/hw/riscv/virt.c @@ -1277,7 +1277,8 @@ static void virt_machine_done(Notifier *notifier, void *data) kernel_start_addr = riscv_calc_kernel_start_addr(&s->soc[0], firmware_end_addr); - kernel_entry = riscv_load_kernel(machine, kernel_start_addr, NULL); + kernel_entry = riscv_load_kernel(machine, &s->soc[0], + kernel_start_addr, NULL); if (machine->initrd_filename) { riscv_load_initrd(machine, kernel_entry); diff --git a/include/hw/riscv/boot.h b/include/hw/riscv/boot.h index 511390f60e..6295316afb 100644 --- a/include/hw/riscv/boot.h +++ b/include/hw/riscv/boot.h @@ -44,6 +44,7 @@ target_ulong riscv_load_firmware(const char *firmware_filename, hwaddr firmware_load_addr, symbol_fn_t sym_cb); target_ulong riscv_load_kernel(MachineState *machine, + RISCVHartArrayState *harts, target_ulong firmware_end_addr, symbol_fn_t sym_cb); void riscv_load_initrd(MachineState *machine, uint64_t kernel_entry); From 487d73fc470d233f2d5da9cec7cd229ae8b88b49 Mon Sep 17 00:00:00 2001 From: Daniel Henrique Barboza Date: Mon, 6 Feb 2023 11:00:21 -0300 Subject: [PATCH 002/129] hw/riscv/boot.c: consolidate all kernel init in riscv_load_kernel() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The microchip_icicle_kit, sifive_u, spike and virt boards are now doing the same steps when '-kernel' is used: - execute load_kernel() - load init_rd() - write kernel_cmdline Let's fold everything inside riscv_load_kernel() to avoid code repetition. To not change the behavior of boards that aren't calling riscv_load_init(), add an 'load_initrd' flag to riscv_load_kernel() and allow these boards to opt out from initrd loading. Cc: Palmer Dabbelt Reviewed-by: Bin Meng Reviewed-by: Alistair Francis Signed-off-by: Daniel Henrique Barboza Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20230206140022.2748401-3-dbarboza@ventanamicro.com> Signed-off-by: Alistair Francis Signed-off-by: Palmer Dabbelt --- hw/riscv/boot.c | 11 +++++++++++ hw/riscv/microchip_pfsoc.c | 11 +---------- hw/riscv/opentitan.c | 3 ++- hw/riscv/sifive_e.c | 3 ++- hw/riscv/sifive_u.c | 11 +---------- hw/riscv/spike.c | 11 +---------- hw/riscv/virt.c | 11 +---------- include/hw/riscv/boot.h | 1 + 8 files changed, 20 insertions(+), 42 deletions(-) diff --git a/hw/riscv/boot.c b/hw/riscv/boot.c index df6b4a1fba..4954bb9d4b 100644 --- a/hw/riscv/boot.c +++ b/hw/riscv/boot.c @@ -176,10 +176,12 @@ target_ulong riscv_load_firmware(const char *firmware_filename, target_ulong riscv_load_kernel(MachineState *machine, RISCVHartArrayState *harts, target_ulong kernel_start_addr, + bool load_initrd, symbol_fn_t sym_cb) { const char *kernel_filename = machine->kernel_filename; uint64_t kernel_load_base, kernel_entry; + void *fdt = machine->fdt; g_assert(kernel_filename != NULL); @@ -220,6 +222,15 @@ out: kernel_entry = extract64(kernel_entry, 0, 32); } + if (load_initrd && machine->initrd_filename) { + riscv_load_initrd(machine, kernel_entry); + } + + if (fdt && machine->kernel_cmdline && *machine->kernel_cmdline) { + qemu_fdt_setprop_string(fdt, "/chosen", "bootargs", + machine->kernel_cmdline); + } + return kernel_entry; } diff --git a/hw/riscv/microchip_pfsoc.c b/hw/riscv/microchip_pfsoc.c index 712625d2a4..e81bbd12df 100644 --- a/hw/riscv/microchip_pfsoc.c +++ b/hw/riscv/microchip_pfsoc.c @@ -630,16 +630,7 @@ static void microchip_icicle_kit_machine_init(MachineState *machine) firmware_end_addr); kernel_entry = riscv_load_kernel(machine, &s->soc.u_cpus, - kernel_start_addr, NULL); - - if (machine->initrd_filename) { - riscv_load_initrd(machine, kernel_entry); - } - - if (machine->kernel_cmdline && *machine->kernel_cmdline) { - qemu_fdt_setprop_string(machine->fdt, "/chosen", - "bootargs", machine->kernel_cmdline); - } + kernel_start_addr, true, NULL); /* Compute the fdt load address in dram */ fdt_load_addr = riscv_compute_fdt_addr(memmap[MICROCHIP_PFSOC_DRAM_LO].base, diff --git a/hw/riscv/opentitan.c b/hw/riscv/opentitan.c index 7fe4fb5628..b06944d382 100644 --- a/hw/riscv/opentitan.c +++ b/hw/riscv/opentitan.c @@ -102,7 +102,8 @@ static void opentitan_board_init(MachineState *machine) if (machine->kernel_filename) { riscv_load_kernel(machine, &s->soc.cpus, - memmap[IBEX_DEV_RAM].base, NULL); + memmap[IBEX_DEV_RAM].base, + false, NULL); } } diff --git a/hw/riscv/sifive_e.c b/hw/riscv/sifive_e.c index 1a7d381514..04939b60c3 100644 --- a/hw/riscv/sifive_e.c +++ b/hw/riscv/sifive_e.c @@ -115,7 +115,8 @@ static void sifive_e_machine_init(MachineState *machine) if (machine->kernel_filename) { riscv_load_kernel(machine, &s->soc.cpus, - memmap[SIFIVE_E_DEV_DTIM].base, NULL); + memmap[SIFIVE_E_DEV_DTIM].base, + false, NULL); } } diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c index 71be442a50..ad3bb35b34 100644 --- a/hw/riscv/sifive_u.c +++ b/hw/riscv/sifive_u.c @@ -599,16 +599,7 @@ static void sifive_u_machine_init(MachineState *machine) firmware_end_addr); kernel_entry = riscv_load_kernel(machine, &s->soc.u_cpus, - kernel_start_addr, NULL); - - if (machine->initrd_filename) { - riscv_load_initrd(machine, kernel_entry); - } - - if (machine->kernel_cmdline && *machine->kernel_cmdline) { - qemu_fdt_setprop_string(machine->fdt, "/chosen", "bootargs", - machine->kernel_cmdline); - } + kernel_start_addr, true, NULL); } else { /* * If dynamic firmware is used, it doesn't know where is the next mode diff --git a/hw/riscv/spike.c b/hw/riscv/spike.c index 1fa91167ab..a584d5b3a2 100644 --- a/hw/riscv/spike.c +++ b/hw/riscv/spike.c @@ -307,16 +307,7 @@ static void spike_board_init(MachineState *machine) kernel_entry = riscv_load_kernel(machine, &s->soc[0], kernel_start_addr, - htif_symbol_callback); - - if (machine->initrd_filename) { - riscv_load_initrd(machine, kernel_entry); - } - - if (machine->kernel_cmdline && *machine->kernel_cmdline) { - qemu_fdt_setprop_string(machine->fdt, "/chosen", "bootargs", - machine->kernel_cmdline); - } + true, htif_symbol_callback); } else { /* * If dynamic firmware is used, it doesn't know where is the next mode diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c index 797c6084b6..86c4adc0c9 100644 --- a/hw/riscv/virt.c +++ b/hw/riscv/virt.c @@ -1278,16 +1278,7 @@ static void virt_machine_done(Notifier *notifier, void *data) firmware_end_addr); kernel_entry = riscv_load_kernel(machine, &s->soc[0], - kernel_start_addr, NULL); - - if (machine->initrd_filename) { - riscv_load_initrd(machine, kernel_entry); - } - - if (machine->kernel_cmdline && *machine->kernel_cmdline) { - qemu_fdt_setprop_string(machine->fdt, "/chosen", "bootargs", - machine->kernel_cmdline); - } + kernel_start_addr, true, NULL); } else { /* * If dynamic firmware is used, it doesn't know where is the next mode diff --git a/include/hw/riscv/boot.h b/include/hw/riscv/boot.h index 6295316afb..ea1de8b020 100644 --- a/include/hw/riscv/boot.h +++ b/include/hw/riscv/boot.h @@ -46,6 +46,7 @@ target_ulong riscv_load_firmware(const char *firmware_filename, target_ulong riscv_load_kernel(MachineState *machine, RISCVHartArrayState *harts, target_ulong firmware_end_addr, + bool load_initrd, symbol_fn_t sym_cb); void riscv_load_initrd(MachineState *machine, uint64_t kernel_entry); uint64_t riscv_compute_fdt_addr(hwaddr dram_start, uint64_t dram_size, From 8b64475bd529ffe42f89b6c2f819e5133c9f8317 Mon Sep 17 00:00:00 2001 From: Daniel Henrique Barboza Date: Mon, 6 Feb 2023 11:00:22 -0300 Subject: [PATCH 003/129] hw/riscv/boot.c: make riscv_load_initrd() static MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The only remaining caller is riscv_load_kernel_and_initrd() which belongs to the same file. Signed-off-by: Daniel Henrique Barboza Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Bin Meng Reviewed-by: Alistair Francis Message-Id: <20230206140022.2748401-4-dbarboza@ventanamicro.com> Signed-off-by: Alistair Francis Signed-off-by: Palmer Dabbelt --- hw/riscv/boot.c | 80 ++++++++++++++++++++--------------------- include/hw/riscv/boot.h | 1 - 2 files changed, 40 insertions(+), 41 deletions(-) diff --git a/hw/riscv/boot.c b/hw/riscv/boot.c index 4954bb9d4b..52bf8e67de 100644 --- a/hw/riscv/boot.c +++ b/hw/riscv/boot.c @@ -173,6 +173,46 @@ target_ulong riscv_load_firmware(const char *firmware_filename, exit(1); } +static void riscv_load_initrd(MachineState *machine, uint64_t kernel_entry) +{ + const char *filename = machine->initrd_filename; + uint64_t mem_size = machine->ram_size; + void *fdt = machine->fdt; + hwaddr start, end; + ssize_t size; + + g_assert(filename != NULL); + + /* + * We want to put the initrd far enough into RAM that when the + * kernel is uncompressed it will not clobber the initrd. However + * on boards without much RAM we must ensure that we still leave + * enough room for a decent sized initrd, and on boards with large + * amounts of RAM we must avoid the initrd being so far up in RAM + * that it is outside lowmem and inaccessible to the kernel. + * So for boards with less than 256MB of RAM we put the initrd + * halfway into RAM, and for boards with 256MB of RAM or more we put + * the initrd at 128MB. + */ + start = kernel_entry + MIN(mem_size / 2, 128 * MiB); + + size = load_ramdisk(filename, start, mem_size - start); + if (size == -1) { + size = load_image_targphys(filename, start, mem_size - start); + if (size == -1) { + error_report("could not load ramdisk '%s'", filename); + exit(1); + } + } + + /* Some RISC-V machines (e.g. opentitan) don't have a fdt. */ + if (fdt) { + end = start + size; + qemu_fdt_setprop_cell(fdt, "/chosen", "linux,initrd-start", start); + qemu_fdt_setprop_cell(fdt, "/chosen", "linux,initrd-end", end); + } +} + target_ulong riscv_load_kernel(MachineState *machine, RISCVHartArrayState *harts, target_ulong kernel_start_addr, @@ -234,46 +274,6 @@ out: return kernel_entry; } -void riscv_load_initrd(MachineState *machine, uint64_t kernel_entry) -{ - const char *filename = machine->initrd_filename; - uint64_t mem_size = machine->ram_size; - void *fdt = machine->fdt; - hwaddr start, end; - ssize_t size; - - g_assert(filename != NULL); - - /* - * We want to put the initrd far enough into RAM that when the - * kernel is uncompressed it will not clobber the initrd. However - * on boards without much RAM we must ensure that we still leave - * enough room for a decent sized initrd, and on boards with large - * amounts of RAM we must avoid the initrd being so far up in RAM - * that it is outside lowmem and inaccessible to the kernel. - * So for boards with less than 256MB of RAM we put the initrd - * halfway into RAM, and for boards with 256MB of RAM or more we put - * the initrd at 128MB. - */ - start = kernel_entry + MIN(mem_size / 2, 128 * MiB); - - size = load_ramdisk(filename, start, mem_size - start); - if (size == -1) { - size = load_image_targphys(filename, start, mem_size - start); - if (size == -1) { - error_report("could not load ramdisk '%s'", filename); - exit(1); - } - } - - /* Some RISC-V machines (e.g. opentitan) don't have a fdt. */ - if (fdt) { - end = start + size; - qemu_fdt_setprop_cell(fdt, "/chosen", "linux,initrd-start", start); - qemu_fdt_setprop_cell(fdt, "/chosen", "linux,initrd-end", end); - } -} - /* * This function makes an assumption that the DRAM interval * 'dram_base' + 'dram_size' is contiguous. diff --git a/include/hw/riscv/boot.h b/include/hw/riscv/boot.h index ea1de8b020..a2e4ae9cb0 100644 --- a/include/hw/riscv/boot.h +++ b/include/hw/riscv/boot.h @@ -48,7 +48,6 @@ target_ulong riscv_load_kernel(MachineState *machine, target_ulong firmware_end_addr, bool load_initrd, symbol_fn_t sym_cb); -void riscv_load_initrd(MachineState *machine, uint64_t kernel_entry); uint64_t riscv_compute_fdt_addr(hwaddr dram_start, uint64_t dram_size, MachineState *ms); void riscv_load_fdt(hwaddr fdt_addr, void *fdt); From 6fbef9426bac7184b5d5887589d8386e732865eb Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Sat, 14 Jan 2023 15:21:03 -1000 Subject: [PATCH 004/129] target/i386: Fix 32-bit AD[CO]X insns in 64-bit mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Failure to truncate the inputs results in garbage for the carry-out. Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1373 Signed-off-by: Richard Henderson Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20230115012103.3131796-1-richard.henderson@linaro.org> Signed-off-by: Paolo Bonzini --- target/i386/tcg/emit.c.inc | 2 + tests/tcg/x86_64/Makefile.target | 3 ++ tests/tcg/x86_64/adox.c | 69 ++++++++++++++++++++++++++++++++ 3 files changed, 74 insertions(+) create mode 100644 tests/tcg/x86_64/adox.c diff --git a/target/i386/tcg/emit.c.inc b/target/i386/tcg/emit.c.inc index 0d7c6e80ae..e61ae9a2e9 100644 --- a/target/i386/tcg/emit.c.inc +++ b/target/i386/tcg/emit.c.inc @@ -1037,6 +1037,8 @@ static void gen_ADCOX(DisasContext *s, CPUX86State *env, MemOp ot, int cc_op) #ifdef TARGET_X86_64 case MO_32: /* If TL is 64-bit just do everything in 64-bit arithmetic. */ + tcg_gen_ext32u_tl(s->T0, s->T0); + tcg_gen_ext32u_tl(s->T1, s->T1); tcg_gen_add_i64(s->T0, s->T0, s->T1); tcg_gen_add_i64(s->T0, s->T0, carry_in); tcg_gen_shri_i64(carry_out, s->T0, 32); diff --git a/tests/tcg/x86_64/Makefile.target b/tests/tcg/x86_64/Makefile.target index 4eac78293f..e64aab1b81 100644 --- a/tests/tcg/x86_64/Makefile.target +++ b/tests/tcg/x86_64/Makefile.target @@ -12,11 +12,14 @@ ifeq ($(filter %-linux-user, $(TARGET)),$(TARGET)) X86_64_TESTS += vsyscall X86_64_TESTS += noexec X86_64_TESTS += cmpxchg +X86_64_TESTS += adox TESTS=$(MULTIARCH_TESTS) $(X86_64_TESTS) test-x86_64 else TESTS=$(MULTIARCH_TESTS) endif +adox: CFLAGS=-O2 + run-test-i386-ssse3: QEMU_OPTS += -cpu max run-plugin-test-i386-ssse3-%: QEMU_OPTS += -cpu max diff --git a/tests/tcg/x86_64/adox.c b/tests/tcg/x86_64/adox.c new file mode 100644 index 0000000000..36be644c8b --- /dev/null +++ b/tests/tcg/x86_64/adox.c @@ -0,0 +1,69 @@ +/* See if ADOX give expected results */ + +#include +#include +#include + +static uint64_t adoxq(bool *c_out, uint64_t a, uint64_t b, bool c) +{ + asm ("addl $0x7fffffff, %k1\n\t" + "adoxq %2, %0\n\t" + "seto %b1" + : "+r"(a), "=&r"(c) : "r"(b), "1"((int)c)); + *c_out = c; + return a; +} + +static uint64_t adoxl(bool *c_out, uint64_t a, uint64_t b, bool c) +{ + asm ("addl $0x7fffffff, %k1\n\t" + "adoxl %k2, %k0\n\t" + "seto %b1" + : "+r"(a), "=&r"(c) : "r"(b), "1"((int)c)); + *c_out = c; + return a; +} + +int main() +{ + uint64_t r; + bool c; + + r = adoxq(&c, 0, 0, 0); + assert(r == 0); + assert(c == 0); + + r = adoxl(&c, 0, 0, 0); + assert(r == 0); + assert(c == 0); + + r = adoxl(&c, 0x100000000, 0, 0); + assert(r == 0); + assert(c == 0); + + r = adoxq(&c, 0, 0, 1); + assert(r == 1); + assert(c == 0); + + r = adoxl(&c, 0, 0, 1); + assert(r == 1); + assert(c == 0); + + r = adoxq(&c, -1, -1, 0); + assert(r == -2); + assert(c == 1); + + r = adoxl(&c, -1, -1, 0); + assert(r == 0xfffffffe); + assert(c == 1); + + r = adoxq(&c, -1, -1, 1); + assert(r == -1); + assert(c == 1); + + r = adoxl(&c, -1, -1, 1); + assert(r == 0xffffffff); + assert(c == 1); + + return 0; +} From 3ada67a306904fe0eb3093aff9278439a0e093c8 Mon Sep 17 00:00:00 2001 From: Brad Smith Date: Sun, 18 Dec 2022 03:22:04 -0500 Subject: [PATCH 005/129] thread-posix: add support for setting threads name on OpenBSD MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make use of pthread_set_name_np() to be able to set the threads name on OpenBSD. Signed-off-by: Brad Smith Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Message-Id: Signed-off-by: Paolo Bonzini --- meson.build | 12 ++++++++++++ util/qemu-thread-posix.c | 9 ++++++++- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/meson.build b/meson.build index a76c855312..86e8ff9109 100644 --- a/meson.build +++ b/meson.build @@ -2133,6 +2133,18 @@ config_host_data.set('CONFIG_PTHREAD_SETNAME_NP_WO_TID', cc.links(gnu_source_pre pthread_create(&thread, 0, f, 0); return 0; }''', dependencies: threads)) +config_host_data.set('CONFIG_PTHREAD_SET_NAME_NP', cc.links(gnu_source_prefix + ''' + #include + #include + + static void *f(void *p) { return NULL; } + int main(void) + { + pthread_t thread; + pthread_create(&thread, 0, f, 0); + pthread_set_name_np(thread, "QEMU"); + return 0; + }''', dependencies: threads)) config_host_data.set('CONFIG_PTHREAD_CONDATTR_SETCLOCK', cc.links(gnu_source_prefix + ''' #include #include diff --git a/util/qemu-thread-posix.c b/util/qemu-thread-posix.c index bae938c670..412caa45ef 100644 --- a/util/qemu-thread-posix.c +++ b/util/qemu-thread-posix.c @@ -18,6 +18,10 @@ #include "qemu/tsan.h" #include "qemu/bitmap.h" +#ifdef CONFIG_PTHREAD_SET_NAME_NP +#include +#endif + static bool name_threads; void qemu_thread_naming(bool enable) @@ -25,7 +29,8 @@ void qemu_thread_naming(bool enable) name_threads = enable; #if !defined CONFIG_PTHREAD_SETNAME_NP_W_TID && \ - !defined CONFIG_PTHREAD_SETNAME_NP_WO_TID + !defined CONFIG_PTHREAD_SETNAME_NP_WO_TID && \ + !defined CONFIG_PTHREAD_SET_NAME_NP /* This is a debugging option, not fatal */ if (enable) { fprintf(stderr, "qemu: thread naming not supported on this host\n"); @@ -480,6 +485,8 @@ static void *qemu_thread_start(void *args) pthread_setname_np(pthread_self(), qemu_thread_args->name); # elif defined(CONFIG_PTHREAD_SETNAME_NP_WO_TID) pthread_setname_np(qemu_thread_args->name); +# elif defined(CONFIG_PTHREAD_SET_NAME_NP) + pthread_set_name_np(pthread_self(), qemu_thread_args->name); # endif } QEMU_TSAN_ANNOTATE_THREAD_NAME(qemu_thread_args->name); From 8d0efbcfa0656bef76e95d40933b6243feca58c9 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Fri, 17 Feb 2023 13:09:56 +0100 Subject: [PATCH 006/129] docs: build-platforms: refine requirements on Python build dependencies MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Historically, the critical dependency for both building and running QEMU has been the distro packages. Because QEMU is written in C and C's package management has been tied to distros (at least if you do not want to bundle libraries with the binary, otherwise I suppose you could use something like conda or wrapdb), C dependencies of QEMU would target the version that is shipped in relatively old but still commonly used distros. For non-C libraries, however, the situation is different, as these languages have their own package management tool (cpan, pip, gem, npm, and so on). For some of these languages, the amount of dependencies for even a simple program can easily balloon to the point that many distros have given up on packaging non-C code. For this reason, it has become increasingly normal for developers to download dependencies into a self-contained local environment, instead of relying on distro packages. Fortunately, this affects QEMU only at build time, as qemu.git does not package non-C artifacts such as the qemu.qmp package; but still, as we make more use of Python, we experience a clash between a support policy that is written for the C world, and dependencies (both direct and indirect) that increasingly do not care for the distro versions and are quick at moving past Python runtime versions that are declared end-of-life. For example, Python 3.6 has been EOL'd since December 2021 and Meson 0.62 (released the following March) already dropped support for it. Yet, Python 3.6 is the default version of the Python runtime for RHEL/CentOS 8 and SLE 15, respectively the penultimate and the most recent version of two distros that QEMU would like to support. (It is also the version used by Ubuntu 18.04, but QEMU stopped supporting it in April 2022). There are good reasons to move forward with the deprecation of Python 3.6 in QEMU as well: completing the configure->meson switch (which requires Meson 0.63), and making the QAPI generator fully typed (which requires newer versions of not just mypy but also Python, due to PEP563). Fortunately, these long-term support distros do include newer versions of the Python runtime. However, these more recent runtimes only come with a very small subset of the Python packages that the distro includes. Because most dependencies are optional tests (avocado, mypy, flake8) and Meson is bundled with QEMU, the most noticeably missing package is Sphinx (and the readthedocs theme). There are four possibilities: * we change the support policy and stop supporting CentOS 8 and SLE 15; not a good idea since CentOS 8 is not an unreasonable distro for us to want to continue to support * we keep supporting Python 3.6 until CentOS 8 and SLE 15 stop being supported. This is a possibility---but we may want to revise the support policy anyway because SLE 16 has not even been released, so this would mean delaying those desirable reasons for perhaps three years; * we support Python 3.6 just for building documentation, i.e. we are careful not to use Python 3.7+ features in our Sphinx extensions but are free to use them elsewhere. Besides being more complicated to understand for developers, this can be quite limiting; parts of the QAPI generator run at sphinx-build time, which would exclude one of the areas which would benefit from a newer version of the runtime; * we only support Python 3.7+, which means CentOS 8 CI and users have to either install Sphinx from pip or disable documentation. This proposed update to the support policy chooses the last of these possibilities. It does by modifying three aspects of the support policy: * it introduces different support periods for *native* vs. *non-native* dependencies. Non-native dependencies are currently Python ones only, and for simplicity the policy only mentions Python; however, the concept generalizes to other languages with a well-known upstream package manager, that users of older distributions can fetch dependencies from; * it opens up the possibility of taking non-native dependencies from their own package index instead of using the version in the distribution. The wording right now is specific to dependencies that are only required at build time. In the future we may have to refine it if, for example, parts of QEMU will be written in Rust; in that case, crates would be handled in a similar way to submodules and vendored in the release tarballs. * it mentions specifically that optional build dependencies are excluded from the platform policy. Tools such as mypy don't affect the ability to build QEMU and move fast enough that distros cannot standardize on a single version of them (for example RHEL9 does not package them at all, nor does it run them at rpmbuild time). In other cases, such as cross compilers, we have alternatives. Right now, non-native dependencies have to be download manually by running "pip" before "configure". In the future, it will be desirable for configure to set up a virtual environment and download them in the same way that it populates git submodules (but, in this case, without vendoring them in the release tarballs). Just like with submodules, this would make things easier for people that can afford accessing the network in their build environment; the option to populate the build environment manually would remain for people whose build machines lack network access. The change to the support policy neither requires nor forbids this future change. [Thanks to Daniel P. Berrangé, Peter Maydell and others for discussions that were copied or summarized in the above commit message] Cc: Markus Armbruster Cc: Peter Maydell Cc: John Snow Cc: Kevin Wolf Reviewed-by: Daniel P. Berrangé Reviewed-by: Alex Bennée Signed-off-by: Paolo Bonzini --- docs/about/build-platforms.rst | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/docs/about/build-platforms.rst b/docs/about/build-platforms.rst index 1c1e7b9e11..20b97c3310 100644 --- a/docs/about/build-platforms.rst +++ b/docs/about/build-platforms.rst @@ -86,6 +86,38 @@ respective ports repository, while NetBSD will use the pkgsrc repository. For macOS, `Homebrew`_ will be used, although `MacPorts`_ is expected to carry similar versions. +Some build dependencies may follow less conservative rules: + +Python runtime + Distributions with long-term support often provide multiple versions + of the Python runtime. While QEMU will initially aim to support the + distribution's default runtime, it may later increase its minimum version + to any newer python that is available as an option from the vendor. + In this case, it will be necessary to use the ``--python`` command line + option of the ``configure`` script to point QEMU to a supported + version of the Python runtime. + + As of QEMU |version|, the minimum supported version of Python is 3.6. + +Python build dependencies + Some of QEMU's build dependencies are written in Python. Usually these + are only packaged by distributions for the default Python runtime. + If QEMU bumps its minimum Python version and a non-default runtime is + required, it may be necessary to fetch python modules from the Python + Package Index (PyPI) via ``pip``, in order to build QEMU. + +Optional build dependencies + Build components whose absence does not affect the ability to build + QEMU may not be available in distros, or may be too old for QEMU's + requirements. Many of these, such as the Avocado testing framework + or various linters, are written in Python and therefore can also + be installed using ``pip``. Cross compilers are another example + of optional build-time dependency; in this case it is possible to + download them from repositories such as EPEL, to use container-based + cross compilation using ``docker`` or ``podman``, or to use pre-built + binaries distributed with QEMU. + + Windows ------- From 49be78ca02a687ea00ad7534254217b479a4e92d Mon Sep 17 00:00:00 2001 From: TaiseiIto Date: Mon, 19 Dec 2022 13:04:12 +0900 Subject: [PATCH 007/129] target/i386/gdbstub: Fix a bug about order of FPU stack in 'g' packets. Before this commit, when GDB attached an OS working on QEMU, order of FPU stack registers printed by GDB command 'info float' was wrong. There was a bug causing the problem in 'g' packets sent by QEMU to GDB. The packets have values of registers of machine emulated by QEMU containing FPU stack registers. There are 2 ways to specify a x87 FPU stack register. The first is specifying by absolute indexed register names (R0, ..., R7). The second is specifying by stack top relative indexed register names (ST0, ..., ST7). Values of the FPU stack registers should be located in 'g' packet and be ordered by the relative index. But QEMU had located these registers ordered by the absolute index. After this commit, when QEMU reads registers to make a 'g' packet, QEMU specifies FPU stack registers by the relative index. Then, the registers are ordered correctly in the packet. As a result, GDB, the packet receiver, can print FPU stack registers in the correct order. Signed-off-by: TaiseiIto Reviewed-by: Richard Henderson Message-Id: Signed-off-by: Paolo Bonzini --- target/i386/gdbstub.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/target/i386/gdbstub.c b/target/i386/gdbstub.c index c3a2cf6f28..786971284a 100644 --- a/target/i386/gdbstub.c +++ b/target/i386/gdbstub.c @@ -121,7 +121,9 @@ int x86_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n) return gdb_get_reg32(mem_buf, env->regs[gpr_map32[n]]); } } else if (n >= IDX_FP_REGS && n < IDX_FP_REGS + 8) { - floatx80 *fp = (floatx80 *) &env->fpregs[n - IDX_FP_REGS]; + int st_index = n - IDX_FP_REGS; + int r_index = (st_index + env->fpstt) % 8; + floatx80 *fp = &env->fpregs[r_index].d; int len = gdb_get_reg64(mem_buf, cpu_to_le64(fp->low)); len += gdb_get_reg16(mem_buf, cpu_to_le16(fp->high)); return len; From 2627e4524ea6c6ba14f9d6b298e08c9d4d3cc4fe Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 6 Feb 2023 09:26:29 -1000 Subject: [PATCH 008/129] accel/tcg: Allow the second page of an instruction to be MMIO MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If an instruction straddles a page boundary, and the first page was ram, but the second page was MMIO, we would abort. Handle this as if both pages are MMIO, by setting the ram_addr_t for the first page to -1. Reported-by: Sid Manning Reported-by: Jørgen Hansen Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Richard Henderson --- accel/tcg/translator.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/accel/tcg/translator.c b/accel/tcg/translator.c index ef5193c67e..1cf404ced0 100644 --- a/accel/tcg/translator.c +++ b/accel/tcg/translator.c @@ -176,8 +176,16 @@ static void *translator_access(CPUArchState *env, DisasContextBase *db, if (host == NULL) { tb_page_addr_t phys_page = get_page_addr_code_hostp(env, base, &db->host_addr[1]); - /* We cannot handle MMIO as second page. */ - assert(phys_page != -1); + + /* + * If the second page is MMIO, treat as if the first page + * was MMIO as well, so that we do not cache the TB. + */ + if (unlikely(phys_page == -1)) { + tb_set_page_addr0(tb, -1); + return NULL; + } + tb_set_page_addr1(tb, phys_page); #ifdef CONFIG_USER_ONLY page_protect(end); From 21a474c41d18eb56186e2022e8e081c2b6011bd3 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Wed, 1 Feb 2023 10:56:15 -1000 Subject: [PATCH 009/129] linux-user/sparc: Raise SIGILL for all unhandled software traps The linux kernel's trap tables vector all unassigned trap numbers to BAD_TRAP, which then raises SIGILL. Tested-by: Ilya Leoshkevich Reported-by: Ilya Leoshkevich Signed-off-by: Richard Henderson --- linux-user/sparc/cpu_loop.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/linux-user/sparc/cpu_loop.c b/linux-user/sparc/cpu_loop.c index 434c90a55f..c120c42278 100644 --- a/linux-user/sparc/cpu_loop.c +++ b/linux-user/sparc/cpu_loop.c @@ -248,6 +248,14 @@ void cpu_loop (CPUSPARCState *env) cpu_exec_step_atomic(cs); break; default: + /* + * Most software trap numbers vector to BAD_TRAP. + * Handle anything not explicitly matched above. + */ + if (trapnr >= TT_TRAP && trapnr <= TT_TRAP + 0x7f) { + force_sig_fault(TARGET_SIGILL, ILL_ILLTRP, env->pc); + break; + } fprintf(stderr, "Unhandled trap: 0x%x\n", trapnr); cpu_dump_state(cs, stderr, 0); exit(EXIT_FAILURE); From 7de0816f699553514016f52a76e26d1c2ae14034 Mon Sep 17 00:00:00 2001 From: Ilya Leoshkevich Date: Tue, 14 Feb 2023 15:08:26 +0100 Subject: [PATCH 010/129] linux-user: Always exit from exclusive state in fork_end() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fork()ed processes currently start with current_cpu->in_exclusive_context set, which is, strictly speaking, not correct, but does not cause problems (even assertion failures). With one of the next patches, the code begins to rely on this value, so fix it by always calling end_exclusive() in fork_end(). Reviewed-by: Richard Henderson Reviewed-by: Alex Bennée Signed-off-by: Ilya Leoshkevich Message-Id: <20230214140829.45392-2-iii@linux.ibm.com> Signed-off-by: Richard Henderson --- linux-user/main.c | 10 ++++++---- linux-user/syscall.c | 1 + 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/linux-user/main.c b/linux-user/main.c index 4290651c3c..4ff30ff980 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -161,13 +161,15 @@ void fork_end(int child) } qemu_init_cpu_list(); gdbserver_fork(thread_cpu); - /* qemu_init_cpu_list() takes care of reinitializing the - * exclusive state, so we don't need to end_exclusive() here. - */ } else { cpu_list_unlock(); - end_exclusive(); } + /* + * qemu_init_cpu_list() reinitialized the child exclusive state, but we + * also need to keep current_cpu consistent, so call end_exclusive() for + * both child and parent. + */ + end_exclusive(); } __thread CPUState *thread_cpu; diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 1e868e9b0e..a6c426d73c 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -6752,6 +6752,7 @@ static int do_fork(CPUArchState *env, unsigned int flags, abi_ulong newsp, cpu_clone_regs_parent(env, flags); fork_end(0); } + g_assert(!cpu_in_exclusive_context(cpu)); } return ret; } From df8a688032280ecd07ace7c6fbc70f5650cca9af Mon Sep 17 00:00:00 2001 From: Ilya Leoshkevich Date: Tue, 14 Feb 2023 15:08:27 +0100 Subject: [PATCH 011/129] cpus: Make {start,end}_exclusive() recursive MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently dying to one of the core_dump_signal()s deadlocks, because dump_core_and_abort() calls start_exclusive() two times: first via stop_all_tasks(), and then via preexit_cleanup() -> qemu_plugin_user_exit(). There are a number of ways to solve this: resume after dumping core; check cpu_in_exclusive_context() in qemu_plugin_user_exit(); or make {start,end}_exclusive() recursive. Pick the last option, since it's the most straightforward one. Fixes: da91c1920242 ("linux-user: Clean up when exiting due to a signal") Reviewed-by: Richard Henderson Reviewed-by: Alex Bennée Signed-off-by: Ilya Leoshkevich Message-Id: <20230214140829.45392-3-iii@linux.ibm.com> Signed-off-by: Richard Henderson --- cpus-common.c | 12 ++++++++++-- include/hw/core/cpu.h | 4 ++-- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/cpus-common.c b/cpus-common.c index 793364dc0e..39f355de98 100644 --- a/cpus-common.c +++ b/cpus-common.c @@ -192,6 +192,11 @@ void start_exclusive(void) CPUState *other_cpu; int running_cpus; + if (current_cpu->exclusive_context_count) { + current_cpu->exclusive_context_count++; + return; + } + qemu_mutex_lock(&qemu_cpu_list_lock); exclusive_idle(); @@ -219,13 +224,16 @@ void start_exclusive(void) */ qemu_mutex_unlock(&qemu_cpu_list_lock); - current_cpu->in_exclusive_context = true; + current_cpu->exclusive_context_count = 1; } /* Finish an exclusive operation. */ void end_exclusive(void) { - current_cpu->in_exclusive_context = false; + current_cpu->exclusive_context_count--; + if (current_cpu->exclusive_context_count) { + return; + } qemu_mutex_lock(&qemu_cpu_list_lock); qatomic_set(&pending_cpus, 0); diff --git a/include/hw/core/cpu.h b/include/hw/core/cpu.h index 2417597236..671f041bec 100644 --- a/include/hw/core/cpu.h +++ b/include/hw/core/cpu.h @@ -349,7 +349,7 @@ struct CPUState { bool unplug; bool crash_occurred; bool exit_request; - bool in_exclusive_context; + int exclusive_context_count; uint32_t cflags_next_tb; /* updates protected by BQL */ uint32_t interrupt_request; @@ -758,7 +758,7 @@ void async_safe_run_on_cpu(CPUState *cpu, run_on_cpu_func func, run_on_cpu_data */ static inline bool cpu_in_exclusive_context(const CPUState *cpu) { - return cpu->in_exclusive_context; + return cpu->exclusive_context_count; } /** From d7d5601c788b7972d7e62ce2e8af4587db9e2da1 Mon Sep 17 00:00:00 2001 From: Ilya Leoshkevich Date: Tue, 14 Feb 2023 15:08:28 +0100 Subject: [PATCH 012/129] linux-user/microblaze: Handle privileged exception Follow what kernel's full_exception() is doing. Reviewed-by: Richard Henderson Signed-off-by: Ilya Leoshkevich Message-Id: <20230214140829.45392-4-iii@linux.ibm.com> Signed-off-by: Richard Henderson --- linux-user/microblaze/cpu_loop.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/linux-user/microblaze/cpu_loop.c b/linux-user/microblaze/cpu_loop.c index 5ccf9e942e..212e62d0a6 100644 --- a/linux-user/microblaze/cpu_loop.c +++ b/linux-user/microblaze/cpu_loop.c @@ -25,8 +25,8 @@ void cpu_loop(CPUMBState *env) { + int trapnr, ret, si_code, sig; CPUState *cs = env_cpu(env); - int trapnr, ret, si_code; while (1) { cpu_exec_start(cs); @@ -76,6 +76,7 @@ void cpu_loop(CPUMBState *env) env->iflags &= ~(IMM_FLAG | D_FLAG); switch (env->esr & 31) { case ESR_EC_DIVZERO: + sig = TARGET_SIGFPE; si_code = TARGET_FPE_INTDIV; break; case ESR_EC_FPU: @@ -84,6 +85,7 @@ void cpu_loop(CPUMBState *env) * if there's no recognized bit set. Possibly this * implies that si_code is 0, but follow the structure. */ + sig = TARGET_SIGFPE; si_code = env->fsr; if (si_code & FSR_IO) { si_code = TARGET_FPE_FLTINV; @@ -97,13 +99,17 @@ void cpu_loop(CPUMBState *env) si_code = TARGET_FPE_FLTRES; } break; + case ESR_EC_PRIVINSN: + sig = SIGILL; + si_code = ILL_PRVOPC; + break; default: fprintf(stderr, "Unhandled hw-exception: 0x%x\n", env->esr & ESR_EC_MASK); cpu_dump_state(cs, stderr, 0); exit(EXIT_FAILURE); } - force_sig_fault(TARGET_SIGFPE, si_code, env->pc); + force_sig_fault(sig, si_code, env->pc); break; case EXCP_DEBUG: From c3bef3b4de8e60affa6aa3a46dcfcf3bd09459a1 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 30 Dec 2022 07:54:58 -0800 Subject: [PATCH 013/129] target/microblaze: Add gdbstub xml Mirroring the upstream gdb xml files, the two stack boundary registers are separated out. Reviewed-by: Edgar E. Iglesias Signed-off-by: Richard Henderson --- configs/targets/microblaze-linux-user.mak | 1 + configs/targets/microblaze-softmmu.mak | 1 + configs/targets/microblazeel-linux-user.mak | 1 + configs/targets/microblazeel-softmmu.mak | 1 + gdb-xml/microblaze-core.xml | 67 +++++++++++++++++++++ gdb-xml/microblaze-stack-protect.xml | 12 ++++ target/microblaze/cpu.c | 7 ++- target/microblaze/cpu.h | 2 + target/microblaze/gdbstub.c | 51 +++++++++++----- 9 files changed, 128 insertions(+), 15 deletions(-) create mode 100644 gdb-xml/microblaze-core.xml create mode 100644 gdb-xml/microblaze-stack-protect.xml diff --git a/configs/targets/microblaze-linux-user.mak b/configs/targets/microblaze-linux-user.mak index 4249a37f65..0a2322c249 100644 --- a/configs/targets/microblaze-linux-user.mak +++ b/configs/targets/microblaze-linux-user.mak @@ -3,3 +3,4 @@ TARGET_SYSTBL_ABI=common TARGET_SYSTBL=syscall.tbl TARGET_BIG_ENDIAN=y TARGET_HAS_BFLT=y +TARGET_XML_FILES=gdb-xml/microblaze-core.xml gdb-xml/microblaze-stack-protect.xml diff --git a/configs/targets/microblaze-softmmu.mak b/configs/targets/microblaze-softmmu.mak index 8385e2d333..e84c0cc728 100644 --- a/configs/targets/microblaze-softmmu.mak +++ b/configs/targets/microblaze-softmmu.mak @@ -2,3 +2,4 @@ TARGET_ARCH=microblaze TARGET_BIG_ENDIAN=y TARGET_SUPPORTS_MTTCG=y TARGET_NEED_FDT=y +TARGET_XML_FILES=gdb-xml/microblaze-core.xml gdb-xml/microblaze-stack-protect.xml diff --git a/configs/targets/microblazeel-linux-user.mak b/configs/targets/microblazeel-linux-user.mak index d0e775d840..270743156a 100644 --- a/configs/targets/microblazeel-linux-user.mak +++ b/configs/targets/microblazeel-linux-user.mak @@ -2,3 +2,4 @@ TARGET_ARCH=microblaze TARGET_SYSTBL_ABI=common TARGET_SYSTBL=syscall.tbl TARGET_HAS_BFLT=y +TARGET_XML_FILES=gdb-xml/microblaze-core.xml gdb-xml/microblaze-stack-protect.xml diff --git a/configs/targets/microblazeel-softmmu.mak b/configs/targets/microblazeel-softmmu.mak index af40391f2f..9b688036bd 100644 --- a/configs/targets/microblazeel-softmmu.mak +++ b/configs/targets/microblazeel-softmmu.mak @@ -1,3 +1,4 @@ TARGET_ARCH=microblaze TARGET_SUPPORTS_MTTCG=y TARGET_NEED_FDT=y +TARGET_XML_FILES=gdb-xml/microblaze-core.xml gdb-xml/microblaze-stack-protect.xml diff --git a/gdb-xml/microblaze-core.xml b/gdb-xml/microblaze-core.xml new file mode 100644 index 0000000000..becf77c89c --- /dev/null +++ b/gdb-xml/microblaze-core.xml @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gdb-xml/microblaze-stack-protect.xml b/gdb-xml/microblaze-stack-protect.xml new file mode 100644 index 0000000000..997301e8a2 --- /dev/null +++ b/gdb-xml/microblaze-stack-protect.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/target/microblaze/cpu.c b/target/microblaze/cpu.c index 817681f9b2..a2d2f5c340 100644 --- a/target/microblaze/cpu.c +++ b/target/microblaze/cpu.c @@ -28,6 +28,7 @@ #include "qemu/module.h" #include "hw/qdev-properties.h" #include "exec/exec-all.h" +#include "exec/gdbstub.h" #include "fpu/softfloat-helpers.h" static const struct { @@ -294,6 +295,9 @@ static void mb_cpu_initfn(Object *obj) CPUMBState *env = &cpu->env; cpu_set_cpustate_pointers(cpu); + gdb_register_coprocessor(CPU(cpu), mb_cpu_gdb_read_stack_protect, + mb_cpu_gdb_write_stack_protect, 2, + "microblaze-stack-protect.xml", 0); set_float_rounding_mode(float_round_nearest_even, &env->fp_status); @@ -422,7 +426,8 @@ static void mb_cpu_class_init(ObjectClass *oc, void *data) cc->sysemu_ops = &mb_sysemu_ops; #endif device_class_set_props(dc, mb_properties); - cc->gdb_num_core_regs = 32 + 27; + cc->gdb_num_core_regs = 32 + 25; + cc->gdb_core_xml_file = "microblaze-core.xml"; cc->disas_set_info = mb_disas_set_info; cc->tcg_ops = &mb_tcg_ops; diff --git a/target/microblaze/cpu.h b/target/microblaze/cpu.h index 1e84dd8f47..e541fbb0b3 100644 --- a/target/microblaze/cpu.h +++ b/target/microblaze/cpu.h @@ -367,6 +367,8 @@ hwaddr mb_cpu_get_phys_page_attrs_debug(CPUState *cpu, vaddr addr, MemTxAttrs *attrs); int mb_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg); int mb_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg); +int mb_cpu_gdb_read_stack_protect(CPUArchState *cpu, GByteArray *buf, int reg); +int mb_cpu_gdb_write_stack_protect(CPUArchState *cpu, uint8_t *buf, int reg); static inline uint32_t mb_cpu_read_msr(const CPUMBState *env) { diff --git a/target/microblaze/gdbstub.c b/target/microblaze/gdbstub.c index 2e6e070051..8143fcae88 100644 --- a/target/microblaze/gdbstub.c +++ b/target/microblaze/gdbstub.c @@ -39,8 +39,11 @@ enum { GDB_PVR0 = 32 + 6, GDB_PVR11 = 32 + 17, GDB_EDR = 32 + 18, - GDB_SLR = 32 + 25, - GDB_SHR = 32 + 26, +}; + +enum { + GDB_SP_SHL, + GDB_SP_SHR, }; int mb_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n) @@ -83,12 +86,6 @@ int mb_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n) case GDB_EDR: val = env->edr; break; - case GDB_SLR: - val = env->slr; - break; - case GDB_SHR: - val = env->shr; - break; default: /* Other SRegs aren't modeled, so report a value of 0 */ val = 0; @@ -97,6 +94,23 @@ int mb_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n) return gdb_get_reg32(mem_buf, val); } +int mb_cpu_gdb_read_stack_protect(CPUMBState *env, GByteArray *mem_buf, int n) +{ + uint32_t val; + + switch (n) { + case GDB_SP_SHL: + val = env->slr; + break; + case GDB_SP_SHR: + val = env->shr; + break; + default: + return 0; + } + return gdb_get_reg32(mem_buf, val); +} + int mb_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n) { MicroBlazeCPU *cpu = MICROBLAZE_CPU(cs); @@ -135,12 +149,21 @@ int mb_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n) case GDB_EDR: env->edr = tmp; break; - case GDB_SLR: - env->slr = tmp; - break; - case GDB_SHR: - env->shr = tmp; - break; + } + return 4; +} + +int mb_cpu_gdb_write_stack_protect(CPUMBState *env, uint8_t *mem_buf, int n) +{ + switch (n) { + case GDB_SP_SHL: + env->slr = ldl_p(mem_buf); + break; + case GDB_SP_SHR: + env->shr = ldl_p(mem_buf); + break; + default: + return 0; } return 4; } From b3c326029554a7d134e26e749240ba2d8ac288b1 Mon Sep 17 00:00:00 2001 From: Pierrick Bouvier Date: Tue, 21 Feb 2023 16:30:03 +0100 Subject: [PATCH 014/129] util/cacheflush: fix cache on windows-arm64 ctr_el0 access is privileged on this platform and fails as an illegal instruction. Windows does not offer a way to flush data cache from userspace, and only FlushInstructionCache is available in Windows API. The generic implementation of flush_idcache_range uses, __builtin___clear_cache, which already use the FlushInstructionCache function. So we rely on that. Signed-off-by: Pierrick Bouvier Reviewed-by: Richard Henderson Message-Id: <20230221153006.20300-2-pierrick.bouvier@linaro.org> Signed-off-by: Richard Henderson --- util/cacheflush.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/util/cacheflush.c b/util/cacheflush.c index 2c2c73e085..06c2333a60 100644 --- a/util/cacheflush.c +++ b/util/cacheflush.c @@ -121,8 +121,12 @@ static void sys_cache_info(int *isize, int *dsize) static bool have_coherent_icache; #endif -#if defined(__aarch64__) && !defined(CONFIG_DARWIN) -/* Apple does not expose CTR_EL0, so we must use system interfaces. */ +#if defined(__aarch64__) && !defined(CONFIG_DARWIN) && !defined(CONFIG_WIN32) +/* + * Apple does not expose CTR_EL0, so we must use system interfaces. + * Windows neither, but we use a generic implementation of flush_idcache_range + * in this case. + */ static uint64_t save_ctr_el0; static void arch_cache_info(int *isize, int *dsize) { @@ -225,7 +229,11 @@ static void __attribute__((constructor)) init_cache_info(void) /* Caches are coherent and do not require flushing; symbol inline. */ -#elif defined(__aarch64__) +#elif defined(__aarch64__) && !defined(CONFIG_WIN32) +/* + * For Windows, we use generic implementation of flush_idcache_range, that + * performs a call to FlushInstructionCache, through __builtin___clear_cache. + */ #ifdef CONFIG_DARWIN /* Apple does not expose CTR_EL0, so we must use system interfaces. */ From dbd672c87f19949bb62bfb1fb3a97b9729fd7560 Mon Sep 17 00:00:00 2001 From: Pierrick Bouvier Date: Tue, 21 Feb 2023 16:30:04 +0100 Subject: [PATCH 015/129] sysemu/os-win32: fix setjmp/longjmp on windows-arm64 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Windows implementation of setjmp/longjmp is done in C:/WINDOWS/system32/ucrtbase.dll. Alas, on arm64, it seems to *always* perform stack unwinding, which crashes from generated code. By using alternative implementation built in mingw, we avoid doing stack unwinding and this fixes crash when calling longjmp. Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Pierrick Bouvier Acked-by: Richard Henderson Message-Id: <20230221153006.20300-3-pierrick.bouvier@linaro.org> Signed-off-by: Richard Henderson --- include/sysemu/os-win32.h | 28 ++++++++++++++++++++++++---- meson.build | 21 +++++++++++++++++++++ 2 files changed, 45 insertions(+), 4 deletions(-) diff --git a/include/sysemu/os-win32.h b/include/sysemu/os-win32.h index 5b38c7bd04..97d0243aee 100644 --- a/include/sysemu/os-win32.h +++ b/include/sysemu/os-win32.h @@ -51,14 +51,34 @@ typedef struct sockaddr_un { extern "C" { #endif -#if defined(_WIN64) -/* On w64, setjmp is implemented by _setjmp which needs a second parameter. +#if defined(__aarch64__) +/* + * On windows-arm64, setjmp is available in only one variant, and longjmp always + * does stack unwinding. This crash with generated code. + * Thus, we use another implementation of setjmp (not windows one), coming from + * mingw, which never performs stack unwinding. + */ +#undef setjmp +#undef longjmp +/* + * These functions are not declared in setjmp.h because __aarch64__ defines + * setjmp to _setjmpex instead. However, they are still defined in libmingwex.a, + * which gets linked automatically. + */ +extern int __mingw_setjmp(jmp_buf); +extern void __attribute__((noreturn)) __mingw_longjmp(jmp_buf, int); +#define setjmp(env) __mingw_setjmp(env) +#define longjmp(env, val) __mingw_longjmp(env, val) +#elif defined(_WIN64) +/* + * On windows-x64, setjmp is implemented by _setjmp which needs a second parameter. * If this parameter is NULL, longjump does no stack unwinding. * That is what we need for QEMU. Passing the value of register rsp (default) - * lets longjmp try a stack unwinding which will crash with generated code. */ + * lets longjmp try a stack unwinding which will crash with generated code. + */ # undef setjmp # define setjmp(env) _setjmp(env, NULL) -#endif +#endif /* __aarch64__ */ /* QEMU uses sigsetjmp()/siglongjmp() as the portable way to specify * "longjmp and don't touch the signal masks". Since we know that the * savemask parameter will always be zero we can safely define these diff --git a/meson.build b/meson.build index bc7e5b1d15..6a139e7085 100644 --- a/meson.build +++ b/meson.build @@ -2466,6 +2466,27 @@ if targetos == 'windows' }''', name: '_lock_file and _unlock_file')) endif +if targetos == 'windows' + mingw_has_setjmp_longjmp = cc.links(''' + #include + int main(void) { + /* + * These functions are not available in setjmp header, but may be + * available at link time, from libmingwex.a. + */ + extern int __mingw_setjmp(jmp_buf); + extern void __attribute__((noreturn)) __mingw_longjmp(jmp_buf, int); + jmp_buf env; + __mingw_setjmp(env); + __mingw_longjmp(env, 0); + } + ''', name: 'mingw setjmp and longjmp') + + if cpu == 'aarch64' and not mingw_has_setjmp_longjmp + error('mingw must provide setjmp/longjmp for windows-arm64') + endif +endif + ######################## # Target configuration # ######################## From aef633e76504f6f2f3be47a22b271ce6469c0d9d Mon Sep 17 00:00:00 2001 From: John Snow Date: Thu, 9 Feb 2023 19:31:41 -0500 Subject: [PATCH 016/129] python: support pylint 2.16 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pylint 2.16 adds a few new checks that cause the optional check-tox CI job to fail. 1. The superfluous-parens check seems to be a bit more aggressive, 2. broad-exception-raised is new; it discourages "raise Exception". Fix these minor issues and turn the lights green. Signed-off-by: John Snow Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Beraldo Leal Message-id: 20230210003147.1309376-2-jsnow@redhat.com Signed-off-by: John Snow --- python/qemu/qmp/protocol.py | 2 +- python/qemu/qmp/qmp_client.py | 2 +- python/qemu/utils/qemu_ga_client.py | 6 +++--- tests/qemu-iotests/iotests.py | 4 ++-- tests/qemu-iotests/tests/migrate-bitmaps-postcopy-test | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/python/qemu/qmp/protocol.py b/python/qemu/qmp/protocol.py index 6d3d739daa..22e60298d2 100644 --- a/python/qemu/qmp/protocol.py +++ b/python/qemu/qmp/protocol.py @@ -207,7 +207,7 @@ class AsyncProtocol(Generic[T]): logger = logging.getLogger(__name__) # Maximum allowable size of read buffer - _limit = (64 * 1024) + _limit = 64 * 1024 # ------------------------- # Section: Public interface diff --git a/python/qemu/qmp/qmp_client.py b/python/qemu/qmp/qmp_client.py index b5772e7f32..9d73ae6e7a 100644 --- a/python/qemu/qmp/qmp_client.py +++ b/python/qemu/qmp/qmp_client.py @@ -198,7 +198,7 @@ class QMPClient(AsyncProtocol[Message], Events): logger = logging.getLogger(__name__) # Read buffer limit; 10MB like libvirt default - _limit = (10 * 1024 * 1024) + _limit = 10 * 1024 * 1024 # Type alias for pending execute() result items _PendingT = Union[Message, ExecInterruptedError] diff --git a/python/qemu/utils/qemu_ga_client.py b/python/qemu/utils/qemu_ga_client.py index 8c38a7ac9c..d8411bb2d0 100644 --- a/python/qemu/utils/qemu_ga_client.py +++ b/python/qemu/utils/qemu_ga_client.py @@ -155,7 +155,7 @@ class QemuGuestAgentClient: def fsfreeze(self, cmd: str) -> object: if cmd not in ['status', 'freeze', 'thaw']: - raise Exception('Invalid command: ' + cmd) + raise ValueError('Invalid command: ' + cmd) # Can be int (freeze, thaw) or GuestFsfreezeStatus (status) return getattr(self.qga, 'fsfreeze' + '_' + cmd)() @@ -167,7 +167,7 @@ class QemuGuestAgentClient: def suspend(self, mode: str) -> None: if mode not in ['disk', 'ram', 'hybrid']: - raise Exception('Invalid mode: ' + mode) + raise ValueError('Invalid mode: ' + mode) try: getattr(self.qga, 'suspend' + '_' + mode)() @@ -178,7 +178,7 @@ class QemuGuestAgentClient: def shutdown(self, mode: str = 'powerdown') -> None: if mode not in ['powerdown', 'halt', 'reboot']: - raise Exception('Invalid mode: ' + mode) + raise ValueError('Invalid mode: ' + mode) try: self.qga.shutdown(mode=mode) diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py index 94aeb3f3b2..3e82c634cf 100644 --- a/tests/qemu-iotests/iotests.py +++ b/tests/qemu-iotests/iotests.py @@ -720,7 +720,7 @@ class Timeout: signal.setitimer(signal.ITIMER_REAL, 0) return False def timeout(self, signum, frame): - raise Exception(self.errmsg) + raise TimeoutError(self.errmsg) def file_pattern(name): return "{0}-{1}".format(os.getpid(), name) @@ -804,7 +804,7 @@ def remote_filename(path): elif imgproto == 'ssh': return "ssh://%s@127.0.0.1:22%s" % (os.environ.get('USER'), path) else: - raise Exception("Protocol %s not supported" % (imgproto)) + raise ValueError("Protocol %s not supported" % (imgproto)) class VM(qtest.QEMUQtestMachine): '''A QEMU VM''' diff --git a/tests/qemu-iotests/tests/migrate-bitmaps-postcopy-test b/tests/qemu-iotests/tests/migrate-bitmaps-postcopy-test index fc9c4b4ef4..dda55fad28 100755 --- a/tests/qemu-iotests/tests/migrate-bitmaps-postcopy-test +++ b/tests/qemu-iotests/tests/migrate-bitmaps-postcopy-test @@ -84,7 +84,7 @@ class TestDirtyBitmapPostcopyMigration(iotests.QMPTestCase): e['vm'] = 'SRC' for e in self.vm_b_events: e['vm'] = 'DST' - events = (self.vm_a_events + self.vm_b_events) + events = self.vm_a_events + self.vm_b_events events = [(e['timestamp']['seconds'], e['timestamp']['microseconds'], e['vm'], From 6832189fd791622c30e7bbe3a12b76be14dc1158 Mon Sep 17 00:00:00 2001 From: John Snow Date: Thu, 9 Feb 2023 19:31:42 -0500 Subject: [PATCH 017/129] python: drop pipenv The pipenv tool was nice in theory, but in practice it's just too hard to update selectively, and it makes using it a pain. The qemu.qmp repo dropped pipenv support a while back and it's been functioning just fine, so I'm backporting that change here to qemu.git. Signed-off-by: John Snow Message-id: 20230210003147.1309376-3-jsnow@redhat.com Signed-off-by: John Snow --- .gitlab-ci.d/static_checks.yml | 4 +- python/.gitignore | 4 +- python/Makefile | 53 ++-- python/Pipfile | 13 - python/Pipfile.lock | 347 ------------------------- python/README.rst | 3 - python/setup.cfg | 4 +- python/tests/minreqs.txt | 45 ++++ tests/docker/dockerfiles/python.docker | 1 - 9 files changed, 86 insertions(+), 388 deletions(-) delete mode 100644 python/Pipfile delete mode 100644 python/Pipfile.lock create mode 100644 python/tests/minreqs.txt diff --git a/.gitlab-ci.d/static_checks.yml b/.gitlab-ci.d/static_checks.yml index 289ad1359e..b4cbdbce2a 100644 --- a/.gitlab-ci.d/static_checks.yml +++ b/.gitlab-ci.d/static_checks.yml @@ -23,12 +23,12 @@ check-dco: before_script: - apk -U add git -check-python-pipenv: +check-python-minreqs: extends: .base_job_template stage: test image: $CI_REGISTRY_IMAGE/qemu/python:latest script: - - make -C python check-pipenv + - make -C python check-minreqs variables: GIT_DEPTH: 1 needs: diff --git a/python/.gitignore b/python/.gitignore index 904f324bb1..c3ceb1ca0a 100644 --- a/python/.gitignore +++ b/python/.gitignore @@ -11,8 +11,8 @@ qemu.egg-info/ .idea/ .vscode/ -# virtual environments (pipenv et al) -.venv/ +# virtual environments +.min-venv/ .tox/ .dev-venv/ diff --git a/python/Makefile b/python/Makefile index b170708398..c5bd6ff83a 100644 --- a/python/Makefile +++ b/python/Makefile @@ -1,15 +1,16 @@ QEMU_VENV_DIR=.dev-venv +QEMU_MINVENV_DIR=.min-venv QEMU_TOX_EXTRA_ARGS ?= .PHONY: help help: @echo "python packaging help:" @echo "" - @echo "make check-pipenv:" - @echo " Run tests in pipenv's virtual environment." + @echo "make check-minreqs:" + @echo " Run tests in the minreqs virtual environment." @echo " These tests use the oldest dependencies." - @echo " Requires: Python 3.6 and pipenv." - @echo " Hint (Fedora): 'sudo dnf install python3.6 pipenv'" + @echo " Requires: Python 3.6" + @echo " Hint (Fedora): 'sudo dnf install python3.6'" @echo "" @echo "make check-tox:" @echo " Run tests against multiple python versions." @@ -33,8 +34,8 @@ help: @echo " and install the qemu package in editable mode." @echo " (Can be used in or outside of a venv.)" @echo "" - @echo "make pipenv" - @echo " Creates pipenv's virtual environment (.venv)" + @echo "make min-venv" + @echo " Creates the minreqs virtual environment ($(QEMU_MINVENV_DIR))" @echo "" @echo "make dev-venv" @echo " Creates a simple venv for check-dev. ($(QEMU_VENV_DIR))" @@ -43,21 +44,38 @@ help: @echo " Remove package build output." @echo "" @echo "make distclean:" - @echo " remove pipenv/venv files, qemu package forwarder," + @echo " remove venv files, qemu package forwarder," @echo " built distribution files, and everything from 'make clean'." @echo "" @echo -e "Have a nice day ^_^\n" -.PHONY: pipenv -pipenv: .venv -.venv: Pipfile.lock - @PIPENV_VENV_IN_PROJECT=1 pipenv sync --dev --keep-outdated - rm -f pyproject.toml - @touch .venv +.PHONY: pipenv check-pipenv +pipenv check-pipenv: + @echo "pipenv was dropped; try 'make check-minreqs' or 'make min-venv'" + @exit 1 -.PHONY: check-pipenv -check-pipenv: pipenv - @pipenv run make check +.PHONY: min-venv +min-venv: $(QEMU_MINVENV_DIR) $(QEMU_MINVENV_DIR)/bin/activate +$(QEMU_MINVENV_DIR) $(QEMU_MINVENV_DIR)/bin/activate: setup.cfg tests/minreqs.txt + @echo "VENV $(QEMU_MINVENV_DIR)" + @python3.6 -m venv $(QEMU_MINVENV_DIR) + @( \ + echo "ACTIVATE $(QEMU_MINVENV_DIR)"; \ + . $(QEMU_MINVENV_DIR)/bin/activate; \ + echo "INSTALL -r tests/minreqs.txt $(QEMU_MINVENV_DIR)";\ + pip install -r tests/minreqs.txt 1>/dev/null; \ + echo "INSTALL -e qemu $(QEMU_MINVENV_DIR)"; \ + pip install -e . 1>/dev/null; \ + ) + @touch $(QEMU_MINVENV_DIR) + +.PHONY: check-minreqs +check-minreqs: min-venv + @( \ + echo "ACTIVATE $(QEMU_MINVENV_DIR)"; \ + . $(QEMU_MINVENV_DIR)/bin/activate; \ + make check; \ + ) .PHONY: dev-venv dev-venv: $(QEMU_VENV_DIR) $(QEMU_VENV_DIR)/bin/activate @@ -106,6 +124,7 @@ clean: .PHONY: distclean distclean: clean - rm -rf qemu.egg-info/ .venv/ .tox/ $(QEMU_VENV_DIR) dist/ + rm -rf qemu.egg-info/ .eggs/ dist/ + rm -rf $(QEMU_VENV_DIR) $(QEMU_MINVENV_DIR) .tox/ rm -f .coverage .coverage.* rm -rf htmlcov/ diff --git a/python/Pipfile b/python/Pipfile deleted file mode 100644 index e7acb8cefa..0000000000 --- a/python/Pipfile +++ /dev/null @@ -1,13 +0,0 @@ -[[source]] -name = "pypi" -url = "https://pypi.org/simple" -verify_ssl = true - -[dev-packages] -qemu = {editable = true, extras = ["devel"], path = "."} - -[packages] -qemu = {editable = true,path = "."} - -[requires] -python_version = "3.6" diff --git a/python/Pipfile.lock b/python/Pipfile.lock deleted file mode 100644 index ce46404ce0..0000000000 --- a/python/Pipfile.lock +++ /dev/null @@ -1,347 +0,0 @@ -{ - "_meta": { - "hash": { - "sha256": "f1a25654d884a5b450e38d78b1f2e3ebb9073e421cc4358d4bbb83ac251a5670" - }, - "pipfile-spec": 6, - "requires": { - "python_version": "3.6" - }, - "sources": [ - { - "name": "pypi", - "url": "https://pypi.org/simple", - "verify_ssl": true - } - ] - }, - "default": { - "qemu": { - "editable": true, - "path": "." - } - }, - "develop": { - "appdirs": { - "hashes": [ - "sha256:7d5d0167b2b1ba821647616af46a749d1c653740dd0d2415100fe26e27afdf41", - "sha256:a841dacd6b99318a741b166adb07e19ee71a274450e68237b4650ca1055ab128" - ], - "version": "==1.4.4" - }, - "astroid": { - "hashes": [ - "sha256:09bdb456e02564731f8b5957cdd0c98a7f01d2db5e90eb1d794c353c28bfd705", - "sha256:6a8a51f64dae307f6e0c9db752b66a7951e282389d8362cc1d39a56f3feeb31d" - ], - "index": "pypi", - "version": "==2.6.0" - }, - "avocado-framework": { - "hashes": [ - "sha256:244cb569f8eb4e50a22ac82e1a2b2bba2458999f4281efbe2651bd415d59c65b", - "sha256:6f15998b67ecd0e7dde790c4de4dd249d6df52dfe6d5cc4e2dd6596df51c3583" - ], - "index": "pypi", - "version": "==90.0" - }, - "distlib": { - "hashes": [ - "sha256:106fef6dc37dd8c0e2c0a60d3fca3e77460a48907f335fa28420463a6f799736", - "sha256:23e223426b28491b1ced97dc3bbe183027419dfc7982b4fa2f05d5f3ff10711c" - ], - "index": "pypi", - "version": "==0.3.2" - }, - "filelock": { - "hashes": [ - "sha256:18d82244ee114f543149c66a6e0c14e9c4f8a1044b5cdaadd0f82159d6a6ff59", - "sha256:929b7d63ec5b7d6b71b0fa5ac14e030b3f70b75747cef1b10da9b879fef15836" - ], - "index": "pypi", - "version": "==3.0.12" - }, - "flake8": { - "hashes": [ - "sha256:6a35f5b8761f45c5513e3405f110a86bea57982c3b75b766ce7b65217abe1670", - "sha256:c01f8a3963b3571a8e6bd7a4063359aff90749e160778e03817cd9b71c9e07d2" - ], - "index": "pypi", - "version": "==3.6.0" - }, - "fusepy": { - "hashes": [ - "sha256:10f5c7f5414241bffecdc333c4d3a725f1d6605cae6b4eaf86a838ff49cdaf6c", - "sha256:a9f3a3699080ddcf0919fd1eb2cf743e1f5859ca54c2018632f939bdfac269ee" - ], - "index": "pypi", - "version": "==2.0.4" - }, - "importlib-metadata": { - "hashes": [ - "sha256:90bb658cdbbf6d1735b6341ce708fc7024a3e14e99ffdc5783edea9f9b077f83", - "sha256:dc15b2969b4ce36305c51eebe62d418ac7791e9a157911d58bfb1f9ccd8e2070" - ], - "markers": "python_version < '3.8'", - "version": "==1.7.0" - }, - "importlib-resources": { - "hashes": [ - "sha256:54161657e8ffc76596c4ede7080ca68cb02962a2e074a2586b695a93a925d36e", - "sha256:e962bff7440364183203d179d7ae9ad90cb1f2b74dcb84300e88ecc42dca3351" - ], - "index": "pypi", - "version": "==5.1.4" - }, - "isort": { - "hashes": [ - "sha256:408e4d75d84f51b64d0824894afee44469eba34a4caee621dc53799f80d71ccc", - "sha256:64022dea6a06badfa09b300b4dfe8ba968114a737919e8ed50aea1c288f078aa" - ], - "index": "pypi", - "version": "==5.1.2" - }, - "lazy-object-proxy": { - "hashes": [ - "sha256:17e0967ba374fc24141738c69736da90e94419338fd4c7c7bef01ee26b339653", - "sha256:1fee665d2638491f4d6e55bd483e15ef21f6c8c2095f235fef72601021e64f61", - "sha256:22ddd618cefe54305df49e4c069fa65715be4ad0e78e8d252a33debf00f6ede2", - "sha256:24a5045889cc2729033b3e604d496c2b6f588c754f7a62027ad4437a7ecc4837", - "sha256:410283732af311b51b837894fa2f24f2c0039aa7f220135192b38fcc42bd43d3", - "sha256:4732c765372bd78a2d6b2150a6e99d00a78ec963375f236979c0626b97ed8e43", - "sha256:489000d368377571c6f982fba6497f2aa13c6d1facc40660963da62f5c379726", - "sha256:4f60460e9f1eb632584c9685bccea152f4ac2130e299784dbaf9fae9f49891b3", - "sha256:5743a5ab42ae40caa8421b320ebf3a998f89c85cdc8376d6b2e00bd12bd1b587", - "sha256:85fb7608121fd5621cc4377a8961d0b32ccf84a7285b4f1d21988b2eae2868e8", - "sha256:9698110e36e2df951c7c36b6729e96429c9c32b3331989ef19976592c5f3c77a", - "sha256:9d397bf41caad3f489e10774667310d73cb9c4258e9aed94b9ec734b34b495fd", - "sha256:b579f8acbf2bdd9ea200b1d5dea36abd93cabf56cf626ab9c744a432e15c815f", - "sha256:b865b01a2e7f96db0c5d12cfea590f98d8c5ba64ad222300d93ce6ff9138bcad", - "sha256:bf34e368e8dd976423396555078def5cfc3039ebc6fc06d1ae2c5a65eebbcde4", - "sha256:c6938967f8528b3668622a9ed3b31d145fab161a32f5891ea7b84f6b790be05b", - "sha256:d1c2676e3d840852a2de7c7d5d76407c772927addff8d742b9808fe0afccebdf", - "sha256:d7124f52f3bd259f510651450e18e0fd081ed82f3c08541dffc7b94b883aa981", - "sha256:d900d949b707778696fdf01036f58c9876a0d8bfe116e8d220cfd4b15f14e741", - "sha256:ebfd274dcd5133e0afae738e6d9da4323c3eb021b3e13052d8cbd0e457b1256e", - "sha256:ed361bb83436f117f9917d282a456f9e5009ea12fd6de8742d1a4752c3017e93", - "sha256:f5144c75445ae3ca2057faac03fda5a902eff196702b0a24daf1d6ce0650514b" - ], - "index": "pypi", - "version": "==1.6.0" - }, - "mccabe": { - "hashes": [ - "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42", - "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f" - ], - "version": "==0.6.1" - }, - "mypy": { - "hashes": [ - "sha256:00cb1964a7476e871d6108341ac9c1a857d6bd20bf5877f4773ac5e9d92cd3cd", - "sha256:127de5a9b817a03a98c5ae8a0c46a20dc44442af6dcfa2ae7f96cb519b312efa", - "sha256:1f3976a945ad7f0a0727aafdc5651c2d3278e3c88dee94e2bf75cd3386b7b2f4", - "sha256:2f8c098f12b402c19b735aec724cc9105cc1a9eea405d08814eb4b14a6fb1a41", - "sha256:4ef13b619a289aa025f2273e05e755f8049bb4eaba6d703a425de37d495d178d", - "sha256:5d142f219bf8c7894dfa79ebfb7d352c4c63a325e75f10dfb4c3db9417dcd135", - "sha256:62eb5dd4ea86bda8ce386f26684f7f26e4bfe6283c9f2b6ca6d17faf704dcfad", - "sha256:64c36eb0936d0bfb7d8da49f92c18e312ad2e3ed46e5548ae4ca997b0d33bd59", - "sha256:75eed74d2faf2759f79c5f56f17388defd2fc994222312ec54ee921e37b31ad4", - "sha256:974bebe3699b9b46278a7f076635d219183da26e1a675c1f8243a69221758273", - "sha256:a5e5bb12b7982b179af513dddb06fca12285f0316d74f3964078acbfcf4c68f2", - "sha256:d31291df31bafb997952dc0a17ebb2737f802c754aed31dd155a8bfe75112c57", - "sha256:d3b4941de44341227ece1caaf5b08b23e42ad4eeb8b603219afb11e9d4cfb437", - "sha256:eadb865126da4e3c4c95bdb47fe1bb087a3e3ea14d39a3b13224b8a4d9f9a102" - ], - "index": "pypi", - "version": "==0.780" - }, - "mypy-extensions": { - "hashes": [ - "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d", - "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8" - ], - "version": "==0.4.3" - }, - "packaging": { - "hashes": [ - "sha256:5b327ac1320dc863dca72f4514ecc086f31186744b84a230374cc1fd776feae5", - "sha256:67714da7f7bc052e064859c05c595155bd1ee9f69f76557e21f051443c20947a" - ], - "index": "pypi", - "version": "==20.9" - }, - "pluggy": { - "hashes": [ - "sha256:15b2acde666561e1298d71b523007ed7364de07029219b604cf808bfa1c765b0", - "sha256:966c145cd83c96502c3c3868f50408687b38434af77734af1e9ca461a4081d2d" - ], - "index": "pypi", - "version": "==0.13.1" - }, - "py": { - "hashes": [ - "sha256:21b81bda15b66ef5e1a777a21c4dcd9c20ad3efd0b3f817e7a809035269e1bd3", - "sha256:3b80836aa6d1feeaa108e046da6423ab8f6ceda6468545ae8d02d9d58d18818a" - ], - "index": "pypi", - "version": "==1.10.0" - }, - "pycodestyle": { - "hashes": [ - "sha256:74abc4e221d393ea5ce1f129ea6903209940c1ecd29e002e8c6933c2b21026e0", - "sha256:cbc619d09254895b0d12c2c691e237b2e91e9b2ecf5e84c26b35400f93dcfb83", - "sha256:cbfca99bd594a10f674d0cd97a3d802a1fdef635d4361e1a2658de47ed261e3a" - ], - "version": "==2.4.0" - }, - "pyflakes": { - "hashes": [ - "sha256:9a7662ec724d0120012f6e29d6248ae3727d821bba522a0e6b356eff19126a49", - "sha256:f661252913bc1dbe7fcfcbf0af0db3f42ab65aabd1a6ca68fe5d466bace94dae" - ], - "version": "==2.0.0" - }, - "pygments": { - "hashes": [ - "sha256:a18f47b506a429f6f4b9df81bb02beab9ca21d0a5fee38ed15aef65f0545519f", - "sha256:d66e804411278594d764fc69ec36ec13d9ae9147193a1740cd34d272ca383b8e" - ], - "index": "pypi", - "version": "==2.9.0" - }, - "pylint": { - "hashes": [ - "sha256:082a6d461b54f90eea49ca90fff4ee8b6e45e8029e5dbd72f6107ef84f3779c0", - "sha256:a01cd675eccf6e25b3bdb42be184eb46aaf89187d612ba0fb5f93328ed6b0fd5" - ], - "index": "pypi", - "version": "==2.8.0" - }, - "pyparsing": { - "hashes": [ - "sha256:c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1", - "sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b" - ], - "index": "pypi", - "version": "==2.4.7" - }, - "qemu": { - "editable": true, - "path": "." - }, - "setuptools": { - "hashes": [ - "sha256:22c7348c6d2976a52632c67f7ab0cdf40147db7789f9aed18734643fe9cf3373", - "sha256:4ce92f1e1f8f01233ee9952c04f6b81d1e02939d6e1b488428154974a4d0783e" - ], - "markers": "python_version >= '3.6'", - "version": "==59.6.0" - }, - "six": { - "hashes": [ - "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926", - "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254" - ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", - "version": "==1.16.0" - }, - "toml": { - "hashes": [ - "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b", - "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f" - ], - "markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3'", - "version": "==0.10.2" - }, - "tox": { - "hashes": [ - "sha256:c60692d92fe759f46c610ac04c03cf0169432d1ff8e981e8ae63e068d0954fc3", - "sha256:f179cb4043d7dc1339425dd49ab1dd8c916246b0d9173143c1b0af7498a03ab0" - ], - "index": "pypi", - "version": "==3.18.0" - }, - "typed-ast": { - "hashes": [ - "sha256:01ae5f73431d21eead5015997ab41afa53aa1fbe252f9da060be5dad2c730ace", - "sha256:067a74454df670dcaa4e59349a2e5c81e567d8d65458d480a5b3dfecec08c5ff", - "sha256:0fb71b8c643187d7492c1f8352f2c15b4c4af3f6338f21681d3681b3dc31a266", - "sha256:1b3ead4a96c9101bef08f9f7d1217c096f31667617b58de957f690c92378b528", - "sha256:2068531575a125b87a41802130fa7e29f26c09a2833fea68d9a40cf33902eba6", - "sha256:209596a4ec71d990d71d5e0d312ac935d86930e6eecff6ccc7007fe54d703808", - "sha256:2c726c276d09fc5c414693a2de063f521052d9ea7c240ce553316f70656c84d4", - "sha256:398e44cd480f4d2b7ee8d98385ca104e35c81525dd98c519acff1b79bdaac363", - "sha256:52b1eb8c83f178ab787f3a4283f68258525f8d70f778a2f6dd54d3b5e5fb4341", - "sha256:5feca99c17af94057417d744607b82dd0a664fd5e4ca98061480fd8b14b18d04", - "sha256:7538e495704e2ccda9b234b82423a4038f324f3a10c43bc088a1636180f11a41", - "sha256:760ad187b1041a154f0e4d0f6aae3e40fdb51d6de16e5c99aedadd9246450e9e", - "sha256:777a26c84bea6cd934422ac2e3b78863a37017618b6e5c08f92ef69853e765d3", - "sha256:95431a26309a21874005845c21118c83991c63ea800dd44843e42a916aec5899", - "sha256:9ad2c92ec681e02baf81fdfa056fe0d818645efa9af1f1cd5fd6f1bd2bdfd805", - "sha256:9c6d1a54552b5330bc657b7ef0eae25d00ba7ffe85d9ea8ae6540d2197a3788c", - "sha256:aee0c1256be6c07bd3e1263ff920c325b59849dc95392a05f258bb9b259cf39c", - "sha256:af3d4a73793725138d6b334d9d247ce7e5f084d96284ed23f22ee626a7b88e39", - "sha256:b36b4f3920103a25e1d5d024d155c504080959582b928e91cb608a65c3a49e1a", - "sha256:b9574c6f03f685070d859e75c7f9eeca02d6933273b5e69572e5ff9d5e3931c3", - "sha256:bff6ad71c81b3bba8fa35f0f1921fb24ff4476235a6e94a26ada2e54370e6da7", - "sha256:c190f0899e9f9f8b6b7863debfb739abcb21a5c054f911ca3596d12b8a4c4c7f", - "sha256:c907f561b1e83e93fad565bac5ba9c22d96a54e7ea0267c708bffe863cbe4075", - "sha256:cae53c389825d3b46fb37538441f75d6aecc4174f615d048321b716df2757fb0", - "sha256:dd4a21253f42b8d2b48410cb31fe501d32f8b9fbeb1f55063ad102fe9c425e40", - "sha256:dde816ca9dac1d9c01dd504ea5967821606f02e510438120091b84e852367428", - "sha256:f2362f3cb0f3172c42938946dbc5b7843c2a28aec307c49100c8b38764eb6927", - "sha256:f328adcfebed9f11301eaedfa48e15bdece9b519fb27e6a8c01aa52a17ec31b3", - "sha256:f8afcf15cc511ada719a88e013cec87c11aff7b91f019295eb4530f96fe5ef2f", - "sha256:fb1bbeac803adea29cedd70781399c99138358c26d05fcbd23c13016b7f5ec65" - ], - "markers": "python_version < '3.8' and implementation_name == 'cpython'", - "version": "==1.4.3" - }, - "typing-extensions": { - "hashes": [ - "sha256:0ac0f89795dd19de6b97debb0c6af1c70987fd80a2d62d1958f7e56fcc31b497", - "sha256:50b6f157849174217d0656f99dc82fe932884fb250826c18350e159ec6cdf342", - "sha256:779383f6086d90c99ae41cf0ff39aac8a7937a9283ce0a414e5dd782f4c94a84" - ], - "index": "pypi", - "version": "==3.10.0.0" - }, - "urwid": { - "hashes": [ - "sha256:588bee9c1cb208d0906a9f73c613d2bd32c3ed3702012f51efe318a3f2127eae" - ], - "index": "pypi", - "version": "==2.1.2" - }, - "urwid-readline": { - "hashes": [ - "sha256:018020cbc864bb5ed87be17dc26b069eae2755cb29f3a9c569aac3bded1efaf4" - ], - "index": "pypi", - "version": "==0.13" - }, - "virtualenv": { - "hashes": [ - "sha256:14fdf849f80dbb29a4eb6caa9875d476ee2a5cf76a5f5415fa2f1606010ab467", - "sha256:2b0126166ea7c9c3661f5b8e06773d28f83322de7a3ff7d06f0aed18c9de6a76" - ], - "index": "pypi", - "version": "==20.4.7" - }, - "wrapt": { - "hashes": [ - "sha256:b62ffa81fb85f4332a4f609cab4ac40709470da05643a082ec1eb88e6d9b97d7" - ], - "version": "==1.12.1" - }, - "zipp": { - "hashes": [ - "sha256:3607921face881ba3e026887d8150cca609d517579abe052ac81fc5aeffdbd76", - "sha256:51cb66cc54621609dd593d1787f286ee42a5c0adbb4b29abea5a63edc3e03098" - ], - "index": "pypi", - "version": "==3.4.1" - } - } -} diff --git a/python/README.rst b/python/README.rst index 9c1fceaee7..d62e71528d 100644 --- a/python/README.rst +++ b/python/README.rst @@ -77,9 +77,6 @@ Files in this directory - ``MANIFEST.in`` is read by python setuptools, it specifies additional files that should be included by a source distribution. - ``PACKAGE.rst`` is used as the README file that is visible on PyPI.org. -- ``Pipfile`` is used by Pipenv to generate ``Pipfile.lock``. -- ``Pipfile.lock`` is a set of pinned package dependencies that this package - is tested under in our CI suite. It is used by ``make check-pipenv``. - ``README.rst`` you are here! - ``VERSION`` contains the PEP-440 compliant version used to describe this package; it is referenced by ``setup.cfg``. diff --git a/python/setup.cfg b/python/setup.cfg index 5641815706..9e923d9762 100644 --- a/python/setup.cfg +++ b/python/setup.cfg @@ -33,9 +33,7 @@ packages = * = py.typed [options.extras_require] -# For the devel group, When adding new dependencies or bumping the minimum -# version, use e.g. "pipenv install --dev pylint==3.0.0". -# Subsequently, edit 'Pipfile' to remove e.g. 'pylint = "==3.0.0'. +# Remember to update tests/minreqs.txt if changing anything below: devel = avocado-framework >= 90.0 flake8 >= 3.6.0 diff --git a/python/tests/minreqs.txt b/python/tests/minreqs.txt new file mode 100644 index 0000000000..dfb8abb155 --- /dev/null +++ b/python/tests/minreqs.txt @@ -0,0 +1,45 @@ +# This file lists the ***oldest possible dependencies*** needed to run +# "make check" successfully under ***Python 3.6***. It is used primarily +# by GitLab CI to ensure that our stated minimum versions in setup.cfg +# are truthful and regularly validated. +# +# This file should not contain any dependencies that are not expressed +# by the [devel] section of setup.cfg, except for transitive +# dependencies which must be enumerated here explicitly to eliminate +# dependency resolution ambiguity. +# +# When adding new dependencies, pin the very oldest non-yanked version +# on PyPI that allows the test suite to pass. + +# Dependencies for the TUI addon (Required for successful linting) +urwid==2.1.2 +urwid-readline==0.13 +Pygments==2.9.0 + +# Dependencies for FUSE support for qom-fuse +fusepy==2.0.4 + +# Test-runners, utilities, etc. +avocado-framework==90.0 + +# Linters +flake8==3.6.0 +isort==5.1.2 +mypy==0.780 +pylint==2.8.0 + +# Transitive flake8 dependencies +mccabe==0.6.0 +pycodestyle==2.4.0 +pyflakes==2.0.0 + +# Transitive mypy dependencies +mypy-extensions==0.4.3 +typed-ast==1.4.0 +typing-extensions==3.7.4 + +# Transitive pylint dependencies +astroid==2.5.4 +lazy-object-proxy==1.4.0 +toml==0.10.0 +wrapt==1.12.1 diff --git a/tests/docker/dockerfiles/python.docker b/tests/docker/dockerfiles/python.docker index 56d88417df..175c10a34e 100644 --- a/tests/docker/dockerfiles/python.docker +++ b/tests/docker/dockerfiles/python.docker @@ -7,7 +7,6 @@ MAINTAINER John Snow ENV PACKAGES \ gcc \ make \ - pipenv \ python3 \ python3-pip \ python3-tox \ From ebf1b324e8d1b05be5327f3e6a13d8570f7fd1e3 Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Mon, 13 Feb 2023 14:20:08 +0100 Subject: [PATCH 018/129] docs/devel/qapi-code-gen: Belatedly update features documentation Commit 013b4efc9be "qapi: Add feature flags to remaining definitions" (v5.0.0), commit 84ab0086879 "qapi: Add feature flags to struct members" (v5.0.0), and commit b6c18755e41 "qapi: Add feature flags to enum members" (v6.2.0) neglected to update section "Features". Make up for that. Signed-off-by: Markus Armbruster Message-Id: <20230213132009.918801-2-armbru@redhat.com> Reviewed-by: Eric Blake Reviewed-by: John Snow --- docs/devel/qapi-code-gen.rst | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/docs/devel/qapi-code-gen.rst b/docs/devel/qapi-code-gen.rst index 5edc49aa74..566640edf8 100644 --- a/docs/devel/qapi-code-gen.rst +++ b/docs/devel/qapi-code-gen.rst @@ -685,9 +685,10 @@ change in the QMP syntax (usually by allowing values or operations that previously resulted in an error). QMP clients may still need to know whether the extension is available. -For this purpose, a list of features can be specified for a command or -struct type. Each list member can either be ``{ 'name': STRING, '*if': -COND }``, or STRING, which is shorthand for ``{ 'name': STRING }``. +For this purpose, a list of features can be specified for definitions, +enumeration values, and struct members. Each feature list member can +either be ``{ 'name': STRING, '*if': COND }``, or STRING, which is +shorthand for ``{ 'name': STRING }``. The optional 'if' member specifies a conditional. See `Configuring the schema`_ below for more on this. From c2985e38f0a5e00bfb2540b43531baf485de2ee2 Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Mon, 13 Feb 2023 14:20:09 +0100 Subject: [PATCH 019/129] docs/devel/qapi-code-gen: Fix a missing 'may', clarify SchemaInfo Documentation of enumeration value conditions lacks a 'may'. Fix that. Clarify SchemaInfo documentation for struct and union types. Signed-off-by: Markus Armbruster Message-Id: <20230213132009.918801-3-armbru@redhat.com> Reviewed-by: Eric Blake Reviewed-by: John Snow --- docs/devel/qapi-code-gen.rst | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/docs/devel/qapi-code-gen.rst b/docs/devel/qapi-code-gen.rst index 566640edf8..23e7f2fb1c 100644 --- a/docs/devel/qapi-code-gen.rst +++ b/docs/devel/qapi-code-gen.rst @@ -818,8 +818,8 @@ member 'bar' :: A union's discriminator may not be conditional. -Likewise, individual enumeration values be conditional. This requires -the longhand form of ENUM-VALUE_. +Likewise, individual enumeration values may be conditional. This +requires the longhand form of ENUM-VALUE_. Example: an enum type with unconditional value 'foo' and conditional value 'bar' :: @@ -1158,9 +1158,8 @@ Example: the SchemaInfo for EVENT_C from section Events_ :: Type "q_obj-EVENT_C-arg" is an implicitly defined object type with the two members from the event's definition. -The SchemaInfo for struct and union types has meta-type "object". - -The SchemaInfo for a struct type has variant member "members". +The SchemaInfo for struct and union types has meta-type "object" and +variant member "members". The SchemaInfo for a union type additionally has variant members "tag" and "variants". From 6f2ddcde774d5cbe522693b374f45a1bcb70cebf Mon Sep 17 00:00:00 2001 From: John Snow Date: Tue, 14 Feb 2023 19:00:06 -0500 Subject: [PATCH 020/129] qapi: Update flake8 config New versions of flake8 don't like same-line comments. (It's a version newer than what fc37 ships, but it still makes my life easier to fix it now.) Signed-off-by: John Snow Reviewed-by: Markus Armbruster Message-Id: <20230215000011.1725012-2-jsnow@redhat.com> --- scripts/qapi/.flake8 | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/qapi/.flake8 b/scripts/qapi/.flake8 index 6b158c68b8..a873ff6730 100644 --- a/scripts/qapi/.flake8 +++ b/scripts/qapi/.flake8 @@ -1,2 +1,3 @@ [flake8] -extend-ignore = E722 # Prefer pylint's bare-except checks to flake8's +# Prefer pylint's bare-except checks to flake8's +extend-ignore = E722 From 885ecdbec9da62ede8019fc74f9154215e410aee Mon Sep 17 00:00:00 2001 From: John Snow Date: Tue, 14 Feb 2023 19:00:07 -0500 Subject: [PATCH 021/129] qapi: update pylint configuration Newer versions of pylint disable the "no-self-use" message by default. Older versions don't, though. If we leave the suppressions in, pylint yelps about useless options. Just tell pylint to shush. Signed-off-by: John Snow Reviewed-by: Markus Armbruster Message-Id: <20230215000011.1725012-3-jsnow@redhat.com> --- scripts/qapi/pylintrc | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/qapi/pylintrc b/scripts/qapi/pylintrc index a724628203..90546df534 100644 --- a/scripts/qapi/pylintrc +++ b/scripts/qapi/pylintrc @@ -23,6 +23,7 @@ disable=fixme, too-many-statements, too-many-instance-attributes, consider-using-f-string, + useless-option-value, [REPORTS] From c60caf8086247afbfbf0673993d809d348238ef6 Mon Sep 17 00:00:00 2001 From: John Snow Date: Tue, 14 Feb 2023 19:00:08 -0500 Subject: [PATCH 022/129] qapi: Add minor typing workaround for 3.6 Pylint under 3.6 does not believe that Collection is subscriptable at runtime. It is, making this a Pylint bug. https://github.com/PyCQA/pylint/issues/2377 They closed it as fixed, but that doesn't seem to be true as of Pylint 2.13.9, the latest version you can install under Python 3.6. 2.13.9 was released 2022-05-13, about seven months after the bug was closed. The least-annoying fix here is to just use the concret type. Signed-off-by: John Snow Message-Id: <20230215000011.1725012-4-jsnow@redhat.com> [Dumbed down from Sequence[str] to List[str], commit message adjusted] Reviewed-by: Markus Armbruster --- scripts/qapi/expr.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/scripts/qapi/expr.py b/scripts/qapi/expr.py index 5a1782b57e..358b8e2a8b 100644 --- a/scripts/qapi/expr.py +++ b/scripts/qapi/expr.py @@ -33,7 +33,6 @@ structures and contextual semantic validation. import re from typing import ( - Collection, Dict, Iterable, List, @@ -195,8 +194,8 @@ def check_defn_name_str(name: str, info: QAPISourceInfo, meta: str) -> None: def check_keys(value: _JSONObject, info: QAPISourceInfo, source: str, - required: Collection[str], - optional: Collection[str]) -> None: + required: List[str], + optional: List[str]) -> None: """ Ensure that a dict has a specific set of keys. From 420110591c54f5fd38e065d5bddac73b3076bf9e Mon Sep 17 00:00:00 2001 From: John Snow Date: Tue, 14 Feb 2023 19:00:09 -0500 Subject: [PATCH 023/129] qapi/parser: add QAPIExpression type This patch creates a new type, QAPIExpression, which represents a parsed expression complete with QAPIDoc and QAPISourceInfo. This patch turns parser.exprs into a list of QAPIExpression instead, and adjusts expr.py to match. This allows the types we specify in parser.py to be "remembered" all the way through expr.py and into schema.py. Several assertions around packing and unpacking this data can be removed as a result. It also corrects a harmless typing error. Before the patch, check_exprs() allegedly takes a List[_JSONObject]. It actually takes a list of dicts of the form {'expr': E, 'info': I, 'doc': D} where E is of type _ExprValue, I is of type QAPISourceInfo, and D is of type QAPIDoc. Key 'doc' is optional. This is not a _JSONObject! Passes type checking anyway, because _JSONObject is Dict[str, object]. Signed-off-by: John Snow Message-Id: <20230215000011.1725012-5-jsnow@redhat.com> Reviewed-by: Markus Armbruster [Commit message amended to point out the typing fix] --- scripts/qapi/expr.py | 82 +++++++++++++++++------------------------- scripts/qapi/parser.py | 46 ++++++++++++++---------- scripts/qapi/schema.py | 72 ++++++++++++++++++++----------------- 3 files changed, 100 insertions(+), 100 deletions(-) diff --git a/scripts/qapi/expr.py b/scripts/qapi/expr.py index 358b8e2a8b..b8f905543e 100644 --- a/scripts/qapi/expr.py +++ b/scripts/qapi/expr.py @@ -43,7 +43,7 @@ from typing import ( from .common import c_name from .error import QAPISemError -from .parser import QAPIDoc +from .parser import QAPIExpression from .source import QAPISourceInfo @@ -228,12 +228,11 @@ def check_keys(value: _JSONObject, pprint(unknown), pprint(allowed))) -def check_flags(expr: _JSONObject, info: QAPISourceInfo) -> None: +def check_flags(expr: QAPIExpression) -> None: """ Ensure flag members (if present) have valid values. :param expr: The expression to validate. - :param info: QAPI schema source file information. :raise QAPISemError: When certain flags have an invalid value, or when @@ -242,18 +241,18 @@ def check_flags(expr: _JSONObject, info: QAPISourceInfo) -> None: for key in ('gen', 'success-response'): if key in expr and expr[key] is not False: raise QAPISemError( - info, "flag '%s' may only use false value" % key) + expr.info, "flag '%s' may only use false value" % key) for key in ('boxed', 'allow-oob', 'allow-preconfig', 'coroutine'): if key in expr and expr[key] is not True: raise QAPISemError( - info, "flag '%s' may only use true value" % key) + expr.info, "flag '%s' may only use true value" % key) if 'allow-oob' in expr and 'coroutine' in expr: # This is not necessarily a fundamental incompatibility, but # we don't have a use case and the desired semantics isn't # obvious. The simplest solution is to forbid it until we get # a use case for it. - raise QAPISemError(info, "flags 'allow-oob' and 'coroutine' " - "are incompatible") + raise QAPISemError( + expr.info, "flags 'allow-oob' and 'coroutine' are incompatible") def check_if(expr: _JSONObject, info: QAPISourceInfo, source: str) -> None: @@ -446,12 +445,11 @@ def check_features(features: Optional[object], check_if(feat, info, source) -def check_enum(expr: _JSONObject, info: QAPISourceInfo) -> None: +def check_enum(expr: QAPIExpression) -> None: """ Normalize and validate this expression as an ``enum`` definition. :param expr: The expression to validate. - :param info: QAPI schema source file information. :raise QAPISemError: When ``expr`` is not a valid ``enum``. :return: None, ``expr`` is normalized in-place as needed. @@ -459,6 +457,7 @@ def check_enum(expr: _JSONObject, info: QAPISourceInfo) -> None: name = expr['enum'] members = expr['data'] prefix = expr.get('prefix') + info = expr.info if not isinstance(members, list): raise QAPISemError(info, "'data' must be an array") @@ -485,12 +484,11 @@ def check_enum(expr: _JSONObject, info: QAPISourceInfo) -> None: check_features(member.get('features'), info) -def check_struct(expr: _JSONObject, info: QAPISourceInfo) -> None: +def check_struct(expr: QAPIExpression) -> None: """ Normalize and validate this expression as a ``struct`` definition. :param expr: The expression to validate. - :param info: QAPI schema source file information. :raise QAPISemError: When ``expr`` is not a valid ``struct``. :return: None, ``expr`` is normalized in-place as needed. @@ -498,16 +496,15 @@ def check_struct(expr: _JSONObject, info: QAPISourceInfo) -> None: name = cast(str, expr['struct']) # Checked in check_exprs members = expr['data'] - check_type(members, info, "'data'", allow_dict=name) - check_type(expr.get('base'), info, "'base'") + check_type(members, expr.info, "'data'", allow_dict=name) + check_type(expr.get('base'), expr.info, "'base'") -def check_union(expr: _JSONObject, info: QAPISourceInfo) -> None: +def check_union(expr: QAPIExpression) -> None: """ Normalize and validate this expression as a ``union`` definition. :param expr: The expression to validate. - :param info: QAPI schema source file information. :raise QAPISemError: when ``expr`` is not a valid ``union``. :return: None, ``expr`` is normalized in-place as needed. @@ -516,6 +513,7 @@ def check_union(expr: _JSONObject, info: QAPISourceInfo) -> None: base = expr['base'] discriminator = expr['discriminator'] members = expr['data'] + info = expr.info check_type(base, info, "'base'", allow_dict=name) check_name_is_str(discriminator, info, "'discriminator'") @@ -530,17 +528,17 @@ def check_union(expr: _JSONObject, info: QAPISourceInfo) -> None: check_type(value['type'], info, source, allow_array=not base) -def check_alternate(expr: _JSONObject, info: QAPISourceInfo) -> None: +def check_alternate(expr: QAPIExpression) -> None: """ Normalize and validate this expression as an ``alternate`` definition. :param expr: The expression to validate. - :param info: QAPI schema source file information. :raise QAPISemError: When ``expr`` is not a valid ``alternate``. :return: None, ``expr`` is normalized in-place as needed. """ members = expr['data'] + info = expr.info if not members: raise QAPISemError(info, "'data' must not be empty") @@ -556,12 +554,11 @@ def check_alternate(expr: _JSONObject, info: QAPISourceInfo) -> None: check_type(value['type'], info, source, allow_array=True) -def check_command(expr: _JSONObject, info: QAPISourceInfo) -> None: +def check_command(expr: QAPIExpression) -> None: """ Normalize and validate this expression as a ``command`` definition. :param expr: The expression to validate. - :param info: QAPI schema source file information. :raise QAPISemError: When ``expr`` is not a valid ``command``. :return: None, ``expr`` is normalized in-place as needed. @@ -571,17 +568,16 @@ def check_command(expr: _JSONObject, info: QAPISourceInfo) -> None: boxed = expr.get('boxed', False) if boxed and args is None: - raise QAPISemError(info, "'boxed': true requires 'data'") - check_type(args, info, "'data'", allow_dict=not boxed) - check_type(rets, info, "'returns'", allow_array=True) + raise QAPISemError(expr.info, "'boxed': true requires 'data'") + check_type(args, expr.info, "'data'", allow_dict=not boxed) + check_type(rets, expr.info, "'returns'", allow_array=True) -def check_event(expr: _JSONObject, info: QAPISourceInfo) -> None: +def check_event(expr: QAPIExpression) -> None: """ Normalize and validate this expression as an ``event`` definition. :param expr: The expression to validate. - :param info: QAPI schema source file information. :raise QAPISemError: When ``expr`` is not a valid ``event``. :return: None, ``expr`` is normalized in-place as needed. @@ -590,11 +586,11 @@ def check_event(expr: _JSONObject, info: QAPISourceInfo) -> None: boxed = expr.get('boxed', False) if boxed and args is None: - raise QAPISemError(info, "'boxed': true requires 'data'") - check_type(args, info, "'data'", allow_dict=not boxed) + raise QAPISemError(expr.info, "'boxed': true requires 'data'") + check_type(args, expr.info, "'data'", allow_dict=not boxed) -def check_exprs(exprs: List[_JSONObject]) -> List[_JSONObject]: +def check_exprs(exprs: List[QAPIExpression]) -> List[QAPIExpression]: """ Validate and normalize a list of parsed QAPI schema expressions. @@ -606,21 +602,9 @@ def check_exprs(exprs: List[_JSONObject]) -> List[_JSONObject]: :raise QAPISemError: When any expression fails validation. :return: The same list of expressions (now modified). """ - for expr_elem in exprs: - # Expression - assert isinstance(expr_elem['expr'], dict) - for key in expr_elem['expr'].keys(): - assert isinstance(key, str) - expr: _JSONObject = expr_elem['expr'] - - # QAPISourceInfo - assert isinstance(expr_elem['info'], QAPISourceInfo) - info: QAPISourceInfo = expr_elem['info'] - - # Optional[QAPIDoc] - tmp = expr_elem.get('doc') - assert tmp is None or isinstance(tmp, QAPIDoc) - doc: Optional[QAPIDoc] = tmp + for expr in exprs: + info = expr.info + doc = expr.doc if 'include' in expr: continue @@ -652,24 +636,24 @@ def check_exprs(exprs: List[_JSONObject]) -> List[_JSONObject]: if meta == 'enum': check_keys(expr, info, meta, ['enum', 'data'], ['if', 'features', 'prefix']) - check_enum(expr, info) + check_enum(expr) elif meta == 'union': check_keys(expr, info, meta, ['union', 'base', 'discriminator', 'data'], ['if', 'features']) normalize_members(expr.get('base')) normalize_members(expr['data']) - check_union(expr, info) + check_union(expr) elif meta == 'alternate': check_keys(expr, info, meta, ['alternate', 'data'], ['if', 'features']) normalize_members(expr['data']) - check_alternate(expr, info) + check_alternate(expr) elif meta == 'struct': check_keys(expr, info, meta, ['struct', 'data'], ['base', 'if', 'features']) normalize_members(expr['data']) - check_struct(expr, info) + check_struct(expr) elif meta == 'command': check_keys(expr, info, meta, ['command'], @@ -677,17 +661,17 @@ def check_exprs(exprs: List[_JSONObject]) -> List[_JSONObject]: 'gen', 'success-response', 'allow-oob', 'allow-preconfig', 'coroutine']) normalize_members(expr.get('data')) - check_command(expr, info) + check_command(expr) elif meta == 'event': check_keys(expr, info, meta, ['event'], ['data', 'boxed', 'if', 'features']) normalize_members(expr.get('data')) - check_event(expr, info) + check_event(expr) else: assert False, 'unexpected meta type' check_if(expr, info, meta) check_features(expr.get('features'), info) - check_flags(expr, info) + check_flags(expr) return exprs diff --git a/scripts/qapi/parser.py b/scripts/qapi/parser.py index 1b006cdc13..50906e27d4 100644 --- a/scripts/qapi/parser.py +++ b/scripts/qapi/parser.py @@ -21,6 +21,7 @@ from typing import ( TYPE_CHECKING, Dict, List, + Mapping, Optional, Set, Union, @@ -37,15 +38,24 @@ if TYPE_CHECKING: from .schema import QAPISchemaFeature, QAPISchemaMember -#: Represents a single Top Level QAPI schema expression. -TopLevelExpr = Dict[str, object] - # Return value alias for get_expr(). _ExprValue = Union[List[object], Dict[str, object], str, bool] -# FIXME: Consolidate and centralize definitions for TopLevelExpr, -# _ExprValue, _JSONValue, and _JSONObject; currently scattered across -# several modules. + +# FIXME: Consolidate and centralize definitions for _ExprValue, +# JSONValue, and _JSONObject; currently scattered across several +# modules. + + +class QAPIExpression(Dict[str, object]): + # pylint: disable=too-few-public-methods + def __init__(self, + data: Mapping[str, object], + info: QAPISourceInfo, + doc: Optional['QAPIDoc'] = None): + super().__init__(data) + self.info = info + self.doc: Optional['QAPIDoc'] = doc class QAPIParseError(QAPISourceError): @@ -100,7 +110,7 @@ class QAPISchemaParser: self.line_pos = 0 # Parser output: - self.exprs: List[Dict[str, object]] = [] + self.exprs: List[QAPIExpression] = [] self.docs: List[QAPIDoc] = [] # Showtime! @@ -147,8 +157,7 @@ class QAPISchemaParser: "value of 'include' must be a string") incl_fname = os.path.join(os.path.dirname(self._fname), include) - self.exprs.append({'expr': {'include': incl_fname}, - 'info': info}) + self._add_expr(OrderedDict({'include': incl_fname}), info) exprs_include = self._include(include, info, incl_fname, self._included) if exprs_include: @@ -165,17 +174,18 @@ class QAPISchemaParser: for name, value in pragma.items(): self._pragma(name, value, info) else: - expr_elem = {'expr': expr, - 'info': info} - if cur_doc: - if not cur_doc.symbol: - raise QAPISemError( - cur_doc.info, "definition documentation required") - expr_elem['doc'] = cur_doc - self.exprs.append(expr_elem) + if cur_doc and not cur_doc.symbol: + raise QAPISemError( + cur_doc.info, "definition documentation required") + self._add_expr(expr, info, cur_doc) cur_doc = None self.reject_expr_doc(cur_doc) + def _add_expr(self, expr: Mapping[str, object], + info: QAPISourceInfo, + doc: Optional['QAPIDoc'] = None) -> None: + self.exprs.append(QAPIExpression(expr, info, doc)) + @staticmethod def reject_expr_doc(doc: Optional['QAPIDoc']) -> None: if doc and doc.symbol: @@ -784,7 +794,7 @@ class QAPIDoc: % feature.name) self.features[feature.name].connect(feature) - def check_expr(self, expr: TopLevelExpr) -> None: + def check_expr(self, expr: QAPIExpression) -> None: if self.has_section('Returns') and 'command' not in expr: raise QAPISemError(self.info, "'Returns:' is only valid for commands") diff --git a/scripts/qapi/schema.py b/scripts/qapi/schema.py index cd8661125c..207e4d71f3 100644 --- a/scripts/qapi/schema.py +++ b/scripts/qapi/schema.py @@ -17,7 +17,7 @@ from collections import OrderedDict import os import re -from typing import Optional +from typing import List, Optional from .common import ( POINTER_SUFFIX, @@ -29,7 +29,7 @@ from .common import ( ) from .error import QAPIError, QAPISemError, QAPISourceError from .expr import check_exprs -from .parser import QAPISchemaParser +from .parser import QAPIExpression, QAPISchemaParser class QAPISchemaIfCond: @@ -964,10 +964,11 @@ class QAPISchema: name = self._module_name(fname) return self._module_dict[name] - def _def_include(self, expr, info, doc): + def _def_include(self, expr: QAPIExpression): include = expr['include'] - assert doc is None - self._def_entity(QAPISchemaInclude(self._make_module(include), info)) + assert expr.doc is None + self._def_entity( + QAPISchemaInclude(self._make_module(include), expr.info)) def _def_builtin_type(self, name, json_type, c_type): self._def_entity(QAPISchemaBuiltinType(name, json_type, c_type)) @@ -1045,14 +1046,15 @@ class QAPISchema: name, info, None, ifcond, None, None, members, None)) return name - def _def_enum_type(self, expr, info, doc): + def _def_enum_type(self, expr: QAPIExpression): name = expr['enum'] data = expr['data'] prefix = expr.get('prefix') ifcond = QAPISchemaIfCond(expr.get('if')) + info = expr.info features = self._make_features(expr.get('features'), info) self._def_entity(QAPISchemaEnumType( - name, info, doc, ifcond, features, + name, info, expr.doc, ifcond, features, self._make_enum_members(data, info), prefix)) def _make_member(self, name, typ, ifcond, features, info): @@ -1072,14 +1074,15 @@ class QAPISchema: value.get('features'), info) for (key, value) in data.items()] - def _def_struct_type(self, expr, info, doc): + def _def_struct_type(self, expr: QAPIExpression): name = expr['struct'] base = expr.get('base') data = expr['data'] + info = expr.info ifcond = QAPISchemaIfCond(expr.get('if')) features = self._make_features(expr.get('features'), info) self._def_entity(QAPISchemaObjectType( - name, info, doc, ifcond, features, base, + name, info, expr.doc, ifcond, features, base, self._make_members(data, info), None)) @@ -1089,11 +1092,13 @@ class QAPISchema: typ = self._make_array_type(typ[0], info) return QAPISchemaVariant(case, info, typ, ifcond) - def _def_union_type(self, expr, info, doc): + def _def_union_type(self, expr: QAPIExpression): name = expr['union'] base = expr['base'] tag_name = expr['discriminator'] data = expr['data'] + assert isinstance(data, dict) + info = expr.info ifcond = QAPISchemaIfCond(expr.get('if')) features = self._make_features(expr.get('features'), info) if isinstance(base, dict): @@ -1105,17 +1110,19 @@ class QAPISchema: QAPISchemaIfCond(value.get('if')), info) for (key, value) in data.items()] - members = [] + members: List[QAPISchemaObjectTypeMember] = [] self._def_entity( - QAPISchemaObjectType(name, info, doc, ifcond, features, + QAPISchemaObjectType(name, info, expr.doc, ifcond, features, base, members, QAPISchemaVariants( tag_name, info, None, variants))) - def _def_alternate_type(self, expr, info, doc): + def _def_alternate_type(self, expr: QAPIExpression): name = expr['alternate'] data = expr['data'] + assert isinstance(data, dict) ifcond = QAPISchemaIfCond(expr.get('if')) + info = expr.info features = self._make_features(expr.get('features'), info) variants = [ self._make_variant(key, value['type'], @@ -1124,11 +1131,11 @@ class QAPISchema: for (key, value) in data.items()] tag_member = QAPISchemaObjectTypeMember('type', info, 'QType', False) self._def_entity( - QAPISchemaAlternateType(name, info, doc, ifcond, features, - QAPISchemaVariants( - None, info, tag_member, variants))) + QAPISchemaAlternateType( + name, info, expr.doc, ifcond, features, + QAPISchemaVariants(None, info, tag_member, variants))) - def _def_command(self, expr, info, doc): + def _def_command(self, expr: QAPIExpression): name = expr['command'] data = expr.get('data') rets = expr.get('returns') @@ -1139,6 +1146,7 @@ class QAPISchema: allow_preconfig = expr.get('allow-preconfig', False) coroutine = expr.get('coroutine', False) ifcond = QAPISchemaIfCond(expr.get('if')) + info = expr.info features = self._make_features(expr.get('features'), info) if isinstance(data, OrderedDict): data = self._make_implicit_object_type( @@ -1147,44 +1155,42 @@ class QAPISchema: if isinstance(rets, list): assert len(rets) == 1 rets = self._make_array_type(rets[0], info) - self._def_entity(QAPISchemaCommand(name, info, doc, ifcond, features, - data, rets, + self._def_entity(QAPISchemaCommand(name, info, expr.doc, ifcond, + features, data, rets, gen, success_response, boxed, allow_oob, allow_preconfig, coroutine)) - def _def_event(self, expr, info, doc): + def _def_event(self, expr: QAPIExpression): name = expr['event'] data = expr.get('data') boxed = expr.get('boxed', False) ifcond = QAPISchemaIfCond(expr.get('if')) + info = expr.info features = self._make_features(expr.get('features'), info) if isinstance(data, OrderedDict): data = self._make_implicit_object_type( name, info, ifcond, 'arg', self._make_members(data, info)) - self._def_entity(QAPISchemaEvent(name, info, doc, ifcond, features, - data, boxed)) + self._def_entity(QAPISchemaEvent(name, info, expr.doc, ifcond, + features, data, boxed)) def _def_exprs(self, exprs): - for expr_elem in exprs: - expr = expr_elem['expr'] - info = expr_elem['info'] - doc = expr_elem.get('doc') + for expr in exprs: if 'enum' in expr: - self._def_enum_type(expr, info, doc) + self._def_enum_type(expr) elif 'struct' in expr: - self._def_struct_type(expr, info, doc) + self._def_struct_type(expr) elif 'union' in expr: - self._def_union_type(expr, info, doc) + self._def_union_type(expr) elif 'alternate' in expr: - self._def_alternate_type(expr, info, doc) + self._def_alternate_type(expr) elif 'command' in expr: - self._def_command(expr, info, doc) + self._def_command(expr) elif 'event' in expr: - self._def_event(expr, info, doc) + self._def_event(expr) elif 'include' in expr: - self._def_include(expr, info, doc) + self._def_include(expr) else: assert False From 67a81f9fb78d73398051fed0df7a0aac5b61b7c5 Mon Sep 17 00:00:00 2001 From: John Snow Date: Tue, 14 Feb 2023 19:00:10 -0500 Subject: [PATCH 024/129] qapi: remove _JSONObject We can remove this alias as it only has two usages now, and no longer pays for the confusion of "yet another type". Signed-off-by: John Snow Message-Id: <20230215000011.1725012-6-jsnow@redhat.com> Reviewed-by: Markus Armbruster --- scripts/qapi/expr.py | 13 +++---------- scripts/qapi/parser.py | 5 ++--- 2 files changed, 5 insertions(+), 13 deletions(-) diff --git a/scripts/qapi/expr.py b/scripts/qapi/expr.py index b8f905543e..ca01ea6f4a 100644 --- a/scripts/qapi/expr.py +++ b/scripts/qapi/expr.py @@ -47,14 +47,6 @@ from .parser import QAPIExpression from .source import QAPISourceInfo -# Deserialized JSON objects as returned by the parser. -# The values of this mapping are not necessary to exhaustively type -# here (and also not practical as long as mypy lacks recursive -# types), because the purpose of this module is to interrogate that -# type. -_JSONObject = Dict[str, object] - - # See check_name_str(), below. valid_name = re.compile(r'(__[a-z0-9.-]+_)?' r'(x-)?' @@ -191,7 +183,7 @@ def check_defn_name_str(name: str, info: QAPISourceInfo, meta: str) -> None: info, "%s name should not end in 'List'" % meta) -def check_keys(value: _JSONObject, +def check_keys(value: Dict[str, object], info: QAPISourceInfo, source: str, required: List[str], @@ -255,7 +247,8 @@ def check_flags(expr: QAPIExpression) -> None: expr.info, "flags 'allow-oob' and 'coroutine' are incompatible") -def check_if(expr: _JSONObject, info: QAPISourceInfo, source: str) -> None: +def check_if(expr: Dict[str, object], + info: QAPISourceInfo, source: str) -> None: """ Validate the ``if`` member of an object. diff --git a/scripts/qapi/parser.py b/scripts/qapi/parser.py index 50906e27d4..d570086e1a 100644 --- a/scripts/qapi/parser.py +++ b/scripts/qapi/parser.py @@ -42,9 +42,8 @@ if TYPE_CHECKING: _ExprValue = Union[List[object], Dict[str, object], str, bool] -# FIXME: Consolidate and centralize definitions for _ExprValue, -# JSONValue, and _JSONObject; currently scattered across several -# modules. +# FIXME: Consolidate and centralize definitions for _ExprValue and +# JSONValue; currently scattered across several modules. class QAPIExpression(Dict[str, object]): From c7b7a7ded9376ad936cfedd843752789ca61bc3b Mon Sep 17 00:00:00 2001 From: John Snow Date: Tue, 14 Feb 2023 19:00:11 -0500 Subject: [PATCH 025/129] qapi: remove JSON value FIXME With the two major JSON-ish type hierarchies clarified for distinct purposes; QAPIExpression for parsed expressions and JSONValue for introspection data, remove this FIXME as no longer an action item. A third JSON-y data type, _ExprValue, is not meant to represent JSON in the abstract but rather only the possible legal return values from a single function, get_expr(). It isn't appropriate to attempt to merge it with either of the above two types. In theory, it may be possible to define a completely agnostic one-size-fits-all JSON type hierarchy that any other user could borrow - in practice, it's tough to wrangle the differences between invariant, covariant and contravariant types: input and output parameters demand different properties of such a structure. However, QAPIExpression serves to authoritatively type user input to the QAPI parser, while JSONValue serves to authoritatively type qapi generator *output* to be served back to client users at runtime via QMP. The AST for these two types are different and cannot be wholly merged into a unified syntax. They could, in theory, share some JSON primitive definitions. In practice, this is currently more trouble than it's worth with mypy's current expressive power. As such, declare this "done enough for now". Signed-off-by: John Snow Message-Id: <20230215000011.1725012-7-jsnow@redhat.com> Reviewed-by: Markus Armbruster --- scripts/qapi/parser.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/scripts/qapi/parser.py b/scripts/qapi/parser.py index d570086e1a..878f90b458 100644 --- a/scripts/qapi/parser.py +++ b/scripts/qapi/parser.py @@ -42,10 +42,6 @@ if TYPE_CHECKING: _ExprValue = Union[List[object], Dict[str, object], str, bool] -# FIXME: Consolidate and centralize definitions for _ExprValue and -# JSONValue; currently scattered across several modules. - - class QAPIExpression(Dict[str, object]): # pylint: disable=too-few-public-methods def __init__(self, From 6f1e91f716a96651feae89dfd674b2ea3bf8e282 Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Tue, 7 Feb 2023 08:51:04 +0100 Subject: [PATCH 026/129] error: Drop superfluous #include "qapi/qmp/qerror.h" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Markus Armbruster Message-Id: <20230207075115.1525-2-armbru@redhat.com> Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Juan Quintela Reviewed-by: Konstantin Kostiuk --- authz/listfile.c | 1 - backends/cryptodev-vhost.c | 1 - backends/rng.c | 1 - backends/vhost-user.c | 1 - block/backup.c | 1 - block/commit.c | 1 - block/mirror.c | 1 - block/stream.c | 1 - hw/core/machine.c | 1 - hw/i386/pc.c | 1 - hw/i386/x86.c | 1 - hw/misc/xlnx-zynqmp-apu-ctrl.c | 1 - migration/colo.c | 1 - migration/migration-hmp-cmds.c | 1 - qga/main.c | 1 - softmmu/qtest.c | 1 - target/i386/monitor.c | 1 - target/i386/sev-sysemu-stub.c | 1 - target/i386/sev.c | 1 - util/qemu-config.c | 1 - 20 files changed, 20 deletions(-) diff --git a/authz/listfile.c b/authz/listfile.c index da3a0e69a2..45a60e987d 100644 --- a/authz/listfile.c +++ b/authz/listfile.c @@ -30,7 +30,6 @@ #include "qapi/qapi-visit-authz.h" #include "qapi/qmp/qjson.h" #include "qapi/qmp/qobject.h" -#include "qapi/qmp/qerror.h" #include "qapi/qobject-input-visitor.h" diff --git a/backends/cryptodev-vhost.c b/backends/cryptodev-vhost.c index 572f87b3be..74ea0ad63d 100644 --- a/backends/cryptodev-vhost.c +++ b/backends/cryptodev-vhost.c @@ -28,7 +28,6 @@ #ifdef CONFIG_VHOST_CRYPTO #include "qapi/error.h" -#include "qapi/qmp/qerror.h" #include "qemu/error-report.h" #include "hw/virtio/virtio-crypto.h" #include "sysemu/cryptodev-vhost-user.h" diff --git a/backends/rng.c b/backends/rng.c index 6c7bf64426..9bbd0c77b6 100644 --- a/backends/rng.c +++ b/backends/rng.c @@ -13,7 +13,6 @@ #include "qemu/osdep.h" #include "sysemu/rng.h" #include "qapi/error.h" -#include "qapi/qmp/qerror.h" #include "qemu/module.h" #include "qom/object_interfaces.h" diff --git a/backends/vhost-user.c b/backends/vhost-user.c index 7bfcaef976..0596223ac4 100644 --- a/backends/vhost-user.c +++ b/backends/vhost-user.c @@ -13,7 +13,6 @@ #include "qemu/osdep.h" #include "qapi/error.h" -#include "qapi/qmp/qerror.h" #include "qemu/error-report.h" #include "qom/object_interfaces.h" #include "sysemu/vhost-user-backend.h" diff --git a/block/backup.c b/block/backup.c index 824d39acaa..5b8863b88c 100644 --- a/block/backup.c +++ b/block/backup.c @@ -22,7 +22,6 @@ #include "block/block-copy.h" #include "block/dirty-bitmap.h" #include "qapi/error.h" -#include "qapi/qmp/qerror.h" #include "qemu/cutils.h" #include "sysemu/block-backend.h" #include "qemu/bitmap.h" diff --git a/block/commit.c b/block/commit.c index 41e3599281..387a720d03 100644 --- a/block/commit.c +++ b/block/commit.c @@ -18,7 +18,6 @@ #include "block/block_int.h" #include "block/blockjob_int.h" #include "qapi/error.h" -#include "qapi/qmp/qerror.h" #include "qemu/ratelimit.h" #include "qemu/memalign.h" #include "sysemu/block-backend.h" diff --git a/block/mirror.c b/block/mirror.c index ab326b67c9..0f6551cf5b 100644 --- a/block/mirror.c +++ b/block/mirror.c @@ -21,7 +21,6 @@ #include "block/dirty-bitmap.h" #include "sysemu/block-backend.h" #include "qapi/error.h" -#include "qapi/qmp/qerror.h" #include "qemu/ratelimit.h" #include "qemu/bitmap.h" #include "qemu/memalign.h" diff --git a/block/stream.c b/block/stream.c index 8744ad103f..e77a033233 100644 --- a/block/stream.c +++ b/block/stream.c @@ -16,7 +16,6 @@ #include "block/block_int.h" #include "block/blockjob_int.h" #include "qapi/error.h" -#include "qapi/qmp/qerror.h" #include "qapi/qmp/qdict.h" #include "qemu/ratelimit.h" #include "sysemu/block-backend.h" diff --git a/hw/core/machine.c b/hw/core/machine.c index f73fc4c45c..f29e700ee4 100644 --- a/hw/core/machine.c +++ b/hw/core/machine.c @@ -13,7 +13,6 @@ #include "qemu/osdep.h" #include "qemu/option.h" #include "qemu/accel.h" -#include "qapi/qmp/qerror.h" #include "sysemu/replay.h" #include "qemu/units.h" #include "hw/boards.h" diff --git a/hw/i386/pc.c b/hw/i386/pc.c index 6e592bd969..a7a2ededf9 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -92,7 +92,6 @@ #include "hw/mem/memory-device.h" #include "sysemu/replay.h" #include "target/i386/cpu.h" -#include "qapi/qmp/qerror.h" #include "e820_memory_layout.h" #include "fw_cfg.h" #include "trace.h" diff --git a/hw/i386/x86.c b/hw/i386/x86.c index eaff4227bd..48be7a1c23 100644 --- a/hw/i386/x86.c +++ b/hw/i386/x86.c @@ -28,7 +28,6 @@ #include "qemu/datadir.h" #include "qemu/guest-random.h" #include "qapi/error.h" -#include "qapi/qmp/qerror.h" #include "qapi/qapi-visit-common.h" #include "qapi/clone-visitor.h" #include "qapi/qapi-visit-machine.h" diff --git a/hw/misc/xlnx-zynqmp-apu-ctrl.c b/hw/misc/xlnx-zynqmp-apu-ctrl.c index 20de23cf67..3d2be95e6d 100644 --- a/hw/misc/xlnx-zynqmp-apu-ctrl.c +++ b/hw/misc/xlnx-zynqmp-apu-ctrl.c @@ -18,7 +18,6 @@ #include "hw/register.h" #include "qemu/bitops.h" -#include "qapi/qmp/qerror.h" #include "hw/misc/xlnx-zynqmp-apu-ctrl.h" diff --git a/migration/colo.c b/migration/colo.c index 232c8d44b1..0716e64689 100644 --- a/migration/colo.c +++ b/migration/colo.c @@ -33,7 +33,6 @@ #include "net/colo.h" #include "block/block.h" #include "qapi/qapi-events-migration.h" -#include "qapi/qmp/qerror.h" #include "sysemu/cpus.h" #include "sysemu/runstate.h" #include "net/filter.h" diff --git a/migration/migration-hmp-cmds.c b/migration/migration-hmp-cmds.c index ef25bc8929..72519ea99f 100644 --- a/migration/migration-hmp-cmds.c +++ b/migration/migration-hmp-cmds.c @@ -23,7 +23,6 @@ #include "qapi/qapi-commands-migration.h" #include "qapi/qapi-visit-migration.h" #include "qapi/qmp/qdict.h" -#include "qapi/qmp/qerror.h" #include "qapi/string-input-visitor.h" #include "qapi/string-output-visitor.h" #include "qemu/cutils.h" diff --git a/qga/main.c b/qga/main.c index 85b7d6ced5..2b992a55b3 100644 --- a/qga/main.c +++ b/qga/main.c @@ -24,7 +24,6 @@ #include "qapi/qmp/qjson.h" #include "guest-agent-core.h" #include "qga-qapi-init-commands.h" -#include "qapi/qmp/qerror.h" #include "qapi/error.h" #include "channel.h" #include "qemu/cutils.h" diff --git a/softmmu/qtest.c b/softmmu/qtest.c index d3e0ab4eda..34bd2a33a7 100644 --- a/softmmu/qtest.c +++ b/softmmu/qtest.c @@ -28,7 +28,6 @@ #include "qemu/error-report.h" #include "qemu/module.h" #include "qemu/cutils.h" -#include "qapi/qmp/qerror.h" #include "qom/object_interfaces.h" #include CONFIG_DEVICES #ifdef CONFIG_PSERIES diff --git a/target/i386/monitor.c b/target/i386/monitor.c index ad5b7b8bb5..6512846327 100644 --- a/target/i386/monitor.c +++ b/target/i386/monitor.c @@ -28,7 +28,6 @@ #include "monitor/hmp-target.h" #include "monitor/hmp.h" #include "qapi/qmp/qdict.h" -#include "qapi/qmp/qerror.h" #include "sysemu/kvm.h" #include "qapi/error.h" #include "qapi/qapi-commands-misc-target.h" diff --git a/target/i386/sev-sysemu-stub.c b/target/i386/sev-sysemu-stub.c index 7a29295d1e..96e1c15cc3 100644 --- a/target/i386/sev-sysemu-stub.c +++ b/target/i386/sev-sysemu-stub.c @@ -15,7 +15,6 @@ #include "monitor/monitor.h" #include "monitor/hmp-target.h" #include "qapi/qapi-commands-misc-target.h" -#include "qapi/qmp/qerror.h" #include "qapi/error.h" #include "sev.h" diff --git a/target/i386/sev.c b/target/i386/sev.c index 32f7dbac4e..0ec970496e 100644 --- a/target/i386/sev.c +++ b/target/i386/sev.c @@ -34,7 +34,6 @@ #include "monitor/monitor.h" #include "monitor/hmp-target.h" #include "qapi/qapi-commands-misc-target.h" -#include "qapi/qmp/qerror.h" #include "exec/confidential-guest-support.h" #include "hw/i386/pc.h" #include "exec/address-spaces.h" diff --git a/util/qemu-config.c b/util/qemu-config.c index d63f27438d..42076efe1e 100644 --- a/util/qemu-config.c +++ b/util/qemu-config.c @@ -2,7 +2,6 @@ #include "block/qdict.h" /* for qdict_extract_subqdict() */ #include "qapi/error.h" #include "qapi/qapi-commands-misc.h" -#include "qapi/qmp/qerror.h" #include "qapi/qmp/qdict.h" #include "qapi/qmp/qlist.h" #include "qemu/error-report.h" From f969c627e31fe7752fd5c2ff036e587ec9749a25 Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Tue, 7 Feb 2023 08:51:05 +0100 Subject: [PATCH 027/129] dump: Improve error message when target doesn't support memory dump MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The QERR_ macros are leftovers from the days of "rich" error objects. We've been trying to reduce their remaining use. Get rid of a use of QERR_UNSUPPORTED, and improve the rather vague error message (qemu) dump-guest-memory mumble Error: this feature or command is not currently supported to Error: dumping guest memory is not supported on this target Signed-off-by: Markus Armbruster Message-Id: <20230207075115.1525-3-armbru@redhat.com> Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Juan Quintela [Error message tweaked] --- dump/dump.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dump/dump.c b/dump/dump.c index 279b07f09b..e6833e4cc0 100644 --- a/dump/dump.c +++ b/dump/dump.c @@ -1854,7 +1854,8 @@ static void dump_init(DumpState *s, int fd, bool has_format, */ ret = cpu_get_dump_info(&s->dump_info, &s->guest_phys_blocks); if (ret < 0) { - error_setg(errp, QERR_UNSUPPORTED); + error_setg(errp, + "dumping guest memory is not supported on this target"); goto cleanup; } From f1a4697c236aae8f7d13042e4c6a31c228aa8595 Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Tue, 7 Feb 2023 08:51:06 +0100 Subject: [PATCH 028/129] dump: Assert cpu_get_note_size() can't fail MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The only way cpu_get_note_size() can return a negative value is integer overflow in the non-stub versions, which is a programming error. The stub version is not actually reachable, because the cpu_get_dump_info() stub will fail first. Use assert(). This gets rid of another use of QERR_UNSUPPORTED. Signed-off-by: Markus Armbruster Message-Id: <20230207075115.1525-4-armbru@redhat.com> Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Juan Quintela --- dump/dump.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/dump/dump.c b/dump/dump.c index e6833e4cc0..1362810991 100644 --- a/dump/dump.c +++ b/dump/dump.c @@ -1865,10 +1865,7 @@ static void dump_init(DumpState *s, int fd, bool has_format, s->note_size = cpu_get_note_size(s->dump_info.d_class, s->dump_info.d_machine, nr_cpus); - if (s->note_size < 0) { - error_setg(errp, QERR_UNSUPPORTED); - goto cleanup; - } + assert(s->note_size >= 0); /* * The goal of this block is to (a) update the previously guessed From a0d0267779850f0dee70656dd7c0d11a458bfbaa Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Tue, 7 Feb 2023 08:51:07 +0100 Subject: [PATCH 029/129] hw/core: Improve error message when machine doesn't provide NMIs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The QERR_ macros are leftovers from the days of "rich" error objects. We've been trying to reduce their remaining use. Get rid of a use of QERR_UNSUPPORTED, and improve the rather vague error message (qemu) nmi Error: this feature or command is not currently supported to Error: machine does not provide NMIs Signed-off-by: Markus Armbruster Message-Id: <20230207075115.1525-5-armbru@redhat.com> Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Juan Quintela --- hw/core/nmi.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/hw/core/nmi.c b/hw/core/nmi.c index 481c4b3c7e..a7bce8a04a 100644 --- a/hw/core/nmi.c +++ b/hw/core/nmi.c @@ -22,7 +22,6 @@ #include "qemu/osdep.h" #include "hw/nmi.h" #include "qapi/error.h" -#include "qapi/qmp/qerror.h" #include "qemu/module.h" #include "monitor/monitor.h" @@ -70,7 +69,7 @@ void nmi_monitor_handle(int cpu_index, Error **errp) if (ns.handled) { error_propagate(errp, ns.err); } else { - error_setg(errp, QERR_UNSUPPORTED); + error_setg(errp, "machine does not provide NMIs"); } } From 0ca6745c74778d84c05ca2144cf0d15f8bfe26d8 Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Tue, 7 Feb 2023 08:51:08 +0100 Subject: [PATCH 030/129] hw/smbios: Dumb down smbios_entry_add() stub MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The QERR_ macros are leftovers from the days of "rich" error objects. We've been trying to reduce their remaining use. smbios_entry_add() is only ever called on behalf of CLI option -smbios. Since qemu-options.hx sets @arch_mask to QEMU_ARCH_I386 | QEMU_ARCH_ARM, it is reachable only for these targets. Since they provide a real smbios_entry_add(), the stub is unreachable. There's no point in unreachable code keeping QERR_UNSUPPORTED alive. Dumb it down to g_assert_not_reached(). Signed-off-by: Markus Armbruster Message-Id: <20230207075115.1525-6-armbru@redhat.com> Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Juan Quintela --- hw/smbios/smbios-stub.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/hw/smbios/smbios-stub.c b/hw/smbios/smbios-stub.c index 64e5ba93ec..e8808adfda 100644 --- a/hw/smbios/smbios-stub.c +++ b/hw/smbios/smbios-stub.c @@ -21,11 +21,9 @@ */ #include "qemu/osdep.h" -#include "qapi/error.h" -#include "qapi/qmp/qerror.h" #include "hw/firmware/smbios.h" void smbios_entry_add(QemuOpts *opts, Error **errp) { - error_setg(errp, QERR_UNSUPPORTED); + g_assert_not_reached(); } From 588c13fcb015896e4d1f7a516d8ce6336e64133b Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Tue, 7 Feb 2023 08:51:09 +0100 Subject: [PATCH 031/129] hw/acpi: Dumb down acpi_table_add() stub MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The QERR_ macros are leftovers from the days of "rich" error objects. We've been trying to reduce their remaining use. acpi_table_add() is only ever called on behalf of CLI option -acpitable. Since qemu-options.hx sets @arch_mask to QEMU_ARCH_I386, it is reachable only for these targets. Since they provide a real acpi_table_add(), the stub is unreachable. There's no point in unreachable code keeping QERR_UNSUPPORTED alive. Dumb it down to g_assert_not_reached(). Signed-off-by: Markus Armbruster Message-Id: <20230207075115.1525-7-armbru@redhat.com> Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Juan Quintela --- hw/acpi/acpi-stub.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/hw/acpi/acpi-stub.c b/hw/acpi/acpi-stub.c index 4c9d081ed4..e268ce9b1a 100644 --- a/hw/acpi/acpi-stub.c +++ b/hw/acpi/acpi-stub.c @@ -19,11 +19,9 @@ */ #include "qemu/osdep.h" -#include "qapi/error.h" -#include "qapi/qmp/qerror.h" #include "hw/acpi/acpi.h" void acpi_table_add(const QemuOpts *opts, Error **errp) { - error_setg(errp, QERR_UNSUPPORTED); + g_assert_not_reached(); } From 36ebc7db796e6ac97b400dc544192e2e36986b03 Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Tue, 7 Feb 2023 08:51:10 +0100 Subject: [PATCH 032/129] hw/acpi: Move QMP command to hw/core/ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The QERR_ macros are leftovers from the days of "rich" error objects. We've been trying to reduce their remaining use. qmp_query_vm_generation_id() in stubs/vmgenid.c is the last user of QERR_UNSUPPORTED outside qga/. Unlike the stubs we just dropped, it is actually reachable, namely when CONFIG_ACPI_VMGENID is off. It always fails like (qemu) info vm-generation-id Error: this feature or command is not currently supported Turns out the real qmp_query_vm_generation_id() doesn't actually depend on CONFIG_ACPI_VMGENID, and fails safely when it's off. Move it to hw/core/machine-qmp-cmds.c, and drop the stub. The error message becomes Error: VM Generation ID device not found Feels like an improvement to me. Signed-off-by: Markus Armbruster Message-Id: <20230207075115.1525-8-armbru@redhat.com> Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Juan Quintela --- MAINTAINERS | 1 - hw/acpi/vmgenid.c | 18 ------------------ hw/core/machine-qmp-cmds.c | 18 ++++++++++++++++++ stubs/meson.build | 1 - stubs/vmgenid.c | 10 ---------- 5 files changed, 18 insertions(+), 30 deletions(-) delete mode 100644 stubs/vmgenid.c diff --git a/MAINTAINERS b/MAINTAINERS index 9adb628627..eb917e48c0 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2273,7 +2273,6 @@ F: hw/acpi/vmgenid.c F: include/hw/acpi/vmgenid.h F: docs/specs/vmgenid.txt F: tests/qtest/vmgenid-test.c -F: stubs/vmgenid.c LED M: Philippe Mathieu-Daudé diff --git a/hw/acpi/vmgenid.c b/hw/acpi/vmgenid.c index 0c9f158ac9..a39315c1b3 100644 --- a/hw/acpi/vmgenid.c +++ b/hw/acpi/vmgenid.c @@ -12,7 +12,6 @@ #include "qemu/osdep.h" #include "qapi/error.h" -#include "qapi/qapi-commands-machine.h" #include "qemu/module.h" #include "hw/acpi/acpi.h" #include "hw/acpi/aml-build.h" @@ -244,20 +243,3 @@ static void vmgenid_register_types(void) } type_init(vmgenid_register_types) - -GuidInfo *qmp_query_vm_generation_id(Error **errp) -{ - GuidInfo *info; - VmGenIdState *vms; - Object *obj = find_vmgenid_dev(); - - if (!obj) { - error_setg(errp, "VM Generation ID device not found"); - return NULL; - } - vms = VMGENID(obj); - - info = g_malloc0(sizeof(*info)); - info->guid = qemu_uuid_unparse_strdup(&vms->guid); - return info; -} diff --git a/hw/core/machine-qmp-cmds.c b/hw/core/machine-qmp-cmds.c index 44b5da8880..a6ed3a63c3 100644 --- a/hw/core/machine-qmp-cmds.c +++ b/hw/core/machine-qmp-cmds.c @@ -8,6 +8,7 @@ */ #include "qemu/osdep.h" +#include "hw/acpi/vmgenid.h" #include "hw/boards.h" #include "hw/intc/intc.h" #include "hw/mem/memory-device.h" @@ -383,3 +384,20 @@ HumanReadableText *qmp_x_query_irq(Error **errp) return human_readable_text_from_str(buf); } + +GuidInfo *qmp_query_vm_generation_id(Error **errp) +{ + GuidInfo *info; + VmGenIdState *vms; + Object *obj = find_vmgenid_dev(); + + if (!obj) { + error_setg(errp, "VM Generation ID device not found"); + return NULL; + } + vms = VMGENID(obj); + + info = g_malloc0(sizeof(*info)); + info->guid = qemu_uuid_unparse_strdup(&vms->guid); + return info; +} diff --git a/stubs/meson.build b/stubs/meson.build index 981585cbdf..7657467a5d 100644 --- a/stubs/meson.build +++ b/stubs/meson.build @@ -45,7 +45,6 @@ stub_ss.add(files('target-get-monitor-def.c')) stub_ss.add(files('target-monitor-defs.c')) stub_ss.add(files('trace-control.c')) stub_ss.add(files('uuid.c')) -stub_ss.add(files('vmgenid.c')) stub_ss.add(files('vmstate.c')) stub_ss.add(files('vm-stop.c')) stub_ss.add(files('win32-kbd-hook.c')) diff --git a/stubs/vmgenid.c b/stubs/vmgenid.c deleted file mode 100644 index bfad656c6c..0000000000 --- a/stubs/vmgenid.c +++ /dev/null @@ -1,10 +0,0 @@ -#include "qemu/osdep.h" -#include "qapi/error.h" -#include "qapi/qapi-commands-machine.h" -#include "qapi/qmp/qerror.h" - -GuidInfo *qmp_query_vm_generation_id(Error **errp) -{ - error_setg(errp, QERR_UNSUPPORTED); - return NULL; -} From c40233593ed5732de1676412527e42431e33e62c Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Tue, 7 Feb 2023 08:51:11 +0100 Subject: [PATCH 033/129] qga: Drop dangling reference to QERR_QGA_LOGGING_DISABLED MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit slog()'s function comment advises to use QERR_QGA_LOGGING_DISABLED. This macro never existed. The reference got added in commit e3d4d25206a "guest agent: add guest agent RPCs/commands" along with QERR_QGA_LOGGING_FAILED, so maybe that one was meant. However, QERR_QGA_LOGGING_FAILED was never actually used, and was removed in commit d73f0beadb5 "qerror.h: Remove unused error classes". Drop the dangling reference. Signed-off-by: Markus Armbruster Message-Id: <20230207075115.1525-9-armbru@redhat.com> Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Juan Quintela Reviewed-by: Konstantin Kostiuk --- qga/commands.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/qga/commands.c b/qga/commands.c index 360077364e..172826f8f8 100644 --- a/qga/commands.c +++ b/qga/commands.c @@ -32,9 +32,8 @@ #define GUEST_FILE_READ_COUNT_MAX (48 * MiB) /* Note: in some situations, like with the fsfreeze, logging may be - * temporarilly disabled. if it is necessary that a command be able - * to log for accounting purposes, check ga_logging_enabled() beforehand, - * and use the QERR_QGA_LOGGING_DISABLED to generate an error + * temporarily disabled. if it is necessary that a command be able + * to log for accounting purposes, check ga_logging_enabled() beforehand. */ void slog(const gchar *fmt, ...) { From 0ec8384f839844dfcccdc4784b30c9c9e7171b92 Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Tue, 7 Feb 2023 08:51:12 +0100 Subject: [PATCH 034/129] replay: Simplify setting replay blockers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit replay_add_blocker() takes an Error *. All callers pass one created like this: error_setg(&blocker, QERR_REPLAY_NOT_SUPPORTED, "some feature"); Folding this into replay_add_blocker() simplifies the callers, losing a bit of generality we haven't needed in more than six years. Since there are no other uses of macro QERR_REPLAY_NOT_SUPPORTED, replace the remaining one by its expansion, and drop the macro. Signed-off-by: Markus Armbruster Message-Id: <20230207075115.1525-10-armbru@redhat.com> Reviewed-by: Philippe Mathieu-Daudé --- include/qapi/qmp/qerror.h | 3 --- include/sysemu/replay.h | 2 +- replay/replay.c | 6 +++++- replay/stubs-system.c | 2 +- softmmu/rtc.c | 5 +---- softmmu/vl.c | 13 +++---------- 6 files changed, 11 insertions(+), 20 deletions(-) diff --git a/include/qapi/qmp/qerror.h b/include/qapi/qmp/qerror.h index 87ca83b155..09006e69f7 100644 --- a/include/qapi/qmp/qerror.h +++ b/include/qapi/qmp/qerror.h @@ -59,9 +59,6 @@ #define QERR_QGA_COMMAND_FAILED \ "Guest agent command failed, error was '%s'" -#define QERR_REPLAY_NOT_SUPPORTED \ - "Record/replay feature is not supported for '%s'" - #define QERR_UNSUPPORTED \ "this feature or command is not currently supported" diff --git a/include/sysemu/replay.h b/include/sysemu/replay.h index 7ec0882b50..6e5ab09f71 100644 --- a/include/sysemu/replay.h +++ b/include/sysemu/replay.h @@ -72,7 +72,7 @@ void replay_start(void); /*! Closes replay log file and frees other resources. */ void replay_finish(void); /*! Adds replay blocker with the specified error description */ -void replay_add_blocker(Error *reason); +void replay_add_blocker(const char *feature); /* Returns name of the replay log file */ const char *replay_get_filename(void); /* diff --git a/replay/replay.c b/replay/replay.c index 9a0dc1cf44..c39156c522 100644 --- a/replay/replay.c +++ b/replay/replay.c @@ -376,8 +376,12 @@ void replay_finish(void) replay_mode = REPLAY_MODE_NONE; } -void replay_add_blocker(Error *reason) +void replay_add_blocker(const char *feature) { + Error *reason = NULL; + + error_setg(&reason, "Record/replay feature is not supported for '%s'", + feature); replay_blockers = g_slist_prepend(replay_blockers, reason); } diff --git a/replay/stubs-system.c b/replay/stubs-system.c index 5c262b08f1..50cefdb2d6 100644 --- a/replay/stubs-system.c +++ b/replay/stubs-system.c @@ -12,7 +12,7 @@ void replay_input_sync_event(void) qemu_input_event_sync_impl(); } -void replay_add_blocker(Error *reason) +void replay_add_blocker(const char *feature) { } void replay_audio_in(size_t *recorded, void *samples, size_t *wpos, size_t size) diff --git a/softmmu/rtc.c b/softmmu/rtc.c index f7114bed7d..4b2bf75dd6 100644 --- a/softmmu/rtc.c +++ b/softmmu/rtc.c @@ -152,11 +152,8 @@ void configure_rtc(QemuOpts *opts) if (!strcmp(value, "utc")) { rtc_base_type = RTC_BASE_UTC; } else if (!strcmp(value, "localtime")) { - Error *blocker = NULL; rtc_base_type = RTC_BASE_LOCALTIME; - error_setg(&blocker, QERR_REPLAY_NOT_SUPPORTED, - "-rtc base=localtime"); - replay_add_blocker(blocker); + replay_add_blocker("-rtc base=localtime"); } else { rtc_base_type = RTC_BASE_DATETIME; configure_rtc_base_datetime(value); diff --git a/softmmu/vl.c b/softmmu/vl.c index 459588aa7d..6e526d95bb 100644 --- a/softmmu/vl.c +++ b/softmmu/vl.c @@ -1852,9 +1852,7 @@ static void qemu_apply_machine_options(QDict *qdict) } if (current_machine->smp.cpus > 1) { - Error *blocker = NULL; - error_setg(&blocker, QERR_REPLAY_NOT_SUPPORTED, "smp"); - replay_add_blocker(blocker); + replay_add_blocker("smp"); } } @@ -2774,13 +2772,8 @@ void qemu_init(int argc, char **argv) drive_add(IF_PFLASH, -1, optarg, PFLASH_OPTS); break; case QEMU_OPTION_snapshot: - { - Error *blocker = NULL; - snapshot = 1; - error_setg(&blocker, QERR_REPLAY_NOT_SUPPORTED, - "-snapshot"); - replay_add_blocker(blocker); - } + snapshot = 1; + replay_add_blocker("-snapshot"); break; case QEMU_OPTION_numa: opts = qemu_opts_parse_noisily(qemu_find_opts("numa"), From 0ac02656e28b5e3f1d8ed6c123bd38036df95e9e Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Tue, 7 Feb 2023 08:51:13 +0100 Subject: [PATCH 035/129] hw/core: Improve the query-hotpluggable-cpus error message MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The QERR_ macros are leftovers from the days of "rich" error objects. We've been trying to reduce their remaining use. Get rid of a use of QERR_FEATURE_DISABLED, and improve the slightly awkward error message (qemu) info hotpluggable-cpus Error: The feature 'query-hotpluggable-cpus' is not enabled to Error: machine does not support hot-plugging CPUs Signed-off-by: Markus Armbruster Message-Id: <20230207075115.1525-11-armbru@redhat.com> Reviewed-by: Philippe Mathieu-Daudé --- hw/core/machine-qmp-cmds.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/hw/core/machine-qmp-cmds.c b/hw/core/machine-qmp-cmds.c index a6ed3a63c3..2d904747c0 100644 --- a/hw/core/machine-qmp-cmds.c +++ b/hw/core/machine-qmp-cmds.c @@ -16,7 +16,6 @@ #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 "qapi/type-helpers.h" @@ -141,7 +140,7 @@ HotpluggableCPUList *qmp_query_hotpluggable_cpus(Error **errp) MachineClass *mc = MACHINE_GET_CLASS(ms); if (!mc->has_hotpluggable_cpus) { - error_setg(errp, QERR_FEATURE_DISABLED, "query-hotpluggable-cpus"); + error_setg(errp, "machine does not support hot-plugging CPUs"); return NULL; } From 43aef7e632c98573d907e7d86bbf3a1d6cc68f88 Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Tue, 7 Feb 2023 08:51:14 +0100 Subject: [PATCH 036/129] migration/colo: Improve an x-colo-lost-heartbeat error message MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The QERR_ macros are leftovers from the days of "rich" error objects. We've been trying to reduce their remaining use. Get rid of a use of QERR_FEATURE_DISABLED, and improve the somewhat imprecise error message (qemu) x_colo_lost_heartbeat Error: The feature 'colo' is not enabled to Error: VM is not in COLO mode Signed-off-by: Markus Armbruster Message-Id: <20230207075115.1525-12-armbru@redhat.com> Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Juan Quintela --- migration/colo-failover.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/migration/colo-failover.c b/migration/colo-failover.c index 42453481c4..6cb6f90357 100644 --- a/migration/colo-failover.c +++ b/migration/colo-failover.c @@ -17,7 +17,6 @@ #include "migration.h" #include "qapi/error.h" #include "qapi/qapi-commands-migration.h" -#include "qapi/qmp/qerror.h" #include "qemu/error-report.h" #include "trace.h" @@ -78,7 +77,7 @@ FailoverStatus failover_get_state(void) void qmp_x_colo_lost_heartbeat(Error **errp) { if (get_colo_mode() == COLO_MODE_NONE) { - error_setg(errp, QERR_FEATURE_DISABLED, "colo"); + error_setg(errp, "VM is not in COLO mode"); return; } From 1178710247017ee4f570b16a186ee48c250a18d1 Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Tue, 7 Feb 2023 08:51:15 +0100 Subject: [PATCH 037/129] rocker: Tweak stubbed out monitor commands' error messages MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The QERR_ macros are leftovers from the days of "rich" error objects. We've been trying to reduce their remaining use. The stubbed out Rocker monitor commands are the last remaining users of QERR_FEATURE_DISABLED. They fail like this: (qemu) info rocker mumble Error: The feature 'rocker' is not enabled The real rocker commands fail like this when the named object doesn't exist: Error: rocker mumble not found If that's good enough when Rocker is enabled, then it's good enough when it's disabled, so replace QERR_FEATURE_DISABLED with that, and drop the macro. Signed-off-by: Markus Armbruster Message-Id: <20230207075115.1525-13-armbru@redhat.com> Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Juan Quintela --- hw/net/rocker/qmp-norocker.c | 12 +++++------- include/qapi/qmp/qerror.h | 3 --- 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/hw/net/rocker/qmp-norocker.c b/hw/net/rocker/qmp-norocker.c index 5ef4f9324c..f6c1196a24 100644 --- a/hw/net/rocker/qmp-norocker.c +++ b/hw/net/rocker/qmp-norocker.c @@ -1,6 +1,5 @@ /* - * QMP Target options - Commands handled based on a target config - * versus a host config + * QMP command stubs * * Copyright (c) 2015 David Ahern * @@ -18,17 +17,16 @@ #include "qemu/osdep.h" #include "qapi/error.h" #include "qapi/qapi-commands-rocker.h" -#include "qapi/qmp/qerror.h" RockerSwitch *qmp_query_rocker(const char *name, Error **errp) { - error_setg(errp, QERR_FEATURE_DISABLED, "rocker"); + error_setg(errp, "rocker %s not found", name); return NULL; }; RockerPortList *qmp_query_rocker_ports(const char *name, Error **errp) { - error_setg(errp, QERR_FEATURE_DISABLED, "rocker"); + error_setg(errp, "rocker %s not found", name); return NULL; }; @@ -37,7 +35,7 @@ RockerOfDpaFlowList *qmp_query_rocker_of_dpa_flows(const char *name, uint32_t tbl_id, Error **errp) { - error_setg(errp, QERR_FEATURE_DISABLED, "rocker"); + error_setg(errp, "rocker %s not found", name); return NULL; }; @@ -46,6 +44,6 @@ RockerOfDpaGroupList *qmp_query_rocker_of_dpa_groups(const char *name, uint8_t type, Error **errp) { - error_setg(errp, QERR_FEATURE_DISABLED, "rocker"); + error_setg(errp, "rocker %s not found", name); return NULL; }; diff --git a/include/qapi/qmp/qerror.h b/include/qapi/qmp/qerror.h index 09006e69f7..8dd9fcb071 100644 --- a/include/qapi/qmp/qerror.h +++ b/include/qapi/qmp/qerror.h @@ -29,9 +29,6 @@ #define QERR_DEVICE_NO_HOTPLUG \ "Device '%s' does not support hotplugging" -#define QERR_FEATURE_DISABLED \ - "The feature '%s' is not enabled" - #define QERR_INVALID_PARAMETER \ "Invalid parameter '%s'" From 10e5d70787b0bcb8c4449ee2fa6a0154d4138186 Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Fri, 3 Feb 2023 16:21:40 +0100 Subject: [PATCH 038/129] block: Make bdrv_can_set_read_only() static It is never called outside of block.c. Signed-off-by: Kevin Wolf Message-Id: <20230203152202.49054-2-kwolf@redhat.com> Reviewed-by: Emanuele Giuseppe Esposito Reviewed-by: Vladimir Sementsov-Ogievskiy Signed-off-by: Kevin Wolf --- block.c | 4 ++-- include/block/block-io.h | 2 -- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/block.c b/block.c index 0c807d15cd..31f13092cb 100644 --- a/block.c +++ b/block.c @@ -277,8 +277,8 @@ bool bdrv_is_read_only(BlockDriverState *bs) return !(bs->open_flags & BDRV_O_RDWR); } -int bdrv_can_set_read_only(BlockDriverState *bs, bool read_only, - bool ignore_allow_rdw, Error **errp) +static int bdrv_can_set_read_only(BlockDriverState *bs, bool read_only, + bool ignore_allow_rdw, Error **errp) { IO_CODE(); diff --git a/include/block/block-io.h b/include/block/block-io.h index 614cbd7eda..f9fa88204d 100644 --- a/include/block/block-io.h +++ b/include/block/block-io.h @@ -134,8 +134,6 @@ int bdrv_is_allocated_above(BlockDriverState *top, BlockDriverState *base, int coroutine_fn bdrv_co_is_zero_fast(BlockDriverState *bs, int64_t offset, int64_t bytes); -int bdrv_can_set_read_only(BlockDriverState *bs, bool read_only, - bool ignore_allow_rdw, Error **errp); int bdrv_apply_auto_read_only(BlockDriverState *bs, const char *errmsg, Error **errp); bool bdrv_is_read_only(BlockDriverState *bs); From 32125b14606a454ed109ea6d9da32c747e94926f Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Fri, 3 Feb 2023 16:21:41 +0100 Subject: [PATCH 039/129] mirror: Fix access of uninitialised fields during start bdrv_mirror_top_pwritev() accesses the job object when active mirroring is enabled. It disables this code during early initialisation while s->job isn't set yet. However, s->job is still set way too early when the job object isn't fully initialised. For example, &s->ops_in_flight isn't initialised yet and the in_flight bitmap doesn't exist yet. This causes crashes when a write request comes in too early. Move the assignment of s->job to when the mirror job is actually fully initialised to make sure that the mirror_top driver doesn't access it too early. Signed-off-by: Kevin Wolf Message-Id: <20230203152202.49054-3-kwolf@redhat.com> Reviewed-by: Emanuele Giuseppe Esposito Reviewed-by: Vladimir Sementsov-Ogievskiy Signed-off-by: Kevin Wolf --- block/mirror.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/block/mirror.c b/block/mirror.c index ab326b67c9..fbbb4f619e 100644 --- a/block/mirror.c +++ b/block/mirror.c @@ -896,6 +896,7 @@ static int coroutine_fn mirror_run(Job *job, Error **errp) { MirrorBlockJob *s = container_of(job, MirrorBlockJob, common.job); BlockDriverState *bs = s->mirror_top_bs->backing->bs; + MirrorBDSOpaque *mirror_top_opaque = s->mirror_top_bs->opaque; BlockDriverState *target_bs = blk_bs(s->target); bool need_drain = true; BlockDeviceIoStatus iostatus; @@ -985,6 +986,12 @@ static int coroutine_fn mirror_run(Job *job, Error **errp) } } + /* + * Only now the job is fully initialised and mirror_top_bs should start + * accessing it. + */ + mirror_top_opaque->job = s; + assert(!s->dbi); s->dbi = bdrv_dirty_iter_new(s->dirty_bitmap); for (;;) { @@ -1704,7 +1711,6 @@ static BlockJob *mirror_start_job( if (!s) { goto fail; } - bs_opaque->job = s; /* The block job now has a reference to this node */ bdrv_unref(mirror_top_bs); From c2b8e315162bd5d5ab30c57bcc7bbb88b3ec4d54 Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Fri, 3 Feb 2023 16:21:42 +0100 Subject: [PATCH 040/129] block: Mark bdrv_co_truncate() and callers GRAPH_RDLOCK This adds GRAPH_RDLOCK annotations to declare that callers of bdrv_co_truncate() need to hold a reader lock for the graph. For some places, we know that they will hold the lock, but we don't have the GRAPH_RDLOCK annotations yet. In this case, add assume_graph_lock() with a FIXME comment. These places will be removed once everything is properly annotated. Signed-off-by: Kevin Wolf Message-Id: <20230203152202.49054-4-kwolf@redhat.com> Reviewed-by: Emanuele Giuseppe Esposito Signed-off-by: Kevin Wolf --- block/block-backend.c | 1 + block/crypto.c | 2 +- block/io.c | 1 + block/parallels.c | 14 ++++++++------ block/preallocate.c | 2 +- block/qcow.c | 17 ++++++++++++----- block/qcow2.c | 14 ++++++++------ block/raw-format.c | 6 +++--- block/vmdk.c | 2 ++ include/block/block-io.h | 6 +++--- include/block/block_int-common.h | 7 ++++--- 11 files changed, 44 insertions(+), 28 deletions(-) diff --git a/block/block-backend.c b/block/block-backend.c index ef512f7c48..f25f3ba5e7 100644 --- a/block/block-backend.c +++ b/block/block-backend.c @@ -2372,6 +2372,7 @@ int coroutine_fn blk_co_truncate(BlockBackend *blk, int64_t offset, bool exact, Error **errp) { IO_OR_GS_CODE(); + GRAPH_RDLOCK_GUARD(); if (!blk_is_available(blk)) { error_setg(errp, "No medium inserted"); return -ENOMEDIUM; diff --git a/block/crypto.c b/block/crypto.c index 72ac30568c..a15f77521f 100644 --- a/block/crypto.c +++ b/block/crypto.c @@ -359,7 +359,7 @@ block_crypto_co_create_generic(BlockDriverState *bs, int64_t size, return ret; } -static int coroutine_fn +static int coroutine_fn GRAPH_RDLOCK block_crypto_co_truncate(BlockDriverState *bs, int64_t offset, bool exact, PreallocMode prealloc, BdrvRequestFlags flags, Error **errp) diff --git a/block/io.c b/block/io.c index d2be37b11e..35025fc11b 100644 --- a/block/io.c +++ b/block/io.c @@ -3380,6 +3380,7 @@ int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact, int64_t old_size, new_bytes; int ret; IO_CODE(); + assert_bdrv_graph_readable(); /* if bs->drv == NULL, bs is closed, so there's nothing to do here */ if (!drv) { diff --git a/block/parallels.c b/block/parallels.c index d4378e09de..36c9de8a8a 100644 --- a/block/parallels.c +++ b/block/parallels.c @@ -165,9 +165,9 @@ static int64_t block_status(BDRVParallelsState *s, int64_t sector_num, return start_off; } -static coroutine_fn int64_t allocate_clusters(BlockDriverState *bs, - int64_t sector_num, - int nb_sectors, int *pnum) +static int64_t coroutine_fn GRAPH_RDLOCK +allocate_clusters(BlockDriverState *bs, int64_t sector_num, + int nb_sectors, int *pnum) { int ret = 0; BDRVParallelsState *s = bs->opaque; @@ -329,6 +329,8 @@ static coroutine_fn int parallels_co_writev(BlockDriverState *bs, QEMUIOVector hd_qiov; int ret = 0; + assume_graph_lock(); /* FIXME */ + qemu_iovec_init(&hd_qiov, qiov->niov); while (nb_sectors > 0) { @@ -414,9 +416,9 @@ static coroutine_fn int parallels_co_readv(BlockDriverState *bs, } -static int coroutine_fn parallels_co_check(BlockDriverState *bs, - BdrvCheckResult *res, - BdrvCheckMode fix) +static int coroutine_fn GRAPH_RDLOCK +parallels_co_check(BlockDriverState *bs, BdrvCheckResult *res, + BdrvCheckMode fix) { BDRVParallelsState *s = bs->opaque; int64_t size, prev_off, high_off; diff --git a/block/preallocate.c b/block/preallocate.c index c0dcf8c346..42da9cb9f1 100644 --- a/block/preallocate.c +++ b/block/preallocate.c @@ -370,7 +370,7 @@ static coroutine_fn int preallocate_co_pwritev_part(BlockDriverState *bs, flags); } -static int coroutine_fn +static int coroutine_fn GRAPH_RDLOCK preallocate_co_truncate(BlockDriverState *bs, int64_t offset, bool exact, PreallocMode prealloc, BdrvRequestFlags flags, Error **errp) diff --git a/block/qcow.c b/block/qcow.c index 20c53b447b..5eb1ab5e59 100644 --- a/block/qcow.c +++ b/block/qcow.c @@ -350,11 +350,10 @@ static int qcow_reopen_prepare(BDRVReopenState *state, * return 0 if not allocated, 1 if *result is assigned, and negative * errno on failure. */ -static int coroutine_fn get_cluster_offset(BlockDriverState *bs, - uint64_t offset, int allocate, - int compressed_size, - int n_start, int n_end, - uint64_t *result) +static int coroutine_fn GRAPH_RDLOCK +get_cluster_offset(BlockDriverState *bs, uint64_t offset, int allocate, + int compressed_size, int n_start, int n_end, + uint64_t *result) { BDRVQcowState *s = bs->opaque; int min_index, i, j, l1_index, l2_index, ret; @@ -536,6 +535,8 @@ static int coroutine_fn qcow_co_block_status(BlockDriverState *bs, int64_t n; uint64_t cluster_offset; + assume_graph_lock(); /* FIXME */ + qemu_co_mutex_lock(&s->lock); ret = get_cluster_offset(bs, offset, 0, 0, 0, 0, &cluster_offset); qemu_co_mutex_unlock(&s->lock); @@ -630,6 +631,8 @@ static coroutine_fn int qcow_co_preadv(BlockDriverState *bs, int64_t offset, uint8_t *buf; void *orig_buf; + assume_graph_lock(); /* FIXME */ + if (qiov->niov > 1) { buf = orig_buf = qemu_try_blockalign(bs, qiov->size); if (buf == NULL) { @@ -726,6 +729,8 @@ static coroutine_fn int qcow_co_pwritev(BlockDriverState *bs, int64_t offset, uint8_t *buf; void *orig_buf; + assume_graph_lock(); /* FIXME */ + s->cluster_cache_offset = -1; /* disable compressed cache */ /* We must always copy the iov when encrypting, so we @@ -1056,6 +1061,8 @@ qcow_co_pwritev_compressed(BlockDriverState *bs, int64_t offset, int64_t bytes, uint8_t *buf, *out_buf; uint64_t cluster_offset; + assume_graph_lock(); /* FIXME */ + buf = qemu_blockalign(bs, s->cluster_size); if (bytes != s->cluster_size) { if (bytes > s->cluster_size || diff --git a/block/qcow2.c b/block/qcow2.c index ee0e5b45cc..e06ea7b5ff 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -3183,9 +3183,9 @@ 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, PreallocMode mode, - Error **errp) +static int coroutine_fn GRAPH_RDLOCK +preallocate_co(BlockDriverState *bs, uint64_t offset, uint64_t new_length, + PreallocMode mode, Error **errp) { BDRVQcow2State *s = bs->opaque; uint64_t bytes; @@ -4209,9 +4209,9 @@ fail: return ret; } -static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset, - bool exact, PreallocMode prealloc, - BdrvRequestFlags flags, Error **errp) +static int coroutine_fn GRAPH_RDLOCK +qcow2_co_truncate(BlockDriverState *bs, int64_t offset, bool exact, + PreallocMode prealloc, BdrvRequestFlags flags, Error **errp) { BDRVQcow2State *s = bs->opaque; uint64_t old_length; @@ -4672,6 +4672,8 @@ qcow2_co_pwritev_compressed_part(BlockDriverState *bs, AioTaskPool *aio = NULL; int ret = 0; + assume_graph_lock(); /* FIXME */ + if (has_data_file(bs)) { return -ENOTSUP; } diff --git a/block/raw-format.c b/block/raw-format.c index 0dc469b629..f39e1f502b 100644 --- a/block/raw-format.c +++ b/block/raw-format.c @@ -384,9 +384,9 @@ 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, - BdrvRequestFlags flags, Error **errp) +static int coroutine_fn GRAPH_RDLOCK +raw_co_truncate(BlockDriverState *bs, int64_t offset, bool exact, + PreallocMode prealloc, BdrvRequestFlags flags, Error **errp) { BDRVRawState *s = bs->opaque; diff --git a/block/vmdk.c b/block/vmdk.c index 171c9272ca..3fcb75319f 100644 --- a/block/vmdk.c +++ b/block/vmdk.c @@ -2130,6 +2130,8 @@ static int coroutine_fn vmdk_co_pwritev_compressed(BlockDriverState *bs, int64_t offset, int64_t bytes, QEMUIOVector *qiov) { + assume_graph_lock(); /* FIXME */ + if (bytes == 0) { /* The caller will write bytes 0 to signal EOF. * When receive it, we align EOF to a sector boundary. */ diff --git a/include/block/block-io.h b/include/block/block-io.h index f9fa88204d..9a09ec2bdd 100644 --- a/include/block/block-io.h +++ b/include/block/block-io.h @@ -72,9 +72,9 @@ int coroutine_fn bdrv_co_pwrite_sync(BdrvChild *child, int64_t offset, int coroutine_fn bdrv_co_pwrite_zeroes(BdrvChild *child, int64_t offset, int64_t bytes, BdrvRequestFlags flags); -int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact, - PreallocMode prealloc, BdrvRequestFlags flags, - Error **errp); +int coroutine_fn GRAPH_RDLOCK +bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact, + PreallocMode prealloc, BdrvRequestFlags flags, Error **errp); int64_t coroutine_fn bdrv_co_nb_sectors(BlockDriverState *bs); int64_t co_wrapper_mixed bdrv_nb_sectors(BlockDriverState *bs); diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h index ba2e0fce25..eaf62beaff 100644 --- a/include/block/block_int-common.h +++ b/include/block/block_int-common.h @@ -677,9 +677,10 @@ struct BlockDriver { * If @exact is true and this function fails but would succeed * with @exact = false, it should return -ENOTSUP. */ - int coroutine_fn (*bdrv_co_truncate)(BlockDriverState *bs, int64_t offset, - bool exact, PreallocMode prealloc, - BdrvRequestFlags flags, Error **errp); + int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_truncate)( + BlockDriverState *bs, int64_t offset, bool exact, + PreallocMode prealloc, BdrvRequestFlags flags, Error **errp); + int64_t coroutine_fn (*bdrv_co_getlength)(BlockDriverState *bs); int64_t coroutine_fn (*bdrv_co_get_allocated_file_size)( BlockDriverState *bs); From 7ff9579e60a42e253c6bbbd7ba613f19cc007259 Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Fri, 3 Feb 2023 16:21:43 +0100 Subject: [PATCH 041/129] block: Mark bdrv_co_block_status() and callers GRAPH_RDLOCK This adds GRAPH_RDLOCK annotations to declare that callers of bdrv_co_block_status() need to hold a reader lock for the graph. For some places, we know that they will hold the lock, but we don't have the GRAPH_RDLOCK annotations yet. In this case, add assume_graph_lock() with a FIXME comment. These places will be removed once everything is properly annotated. Signed-off-by: Emanuele Giuseppe Esposito Signed-off-by: Kevin Wolf Message-Id: <20230203152202.49054-5-kwolf@redhat.com> Reviewed-by: Emanuele Giuseppe Esposito Signed-off-by: Kevin Wolf --- block/backup.c | 3 +++ block/block-backend.c | 2 ++ block/block-copy.c | 19 +++++++++++-------- block/coroutines.h | 2 +- block/io.c | 13 ++++++++----- block/mirror.c | 14 +++++++++----- block/qcow.c | 11 ++++------- block/quorum.c | 9 ++++----- block/stream.c | 32 ++++++++++++++++++-------------- include/block/block-copy.h | 6 +++--- include/block/block-io.h | 22 +++++++++++----------- include/block/block_int-common.h | 3 ++- qemu-img.c | 4 +++- tests/unit/test-block-iothread.c | 3 ++- 14 files changed, 81 insertions(+), 62 deletions(-) diff --git a/block/backup.c b/block/backup.c index 824d39acaa..46fca2459d 100644 --- a/block/backup.c +++ b/block/backup.c @@ -270,7 +270,10 @@ static int coroutine_fn backup_run(Job *job, Error **errp) return -ECANCELED; } + /* rdlock protects the subsequent call to bdrv_is_allocated() */ + bdrv_graph_co_rdlock(); ret = block_copy_reset_unallocated(s->bcs, offset, &count); + bdrv_graph_co_rdunlock(); if (ret < 0) { return ret; } diff --git a/block/block-backend.c b/block/block-backend.c index f25f3ba5e7..f5d9e3e269 100644 --- a/block/block-backend.c +++ b/block/block-backend.c @@ -1431,6 +1431,7 @@ int coroutine_fn blk_co_block_status_above(BlockBackend *blk, BlockDriverState **file) { IO_CODE(); + GRAPH_RDLOCK_GUARD(); return bdrv_co_block_status_above(blk_bs(blk), base, offset, bytes, pnum, map, file); } @@ -1441,6 +1442,7 @@ int coroutine_fn blk_co_is_allocated_above(BlockBackend *blk, int64_t bytes, int64_t *pnum) { IO_CODE(); + GRAPH_RDLOCK_GUARD(); return bdrv_co_is_allocated_above(blk_bs(blk), base, include_base, offset, bytes, pnum); } diff --git a/block/block-copy.c b/block/block-copy.c index 30a4da0f2e..d299fac7cc 100644 --- a/block/block-copy.c +++ b/block/block-copy.c @@ -581,9 +581,9 @@ static coroutine_fn int block_copy_task_entry(AioTask *task) return ret; } -static coroutine_fn int block_copy_block_status(BlockCopyState *s, - int64_t offset, - int64_t bytes, int64_t *pnum) +static coroutine_fn GRAPH_RDLOCK +int block_copy_block_status(BlockCopyState *s, int64_t offset, int64_t bytes, + int64_t *pnum) { int64_t num; BlockDriverState *base; @@ -618,9 +618,9 @@ static coroutine_fn int block_copy_block_status(BlockCopyState *s, * Check if the cluster starting at offset is allocated or not. * return via pnum the number of contiguous clusters sharing this allocation. */ -static int coroutine_fn block_copy_is_cluster_allocated(BlockCopyState *s, - int64_t offset, - int64_t *pnum) +static int coroutine_fn GRAPH_RDLOCK +block_copy_is_cluster_allocated(BlockCopyState *s, int64_t offset, + int64_t *pnum) { BlockDriverState *bs = s->source->bs; int64_t count, total_count = 0; @@ -630,6 +630,7 @@ static int coroutine_fn block_copy_is_cluster_allocated(BlockCopyState *s, assert(QEMU_IS_ALIGNED(offset, s->cluster_size)); while (true) { + /* protected in backup_run() */ ret = bdrv_co_is_allocated(bs, offset, bytes, &count); if (ret < 0) { return ret; @@ -704,7 +705,7 @@ int64_t coroutine_fn block_copy_reset_unallocated(BlockCopyState *s, * Returns 1 if dirty clusters found and successfully copied, 0 if no dirty * clusters found and -errno on failure. */ -static int coroutine_fn +static int coroutine_fn GRAPH_RDLOCK block_copy_dirty_clusters(BlockCopyCallState *call_state) { BlockCopyState *s = call_state->s; @@ -827,7 +828,8 @@ void block_copy_kick(BlockCopyCallState *call_state) * it means that some I/O operation failed in context of _this_ block_copy call, * not some parallel operation. */ -static int coroutine_fn block_copy_common(BlockCopyCallState *call_state) +static int coroutine_fn GRAPH_RDLOCK +block_copy_common(BlockCopyCallState *call_state) { int ret; BlockCopyState *s = call_state->s; @@ -892,6 +894,7 @@ static int coroutine_fn block_copy_common(BlockCopyCallState *call_state) static void coroutine_fn block_copy_async_co_entry(void *opaque) { + GRAPH_RDLOCK_GUARD(); block_copy_common(opaque); } diff --git a/block/coroutines.h b/block/coroutines.h index 2a1e0b3c9d..dd9f3d449b 100644 --- a/block/coroutines.h +++ b/block/coroutines.h @@ -43,7 +43,7 @@ bdrv_co_check(BlockDriverState *bs, BdrvCheckResult *res, BdrvCheckMode fix); int coroutine_fn GRAPH_RDLOCK bdrv_co_invalidate_cache(BlockDriverState *bs, Error **errp); -int coroutine_fn +int coroutine_fn GRAPH_RDLOCK bdrv_co_common_block_status_above(BlockDriverState *bs, BlockDriverState *base, bool include_base, diff --git a/block/io.c b/block/io.c index 35025fc11b..a0f8efc9a1 100644 --- a/block/io.c +++ b/block/io.c @@ -2224,11 +2224,10 @@ int bdrv_flush_all(void) * BDRV_BLOCK_OFFSET_VALID bit is set, 'map' and 'file' (if non-NULL) are * set to the host mapping and BDS corresponding to the guest offset. */ -static int coroutine_fn bdrv_co_block_status(BlockDriverState *bs, - bool want_zero, - int64_t offset, int64_t bytes, - int64_t *pnum, int64_t *map, - BlockDriverState **file) +static int coroutine_fn GRAPH_RDLOCK +bdrv_co_block_status(BlockDriverState *bs, bool want_zero, + int64_t offset, int64_t bytes, + int64_t *pnum, int64_t *map, BlockDriverState **file) { int64_t total_size; int64_t n; /* bytes */ @@ -2240,6 +2239,7 @@ static int coroutine_fn bdrv_co_block_status(BlockDriverState *bs, bool has_filtered_child; assert(pnum); + assert_bdrv_graph_readable(); *pnum = 0; total_size = bdrv_getlength(bs); if (total_size < 0) { @@ -2470,6 +2470,7 @@ bdrv_co_common_block_status_above(BlockDriverState *bs, IO_CODE(); assert(!include_base || base); /* Can't include NULL base */ + assert_bdrv_graph_readable(); if (!depth) { depth = &dummy; @@ -2595,6 +2596,8 @@ int coroutine_fn bdrv_co_is_zero_fast(BlockDriverState *bs, int64_t offset, int64_t pnum = bytes; IO_CODE(); + assume_graph_lock(); /* FIXME */ + if (!bytes) { return 1; } diff --git a/block/mirror.c b/block/mirror.c index fbbb4f619e..94c523af28 100644 --- a/block/mirror.c +++ b/block/mirror.c @@ -558,9 +558,11 @@ static uint64_t coroutine_fn mirror_iteration(MirrorBlockJob *s) MirrorMethod mirror_method = MIRROR_METHOD_COPY; assert(!(offset % s->granularity)); - ret = bdrv_block_status_above(source, NULL, offset, - nb_chunks * s->granularity, - &io_bytes, NULL, NULL); + WITH_GRAPH_RDLOCK_GUARD() { + ret = bdrv_block_status_above(source, NULL, offset, + nb_chunks * s->granularity, + &io_bytes, NULL, NULL); + } if (ret < 0) { io_bytes = MIN(nb_chunks * s->granularity, max_io_bytes); } else if (ret & BDRV_BLOCK_DATA) { @@ -863,8 +865,10 @@ static int coroutine_fn mirror_dirty_init(MirrorBlockJob *s) return 0; } - ret = bdrv_is_allocated_above(bs, s->base_overlay, true, offset, bytes, - &count); + WITH_GRAPH_RDLOCK_GUARD() { + ret = bdrv_is_allocated_above(bs, s->base_overlay, true, offset, + bytes, &count); + } if (ret < 0) { return ret; } diff --git a/block/qcow.c b/block/qcow.c index 5eb1ab5e59..2d19a78818 100644 --- a/block/qcow.c +++ b/block/qcow.c @@ -524,19 +524,16 @@ get_cluster_offset(BlockDriverState *bs, uint64_t offset, int allocate, return 1; } -static int coroutine_fn qcow_co_block_status(BlockDriverState *bs, - bool want_zero, - int64_t offset, int64_t bytes, - int64_t *pnum, int64_t *map, - BlockDriverState **file) +static int coroutine_fn GRAPH_RDLOCK +qcow_co_block_status(BlockDriverState *bs, bool want_zero, + int64_t offset, int64_t bytes, int64_t *pnum, + int64_t *map, BlockDriverState **file) { BDRVQcowState *s = bs->opaque; int index_in_cluster, ret; int64_t n; uint64_t cluster_offset; - assume_graph_lock(); /* FIXME */ - qemu_co_mutex_lock(&s->lock); ret = get_cluster_offset(bs, offset, 0, 0, 0, 0, &cluster_offset); qemu_co_mutex_unlock(&s->lock); diff --git a/block/quorum.c b/block/quorum.c index d1dcf2eaba..f3fe067541 100644 --- a/block/quorum.c +++ b/block/quorum.c @@ -1217,11 +1217,10 @@ static void quorum_child_perm(BlockDriverState *bs, BdrvChild *c, * return BDRV_BLOCK_ZERO if *all* children agree that a certain * region contains zeroes, and BDRV_BLOCK_DATA otherwise. */ -static int coroutine_fn quorum_co_block_status(BlockDriverState *bs, - bool want_zero, - int64_t offset, int64_t count, - int64_t *pnum, int64_t *map, - BlockDriverState **file) +static int coroutine_fn GRAPH_RDLOCK +quorum_co_block_status(BlockDriverState *bs, bool want_zero, + int64_t offset, int64_t count, + int64_t *pnum, int64_t *map, BlockDriverState **file) { BDRVQuorumState *s = bs->opaque; int i, ret; diff --git a/block/stream.c b/block/stream.c index 8744ad103f..22368ce186 100644 --- a/block/stream.c +++ b/block/stream.c @@ -161,21 +161,25 @@ static int coroutine_fn stream_run(Job *job, Error **errp) copy = false; - ret = bdrv_is_allocated(unfiltered_bs, offset, STREAM_CHUNK, &n); - if (ret == 1) { - /* Allocated in the top, no need to copy. */ - } else if (ret >= 0) { - /* Copy if allocated in the intermediate images. Limit to the - * known-unallocated area [offset, offset+n*BDRV_SECTOR_SIZE). */ - ret = bdrv_is_allocated_above(bdrv_cow_bs(unfiltered_bs), - s->base_overlay, true, - offset, n, &n); - /* Finish early if end of backing file has been reached */ - if (ret == 0 && n == 0) { - n = len - offset; - } + WITH_GRAPH_RDLOCK_GUARD() { + ret = bdrv_is_allocated(unfiltered_bs, offset, STREAM_CHUNK, &n); + if (ret == 1) { + /* Allocated in the top, no need to copy. */ + } else if (ret >= 0) { + /* + * Copy if allocated in the intermediate images. Limit to the + * known-unallocated area [offset, offset+n*BDRV_SECTOR_SIZE). + */ + ret = bdrv_is_allocated_above(bdrv_cow_bs(unfiltered_bs), + s->base_overlay, true, + offset, n, &n); + /* Finish early if end of backing file has been reached */ + if (ret == 0 && n == 0) { + n = len - offset; + } - copy = (ret > 0); + copy = (ret > 0); + } } trace_stream_one_iteration(s, offset, n, ret); if (copy) { diff --git a/include/block/block-copy.h b/include/block/block-copy.h index d0f8386554..0700953ab8 100644 --- a/include/block/block-copy.h +++ b/include/block/block-copy.h @@ -36,9 +36,9 @@ void block_copy_set_progress_meter(BlockCopyState *s, ProgressMeter *pm); void block_copy_state_free(BlockCopyState *s); void block_copy_reset(BlockCopyState *s, int64_t offset, int64_t bytes); -int64_t coroutine_fn block_copy_reset_unallocated(BlockCopyState *s, - int64_t offset, - int64_t *count); + +int64_t coroutine_fn GRAPH_RDLOCK +block_copy_reset_unallocated(BlockCopyState *s, int64_t offset, int64_t *count); int coroutine_fn block_copy(BlockCopyState *s, int64_t offset, int64_t bytes, bool ignore_ratelimit, uint64_t timeout_ns, diff --git a/include/block/block-io.h b/include/block/block-io.h index 9a09ec2bdd..6303501b0f 100644 --- a/include/block/block-io.h +++ b/include/block/block-io.h @@ -109,24 +109,24 @@ int bdrv_block_status(BlockDriverState *bs, int64_t offset, int64_t bytes, int64_t *pnum, int64_t *map, BlockDriverState **file); -int coroutine_fn bdrv_co_block_status_above(BlockDriverState *bs, - BlockDriverState *base, - int64_t offset, int64_t bytes, - int64_t *pnum, int64_t *map, - BlockDriverState **file); +int coroutine_fn GRAPH_RDLOCK +bdrv_co_block_status_above(BlockDriverState *bs, BlockDriverState *base, + int64_t offset, int64_t bytes, int64_t *pnum, + int64_t *map, BlockDriverState **file); int bdrv_block_status_above(BlockDriverState *bs, BlockDriverState *base, int64_t offset, int64_t bytes, int64_t *pnum, int64_t *map, BlockDriverState **file); -int coroutine_fn bdrv_co_is_allocated(BlockDriverState *bs, int64_t offset, - int64_t bytes, int64_t *pnum); +int coroutine_fn GRAPH_RDLOCK +bdrv_co_is_allocated(BlockDriverState *bs, int64_t offset, int64_t bytes, + int64_t *pnum); int bdrv_is_allocated(BlockDriverState *bs, int64_t offset, int64_t bytes, int64_t *pnum); -int coroutine_fn bdrv_co_is_allocated_above(BlockDriverState *top, - BlockDriverState *base, - bool include_base, int64_t offset, - int64_t bytes, int64_t *pnum); +int coroutine_fn GRAPH_RDLOCK +bdrv_co_is_allocated_above(BlockDriverState *top, BlockDriverState *base, + bool include_base, int64_t offset, int64_t bytes, + int64_t *pnum); int bdrv_is_allocated_above(BlockDriverState *top, BlockDriverState *base, bool include_base, int64_t offset, int64_t bytes, int64_t *pnum); diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h index eaf62beaff..5f0104a1af 100644 --- a/include/block/block_int-common.h +++ b/include/block/block_int-common.h @@ -606,7 +606,8 @@ struct BlockDriver { * *pnum value for the block-status cache on protocol nodes, prior * to clamping *pnum for return to its caller. */ - int coroutine_fn (*bdrv_co_block_status)(BlockDriverState *bs, + int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_block_status)( + BlockDriverState *bs, bool want_zero, int64_t offset, int64_t bytes, int64_t *pnum, int64_t *map, BlockDriverState **file); diff --git a/qemu-img.c b/qemu-img.c index 7c05931866..cd0178b51b 100644 --- a/qemu-img.c +++ b/qemu-img.c @@ -1991,7 +1991,9 @@ static void coroutine_fn convert_co_do_copy(void *opaque) qemu_co_mutex_unlock(&s->lock); break; } - n = convert_iteration_sectors(s, s->sector_num); + WITH_GRAPH_RDLOCK_GUARD() { + n = convert_iteration_sectors(s, s->sector_num); + } if (n < 0) { qemu_co_mutex_unlock(&s->lock); s->ret = n; diff --git a/tests/unit/test-block-iothread.c b/tests/unit/test-block-iothread.c index 6dfac6468a..3a5e1eb2c4 100644 --- a/tests/unit/test-block-iothread.c +++ b/tests/unit/test-block-iothread.c @@ -312,7 +312,8 @@ static void test_sync_op_blk_truncate(BlockBackend *blk) g_assert_cmpint(ret, ==, -EINVAL); } -static void test_sync_op_block_status(BdrvChild *c) +/* Disable TSA to make bdrv_test.bdrv_co_block_status writable */ +static void TSA_NO_TSA test_sync_op_block_status(BdrvChild *c) { int ret; int64_t n; From 26c518ab1e2159fd4b8f6819af2bdba35e6416f5 Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Fri, 3 Feb 2023 16:21:44 +0100 Subject: [PATCH 042/129] block: Mark bdrv_co_ioctl() and callers GRAPH_RDLOCK This adds GRAPH_RDLOCK annotations to declare that callers of bdrv_co_ioctl() need to hold a reader lock for the graph. Signed-off-by: Kevin Wolf Message-Id: <20230203152202.49054-6-kwolf@redhat.com> Reviewed-by: Emanuele Giuseppe Esposito Signed-off-by: Kevin Wolf --- block/block-backend.c | 1 + block/io.c | 1 + block/raw-format.c | 4 ++-- include/block/block-io.h | 3 ++- include/block/block_int-common.h | 9 +++++---- 5 files changed, 11 insertions(+), 7 deletions(-) diff --git a/block/block-backend.c b/block/block-backend.c index f5d9e3e269..5c731a1c6c 100644 --- a/block/block-backend.c +++ b/block/block-backend.c @@ -1672,6 +1672,7 @@ blk_co_do_ioctl(BlockBackend *blk, unsigned long int req, void *buf) IO_CODE(); blk_wait_while_drained(blk); + GRAPH_RDLOCK_GUARD(); if (!blk_is_available(blk)) { return -ENOMEDIUM; diff --git a/block/io.c b/block/io.c index a0f8efc9a1..c03233ae94 100644 --- a/block/io.c +++ b/block/io.c @@ -3083,6 +3083,7 @@ int coroutine_fn bdrv_co_ioctl(BlockDriverState *bs, int req, void *buf) }; BlockAIOCB *acb; IO_CODE(); + assert_bdrv_graph_readable(); bdrv_inc_in_flight(bs); if (!drv || (!drv->bdrv_aio_ioctl && !drv->bdrv_co_ioctl)) { diff --git a/block/raw-format.c b/block/raw-format.c index f39e1f502b..202acb1232 100644 --- a/block/raw-format.c +++ b/block/raw-format.c @@ -415,8 +415,8 @@ static void coroutine_fn raw_co_lock_medium(BlockDriverState *bs, bool locked) bdrv_co_lock_medium(bs->file->bs, locked); } -static int coroutine_fn raw_co_ioctl(BlockDriverState *bs, - unsigned long int req, void *buf) +static int coroutine_fn GRAPH_RDLOCK +raw_co_ioctl(BlockDriverState *bs, unsigned long int req, void *buf) { BDRVRawState *s = bs->opaque; if (s->offset || s->has_size) { diff --git a/include/block/block-io.h b/include/block/block-io.h index 6303501b0f..3f42c76f23 100644 --- a/include/block/block-io.h +++ b/include/block/block-io.h @@ -97,7 +97,8 @@ void bdrv_aio_cancel(BlockAIOCB *acb); void bdrv_aio_cancel_async(BlockAIOCB *acb); /* sg packet commands */ -int coroutine_fn bdrv_co_ioctl(BlockDriverState *bs, int req, void *buf); +int coroutine_fn GRAPH_RDLOCK +bdrv_co_ioctl(BlockDriverState *bs, int req, void *buf); /* Ensure contents are flushed to disk. */ int coroutine_fn bdrv_co_flush(BlockDriverState *bs); diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h index 5f0104a1af..64700daf38 100644 --- a/include/block/block_int-common.h +++ b/include/block/block_int-common.h @@ -714,11 +714,12 @@ struct BlockDriver { void coroutine_fn (*bdrv_co_lock_medium)(BlockDriverState *bs, bool locked); /* to control generic scsi devices */ - BlockAIOCB *(*bdrv_aio_ioctl)(BlockDriverState *bs, - unsigned long int req, void *buf, + BlockAIOCB *coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_aio_ioctl)( + BlockDriverState *bs, unsigned long int req, void *buf, BlockCompletionFunc *cb, void *opaque); - int coroutine_fn (*bdrv_co_ioctl)(BlockDriverState *bs, - unsigned long int req, void *buf); + + int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_ioctl)( + BlockDriverState *bs, unsigned long int req, void *buf); /* * Returns 0 for completed check, -errno for internal errors. From c16b8bd4e5b423dac556cc37a81efeea4bba9cfe Mon Sep 17 00:00:00 2001 From: Emanuele Giuseppe Esposito Date: Fri, 3 Feb 2023 16:21:45 +0100 Subject: [PATCH 043/129] block/qed: add missing graph rdlock in qed_need_check_timer_entry This function is called in two different places: - timer callback, which does not take the graph rdlock. - bdrv_qed_drain_begin(), which is .bdrv_drain_begin() callback documented as function that does not take the lock. Since it calls recursive functions that traverse the graph, we need to protect them with the graph rdlock. Signed-off-by: Emanuele Giuseppe Esposito Signed-off-by: Kevin Wolf Message-Id: <20230203152202.49054-7-kwolf@redhat.com> Reviewed-by: Emanuele Giuseppe Esposito Signed-off-by: Kevin Wolf --- block/qed.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/block/qed.c b/block/qed.c index 175a46c67b..7690d0215d 100644 --- a/block/qed.c +++ b/block/qed.c @@ -282,11 +282,12 @@ static void coroutine_fn qed_unplug_allocating_write_reqs(BDRVQEDState *s) qemu_co_mutex_unlock(&s->table_lock); } -static void coroutine_fn qed_need_check_timer(BDRVQEDState *s) +static void coroutine_fn GRAPH_RDLOCK qed_need_check_timer(BDRVQEDState *s) { int ret; trace_qed_need_check_timer_cb(s); + assert_bdrv_graph_readable(); if (!qed_plug_allocating_write_reqs(s)) { return; @@ -312,6 +313,7 @@ static void coroutine_fn qed_need_check_timer(BDRVQEDState *s) static void coroutine_fn qed_need_check_timer_entry(void *opaque) { BDRVQEDState *s = opaque; + GRAPH_RDLOCK_GUARD(); qed_need_check_timer(opaque); bdrv_dec_in_flight(s->bs); From 880953493386a69416d2e1cdc063c670585a03ac Mon Sep 17 00:00:00 2001 From: Emanuele Giuseppe Esposito Date: Fri, 3 Feb 2023 16:21:46 +0100 Subject: [PATCH 044/129] block: Mark bdrv_co_flush() and callers GRAPH_RDLOCK This adds GRAPH_RDLOCK annotations to declare that callers of bdrv_co_flush() need to hold a reader lock for the graph. For some places, we know that they will hold the lock, but we don't have the GRAPH_RDLOCK annotations yet. In this case, add assume_graph_lock() with a FIXME comment. These places will be removed once everything is properly annotated. Signed-off-by: Emanuele Giuseppe Esposito Signed-off-by: Kevin Wolf Message-Id: <20230203152202.49054-8-kwolf@redhat.com> Reviewed-by: Emanuele Giuseppe Esposito Signed-off-by: Kevin Wolf --- block/blkdebug.c | 2 +- block/blklogwrites.c | 21 ++++++++++----- block/blkreplay.c | 2 +- block/blkverify.c | 2 +- block/block-backend.c | 3 ++- block/copy-before-write.c | 2 +- block/file-posix.c | 4 +-- block/io.c | 7 +++++ block/mirror.c | 2 +- block/preallocate.c | 2 +- block/qcow2.h | 5 +++- block/qed-check.c | 3 ++- block/qed-table.c | 6 ++--- block/qed.c | 44 +++++++++++++++++++------------- block/qed.h | 29 +++++++++++++-------- block/quorum.c | 2 +- block/throttle.c | 2 +- block/vmdk.c | 6 +++-- include/block/block-io.h | 2 +- include/block/block_int-common.h | 12 +++++---- 20 files changed, 98 insertions(+), 60 deletions(-) diff --git a/block/blkdebug.c b/block/blkdebug.c index 28772be73f..5ba3766a2c 100644 --- a/block/blkdebug.c +++ b/block/blkdebug.c @@ -668,7 +668,7 @@ blkdebug_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes, return bdrv_co_pwritev(bs->file, offset, bytes, qiov, flags); } -static int coroutine_fn blkdebug_co_flush(BlockDriverState *bs) +static int GRAPH_RDLOCK coroutine_fn blkdebug_co_flush(BlockDriverState *bs) { int err = rule_check(bs, 0, 0, BLKDEBUG_IO_TYPE_FLUSH); diff --git a/block/blklogwrites.c b/block/blklogwrites.c index b00b8a6dd0..5ec1d23f29 100644 --- a/block/blklogwrites.c +++ b/block/blklogwrites.c @@ -307,7 +307,7 @@ typedef struct BlkLogWritesFileReq { uint64_t bytes; int file_flags; QEMUIOVector *qiov; - int (*func)(struct BlkLogWritesFileReq *r); + int GRAPH_RDLOCK_PTR (*func)(struct BlkLogWritesFileReq *r); int file_ret; } BlkLogWritesFileReq; @@ -319,7 +319,8 @@ typedef struct { int log_ret; } BlkLogWritesLogReq; -static void coroutine_fn blk_log_writes_co_do_log(BlkLogWritesLogReq *lr) +static void coroutine_fn GRAPH_RDLOCK +blk_log_writes_co_do_log(BlkLogWritesLogReq *lr) { BDRVBlkLogWritesState *s = lr->bs->opaque; uint64_t cur_log_offset = s->cur_log_sector << s->sectorbits; @@ -368,15 +369,16 @@ static void coroutine_fn blk_log_writes_co_do_log(BlkLogWritesLogReq *lr) } } -static void coroutine_fn blk_log_writes_co_do_file(BlkLogWritesFileReq *fr) +static void coroutine_fn GRAPH_RDLOCK +blk_log_writes_co_do_file(BlkLogWritesFileReq *fr) { fr->file_ret = fr->func(fr); } -static int coroutine_fn +static int coroutine_fn GRAPH_RDLOCK blk_log_writes_co_log(BlockDriverState *bs, uint64_t offset, uint64_t bytes, QEMUIOVector *qiov, int flags, - int (*file_func)(BlkLogWritesFileReq *r), + int /*GRAPH_RDLOCK*/ (*file_func)(BlkLogWritesFileReq *r), uint64_t entry_flags, bool is_zero_write) { QEMUIOVector log_qiov; @@ -442,7 +444,8 @@ blk_log_writes_co_do_file_pwrite_zeroes(BlkLogWritesFileReq *fr) fr->file_flags); } -static int coroutine_fn blk_log_writes_co_do_file_flush(BlkLogWritesFileReq *fr) +static int coroutine_fn GRAPH_RDLOCK +blk_log_writes_co_do_file_flush(BlkLogWritesFileReq *fr) { return bdrv_co_flush(fr->bs->file->bs); } @@ -457,6 +460,7 @@ static int coroutine_fn blk_log_writes_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes, QEMUIOVector *qiov, BdrvRequestFlags flags) { + assume_graph_lock(); /* FIXME */ return blk_log_writes_co_log(bs, offset, bytes, qiov, flags, blk_log_writes_co_do_file_pwritev, 0, false); } @@ -465,12 +469,14 @@ static int coroutine_fn blk_log_writes_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset, int64_t bytes, BdrvRequestFlags flags) { + assume_graph_lock(); /* FIXME */ return blk_log_writes_co_log(bs, offset, bytes, NULL, flags, blk_log_writes_co_do_file_pwrite_zeroes, 0, true); } -static int coroutine_fn blk_log_writes_co_flush_to_disk(BlockDriverState *bs) +static int coroutine_fn GRAPH_RDLOCK +blk_log_writes_co_flush_to_disk(BlockDriverState *bs) { return blk_log_writes_co_log(bs, 0, 0, NULL, 0, blk_log_writes_co_do_file_flush, @@ -480,6 +486,7 @@ static int coroutine_fn blk_log_writes_co_flush_to_disk(BlockDriverState *bs) static int coroutine_fn blk_log_writes_co_pdiscard(BlockDriverState *bs, int64_t offset, int64_t bytes) { + assume_graph_lock(); /* FIXME */ return blk_log_writes_co_log(bs, offset, bytes, NULL, 0, blk_log_writes_co_do_file_pdiscard, LOG_DISCARD_FLAG, false); diff --git a/block/blkreplay.c b/block/blkreplay.c index 16543f585a..ce13fa5ba5 100644 --- a/block/blkreplay.c +++ b/block/blkreplay.c @@ -113,7 +113,7 @@ static int coroutine_fn blkreplay_co_pdiscard(BlockDriverState *bs, return ret; } -static int coroutine_fn blkreplay_co_flush(BlockDriverState *bs) +static int coroutine_fn GRAPH_RDLOCK blkreplay_co_flush(BlockDriverState *bs) { uint64_t reqid = blkreplay_next_id(); int ret = bdrv_co_flush(bs->file->bs); diff --git a/block/blkverify.c b/block/blkverify.c index edf1a550f2..8c11c2eae4 100644 --- a/block/blkverify.c +++ b/block/blkverify.c @@ -256,7 +256,7 @@ blkverify_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes, return blkverify_co_prwv(bs, &r, offset, bytes, qiov, qiov, flags, true); } -static int coroutine_fn blkverify_co_flush(BlockDriverState *bs) +static int coroutine_fn GRAPH_RDLOCK blkverify_co_flush(BlockDriverState *bs) { BDRVBlkverifyState *s = bs->opaque; diff --git a/block/block-backend.c b/block/block-backend.c index 5c731a1c6c..3e58b95b8a 100644 --- a/block/block-backend.c +++ b/block/block-backend.c @@ -1762,8 +1762,9 @@ int coroutine_fn blk_co_pdiscard(BlockBackend *blk, int64_t offset, /* To be called between exactly one pair of blk_inc/dec_in_flight() */ static int coroutine_fn blk_co_do_flush(BlockBackend *blk) { - blk_wait_while_drained(blk); IO_CODE(); + blk_wait_while_drained(blk); + GRAPH_RDLOCK_GUARD(); if (!blk_is_available(blk)) { return -ENOMEDIUM; diff --git a/block/copy-before-write.c b/block/copy-before-write.c index c9fb809ba0..4ba72c6309 100644 --- a/block/copy-before-write.c +++ b/block/copy-before-write.c @@ -185,7 +185,7 @@ static coroutine_fn int cbw_co_pwritev(BlockDriverState *bs, return bdrv_co_pwritev(bs->file, offset, bytes, qiov, flags); } -static int coroutine_fn cbw_co_flush(BlockDriverState *bs) +static int coroutine_fn GRAPH_RDLOCK cbw_co_flush(BlockDriverState *bs) { if (!bs->file) { return 0; diff --git a/block/file-posix.c b/block/file-posix.c index 9a99111f45..d106f4efa5 100644 --- a/block/file-posix.c +++ b/block/file-posix.c @@ -2920,8 +2920,8 @@ static void coroutine_fn check_cache_dropped(BlockDriverState *bs, Error **errp) } #endif /* __linux__ */ -static void coroutine_fn raw_co_invalidate_cache(BlockDriverState *bs, - Error **errp) +static void coroutine_fn GRAPH_RDLOCK +raw_co_invalidate_cache(BlockDriverState *bs, Error **errp) { BDRVRawState *s = bs->opaque; int ret; diff --git a/block/io.c b/block/io.c index c03233ae94..cfc93dc912 100644 --- a/block/io.c +++ b/block/io.c @@ -933,6 +933,8 @@ int coroutine_fn bdrv_co_pwrite_sync(BdrvChild *child, int64_t offset, int ret; IO_CODE(); + assume_graph_lock(); /* FIXME */ + ret = bdrv_co_pwrite(child, offset, bytes, buf, flags); if (ret < 0) { return ret; @@ -1041,6 +1043,8 @@ static int coroutine_fn bdrv_driver_pwritev(BlockDriverState *bs, QEMUIOVector local_qiov; int ret; + assume_graph_lock(); /* FIXME */ + bdrv_check_qiov_request(offset, bytes, qiov, qiov_offset, &error_abort); if (!drv) { @@ -1680,6 +1684,8 @@ static int coroutine_fn bdrv_co_do_pwrite_zeroes(BlockDriverState *bs, int head = 0; int tail = 0; + assume_graph_lock(); /* FIXME */ + int64_t max_write_zeroes = MIN_NON_ZERO(bs->bl.max_pwrite_zeroes, INT64_MAX); int alignment = MAX(bs->bl.pwrite_zeroes_alignment, @@ -2839,6 +2845,7 @@ int coroutine_fn bdrv_co_flush(BlockDriverState *bs) int ret = 0; IO_CODE(); + assert_bdrv_graph_readable(); bdrv_inc_in_flight(bs); if (!bdrv_co_is_inserted(bs) || bdrv_is_read_only(bs) || diff --git a/block/mirror.c b/block/mirror.c index 94c523af28..d1d79f2319 100644 --- a/block/mirror.c +++ b/block/mirror.c @@ -1535,7 +1535,7 @@ static int coroutine_fn bdrv_mirror_top_pwritev(BlockDriverState *bs, return ret; } -static int coroutine_fn bdrv_mirror_top_flush(BlockDriverState *bs) +static int coroutine_fn GRAPH_RDLOCK bdrv_mirror_top_flush(BlockDriverState *bs) { if (bs->backing == NULL) { /* we can be here after failed bdrv_append in mirror_start_job */ diff --git a/block/preallocate.c b/block/preallocate.c index 42da9cb9f1..483b596280 100644 --- a/block/preallocate.c +++ b/block/preallocate.c @@ -437,7 +437,7 @@ preallocate_co_truncate(BlockDriverState *bs, int64_t offset, return 0; } -static int coroutine_fn preallocate_co_flush(BlockDriverState *bs) +static int coroutine_fn GRAPH_RDLOCK preallocate_co_flush(BlockDriverState *bs) { return bdrv_co_flush(bs->file->bs); } diff --git a/block/qcow2.h b/block/qcow2.h index 2285f18a73..7a02699bfa 100644 --- a/block/qcow2.h +++ b/block/qcow2.h @@ -900,7 +900,10 @@ int coroutine_fn qcow2_detect_metadata_preallocation(BlockDriverState *bs); /* qcow2-cluster.c functions */ int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size, bool exact_size); -int coroutine_fn qcow2_shrink_l1_table(BlockDriverState *bs, uint64_t max_size); + +int coroutine_fn GRAPH_RDLOCK +qcow2_shrink_l1_table(BlockDriverState *bs, uint64_t max_size); + int qcow2_write_l1_entry(BlockDriverState *bs, int l1_index); int qcow2_encrypt_sectors(BDRVQcow2State *s, int64_t sector_num, uint8_t *buf, int nb_sectors, bool enc, Error **errp); diff --git a/block/qed-check.c b/block/qed-check.c index a6612be00f..8fd94f405e 100644 --- a/block/qed-check.c +++ b/block/qed-check.c @@ -107,7 +107,8 @@ static unsigned int qed_check_l2_table(QEDCheck *check, QEDTable *table) /** * Descend tables and check each cluster is referenced once only */ -static int coroutine_fn qed_check_l1_table(QEDCheck *check, QEDTable *table) +static int coroutine_fn GRAPH_RDLOCK +qed_check_l1_table(QEDCheck *check, QEDTable *table) { BDRVQEDState *s = check->s; unsigned int i, num_invalid_l1 = 0; diff --git a/block/qed-table.c b/block/qed-table.c index e41c87a157..e9c72814c8 100644 --- a/block/qed-table.c +++ b/block/qed-table.c @@ -63,9 +63,9 @@ out: * * Called with table_lock held. */ -static int coroutine_fn qed_write_table(BDRVQEDState *s, uint64_t offset, - QEDTable *table, unsigned int index, - unsigned int n, bool flush) +static int coroutine_fn GRAPH_RDLOCK +qed_write_table(BDRVQEDState *s, uint64_t offset, QEDTable *table, + unsigned int index, unsigned int n, bool flush) { unsigned int sector_mask = BDRV_SECTOR_SIZE / sizeof(uint64_t) - 1; unsigned int start, end, i; diff --git a/block/qed.c b/block/qed.c index 7690d0215d..cf794a1add 100644 --- a/block/qed.c +++ b/block/qed.c @@ -395,8 +395,8 @@ static void bdrv_qed_init_state(BlockDriverState *bs) } /* Called with table_lock held. */ -static int coroutine_fn bdrv_qed_do_open(BlockDriverState *bs, QDict *options, - int flags, Error **errp) +static int coroutine_fn GRAPH_RDLOCK +bdrv_qed_do_open(BlockDriverState *bs, QDict *options, int flags, Error **errp) { BDRVQEDState *s = bs->opaque; QEDHeader le_header; @@ -557,7 +557,7 @@ typedef struct QEDOpenCo { int ret; } QEDOpenCo; -static void coroutine_fn bdrv_qed_open_entry(void *opaque) +static void coroutine_fn GRAPH_RDLOCK bdrv_qed_open_entry(void *opaque) { QEDOpenCo *qoc = opaque; BDRVQEDState *s = qoc->bs->opaque; @@ -579,6 +579,8 @@ static int bdrv_qed_open(BlockDriverState *bs, QDict *options, int flags, }; int ret; + assume_graph_lock(); /* FIXME */ + ret = bdrv_open_file_child(NULL, options, "file", bs, errp); if (ret < 0) { return ret; @@ -995,7 +997,7 @@ static void coroutine_fn qed_aio_complete(QEDAIOCB *acb) * * Called with table_lock held. */ -static int coroutine_fn qed_aio_write_l1_update(QEDAIOCB *acb) +static int coroutine_fn GRAPH_RDLOCK qed_aio_write_l1_update(QEDAIOCB *acb) { BDRVQEDState *s = acb_to_s(acb); CachedL2Table *l2_table = acb->request.l2_table; @@ -1025,7 +1027,8 @@ static int coroutine_fn qed_aio_write_l1_update(QEDAIOCB *acb) * * Called with table_lock held. */ -static int coroutine_fn qed_aio_write_l2_update(QEDAIOCB *acb, uint64_t offset) +static int coroutine_fn GRAPH_RDLOCK +qed_aio_write_l2_update(QEDAIOCB *acb, uint64_t offset) { BDRVQEDState *s = acb_to_s(acb); bool need_alloc = acb->find_cluster_ret == QED_CLUSTER_L1; @@ -1081,7 +1084,7 @@ static int coroutine_fn qed_aio_write_main(QEDAIOCB *acb) * * Called with table_lock held. */ -static int coroutine_fn qed_aio_write_cow(QEDAIOCB *acb) +static int coroutine_fn GRAPH_RDLOCK qed_aio_write_cow(QEDAIOCB *acb) { BDRVQEDState *s = acb_to_s(acb); uint64_t start, len, offset; @@ -1159,7 +1162,8 @@ static bool qed_should_set_need_check(BDRVQEDState *s) * * Called with table_lock held. */ -static int coroutine_fn qed_aio_write_alloc(QEDAIOCB *acb, size_t len) +static int coroutine_fn GRAPH_RDLOCK +qed_aio_write_alloc(QEDAIOCB *acb, size_t len) { BDRVQEDState *s = acb_to_s(acb); int ret; @@ -1265,8 +1269,8 @@ out: * * Called with table_lock held. */ -static int coroutine_fn qed_aio_write_data(void *opaque, int ret, - uint64_t offset, size_t len) +static int coroutine_fn GRAPH_RDLOCK +qed_aio_write_data(void *opaque, int ret, uint64_t offset, size_t len) { QEDAIOCB *acb = opaque; @@ -1336,7 +1340,7 @@ static int coroutine_fn qed_aio_read_data(void *opaque, int ret, /** * Begin next I/O or complete the request */ -static int coroutine_fn qed_aio_next_io(QEDAIOCB *acb) +static int coroutine_fn GRAPH_RDLOCK qed_aio_next_io(QEDAIOCB *acb) { BDRVQEDState *s = acb_to_s(acb); uint64_t offset; @@ -1381,9 +1385,9 @@ static int coroutine_fn qed_aio_next_io(QEDAIOCB *acb) return ret; } -static int coroutine_fn qed_co_request(BlockDriverState *bs, int64_t sector_num, - QEMUIOVector *qiov, int nb_sectors, - int flags) +static int coroutine_fn GRAPH_RDLOCK +qed_co_request(BlockDriverState *bs, int64_t sector_num, QEMUIOVector *qiov, + int nb_sectors, int flags) { QEDAIOCB acb = { .bs = bs, @@ -1404,6 +1408,7 @@ static int coroutine_fn bdrv_qed_co_readv(BlockDriverState *bs, int64_t sector_num, int nb_sectors, QEMUIOVector *qiov) { + assume_graph_lock(); /* FIXME */ return qed_co_request(bs, sector_num, qiov, nb_sectors, 0); } @@ -1411,6 +1416,7 @@ static int coroutine_fn bdrv_qed_co_writev(BlockDriverState *bs, int64_t sector_num, int nb_sectors, QEMUIOVector *qiov, int flags) { + assume_graph_lock(); /* FIXME */ return qed_co_request(bs, sector_num, qiov, nb_sectors, QED_AIOCB_WRITE); } @@ -1421,6 +1427,8 @@ static int coroutine_fn bdrv_qed_co_pwrite_zeroes(BlockDriverState *bs, { BDRVQEDState *s = bs->opaque; + assume_graph_lock(); /* FIXME */ + /* * Zero writes start without an I/O buffer. If a buffer becomes necessary * then it will be allocated during request processing. @@ -1571,8 +1579,8 @@ static int bdrv_qed_change_backing_file(BlockDriverState *bs, return ret; } -static void coroutine_fn bdrv_qed_co_invalidate_cache(BlockDriverState *bs, - Error **errp) +static void coroutine_fn GRAPH_RDLOCK +bdrv_qed_co_invalidate_cache(BlockDriverState *bs, Error **errp) { BDRVQEDState *s = bs->opaque; int ret; @@ -1588,9 +1596,9 @@ static void coroutine_fn bdrv_qed_co_invalidate_cache(BlockDriverState *bs, } } -static int coroutine_fn bdrv_qed_co_check(BlockDriverState *bs, - BdrvCheckResult *result, - BdrvCheckMode fix) +static int coroutine_fn GRAPH_RDLOCK +bdrv_qed_co_check(BlockDriverState *bs, BdrvCheckResult *result, + BdrvCheckMode fix) { BDRVQEDState *s = bs->opaque; int ret; diff --git a/block/qed.h b/block/qed.h index 3d12bf78d4..e48f7c2480 100644 --- a/block/qed.h +++ b/block/qed.h @@ -201,20 +201,25 @@ void qed_commit_l2_cache_entry(L2TableCache *l2_cache, CachedL2Table *l2_table); * Table I/O functions */ int coroutine_fn qed_read_l1_table_sync(BDRVQEDState *s); -int coroutine_fn qed_write_l1_table(BDRVQEDState *s, unsigned int index, - unsigned int n); -int coroutine_fn qed_write_l1_table_sync(BDRVQEDState *s, unsigned int index, - unsigned int n); + +int coroutine_fn GRAPH_RDLOCK +qed_write_l1_table(BDRVQEDState *s, unsigned int index, unsigned int n); + +int coroutine_fn GRAPH_RDLOCK +qed_write_l1_table_sync(BDRVQEDState *s, unsigned int index, unsigned int n); + int coroutine_fn qed_read_l2_table_sync(BDRVQEDState *s, QEDRequest *request, uint64_t offset); int coroutine_fn qed_read_l2_table(BDRVQEDState *s, QEDRequest *request, uint64_t offset); -int coroutine_fn qed_write_l2_table(BDRVQEDState *s, QEDRequest *request, - unsigned int index, unsigned int n, - bool flush); -int coroutine_fn qed_write_l2_table_sync(BDRVQEDState *s, QEDRequest *request, - unsigned int index, unsigned int n, - bool flush); + +int coroutine_fn GRAPH_RDLOCK +qed_write_l2_table(BDRVQEDState *s, QEDRequest *request, unsigned int index, + unsigned int n, bool flush); + +int coroutine_fn GRAPH_RDLOCK +qed_write_l2_table_sync(BDRVQEDState *s, QEDRequest *request, + unsigned int index, unsigned int n, bool flush); /** * Cluster functions @@ -226,7 +231,9 @@ int coroutine_fn qed_find_cluster(BDRVQEDState *s, QEDRequest *request, /** * Consistency check */ -int coroutine_fn qed_check(BDRVQEDState *s, BdrvCheckResult *result, bool fix); +int coroutine_fn GRAPH_RDLOCK +qed_check(BDRVQEDState *s, BdrvCheckResult *result, bool fix); + QEDTable *qed_alloc_table(BDRVQEDState *s); diff --git a/block/quorum.c b/block/quorum.c index f3fe067541..3fe3791ab2 100644 --- a/block/quorum.c +++ b/block/quorum.c @@ -778,7 +778,7 @@ static int64_t coroutine_fn quorum_co_getlength(BlockDriverState *bs) return result; } -static coroutine_fn int quorum_co_flush(BlockDriverState *bs) +static coroutine_fn GRAPH_RDLOCK int quorum_co_flush(BlockDriverState *bs) { BDRVQuorumState *s = bs->opaque; QuorumVoteVersion *winner = NULL; diff --git a/block/throttle.c b/block/throttle.c index 64fa0f5acc..a0db840927 100644 --- a/block/throttle.c +++ b/block/throttle.c @@ -162,7 +162,7 @@ static int coroutine_fn throttle_co_pwritev_compressed(BlockDriverState *bs, BDRV_REQ_WRITE_COMPRESSED); } -static int coroutine_fn throttle_co_flush(BlockDriverState *bs) +static int coroutine_fn GRAPH_RDLOCK throttle_co_flush(BlockDriverState *bs) { return bdrv_co_flush(bs->file->bs); } diff --git a/block/vmdk.c b/block/vmdk.c index 3fcb75319f..d074f696aa 100644 --- a/block/vmdk.c +++ b/block/vmdk.c @@ -1484,8 +1484,8 @@ exit: return ret; } -static int coroutine_fn vmdk_L2update(VmdkExtent *extent, VmdkMetaData *m_data, - uint32_t offset) +static int coroutine_fn GRAPH_RDLOCK +vmdk_L2update(VmdkExtent *extent, VmdkMetaData *m_data, uint32_t offset) { offset = cpu_to_le32(offset); /* update L2 table */ @@ -2028,6 +2028,8 @@ static int coroutine_fn vmdk_pwritev(BlockDriverState *bs, uint64_t offset, uint64_t bytes_done = 0; VmdkMetaData m_data; + assume_graph_lock(); /* FIXME */ + if (DIV_ROUND_UP(offset, BDRV_SECTOR_SIZE) > bs->total_sectors) { error_report("Wrong offset: offset=0x%" PRIx64 " total_sectors=0x%" PRIx64, diff --git a/include/block/block-io.h b/include/block/block-io.h index 3f42c76f23..7e96506138 100644 --- a/include/block/block-io.h +++ b/include/block/block-io.h @@ -101,7 +101,7 @@ int coroutine_fn GRAPH_RDLOCK bdrv_co_ioctl(BlockDriverState *bs, int req, void *buf); /* Ensure contents are flushed to disk. */ -int coroutine_fn bdrv_co_flush(BlockDriverState *bs); +int coroutine_fn GRAPH_RDLOCK bdrv_co_flush(BlockDriverState *bs); int coroutine_fn bdrv_co_pdiscard(BdrvChild *child, int64_t offset, int64_t bytes); diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h index 64700daf38..51eaabd9d1 100644 --- a/include/block/block_int-common.h +++ b/include/block/block_int-common.h @@ -477,8 +477,8 @@ struct BlockDriver { BlockAIOCB *(*bdrv_aio_pwritev)(BlockDriverState *bs, int64_t offset, int64_t bytes, QEMUIOVector *qiov, BdrvRequestFlags flags, BlockCompletionFunc *cb, void *opaque); - BlockAIOCB *(*bdrv_aio_flush)(BlockDriverState *bs, - BlockCompletionFunc *cb, void *opaque); + BlockAIOCB * GRAPH_RDLOCK_PTR (*bdrv_aio_flush)( + BlockDriverState *bs, BlockCompletionFunc *cb, void *opaque); BlockAIOCB *(*bdrv_aio_pdiscard)(BlockDriverState *bs, int64_t offset, int bytes, BlockCompletionFunc *cb, void *opaque); @@ -646,7 +646,7 @@ struct BlockDriver { * layers, if needed. This function is needed for deterministic * synchronization of the flush finishing callback. */ - int coroutine_fn (*bdrv_co_flush)(BlockDriverState *bs); + int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_flush)(BlockDriverState *bs); /* Delete a created file. */ int coroutine_fn (*bdrv_co_delete_file)(BlockDriverState *bs, @@ -656,14 +656,16 @@ struct BlockDriver { * Flushes all data that was already written to the OS all the way down to * the disk (for example file-posix.c calls fsync()). */ - int coroutine_fn (*bdrv_co_flush_to_disk)(BlockDriverState *bs); + int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_flush_to_disk)( + BlockDriverState *bs); /* * Flushes all internal caches to the OS. The data may still sit in a * writeback cache of the host OS, but it will survive a crash of the qemu * process. */ - int coroutine_fn (*bdrv_co_flush_to_os)(BlockDriverState *bs); + int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_flush_to_os)( + BlockDriverState *bs); /* * Truncate @bs to @offset bytes using the given @prealloc mode From 9a5a1c621ed72161abcf461d46c7b7b7f97938bf Mon Sep 17 00:00:00 2001 From: Emanuele Giuseppe Esposito Date: Fri, 3 Feb 2023 16:21:47 +0100 Subject: [PATCH 045/129] block: Mark bdrv_co_pdiscard() and callers GRAPH_RDLOCK This adds GRAPH_RDLOCK annotations to declare that callers of bdrv_co_pdiscard() need to hold a reader lock for the graph. For some places, we know that they will hold the lock, but we don't have the GRAPH_RDLOCK annotations yet. In this case, add assume_graph_lock() with a FIXME comment. These places will be removed once everything is properly annotated. Signed-off-by: Kevin Wolf Message-Id: <20230203152202.49054-9-kwolf@redhat.com> Reviewed-by: Emanuele Giuseppe Esposito Signed-off-by: Kevin Wolf --- block/blkdebug.c | 4 ++-- block/blklogwrites.c | 5 ++--- block/blkreplay.c | 4 ++-- block/block-backend.c | 1 + block/copy-before-write.c | 8 ++++---- block/copy-on-read.c | 4 ++-- block/filter-compress.c | 4 ++-- block/io.c | 2 ++ block/mirror.c | 14 +++++++++----- block/preallocate.c | 4 ++-- block/raw-format.c | 4 ++-- block/snapshot-access.c | 4 ++-- block/throttle.c | 4 ++-- include/block/block-io.h | 5 +++-- include/block/block_int-common.h | 15 +++++++++------ include/block/block_int-io.h | 2 +- 16 files changed, 47 insertions(+), 37 deletions(-) diff --git a/block/blkdebug.c b/block/blkdebug.c index 5ba3766a2c..8506004707 100644 --- a/block/blkdebug.c +++ b/block/blkdebug.c @@ -712,8 +712,8 @@ static int coroutine_fn blkdebug_co_pwrite_zeroes(BlockDriverState *bs, return bdrv_co_pwrite_zeroes(bs->file, offset, bytes, flags); } -static int coroutine_fn blkdebug_co_pdiscard(BlockDriverState *bs, - int64_t offset, int64_t bytes) +static int coroutine_fn GRAPH_RDLOCK +blkdebug_co_pdiscard(BlockDriverState *bs, int64_t offset, int64_t bytes) { uint32_t align = bs->bl.pdiscard_alignment; int err; diff --git a/block/blklogwrites.c b/block/blklogwrites.c index 5ec1d23f29..3033f5035b 100644 --- a/block/blklogwrites.c +++ b/block/blklogwrites.c @@ -450,7 +450,7 @@ blk_log_writes_co_do_file_flush(BlkLogWritesFileReq *fr) return bdrv_co_flush(fr->bs->file->bs); } -static int coroutine_fn +static int coroutine_fn GRAPH_RDLOCK blk_log_writes_co_do_file_pdiscard(BlkLogWritesFileReq *fr) { return bdrv_co_pdiscard(fr->bs->file, fr->offset, fr->bytes); @@ -483,10 +483,9 @@ blk_log_writes_co_flush_to_disk(BlockDriverState *bs) LOG_FLUSH_FLAG, false); } -static int coroutine_fn +static int coroutine_fn GRAPH_RDLOCK blk_log_writes_co_pdiscard(BlockDriverState *bs, int64_t offset, int64_t bytes) { - assume_graph_lock(); /* FIXME */ return blk_log_writes_co_log(bs, offset, bytes, NULL, 0, blk_log_writes_co_do_file_pdiscard, LOG_DISCARD_FLAG, false); diff --git a/block/blkreplay.c b/block/blkreplay.c index ce13fa5ba5..c18d3a755d 100644 --- a/block/blkreplay.c +++ b/block/blkreplay.c @@ -102,8 +102,8 @@ static int coroutine_fn blkreplay_co_pwrite_zeroes(BlockDriverState *bs, return ret; } -static int coroutine_fn blkreplay_co_pdiscard(BlockDriverState *bs, - int64_t offset, int64_t bytes) +static int coroutine_fn GRAPH_RDLOCK +blkreplay_co_pdiscard(BlockDriverState *bs, int64_t offset, int64_t bytes) { uint64_t reqid = blkreplay_next_id(); int ret = bdrv_co_pdiscard(bs->file, offset, bytes); diff --git a/block/block-backend.c b/block/block-backend.c index 3e58b95b8a..b4d2387947 100644 --- a/block/block-backend.c +++ b/block/block-backend.c @@ -1719,6 +1719,7 @@ blk_co_do_pdiscard(BlockBackend *blk, int64_t offset, int64_t bytes) IO_CODE(); blk_wait_while_drained(blk); + GRAPH_RDLOCK_GUARD(); ret = blk_check_byte_request(blk, offset, bytes); if (ret < 0) { diff --git a/block/copy-before-write.c b/block/copy-before-write.c index 4ba72c6309..42b46e746a 100644 --- a/block/copy-before-write.c +++ b/block/copy-before-write.c @@ -149,8 +149,8 @@ static coroutine_fn int cbw_do_copy_before_write(BlockDriverState *bs, return 0; } -static int coroutine_fn cbw_co_pdiscard(BlockDriverState *bs, - int64_t offset, int64_t bytes) +static int coroutine_fn GRAPH_RDLOCK +cbw_co_pdiscard(BlockDriverState *bs, int64_t offset, int64_t bytes) { int ret = cbw_do_copy_before_write(bs, offset, bytes, 0); if (ret < 0) { @@ -322,8 +322,8 @@ cbw_co_snapshot_block_status(BlockDriverState *bs, return ret; } -static int coroutine_fn cbw_co_pdiscard_snapshot(BlockDriverState *bs, - int64_t offset, int64_t bytes) +static int coroutine_fn GRAPH_RDLOCK +cbw_co_pdiscard_snapshot(BlockDriverState *bs, int64_t offset, int64_t bytes) { BDRVCopyBeforeWriteState *s = bs->opaque; diff --git a/block/copy-on-read.c b/block/copy-on-read.c index 3280eb2feb..b564f1ca3f 100644 --- a/block/copy-on-read.c +++ b/block/copy-on-read.c @@ -200,8 +200,8 @@ static int coroutine_fn cor_co_pwrite_zeroes(BlockDriverState *bs, } -static int coroutine_fn cor_co_pdiscard(BlockDriverState *bs, - int64_t offset, int64_t bytes) +static int coroutine_fn GRAPH_RDLOCK +cor_co_pdiscard(BlockDriverState *bs, int64_t offset, int64_t bytes) { return bdrv_co_pdiscard(bs->file, offset, bytes); } diff --git a/block/filter-compress.c b/block/filter-compress.c index 2e2a65966c..083aaef53c 100644 --- a/block/filter-compress.c +++ b/block/filter-compress.c @@ -92,8 +92,8 @@ static int coroutine_fn compress_co_pwrite_zeroes(BlockDriverState *bs, } -static int coroutine_fn compress_co_pdiscard(BlockDriverState *bs, - int64_t offset, int64_t bytes) +static int coroutine_fn GRAPH_RDLOCK +compress_co_pdiscard(BlockDriverState *bs, int64_t offset, int64_t bytes) { return bdrv_co_pdiscard(bs->file, offset, bytes); } diff --git a/block/io.c b/block/io.c index cfc93dc912..e97adb5ba4 100644 --- a/block/io.c +++ b/block/io.c @@ -2971,6 +2971,7 @@ int coroutine_fn bdrv_co_pdiscard(BdrvChild *child, int64_t offset, int head, tail, align; BlockDriverState *bs = child->bs; IO_CODE(); + assert_bdrv_graph_readable(); if (!bs || !bs->drv || !bdrv_co_is_inserted(bs)) { return -ENOMEDIUM; @@ -3577,6 +3578,7 @@ bdrv_co_pdiscard_snapshot(BlockDriverState *bs, int64_t offset, int64_t bytes) BlockDriver *drv = bs->drv; int ret; IO_CODE(); + assert_bdrv_graph_readable(); if (!drv) { return -ENOMEDIUM; diff --git a/block/mirror.c b/block/mirror.c index d1d79f2319..b67e8b14f8 100644 --- a/block/mirror.c +++ b/block/mirror.c @@ -1443,9 +1443,10 @@ static int coroutine_fn bdrv_mirror_top_preadv(BlockDriverState *bs, return bdrv_co_preadv(bs->backing, offset, bytes, qiov, flags); } -static int coroutine_fn bdrv_mirror_top_do_write(BlockDriverState *bs, - MirrorMethod method, uint64_t offset, uint64_t bytes, QEMUIOVector *qiov, - int flags) +static int coroutine_fn GRAPH_RDLOCK +bdrv_mirror_top_do_write(BlockDriverState *bs, MirrorMethod method, + uint64_t offset, uint64_t bytes, QEMUIOVector *qiov, + int flags) { MirrorOp *op = NULL; MirrorBDSOpaque *s = bs->opaque; @@ -1503,6 +1504,8 @@ static int coroutine_fn bdrv_mirror_top_pwritev(BlockDriverState *bs, int ret = 0; bool copy_to_target = false; + assume_graph_lock(); /* FIXME */ + if (s->job) { copy_to_target = s->job->ret >= 0 && !job_is_cancelled(&s->job->common.job) && @@ -1547,12 +1550,13 @@ static int coroutine_fn GRAPH_RDLOCK bdrv_mirror_top_flush(BlockDriverState *bs) static int coroutine_fn bdrv_mirror_top_pwrite_zeroes(BlockDriverState *bs, int64_t offset, int64_t bytes, BdrvRequestFlags flags) { + assume_graph_lock(); /* FIXME */ return bdrv_mirror_top_do_write(bs, MIRROR_METHOD_ZERO, offset, bytes, NULL, flags); } -static int coroutine_fn bdrv_mirror_top_pdiscard(BlockDriverState *bs, - int64_t offset, int64_t bytes) +static int coroutine_fn GRAPH_RDLOCK +bdrv_mirror_top_pdiscard(BlockDriverState *bs, int64_t offset, int64_t bytes) { return bdrv_mirror_top_do_write(bs, MIRROR_METHOD_DISCARD, offset, bytes, NULL, 0); diff --git a/block/preallocate.c b/block/preallocate.c index 483b596280..c2c2dc8a8c 100644 --- a/block/preallocate.c +++ b/block/preallocate.c @@ -234,8 +234,8 @@ static coroutine_fn int preallocate_co_preadv_part( flags); } -static int coroutine_fn preallocate_co_pdiscard(BlockDriverState *bs, - int64_t offset, int64_t bytes) +static int coroutine_fn GRAPH_RDLOCK +preallocate_co_pdiscard(BlockDriverState *bs, int64_t offset, int64_t bytes) { return bdrv_co_pdiscard(bs->file, offset, bytes); } diff --git a/block/raw-format.c b/block/raw-format.c index 202acb1232..7f1036ebed 100644 --- a/block/raw-format.c +++ b/block/raw-format.c @@ -305,8 +305,8 @@ static int coroutine_fn raw_co_pwrite_zeroes(BlockDriverState *bs, return bdrv_co_pwrite_zeroes(bs->file, offset, bytes, flags); } -static int coroutine_fn raw_co_pdiscard(BlockDriverState *bs, - int64_t offset, int64_t bytes) +static int coroutine_fn GRAPH_RDLOCK +raw_co_pdiscard(BlockDriverState *bs, int64_t offset, int64_t bytes) { int ret; diff --git a/block/snapshot-access.c b/block/snapshot-access.c index 0a30ec6cd9..009cc4aea0 100644 --- a/block/snapshot-access.c +++ b/block/snapshot-access.c @@ -49,8 +49,8 @@ snapshot_access_co_block_status(BlockDriverState *bs, bytes, pnum, map, file); } -static int coroutine_fn snapshot_access_co_pdiscard(BlockDriverState *bs, - int64_t offset, int64_t bytes) +static int coroutine_fn GRAPH_RDLOCK +snapshot_access_co_pdiscard(BlockDriverState *bs, int64_t offset, int64_t bytes) { return bdrv_co_pdiscard_snapshot(bs->file->bs, offset, bytes); } diff --git a/block/throttle.c b/block/throttle.c index a0db840927..b07d853c0a 100644 --- a/block/throttle.c +++ b/block/throttle.c @@ -144,8 +144,8 @@ static int coroutine_fn throttle_co_pwrite_zeroes(BlockDriverState *bs, return bdrv_co_pwrite_zeroes(bs->file, offset, bytes, flags); } -static int coroutine_fn throttle_co_pdiscard(BlockDriverState *bs, - int64_t offset, int64_t bytes) +static int coroutine_fn GRAPH_RDLOCK +throttle_co_pdiscard(BlockDriverState *bs, int64_t offset, int64_t bytes) { ThrottleGroupMember *tgm = bs->opaque; throttle_group_co_io_limits_intercept(tgm, bytes, true); diff --git a/include/block/block-io.h b/include/block/block-io.h index 7e96506138..627061fd5f 100644 --- a/include/block/block-io.h +++ b/include/block/block-io.h @@ -103,8 +103,9 @@ bdrv_co_ioctl(BlockDriverState *bs, int req, void *buf); /* Ensure contents are flushed to disk. */ int coroutine_fn GRAPH_RDLOCK bdrv_co_flush(BlockDriverState *bs); -int coroutine_fn bdrv_co_pdiscard(BdrvChild *child, int64_t offset, - int64_t bytes); +int coroutine_fn GRAPH_RDLOCK bdrv_co_pdiscard(BdrvChild *child, int64_t offset, + int64_t bytes); + bool bdrv_can_write_zeroes_with_unmap(BlockDriverState *bs); int bdrv_block_status(BlockDriverState *bs, int64_t offset, int64_t bytes, int64_t *pnum, int64_t *map, diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h index 51eaabd9d1..c52190abdb 100644 --- a/include/block/block_int-common.h +++ b/include/block/block_int-common.h @@ -479,8 +479,9 @@ struct BlockDriver { BdrvRequestFlags flags, BlockCompletionFunc *cb, void *opaque); BlockAIOCB * GRAPH_RDLOCK_PTR (*bdrv_aio_flush)( BlockDriverState *bs, BlockCompletionFunc *cb, void *opaque); - BlockAIOCB *(*bdrv_aio_pdiscard)(BlockDriverState *bs, - int64_t offset, int bytes, + + BlockAIOCB * GRAPH_RDLOCK_PTR (*bdrv_aio_pdiscard)( + BlockDriverState *bs, int64_t offset, int bytes, BlockCompletionFunc *cb, void *opaque); int coroutine_fn (*bdrv_co_readv)(BlockDriverState *bs, @@ -543,8 +544,9 @@ struct BlockDriver { */ int coroutine_fn (*bdrv_co_pwrite_zeroes)(BlockDriverState *bs, int64_t offset, int64_t bytes, BdrvRequestFlags flags); - int coroutine_fn (*bdrv_co_pdiscard)(BlockDriverState *bs, - int64_t offset, int64_t bytes); + + int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_pdiscard)( + BlockDriverState *bs, int64_t offset, int64_t bytes); /* * Map [offset, offset + nbytes) range onto a child of @bs to copy from, @@ -632,8 +634,9 @@ struct BlockDriver { int coroutine_fn (*bdrv_co_snapshot_block_status)(BlockDriverState *bs, bool want_zero, int64_t offset, int64_t bytes, int64_t *pnum, int64_t *map, BlockDriverState **file); - int coroutine_fn (*bdrv_co_pdiscard_snapshot)(BlockDriverState *bs, - int64_t offset, int64_t bytes); + + int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_pdiscard_snapshot)( + BlockDriverState *bs, int64_t offset, int64_t bytes); /* * Invalidate any cached meta-data. diff --git a/include/block/block_int-io.h b/include/block/block_int-io.h index 4430bf4c4a..4bb6ccaa34 100644 --- a/include/block/block_int-io.h +++ b/include/block/block_int-io.h @@ -40,7 +40,7 @@ int coroutine_fn bdrv_co_preadv_snapshot(BdrvChild *child, int coroutine_fn bdrv_co_snapshot_block_status(BlockDriverState *bs, bool want_zero, int64_t offset, int64_t bytes, int64_t *pnum, int64_t *map, BlockDriverState **file); -int coroutine_fn bdrv_co_pdiscard_snapshot(BlockDriverState *bs, +int coroutine_fn GRAPH_RDLOCK bdrv_co_pdiscard_snapshot(BlockDriverState *bs, int64_t offset, int64_t bytes); From abaf8b750baef0337efb06c1d3465512b5d9b5dc Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Fri, 3 Feb 2023 16:21:48 +0100 Subject: [PATCH 046/129] block: Mark bdrv_co_pwrite_zeroes() and callers GRAPH_RDLOCK This adds GRAPH_RDLOCK annotations to declare that callers of bdrv_co_pwrite_zeroes() need to hold a reader lock for the graph. For some places, we know that they will hold the lock, but we don't have the GRAPH_RDLOCK annotations yet. In this case, add assume_graph_lock() with a FIXME comment. These places will be removed once everything is properly annotated. Signed-off-by: Kevin Wolf Message-Id: <20230203152202.49054-10-kwolf@redhat.com> Reviewed-by: Emanuele Giuseppe Esposito Signed-off-by: Kevin Wolf --- block/blkdebug.c | 6 +++--- block/blklogwrites.c | 5 ++--- block/blkreplay.c | 5 +++-- block/block-copy.c | 13 +++++++------ block/copy-before-write.c | 5 +++-- block/copy-on-read.c | 6 +++--- block/filter-compress.c | 6 +++--- block/io.c | 12 +++++++++--- block/mirror.c | 6 +++--- block/preallocate.c | 11 +++++++---- block/qcow2.c | 30 ++++++++++++++++++------------ block/qcow2.h | 6 ++++-- block/qed.c | 9 +++------ block/quorum.c | 15 ++++++++++----- block/raw-format.c | 6 +++--- block/throttle.c | 6 +++--- include/block/block-io.h | 9 +++++---- include/block/block_int-common.h | 5 +++-- 18 files changed, 92 insertions(+), 69 deletions(-) diff --git a/block/blkdebug.c b/block/blkdebug.c index 8506004707..eed03bfe7e 100644 --- a/block/blkdebug.c +++ b/block/blkdebug.c @@ -679,9 +679,9 @@ static int GRAPH_RDLOCK coroutine_fn blkdebug_co_flush(BlockDriverState *bs) return bdrv_co_flush(bs->file->bs); } -static int coroutine_fn blkdebug_co_pwrite_zeroes(BlockDriverState *bs, - int64_t offset, int64_t bytes, - BdrvRequestFlags flags) +static int coroutine_fn GRAPH_RDLOCK +blkdebug_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset, int64_t bytes, + BdrvRequestFlags flags) { uint32_t align = MAX(bs->bl.request_alignment, bs->bl.pwrite_zeroes_alignment); diff --git a/block/blklogwrites.c b/block/blklogwrites.c index 3033f5035b..bdaa2a57a2 100644 --- a/block/blklogwrites.c +++ b/block/blklogwrites.c @@ -437,7 +437,7 @@ blk_log_writes_co_do_file_pwritev(BlkLogWritesFileReq *fr) fr->qiov, fr->file_flags); } -static int coroutine_fn +static int coroutine_fn GRAPH_RDLOCK blk_log_writes_co_do_file_pwrite_zeroes(BlkLogWritesFileReq *fr) { return bdrv_co_pwrite_zeroes(fr->bs->file, fr->offset, fr->bytes, @@ -465,11 +465,10 @@ blk_log_writes_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes, blk_log_writes_co_do_file_pwritev, 0, false); } -static int coroutine_fn +static int coroutine_fn GRAPH_RDLOCK blk_log_writes_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset, int64_t bytes, BdrvRequestFlags flags) { - assume_graph_lock(); /* FIXME */ return blk_log_writes_co_log(bs, offset, bytes, NULL, flags, blk_log_writes_co_do_file_pwrite_zeroes, 0, true); diff --git a/block/blkreplay.c b/block/blkreplay.c index c18d3a755d..2703a0c8c6 100644 --- a/block/blkreplay.c +++ b/block/blkreplay.c @@ -91,8 +91,9 @@ static int coroutine_fn blkreplay_co_pwritev(BlockDriverState *bs, return ret; } -static int coroutine_fn blkreplay_co_pwrite_zeroes(BlockDriverState *bs, - int64_t offset, int64_t bytes, BdrvRequestFlags flags) +static int coroutine_fn GRAPH_RDLOCK +blkreplay_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset, int64_t bytes, + BdrvRequestFlags flags) { uint64_t reqid = blkreplay_next_id(); int ret = bdrv_co_pwrite_zeroes(bs->file, offset, bytes, flags); diff --git a/block/block-copy.c b/block/block-copy.c index d299fac7cc..e13d7bc6b6 100644 --- a/block/block-copy.c +++ b/block/block-copy.c @@ -469,10 +469,9 @@ static coroutine_fn int block_copy_task_run(AioTaskPool *pool, * value of @method should be used for subsequent tasks. * Returns 0 on success. */ -static int coroutine_fn block_copy_do_copy(BlockCopyState *s, - int64_t offset, int64_t bytes, - BlockCopyMethod *method, - bool *error_is_read) +static int coroutine_fn GRAPH_RDLOCK +block_copy_do_copy(BlockCopyState *s, int64_t offset, int64_t bytes, + BlockCopyMethod *method, bool *error_is_read) { int ret; int64_t nbytes = MIN(offset + bytes, s->len) - offset; @@ -558,8 +557,10 @@ static coroutine_fn int block_copy_task_entry(AioTask *task) BlockCopyMethod method = t->method; int ret; - ret = block_copy_do_copy(s, t->req.offset, t->req.bytes, &method, - &error_is_read); + WITH_GRAPH_RDLOCK_GUARD() { + ret = block_copy_do_copy(s, t->req.offset, t->req.bytes, &method, + &error_is_read); + } WITH_QEMU_LOCK_GUARD(&s->lock) { if (s->method == t->method) { diff --git a/block/copy-before-write.c b/block/copy-before-write.c index 42b46e746a..61854beae2 100644 --- a/block/copy-before-write.c +++ b/block/copy-before-write.c @@ -160,8 +160,9 @@ cbw_co_pdiscard(BlockDriverState *bs, int64_t offset, int64_t bytes) return bdrv_co_pdiscard(bs->file, offset, bytes); } -static int coroutine_fn cbw_co_pwrite_zeroes(BlockDriverState *bs, - int64_t offset, int64_t bytes, BdrvRequestFlags flags) +static int coroutine_fn GRAPH_RDLOCK +cbw_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset, int64_t bytes, + BdrvRequestFlags flags) { int ret = cbw_do_copy_before_write(bs, offset, bytes, flags); if (ret < 0) { diff --git a/block/copy-on-read.c b/block/copy-on-read.c index b564f1ca3f..ebf6864dd3 100644 --- a/block/copy-on-read.c +++ b/block/copy-on-read.c @@ -192,9 +192,9 @@ static int coroutine_fn cor_co_pwritev_part(BlockDriverState *bs, } -static int coroutine_fn cor_co_pwrite_zeroes(BlockDriverState *bs, - int64_t offset, int64_t bytes, - BdrvRequestFlags flags) +static int coroutine_fn GRAPH_RDLOCK +cor_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset, int64_t bytes, + BdrvRequestFlags flags) { return bdrv_co_pwrite_zeroes(bs->file, offset, bytes, flags); } diff --git a/block/filter-compress.c b/block/filter-compress.c index 083aaef53c..7a632f47fe 100644 --- a/block/filter-compress.c +++ b/block/filter-compress.c @@ -84,9 +84,9 @@ static int coroutine_fn compress_co_pwritev_part(BlockDriverState *bs, } -static int coroutine_fn compress_co_pwrite_zeroes(BlockDriverState *bs, - int64_t offset, int64_t bytes, - BdrvRequestFlags flags) +static int coroutine_fn GRAPH_RDLOCK +compress_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset, int64_t bytes, + BdrvRequestFlags flags) { return bdrv_co_pwrite_zeroes(bs->file, offset, bytes, flags); } diff --git a/block/io.c b/block/io.c index e97adb5ba4..00843362e9 100644 --- a/block/io.c +++ b/block/io.c @@ -1172,6 +1172,8 @@ static int coroutine_fn bdrv_co_do_copy_on_readv(BdrvChild *child, int64_t progress = 0; bool skip_write; + assume_graph_lock(); /* FIXME */ + bdrv_check_qiov_request(offset, bytes, qiov, qiov_offset, &error_abort); if (!drv) { @@ -1692,6 +1694,7 @@ static int coroutine_fn bdrv_co_do_pwrite_zeroes(BlockDriverState *bs, bs->bl.request_alignment); int max_transfer = MIN_NON_ZERO(bs->bl.max_transfer, MAX_BOUNCE_BUFFER); + assert_bdrv_graph_readable(); bdrv_check_request(offset, bytes, &error_abort); if (!drv) { @@ -1907,6 +1910,8 @@ static int coroutine_fn bdrv_aligned_pwritev(BdrvChild *child, int64_t bytes_remaining = bytes; int max_transfer; + assume_graph_lock(); /* FIXME */ + bdrv_check_qiov_request(offset, bytes, qiov, qiov_offset, &error_abort); if (!drv) { @@ -2159,6 +2164,7 @@ int coroutine_fn bdrv_co_pwrite_zeroes(BdrvChild *child, int64_t offset, { IO_CODE(); trace_bdrv_co_pwrite_zeroes(child->bs, offset, bytes, flags); + assert_bdrv_graph_readable(); if (!(child->bs->open_flags & BDRV_O_UNMAP)) { flags &= ~BDRV_REQ_MAY_UNMAP; @@ -2602,8 +2608,6 @@ int coroutine_fn bdrv_co_is_zero_fast(BlockDriverState *bs, int64_t offset, int64_t pnum = bytes; IO_CODE(); - assume_graph_lock(); /* FIXME */ - if (!bytes) { return 1; } @@ -3241,7 +3245,7 @@ void bdrv_unregister_buf(BlockDriverState *bs, void *host, size_t size) } } -static int coroutine_fn bdrv_co_copy_range_internal( +static int coroutine_fn GRAPH_RDLOCK bdrv_co_copy_range_internal( BdrvChild *src, int64_t src_offset, BdrvChild *dst, int64_t dst_offset, int64_t bytes, BdrvRequestFlags read_flags, BdrvRequestFlags write_flags, @@ -3330,6 +3334,7 @@ int coroutine_fn bdrv_co_copy_range_from(BdrvChild *src, int64_t src_offset, BdrvRequestFlags write_flags) { IO_CODE(); + assume_graph_lock(); /* FIXME */ trace_bdrv_co_copy_range_from(src, src_offset, dst, dst_offset, bytes, read_flags, write_flags); return bdrv_co_copy_range_internal(src, src_offset, dst, dst_offset, @@ -3347,6 +3352,7 @@ int coroutine_fn bdrv_co_copy_range_to(BdrvChild *src, int64_t src_offset, BdrvRequestFlags write_flags) { IO_CODE(); + assume_graph_lock(); /* FIXME */ trace_bdrv_co_copy_range_to(src, src_offset, dst, dst_offset, bytes, read_flags, write_flags); return bdrv_co_copy_range_internal(src, src_offset, dst, dst_offset, diff --git a/block/mirror.c b/block/mirror.c index b67e8b14f8..a6f4ec6282 100644 --- a/block/mirror.c +++ b/block/mirror.c @@ -1547,10 +1547,10 @@ static int coroutine_fn GRAPH_RDLOCK bdrv_mirror_top_flush(BlockDriverState *bs) return bdrv_co_flush(bs->backing->bs); } -static int coroutine_fn bdrv_mirror_top_pwrite_zeroes(BlockDriverState *bs, - int64_t offset, int64_t bytes, BdrvRequestFlags flags) +static int coroutine_fn GRAPH_RDLOCK +bdrv_mirror_top_pwrite_zeroes(BlockDriverState *bs, int64_t offset, + int64_t bytes, BdrvRequestFlags flags) { - assume_graph_lock(); /* FIXME */ return bdrv_mirror_top_do_write(bs, MIRROR_METHOD_ZERO, offset, bytes, NULL, flags); } diff --git a/block/preallocate.c b/block/preallocate.c index c2c2dc8a8c..91d73c81c6 100644 --- a/block/preallocate.c +++ b/block/preallocate.c @@ -269,8 +269,9 @@ static bool has_prealloc_perms(BlockDriverState *bs) * want_merge_zero is used to merge write-zero request with preallocation in * one bdrv_co_pwrite_zeroes() call. */ -static bool coroutine_fn handle_write(BlockDriverState *bs, int64_t offset, - int64_t bytes, bool want_merge_zero) +static bool coroutine_fn GRAPH_RDLOCK +handle_write(BlockDriverState *bs, int64_t offset, int64_t bytes, + bool want_merge_zero) { BDRVPreallocateState *s = bs->opaque; int64_t end = offset + bytes; @@ -345,8 +346,9 @@ static bool coroutine_fn handle_write(BlockDriverState *bs, int64_t offset, return want_merge_zero; } -static int coroutine_fn preallocate_co_pwrite_zeroes(BlockDriverState *bs, - int64_t offset, int64_t bytes, BdrvRequestFlags flags) +static int coroutine_fn GRAPH_RDLOCK +preallocate_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset, + int64_t bytes, BdrvRequestFlags flags) { bool want_merge_zero = !(flags & ~(BDRV_REQ_ZERO_WRITE | BDRV_REQ_NO_FALLBACK)); @@ -364,6 +366,7 @@ static coroutine_fn int preallocate_co_pwritev_part(BlockDriverState *bs, size_t qiov_offset, BdrvRequestFlags flags) { + assume_graph_lock(); /* FIXME */ handle_write(bs, offset, bytes, false); return bdrv_co_pwritev_part(bs->file, offset, bytes, qiov, qiov_offset, diff --git a/block/qcow2.c b/block/qcow2.c index e06ea7b5ff..89c3edbd61 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -2450,7 +2450,8 @@ static bool merge_cow(uint64_t offset, unsigned bytes, * Return 1 if the COW regions read as zeroes, 0 if not, < 0 on error. * Note that returning 0 does not guarantee non-zero data. */ -static int coroutine_fn is_zero_cow(BlockDriverState *bs, QCowL2Meta *m) +static int coroutine_fn GRAPH_RDLOCK +is_zero_cow(BlockDriverState *bs, QCowL2Meta *m) { /* * This check is designed for optimization shortcut so it must be @@ -2468,8 +2469,8 @@ static int coroutine_fn is_zero_cow(BlockDriverState *bs, QCowL2Meta *m) m->cow_end.nb_bytes); } -static int coroutine_fn handle_alloc_space(BlockDriverState *bs, - QCowL2Meta *l2meta) +static int coroutine_fn GRAPH_RDLOCK +handle_alloc_space(BlockDriverState *bs, QCowL2Meta *l2meta) { BDRVQcow2State *s = bs->opaque; QCowL2Meta *m; @@ -2532,12 +2533,10 @@ static int coroutine_fn handle_alloc_space(BlockDriverState *bs, * l2meta - if not NULL, qcow2_co_pwritev_task() will consume it. Caller must * not use it somehow after qcow2_co_pwritev_task() call */ -static coroutine_fn int qcow2_co_pwritev_task(BlockDriverState *bs, - uint64_t host_offset, - uint64_t offset, uint64_t bytes, - QEMUIOVector *qiov, - uint64_t qiov_offset, - QCowL2Meta *l2meta) +static coroutine_fn GRAPH_RDLOCK +int qcow2_co_pwritev_task(BlockDriverState *bs, uint64_t host_offset, + uint64_t offset, uint64_t bytes, QEMUIOVector *qiov, + uint64_t qiov_offset, QCowL2Meta *l2meta) { int ret; BDRVQcow2State *s = bs->opaque; @@ -2603,7 +2602,11 @@ out_locked: return ret; } -static coroutine_fn int qcow2_co_pwritev_task_entry(AioTask *task) +/* + * This function can count as GRAPH_RDLOCK because qcow2_co_pwritev_part() holds + * the graph lock and keeps it until this coroutine has terminated. + */ +static coroutine_fn GRAPH_RDLOCK int qcow2_co_pwritev_task_entry(AioTask *task) { Qcow2AioTask *t = container_of(task, Qcow2AioTask, task); @@ -2626,6 +2629,8 @@ static coroutine_fn int qcow2_co_pwritev_part( QCowL2Meta *l2meta = NULL; AioTaskPool *aio = NULL; + assume_graph_lock(); /* FIXME */ + trace_qcow2_writev_start_req(qemu_coroutine_self(), offset, bytes); while (bytes != 0 && aio_task_pool_status(aio) == 0) { @@ -3974,8 +3979,9 @@ static bool is_zero(BlockDriverState *bs, int64_t offset, int64_t bytes) return res >= 0 && (res & BDRV_BLOCK_ZERO) && bytes == 0; } -static coroutine_fn int qcow2_co_pwrite_zeroes(BlockDriverState *bs, - int64_t offset, int64_t bytes, BdrvRequestFlags flags) +static int coroutine_fn GRAPH_RDLOCK +qcow2_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset, int64_t bytes, + BdrvRequestFlags flags) { int ret; BDRVQcow2State *s = bs->opaque; diff --git a/block/qcow2.h b/block/qcow2.h index 7a02699bfa..82cd1664cf 100644 --- a/block/qcow2.h +++ b/block/qcow2.h @@ -927,8 +927,10 @@ void qcow2_alloc_cluster_abort(BlockDriverState *bs, QCowL2Meta *m); int qcow2_cluster_discard(BlockDriverState *bs, uint64_t offset, uint64_t bytes, enum qcow2_discard_type type, bool full_discard); -int coroutine_fn qcow2_subcluster_zeroize(BlockDriverState *bs, uint64_t offset, - uint64_t bytes, int flags); + +int coroutine_fn GRAPH_RDLOCK +qcow2_subcluster_zeroize(BlockDriverState *bs, uint64_t offset, uint64_t bytes, + int flags); int qcow2_expand_zero_clusters(BlockDriverState *bs, BlockDriverAmendStatusCB *status_cb, diff --git a/block/qed.c b/block/qed.c index cf794a1add..bdcb6de6df 100644 --- a/block/qed.c +++ b/block/qed.c @@ -1420,15 +1420,12 @@ static int coroutine_fn bdrv_qed_co_writev(BlockDriverState *bs, return qed_co_request(bs, sector_num, qiov, nb_sectors, QED_AIOCB_WRITE); } -static int coroutine_fn bdrv_qed_co_pwrite_zeroes(BlockDriverState *bs, - int64_t offset, - int64_t bytes, - BdrvRequestFlags flags) +static int coroutine_fn GRAPH_RDLOCK +bdrv_qed_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset, int64_t bytes, + BdrvRequestFlags flags) { BDRVQEDState *s = bs->opaque; - assume_graph_lock(); /* FIXME */ - /* * Zero writes start without an I/O buffer. If a buffer becomes necessary * then it will be allocated during request processing. diff --git a/block/quorum.c b/block/quorum.c index 3fe3791ab2..02ae0d8343 100644 --- a/block/quorum.c +++ b/block/quorum.c @@ -683,7 +683,11 @@ static int coroutine_fn quorum_co_preadv(BlockDriverState *bs, return ret; } -static void coroutine_fn write_quorum_entry(void *opaque) +/* + * This function can count as GRAPH_RDLOCK because quorum_co_pwritev() holds the + * graph lock and keeps it until this coroutine has terminated. + */ +static void coroutine_fn GRAPH_RDLOCK write_quorum_entry(void *opaque) { QuorumCo *co = opaque; QuorumAIOCB *acb = co->acb; @@ -722,6 +726,8 @@ static int coroutine_fn quorum_co_pwritev(BlockDriverState *bs, int64_t offset, QuorumAIOCB *acb = quorum_aio_get(bs, qiov, offset, bytes, flags); int i, ret; + assume_graph_lock(); /* FIXME */ + for (i = 0; i < s->num_children; i++) { Coroutine *co; QuorumCo data = { @@ -745,10 +751,9 @@ static int coroutine_fn quorum_co_pwritev(BlockDriverState *bs, int64_t offset, return ret; } -static int coroutine_fn quorum_co_pwrite_zeroes(BlockDriverState *bs, - int64_t offset, int64_t bytes, - BdrvRequestFlags flags) - +static int coroutine_fn GRAPH_RDLOCK +quorum_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset, int64_t bytes, + BdrvRequestFlags flags) { return quorum_co_pwritev(bs, offset, bytes, NULL, flags | BDRV_REQ_ZERO_WRITE); diff --git a/block/raw-format.c b/block/raw-format.c index 7f1036ebed..007d7f6e42 100644 --- a/block/raw-format.c +++ b/block/raw-format.c @@ -292,9 +292,9 @@ static int coroutine_fn raw_co_block_status(BlockDriverState *bs, return BDRV_BLOCK_RAW | BDRV_BLOCK_OFFSET_VALID; } -static int coroutine_fn raw_co_pwrite_zeroes(BlockDriverState *bs, - int64_t offset, int64_t bytes, - BdrvRequestFlags flags) +static int coroutine_fn GRAPH_RDLOCK +raw_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset, int64_t bytes, + BdrvRequestFlags flags) { int ret; diff --git a/block/throttle.c b/block/throttle.c index b07d853c0a..3db4fa3c40 100644 --- a/block/throttle.c +++ b/block/throttle.c @@ -134,9 +134,9 @@ static int coroutine_fn throttle_co_pwritev(BlockDriverState *bs, return bdrv_co_pwritev(bs->file, offset, bytes, qiov, flags); } -static int coroutine_fn throttle_co_pwrite_zeroes(BlockDriverState *bs, - int64_t offset, int64_t bytes, - BdrvRequestFlags flags) +static int coroutine_fn GRAPH_RDLOCK +throttle_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset, int64_t bytes, + BdrvRequestFlags flags) { ThrottleGroupMember *tgm = bs->opaque; throttle_group_co_io_limits_intercept(tgm, bytes, true); diff --git a/include/block/block-io.h b/include/block/block-io.h index 627061fd5f..ec26f07d60 100644 --- a/include/block/block-io.h +++ b/include/block/block-io.h @@ -69,8 +69,9 @@ int coroutine_fn bdrv_co_pwrite_sync(BdrvChild *child, int64_t offset, * function is not suitable for zeroing the entire image in a single request * because it may allocate memory for the entire region. */ -int coroutine_fn bdrv_co_pwrite_zeroes(BdrvChild *child, int64_t offset, - int64_t bytes, BdrvRequestFlags flags); +int coroutine_fn GRAPH_RDLOCK +bdrv_co_pwrite_zeroes(BdrvChild *child, int64_t offset, int64_t bytes, + BdrvRequestFlags flags); int coroutine_fn GRAPH_RDLOCK bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact, @@ -133,8 +134,8 @@ int bdrv_is_allocated_above(BlockDriverState *top, BlockDriverState *base, bool include_base, int64_t offset, int64_t bytes, int64_t *pnum); -int coroutine_fn bdrv_co_is_zero_fast(BlockDriverState *bs, int64_t offset, - int64_t bytes); +int coroutine_fn GRAPH_RDLOCK +bdrv_co_is_zero_fast(BlockDriverState *bs, int64_t offset, int64_t bytes); int bdrv_apply_auto_read_only(BlockDriverState *bs, const char *errmsg, Error **errp); diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h index c52190abdb..21b4cb1101 100644 --- a/include/block/block_int-common.h +++ b/include/block/block_int-common.h @@ -542,8 +542,9 @@ struct BlockDriver { * function pointer may be NULL or return -ENOSUP and .bdrv_co_writev() * will be called instead. */ - int coroutine_fn (*bdrv_co_pwrite_zeroes)(BlockDriverState *bs, - int64_t offset, int64_t bytes, BdrvRequestFlags flags); + int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_pwrite_zeroes)( + BlockDriverState *bs, int64_t offset, int64_t bytes, + BdrvRequestFlags flags); int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_pdiscard)( BlockDriverState *bs, int64_t offset, int64_t bytes); From 7b1fb72e2c1b9fbca17c13b753aee25f445cad24 Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Fri, 3 Feb 2023 16:21:49 +0100 Subject: [PATCH 047/129] block: Mark read/write in block/io.c GRAPH_RDLOCK This adds GRAPH_RDLOCK annotations to declare that callers of bdrv_driver_*() need to hold a reader lock for the graph. It doesn't add the annotation to public functions yet. For some places, we know that they will hold the lock, but we don't have the GRAPH_RDLOCK annotations yet. In this case, add assume_graph_lock() with a FIXME comment. These places will be removed once everything is properly annotated. Signed-off-by: Kevin Wolf Message-Id: <20230203152202.49054-11-kwolf@redhat.com> Reviewed-by: Emanuele Giuseppe Esposito Signed-off-by: Kevin Wolf --- block/io.c | 66 +++++++++++++++----------------- block/parallels.c | 8 ++-- block/qcow.c | 20 ++++------ block/qcow2-cluster.c | 10 ++--- block/qcow2.c | 37 ++++++++++-------- block/qcow2.h | 5 ++- block/qed.c | 14 +++---- block/quorum.c | 8 ++-- block/vmdk.c | 4 +- include/block/block_int-common.h | 40 ++++++++++--------- 10 files changed, 101 insertions(+), 111 deletions(-) diff --git a/block/io.c b/block/io.c index 00843362e9..2dda1cf5c2 100644 --- a/block/io.c +++ b/block/io.c @@ -160,6 +160,7 @@ void bdrv_refresh_limits(BlockDriverState *bs, Transaction *tran, Error **errp) bool have_limits; GLOBAL_STATE_CODE(); + assume_graph_lock(); /* FIXME */ if (tran) { BdrvRefreshLimitsState *s = g_new(BdrvRefreshLimitsState, 1); @@ -961,10 +962,9 @@ static void bdrv_co_io_em_complete(void *opaque, int ret) aio_co_wake(co->coroutine); } -static int coroutine_fn bdrv_driver_preadv(BlockDriverState *bs, - int64_t offset, int64_t bytes, - QEMUIOVector *qiov, - size_t qiov_offset, int flags) +static int coroutine_fn GRAPH_RDLOCK +bdrv_driver_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes, + QEMUIOVector *qiov, size_t qiov_offset, int flags) { BlockDriver *drv = bs->drv; int64_t sector_num; @@ -1030,11 +1030,10 @@ out: return ret; } -static int coroutine_fn bdrv_driver_pwritev(BlockDriverState *bs, - int64_t offset, int64_t bytes, - QEMUIOVector *qiov, - size_t qiov_offset, - BdrvRequestFlags flags) +static int coroutine_fn GRAPH_RDLOCK +bdrv_driver_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes, + QEMUIOVector *qiov, size_t qiov_offset, + BdrvRequestFlags flags) { BlockDriver *drv = bs->drv; bool emulate_fua = false; @@ -1043,8 +1042,6 @@ static int coroutine_fn bdrv_driver_pwritev(BlockDriverState *bs, QEMUIOVector local_qiov; int ret; - assume_graph_lock(); /* FIXME */ - bdrv_check_qiov_request(offset, bytes, qiov, qiov_offset, &error_abort); if (!drv) { @@ -1114,7 +1111,7 @@ emulate_flags: return ret; } -static int coroutine_fn +static int coroutine_fn GRAPH_RDLOCK bdrv_driver_pwritev_compressed(BlockDriverState *bs, int64_t offset, int64_t bytes, QEMUIOVector *qiov, size_t qiov_offset) @@ -1149,9 +1146,9 @@ bdrv_driver_pwritev_compressed(BlockDriverState *bs, int64_t offset, return ret; } -static int coroutine_fn bdrv_co_do_copy_on_readv(BdrvChild *child, - int64_t offset, int64_t bytes, QEMUIOVector *qiov, - size_t qiov_offset, int flags) +static int coroutine_fn GRAPH_RDLOCK +bdrv_co_do_copy_on_readv(BdrvChild *child, int64_t offset, int64_t bytes, + QEMUIOVector *qiov, size_t qiov_offset, int flags) { BlockDriverState *bs = child->bs; @@ -1172,8 +1169,6 @@ static int coroutine_fn bdrv_co_do_copy_on_readv(BdrvChild *child, int64_t progress = 0; bool skip_write; - assume_graph_lock(); /* FIXME */ - bdrv_check_qiov_request(offset, bytes, qiov, qiov_offset, &error_abort); if (!drv) { @@ -1315,9 +1310,10 @@ err: * handles copy on read, zeroing after EOF, and fragmentation of large * reads; any other features must be implemented by the caller. */ -static int coroutine_fn bdrv_aligned_preadv(BdrvChild *child, - BdrvTrackedRequest *req, int64_t offset, int64_t bytes, - int64_t align, QEMUIOVector *qiov, size_t qiov_offset, int flags) +static int coroutine_fn GRAPH_RDLOCK +bdrv_aligned_preadv(BdrvChild *child, BdrvTrackedRequest *req, + int64_t offset, int64_t bytes, int64_t align, + QEMUIOVector *qiov, size_t qiov_offset, int flags) { BlockDriverState *bs = child->bs; int64_t total_bytes, max_bytes; @@ -1484,10 +1480,9 @@ static bool bdrv_init_padding(BlockDriverState *bs, return true; } -static coroutine_fn int bdrv_padding_rmw_read(BdrvChild *child, - BdrvTrackedRequest *req, - BdrvRequestPadding *pad, - bool zero_middle) +static int coroutine_fn GRAPH_RDLOCK +bdrv_padding_rmw_read(BdrvChild *child, BdrvTrackedRequest *req, + BdrvRequestPadding *pad, bool zero_middle) { QEMUIOVector local_qiov; BlockDriverState *bs = child->bs; @@ -1626,6 +1621,8 @@ int coroutine_fn bdrv_co_preadv_part(BdrvChild *child, int ret; IO_CODE(); + assume_graph_lock(); /* FIXME */ + trace_bdrv_co_preadv_part(bs, offset, bytes, flags); if (!bdrv_co_is_inserted(bs)) { @@ -1898,10 +1895,11 @@ bdrv_co_write_req_finish(BdrvChild *child, int64_t offset, int64_t bytes, * Forwards an already correctly aligned write request to the BlockDriver, * after possibly fragmenting it. */ -static int coroutine_fn bdrv_aligned_pwritev(BdrvChild *child, - BdrvTrackedRequest *req, int64_t offset, int64_t bytes, - int64_t align, QEMUIOVector *qiov, size_t qiov_offset, - BdrvRequestFlags flags) +static int coroutine_fn GRAPH_RDLOCK +bdrv_aligned_pwritev(BdrvChild *child, BdrvTrackedRequest *req, + int64_t offset, int64_t bytes, int64_t align, + QEMUIOVector *qiov, size_t qiov_offset, + BdrvRequestFlags flags) { BlockDriverState *bs = child->bs; BlockDriver *drv = bs->drv; @@ -1910,8 +1908,6 @@ static int coroutine_fn bdrv_aligned_pwritev(BdrvChild *child, int64_t bytes_remaining = bytes; int max_transfer; - assume_graph_lock(); /* FIXME */ - bdrv_check_qiov_request(offset, bytes, qiov, qiov_offset, &error_abort); if (!drv) { @@ -1987,11 +1983,9 @@ static int coroutine_fn bdrv_aligned_pwritev(BdrvChild *child, return ret; } -static int coroutine_fn bdrv_co_do_zero_pwritev(BdrvChild *child, - int64_t offset, - int64_t bytes, - BdrvRequestFlags flags, - BdrvTrackedRequest *req) +static int coroutine_fn GRAPH_RDLOCK +bdrv_co_do_zero_pwritev(BdrvChild *child, int64_t offset, int64_t bytes, + BdrvRequestFlags flags, BdrvTrackedRequest *req) { BlockDriverState *bs = child->bs; QEMUIOVector local_qiov; @@ -2079,6 +2073,8 @@ int coroutine_fn bdrv_co_pwritev_part(BdrvChild *child, bool padded = false; IO_CODE(); + assume_graph_lock(); /* FIXME */ + trace_bdrv_co_pwritev_part(child->bs, offset, bytes, flags); if (!bdrv_co_is_inserted(bs)) { diff --git a/block/parallels.c b/block/parallels.c index 36c9de8a8a..2cf5061524 100644 --- a/block/parallels.c +++ b/block/parallels.c @@ -320,17 +320,15 @@ static int coroutine_fn parallels_co_block_status(BlockDriverState *bs, return BDRV_BLOCK_DATA | BDRV_BLOCK_OFFSET_VALID; } -static coroutine_fn int parallels_co_writev(BlockDriverState *bs, - int64_t sector_num, int nb_sectors, - QEMUIOVector *qiov, int flags) +static int coroutine_fn GRAPH_RDLOCK +parallels_co_writev(BlockDriverState *bs, int64_t sector_num, int nb_sectors, + QEMUIOVector *qiov, int flags) { BDRVParallelsState *s = bs->opaque; uint64_t bytes_done = 0; QEMUIOVector hd_qiov; int ret = 0; - assume_graph_lock(); /* FIXME */ - qemu_iovec_init(&hd_qiov, qiov->niov); while (nb_sectors > 0) { diff --git a/block/qcow.c b/block/qcow.c index 2d19a78818..1e1d1792d0 100644 --- a/block/qcow.c +++ b/block/qcow.c @@ -617,9 +617,9 @@ static void qcow_refresh_limits(BlockDriverState *bs, Error **errp) bs->bl.request_alignment = BDRV_SECTOR_SIZE; } -static coroutine_fn int qcow_co_preadv(BlockDriverState *bs, int64_t offset, - int64_t bytes, QEMUIOVector *qiov, - BdrvRequestFlags flags) +static int coroutine_fn GRAPH_RDLOCK +qcow_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes, + QEMUIOVector *qiov, BdrvRequestFlags flags) { BDRVQcowState *s = bs->opaque; int offset_in_cluster; @@ -628,8 +628,6 @@ static coroutine_fn int qcow_co_preadv(BlockDriverState *bs, int64_t offset, uint8_t *buf; void *orig_buf; - assume_graph_lock(); /* FIXME */ - if (qiov->niov > 1) { buf = orig_buf = qemu_try_blockalign(bs, qiov->size); if (buf == NULL) { @@ -715,9 +713,9 @@ static coroutine_fn int qcow_co_preadv(BlockDriverState *bs, int64_t offset, return ret; } -static coroutine_fn int qcow_co_pwritev(BlockDriverState *bs, int64_t offset, - int64_t bytes, QEMUIOVector *qiov, - BdrvRequestFlags flags) +static int coroutine_fn GRAPH_RDLOCK +qcow_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes, + QEMUIOVector *qiov, BdrvRequestFlags flags) { BDRVQcowState *s = bs->opaque; int offset_in_cluster; @@ -726,8 +724,6 @@ static coroutine_fn int qcow_co_pwritev(BlockDriverState *bs, int64_t offset, uint8_t *buf; void *orig_buf; - assume_graph_lock(); /* FIXME */ - s->cluster_cache_offset = -1; /* disable compressed cache */ /* We must always copy the iov when encrypting, so we @@ -1048,7 +1044,7 @@ static int qcow_make_empty(BlockDriverState *bs) /* XXX: put compressed sectors first, then all the cluster aligned tables to avoid losing bytes in alignment */ -static coroutine_fn int +static int coroutine_fn GRAPH_RDLOCK qcow_co_pwritev_compressed(BlockDriverState *bs, int64_t offset, int64_t bytes, QEMUIOVector *qiov) { @@ -1058,8 +1054,6 @@ qcow_co_pwritev_compressed(BlockDriverState *bs, int64_t offset, int64_t bytes, uint8_t *buf, *out_buf; uint64_t cluster_offset; - assume_graph_lock(); /* FIXME */ - buf = qemu_blockalign(bs, s->cluster_size); if (bytes != s->cluster_size) { if (bytes > s->cluster_size || diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c index 870be106b6..a22607d90d 100644 --- a/block/qcow2-cluster.c +++ b/block/qcow2-cluster.c @@ -491,10 +491,9 @@ static int count_contiguous_subclusters(BlockDriverState *bs, int nb_clusters, return count; } -static int coroutine_fn do_perform_cow_read(BlockDriverState *bs, - uint64_t src_cluster_offset, - unsigned offset_in_cluster, - QEMUIOVector *qiov) +static int coroutine_fn GRAPH_RDLOCK +do_perform_cow_read(BlockDriverState *bs, uint64_t src_cluster_offset, + unsigned offset_in_cluster, QEMUIOVector *qiov) { int ret; @@ -886,7 +885,8 @@ int coroutine_fn qcow2_alloc_compressed_cluster_offset(BlockDriverState *bs, return 0; } -static int coroutine_fn perform_cow(BlockDriverState *bs, QCowL2Meta *m) +static int coroutine_fn GRAPH_RDLOCK +perform_cow(BlockDriverState *bs, QCowL2Meta *m) { BDRVQcow2State *s = bs->opaque; Qcow2COWRegion *start = &m->cow_start; diff --git a/block/qcow2.c b/block/qcow2.c index 89c3edbd61..8f5ad75984 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -2137,9 +2137,8 @@ static int coroutine_fn qcow2_co_block_status(BlockDriverState *bs, return status; } -static coroutine_fn int qcow2_handle_l2meta(BlockDriverState *bs, - QCowL2Meta **pl2meta, - bool link_l2) +static int coroutine_fn GRAPH_RDLOCK +qcow2_handle_l2meta(BlockDriverState *bs, QCowL2Meta **pl2meta, bool link_l2) { int ret = 0; QCowL2Meta *l2meta = *pl2meta; @@ -2617,9 +2616,10 @@ static coroutine_fn GRAPH_RDLOCK int qcow2_co_pwritev_task_entry(AioTask *task) t->l2meta); } -static coroutine_fn int qcow2_co_pwritev_part( - BlockDriverState *bs, int64_t offset, int64_t bytes, - QEMUIOVector *qiov, size_t qiov_offset, BdrvRequestFlags flags) +static int coroutine_fn GRAPH_RDLOCK +qcow2_co_pwritev_part(BlockDriverState *bs, int64_t offset, int64_t bytes, + QEMUIOVector *qiov, size_t qiov_offset, + BdrvRequestFlags flags) { BDRVQcow2State *s = bs->opaque; int offset_in_cluster; @@ -2629,8 +2629,6 @@ static coroutine_fn int qcow2_co_pwritev_part( QCowL2Meta *l2meta = NULL; AioTaskPool *aio = NULL; - assume_graph_lock(); /* FIXME */ - trace_qcow2_writev_start_req(qemu_coroutine_self(), offset, bytes); while (bytes != 0 && aio_task_pool_status(aio) == 0) { @@ -4160,6 +4158,7 @@ qcow2_co_copy_range_to(BlockDriverState *bs, uint64_t host_offset; QCowL2Meta *l2meta = NULL; + assume_graph_lock(); /* FIXME */ assert(!bs->encrypted); qemu_co_mutex_lock(&s->lock); @@ -4591,7 +4590,7 @@ fail: return ret; } -static coroutine_fn int +static int coroutine_fn GRAPH_RDLOCK qcow2_co_pwritev_compressed_task(BlockDriverState *bs, uint64_t offset, uint64_t bytes, QEMUIOVector *qiov, size_t qiov_offset) @@ -4655,7 +4654,13 @@ fail: return ret; } -static coroutine_fn int qcow2_co_pwritev_compressed_task_entry(AioTask *task) +/* + * This function can count as GRAPH_RDLOCK because + * qcow2_co_pwritev_compressed_part() holds the graph lock and keeps it until + * this coroutine has terminated. + */ +static int coroutine_fn GRAPH_RDLOCK +qcow2_co_pwritev_compressed_task_entry(AioTask *task) { Qcow2AioTask *t = container_of(task, Qcow2AioTask, task); @@ -4669,7 +4674,7 @@ static coroutine_fn int qcow2_co_pwritev_compressed_task_entry(AioTask *task) * XXX: put compressed sectors first, then all the cluster aligned * tables to avoid losing bytes in alignment */ -static coroutine_fn int +static int coroutine_fn GRAPH_RDLOCK qcow2_co_pwritev_compressed_part(BlockDriverState *bs, int64_t offset, int64_t bytes, QEMUIOVector *qiov, size_t qiov_offset) @@ -4678,8 +4683,6 @@ qcow2_co_pwritev_compressed_part(BlockDriverState *bs, AioTaskPool *aio = NULL; int ret = 0; - assume_graph_lock(); /* FIXME */ - if (has_data_file(bs)) { return -ENOTSUP; } @@ -5296,8 +5299,8 @@ static int64_t qcow2_check_vmstate_request(BlockDriverState *bs, return pos; } -static coroutine_fn int qcow2_co_save_vmstate(BlockDriverState *bs, - QEMUIOVector *qiov, int64_t pos) +static int coroutine_fn GRAPH_RDLOCK +qcow2_co_save_vmstate(BlockDriverState *bs, QEMUIOVector *qiov, int64_t pos) { int64_t offset = qcow2_check_vmstate_request(bs, qiov, pos); if (offset < 0) { @@ -5308,8 +5311,8 @@ static coroutine_fn int qcow2_co_save_vmstate(BlockDriverState *bs, return bs->drv->bdrv_co_pwritev_part(bs, offset, qiov->size, qiov, 0, 0); } -static coroutine_fn int qcow2_co_load_vmstate(BlockDriverState *bs, - QEMUIOVector *qiov, int64_t pos) +static int coroutine_fn GRAPH_RDLOCK +qcow2_co_load_vmstate(BlockDriverState *bs, QEMUIOVector *qiov, int64_t pos) { int64_t offset = qcow2_check_vmstate_request(bs, qiov, pos); if (offset < 0) { diff --git a/block/qcow2.h b/block/qcow2.h index 82cd1664cf..46dca53e45 100644 --- a/block/qcow2.h +++ b/block/qcow2.h @@ -921,8 +921,9 @@ int coroutine_fn qcow2_alloc_compressed_cluster_offset(BlockDriverState *bs, void qcow2_parse_compressed_l2_entry(BlockDriverState *bs, uint64_t l2_entry, uint64_t *coffset, int *csize); -int coroutine_fn qcow2_alloc_cluster_link_l2(BlockDriverState *bs, - QCowL2Meta *m); +int coroutine_fn GRAPH_RDLOCK +qcow2_alloc_cluster_link_l2(BlockDriverState *bs, QCowL2Meta *m); + void qcow2_alloc_cluster_abort(BlockDriverState *bs, QCowL2Meta *m); int qcow2_cluster_discard(BlockDriverState *bs, uint64_t offset, uint64_t bytes, enum qcow2_discard_type type, diff --git a/block/qed.c b/block/qed.c index bdcb6de6df..a4a74e59ef 100644 --- a/block/qed.c +++ b/block/qed.c @@ -1404,19 +1404,17 @@ qed_co_request(BlockDriverState *bs, int64_t sector_num, QEMUIOVector *qiov, return qed_aio_next_io(&acb); } -static int coroutine_fn bdrv_qed_co_readv(BlockDriverState *bs, - int64_t sector_num, int nb_sectors, - QEMUIOVector *qiov) +static int coroutine_fn GRAPH_RDLOCK +bdrv_qed_co_readv(BlockDriverState *bs, int64_t sector_num, int nb_sectors, + QEMUIOVector *qiov) { - assume_graph_lock(); /* FIXME */ return qed_co_request(bs, sector_num, qiov, nb_sectors, 0); } -static int coroutine_fn bdrv_qed_co_writev(BlockDriverState *bs, - int64_t sector_num, int nb_sectors, - QEMUIOVector *qiov, int flags) +static int coroutine_fn GRAPH_RDLOCK +bdrv_qed_co_writev(BlockDriverState *bs, int64_t sector_num, int nb_sectors, + QEMUIOVector *qiov, int flags) { - assume_graph_lock(); /* FIXME */ return qed_co_request(bs, sector_num, qiov, nb_sectors, QED_AIOCB_WRITE); } diff --git a/block/quorum.c b/block/quorum.c index 02ae0d8343..ef6cda2868 100644 --- a/block/quorum.c +++ b/block/quorum.c @@ -718,16 +718,14 @@ static void coroutine_fn GRAPH_RDLOCK write_quorum_entry(void *opaque) } } -static int coroutine_fn quorum_co_pwritev(BlockDriverState *bs, int64_t offset, - int64_t bytes, QEMUIOVector *qiov, - BdrvRequestFlags flags) +static int coroutine_fn GRAPH_RDLOCK +quorum_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes, + QEMUIOVector *qiov, BdrvRequestFlags flags) { BDRVQuorumState *s = bs->opaque; QuorumAIOCB *acb = quorum_aio_get(bs, qiov, offset, bytes, flags); int i, ret; - assume_graph_lock(); /* FIXME */ - for (i = 0; i < s->num_children; i++) { Coroutine *co; QuorumCo data = { diff --git a/block/vmdk.c b/block/vmdk.c index d074f696aa..8b844300f4 100644 --- a/block/vmdk.c +++ b/block/vmdk.c @@ -2128,12 +2128,10 @@ vmdk_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes, return ret; } -static int coroutine_fn +static int coroutine_fn GRAPH_RDLOCK vmdk_co_pwritev_compressed(BlockDriverState *bs, int64_t offset, int64_t bytes, QEMUIOVector *qiov) { - assume_graph_lock(); /* FIXME */ - if (bytes == 0) { /* The caller will write bytes 0 to signal EOF. * When receive it, we align EOF to a sector boundary. */ diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h index 21b4cb1101..192841f040 100644 --- a/include/block/block_int-common.h +++ b/include/block/block_int-common.h @@ -471,12 +471,14 @@ struct BlockDriver { Error **errp); /* aio */ - BlockAIOCB *(*bdrv_aio_preadv)(BlockDriverState *bs, + BlockAIOCB * GRAPH_RDLOCK_PTR (*bdrv_aio_preadv)(BlockDriverState *bs, int64_t offset, int64_t bytes, QEMUIOVector *qiov, BdrvRequestFlags flags, BlockCompletionFunc *cb, void *opaque); - BlockAIOCB *(*bdrv_aio_pwritev)(BlockDriverState *bs, + + BlockAIOCB * GRAPH_RDLOCK_PTR (*bdrv_aio_pwritev)(BlockDriverState *bs, int64_t offset, int64_t bytes, QEMUIOVector *qiov, BdrvRequestFlags flags, BlockCompletionFunc *cb, void *opaque); + BlockAIOCB * GRAPH_RDLOCK_PTR (*bdrv_aio_flush)( BlockDriverState *bs, BlockCompletionFunc *cb, void *opaque); @@ -484,7 +486,7 @@ struct BlockDriver { BlockDriverState *bs, int64_t offset, int bytes, BlockCompletionFunc *cb, void *opaque); - int coroutine_fn (*bdrv_co_readv)(BlockDriverState *bs, + int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_readv)(BlockDriverState *bs, int64_t sector_num, int nb_sectors, QEMUIOVector *qiov); /** @@ -502,16 +504,16 @@ struct BlockDriver { * * The buffer in @qiov may point directly to guest memory. */ - int coroutine_fn (*bdrv_co_preadv)(BlockDriverState *bs, + int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_preadv)(BlockDriverState *bs, int64_t offset, int64_t bytes, QEMUIOVector *qiov, BdrvRequestFlags flags); - int coroutine_fn (*bdrv_co_preadv_part)(BlockDriverState *bs, - int64_t offset, int64_t bytes, + int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_preadv_part)( + BlockDriverState *bs, int64_t offset, int64_t bytes, QEMUIOVector *qiov, size_t qiov_offset, BdrvRequestFlags flags); - int coroutine_fn (*bdrv_co_writev)(BlockDriverState *bs, + int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_writev)(BlockDriverState *bs, int64_t sector_num, int nb_sectors, QEMUIOVector *qiov, int flags); /** @@ -529,12 +531,12 @@ struct BlockDriver { * * The buffer in @qiov may point directly to guest memory. */ - int coroutine_fn (*bdrv_co_pwritev)(BlockDriverState *bs, - int64_t offset, int64_t bytes, QEMUIOVector *qiov, - BdrvRequestFlags flags); - int coroutine_fn (*bdrv_co_pwritev_part)(BlockDriverState *bs, - int64_t offset, int64_t bytes, QEMUIOVector *qiov, size_t qiov_offset, + int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_pwritev)( + BlockDriverState *bs, int64_t offset, int64_t bytes, QEMUIOVector *qiov, BdrvRequestFlags flags); + int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_pwritev_part)( + BlockDriverState *bs, int64_t offset, int64_t bytes, QEMUIOVector *qiov, + size_t qiov_offset, BdrvRequestFlags flags); /* * Efficiently zero a region of the disk image. Typically an image format @@ -695,11 +697,13 @@ struct BlockDriver { BlockMeasureInfo *(*bdrv_measure)(QemuOpts *opts, BlockDriverState *in_bs, Error **errp); - int coroutine_fn (*bdrv_co_pwritev_compressed)(BlockDriverState *bs, - int64_t offset, int64_t bytes, QEMUIOVector *qiov); - int coroutine_fn (*bdrv_co_pwritev_compressed_part)(BlockDriverState *bs, - int64_t offset, int64_t bytes, QEMUIOVector *qiov, - size_t qiov_offset); + int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_pwritev_compressed)( + BlockDriverState *bs, int64_t offset, int64_t bytes, + QEMUIOVector *qiov); + + int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_pwritev_compressed_part)( + BlockDriverState *bs, int64_t offset, int64_t bytes, + QEMUIOVector *qiov, size_t qiov_offset); int coroutine_fn (*bdrv_co_get_info)(BlockDriverState *bs, BlockDriverInfo *bdi); @@ -764,7 +768,7 @@ struct BlockDriver { BlockDriverState *bs, const char *name, Error **errp); }; -static inline bool block_driver_can_compress(BlockDriver *drv) +static inline bool TSA_NO_TSA block_driver_can_compress(BlockDriver *drv) { return drv->bdrv_co_pwritev_compressed || drv->bdrv_co_pwritev_compressed_part; From b9b10c35e5c8bdb800601b142c44a4bd2da5a6d2 Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Fri, 3 Feb 2023 16:21:50 +0100 Subject: [PATCH 048/129] block: Mark public read/write functions GRAPH_RDLOCK This adds GRAPH_RDLOCK annotations to declare that callers of bdrv_co_pread*/pwrite*() need to hold a reader lock for the graph. For some places, we know that they will hold the lock, but we don't have the GRAPH_RDLOCK annotations yet. In this case, add assume_graph_lock() with a FIXME comment. These places will be removed once everything is properly annotated. Signed-off-by: Kevin Wolf Message-Id: <20230203152202.49054-12-kwolf@redhat.com> Reviewed-by: Emanuele Giuseppe Esposito Signed-off-by: Kevin Wolf --- block/blkdebug.c | 4 +-- block/blklogwrites.c | 7 ++-- block/blkreplay.c | 10 +++--- block/block-backend.c | 2 ++ block/bochs.c | 2 +- block/commit.c | 5 +-- block/copy-before-write.c | 16 ++++----- block/copy-on-read.c | 26 ++++++--------- block/crypto.c | 4 +-- block/filter-compress.c | 19 +++++------ block/io.c | 7 ++-- block/mirror.c | 18 +++++----- block/parallels.c | 8 +++-- block/preallocate.c | 18 +++++----- block/qcow.c | 8 ++--- block/qcow2-cluster.c | 7 ++-- block/qcow2.c | 53 +++++++++++++++-------------- block/qcow2.h | 9 ++--- block/qed-table.c | 4 +-- block/qed.c | 31 +++++++++-------- block/qed.h | 18 +++++----- block/quorum.c | 29 ++++++++++------ block/raw-format.c | 12 +++---- block/replication.c | 15 ++++----- block/throttle.c | 21 +++++------- block/vdi.c | 4 +-- block/vhdx.c | 11 +++--- block/vmdk.c | 65 +++++++++++++++--------------------- block/vpc.c | 4 +-- include/block/block_int-io.h | 14 ++++---- tests/unit/test-bdrv-drain.c | 20 ++++++----- 31 files changed, 233 insertions(+), 238 deletions(-) diff --git a/block/blkdebug.c b/block/blkdebug.c index eed03bfe7e..f418a90873 100644 --- a/block/blkdebug.c +++ b/block/blkdebug.c @@ -626,7 +626,7 @@ static int rule_check(BlockDriverState *bs, uint64_t offset, uint64_t bytes, return -error; } -static int coroutine_fn +static int coroutine_fn GRAPH_RDLOCK blkdebug_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes, QEMUIOVector *qiov, BdrvRequestFlags flags) { @@ -647,7 +647,7 @@ blkdebug_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes, return bdrv_co_preadv(bs->file, offset, bytes, qiov, flags); } -static int coroutine_fn +static int coroutine_fn GRAPH_RDLOCK blkdebug_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes, QEMUIOVector *qiov, BdrvRequestFlags flags) { diff --git a/block/blklogwrites.c b/block/blklogwrites.c index bdaa2a57a2..93086c31e1 100644 --- a/block/blklogwrites.c +++ b/block/blklogwrites.c @@ -294,7 +294,7 @@ static void blk_log_writes_refresh_limits(BlockDriverState *bs, Error **errp) bs->bl.request_alignment = s->sectorsize; } -static int coroutine_fn +static int coroutine_fn GRAPH_RDLOCK blk_log_writes_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes, QEMUIOVector *qiov, BdrvRequestFlags flags) { @@ -430,7 +430,7 @@ blk_log_writes_co_log(BlockDriverState *bs, uint64_t offset, uint64_t bytes, return fr.file_ret; } -static int coroutine_fn +static int coroutine_fn GRAPH_RDLOCK blk_log_writes_co_do_file_pwritev(BlkLogWritesFileReq *fr) { return bdrv_co_pwritev(fr->bs->file, fr->offset, fr->bytes, @@ -456,11 +456,10 @@ blk_log_writes_co_do_file_pdiscard(BlkLogWritesFileReq *fr) return bdrv_co_pdiscard(fr->bs->file, fr->offset, fr->bytes); } -static int coroutine_fn +static int coroutine_fn GRAPH_RDLOCK blk_log_writes_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes, QEMUIOVector *qiov, BdrvRequestFlags flags) { - assume_graph_lock(); /* FIXME */ return blk_log_writes_co_log(bs, offset, bytes, qiov, flags, blk_log_writes_co_do_file_pwritev, 0, false); } diff --git a/block/blkreplay.c b/block/blkreplay.c index 2703a0c8c6..bc96bbd41e 100644 --- a/block/blkreplay.c +++ b/block/blkreplay.c @@ -69,8 +69,9 @@ static void block_request_create(uint64_t reqid, BlockDriverState *bs, replay_block_event(req->bh, reqid); } -static int coroutine_fn blkreplay_co_preadv(BlockDriverState *bs, - int64_t offset, int64_t bytes, QEMUIOVector *qiov, BdrvRequestFlags flags) +static int coroutine_fn GRAPH_RDLOCK +blkreplay_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes, + QEMUIOVector *qiov, BdrvRequestFlags flags) { uint64_t reqid = blkreplay_next_id(); int ret = bdrv_co_preadv(bs->file, offset, bytes, qiov, flags); @@ -80,8 +81,9 @@ static int coroutine_fn blkreplay_co_preadv(BlockDriverState *bs, return ret; } -static int coroutine_fn blkreplay_co_pwritev(BlockDriverState *bs, - int64_t offset, int64_t bytes, QEMUIOVector *qiov, BdrvRequestFlags flags) +static int coroutine_fn GRAPH_RDLOCK +blkreplay_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes, + QEMUIOVector *qiov, BdrvRequestFlags flags) { uint64_t reqid = blkreplay_next_id(); int ret = bdrv_co_pwritev(bs->file, offset, bytes, qiov, flags); diff --git a/block/block-backend.c b/block/block-backend.c index b4d2387947..146ef91547 100644 --- a/block/block-backend.c +++ b/block/block-backend.c @@ -1289,6 +1289,7 @@ blk_co_do_preadv_part(BlockBackend *blk, int64_t offset, int64_t bytes, IO_CODE(); blk_wait_while_drained(blk); + GRAPH_RDLOCK_GUARD(); /* Call blk_bs() only after waiting, the graph may have changed */ bs = blk_bs(blk); @@ -1363,6 +1364,7 @@ blk_co_do_pwritev_part(BlockBackend *blk, int64_t offset, int64_t bytes, IO_CODE(); blk_wait_while_drained(blk); + GRAPH_RDLOCK_GUARD(); /* Call blk_bs() only after waiting, the graph may have changed */ bs = blk_bs(blk); diff --git a/block/bochs.c b/block/bochs.c index 46e7958316..2f5ae52c90 100644 --- a/block/bochs.c +++ b/block/bochs.c @@ -237,7 +237,7 @@ static int64_t seek_to_sector(BlockDriverState *bs, int64_t sector_num) return bitmap_offset + (512 * (s->bitmap_blocks + extent_offset)); } -static int coroutine_fn +static int coroutine_fn GRAPH_RDLOCK bochs_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes, QEMUIOVector *qiov, BdrvRequestFlags flags) { diff --git a/block/commit.c b/block/commit.c index 41e3599281..10f6512e07 100644 --- a/block/commit.c +++ b/block/commit.c @@ -207,8 +207,9 @@ static const BlockJobDriver commit_job_driver = { }, }; -static int coroutine_fn bdrv_commit_top_preadv(BlockDriverState *bs, - int64_t offset, int64_t bytes, QEMUIOVector *qiov, BdrvRequestFlags flags) +static int coroutine_fn GRAPH_RDLOCK +bdrv_commit_top_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes, + QEMUIOVector *qiov, BdrvRequestFlags flags) { return bdrv_co_preadv(bs->backing, offset, bytes, qiov, flags); } diff --git a/block/copy-before-write.c b/block/copy-before-write.c index 61854beae2..e223e37300 100644 --- a/block/copy-before-write.c +++ b/block/copy-before-write.c @@ -78,9 +78,9 @@ typedef struct BDRVCopyBeforeWriteState { int snapshot_error; } BDRVCopyBeforeWriteState; -static coroutine_fn int cbw_co_preadv( - BlockDriverState *bs, int64_t offset, int64_t bytes, - QEMUIOVector *qiov, BdrvRequestFlags flags) +static int coroutine_fn GRAPH_RDLOCK +cbw_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes, + QEMUIOVector *qiov, BdrvRequestFlags flags) { return bdrv_co_preadv(bs->file, offset, bytes, qiov, flags); } @@ -172,11 +172,9 @@ cbw_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset, int64_t bytes, return bdrv_co_pwrite_zeroes(bs->file, offset, bytes, flags); } -static coroutine_fn int cbw_co_pwritev(BlockDriverState *bs, - int64_t offset, - int64_t bytes, - QEMUIOVector *qiov, - BdrvRequestFlags flags) +static coroutine_fn GRAPH_RDLOCK +int cbw_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes, + QEMUIOVector *qiov, BdrvRequestFlags flags) { int ret = cbw_do_copy_before_write(bs, offset, bytes, flags); if (ret < 0) { @@ -266,6 +264,8 @@ cbw_co_preadv_snapshot(BlockDriverState *bs, int64_t offset, int64_t bytes, BdrvChild *file; int ret; + assume_graph_lock(); /* FIXME */ + /* TODO: upgrade to async loop using AioTask */ while (bytes) { int64_t cur_bytes; diff --git a/block/copy-on-read.c b/block/copy-on-read.c index ebf6864dd3..78da353f88 100644 --- a/block/copy-on-read.c +++ b/block/copy-on-read.c @@ -127,11 +127,10 @@ static int64_t coroutine_fn cor_co_getlength(BlockDriverState *bs) } -static int coroutine_fn cor_co_preadv_part(BlockDriverState *bs, - int64_t offset, int64_t bytes, - QEMUIOVector *qiov, - size_t qiov_offset, - BdrvRequestFlags flags) +static int coroutine_fn GRAPH_RDLOCK +cor_co_preadv_part(BlockDriverState *bs, int64_t offset, int64_t bytes, + QEMUIOVector *qiov, size_t qiov_offset, + BdrvRequestFlags flags) { int64_t n; int local_flags; @@ -180,12 +179,10 @@ static int coroutine_fn cor_co_preadv_part(BlockDriverState *bs, } -static int coroutine_fn cor_co_pwritev_part(BlockDriverState *bs, - int64_t offset, - int64_t bytes, - QEMUIOVector *qiov, - size_t qiov_offset, - BdrvRequestFlags flags) +static int coroutine_fn GRAPH_RDLOCK +cor_co_pwritev_part(BlockDriverState *bs, int64_t offset, int64_t bytes, + QEMUIOVector *qiov, size_t qiov_offset, + BdrvRequestFlags flags) { return bdrv_co_pwritev_part(bs->file, offset, bytes, qiov, qiov_offset, flags); @@ -207,10 +204,9 @@ cor_co_pdiscard(BlockDriverState *bs, int64_t offset, int64_t bytes) } -static int coroutine_fn cor_co_pwritev_compressed(BlockDriverState *bs, - int64_t offset, - int64_t bytes, - QEMUIOVector *qiov) +static int coroutine_fn GRAPH_RDLOCK +cor_co_pwritev_compressed(BlockDriverState *bs, int64_t offset, int64_t bytes, + QEMUIOVector *qiov) { return bdrv_co_pwritev(bs->file, offset, bytes, qiov, BDRV_REQ_WRITE_COMPRESSED); diff --git a/block/crypto.c b/block/crypto.c index a15f77521f..0ebb846534 100644 --- a/block/crypto.c +++ b/block/crypto.c @@ -397,7 +397,7 @@ static int block_crypto_reopen_prepare(BDRVReopenState *state, */ #define BLOCK_CRYPTO_MAX_IO_SIZE (1024 * 1024) -static coroutine_fn int +static int coroutine_fn GRAPH_RDLOCK block_crypto_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes, QEMUIOVector *qiov, BdrvRequestFlags flags) { @@ -459,7 +459,7 @@ block_crypto_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes, } -static coroutine_fn int +static int coroutine_fn GRAPH_RDLOCK block_crypto_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes, QEMUIOVector *qiov, BdrvRequestFlags flags) { diff --git a/block/filter-compress.c b/block/filter-compress.c index 7a632f47fe..0dd5606410 100644 --- a/block/filter-compress.c +++ b/block/filter-compress.c @@ -61,23 +61,20 @@ static int64_t coroutine_fn compress_co_getlength(BlockDriverState *bs) } -static int coroutine_fn compress_co_preadv_part(BlockDriverState *bs, - int64_t offset, int64_t bytes, - QEMUIOVector *qiov, - size_t qiov_offset, - BdrvRequestFlags flags) +static int coroutine_fn GRAPH_RDLOCK +compress_co_preadv_part(BlockDriverState *bs, int64_t offset, int64_t bytes, + QEMUIOVector *qiov, size_t qiov_offset, + BdrvRequestFlags flags) { return bdrv_co_preadv_part(bs->file, offset, bytes, qiov, qiov_offset, flags); } -static int coroutine_fn compress_co_pwritev_part(BlockDriverState *bs, - int64_t offset, - int64_t bytes, - QEMUIOVector *qiov, - size_t qiov_offset, - BdrvRequestFlags flags) +static int coroutine_fn GRAPH_RDLOCK +compress_co_pwritev_part(BlockDriverState *bs, int64_t offset, int64_t bytes, + QEMUIOVector *qiov, size_t qiov_offset, + BdrvRequestFlags flags) { return bdrv_co_pwritev_part(bs->file, offset, bytes, qiov, qiov_offset, flags | BDRV_REQ_WRITE_COMPRESSED); diff --git a/block/io.c b/block/io.c index 2dda1cf5c2..ec8b317818 100644 --- a/block/io.c +++ b/block/io.c @@ -971,6 +971,7 @@ bdrv_driver_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes, unsigned int nb_sectors; QEMUIOVector local_qiov; int ret; + assert_bdrv_graph_readable(); bdrv_check_qiov_request(offset, bytes, qiov, qiov_offset, &error_abort); assert(!(flags & ~bs->supported_read_flags)); @@ -1041,6 +1042,7 @@ bdrv_driver_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes, unsigned int nb_sectors; QEMUIOVector local_qiov; int ret; + assert_bdrv_graph_readable(); bdrv_check_qiov_request(offset, bytes, qiov, qiov_offset, &error_abort); @@ -1119,6 +1121,7 @@ bdrv_driver_pwritev_compressed(BlockDriverState *bs, int64_t offset, BlockDriver *drv = bs->drv; QEMUIOVector local_qiov; int ret; + assert_bdrv_graph_readable(); bdrv_check_qiov_request(offset, bytes, qiov, qiov_offset, &error_abort); @@ -1621,8 +1624,6 @@ int coroutine_fn bdrv_co_preadv_part(BdrvChild *child, int ret; IO_CODE(); - assume_graph_lock(); /* FIXME */ - trace_bdrv_co_preadv_part(bs, offset, bytes, flags); if (!bdrv_co_is_inserted(bs)) { @@ -2073,8 +2074,6 @@ int coroutine_fn bdrv_co_pwritev_part(BdrvChild *child, bool padded = false; IO_CODE(); - assume_graph_lock(); /* FIXME */ - trace_bdrv_co_pwritev_part(child->bs, offset, bytes, flags); if (!bdrv_co_is_inserted(bs)) { diff --git a/block/mirror.c b/block/mirror.c index a6f4ec6282..ec5cd22a7c 100644 --- a/block/mirror.c +++ b/block/mirror.c @@ -390,8 +390,10 @@ static void coroutine_fn mirror_co_read(void *opaque) op->is_in_flight = true; trace_mirror_one_iteration(s, op->offset, op->bytes); - ret = bdrv_co_preadv(s->mirror_top_bs->backing, op->offset, op->bytes, - &op->qiov, 0); + WITH_GRAPH_RDLOCK_GUARD() { + ret = bdrv_co_preadv(s->mirror_top_bs->backing, op->offset, op->bytes, + &op->qiov, 0); + } mirror_read_complete(op, ret); } @@ -1437,8 +1439,9 @@ static void coroutine_fn active_write_settle(MirrorOp *op) g_free(op); } -static int coroutine_fn bdrv_mirror_top_preadv(BlockDriverState *bs, - int64_t offset, int64_t bytes, QEMUIOVector *qiov, BdrvRequestFlags flags) +static int coroutine_fn GRAPH_RDLOCK +bdrv_mirror_top_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes, + QEMUIOVector *qiov, BdrvRequestFlags flags) { return bdrv_co_preadv(bs->backing, offset, bytes, qiov, flags); } @@ -1495,8 +1498,9 @@ out: return ret; } -static int coroutine_fn bdrv_mirror_top_pwritev(BlockDriverState *bs, - int64_t offset, int64_t bytes, QEMUIOVector *qiov, BdrvRequestFlags flags) +static int coroutine_fn GRAPH_RDLOCK +bdrv_mirror_top_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes, + QEMUIOVector *qiov, BdrvRequestFlags flags) { MirrorBDSOpaque *s = bs->opaque; QEMUIOVector bounce_qiov; @@ -1504,8 +1508,6 @@ static int coroutine_fn bdrv_mirror_top_pwritev(BlockDriverState *bs, int ret = 0; bool copy_to_target = false; - assume_graph_lock(); /* FIXME */ - if (s->job) { copy_to_target = s->job->ret >= 0 && !job_is_cancelled(&s->job->common.job) && diff --git a/block/parallels.c b/block/parallels.c index 2cf5061524..a7e9cad146 100644 --- a/block/parallels.c +++ b/block/parallels.c @@ -261,7 +261,8 @@ allocate_clusters(BlockDriverState *bs, int64_t sector_num, } -static coroutine_fn int parallels_co_flush_to_os(BlockDriverState *bs) +static int coroutine_fn GRAPH_RDLOCK +parallels_co_flush_to_os(BlockDriverState *bs) { BDRVParallelsState *s = bs->opaque; unsigned long size = DIV_ROUND_UP(s->header_size, s->bat_dirty_block); @@ -363,8 +364,9 @@ parallels_co_writev(BlockDriverState *bs, int64_t sector_num, int nb_sectors, return ret; } -static coroutine_fn int parallels_co_readv(BlockDriverState *bs, - int64_t sector_num, int nb_sectors, QEMUIOVector *qiov) +static int coroutine_fn GRAPH_RDLOCK +parallels_co_readv(BlockDriverState *bs, int64_t sector_num, int nb_sectors, + QEMUIOVector *qiov) { BDRVParallelsState *s = bs->opaque; uint64_t bytes_done = 0; diff --git a/block/preallocate.c b/block/preallocate.c index 91d73c81c6..63a296882d 100644 --- a/block/preallocate.c +++ b/block/preallocate.c @@ -226,9 +226,10 @@ static void preallocate_reopen_abort(BDRVReopenState *state) state->opaque = NULL; } -static coroutine_fn int preallocate_co_preadv_part( - BlockDriverState *bs, int64_t offset, int64_t bytes, - QEMUIOVector *qiov, size_t qiov_offset, BdrvRequestFlags flags) +static int coroutine_fn GRAPH_RDLOCK +preallocate_co_preadv_part(BlockDriverState *bs, int64_t offset, int64_t bytes, + QEMUIOVector *qiov, size_t qiov_offset, + BdrvRequestFlags flags) { return bdrv_co_preadv_part(bs->file, offset, bytes, qiov, qiov_offset, flags); @@ -359,14 +360,11 @@ preallocate_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset, return bdrv_co_pwrite_zeroes(bs->file, offset, bytes, flags); } -static coroutine_fn int preallocate_co_pwritev_part(BlockDriverState *bs, - int64_t offset, - int64_t bytes, - QEMUIOVector *qiov, - size_t qiov_offset, - BdrvRequestFlags flags) +static int coroutine_fn GRAPH_RDLOCK +preallocate_co_pwritev_part(BlockDriverState *bs, int64_t offset, int64_t bytes, + QEMUIOVector *qiov, size_t qiov_offset, + BdrvRequestFlags flags) { - assume_graph_lock(); /* FIXME */ handle_write(bs, offset, bytes, false); return bdrv_co_pwritev_part(bs->file, offset, bytes, qiov, qiov_offset, diff --git a/block/qcow.c b/block/qcow.c index 1e1d1792d0..58a0b4e2f0 100644 --- a/block/qcow.c +++ b/block/qcow.c @@ -92,8 +92,8 @@ typedef struct BDRVQcowState { static QemuOptsList qcow_create_opts; -static int coroutine_fn decompress_cluster(BlockDriverState *bs, - uint64_t cluster_offset); +static int coroutine_fn GRAPH_RDLOCK +decompress_cluster(BlockDriverState *bs, uint64_t cluster_offset); static int qcow_probe(const uint8_t *buf, int buf_size, const char *filename) { @@ -584,8 +584,8 @@ static int decompress_buffer(uint8_t *out_buf, int out_buf_size, return 0; } -static int coroutine_fn decompress_cluster(BlockDriverState *bs, - uint64_t cluster_offset) +static int coroutine_fn GRAPH_RDLOCK +decompress_cluster(BlockDriverState *bs, uint64_t cluster_offset) { BDRVQcowState *s = bs->opaque; int ret, csize; diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c index a22607d90d..a9e6622fe3 100644 --- a/block/qcow2-cluster.c +++ b/block/qcow2-cluster.c @@ -534,10 +534,9 @@ do_perform_cow_read(BlockDriverState *bs, uint64_t src_cluster_offset, return 0; } -static int coroutine_fn do_perform_cow_write(BlockDriverState *bs, - uint64_t cluster_offset, - unsigned offset_in_cluster, - QEMUIOVector *qiov) +static int coroutine_fn GRAPH_RDLOCK +do_perform_cow_write(BlockDriverState *bs, uint64_t cluster_offset, + unsigned offset_in_cluster, QEMUIOVector *qiov) { BDRVQcow2State *s = bs->opaque; int ret; diff --git a/block/qcow2.c b/block/qcow2.c index 8f5ad75984..ddf9394bf0 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -601,9 +601,9 @@ static void qcow2_add_check_result(BdrvCheckResult *out, } } -static int coroutine_fn qcow2_co_check_locked(BlockDriverState *bs, - BdrvCheckResult *result, - BdrvCheckMode fix) +static int coroutine_fn GRAPH_RDLOCK +qcow2_co_check_locked(BlockDriverState *bs, BdrvCheckResult *result, + BdrvCheckMode fix) { BdrvCheckResult snapshot_res = {}; BdrvCheckResult refcount_res = {}; @@ -640,9 +640,9 @@ static int coroutine_fn qcow2_co_check_locked(BlockDriverState *bs, return ret; } -static int coroutine_fn qcow2_co_check(BlockDriverState *bs, - BdrvCheckResult *result, - BdrvCheckMode fix) +static int coroutine_fn GRAPH_RDLOCK +qcow2_co_check(BlockDriverState *bs, BdrvCheckResult *result, + BdrvCheckMode fix) { BDRVQcow2State *s = bs->opaque; int ret; @@ -1294,9 +1294,9 @@ static int validate_compression_type(BDRVQcow2State *s, Error **errp) } /* Called with s->lock held. */ -static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options, - int flags, bool open_data_file, - Error **errp) +static int coroutine_fn GRAPH_RDLOCK +qcow2_do_open(BlockDriverState *bs, QDict *options, int flags, + bool open_data_file, Error **errp) { ERRP_GUARD(); BDRVQcow2State *s = bs->opaque; @@ -1890,6 +1890,8 @@ static void coroutine_fn qcow2_open_entry(void *opaque) QCow2OpenCo *qoc = opaque; BDRVQcow2State *s = qoc->bs->opaque; + assume_graph_lock(); /* FIXME */ + qemu_co_mutex_lock(&s->lock); qoc->ret = qcow2_do_open(qoc->bs, qoc->options, qoc->flags, true, qoc->errp); @@ -2169,7 +2171,7 @@ out: return ret; } -static coroutine_fn int +static int coroutine_fn GRAPH_RDLOCK qcow2_co_preadv_encrypted(BlockDriverState *bs, uint64_t host_offset, uint64_t offset, @@ -2270,12 +2272,10 @@ static coroutine_fn int qcow2_add_task(BlockDriverState *bs, return 0; } -static coroutine_fn int qcow2_co_preadv_task(BlockDriverState *bs, - QCow2SubclusterType subc_type, - uint64_t host_offset, - uint64_t offset, uint64_t bytes, - QEMUIOVector *qiov, - size_t qiov_offset) +static int coroutine_fn GRAPH_RDLOCK +qcow2_co_preadv_task(BlockDriverState *bs, QCow2SubclusterType subc_type, + uint64_t host_offset, uint64_t offset, uint64_t bytes, + QEMUIOVector *qiov, size_t qiov_offset) { BDRVQcow2State *s = bs->opaque; @@ -2314,7 +2314,11 @@ static coroutine_fn int qcow2_co_preadv_task(BlockDriverState *bs, g_assert_not_reached(); } -static coroutine_fn int qcow2_co_preadv_task_entry(AioTask *task) +/* + * This function can count as GRAPH_RDLOCK because qcow2_co_preadv_part() holds + * the graph lock and keeps it until this coroutine has terminated. + */ +static int coroutine_fn GRAPH_RDLOCK qcow2_co_preadv_task_entry(AioTask *task) { Qcow2AioTask *t = container_of(task, Qcow2AioTask, task); @@ -2325,11 +2329,10 @@ static coroutine_fn int qcow2_co_preadv_task_entry(AioTask *task) t->qiov, t->qiov_offset); } -static coroutine_fn int qcow2_co_preadv_part(BlockDriverState *bs, - int64_t offset, int64_t bytes, - QEMUIOVector *qiov, - size_t qiov_offset, - BdrvRequestFlags flags) +static int coroutine_fn GRAPH_RDLOCK +qcow2_co_preadv_part(BlockDriverState *bs, int64_t offset, int64_t bytes, + QEMUIOVector *qiov, size_t qiov_offset, + BdrvRequestFlags flags) { BDRVQcow2State *s = bs->opaque; int ret = 0; @@ -2774,8 +2777,8 @@ static void qcow2_close(BlockDriverState *bs) qcow2_do_close(bs, true); } -static void coroutine_fn qcow2_co_invalidate_cache(BlockDriverState *bs, - Error **errp) +static void coroutine_fn GRAPH_RDLOCK +qcow2_co_invalidate_cache(BlockDriverState *bs, Error **errp) { ERRP_GUARD(); BDRVQcow2State *s = bs->opaque; @@ -4737,7 +4740,7 @@ qcow2_co_pwritev_compressed_part(BlockDriverState *bs, return ret; } -static int coroutine_fn +static int coroutine_fn GRAPH_RDLOCK qcow2_co_preadv_compressed(BlockDriverState *bs, uint64_t l2_entry, uint64_t offset, diff --git a/block/qcow2.h b/block/qcow2.h index 46dca53e45..7487bcfcf9 100644 --- a/block/qcow2.h +++ b/block/qcow2.h @@ -846,7 +846,7 @@ int qcow2_validate_table(BlockDriverState *bs, uint64_t offset, Error **errp); /* qcow2-refcount.c functions */ -int coroutine_fn qcow2_refcount_init(BlockDriverState *bs); +int coroutine_fn GRAPH_RDLOCK qcow2_refcount_init(BlockDriverState *bs); void qcow2_refcount_close(BlockDriverState *bs); int qcow2_get_refcount(BlockDriverState *bs, int64_t cluster_index, @@ -954,9 +954,10 @@ void qcow2_free_snapshots(BlockDriverState *bs); int qcow2_read_snapshots(BlockDriverState *bs, Error **errp); int qcow2_write_snapshots(BlockDriverState *bs); -int coroutine_fn qcow2_check_read_snapshot_table(BlockDriverState *bs, - BdrvCheckResult *result, - BdrvCheckMode fix); +int coroutine_fn GRAPH_RDLOCK +qcow2_check_read_snapshot_table(BlockDriverState *bs, BdrvCheckResult *result, + BdrvCheckMode fix); + int coroutine_fn qcow2_check_fix_snapshot_table(BlockDriverState *bs, BdrvCheckResult *result, BdrvCheckMode fix); diff --git a/block/qed-table.c b/block/qed-table.c index e9c72814c8..3b331ce709 100644 --- a/block/qed-table.c +++ b/block/qed-table.c @@ -21,8 +21,8 @@ #include "qemu/memalign.h" /* Called with table_lock held. */ -static int coroutine_fn qed_read_table(BDRVQEDState *s, uint64_t offset, - QEDTable *table) +static int coroutine_fn GRAPH_RDLOCK +qed_read_table(BDRVQEDState *s, uint64_t offset, QEDTable *table) { unsigned int bytes = s->header.cluster_size * s->header.table_size; diff --git a/block/qed.c b/block/qed.c index a4a74e59ef..c969b31e2c 100644 --- a/block/qed.c +++ b/block/qed.c @@ -100,7 +100,7 @@ int qed_write_header_sync(BDRVQEDState *s) * * No new allocating reqs can start while this function runs. */ -static int coroutine_fn qed_write_header(BDRVQEDState *s) +static int coroutine_fn GRAPH_RDLOCK qed_write_header(BDRVQEDState *s) { /* We must write full sectors for O_DIRECT but cannot necessarily generate * the data following the header if an unrecognized compat feature is @@ -826,11 +826,10 @@ fail: return ret; } -static int coroutine_fn bdrv_qed_co_block_status(BlockDriverState *bs, - bool want_zero, - int64_t pos, int64_t bytes, - int64_t *pnum, int64_t *map, - BlockDriverState **file) +static int coroutine_fn GRAPH_RDLOCK +bdrv_qed_co_block_status(BlockDriverState *bs, bool want_zero, int64_t pos, + int64_t bytes, int64_t *pnum, int64_t *map, + BlockDriverState **file) { BDRVQEDState *s = bs->opaque; size_t len = MIN(bytes, SIZE_MAX); @@ -883,8 +882,8 @@ static BDRVQEDState *acb_to_s(QEDAIOCB *acb) * This function reads qiov->size bytes starting at pos from the backing file. * If there is no backing file then zeroes are read. */ -static int coroutine_fn qed_read_backing_file(BDRVQEDState *s, uint64_t pos, - QEMUIOVector *qiov) +static int coroutine_fn GRAPH_RDLOCK +qed_read_backing_file(BDRVQEDState *s, uint64_t pos, QEMUIOVector *qiov) { if (s->bs->backing) { BLKDBG_EVENT(s->bs->file, BLKDBG_READ_BACKING_AIO); @@ -902,9 +901,9 @@ static int coroutine_fn qed_read_backing_file(BDRVQEDState *s, uint64_t pos, * @len: Number of bytes * @offset: Byte offset in image file */ -static int coroutine_fn qed_copy_from_backing_file(BDRVQEDState *s, - uint64_t pos, uint64_t len, - uint64_t offset) +static int coroutine_fn GRAPH_RDLOCK +qed_copy_from_backing_file(BDRVQEDState *s, uint64_t pos, uint64_t len, + uint64_t offset) { QEMUIOVector qiov; int ret; @@ -1066,7 +1065,7 @@ qed_aio_write_l2_update(QEDAIOCB *acb, uint64_t offset) * * Called with table_lock *not* held. */ -static int coroutine_fn qed_aio_write_main(QEDAIOCB *acb) +static int coroutine_fn GRAPH_RDLOCK qed_aio_write_main(QEDAIOCB *acb) { BDRVQEDState *s = acb_to_s(acb); uint64_t offset = acb->cur_cluster + @@ -1226,8 +1225,8 @@ qed_aio_write_alloc(QEDAIOCB *acb, size_t len) * * Called with table_lock held. */ -static int coroutine_fn qed_aio_write_inplace(QEDAIOCB *acb, uint64_t offset, - size_t len) +static int coroutine_fn GRAPH_RDLOCK +qed_aio_write_inplace(QEDAIOCB *acb, uint64_t offset, size_t len) { BDRVQEDState *s = acb_to_s(acb); int r; @@ -1302,8 +1301,8 @@ qed_aio_write_data(void *opaque, int ret, uint64_t offset, size_t len) * * Called with table_lock held. */ -static int coroutine_fn qed_aio_read_data(void *opaque, int ret, - uint64_t offset, size_t len) +static int coroutine_fn GRAPH_RDLOCK +qed_aio_read_data(void *opaque, int ret, uint64_t offset, size_t len) { QEDAIOCB *acb = opaque; BDRVQEDState *s = acb_to_s(acb); diff --git a/block/qed.h b/block/qed.h index e48f7c2480..988654cb86 100644 --- a/block/qed.h +++ b/block/qed.h @@ -200,7 +200,7 @@ void qed_commit_l2_cache_entry(L2TableCache *l2_cache, CachedL2Table *l2_table); /** * Table I/O functions */ -int coroutine_fn qed_read_l1_table_sync(BDRVQEDState *s); +int coroutine_fn GRAPH_RDLOCK qed_read_l1_table_sync(BDRVQEDState *s); int coroutine_fn GRAPH_RDLOCK qed_write_l1_table(BDRVQEDState *s, unsigned int index, unsigned int n); @@ -208,10 +208,11 @@ qed_write_l1_table(BDRVQEDState *s, unsigned int index, unsigned int n); int coroutine_fn GRAPH_RDLOCK qed_write_l1_table_sync(BDRVQEDState *s, unsigned int index, unsigned int n); -int coroutine_fn qed_read_l2_table_sync(BDRVQEDState *s, QEDRequest *request, - uint64_t offset); -int coroutine_fn qed_read_l2_table(BDRVQEDState *s, QEDRequest *request, - uint64_t offset); +int coroutine_fn GRAPH_RDLOCK +qed_read_l2_table_sync(BDRVQEDState *s, QEDRequest *request, uint64_t offset); + +int coroutine_fn GRAPH_RDLOCK +qed_read_l2_table(BDRVQEDState *s, QEDRequest *request, uint64_t offset); int coroutine_fn GRAPH_RDLOCK qed_write_l2_table(BDRVQEDState *s, QEDRequest *request, unsigned int index, @@ -224,9 +225,9 @@ qed_write_l2_table_sync(BDRVQEDState *s, QEDRequest *request, /** * Cluster functions */ -int coroutine_fn qed_find_cluster(BDRVQEDState *s, QEDRequest *request, - uint64_t pos, size_t *len, - uint64_t *img_offset); +int coroutine_fn GRAPH_RDLOCK +qed_find_cluster(BDRVQEDState *s, QEDRequest *request, uint64_t pos, + size_t *len, uint64_t *img_offset); /** * Consistency check @@ -234,7 +235,6 @@ int coroutine_fn qed_find_cluster(BDRVQEDState *s, QEDRequest *request, int coroutine_fn GRAPH_RDLOCK qed_check(BDRVQEDState *s, BdrvCheckResult *result, bool fix); - QEDTable *qed_alloc_table(BDRVQEDState *s); /** diff --git a/block/quorum.c b/block/quorum.c index ef6cda2868..d58f86d3a5 100644 --- a/block/quorum.c +++ b/block/quorum.c @@ -270,7 +270,11 @@ static void quorum_report_bad_versions(BDRVQuorumState *s, } } -static void coroutine_fn quorum_rewrite_entry(void *opaque) +/* + * This function can count as GRAPH_RDLOCK because read_quorum_children() holds + * the graph lock and keeps it until this coroutine has terminated. + */ +static void coroutine_fn GRAPH_RDLOCK quorum_rewrite_entry(void *opaque) { QuorumCo *co = opaque; QuorumAIOCB *acb = co->acb; @@ -290,8 +294,8 @@ static void coroutine_fn quorum_rewrite_entry(void *opaque) } } -static bool quorum_rewrite_bad_versions(QuorumAIOCB *acb, - QuorumVoteValue *value) +static bool coroutine_fn GRAPH_RDLOCK +quorum_rewrite_bad_versions(QuorumAIOCB *acb, QuorumVoteValue *value) { QuorumVoteVersion *version; QuorumVoteItem *item; @@ -491,7 +495,7 @@ static int quorum_vote_error(QuorumAIOCB *acb) return ret; } -static void quorum_vote(QuorumAIOCB *acb) +static void coroutine_fn GRAPH_RDLOCK quorum_vote(QuorumAIOCB *acb) { bool quorum = true; int i, j, ret; @@ -571,7 +575,11 @@ free_exit: quorum_free_vote_list(&acb->votes); } -static void coroutine_fn read_quorum_children_entry(void *opaque) +/* + * This function can count as GRAPH_RDLOCK because read_quorum_children() holds + * the graph lock and keeps it until this coroutine has terminated. + */ +static void coroutine_fn GRAPH_RDLOCK read_quorum_children_entry(void *opaque) { QuorumCo *co = opaque; QuorumAIOCB *acb = co->acb; @@ -599,7 +607,7 @@ static void coroutine_fn read_quorum_children_entry(void *opaque) } } -static int coroutine_fn read_quorum_children(QuorumAIOCB *acb) +static int coroutine_fn GRAPH_RDLOCK read_quorum_children(QuorumAIOCB *acb) { BDRVQuorumState *s = acb->bs->opaque; int i; @@ -640,7 +648,7 @@ static int coroutine_fn read_quorum_children(QuorumAIOCB *acb) return acb->vote_ret; } -static int coroutine_fn read_fifo_child(QuorumAIOCB *acb) +static int coroutine_fn GRAPH_RDLOCK read_fifo_child(QuorumAIOCB *acb) { BDRVQuorumState *s = acb->bs->opaque; int n, ret; @@ -661,10 +669,9 @@ static int coroutine_fn read_fifo_child(QuorumAIOCB *acb) return ret; } -static int coroutine_fn quorum_co_preadv(BlockDriverState *bs, - int64_t offset, int64_t bytes, - QEMUIOVector *qiov, - BdrvRequestFlags flags) +static int coroutine_fn GRAPH_RDLOCK +quorum_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes, + QEMUIOVector *qiov, BdrvRequestFlags flags) { BDRVQuorumState *s = bs->opaque; QuorumAIOCB *acb = quorum_aio_get(bs, qiov, offset, bytes, flags); diff --git a/block/raw-format.c b/block/raw-format.c index 007d7f6e42..92adf97ab0 100644 --- a/block/raw-format.c +++ b/block/raw-format.c @@ -203,9 +203,9 @@ static inline int raw_adjust_offset(BlockDriverState *bs, int64_t *offset, return 0; } -static int coroutine_fn raw_co_preadv(BlockDriverState *bs, int64_t offset, - int64_t bytes, QEMUIOVector *qiov, - BdrvRequestFlags flags) +static int coroutine_fn GRAPH_RDLOCK +raw_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes, + QEMUIOVector *qiov, BdrvRequestFlags flags) { int ret; @@ -218,9 +218,9 @@ static int coroutine_fn raw_co_preadv(BlockDriverState *bs, int64_t offset, return bdrv_co_preadv(bs->file, offset, bytes, qiov, flags); } -static int coroutine_fn raw_co_pwritev(BlockDriverState *bs, int64_t offset, - int64_t bytes, QEMUIOVector *qiov, - BdrvRequestFlags flags) +static int coroutine_fn GRAPH_RDLOCK +raw_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes, + QEMUIOVector *qiov, BdrvRequestFlags flags) { void *buf = NULL; BlockDriver *drv; diff --git a/block/replication.c b/block/replication.c index a27417d310..f9f899bfc8 100644 --- a/block/replication.c +++ b/block/replication.c @@ -220,10 +220,9 @@ static int replication_return_value(BDRVReplicationState *s, int ret) return ret; } -static coroutine_fn int replication_co_readv(BlockDriverState *bs, - int64_t sector_num, - int remaining_sectors, - QEMUIOVector *qiov) +static int coroutine_fn GRAPH_RDLOCK +replication_co_readv(BlockDriverState *bs, int64_t sector_num, + int remaining_sectors, QEMUIOVector *qiov) { BDRVReplicationState *s = bs->opaque; int ret; @@ -244,11 +243,9 @@ static coroutine_fn int replication_co_readv(BlockDriverState *bs, return replication_return_value(s, ret); } -static coroutine_fn int replication_co_writev(BlockDriverState *bs, - int64_t sector_num, - int remaining_sectors, - QEMUIOVector *qiov, - int flags) +static int coroutine_fn GRAPH_RDLOCK +replication_co_writev(BlockDriverState *bs, int64_t sector_num, + int remaining_sectors, QEMUIOVector *qiov, int flags) { BDRVReplicationState *s = bs->opaque; QEMUIOVector hd_qiov; diff --git a/block/throttle.c b/block/throttle.c index 3db4fa3c40..5cfea3d5f8 100644 --- a/block/throttle.c +++ b/block/throttle.c @@ -111,10 +111,9 @@ static int64_t coroutine_fn throttle_co_getlength(BlockDriverState *bs) return bdrv_co_getlength(bs->file->bs); } -static int coroutine_fn throttle_co_preadv(BlockDriverState *bs, - int64_t offset, int64_t bytes, - QEMUIOVector *qiov, - BdrvRequestFlags flags) +static int coroutine_fn GRAPH_RDLOCK +throttle_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes, + QEMUIOVector *qiov, BdrvRequestFlags flags) { ThrottleGroupMember *tgm = bs->opaque; @@ -123,10 +122,9 @@ static int coroutine_fn throttle_co_preadv(BlockDriverState *bs, return bdrv_co_preadv(bs->file, offset, bytes, qiov, flags); } -static int coroutine_fn throttle_co_pwritev(BlockDriverState *bs, - int64_t offset, int64_t bytes, - QEMUIOVector *qiov, - BdrvRequestFlags flags) +static int coroutine_fn GRAPH_RDLOCK +throttle_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes, + QEMUIOVector *qiov, BdrvRequestFlags flags) { ThrottleGroupMember *tgm = bs->opaque; throttle_group_co_io_limits_intercept(tgm, bytes, true); @@ -153,10 +151,9 @@ throttle_co_pdiscard(BlockDriverState *bs, int64_t offset, int64_t bytes) return bdrv_co_pdiscard(bs->file, offset, bytes); } -static int coroutine_fn throttle_co_pwritev_compressed(BlockDriverState *bs, - int64_t offset, - int64_t bytes, - QEMUIOVector *qiov) +static int coroutine_fn GRAPH_RDLOCK +throttle_co_pwritev_compressed(BlockDriverState *bs, int64_t offset, + int64_t bytes, QEMUIOVector *qiov) { return throttle_co_pwritev(bs, offset, bytes, qiov, BDRV_REQ_WRITE_COMPRESSED); diff --git a/block/vdi.c b/block/vdi.c index 27db67d493..b50c0b7277 100644 --- a/block/vdi.c +++ b/block/vdi.c @@ -544,7 +544,7 @@ static int coroutine_fn vdi_co_block_status(BlockDriverState *bs, (s->header.image_type == VDI_TYPE_STATIC ? BDRV_BLOCK_RECURSE : 0); } -static int coroutine_fn +static int coroutine_fn GRAPH_RDLOCK vdi_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes, QEMUIOVector *qiov, BdrvRequestFlags flags) { @@ -600,7 +600,7 @@ vdi_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes, return ret; } -static int coroutine_fn +static int coroutine_fn GRAPH_RDLOCK vdi_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes, QEMUIOVector *qiov, BdrvRequestFlags flags) { diff --git a/block/vhdx.c b/block/vhdx.c index 59fbdb413b..ffa4455e82 100644 --- a/block/vhdx.c +++ b/block/vhdx.c @@ -1172,8 +1172,9 @@ vhdx_co_get_info(BlockDriverState *bs, BlockDriverInfo *bdi) } -static coroutine_fn int vhdx_co_readv(BlockDriverState *bs, int64_t sector_num, - int nb_sectors, QEMUIOVector *qiov) +static int coroutine_fn GRAPH_RDLOCK +vhdx_co_readv(BlockDriverState *bs, int64_t sector_num, int nb_sectors, + QEMUIOVector *qiov) { BDRVVHDXState *s = bs->opaque; int ret = 0; @@ -1324,9 +1325,9 @@ int vhdx_user_visible_write(BlockDriverState *bs, BDRVVHDXState *s) return ret; } -static coroutine_fn int vhdx_co_writev(BlockDriverState *bs, int64_t sector_num, - int nb_sectors, QEMUIOVector *qiov, - int flags) +static int coroutine_fn GRAPH_RDLOCK +vhdx_co_writev(BlockDriverState *bs, int64_t sector_num, int nb_sectors, + QEMUIOVector *qiov, int flags) { int ret = -ENOTSUP; BDRVVHDXState *s = bs->opaque; diff --git a/block/vmdk.c b/block/vmdk.c index 8b844300f4..c601ca85f4 100644 --- a/block/vmdk.c +++ b/block/vmdk.c @@ -1403,13 +1403,11 @@ static void vmdk_refresh_limits(BlockDriverState *bs, Error **errp) * [@skip_start_sector, @skip_end_sector) is not copied or written, and leave * it for call to write user data in the request. */ -static int coroutine_fn get_whole_cluster(BlockDriverState *bs, - VmdkExtent *extent, - uint64_t cluster_offset, - uint64_t offset, - uint64_t skip_start_bytes, - uint64_t skip_end_bytes, - bool zeroed) +static int coroutine_fn GRAPH_RDLOCK +get_whole_cluster(BlockDriverState *bs, VmdkExtent *extent, + uint64_t cluster_offset, uint64_t offset, + uint64_t skip_start_bytes, uint64_t skip_end_bytes, + bool zeroed) { int ret = VMDK_OK; int64_t cluster_bytes; @@ -1536,14 +1534,11 @@ vmdk_L2update(VmdkExtent *extent, VmdkMetaData *m_data, uint32_t offset) * VMDK_UNALLOC if cluster is not mapped and @allocate is false. * VMDK_ERROR if failed. */ -static int coroutine_fn get_cluster_offset(BlockDriverState *bs, - VmdkExtent *extent, - VmdkMetaData *m_data, - uint64_t offset, - bool allocate, - uint64_t *cluster_offset, - uint64_t skip_start_bytes, - uint64_t skip_end_bytes) +static int coroutine_fn GRAPH_RDLOCK +get_cluster_offset(BlockDriverState *bs, VmdkExtent *extent, + VmdkMetaData *m_data, uint64_t offset, bool allocate, + uint64_t *cluster_offset, uint64_t skip_start_bytes, + uint64_t skip_end_bytes) { unsigned int l1_index, l2_offset, l2_index; int min_index, i, j; @@ -1736,11 +1731,10 @@ static inline uint64_t vmdk_find_offset_in_cluster(VmdkExtent *extent, return extent_relative_offset % cluster_size; } -static int coroutine_fn vmdk_co_block_status(BlockDriverState *bs, - bool want_zero, - int64_t offset, int64_t bytes, - int64_t *pnum, int64_t *map, - BlockDriverState **file) +static int coroutine_fn GRAPH_RDLOCK +vmdk_co_block_status(BlockDriverState *bs, bool want_zero, + int64_t offset, int64_t bytes, int64_t *pnum, + int64_t *map, BlockDriverState **file) { BDRVVmdkState *s = bs->opaque; int64_t index_in_cluster, n, ret; @@ -1785,7 +1779,7 @@ static int coroutine_fn vmdk_co_block_status(BlockDriverState *bs, return ret; } -static int coroutine_fn +static int coroutine_fn GRAPH_RDLOCK vmdk_write_extent(VmdkExtent *extent, int64_t cluster_offset, int64_t offset_in_cluster, QEMUIOVector *qiov, uint64_t qiov_offset, uint64_t n_bytes, @@ -1867,10 +1861,9 @@ vmdk_write_extent(VmdkExtent *extent, int64_t cluster_offset, return ret; } -static int coroutine_fn +static int coroutine_fn GRAPH_RDLOCK vmdk_read_extent(VmdkExtent *extent, int64_t cluster_offset, - int64_t offset_in_cluster, QEMUIOVector *qiov, - int bytes) + int64_t offset_in_cluster, QEMUIOVector *qiov, int bytes) { int ret; int cluster_bytes, buf_bytes; @@ -1934,7 +1927,7 @@ vmdk_read_extent(VmdkExtent *extent, int64_t cluster_offset, return ret; } -static int coroutine_fn +static int coroutine_fn GRAPH_RDLOCK vmdk_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes, QEMUIOVector *qiov, BdrvRequestFlags flags) { @@ -2016,9 +2009,9 @@ fail: * * Returns: error code with 0 for success. */ -static int coroutine_fn vmdk_pwritev(BlockDriverState *bs, uint64_t offset, - uint64_t bytes, QEMUIOVector *qiov, - bool zeroed, bool zero_dry_run) +static int coroutine_fn GRAPH_RDLOCK +vmdk_pwritev(BlockDriverState *bs, uint64_t offset, uint64_t bytes, + QEMUIOVector *qiov, bool zeroed, bool zero_dry_run) { BDRVVmdkState *s = bs->opaque; VmdkExtent *extent = NULL; @@ -2028,8 +2021,6 @@ static int coroutine_fn vmdk_pwritev(BlockDriverState *bs, uint64_t offset, uint64_t bytes_done = 0; VmdkMetaData m_data; - assume_graph_lock(); /* FIXME */ - if (DIV_ROUND_UP(offset, BDRV_SECTOR_SIZE) > bs->total_sectors) { error_report("Wrong offset: offset=0x%" PRIx64 " total_sectors=0x%" PRIx64, @@ -2116,7 +2107,7 @@ static int coroutine_fn vmdk_pwritev(BlockDriverState *bs, uint64_t offset, return 0; } -static int coroutine_fn +static int coroutine_fn GRAPH_RDLOCK vmdk_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes, QEMUIOVector *qiov, BdrvRequestFlags flags) { @@ -2156,10 +2147,9 @@ vmdk_co_pwritev_compressed(BlockDriverState *bs, int64_t offset, int64_t bytes, return vmdk_co_pwritev(bs, offset, bytes, qiov, 0); } -static int coroutine_fn vmdk_co_pwrite_zeroes(BlockDriverState *bs, - int64_t offset, - int64_t bytes, - BdrvRequestFlags flags) +static int coroutine_fn GRAPH_RDLOCK +vmdk_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset, int64_t bytes, + BdrvRequestFlags flags) { int ret; BDRVVmdkState *s = bs->opaque; @@ -2920,9 +2910,8 @@ static VmdkExtentInfo *vmdk_get_extent_info(VmdkExtent *extent) return info; } -static int coroutine_fn vmdk_co_check(BlockDriverState *bs, - BdrvCheckResult *result, - BdrvCheckMode fix) +static int coroutine_fn GRAPH_RDLOCK +vmdk_co_check(BlockDriverState *bs, BdrvCheckResult *result, BdrvCheckMode fix) { BDRVVmdkState *s = bs->opaque; VmdkExtent *extent = NULL; diff --git a/block/vpc.c b/block/vpc.c index 3c256fc5a4..1f0f26c0c4 100644 --- a/block/vpc.c +++ b/block/vpc.c @@ -610,7 +610,7 @@ vpc_co_get_info(BlockDriverState *bs, BlockDriverInfo *bdi) return 0; } -static int coroutine_fn +static int coroutine_fn GRAPH_RDLOCK vpc_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes, QEMUIOVector *qiov, BdrvRequestFlags flags) { @@ -660,7 +660,7 @@ fail: return ret; } -static int coroutine_fn +static int coroutine_fn GRAPH_RDLOCK vpc_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes, QEMUIOVector *qiov, BdrvRequestFlags flags) { diff --git a/include/block/block_int-io.h b/include/block/block_int-io.h index 4bb6ccaa34..34d4b0fb8e 100644 --- a/include/block/block_int-io.h +++ b/include/block/block_int-io.h @@ -44,33 +44,35 @@ int coroutine_fn GRAPH_RDLOCK bdrv_co_pdiscard_snapshot(BlockDriverState *bs, int64_t offset, int64_t bytes); -int coroutine_fn bdrv_co_preadv(BdrvChild *child, +int coroutine_fn GRAPH_RDLOCK bdrv_co_preadv(BdrvChild *child, int64_t offset, int64_t bytes, QEMUIOVector *qiov, BdrvRequestFlags flags); -int coroutine_fn bdrv_co_preadv_part(BdrvChild *child, +int coroutine_fn GRAPH_RDLOCK bdrv_co_preadv_part(BdrvChild *child, int64_t offset, int64_t bytes, QEMUIOVector *qiov, size_t qiov_offset, BdrvRequestFlags flags); -int coroutine_fn bdrv_co_pwritev(BdrvChild *child, +int coroutine_fn GRAPH_RDLOCK bdrv_co_pwritev(BdrvChild *child, int64_t offset, int64_t bytes, QEMUIOVector *qiov, BdrvRequestFlags flags); -int coroutine_fn bdrv_co_pwritev_part(BdrvChild *child, +int coroutine_fn GRAPH_RDLOCK bdrv_co_pwritev_part(BdrvChild *child, int64_t offset, int64_t bytes, QEMUIOVector *qiov, size_t qiov_offset, BdrvRequestFlags flags); -static inline int coroutine_fn bdrv_co_pread(BdrvChild *child, +static inline int coroutine_fn GRAPH_RDLOCK bdrv_co_pread(BdrvChild *child, int64_t offset, int64_t bytes, void *buf, BdrvRequestFlags flags) { QEMUIOVector qiov = QEMU_IOVEC_INIT_BUF(qiov, buf, bytes); IO_CODE(); + assert_bdrv_graph_readable(); return bdrv_co_preadv(child, offset, bytes, &qiov, flags); } -static inline int coroutine_fn bdrv_co_pwrite(BdrvChild *child, +static inline int coroutine_fn GRAPH_RDLOCK bdrv_co_pwrite(BdrvChild *child, int64_t offset, int64_t bytes, const void *buf, BdrvRequestFlags flags) { QEMUIOVector qiov = QEMU_IOVEC_INIT_BUF(qiov, buf, bytes); IO_CODE(); + assert_bdrv_graph_readable(); return bdrv_co_pwritev(child, offset, bytes, &qiov, flags); } diff --git a/tests/unit/test-bdrv-drain.c b/tests/unit/test-bdrv-drain.c index 4fed8b751f..d9d3807062 100644 --- a/tests/unit/test-bdrv-drain.c +++ b/tests/unit/test-bdrv-drain.c @@ -933,10 +933,9 @@ static void bdrv_test_top_close(BlockDriverState *bs) } } -static int coroutine_fn bdrv_test_top_co_preadv(BlockDriverState *bs, - int64_t offset, int64_t bytes, - QEMUIOVector *qiov, - BdrvRequestFlags flags) +static int coroutine_fn GRAPH_RDLOCK +bdrv_test_top_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes, + QEMUIOVector *qiov, BdrvRequestFlags flags) { BDRVTestTopState *tts = bs->opaque; return bdrv_co_preadv(tts->wait_child, offset, bytes, qiov, flags); @@ -967,6 +966,8 @@ static void coroutine_fn test_co_delete_by_drain(void *opaque) void *buffer = g_malloc(65536); QEMUIOVector qiov = QEMU_IOVEC_INIT_BUF(qiov, buffer, 65536); + GRAPH_RDLOCK_GUARD(); + /* Pretend some internal write operation from parent to child. * Important: We have to read from the child, not from the parent! * Draining works by first propagating it all up the tree to the @@ -1698,11 +1699,9 @@ static void bdrv_replace_test_close(BlockDriverState *bs) * Otherwise: * Set .has_read to true and return success. */ -static int coroutine_fn bdrv_replace_test_co_preadv(BlockDriverState *bs, - int64_t offset, - int64_t bytes, - QEMUIOVector *qiov, - BdrvRequestFlags flags) +static int coroutine_fn GRAPH_RDLOCK +bdrv_replace_test_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes, + QEMUIOVector *qiov, BdrvRequestFlags flags) { BDRVReplaceTestState *s = bs->opaque; @@ -1778,7 +1777,10 @@ static void coroutine_fn bdrv_replace_test_read_entry(void *opaque) int ret; /* Queue a read request post-drain */ + bdrv_graph_co_rdlock(); ret = bdrv_replace_test_co_preadv(bs, 0, 1, &qiov, 0); + bdrv_graph_co_rdunlock(); + g_assert(ret >= 0); bdrv_dec_in_flight(bs); } From b24a4c41ba804f2f465adbc0ab57854cba4868e1 Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Fri, 3 Feb 2023 16:21:51 +0100 Subject: [PATCH 049/129] block: Mark bdrv_co_pwrite_sync() and callers GRAPH_RDLOCK This adds GRAPH_RDLOCK annotations to declare that callers of bdrv_co_pwrite_sync() need to hold a reader lock for the graph. For some places, we know that they will hold the lock, but we don't have the GRAPH_RDLOCK annotations yet. In this case, add assume_graph_lock() with a FIXME comment. These places will be removed once everything is properly annotated. Signed-off-by: Kevin Wolf Message-Id: <20230203152202.49054-13-kwolf@redhat.com> Reviewed-by: Emanuele Giuseppe Esposito Signed-off-by: Kevin Wolf --- block/io.c | 3 +-- block/qcow2.h | 2 +- include/block/block-io.h | 7 ++++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/block/io.c b/block/io.c index ec8b317818..2593823f62 100644 --- a/block/io.c +++ b/block/io.c @@ -933,8 +933,7 @@ int coroutine_fn bdrv_co_pwrite_sync(BdrvChild *child, int64_t offset, { int ret; IO_CODE(); - - assume_graph_lock(); /* FIXME */ + assert_bdrv_graph_readable(); ret = bdrv_co_pwrite(child, offset, bytes, buf, flags); if (ret < 0) { diff --git a/block/qcow2.h b/block/qcow2.h index 7487bcfcf9..c59e33c01c 100644 --- a/block/qcow2.h +++ b/block/qcow2.h @@ -893,7 +893,7 @@ int qcow2_inc_refcounts_imrt(BlockDriverState *bs, BdrvCheckResult *res, int qcow2_change_refcount_order(BlockDriverState *bs, int refcount_order, BlockDriverAmendStatusCB *status_cb, void *cb_opaque, Error **errp); -int coroutine_fn qcow2_shrink_reftable(BlockDriverState *bs); +int coroutine_fn GRAPH_RDLOCK qcow2_shrink_reftable(BlockDriverState *bs); int64_t qcow2_get_last_cluster(BlockDriverState *bs, int64_t size); int coroutine_fn qcow2_detect_metadata_preallocation(BlockDriverState *bs); diff --git a/include/block/block-io.h b/include/block/block-io.h index ec26f07d60..bbe8a5659a 100644 --- a/include/block/block-io.h +++ b/include/block/block-io.h @@ -60,9 +60,10 @@ int co_wrapper_mixed_bdrv_rdlock bdrv_pwrite_sync(BdrvChild *child, int64_t offset, int64_t bytes, const void *buf, BdrvRequestFlags flags); -int coroutine_fn bdrv_co_pwrite_sync(BdrvChild *child, int64_t offset, - int64_t bytes, const void *buf, - BdrvRequestFlags flags); +int coroutine_fn GRAPH_RDLOCK +bdrv_co_pwrite_sync(BdrvChild *child, int64_t offset, int64_t bytes, + const void *buf, BdrvRequestFlags flags); + /* * Efficiently zero a region of the disk image. Note that this is a regular * I/O request like read or write and should have a reasonable size. This From eeb4777544e41106c85146a96e16da14ab13110f Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Fri, 3 Feb 2023 16:21:52 +0100 Subject: [PATCH 050/129] block: Mark bdrv_co_do_pwrite_zeroes() GRAPH_RDLOCK All callers are already GRAPH_RDLOCK, so just add the annotation and remove assume_graph_lock(). Signed-off-by: Kevin Wolf Message-Id: <20230203152202.49054-14-kwolf@redhat.com> Reviewed-by: Emanuele Giuseppe Esposito Signed-off-by: Kevin Wolf --- block/io.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/block/io.c b/block/io.c index 2593823f62..628b350002 100644 --- a/block/io.c +++ b/block/io.c @@ -1672,8 +1672,9 @@ fail: return ret; } -static int coroutine_fn bdrv_co_do_pwrite_zeroes(BlockDriverState *bs, - int64_t offset, int64_t bytes, BdrvRequestFlags flags) +static int coroutine_fn GRAPH_RDLOCK +bdrv_co_do_pwrite_zeroes(BlockDriverState *bs, int64_t offset, int64_t bytes, + BdrvRequestFlags flags) { BlockDriver *drv = bs->drv; QEMUIOVector qiov; @@ -1683,8 +1684,6 @@ static int coroutine_fn bdrv_co_do_pwrite_zeroes(BlockDriverState *bs, int head = 0; int tail = 0; - assume_graph_lock(); /* FIXME */ - int64_t max_write_zeroes = MIN_NON_ZERO(bs->bl.max_pwrite_zeroes, INT64_MAX); int alignment = MAX(bs->bl.pwrite_zeroes_alignment, From 742bf09b2004a78708f64327d61471fe011ff799 Mon Sep 17 00:00:00 2001 From: Emanuele Giuseppe Esposito Date: Fri, 3 Feb 2023 16:21:53 +0100 Subject: [PATCH 051/129] block: Mark bdrv_co_copy_range() GRAPH_RDLOCK This adds GRAPH_RDLOCK annotations to declare that callers of bdrv_co_copy_range() need to hold a reader lock for the graph. Signed-off-by: Emanuele Giuseppe Esposito Signed-off-by: Kevin Wolf Message-Id: <20230203152202.49054-15-kwolf@redhat.com> Reviewed-by: Emanuele Giuseppe Esposito Signed-off-by: Kevin Wolf --- block/block-backend.c | 2 ++ block/file-posix.c | 16 +++++++--------- block/io.c | 7 +++++-- block/iscsi.c | 28 ++++++++++++---------------- block/qcow2.c | 5 ++--- block/raw-format.c | 28 ++++++++++++---------------- include/block/block-io.h | 9 +++++---- include/block/block_int-common.h | 24 ++++++++---------------- include/block/block_int-io.h | 20 ++++++++++---------- qemu-img.c | 4 +++- 10 files changed, 66 insertions(+), 77 deletions(-) diff --git a/block/block-backend.c b/block/block-backend.c index 146ef91547..fdb1e1d5f7 100644 --- a/block/block-backend.c +++ b/block/block-backend.c @@ -2644,6 +2644,8 @@ int coroutine_fn blk_co_copy_range(BlockBackend *blk_in, int64_t off_in, if (r) { return r; } + + GRAPH_RDLOCK_GUARD(); return bdrv_co_copy_range(blk_in->root, off_in, blk_out->root, off_out, bytes, read_flags, write_flags); diff --git a/block/file-posix.c b/block/file-posix.c index d106f4efa5..13da095efa 100644 --- a/block/file-posix.c +++ b/block/file-posix.c @@ -3272,7 +3272,7 @@ static void raw_abort_perm_update(BlockDriverState *bs) raw_handle_perm_lock(bs, RAW_PL_ABORT, 0, 0, NULL); } -static int coroutine_fn raw_co_copy_range_from( +static int coroutine_fn GRAPH_RDLOCK raw_co_copy_range_from( BlockDriverState *bs, BdrvChild *src, int64_t src_offset, BdrvChild *dst, int64_t dst_offset, int64_t bytes, BdrvRequestFlags read_flags, BdrvRequestFlags write_flags) @@ -3281,14 +3281,12 @@ static int coroutine_fn raw_co_copy_range_from( read_flags, write_flags); } -static int coroutine_fn raw_co_copy_range_to(BlockDriverState *bs, - BdrvChild *src, - int64_t src_offset, - BdrvChild *dst, - int64_t dst_offset, - int64_t bytes, - BdrvRequestFlags read_flags, - BdrvRequestFlags write_flags) +static int coroutine_fn GRAPH_RDLOCK +raw_co_copy_range_to(BlockDriverState *bs, + BdrvChild *src, int64_t src_offset, + BdrvChild *dst, int64_t dst_offset, + int64_t bytes, BdrvRequestFlags read_flags, + BdrvRequestFlags write_flags) { RawPosixAIOData acb; BDRVRawState *s = bs->opaque; diff --git a/block/io.c b/block/io.c index 628b350002..86e5ea362d 100644 --- a/block/io.c +++ b/block/io.c @@ -3246,6 +3246,7 @@ static int coroutine_fn GRAPH_RDLOCK bdrv_co_copy_range_internal( { BdrvTrackedRequest req; int ret; + assert_bdrv_graph_readable(); /* TODO We can support BDRV_REQ_NO_FALLBACK here */ assert(!(read_flags & BDRV_REQ_NO_FALLBACK)); @@ -3327,7 +3328,7 @@ int coroutine_fn bdrv_co_copy_range_from(BdrvChild *src, int64_t src_offset, BdrvRequestFlags write_flags) { IO_CODE(); - assume_graph_lock(); /* FIXME */ + assert_bdrv_graph_readable(); trace_bdrv_co_copy_range_from(src, src_offset, dst, dst_offset, bytes, read_flags, write_flags); return bdrv_co_copy_range_internal(src, src_offset, dst, dst_offset, @@ -3345,7 +3346,7 @@ int coroutine_fn bdrv_co_copy_range_to(BdrvChild *src, int64_t src_offset, BdrvRequestFlags write_flags) { IO_CODE(); - assume_graph_lock(); /* FIXME */ + assert_bdrv_graph_readable(); trace_bdrv_co_copy_range_to(src, src_offset, dst, dst_offset, bytes, read_flags, write_flags); return bdrv_co_copy_range_internal(src, src_offset, dst, dst_offset, @@ -3358,6 +3359,8 @@ int coroutine_fn bdrv_co_copy_range(BdrvChild *src, int64_t src_offset, BdrvRequestFlags write_flags) { IO_CODE(); + assert_bdrv_graph_readable(); + return bdrv_co_copy_range_from(src, src_offset, dst, dst_offset, bytes, read_flags, write_flags); diff --git a/block/iscsi.c b/block/iscsi.c index dc9a33bbff..9fc0bed90b 100644 --- a/block/iscsi.c +++ b/block/iscsi.c @@ -2190,14 +2190,12 @@ static void coroutine_fn iscsi_co_invalidate_cache(BlockDriverState *bs, iscsi_allocmap_invalidate(iscsilun); } -static int coroutine_fn iscsi_co_copy_range_from(BlockDriverState *bs, - BdrvChild *src, - int64_t src_offset, - BdrvChild *dst, - int64_t dst_offset, - int64_t bytes, - BdrvRequestFlags read_flags, - BdrvRequestFlags write_flags) +static int coroutine_fn GRAPH_RDLOCK +iscsi_co_copy_range_from(BlockDriverState *bs, + BdrvChild *src, int64_t src_offset, + BdrvChild *dst, int64_t dst_offset, + int64_t bytes, BdrvRequestFlags read_flags, + BdrvRequestFlags write_flags) { return bdrv_co_copy_range_to(src, src_offset, dst, dst_offset, bytes, read_flags, write_flags); @@ -2331,14 +2329,12 @@ static void iscsi_xcopy_data(struct iscsi_data *data, src_lba, dst_lba); } -static int coroutine_fn iscsi_co_copy_range_to(BlockDriverState *bs, - BdrvChild *src, - int64_t src_offset, - BdrvChild *dst, - int64_t dst_offset, - int64_t bytes, - BdrvRequestFlags read_flags, - BdrvRequestFlags write_flags) +static int coroutine_fn GRAPH_RDLOCK +iscsi_co_copy_range_to(BlockDriverState *bs, + BdrvChild *src, int64_t src_offset, + BdrvChild *dst, int64_t dst_offset, + int64_t bytes, BdrvRequestFlags read_flags, + BdrvRequestFlags write_flags) { IscsiLun *dst_lun = dst->bs->opaque; IscsiLun *src_lun; diff --git a/block/qcow2.c b/block/qcow2.c index ddf9394bf0..c318f41f38 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -4065,7 +4065,7 @@ static coroutine_fn int qcow2_co_pdiscard(BlockDriverState *bs, return ret; } -static int coroutine_fn +static int coroutine_fn GRAPH_RDLOCK qcow2_co_copy_range_from(BlockDriverState *bs, BdrvChild *src, int64_t src_offset, BdrvChild *dst, int64_t dst_offset, @@ -4148,7 +4148,7 @@ out: return ret; } -static int coroutine_fn +static int coroutine_fn GRAPH_RDLOCK qcow2_co_copy_range_to(BlockDriverState *bs, BdrvChild *src, int64_t src_offset, BdrvChild *dst, int64_t dst_offset, @@ -4161,7 +4161,6 @@ qcow2_co_copy_range_to(BlockDriverState *bs, uint64_t host_offset; QCowL2Meta *l2meta = NULL; - assume_graph_lock(); /* FIXME */ assert(!bs->encrypted); qemu_co_mutex_lock(&s->lock); diff --git a/block/raw-format.c b/block/raw-format.c index 92adf97ab0..9913cb8174 100644 --- a/block/raw-format.c +++ b/block/raw-format.c @@ -536,14 +536,12 @@ static int raw_probe_geometry(BlockDriverState *bs, HDGeometry *geo) return bdrv_probe_geometry(bs->file->bs, geo); } -static int coroutine_fn raw_co_copy_range_from(BlockDriverState *bs, - BdrvChild *src, - int64_t src_offset, - BdrvChild *dst, - int64_t dst_offset, - int64_t bytes, - BdrvRequestFlags read_flags, - BdrvRequestFlags write_flags) +static int coroutine_fn GRAPH_RDLOCK +raw_co_copy_range_from(BlockDriverState *bs, + BdrvChild *src, int64_t src_offset, + BdrvChild *dst, int64_t dst_offset, + int64_t bytes, BdrvRequestFlags read_flags, + BdrvRequestFlags write_flags) { int ret; @@ -555,14 +553,12 @@ static int coroutine_fn raw_co_copy_range_from(BlockDriverState *bs, bytes, read_flags, write_flags); } -static int coroutine_fn raw_co_copy_range_to(BlockDriverState *bs, - BdrvChild *src, - int64_t src_offset, - BdrvChild *dst, - int64_t dst_offset, - int64_t bytes, - BdrvRequestFlags read_flags, - BdrvRequestFlags write_flags) +static int coroutine_fn GRAPH_RDLOCK +raw_co_copy_range_to(BlockDriverState *bs, + BdrvChild *src, int64_t src_offset, + BdrvChild *dst, int64_t dst_offset, + int64_t bytes, BdrvRequestFlags read_flags, + BdrvRequestFlags write_flags) { int ret; diff --git a/include/block/block-io.h b/include/block/block-io.h index bbe8a5659a..c551742a86 100644 --- a/include/block/block-io.h +++ b/include/block/block-io.h @@ -274,10 +274,11 @@ bool co_wrapper bdrv_can_store_new_dirty_bitmap(BlockDriverState *bs, * * Returns: 0 if succeeded; negative error code if failed. **/ -int coroutine_fn bdrv_co_copy_range(BdrvChild *src, int64_t src_offset, - BdrvChild *dst, int64_t dst_offset, - int64_t bytes, BdrvRequestFlags read_flags, - BdrvRequestFlags write_flags); +int coroutine_fn GRAPH_RDLOCK +bdrv_co_copy_range(BdrvChild *src, int64_t src_offset, + BdrvChild *dst, int64_t dst_offset, + int64_t bytes, BdrvRequestFlags read_flags, + BdrvRequestFlags write_flags); /* * "I/O or GS" API functions. These functions can run without diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h index 192841f040..29b230cc0b 100644 --- a/include/block/block_int-common.h +++ b/include/block/block_int-common.h @@ -559,14 +559,10 @@ struct BlockDriver { * See the comment of bdrv_co_copy_range for the parameter and return value * semantics. */ - int coroutine_fn (*bdrv_co_copy_range_from)(BlockDriverState *bs, - BdrvChild *src, - int64_t offset, - BdrvChild *dst, - int64_t dst_offset, - int64_t bytes, - BdrvRequestFlags read_flags, - BdrvRequestFlags write_flags); + int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_copy_range_from)( + BlockDriverState *bs, BdrvChild *src, int64_t offset, + BdrvChild *dst, int64_t dst_offset, int64_t bytes, + BdrvRequestFlags read_flags, BdrvRequestFlags write_flags); /* * Map [offset, offset + nbytes) range onto a child of bs to copy data to, @@ -577,14 +573,10 @@ struct BlockDriver { * See the comment of bdrv_co_copy_range for the parameter and return value * semantics. */ - int coroutine_fn (*bdrv_co_copy_range_to)(BlockDriverState *bs, - BdrvChild *src, - int64_t src_offset, - BdrvChild *dst, - int64_t dst_offset, - int64_t bytes, - BdrvRequestFlags read_flags, - BdrvRequestFlags write_flags); + int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_copy_range_to)( + BlockDriverState *bs, BdrvChild *src, int64_t src_offset, + BdrvChild *dst, int64_t dst_offset, int64_t bytes, + BdrvRequestFlags read_flags, BdrvRequestFlags write_flags); /* * Building block for bdrv_block_status[_above] and diff --git a/include/block/block_int-io.h b/include/block/block_int-io.h index 34d4b0fb8e..5788bd66ba 100644 --- a/include/block/block_int-io.h +++ b/include/block/block_int-io.h @@ -113,16 +113,16 @@ void bdrv_dirty_bitmap_merge_internal(BdrvDirtyBitmap *dest, void bdrv_inc_in_flight(BlockDriverState *bs); void bdrv_dec_in_flight(BlockDriverState *bs); -int coroutine_fn bdrv_co_copy_range_from(BdrvChild *src, int64_t src_offset, - BdrvChild *dst, int64_t dst_offset, - int64_t bytes, - BdrvRequestFlags read_flags, - BdrvRequestFlags write_flags); -int coroutine_fn bdrv_co_copy_range_to(BdrvChild *src, int64_t src_offset, - BdrvChild *dst, int64_t dst_offset, - int64_t bytes, - BdrvRequestFlags read_flags, - BdrvRequestFlags write_flags); +int coroutine_fn GRAPH_RDLOCK +bdrv_co_copy_range_from(BdrvChild *src, int64_t src_offset, + BdrvChild *dst, int64_t dst_offset, + int64_t bytes, BdrvRequestFlags read_flags, + BdrvRequestFlags write_flags); +int coroutine_fn GRAPH_RDLOCK +bdrv_co_copy_range_to(BdrvChild *src, int64_t src_offset, + BdrvChild *dst, int64_t dst_offset, + int64_t bytes, BdrvRequestFlags read_flags, + BdrvRequestFlags write_flags); int coroutine_fn bdrv_co_refresh_total_sectors(BlockDriverState *bs, int64_t hint); diff --git a/qemu-img.c b/qemu-img.c index cd0178b51b..9aeac69fa6 100644 --- a/qemu-img.c +++ b/qemu-img.c @@ -2041,7 +2041,9 @@ retry: if (s->ret == -EINPROGRESS) { if (copy_range) { - ret = convert_co_copy_range(s, sector_num, n); + WITH_GRAPH_RDLOCK_GUARD() { + ret = convert_co_copy_range(s, sector_num, n); + } if (ret) { s->copy_range = false; goto retry; From 7b9e8b22bca534e0e86915c0856d77a7ae99e160 Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Fri, 3 Feb 2023 16:21:54 +0100 Subject: [PATCH 052/129] block: Mark preadv_snapshot/snapshot_block_status GRAPH_RDLOCK Signed-off-by: Kevin Wolf Message-Id: <20230203152202.49054-16-kwolf@redhat.com> Reviewed-by: Emanuele Giuseppe Esposito Signed-off-by: Kevin Wolf --- block/copy-before-write.c | 6 ++---- block/io.c | 2 ++ block/snapshot-access.c | 4 ++-- include/block/block_int-common.h | 12 +++++++----- include/block/block_int-io.h | 8 ++++---- 5 files changed, 17 insertions(+), 15 deletions(-) diff --git a/block/copy-before-write.c b/block/copy-before-write.c index e223e37300..646d8227a4 100644 --- a/block/copy-before-write.c +++ b/block/copy-before-write.c @@ -256,7 +256,7 @@ cbw_snapshot_read_unlock(BlockDriverState *bs, BlockReq *req) g_free(req); } -static coroutine_fn int +static int coroutine_fn GRAPH_RDLOCK cbw_co_preadv_snapshot(BlockDriverState *bs, int64_t offset, int64_t bytes, QEMUIOVector *qiov, size_t qiov_offset) { @@ -264,8 +264,6 @@ cbw_co_preadv_snapshot(BlockDriverState *bs, int64_t offset, int64_t bytes, BdrvChild *file; int ret; - assume_graph_lock(); /* FIXME */ - /* TODO: upgrade to async loop using AioTask */ while (bytes) { int64_t cur_bytes; @@ -290,7 +288,7 @@ cbw_co_preadv_snapshot(BlockDriverState *bs, int64_t offset, int64_t bytes, return 0; } -static int coroutine_fn +static int coroutine_fn GRAPH_RDLOCK cbw_co_snapshot_block_status(BlockDriverState *bs, bool want_zero, int64_t offset, int64_t bytes, int64_t *pnum, int64_t *map, diff --git a/block/io.c b/block/io.c index 86e5ea362d..d9c1594960 100644 --- a/block/io.c +++ b/block/io.c @@ -3532,6 +3532,7 @@ bdrv_co_preadv_snapshot(BdrvChild *child, int64_t offset, int64_t bytes, BlockDriver *drv = bs->drv; int ret; IO_CODE(); + assert_bdrv_graph_readable(); if (!drv) { return -ENOMEDIUM; @@ -3557,6 +3558,7 @@ bdrv_co_snapshot_block_status(BlockDriverState *bs, BlockDriver *drv = bs->drv; int ret; IO_CODE(); + assert_bdrv_graph_readable(); if (!drv) { return -ENOMEDIUM; diff --git a/block/snapshot-access.c b/block/snapshot-access.c index 009cc4aea0..67ea339da9 100644 --- a/block/snapshot-access.c +++ b/block/snapshot-access.c @@ -26,7 +26,7 @@ #include "qemu/cutils.h" #include "block/block_int.h" -static coroutine_fn int +static int coroutine_fn GRAPH_RDLOCK snapshot_access_co_preadv_part(BlockDriverState *bs, int64_t offset, int64_t bytes, QEMUIOVector *qiov, size_t qiov_offset, @@ -39,7 +39,7 @@ snapshot_access_co_preadv_part(BlockDriverState *bs, return bdrv_co_preadv_snapshot(bs->file, offset, bytes, qiov, qiov_offset); } -static int coroutine_fn +static int coroutine_fn GRAPH_RDLOCK snapshot_access_co_block_status(BlockDriverState *bs, bool want_zero, int64_t offset, int64_t bytes, int64_t *pnum, diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h index 29b230cc0b..7d8309ba5a 100644 --- a/include/block/block_int-common.h +++ b/include/block/block_int-common.h @@ -624,11 +624,13 @@ struct BlockDriver { * - receive the snapshot's actual length (which may differ from bs's * length) */ - int coroutine_fn (*bdrv_co_preadv_snapshot)(BlockDriverState *bs, - int64_t offset, int64_t bytes, QEMUIOVector *qiov, size_t qiov_offset); - int coroutine_fn (*bdrv_co_snapshot_block_status)(BlockDriverState *bs, - bool want_zero, int64_t offset, int64_t bytes, int64_t *pnum, - int64_t *map, BlockDriverState **file); + int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_preadv_snapshot)( + BlockDriverState *bs, int64_t offset, int64_t bytes, + QEMUIOVector *qiov, size_t qiov_offset); + + int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_snapshot_block_status)( + BlockDriverState *bs, bool want_zero, int64_t offset, int64_t bytes, + int64_t *pnum, int64_t *map, BlockDriverState **file); int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_pdiscard_snapshot)( BlockDriverState *bs, int64_t offset, int64_t bytes); diff --git a/include/block/block_int-io.h b/include/block/block_int-io.h index 5788bd66ba..612e5ddf99 100644 --- a/include/block/block_int-io.h +++ b/include/block/block_int-io.h @@ -35,11 +35,11 @@ * the I/O API. */ -int coroutine_fn bdrv_co_preadv_snapshot(BdrvChild *child, +int coroutine_fn GRAPH_RDLOCK bdrv_co_preadv_snapshot(BdrvChild *child, int64_t offset, int64_t bytes, QEMUIOVector *qiov, size_t qiov_offset); -int coroutine_fn bdrv_co_snapshot_block_status(BlockDriverState *bs, - bool want_zero, int64_t offset, int64_t bytes, int64_t *pnum, - int64_t *map, BlockDriverState **file); +int coroutine_fn GRAPH_RDLOCK bdrv_co_snapshot_block_status( + BlockDriverState *bs, bool want_zero, int64_t offset, int64_t bytes, + int64_t *pnum, int64_t *map, BlockDriverState **file); int coroutine_fn GRAPH_RDLOCK bdrv_co_pdiscard_snapshot(BlockDriverState *bs, int64_t offset, int64_t bytes); From 4ec8df0183d0906ae6704d65ef6d8082c970ecdf Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Fri, 3 Feb 2023 16:21:55 +0100 Subject: [PATCH 053/129] block: Mark bdrv_co_create() and callers GRAPH_RDLOCK This adds GRAPH_RDLOCK annotations to declare that callers of bdrv_co_create() need to hold a reader lock for the graph. Signed-off-by: Emanuele Giuseppe Esposito Signed-off-by: Kevin Wolf Message-Id: <20230203152202.49054-17-kwolf@redhat.com> Reviewed-by: Emanuele Giuseppe Esposito Signed-off-by: Kevin Wolf --- block.c | 1 + block/create.c | 9 ++++- block/crypto.c | 7 ++-- block/file-posix.c | 7 ++-- block/file-win32.c | 7 ++-- block/parallels.c | 7 ++-- block/qcow.c | 6 +-- block/qcow2.c | 7 ++-- block/qed.c | 7 ++-- block/raw-format.c | 7 ++-- block/vdi.c | 7 ++-- block/vhdx.c | 7 ++-- block/vmdk.c | 63 ++++++++++++++---------------- block/vpc.c | 7 ++-- include/block/block-global-state.h | 14 ++++--- include/block/block_int-common.h | 11 +++--- 16 files changed, 84 insertions(+), 90 deletions(-) diff --git a/block.c b/block.c index 31f13092cb..484f48ae2d 100644 --- a/block.c +++ b/block.c @@ -533,6 +533,7 @@ int coroutine_fn bdrv_co_create(BlockDriver *drv, const char *filename, int ret; GLOBAL_STATE_CODE(); ERRP_GUARD(); + assert_bdrv_graph_readable(); if (!drv->bdrv_co_create_opts) { error_setg(errp, "Driver '%s' does not support image creation", diff --git a/block/create.c b/block/create.c index 4df43f11f4..bf67b9947c 100644 --- a/block/create.c +++ b/block/create.c @@ -43,6 +43,7 @@ static int coroutine_fn blockdev_create_run(Job *job, Error **errp) int ret; GLOBAL_STATE_CODE(); + GRAPH_RDLOCK_GUARD(); job_progress_set_remaining(&s->common, 1); ret = s->drv->bdrv_co_create(s->opts, errp); @@ -59,6 +60,12 @@ static const JobDriver blockdev_create_job_driver = { .run = blockdev_create_run, }; +/* Checking whether the function is present doesn't require the graph lock */ +static inline bool TSA_NO_TSA has_bdrv_co_create(BlockDriver *drv) +{ + return drv->bdrv_co_create; +} + void qmp_blockdev_create(const char *job_id, BlockdevCreateOptions *options, Error **errp) { @@ -79,7 +86,7 @@ void qmp_blockdev_create(const char *job_id, BlockdevCreateOptions *options, } /* Error out if the driver doesn't support .bdrv_co_create */ - if (!drv->bdrv_co_create) { + if (!has_bdrv_co_create(drv)) { error_setg(errp, "Driver does not support blockdev-create"); return; } diff --git a/block/crypto.c b/block/crypto.c index 0ebb846534..e77790ac8a 100644 --- a/block/crypto.c +++ b/block/crypto.c @@ -664,10 +664,9 @@ fail: return ret; } -static int coroutine_fn block_crypto_co_create_opts_luks(BlockDriver *drv, - const char *filename, - QemuOpts *opts, - Error **errp) +static int coroutine_fn GRAPH_RDLOCK +block_crypto_co_create_opts_luks(BlockDriver *drv, const char *filename, + QemuOpts *opts, Error **errp) { QCryptoBlockCreateOptions *create_opts = NULL; BlockDriverState *bs = NULL; diff --git a/block/file-posix.c b/block/file-posix.c index 13da095efa..5760cf22d1 100644 --- a/block/file-posix.c +++ b/block/file-posix.c @@ -2607,10 +2607,9 @@ out: return result; } -static int coroutine_fn raw_co_create_opts(BlockDriver *drv, - const char *filename, - QemuOpts *opts, - Error **errp) +static int coroutine_fn GRAPH_RDLOCK +raw_co_create_opts(BlockDriver *drv, const char *filename, + QemuOpts *opts, Error **errp) { BlockdevCreateOptions options; int64_t total_size = 0; diff --git a/block/file-win32.c b/block/file-win32.c index 200d244116..c7d0b85306 100644 --- a/block/file-win32.c +++ b/block/file-win32.c @@ -613,10 +613,9 @@ static int raw_co_create(BlockdevCreateOptions *options, Error **errp) return 0; } -static int coroutine_fn raw_co_create_opts(BlockDriver *drv, - const char *filename, - QemuOpts *opts, - Error **errp) +static int coroutine_fn GRAPH_RDLOCK +raw_co_create_opts(BlockDriver *drv, const char *filename, + QemuOpts *opts, Error **errp) { BlockdevCreateOptions options; int64_t total_size = 0; diff --git a/block/parallels.c b/block/parallels.c index a7e9cad146..013684801a 100644 --- a/block/parallels.c +++ b/block/parallels.c @@ -622,10 +622,9 @@ exit: goto out; } -static int coroutine_fn parallels_co_create_opts(BlockDriver *drv, - const char *filename, - QemuOpts *opts, - Error **errp) +static int coroutine_fn GRAPH_RDLOCK +parallels_co_create_opts(BlockDriver *drv, const char *filename, + QemuOpts *opts, Error **errp) { BlockdevCreateOptions *create_options = NULL; BlockDriverState *bs = NULL; diff --git a/block/qcow.c b/block/qcow.c index 58a0b4e2f0..490e4f819e 100644 --- a/block/qcow.c +++ b/block/qcow.c @@ -921,9 +921,9 @@ exit: return ret; } -static int coroutine_fn qcow_co_create_opts(BlockDriver *drv, - const char *filename, - QemuOpts *opts, Error **errp) +static int coroutine_fn GRAPH_RDLOCK +qcow_co_create_opts(BlockDriver *drv, const char *filename, + QemuOpts *opts, Error **errp) { BlockdevCreateOptions *create_options = NULL; BlockDriverState *bs = NULL; diff --git a/block/qcow2.c b/block/qcow2.c index c318f41f38..30fd53fa64 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -3816,10 +3816,9 @@ out: return ret; } -static int coroutine_fn qcow2_co_create_opts(BlockDriver *drv, - const char *filename, - QemuOpts *opts, - Error **errp) +static int coroutine_fn GRAPH_RDLOCK +qcow2_co_create_opts(BlockDriver *drv, const char *filename, QemuOpts *opts, + Error **errp) { BlockdevCreateOptions *create_options = NULL; QDict *qdict; diff --git a/block/qed.c b/block/qed.c index c969b31e2c..ed94bb61ca 100644 --- a/block/qed.c +++ b/block/qed.c @@ -754,10 +754,9 @@ out: return ret; } -static int coroutine_fn bdrv_qed_co_create_opts(BlockDriver *drv, - const char *filename, - QemuOpts *opts, - Error **errp) +static int coroutine_fn GRAPH_RDLOCK +bdrv_qed_co_create_opts(BlockDriver *drv, const char *filename, + QemuOpts *opts, Error **errp) { BlockdevCreateOptions *create_options = NULL; QDict *qdict; diff --git a/block/raw-format.c b/block/raw-format.c index 9913cb8174..646606e223 100644 --- a/block/raw-format.c +++ b/block/raw-format.c @@ -430,10 +430,9 @@ static int raw_has_zero_init(BlockDriverState *bs) return bdrv_has_zero_init(bs->file->bs); } -static int coroutine_fn raw_co_create_opts(BlockDriver *drv, - const char *filename, - QemuOpts *opts, - Error **errp) +static int coroutine_fn GRAPH_RDLOCK +raw_co_create_opts(BlockDriver *drv, const char *filename, + QemuOpts *opts, Error **errp) { return bdrv_co_create_file(filename, opts, errp); } diff --git a/block/vdi.c b/block/vdi.c index b50c0b7277..f2434d6153 100644 --- a/block/vdi.c +++ b/block/vdi.c @@ -898,10 +898,9 @@ static int coroutine_fn vdi_co_create(BlockdevCreateOptions *create_options, return vdi_co_do_create(create_options, DEFAULT_CLUSTER_SIZE, errp); } -static int coroutine_fn vdi_co_create_opts(BlockDriver *drv, - const char *filename, - QemuOpts *opts, - Error **errp) +static int coroutine_fn GRAPH_RDLOCK +vdi_co_create_opts(BlockDriver *drv, const char *filename, + QemuOpts *opts, Error **errp) { QDict *qdict = NULL; BlockdevCreateOptions *create_options = NULL; diff --git a/block/vhdx.c b/block/vhdx.c index ffa4455e82..81420722a1 100644 --- a/block/vhdx.c +++ b/block/vhdx.c @@ -2059,10 +2059,9 @@ delete_and_exit: return ret; } -static int coroutine_fn vhdx_co_create_opts(BlockDriver *drv, - const char *filename, - QemuOpts *opts, - Error **errp) +static int coroutine_fn GRAPH_RDLOCK +vhdx_co_create_opts(BlockDriver *drv, const char *filename, + QemuOpts *opts, Error **errp) { BlockdevCreateOptions *create_options = NULL; QDict *qdict; diff --git a/block/vmdk.c b/block/vmdk.c index c601ca85f4..f5f49018fe 100644 --- a/block/vmdk.c +++ b/block/vmdk.c @@ -2277,11 +2277,10 @@ exit: return ret; } -static int coroutine_fn vmdk_create_extent(const char *filename, - int64_t filesize, bool flat, - bool compress, bool zeroed_grain, - BlockBackend **pbb, - QemuOpts *opts, Error **errp) +static int coroutine_fn GRAPH_RDLOCK +vmdk_create_extent(const char *filename, int64_t filesize, bool flat, + bool compress, bool zeroed_grain, BlockBackend **pbb, + QemuOpts *opts, Error **errp) { int ret; BlockBackend *blk = NULL; @@ -2359,14 +2358,10 @@ static int filename_decompose(const char *filename, char *path, char *prefix, * non-split format. * idx >= 1: get the n-th extent if in a split subformat */ -typedef BlockBackend * coroutine_fn (*vmdk_create_extent_fn)(int64_t size, - int idx, - bool flat, - bool split, - bool compress, - bool zeroed_grain, - void *opaque, - Error **errp); +typedef BlockBackend * coroutine_fn /* GRAPH_RDLOCK */ + (*vmdk_create_extent_fn)(int64_t size, int idx, bool flat, bool split, + bool compress, bool zeroed_grain, void *opaque, + Error **errp); static void vmdk_desc_add_extent(GString *desc, const char *extent_line_fmt, @@ -2379,17 +2374,18 @@ static void vmdk_desc_add_extent(GString *desc, g_free(basename); } -static int coroutine_fn vmdk_co_do_create(int64_t size, - BlockdevVmdkSubformat subformat, - BlockdevVmdkAdapterType adapter_type, - const char *backing_file, - const char *hw_version, - const char *toolsversion, - bool compat6, - bool zeroed_grain, - vmdk_create_extent_fn extent_fn, - void *opaque, - Error **errp) +static int coroutine_fn GRAPH_RDLOCK +vmdk_co_do_create(int64_t size, + BlockdevVmdkSubformat subformat, + BlockdevVmdkAdapterType adapter_type, + const char *backing_file, + const char *hw_version, + const char *toolsversion, + bool compat6, + bool zeroed_grain, + vmdk_create_extent_fn extent_fn, + void *opaque, + Error **errp) { int extent_idx; BlockBackend *blk = NULL; @@ -2609,10 +2605,10 @@ typedef struct { QemuOpts *opts; } VMDKCreateOptsData; -static BlockBackend * coroutine_fn vmdk_co_create_opts_cb(int64_t size, int idx, - bool flat, bool split, bool compress, - bool zeroed_grain, void *opaque, - Error **errp) +static BlockBackend * coroutine_fn GRAPH_RDLOCK +vmdk_co_create_opts_cb(int64_t size, int idx, bool flat, bool split, + bool compress, bool zeroed_grain, void *opaque, + Error **errp) { BlockBackend *blk = NULL; BlockDriverState *bs = NULL; @@ -2651,10 +2647,9 @@ exit: return blk; } -static int coroutine_fn vmdk_co_create_opts(BlockDriver *drv, - const char *filename, - QemuOpts *opts, - Error **errp) +static int coroutine_fn GRAPH_RDLOCK +vmdk_co_create_opts(BlockDriver *drv, const char *filename, + QemuOpts *opts, Error **errp) { Error *local_err = NULL; char *desc = NULL; @@ -2814,8 +2809,8 @@ static BlockBackend * coroutine_fn vmdk_co_create_cb(int64_t size, int idx, return blk; } -static int coroutine_fn vmdk_co_create(BlockdevCreateOptions *create_options, - Error **errp) +static int coroutine_fn GRAPH_RDLOCK +vmdk_co_create(BlockdevCreateOptions *create_options, Error **errp) { BlockdevCreateOptionsVmdk *opts; diff --git a/block/vpc.c b/block/vpc.c index 1f0f26c0c4..b89b0ff8e2 100644 --- a/block/vpc.c +++ b/block/vpc.c @@ -1087,10 +1087,9 @@ out: return ret; } -static int coroutine_fn vpc_co_create_opts(BlockDriver *drv, - const char *filename, - QemuOpts *opts, - Error **errp) +static int coroutine_fn GRAPH_RDLOCK +vpc_co_create_opts(BlockDriver *drv, const char *filename, + QemuOpts *opts, Error **errp) { BlockdevCreateOptions *create_options = NULL; QDict *qdict; diff --git a/include/block/block-global-state.h b/include/block/block-global-state.h index 447176414e..399200a9a3 100644 --- a/include/block/block-global-state.h +++ b/include/block/block-global-state.h @@ -58,13 +58,15 @@ BlockDriver *bdrv_find_protocol(const char *filename, Error **errp); BlockDriver *bdrv_find_format(const char *format_name); -int coroutine_fn bdrv_co_create(BlockDriver *drv, const char *filename, - QemuOpts *opts, Error **errp); -int co_wrapper bdrv_create(BlockDriver *drv, const char *filename, - QemuOpts *opts, Error **errp); +int coroutine_fn GRAPH_RDLOCK +bdrv_co_create(BlockDriver *drv, const char *filename, QemuOpts *opts, + Error **errp); -int coroutine_fn bdrv_co_create_file(const char *filename, QemuOpts *opts, - Error **errp); +int co_wrapper_bdrv_rdlock bdrv_create(BlockDriver *drv, const char *filename, + QemuOpts *opts, Error **errp); + +int coroutine_fn GRAPH_RDLOCK +bdrv_co_create_file(const char *filename, QemuOpts *opts, Error **errp); BlockDriverState *bdrv_new(void); int bdrv_append(BlockDriverState *bs_new, BlockDriverState *bs_top, diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h index 7d8309ba5a..6b8fd22c71 100644 --- a/include/block/block_int-common.h +++ b/include/block/block_int-common.h @@ -246,12 +246,11 @@ struct BlockDriver { Error **errp); void (*bdrv_close)(BlockDriverState *bs); - int coroutine_fn (*bdrv_co_create)(BlockdevCreateOptions *opts, - Error **errp); - int coroutine_fn (*bdrv_co_create_opts)(BlockDriver *drv, - const char *filename, - QemuOpts *opts, - Error **errp); + int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_create)( + BlockdevCreateOptions *opts, Error **errp); + + int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_create_opts)( + BlockDriver *drv, const char *filename, QemuOpts *opts, Error **errp); int (*bdrv_amend_options)(BlockDriverState *bs, QemuOpts *opts, From c38270692593602c4f57449c802c6cbfc16c6108 Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Fri, 3 Feb 2023 16:21:56 +0100 Subject: [PATCH 054/129] block: Mark bdrv_co_io_(un)plug() and callers GRAPH_RDLOCK This adds GRAPH_RDLOCK annotations to declare that callers of bdrv_co_io_plug() and bdrv_co_io_unplug() need to hold a reader lock for the graph. Signed-off-by: Kevin Wolf Message-Id: <20230203152202.49054-18-kwolf@redhat.com> Reviewed-by: Emanuele Giuseppe Esposito Signed-off-by: Kevin Wolf --- block/block-backend.c | 2 ++ block/io.c | 2 ++ include/block/block-io.h | 4 ++-- include/block/block_int-common.h | 5 +++-- 4 files changed, 9 insertions(+), 4 deletions(-) diff --git a/block/block-backend.c b/block/block-backend.c index fdb1e1d5f7..3661a066b3 100644 --- a/block/block-backend.c +++ b/block/block-backend.c @@ -2328,6 +2328,7 @@ void coroutine_fn blk_co_io_plug(BlockBackend *blk) { BlockDriverState *bs = blk_bs(blk); IO_CODE(); + GRAPH_RDLOCK_GUARD(); if (bs) { bdrv_co_io_plug(bs); @@ -2338,6 +2339,7 @@ void coroutine_fn blk_co_io_unplug(BlockBackend *blk) { BlockDriverState *bs = blk_bs(blk); IO_CODE(); + GRAPH_RDLOCK_GUARD(); if (bs) { bdrv_co_io_unplug(bs); diff --git a/block/io.c b/block/io.c index d9c1594960..b5459c2f41 100644 --- a/block/io.c +++ b/block/io.c @@ -3153,6 +3153,7 @@ void coroutine_fn bdrv_co_io_plug(BlockDriverState *bs) { BdrvChild *child; IO_CODE(); + assert_bdrv_graph_readable(); QLIST_FOREACH(child, &bs->children, next) { bdrv_co_io_plug(child->bs); @@ -3170,6 +3171,7 @@ void coroutine_fn bdrv_co_io_unplug(BlockDriverState *bs) { BdrvChild *child; IO_CODE(); + assert_bdrv_graph_readable(); assert(bs->io_plugged); if (qatomic_fetch_dec(&bs->io_plugged) == 1) { diff --git a/include/block/block-io.h b/include/block/block-io.h index c551742a86..b8f99741a3 100644 --- a/include/block/block-io.h +++ b/include/block/block-io.h @@ -233,8 +233,8 @@ void coroutine_fn bdrv_co_leave(BlockDriverState *bs, AioContext *old_ctx); AioContext *child_of_bds_get_parent_aio_context(BdrvChild *c); -void coroutine_fn bdrv_co_io_plug(BlockDriverState *bs); -void coroutine_fn bdrv_co_io_unplug(BlockDriverState *bs); +void coroutine_fn GRAPH_RDLOCK bdrv_co_io_plug(BlockDriverState *bs); +void coroutine_fn GRAPH_RDLOCK bdrv_co_io_unplug(BlockDriverState *bs); bool coroutine_fn bdrv_co_can_store_new_dirty_bitmap(BlockDriverState *bs, const char *name, diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h index 6b8fd22c71..61f894bcf6 100644 --- a/include/block/block_int-common.h +++ b/include/block/block_int-common.h @@ -735,8 +735,9 @@ struct BlockDriver { BlkdebugEvent event); /* io queue for linux-aio */ - void coroutine_fn (*bdrv_co_io_plug)(BlockDriverState *bs); - void coroutine_fn (*bdrv_co_io_unplug)(BlockDriverState *bs); + void coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_io_plug)(BlockDriverState *bs); + void coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_io_unplug)( + BlockDriverState *bs); /** * bdrv_drain_begin is called if implemented in the beginning of a From c73ff92c9d00f9aa535044e7348d0330aa94f467 Mon Sep 17 00:00:00 2001 From: Emanuele Giuseppe Esposito Date: Fri, 3 Feb 2023 16:21:57 +0100 Subject: [PATCH 055/129] block: Mark bdrv_co_is_inserted() and callers GRAPH_RDLOCK This adds GRAPH_RDLOCK annotations to declare that callers of bdrv_co_is_inserted() need to hold a reader lock for the graph. blk_is_inserted() is done as a co_wrapper_mixed_bdrv_rdlock (unlike most other blk_* functions) because it is called a lot from other blk_co_*() functions that already hold the lock. These calls go through blk_is_available(), which becomes a co_wrapper_mixed_bdrv_rdlock, too, for the same reason. Functions that run in a coroutine and can call bdrv_co_is_available() directly are changed to do so, which results in better TSA coverage. Signed-off-by: Emanuele Giuseppe Esposito Signed-off-by: Kevin Wolf Message-Id: <20230203152202.49054-19-kwolf@redhat.com> Reviewed-by: Emanuele Giuseppe Esposito Signed-off-by: Kevin Wolf --- block.c | 1 + block/block-backend.c | 25 ++++++++++++++----------- include/block/block-io.h | 4 ++-- include/block/block_int-common.h | 3 ++- include/sysemu/block-backend-io.h | 7 ++++--- 5 files changed, 23 insertions(+), 17 deletions(-) diff --git a/block.c b/block.c index 484f48ae2d..738b42046c 100644 --- a/block.c +++ b/block.c @@ -6826,6 +6826,7 @@ bool coroutine_fn bdrv_co_is_inserted(BlockDriverState *bs) BlockDriver *drv = bs->drv; BdrvChild *child; IO_CODE(); + assert_bdrv_graph_readable(); if (!drv) { return false; diff --git a/block/block-backend.c b/block/block-backend.c index 3661a066b3..20af699f00 100644 --- a/block/block-backend.c +++ b/block/block-backend.c @@ -1235,8 +1235,8 @@ void blk_set_disable_request_queuing(BlockBackend *blk, bool disable) blk->disable_request_queuing = disable; } -static coroutine_fn int blk_check_byte_request(BlockBackend *blk, - int64_t offset, int64_t bytes) +static int coroutine_fn GRAPH_RDLOCK +blk_check_byte_request(BlockBackend *blk, int64_t offset, int64_t bytes) { int64_t len; @@ -1244,7 +1244,7 @@ static coroutine_fn int blk_check_byte_request(BlockBackend *blk, return -EIO; } - if (!blk_is_available(blk)) { + if (!blk_co_is_available(blk)) { return -ENOMEDIUM; } @@ -1606,8 +1606,9 @@ BlockAIOCB *blk_aio_pwrite_zeroes(BlockBackend *blk, int64_t offset, int64_t coroutine_fn blk_co_getlength(BlockBackend *blk) { IO_CODE(); + GRAPH_RDLOCK_GUARD(); - if (!blk_is_available(blk)) { + if (!blk_co_is_available(blk)) { return -ENOMEDIUM; } @@ -1627,8 +1628,9 @@ void blk_get_geometry(BlockBackend *blk, uint64_t *nb_sectors_ptr) int64_t coroutine_fn blk_co_nb_sectors(BlockBackend *blk) { IO_CODE(); + GRAPH_RDLOCK_GUARD(); - if (!blk_is_available(blk)) { + if (!blk_co_is_available(blk)) { return -ENOMEDIUM; } @@ -1676,7 +1678,7 @@ blk_co_do_ioctl(BlockBackend *blk, unsigned long int req, void *buf) blk_wait_while_drained(blk); GRAPH_RDLOCK_GUARD(); - if (!blk_is_available(blk)) { + if (!blk_co_is_available(blk)) { return -ENOMEDIUM; } @@ -1769,7 +1771,7 @@ static int coroutine_fn blk_co_do_flush(BlockBackend *blk) blk_wait_while_drained(blk); GRAPH_RDLOCK_GUARD(); - if (!blk_is_available(blk)) { + if (!blk_co_is_available(blk)) { return -ENOMEDIUM; } @@ -1996,14 +1998,15 @@ bool coroutine_fn blk_co_is_inserted(BlockBackend *blk) { BlockDriverState *bs = blk_bs(blk); IO_CODE(); + assert_bdrv_graph_readable(); return bs && bdrv_co_is_inserted(bs); } -bool blk_is_available(BlockBackend *blk) +bool coroutine_fn blk_co_is_available(BlockBackend *blk) { IO_CODE(); - return blk_is_inserted(blk) && !blk_dev_is_tray_open(blk); + return blk_co_is_inserted(blk) && !blk_dev_is_tray_open(blk); } void coroutine_fn blk_co_lock_medium(BlockBackend *blk, bool locked) @@ -2382,7 +2385,7 @@ int coroutine_fn blk_co_truncate(BlockBackend *blk, int64_t offset, bool exact, { IO_OR_GS_CODE(); GRAPH_RDLOCK_GUARD(); - if (!blk_is_available(blk)) { + if (!blk_co_is_available(blk)) { error_setg(errp, "No medium inserted"); return -ENOMEDIUM; } @@ -2637,6 +2640,7 @@ int coroutine_fn blk_co_copy_range(BlockBackend *blk_in, int64_t off_in, { int r; IO_CODE(); + GRAPH_RDLOCK_GUARD(); r = blk_check_byte_request(blk_in, off_in, bytes); if (r) { @@ -2647,7 +2651,6 @@ int coroutine_fn blk_co_copy_range(BlockBackend *blk_in, int64_t off_in, return r; } - GRAPH_RDLOCK_GUARD(); return bdrv_co_copy_range(blk_in->root, off_in, blk_out->root, off_out, bytes, read_flags, write_flags); diff --git a/include/block/block-io.h b/include/block/block-io.h index b8f99741a3..88db63492a 100644 --- a/include/block/block-io.h +++ b/include/block/block-io.h @@ -145,8 +145,8 @@ bool bdrv_is_writable(BlockDriverState *bs); bool bdrv_is_sg(BlockDriverState *bs); int bdrv_get_flags(BlockDriverState *bs); -bool coroutine_fn bdrv_co_is_inserted(BlockDriverState *bs); -bool co_wrapper bdrv_is_inserted(BlockDriverState *bs); +bool coroutine_fn GRAPH_RDLOCK bdrv_co_is_inserted(BlockDriverState *bs); +bool co_wrapper_bdrv_rdlock bdrv_is_inserted(BlockDriverState *bs); void coroutine_fn bdrv_co_lock_medium(BlockDriverState *bs, bool locked); void coroutine_fn bdrv_co_eject(BlockDriverState *bs, bool eject_flag); diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h index 61f894bcf6..b4a82269e5 100644 --- a/include/block/block_int-common.h +++ b/include/block/block_int-common.h @@ -712,7 +712,8 @@ struct BlockDriver { BlockDriverState *bs, QEMUIOVector *qiov, int64_t pos); /* removable device specific */ - bool coroutine_fn (*bdrv_co_is_inserted)(BlockDriverState *bs); + bool coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_is_inserted)( + BlockDriverState *bs); void coroutine_fn (*bdrv_co_eject)(BlockDriverState *bs, bool eject_flag); void coroutine_fn (*bdrv_co_lock_medium)(BlockDriverState *bs, bool locked); diff --git a/include/sysemu/block-backend-io.h b/include/sysemu/block-backend-io.h index b1196ab93c..40ab178719 100644 --- a/include/sysemu/block-backend-io.h +++ b/include/sysemu/block-backend-io.h @@ -55,10 +55,11 @@ BlockAIOCB *blk_aio_ioctl(BlockBackend *blk, unsigned long int req, void *buf, void blk_inc_in_flight(BlockBackend *blk); void blk_dec_in_flight(BlockBackend *blk); -bool coroutine_fn blk_co_is_inserted(BlockBackend *blk); -bool co_wrapper_mixed blk_is_inserted(BlockBackend *blk); +bool coroutine_fn GRAPH_RDLOCK blk_co_is_inserted(BlockBackend *blk); +bool co_wrapper_mixed_bdrv_rdlock blk_is_inserted(BlockBackend *blk); -bool blk_is_available(BlockBackend *blk); +bool coroutine_fn GRAPH_RDLOCK blk_co_is_available(BlockBackend *blk); +bool co_wrapper_mixed_bdrv_rdlock blk_is_available(BlockBackend *blk); void coroutine_fn blk_co_lock_medium(BlockBackend *blk, bool locked); void co_wrapper blk_lock_medium(BlockBackend *blk, bool locked); From 79a292e5ec767eea27a0cc456570ee028f4e3972 Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Fri, 3 Feb 2023 16:21:58 +0100 Subject: [PATCH 056/129] block: Mark bdrv_co_eject/lock_medium() and callers GRAPH_RDLOCK This adds GRAPH_RDLOCK annotations to declare that callers of bdrv_co_eject() and bdrv_co_lock_medium() need to hold a reader lock for the graph. Signed-off-by: Emanuele Giuseppe Esposito Signed-off-by: Kevin Wolf Message-Id: <20230203152202.49054-20-kwolf@redhat.com> Reviewed-by: Emanuele Giuseppe Esposito Signed-off-by: Kevin Wolf --- block.c | 2 ++ block/block-backend.c | 2 ++ block/copy-on-read.c | 6 ++++-- block/filter-compress.c | 4 ++-- block/raw-format.c | 6 ++++-- include/block/block-io.h | 7 +++++-- include/block/block_int-common.h | 6 ++++-- 7 files changed, 23 insertions(+), 10 deletions(-) diff --git a/block.c b/block.c index 738b42046c..1060194e8f 100644 --- a/block.c +++ b/block.c @@ -6849,6 +6849,7 @@ void coroutine_fn bdrv_co_eject(BlockDriverState *bs, bool eject_flag) { BlockDriver *drv = bs->drv; IO_CODE(); + assert_bdrv_graph_readable(); if (drv && drv->bdrv_co_eject) { drv->bdrv_co_eject(bs, eject_flag); @@ -6863,6 +6864,7 @@ void coroutine_fn bdrv_co_lock_medium(BlockDriverState *bs, bool locked) { BlockDriver *drv = bs->drv; IO_CODE(); + assert_bdrv_graph_readable(); trace_bdrv_lock_medium(bs, locked); if (drv && drv->bdrv_co_lock_medium) { diff --git a/block/block-backend.c b/block/block-backend.c index 20af699f00..278b04ce69 100644 --- a/block/block-backend.c +++ b/block/block-backend.c @@ -2013,6 +2013,7 @@ void coroutine_fn blk_co_lock_medium(BlockBackend *blk, bool locked) { BlockDriverState *bs = blk_bs(blk); IO_CODE(); + GRAPH_RDLOCK_GUARD(); if (bs) { bdrv_co_lock_medium(bs, locked); @@ -2024,6 +2025,7 @@ void coroutine_fn blk_co_eject(BlockBackend *blk, bool eject_flag) BlockDriverState *bs = blk_bs(blk); char *id; IO_CODE(); + GRAPH_RDLOCK_GUARD(); if (bs) { bdrv_co_eject(bs, eject_flag); diff --git a/block/copy-on-read.c b/block/copy-on-read.c index 78da353f88..20215cff93 100644 --- a/block/copy-on-read.c +++ b/block/copy-on-read.c @@ -213,13 +213,15 @@ cor_co_pwritev_compressed(BlockDriverState *bs, int64_t offset, int64_t bytes, } -static void coroutine_fn cor_co_eject(BlockDriverState *bs, bool eject_flag) +static void coroutine_fn GRAPH_RDLOCK +cor_co_eject(BlockDriverState *bs, bool eject_flag) { bdrv_co_eject(bs->file->bs, eject_flag); } -static void coroutine_fn cor_co_lock_medium(BlockDriverState *bs, bool locked) +static void coroutine_fn GRAPH_RDLOCK +cor_co_lock_medium(BlockDriverState *bs, bool locked) { bdrv_co_lock_medium(bs->file->bs, locked); } diff --git a/block/filter-compress.c b/block/filter-compress.c index 0dd5606410..c7d50a67a7 100644 --- a/block/filter-compress.c +++ b/block/filter-compress.c @@ -114,14 +114,14 @@ static void compress_refresh_limits(BlockDriverState *bs, Error **errp) } -static void coroutine_fn +static void coroutine_fn GRAPH_RDLOCK compress_co_eject(BlockDriverState *bs, bool eject_flag) { bdrv_co_eject(bs->file->bs, eject_flag); } -static void coroutine_fn +static void coroutine_fn GRAPH_RDLOCK compress_co_lock_medium(BlockDriverState *bs, bool locked) { bdrv_co_lock_medium(bs->file->bs, locked); diff --git a/block/raw-format.c b/block/raw-format.c index 646606e223..f4203d4806 100644 --- a/block/raw-format.c +++ b/block/raw-format.c @@ -405,12 +405,14 @@ raw_co_truncate(BlockDriverState *bs, int64_t offset, bool exact, return bdrv_co_truncate(bs->file, offset, exact, prealloc, flags, errp); } -static void coroutine_fn raw_co_eject(BlockDriverState *bs, bool eject_flag) +static void coroutine_fn GRAPH_RDLOCK +raw_co_eject(BlockDriverState *bs, bool eject_flag) { bdrv_co_eject(bs->file->bs, eject_flag); } -static void coroutine_fn raw_co_lock_medium(BlockDriverState *bs, bool locked) +static void coroutine_fn GRAPH_RDLOCK +raw_co_lock_medium(BlockDriverState *bs, bool locked) { bdrv_co_lock_medium(bs->file->bs, locked); } diff --git a/include/block/block-io.h b/include/block/block-io.h index 88db63492a..bf2748011e 100644 --- a/include/block/block-io.h +++ b/include/block/block-io.h @@ -148,8 +148,11 @@ int bdrv_get_flags(BlockDriverState *bs); bool coroutine_fn GRAPH_RDLOCK bdrv_co_is_inserted(BlockDriverState *bs); bool co_wrapper_bdrv_rdlock bdrv_is_inserted(BlockDriverState *bs); -void coroutine_fn bdrv_co_lock_medium(BlockDriverState *bs, bool locked); -void coroutine_fn bdrv_co_eject(BlockDriverState *bs, bool eject_flag); +void coroutine_fn GRAPH_RDLOCK +bdrv_co_lock_medium(BlockDriverState *bs, bool locked); + +void coroutine_fn GRAPH_RDLOCK +bdrv_co_eject(BlockDriverState *bs, bool eject_flag); const char *bdrv_get_format_name(BlockDriverState *bs); diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h index b4a82269e5..30e6bd4909 100644 --- a/include/block/block_int-common.h +++ b/include/block/block_int-common.h @@ -714,8 +714,10 @@ struct BlockDriver { /* removable device specific */ bool coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_is_inserted)( BlockDriverState *bs); - void coroutine_fn (*bdrv_co_eject)(BlockDriverState *bs, bool eject_flag); - void coroutine_fn (*bdrv_co_lock_medium)(BlockDriverState *bs, bool locked); + void coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_eject)( + BlockDriverState *bs, bool eject_flag); + void coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_lock_medium)( + BlockDriverState *bs, bool locked); /* to control generic scsi devices */ BlockAIOCB *coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_aio_ioctl)( From d9249c253c28ef836641bea98180784fc2e9f655 Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Fri, 3 Feb 2023 16:21:59 +0100 Subject: [PATCH 057/129] block: Mark bdrv_(un)register_buf() GRAPH_RDLOCK This adds GRAPH_RDLOCK annotations to declare that callers of bdrv_register_buf() and bdrv_unregister_buf() need to hold a reader lock for the graph. Signed-off-by: Kevin Wolf Message-Id: <20230203152202.49054-21-kwolf@redhat.com> Reviewed-by: Emanuele Giuseppe Esposito Signed-off-by: Kevin Wolf --- block/io.c | 14 ++++++++++---- include/block/block_int-common.h | 7 ++++--- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/block/io.c b/block/io.c index b5459c2f41..8974d46941 100644 --- a/block/io.c +++ b/block/io.c @@ -3187,13 +3187,15 @@ void coroutine_fn bdrv_co_io_unplug(BlockDriverState *bs) } /* Helper that undoes bdrv_register_buf() when it fails partway through */ -static void bdrv_register_buf_rollback(BlockDriverState *bs, - void *host, - size_t size, - BdrvChild *final_child) +static void GRAPH_RDLOCK +bdrv_register_buf_rollback(BlockDriverState *bs, void *host, size_t size, + BdrvChild *final_child) { BdrvChild *child; + GLOBAL_STATE_CODE(); + assert_bdrv_graph_readable(); + QLIST_FOREACH(child, &bs->children, next) { if (child == final_child) { break; @@ -3213,6 +3215,8 @@ bool bdrv_register_buf(BlockDriverState *bs, void *host, size_t size, BdrvChild *child; GLOBAL_STATE_CODE(); + GRAPH_RDLOCK_GUARD_MAINLOOP(); + if (bs->drv && bs->drv->bdrv_register_buf) { if (!bs->drv->bdrv_register_buf(bs, host, size, errp)) { return false; @@ -3232,6 +3236,8 @@ void bdrv_unregister_buf(BlockDriverState *bs, void *host, size_t size) BdrvChild *child; GLOBAL_STATE_CODE(); + GRAPH_RDLOCK_GUARD_MAINLOOP(); + if (bs->drv && bs->drv->bdrv_unregister_buf) { bs->drv->bdrv_unregister_buf(bs, host, size); } diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h index 30e6bd4909..88d9897c97 100644 --- a/include/block/block_int-common.h +++ b/include/block/block_int-common.h @@ -445,9 +445,10 @@ struct BlockDriver { * * Returns: true on success, false on failure */ - bool (*bdrv_register_buf)(BlockDriverState *bs, void *host, size_t size, - Error **errp); - void (*bdrv_unregister_buf)(BlockDriverState *bs, void *host, size_t size); + bool GRAPH_RDLOCK_PTR (*bdrv_register_buf)( + BlockDriverState *bs, void *host, size_t size, Error **errp); + void GRAPH_RDLOCK_PTR (*bdrv_unregister_buf)( + BlockDriverState *bs, void *host, size_t size); /* * This field is modified only under the BQL, and is part of From 48aef7944090fdddd6a89e07b790798cf31b56a4 Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Fri, 3 Feb 2023 16:22:00 +0100 Subject: [PATCH 058/129] block: Mark bdrv_co_delete_file() and callers GRAPH_RDLOCK This adds GRAPH_RDLOCK annotations to declare that callers of bdrv_co_delete_file() need to hold a reader lock for the graph. Signed-off-by: Kevin Wolf Message-Id: <20230203152202.49054-22-kwolf@redhat.com> Reviewed-by: Emanuele Giuseppe Esposito Signed-off-by: Kevin Wolf --- block.c | 1 + include/block/block-io.h | 8 ++++++-- include/block/block_int-common.h | 4 ++-- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/block.c b/block.c index 1060194e8f..c4c67d09d4 100644 --- a/block.c +++ b/block.c @@ -740,6 +740,7 @@ int coroutine_fn bdrv_co_delete_file(BlockDriverState *bs, Error **errp) IO_CODE(); assert(bs != NULL); + assert_bdrv_graph_readable(); if (!bs->drv) { error_setg(errp, "Block node '%s' is not opened", bs->filename); diff --git a/include/block/block-io.h b/include/block/block-io.h index bf2748011e..a195a9fb11 100644 --- a/include/block/block-io.h +++ b/include/block/block-io.h @@ -90,8 +90,12 @@ int64_t co_wrapper bdrv_get_allocated_file_size(BlockDriverState *bs); BlockMeasureInfo *bdrv_measure(BlockDriver *drv, QemuOpts *opts, BlockDriverState *in_bs, Error **errp); void bdrv_get_geometry(BlockDriverState *bs, uint64_t *nb_sectors_ptr); -int coroutine_fn bdrv_co_delete_file(BlockDriverState *bs, Error **errp); -void coroutine_fn bdrv_co_delete_file_noerr(BlockDriverState *bs); + +int coroutine_fn GRAPH_RDLOCK +bdrv_co_delete_file(BlockDriverState *bs, Error **errp); + +void coroutine_fn GRAPH_RDLOCK +bdrv_co_delete_file_noerr(BlockDriverState *bs); /* async block I/O */ diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h index 88d9897c97..257a9d18c6 100644 --- a/include/block/block_int-common.h +++ b/include/block/block_int-common.h @@ -649,8 +649,8 @@ struct BlockDriver { int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_flush)(BlockDriverState *bs); /* Delete a created file. */ - int coroutine_fn (*bdrv_co_delete_file)(BlockDriverState *bs, - Error **errp); + int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_delete_file)( + BlockDriverState *bs, Error **errp); /* * Flushes all data that was already written to the OS all the way down to From 167f748d8c1300196ac55fe3eef5518bf7b1f949 Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Fri, 3 Feb 2023 16:22:01 +0100 Subject: [PATCH 059/129] block: Mark bdrv_*_dirty_bitmap() and callers GRAPH_RDLOCK This adds GRAPH_RDLOCK annotations to declare that callers of bdrv_*_dirty_bitmap() need to hold a reader lock for the graph. Signed-off-by: Kevin Wolf Message-Id: <20230203152202.49054-23-kwolf@redhat.com> Reviewed-by: Emanuele Giuseppe Esposito Signed-off-by: Kevin Wolf --- block/dirty-bitmap.c | 2 ++ include/block/block-io.h | 14 ++++++-------- include/block/block_int-common.h | 6 ++++-- include/block/dirty-bitmap.h | 12 ++++++------ 4 files changed, 18 insertions(+), 16 deletions(-) diff --git a/block/dirty-bitmap.c b/block/dirty-bitmap.c index 1e7aee4010..13a1979755 100644 --- a/block/dirty-bitmap.c +++ b/block/dirty-bitmap.c @@ -394,6 +394,7 @@ int coroutine_fn bdrv_co_remove_persistent_dirty_bitmap(BlockDriverState *bs, const char *name, Error **errp) { + assert_bdrv_graph_readable(); if (bs->drv && bs->drv->bdrv_co_remove_persistent_dirty_bitmap) { return bs->drv->bdrv_co_remove_persistent_dirty_bitmap(bs, name, errp); } @@ -415,6 +416,7 @@ bdrv_co_can_store_new_dirty_bitmap(BlockDriverState *bs, const char *name, uint32_t granularity, Error **errp) { BlockDriver *drv = bs->drv; + assert_bdrv_graph_readable(); if (!drv) { error_setg_errno(errp, ENOMEDIUM, diff --git a/include/block/block-io.h b/include/block/block-io.h index a195a9fb11..95bcc79b75 100644 --- a/include/block/block-io.h +++ b/include/block/block-io.h @@ -243,14 +243,12 @@ AioContext *child_of_bds_get_parent_aio_context(BdrvChild *c); void coroutine_fn GRAPH_RDLOCK bdrv_co_io_plug(BlockDriverState *bs); void coroutine_fn GRAPH_RDLOCK bdrv_co_io_unplug(BlockDriverState *bs); -bool coroutine_fn bdrv_co_can_store_new_dirty_bitmap(BlockDriverState *bs, - const char *name, - uint32_t granularity, - Error **errp); -bool co_wrapper bdrv_can_store_new_dirty_bitmap(BlockDriverState *bs, - const char *name, - uint32_t granularity, - Error **errp); +bool coroutine_fn GRAPH_RDLOCK +bdrv_co_can_store_new_dirty_bitmap(BlockDriverState *bs, const char *name, + uint32_t granularity, Error **errp); +bool co_wrapper_bdrv_rdlock +bdrv_can_store_new_dirty_bitmap(BlockDriverState *bs, const char *name, + uint32_t granularity, Error **errp); /** * diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h index 257a9d18c6..d72e31aba3 100644 --- a/include/block/block_int-common.h +++ b/include/block/block_int-common.h @@ -759,10 +759,12 @@ struct BlockDriver { void (*bdrv_drain_end)(BlockDriverState *bs); bool (*bdrv_supports_persistent_dirty_bitmap)(BlockDriverState *bs); - bool coroutine_fn (*bdrv_co_can_store_new_dirty_bitmap)( + + bool coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_can_store_new_dirty_bitmap)( BlockDriverState *bs, const char *name, uint32_t granularity, Error **errp); - int coroutine_fn (*bdrv_co_remove_persistent_dirty_bitmap)( + + int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_remove_persistent_dirty_bitmap)( BlockDriverState *bs, const char *name, Error **errp); }; diff --git a/include/block/dirty-bitmap.h b/include/block/dirty-bitmap.h index 233535ef2d..fa956debfb 100644 --- a/include/block/dirty-bitmap.h +++ b/include/block/dirty-bitmap.h @@ -36,12 +36,12 @@ int bdrv_dirty_bitmap_check(const BdrvDirtyBitmap *bitmap, uint32_t flags, void bdrv_release_dirty_bitmap(BdrvDirtyBitmap *bitmap); void bdrv_release_named_dirty_bitmaps(BlockDriverState *bs); -int coroutine_fn bdrv_co_remove_persistent_dirty_bitmap(BlockDriverState *bs, - const char *name, - Error **errp); -int co_wrapper bdrv_remove_persistent_dirty_bitmap(BlockDriverState *bs, - const char *name, - Error **errp); +int coroutine_fn GRAPH_RDLOCK +bdrv_co_remove_persistent_dirty_bitmap(BlockDriverState *bs, const char *name, + Error **errp); +int co_wrapper_bdrv_rdlock +bdrv_remove_persistent_dirty_bitmap(BlockDriverState *bs, const char *name, + Error **errp); void bdrv_disable_dirty_bitmap(BdrvDirtyBitmap *bitmap); void bdrv_enable_dirty_bitmap(BdrvDirtyBitmap *bitmap); From 8ab8140a04cf771d63e9754d6ba6c1e676bfe507 Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Fri, 3 Feb 2023 16:22:02 +0100 Subject: [PATCH 060/129] block: Mark bdrv_co_refresh_total_sectors() and callers GRAPH_RDLOCK This adds GRAPH_RDLOCK annotations to declare that callers of bdrv_co_refresh_total_sectors() need to hold a reader lock for the graph. Signed-off-by: Kevin Wolf Message-Id: <20230203152202.49054-24-kwolf@redhat.com> Reviewed-by: Emanuele Giuseppe Esposito Signed-off-by: Kevin Wolf --- block.c | 3 +++ block/blkdebug.c | 3 ++- block/blklogwrites.c | 3 ++- block/blkreplay.c | 3 ++- block/blkverify.c | 3 ++- block/copy-on-read.c | 2 +- block/crypto.c | 3 ++- block/filter-compress.c | 3 ++- block/mirror.c | 3 +++ block/preallocate.c | 3 ++- block/quorum.c | 3 ++- block/raw-format.c | 3 ++- block/replication.c | 3 ++- block/stream.c | 8 +++++--- block/throttle.c | 3 ++- include/block/block-io.h | 8 ++++---- include/block/block_int-common.h | 4 +++- include/block/block_int-io.h | 7 ++++--- 18 files changed, 45 insertions(+), 23 deletions(-) diff --git a/block.c b/block.c index c4c67d09d4..0dd604d0f6 100644 --- a/block.c +++ b/block.c @@ -1042,6 +1042,7 @@ int coroutine_fn bdrv_co_refresh_total_sectors(BlockDriverState *bs, { BlockDriver *drv = bs->drv; IO_CODE(); + assert_bdrv_graph_readable(); if (!drv) { return -ENOMEDIUM; @@ -5843,6 +5844,7 @@ int64_t coroutine_fn bdrv_co_nb_sectors(BlockDriverState *bs) { BlockDriver *drv = bs->drv; IO_CODE(); + assert_bdrv_graph_readable(); if (!drv) return -ENOMEDIUM; @@ -5864,6 +5866,7 @@ int64_t coroutine_fn bdrv_co_getlength(BlockDriverState *bs) { int64_t ret; IO_CODE(); + assert_bdrv_graph_readable(); ret = bdrv_co_nb_sectors(bs); if (ret < 0) { diff --git a/block/blkdebug.c b/block/blkdebug.c index f418a90873..978c8cff9e 100644 --- a/block/blkdebug.c +++ b/block/blkdebug.c @@ -967,7 +967,8 @@ static bool blkdebug_debug_is_suspended(BlockDriverState *bs, const char *tag) return false; } -static int64_t coroutine_fn blkdebug_co_getlength(BlockDriverState *bs) +static int64_t coroutine_fn GRAPH_RDLOCK +blkdebug_co_getlength(BlockDriverState *bs) { return bdrv_co_getlength(bs->file->bs); } diff --git a/block/blklogwrites.c b/block/blklogwrites.c index 93086c31e1..3ea7141cb5 100644 --- a/block/blklogwrites.c +++ b/block/blklogwrites.c @@ -267,7 +267,8 @@ static void blk_log_writes_close(BlockDriverState *bs) s->log_file = NULL; } -static int64_t coroutine_fn blk_log_writes_co_getlength(BlockDriverState *bs) +static int64_t coroutine_fn GRAPH_RDLOCK +blk_log_writes_co_getlength(BlockDriverState *bs) { return bdrv_co_getlength(bs->file->bs); } diff --git a/block/blkreplay.c b/block/blkreplay.c index bc96bbd41e..04f53eea41 100644 --- a/block/blkreplay.c +++ b/block/blkreplay.c @@ -40,7 +40,8 @@ fail: return ret; } -static int64_t coroutine_fn blkreplay_co_getlength(BlockDriverState *bs) +static int64_t coroutine_fn GRAPH_RDLOCK +blkreplay_co_getlength(BlockDriverState *bs) { return bdrv_co_getlength(bs->file->bs); } diff --git a/block/blkverify.c b/block/blkverify.c index 8c11c2eae4..1c16f86b2e 100644 --- a/block/blkverify.c +++ b/block/blkverify.c @@ -155,7 +155,8 @@ static void blkverify_close(BlockDriverState *bs) s->test_file = NULL; } -static int64_t coroutine_fn blkverify_co_getlength(BlockDriverState *bs) +static int64_t coroutine_fn GRAPH_RDLOCK +blkverify_co_getlength(BlockDriverState *bs) { BDRVBlkverifyState *s = bs->opaque; diff --git a/block/copy-on-read.c b/block/copy-on-read.c index 20215cff93..cc0f848b0f 100644 --- a/block/copy-on-read.c +++ b/block/copy-on-read.c @@ -121,7 +121,7 @@ static void cor_child_perm(BlockDriverState *bs, BdrvChild *c, } -static int64_t coroutine_fn cor_co_getlength(BlockDriverState *bs) +static int64_t coroutine_fn GRAPH_RDLOCK cor_co_getlength(BlockDriverState *bs) { return bdrv_co_getlength(bs->file->bs); } diff --git a/block/crypto.c b/block/crypto.c index e77790ac8a..ca67289187 100644 --- a/block/crypto.c +++ b/block/crypto.c @@ -530,7 +530,8 @@ static void block_crypto_refresh_limits(BlockDriverState *bs, Error **errp) } -static int64_t coroutine_fn block_crypto_co_getlength(BlockDriverState *bs) +static int64_t coroutine_fn GRAPH_RDLOCK +block_crypto_co_getlength(BlockDriverState *bs) { BlockCrypto *crypto = bs->opaque; int64_t len = bdrv_co_getlength(bs->file->bs); diff --git a/block/filter-compress.c b/block/filter-compress.c index c7d50a67a7..ac285f4b66 100644 --- a/block/filter-compress.c +++ b/block/filter-compress.c @@ -55,7 +55,8 @@ static int compress_open(BlockDriverState *bs, QDict *options, int flags, } -static int64_t coroutine_fn compress_co_getlength(BlockDriverState *bs) +static int64_t coroutine_fn GRAPH_RDLOCK +compress_co_getlength(BlockDriverState *bs) { return bdrv_co_getlength(bs->file->bs); } diff --git a/block/mirror.c b/block/mirror.c index ec5cd22a7c..97c6a5777d 100644 --- a/block/mirror.c +++ b/block/mirror.c @@ -917,7 +917,10 @@ static int coroutine_fn mirror_run(Job *job, Error **errp) goto immediate_exit; } + bdrv_graph_co_rdlock(); s->bdev_length = bdrv_co_getlength(bs); + bdrv_graph_co_rdunlock(); + if (s->bdev_length < 0) { ret = s->bdev_length; goto immediate_exit; diff --git a/block/preallocate.c b/block/preallocate.c index 63a296882d..71c3601809 100644 --- a/block/preallocate.c +++ b/block/preallocate.c @@ -443,7 +443,8 @@ static int coroutine_fn GRAPH_RDLOCK preallocate_co_flush(BlockDriverState *bs) return bdrv_co_flush(bs->file->bs); } -static int64_t coroutine_fn preallocate_co_getlength(BlockDriverState *bs) +static int64_t coroutine_fn GRAPH_RDLOCK +preallocate_co_getlength(BlockDriverState *bs) { int64_t ret; BDRVPreallocateState *s = bs->opaque; diff --git a/block/quorum.c b/block/quorum.c index d58f86d3a5..ff5a0a2da3 100644 --- a/block/quorum.c +++ b/block/quorum.c @@ -764,7 +764,8 @@ quorum_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset, int64_t bytes, flags | BDRV_REQ_ZERO_WRITE); } -static int64_t coroutine_fn quorum_co_getlength(BlockDriverState *bs) +static int64_t coroutine_fn GRAPH_RDLOCK +quorum_co_getlength(BlockDriverState *bs) { BDRVQuorumState *s = bs->opaque; int64_t result; diff --git a/block/raw-format.c b/block/raw-format.c index f4203d4806..66783ed8e7 100644 --- a/block/raw-format.c +++ b/block/raw-format.c @@ -317,7 +317,8 @@ raw_co_pdiscard(BlockDriverState *bs, int64_t offset, int64_t bytes) return bdrv_co_pdiscard(bs->file, offset, bytes); } -static int64_t coroutine_fn raw_co_getlength(BlockDriverState *bs) +static int64_t coroutine_fn GRAPH_RDLOCK +raw_co_getlength(BlockDriverState *bs) { int64_t len; BDRVRawState *s = bs->opaque; diff --git a/block/replication.c b/block/replication.c index f9f899bfc8..de01f96184 100644 --- a/block/replication.c +++ b/block/replication.c @@ -179,7 +179,8 @@ static void replication_child_perm(BlockDriverState *bs, BdrvChild *c, return; } -static int64_t coroutine_fn replication_co_getlength(BlockDriverState *bs) +static int64_t coroutine_fn GRAPH_RDLOCK +replication_co_getlength(BlockDriverState *bs) { return bdrv_co_getlength(bs->file->bs); } diff --git a/block/stream.c b/block/stream.c index 22368ce186..68018699de 100644 --- a/block/stream.c +++ b/block/stream.c @@ -141,9 +141,11 @@ static int coroutine_fn stream_run(Job *job, Error **errp) return 0; } - len = bdrv_getlength(s->target_bs); - if (len < 0) { - return len; + WITH_GRAPH_RDLOCK_GUARD() { + len = bdrv_co_getlength(s->target_bs); + if (len < 0) { + return len; + } } job_progress_set_remaining(&s->common.job, len); diff --git a/block/throttle.c b/block/throttle.c index 5cfea3d5f8..3aaef18d4e 100644 --- a/block/throttle.c +++ b/block/throttle.c @@ -106,7 +106,8 @@ static void throttle_close(BlockDriverState *bs) } -static int64_t coroutine_fn throttle_co_getlength(BlockDriverState *bs) +static int64_t coroutine_fn GRAPH_RDLOCK +throttle_co_getlength(BlockDriverState *bs) { return bdrv_co_getlength(bs->file->bs); } diff --git a/include/block/block-io.h b/include/block/block-io.h index 95bcc79b75..5da99d4d60 100644 --- a/include/block/block-io.h +++ b/include/block/block-io.h @@ -78,11 +78,11 @@ int coroutine_fn GRAPH_RDLOCK bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact, PreallocMode prealloc, BdrvRequestFlags flags, Error **errp); -int64_t coroutine_fn bdrv_co_nb_sectors(BlockDriverState *bs); -int64_t co_wrapper_mixed bdrv_nb_sectors(BlockDriverState *bs); +int64_t coroutine_fn GRAPH_RDLOCK bdrv_co_nb_sectors(BlockDriverState *bs); +int64_t co_wrapper_mixed_bdrv_rdlock bdrv_nb_sectors(BlockDriverState *bs); -int64_t coroutine_fn bdrv_co_getlength(BlockDriverState *bs); -int64_t co_wrapper_mixed bdrv_getlength(BlockDriverState *bs); +int64_t coroutine_fn GRAPH_RDLOCK bdrv_co_getlength(BlockDriverState *bs); +int64_t co_wrapper_mixed_bdrv_rdlock bdrv_getlength(BlockDriverState *bs); int64_t coroutine_fn bdrv_co_get_allocated_file_size(BlockDriverState *bs); int64_t co_wrapper bdrv_get_allocated_file_size(BlockDriverState *bs); diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h index d72e31aba3..d419017328 100644 --- a/include/block/block_int-common.h +++ b/include/block/block_int-common.h @@ -684,7 +684,9 @@ struct BlockDriver { BlockDriverState *bs, int64_t offset, bool exact, PreallocMode prealloc, BdrvRequestFlags flags, Error **errp); - int64_t coroutine_fn (*bdrv_co_getlength)(BlockDriverState *bs); + int64_t coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_getlength)( + BlockDriverState *bs); + int64_t coroutine_fn (*bdrv_co_get_allocated_file_size)( BlockDriverState *bs); diff --git a/include/block/block_int-io.h b/include/block/block_int-io.h index 612e5ddf99..eb0da7232e 100644 --- a/include/block/block_int-io.h +++ b/include/block/block_int-io.h @@ -124,9 +124,10 @@ bdrv_co_copy_range_to(BdrvChild *src, int64_t src_offset, int64_t bytes, BdrvRequestFlags read_flags, BdrvRequestFlags write_flags); -int coroutine_fn bdrv_co_refresh_total_sectors(BlockDriverState *bs, - int64_t hint); -int co_wrapper_mixed +int coroutine_fn GRAPH_RDLOCK +bdrv_co_refresh_total_sectors(BlockDriverState *bs, int64_t hint); + +int co_wrapper_mixed_bdrv_rdlock bdrv_refresh_total_sectors(BlockDriverState *bs, int64_t hint); BdrvChild *bdrv_cow_child(BlockDriverState *bs); From 7b7fc3d0102dafe8eb44802493036a526e921a71 Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Tue, 21 Feb 2023 16:22:16 -0500 Subject: [PATCH 061/129] scsi: protect req->aiocb with AioContext lock If requests are being processed in the IOThread when a SCSIDevice is unplugged, scsi_device_purge_requests() -> scsi_req_cancel_async() races with I/O completion callbacks. Both threads load and store req->aiocb. This can lead to assert(r->req.aiocb == NULL) failures and undefined behavior. Protect r->req.aiocb with the AioContext lock to prevent the race. Reviewed-by: Eric Blake Reviewed-by: Kevin Wolf Signed-off-by: Stefan Hajnoczi Message-Id: <20230221212218.1378734-2-stefanha@redhat.com> Signed-off-by: Kevin Wolf --- hw/scsi/scsi-disk.c | 23 ++++++++++++++++------- hw/scsi/scsi-generic.c | 11 ++++++----- 2 files changed, 22 insertions(+), 12 deletions(-) diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c index d4e360850f..115584f8b9 100644 --- a/hw/scsi/scsi-disk.c +++ b/hw/scsi/scsi-disk.c @@ -273,9 +273,11 @@ static void scsi_aio_complete(void *opaque, int ret) SCSIDiskReq *r = (SCSIDiskReq *)opaque; SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev); + aio_context_acquire(blk_get_aio_context(s->qdev.conf.blk)); + assert(r->req.aiocb != NULL); r->req.aiocb = NULL; - aio_context_acquire(blk_get_aio_context(s->qdev.conf.blk)); + if (scsi_disk_req_check_error(r, ret, true)) { goto done; } @@ -357,10 +359,11 @@ static void scsi_dma_complete(void *opaque, int ret) SCSIDiskReq *r = (SCSIDiskReq *)opaque; SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev); + aio_context_acquire(blk_get_aio_context(s->qdev.conf.blk)); + assert(r->req.aiocb != NULL); r->req.aiocb = NULL; - aio_context_acquire(blk_get_aio_context(s->qdev.conf.blk)); if (ret < 0) { block_acct_failed(blk_get_stats(s->qdev.conf.blk), &r->acct); } else { @@ -393,10 +396,11 @@ static void scsi_read_complete(void *opaque, int ret) SCSIDiskReq *r = (SCSIDiskReq *)opaque; SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev); + aio_context_acquire(blk_get_aio_context(s->qdev.conf.blk)); + assert(r->req.aiocb != NULL); r->req.aiocb = NULL; - aio_context_acquire(blk_get_aio_context(s->qdev.conf.blk)); if (ret < 0) { block_acct_failed(blk_get_stats(s->qdev.conf.blk), &r->acct); } else { @@ -446,10 +450,11 @@ static void scsi_do_read_cb(void *opaque, int ret) SCSIDiskReq *r = (SCSIDiskReq *)opaque; SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev); + aio_context_acquire(blk_get_aio_context(s->qdev.conf.blk)); + assert (r->req.aiocb != NULL); r->req.aiocb = NULL; - aio_context_acquire(blk_get_aio_context(s->qdev.conf.blk)); if (ret < 0) { block_acct_failed(blk_get_stats(s->qdev.conf.blk), &r->acct); } else { @@ -530,10 +535,11 @@ static void scsi_write_complete(void * opaque, int ret) SCSIDiskReq *r = (SCSIDiskReq *)opaque; SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev); + aio_context_acquire(blk_get_aio_context(s->qdev.conf.blk)); + assert (r->req.aiocb != NULL); r->req.aiocb = NULL; - aio_context_acquire(blk_get_aio_context(s->qdev.conf.blk)); if (ret < 0) { block_acct_failed(blk_get_stats(s->qdev.conf.blk), &r->acct); } else { @@ -1737,10 +1743,11 @@ static void scsi_unmap_complete(void *opaque, int ret) SCSIDiskReq *r = data->r; SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev); + aio_context_acquire(blk_get_aio_context(s->qdev.conf.blk)); + assert(r->req.aiocb != NULL); r->req.aiocb = NULL; - aio_context_acquire(blk_get_aio_context(s->qdev.conf.blk)); if (scsi_disk_req_check_error(r, ret, true)) { scsi_req_unref(&r->req); g_free(data); @@ -1816,9 +1823,11 @@ static void scsi_write_same_complete(void *opaque, int ret) SCSIDiskReq *r = data->r; SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev); + aio_context_acquire(blk_get_aio_context(s->qdev.conf.blk)); + assert(r->req.aiocb != NULL); r->req.aiocb = NULL; - aio_context_acquire(blk_get_aio_context(s->qdev.conf.blk)); + if (scsi_disk_req_check_error(r, ret, true)) { goto done; } diff --git a/hw/scsi/scsi-generic.c b/hw/scsi/scsi-generic.c index 92cce20a4d..ac9fa662b4 100644 --- a/hw/scsi/scsi-generic.c +++ b/hw/scsi/scsi-generic.c @@ -111,10 +111,11 @@ static void scsi_command_complete(void *opaque, int ret) SCSIGenericReq *r = (SCSIGenericReq *)opaque; SCSIDevice *s = r->req.dev; + aio_context_acquire(blk_get_aio_context(s->conf.blk)); + assert(r->req.aiocb != NULL); r->req.aiocb = NULL; - aio_context_acquire(blk_get_aio_context(s->conf.blk)); scsi_command_complete_noio(r, ret); aio_context_release(blk_get_aio_context(s->conf.blk)); } @@ -269,11 +270,11 @@ static void scsi_read_complete(void * opaque, int ret) SCSIDevice *s = r->req.dev; int len; + aio_context_acquire(blk_get_aio_context(s->conf.blk)); + assert(r->req.aiocb != NULL); r->req.aiocb = NULL; - aio_context_acquire(blk_get_aio_context(s->conf.blk)); - if (ret || r->req.io_canceled) { scsi_command_complete_noio(r, ret); goto done; @@ -386,11 +387,11 @@ static void scsi_write_complete(void * opaque, int ret) trace_scsi_generic_write_complete(ret); + aio_context_acquire(blk_get_aio_context(s->conf.blk)); + assert(r->req.aiocb != NULL); r->req.aiocb = NULL; - aio_context_acquire(blk_get_aio_context(s->conf.blk)); - if (ret || r->req.io_canceled) { scsi_command_complete_noio(r, ret); goto done; From abfcd2760b3e70727bbc0792221b8b98a733dc32 Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Tue, 21 Feb 2023 16:22:17 -0500 Subject: [PATCH 062/129] dma-helpers: prevent dma_blk_cb() vs dma_aio_cancel() race dma_blk_cb() only takes the AioContext lock around ->io_func(). That means the rest of dma_blk_cb() is not protected. In particular, the DMAAIOCB field accesses happen outside the lock. There is a race when the main loop thread holds the AioContext lock and invokes scsi_device_purge_requests() -> bdrv_aio_cancel() -> dma_aio_cancel() while an IOThread executes dma_blk_cb(). The dbs->acb field determines how cancellation proceeds. If dma_aio_cancel() sees dbs->acb == NULL while dma_blk_cb() is still running, the request can be completed twice (-ECANCELED and the actual return value). The following assertion can occur with virtio-scsi when an IOThread is used: ../hw/scsi/scsi-disk.c:368: scsi_dma_complete: Assertion `r->req.aiocb != NULL' failed. Fix the race by holding the AioContext across dma_blk_cb(). Now dma_aio_cancel() under the AioContext lock will not see inconsistent/intermediate states. Cc: Paolo Bonzini Reviewed-by: Eric Blake Signed-off-by: Stefan Hajnoczi Message-Id: <20230221212218.1378734-3-stefanha@redhat.com> Signed-off-by: Kevin Wolf --- hw/scsi/scsi-disk.c | 4 +--- softmmu/dma-helpers.c | 12 +++++++----- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c index 115584f8b9..97c9b1c8cd 100644 --- a/hw/scsi/scsi-disk.c +++ b/hw/scsi/scsi-disk.c @@ -354,13 +354,12 @@ done: scsi_req_unref(&r->req); } +/* Called with AioContext lock held */ static void scsi_dma_complete(void *opaque, int ret) { SCSIDiskReq *r = (SCSIDiskReq *)opaque; SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev); - aio_context_acquire(blk_get_aio_context(s->qdev.conf.blk)); - assert(r->req.aiocb != NULL); r->req.aiocb = NULL; @@ -370,7 +369,6 @@ static void scsi_dma_complete(void *opaque, int ret) block_acct_done(blk_get_stats(s->qdev.conf.blk), &r->acct); } scsi_dma_complete_noio(r, ret); - aio_context_release(blk_get_aio_context(s->qdev.conf.blk)); } static void scsi_read_complete_noio(SCSIDiskReq *r, int ret) diff --git a/softmmu/dma-helpers.c b/softmmu/dma-helpers.c index 7820fec54c..2463964805 100644 --- a/softmmu/dma-helpers.c +++ b/softmmu/dma-helpers.c @@ -113,17 +113,19 @@ static void dma_complete(DMAAIOCB *dbs, int ret) static void dma_blk_cb(void *opaque, int ret) { DMAAIOCB *dbs = (DMAAIOCB *)opaque; + AioContext *ctx = dbs->ctx; dma_addr_t cur_addr, cur_len; void *mem; trace_dma_blk_cb(dbs, ret); + aio_context_acquire(ctx); dbs->acb = NULL; dbs->offset += dbs->iov.size; if (dbs->sg_cur_index == dbs->sg->nsg || ret < 0) { dma_complete(dbs, ret); - return; + goto out; } dma_blk_unmap(dbs); @@ -164,9 +166,9 @@ static void dma_blk_cb(void *opaque, int ret) if (dbs->iov.size == 0) { trace_dma_map_wait(dbs); - dbs->bh = aio_bh_new(dbs->ctx, reschedule_dma, dbs); + dbs->bh = aio_bh_new(ctx, reschedule_dma, dbs); cpu_register_map_client(dbs->bh); - return; + goto out; } if (!QEMU_IS_ALIGNED(dbs->iov.size, dbs->align)) { @@ -174,11 +176,11 @@ static void dma_blk_cb(void *opaque, int ret) QEMU_ALIGN_DOWN(dbs->iov.size, dbs->align)); } - aio_context_acquire(dbs->ctx); dbs->acb = dbs->io_func(dbs->offset, &dbs->iov, dma_blk_cb, dbs, dbs->io_func_opaque); - aio_context_release(dbs->ctx); assert(dbs->acb); +out: + aio_context_release(ctx); } static void dma_aio_cancel(BlockAIOCB *acb) From be2c42b97c3a3a395b2f05bad1b6c7de20ecf2a5 Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Tue, 21 Feb 2023 16:22:18 -0500 Subject: [PATCH 063/129] virtio-scsi: reset SCSI devices from main loop thread When an IOThread is configured, the ctrl virtqueue is processed in the IOThread. TMFs that reset SCSI devices are currently called directly from the IOThread and trigger an assertion failure in blk_drain() from the following call stack: virtio_scsi_handle_ctrl_req -> virtio_scsi_do_tmf -> device_code_reset -> scsi_disk_reset -> scsi_device_purge_requests -> blk_drain ../block/block-backend.c:1780: void blk_drain(BlockBackend *): Assertion `qemu_in_main_thread()' failed. The blk_drain() function is not designed to be called from an IOThread because it needs the Big QEMU Lock (BQL). This patch defers TMFs that reset SCSI devices to a Bottom Half (BH) that runs in the main loop thread under the BQL. This way it's safe to call blk_drain() and the assertion failure is avoided. Introduce s->tmf_bh_list for tracking TMF requests that have been deferred to the BH. When the BH runs it will grab the entire list and process all requests. Care must be taken to clear the list when the virtio-scsi device is reset or unrealized. Otherwise deferred TMF requests could execute later and lead to use-after-free or other undefined behavior. The s->resetting counter that's used by TMFs that reset SCSI devices is accessed from multiple threads. This patch makes that explicit by using atomic accessor functions. With this patch applied the counter is only modified by the main loop thread under the BQL but can be read by any thread. Reported-by: Qing Wang Cc: Paolo Bonzini Reviewed-by: Eric Blake Signed-off-by: Stefan Hajnoczi Message-Id: <20230221212218.1378734-4-stefanha@redhat.com> Signed-off-by: Kevin Wolf --- hw/scsi/virtio-scsi.c | 169 +++++++++++++++++++++++++------- include/hw/virtio/virtio-scsi.h | 11 ++- 2 files changed, 143 insertions(+), 37 deletions(-) diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c index 2b649ca976..612c525d9d 100644 --- a/hw/scsi/virtio-scsi.c +++ b/hw/scsi/virtio-scsi.c @@ -43,13 +43,11 @@ typedef struct VirtIOSCSIReq { QEMUSGList qsgl; QEMUIOVector resp_iov; - union { - /* Used for two-stage request submission */ - QTAILQ_ENTRY(VirtIOSCSIReq) next; + /* Used for two-stage request submission and TMFs deferred to BH */ + QTAILQ_ENTRY(VirtIOSCSIReq) next; - /* Used for cancellation of request during TMFs */ - int remaining; - }; + /* Used for cancellation of request during TMFs */ + int remaining; SCSIRequest *sreq; size_t resp_size; @@ -294,6 +292,122 @@ static inline void virtio_scsi_ctx_check(VirtIOSCSI *s, SCSIDevice *d) } } +static void virtio_scsi_do_one_tmf_bh(VirtIOSCSIReq *req) +{ + VirtIOSCSI *s = req->dev; + SCSIDevice *d = virtio_scsi_device_get(s, req->req.tmf.lun); + BusChild *kid; + int target; + + switch (req->req.tmf.subtype) { + case VIRTIO_SCSI_T_TMF_LOGICAL_UNIT_RESET: + if (!d) { + req->resp.tmf.response = VIRTIO_SCSI_S_BAD_TARGET; + goto out; + } + if (d->lun != virtio_scsi_get_lun(req->req.tmf.lun)) { + req->resp.tmf.response = VIRTIO_SCSI_S_INCORRECT_LUN; + goto out; + } + qatomic_inc(&s->resetting); + device_cold_reset(&d->qdev); + qatomic_dec(&s->resetting); + break; + + case VIRTIO_SCSI_T_TMF_I_T_NEXUS_RESET: + target = req->req.tmf.lun[1]; + qatomic_inc(&s->resetting); + + rcu_read_lock(); + QTAILQ_FOREACH_RCU(kid, &s->bus.qbus.children, sibling) { + SCSIDevice *d1 = SCSI_DEVICE(kid->child); + if (d1->channel == 0 && d1->id == target) { + device_cold_reset(&d1->qdev); + } + } + rcu_read_unlock(); + + qatomic_dec(&s->resetting); + break; + + default: + g_assert_not_reached(); + break; + } + +out: + object_unref(OBJECT(d)); + + virtio_scsi_acquire(s); + virtio_scsi_complete_req(req); + virtio_scsi_release(s); +} + +/* Some TMFs must be processed from the main loop thread */ +static void virtio_scsi_do_tmf_bh(void *opaque) +{ + VirtIOSCSI *s = opaque; + QTAILQ_HEAD(, VirtIOSCSIReq) reqs = QTAILQ_HEAD_INITIALIZER(reqs); + VirtIOSCSIReq *req; + VirtIOSCSIReq *tmp; + + GLOBAL_STATE_CODE(); + + virtio_scsi_acquire(s); + + QTAILQ_FOREACH_SAFE(req, &s->tmf_bh_list, next, tmp) { + QTAILQ_REMOVE(&s->tmf_bh_list, req, next); + QTAILQ_INSERT_TAIL(&reqs, req, next); + } + + qemu_bh_delete(s->tmf_bh); + s->tmf_bh = NULL; + + virtio_scsi_release(s); + + QTAILQ_FOREACH_SAFE(req, &reqs, next, tmp) { + QTAILQ_REMOVE(&reqs, req, next); + virtio_scsi_do_one_tmf_bh(req); + } +} + +static void virtio_scsi_reset_tmf_bh(VirtIOSCSI *s) +{ + VirtIOSCSIReq *req; + VirtIOSCSIReq *tmp; + + GLOBAL_STATE_CODE(); + + virtio_scsi_acquire(s); + + if (s->tmf_bh) { + qemu_bh_delete(s->tmf_bh); + s->tmf_bh = NULL; + } + + QTAILQ_FOREACH_SAFE(req, &s->tmf_bh_list, next, tmp) { + QTAILQ_REMOVE(&s->tmf_bh_list, req, next); + + /* SAM-6 6.3.2 Hard reset */ + req->resp.tmf.response = VIRTIO_SCSI_S_TARGET_FAILURE; + virtio_scsi_complete_req(req); + } + + virtio_scsi_release(s); +} + +static void virtio_scsi_defer_tmf_to_bh(VirtIOSCSIReq *req) +{ + VirtIOSCSI *s = req->dev; + + QTAILQ_INSERT_TAIL(&s->tmf_bh_list, req, next); + + if (!s->tmf_bh) { + s->tmf_bh = qemu_bh_new(virtio_scsi_do_tmf_bh, s); + qemu_bh_schedule(s->tmf_bh); + } +} + /* Return 0 if the request is ready to be completed and return to guest; * -EINPROGRESS if the request is submitted and will be completed later, in the * case of async cancellation. */ @@ -301,8 +415,6 @@ static int virtio_scsi_do_tmf(VirtIOSCSI *s, VirtIOSCSIReq *req) { SCSIDevice *d = virtio_scsi_device_get(s, req->req.tmf.lun); SCSIRequest *r, *next; - BusChild *kid; - int target; int ret = 0; virtio_scsi_ctx_check(s, d); @@ -359,15 +471,9 @@ static int virtio_scsi_do_tmf(VirtIOSCSI *s, VirtIOSCSIReq *req) break; case VIRTIO_SCSI_T_TMF_LOGICAL_UNIT_RESET: - if (!d) { - goto fail; - } - if (d->lun != virtio_scsi_get_lun(req->req.tmf.lun)) { - goto incorrect_lun; - } - s->resetting++; - device_cold_reset(&d->qdev); - s->resetting--; + case VIRTIO_SCSI_T_TMF_I_T_NEXUS_RESET: + virtio_scsi_defer_tmf_to_bh(req); + ret = -EINPROGRESS; break; case VIRTIO_SCSI_T_TMF_ABORT_TASK_SET: @@ -410,22 +516,6 @@ static int virtio_scsi_do_tmf(VirtIOSCSI *s, VirtIOSCSIReq *req) } break; - case VIRTIO_SCSI_T_TMF_I_T_NEXUS_RESET: - target = req->req.tmf.lun[1]; - s->resetting++; - - rcu_read_lock(); - QTAILQ_FOREACH_RCU(kid, &s->bus.qbus.children, sibling) { - SCSIDevice *d1 = SCSI_DEVICE(kid->child); - if (d1->channel == 0 && d1->id == target) { - device_cold_reset(&d1->qdev); - } - } - rcu_read_unlock(); - - s->resetting--; - break; - case VIRTIO_SCSI_T_TMF_CLEAR_ACA: default: req->resp.tmf.response = VIRTIO_SCSI_S_FUNCTION_REJECTED; @@ -655,7 +745,7 @@ static void virtio_scsi_request_cancelled(SCSIRequest *r) if (!req) { return; } - if (req->dev->resetting) { + if (qatomic_read(&req->dev->resetting)) { req->resp.cmd.response = VIRTIO_SCSI_S_RESET; } else { req->resp.cmd.response = VIRTIO_SCSI_S_ABORTED; @@ -831,9 +921,12 @@ static void virtio_scsi_reset(VirtIODevice *vdev) VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(vdev); assert(!s->dataplane_started); - s->resetting++; + + virtio_scsi_reset_tmf_bh(s); + + qatomic_inc(&s->resetting); bus_cold_reset(BUS(&s->bus)); - s->resetting--; + qatomic_dec(&s->resetting); vs->sense_size = VIRTIO_SCSI_SENSE_DEFAULT_SIZE; vs->cdb_size = VIRTIO_SCSI_CDB_DEFAULT_SIZE; @@ -1053,6 +1146,8 @@ static void virtio_scsi_device_realize(DeviceState *dev, Error **errp) VirtIOSCSI *s = VIRTIO_SCSI(dev); Error *err = NULL; + QTAILQ_INIT(&s->tmf_bh_list); + virtio_scsi_common_realize(dev, virtio_scsi_handle_ctrl, virtio_scsi_handle_event, @@ -1090,6 +1185,8 @@ static void virtio_scsi_device_unrealize(DeviceState *dev) { VirtIOSCSI *s = VIRTIO_SCSI(dev); + virtio_scsi_reset_tmf_bh(s); + qbus_set_hotplug_handler(BUS(&s->bus), NULL); virtio_scsi_common_unrealize(dev); } diff --git a/include/hw/virtio/virtio-scsi.h b/include/hw/virtio/virtio-scsi.h index 37b75e15e3..779568ab5d 100644 --- a/include/hw/virtio/virtio-scsi.h +++ b/include/hw/virtio/virtio-scsi.h @@ -74,13 +74,22 @@ struct VirtIOSCSICommon { VirtQueue **cmd_vqs; }; +struct VirtIOSCSIReq; + struct VirtIOSCSI { VirtIOSCSICommon parent_obj; SCSIBus bus; - int resetting; + int resetting; /* written from main loop thread, read from any thread */ bool events_dropped; + /* + * TMFs deferred to main loop BH. These fields are protected by + * virtio_scsi_acquire(). + */ + QEMUBH *tmf_bh; + QTAILQ_HEAD(, VirtIOSCSIReq) tmf_bh_list; + /* Fields for dataplane below */ AioContext *ctx; /* one iothread per virtio-scsi-pci for now */ From a4ac51ac4ebebf812e20e7572e62bc1b8d569617 Mon Sep 17 00:00:00 2001 From: Or Ozeri Date: Sun, 29 Jan 2023 05:31:18 -0600 Subject: [PATCH 064/129] block/rbd: Remove redundant stack variable passphrase_len Signed-off-by: Or Ozeri Message-Id: <20230129113120.722708-2-oro@oro.sl.cloud9.ibm.com> Reviewed-by: Ilya Dryomov Reviewed-by: Kevin Wolf Signed-off-by: Kevin Wolf --- block/rbd.c | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/block/rbd.c b/block/rbd.c index 5e102fea0d..4bd75c9bb7 100644 --- a/block/rbd.c +++ b/block/rbd.c @@ -386,7 +386,6 @@ static int qemu_rbd_encryption_format(rbd_image_t image, { int r = 0; g_autofree char *passphrase = NULL; - size_t passphrase_len; rbd_encryption_format_t format; rbd_encryption_options_t opts; rbd_encryption_luks1_format_options_t luks_opts; @@ -408,12 +407,12 @@ static int qemu_rbd_encryption_format(rbd_image_t image, opts_size = sizeof(luks_opts); r = qemu_rbd_convert_luks_create_options( qapi_RbdEncryptionCreateOptionsLUKS_base(&encrypt->u.luks), - &luks_opts.alg, &passphrase, &passphrase_len, errp); + &luks_opts.alg, &passphrase, &luks_opts.passphrase_size, + errp); if (r < 0) { return r; } luks_opts.passphrase = passphrase; - luks_opts.passphrase_size = passphrase_len; break; } case RBD_IMAGE_ENCRYPTION_FORMAT_LUKS2: { @@ -424,12 +423,12 @@ static int qemu_rbd_encryption_format(rbd_image_t image, r = qemu_rbd_convert_luks_create_options( qapi_RbdEncryptionCreateOptionsLUKS2_base( &encrypt->u.luks2), - &luks2_opts.alg, &passphrase, &passphrase_len, errp); + &luks2_opts.alg, &passphrase, &luks2_opts.passphrase_size, + errp); if (r < 0) { return r; } luks2_opts.passphrase = passphrase; - luks2_opts.passphrase_size = passphrase_len; break; } default: { @@ -468,7 +467,6 @@ static int qemu_rbd_encryption_load(rbd_image_t image, { int r = 0; g_autofree char *passphrase = NULL; - size_t passphrase_len; rbd_encryption_luks1_format_options_t luks_opts; rbd_encryption_luks2_format_options_t luks2_opts; rbd_encryption_format_t format; @@ -483,12 +481,11 @@ static int qemu_rbd_encryption_load(rbd_image_t image, opts_size = sizeof(luks_opts); r = qemu_rbd_convert_luks_options( qapi_RbdEncryptionOptionsLUKS_base(&encrypt->u.luks), - &passphrase, &passphrase_len, errp); + &passphrase, &luks_opts.passphrase_size, errp); if (r < 0) { return r; } luks_opts.passphrase = passphrase; - luks_opts.passphrase_size = passphrase_len; break; } case RBD_IMAGE_ENCRYPTION_FORMAT_LUKS2: { @@ -498,12 +495,11 @@ static int qemu_rbd_encryption_load(rbd_image_t image, opts_size = sizeof(luks2_opts); r = qemu_rbd_convert_luks_options( qapi_RbdEncryptionOptionsLUKS2_base(&encrypt->u.luks2), - &passphrase, &passphrase_len, errp); + &passphrase, &luks2_opts.passphrase_size, errp); if (r < 0) { return r; } luks2_opts.passphrase = passphrase; - luks2_opts.passphrase_size = passphrase_len; break; } default: { From b8f218ef6036d4d62968f6da9319c9d0663539dd Mon Sep 17 00:00:00 2001 From: Or Ozeri Date: Sun, 29 Jan 2023 05:31:19 -0600 Subject: [PATCH 065/129] block/rbd: Add luks-any encryption opening option Ceph RBD encryption API required specifying the encryption format for loading encryption. The supported formats were LUKS (v1) and LUKS2. Starting from Reef release, RBD also supports loading with "luks-any" format, which works for both versions of LUKS. This commit extends the qemu rbd driver API to enable qemu users to use this luks-any wildcard format. Signed-off-by: Or Ozeri Message-Id: <20230129113120.722708-3-oro@oro.sl.cloud9.ibm.com> Reviewed-by: Ilya Dryomov Reviewed-by: Kevin Wolf Signed-off-by: Kevin Wolf --- block/rbd.c | 19 +++++++++++++++++++ qapi/block-core.json | 16 ++++++++++++++-- 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/block/rbd.c b/block/rbd.c index 4bd75c9bb7..744f84c222 100644 --- a/block/rbd.c +++ b/block/rbd.c @@ -469,6 +469,9 @@ static int qemu_rbd_encryption_load(rbd_image_t image, g_autofree char *passphrase = NULL; rbd_encryption_luks1_format_options_t luks_opts; rbd_encryption_luks2_format_options_t luks2_opts; +#ifdef LIBRBD_SUPPORTS_ENCRYPTION_LOAD2 + rbd_encryption_luks_format_options_t luks_any_opts; +#endif rbd_encryption_format_t format; rbd_encryption_options_t opts; size_t opts_size; @@ -502,6 +505,22 @@ static int qemu_rbd_encryption_load(rbd_image_t image, luks2_opts.passphrase = passphrase; break; } +#ifdef LIBRBD_SUPPORTS_ENCRYPTION_LOAD2 + case RBD_IMAGE_ENCRYPTION_FORMAT_LUKS_ANY: { + memset(&luks_any_opts, 0, sizeof(luks_any_opts)); + format = RBD_ENCRYPTION_FORMAT_LUKS; + opts = &luks_any_opts; + opts_size = sizeof(luks_any_opts); + r = qemu_rbd_convert_luks_options( + qapi_RbdEncryptionOptionsLUKSAny_base(&encrypt->u.luks_any), + &passphrase, &luks_any_opts.passphrase_size, errp); + if (r < 0) { + return r; + } + luks_any_opts.passphrase = passphrase; + break; + } +#endif default: { r = -ENOTSUP; error_setg_errno( diff --git a/qapi/block-core.json b/qapi/block-core.json index 7f331eb8ea..5f09b1d31a 100644 --- a/qapi/block-core.json +++ b/qapi/block-core.json @@ -3922,10 +3922,12 @@ ## # @RbdImageEncryptionFormat: # +# @luks-any: Used for opening either luks or luks2 (Since 8.0) +# # Since: 6.1 ## { 'enum': 'RbdImageEncryptionFormat', - 'data': [ 'luks', 'luks2' ] } + 'data': [ 'luks', 'luks2', 'luks-any' ] } ## # @RbdEncryptionOptionsLUKSBase: @@ -3967,6 +3969,15 @@ 'base': 'RbdEncryptionOptionsLUKSBase', 'data': { } } +## +# @RbdEncryptionOptionsLUKSAny: +# +# Since: 8.0 +## +{ 'struct': 'RbdEncryptionOptionsLUKSAny', + 'base': 'RbdEncryptionOptionsLUKSBase', + 'data': { } } + ## # @RbdEncryptionCreateOptionsLUKS: # @@ -3994,7 +4005,8 @@ 'base': { 'format': 'RbdImageEncryptionFormat' }, 'discriminator': 'format', 'data': { 'luks': 'RbdEncryptionOptionsLUKS', - 'luks2': 'RbdEncryptionOptionsLUKS2' } } + 'luks2': 'RbdEncryptionOptionsLUKS2', + 'luks-any': 'RbdEncryptionOptionsLUKSAny'} } ## # @RbdEncryptionCreateOptions: From 0f385a2420d2c3f8ae7ed65fbe2712027664059e Mon Sep 17 00:00:00 2001 From: Or Ozeri Date: Sun, 29 Jan 2023 05:31:20 -0600 Subject: [PATCH 066/129] block/rbd: Add support for layered encryption Starting from ceph Reef, RBD has built-in support for layered encryption, where each ancestor image (in a cloned image setting) can be possibly encrypted using a unique passphrase. A new function, rbd_encryption_load2, was added to librbd API. This new function supports an array of passphrases (via "spec" structs). This commit extends the qemu rbd driver API to use this new librbd API, in order to support this new layered encryption feature. Signed-off-by: Or Ozeri Message-Id: <20230129113120.722708-4-oro@oro.sl.cloud9.ibm.com> Reviewed-by: Ilya Dryomov Reviewed-by: Kevin Wolf Signed-off-by: Kevin Wolf --- block/rbd.c | 153 ++++++++++++++++++++++++++++++++++++++++++- qapi/block-core.json | 11 +++- 2 files changed, 162 insertions(+), 2 deletions(-) diff --git a/block/rbd.c b/block/rbd.c index 744f84c222..978671411e 100644 --- a/block/rbd.c +++ b/block/rbd.c @@ -72,6 +72,16 @@ static const char rbd_luks2_header_verification[ 'L', 'U', 'K', 'S', 0xBA, 0xBE, 0, 2 }; +static const char rbd_layered_luks_header_verification[ + RBD_ENCRYPTION_LUKS_HEADER_VERIFICATION_LEN] = { + 'R', 'B', 'D', 'L', 0xBA, 0xBE, 0, 1 +}; + +static const char rbd_layered_luks2_header_verification[ + RBD_ENCRYPTION_LUKS_HEADER_VERIFICATION_LEN] = { + 'R', 'B', 'D', 'L', 0xBA, 0xBE, 0, 2 +}; + typedef enum { RBD_AIO_READ, RBD_AIO_WRITE, @@ -538,6 +548,128 @@ static int qemu_rbd_encryption_load(rbd_image_t image, return 0; } + +#ifdef LIBRBD_SUPPORTS_ENCRYPTION_LOAD2 +static int qemu_rbd_encryption_load2(rbd_image_t image, + RbdEncryptionOptions *encrypt, + Error **errp) +{ + int r = 0; + int encrypt_count = 1; + int i; + RbdEncryptionOptions *curr_encrypt; + rbd_encryption_spec_t *specs; + rbd_encryption_luks1_format_options_t *luks_opts; + rbd_encryption_luks2_format_options_t *luks2_opts; + rbd_encryption_luks_format_options_t *luks_any_opts; + + /* count encryption options */ + for (curr_encrypt = encrypt->parent; curr_encrypt; + curr_encrypt = curr_encrypt->parent) { + ++encrypt_count; + } + + specs = g_new0(rbd_encryption_spec_t, encrypt_count); + + curr_encrypt = encrypt; + for (i = 0; i < encrypt_count; ++i) { + switch (curr_encrypt->format) { + case RBD_IMAGE_ENCRYPTION_FORMAT_LUKS: { + specs[i].format = RBD_ENCRYPTION_FORMAT_LUKS1; + + luks_opts = g_new0(rbd_encryption_luks1_format_options_t, 1); + specs[i].opts = luks_opts; + specs[i].opts_size = sizeof(*luks_opts); + + r = qemu_rbd_convert_luks_options( + qapi_RbdEncryptionOptionsLUKS_base( + &curr_encrypt->u.luks), + (char **)&luks_opts->passphrase, + &luks_opts->passphrase_size, + errp); + break; + } + case RBD_IMAGE_ENCRYPTION_FORMAT_LUKS2: { + specs[i].format = RBD_ENCRYPTION_FORMAT_LUKS2; + + luks2_opts = g_new0(rbd_encryption_luks2_format_options_t, 1); + specs[i].opts = luks2_opts; + specs[i].opts_size = sizeof(*luks2_opts); + + r = qemu_rbd_convert_luks_options( + qapi_RbdEncryptionOptionsLUKS2_base( + &curr_encrypt->u.luks2), + (char **)&luks2_opts->passphrase, + &luks2_opts->passphrase_size, + errp); + break; + } + case RBD_IMAGE_ENCRYPTION_FORMAT_LUKS_ANY: { + specs[i].format = RBD_ENCRYPTION_FORMAT_LUKS; + + luks_any_opts = g_new0(rbd_encryption_luks_format_options_t, 1); + specs[i].opts = luks_any_opts; + specs[i].opts_size = sizeof(*luks_any_opts); + + r = qemu_rbd_convert_luks_options( + qapi_RbdEncryptionOptionsLUKSAny_base( + &curr_encrypt->u.luks_any), + (char **)&luks_any_opts->passphrase, + &luks_any_opts->passphrase_size, + errp); + break; + } + default: { + r = -ENOTSUP; + error_setg_errno( + errp, -r, "unknown image encryption format: %u", + curr_encrypt->format); + } + } + + if (r < 0) { + goto exit; + } + + curr_encrypt = curr_encrypt->parent; + } + + r = rbd_encryption_load2(image, specs, encrypt_count); + if (r < 0) { + error_setg_errno(errp, -r, "layered encryption load fail"); + goto exit; + } + +exit: + for (i = 0; i < encrypt_count; ++i) { + if (!specs[i].opts) { + break; + } + + switch (specs[i].format) { + case RBD_ENCRYPTION_FORMAT_LUKS1: { + luks_opts = specs[i].opts; + g_free((void *)luks_opts->passphrase); + break; + } + case RBD_ENCRYPTION_FORMAT_LUKS2: { + luks2_opts = specs[i].opts; + g_free((void *)luks2_opts->passphrase); + break; + } + case RBD_ENCRYPTION_FORMAT_LUKS: { + luks_any_opts = specs[i].opts; + g_free((void *)luks_any_opts->passphrase); + break; + } + } + + g_free(specs[i].opts); + } + g_free(specs); + return r; +} +#endif #endif /* FIXME Deprecate and remove keypairs or make it available in QMP. */ @@ -1004,7 +1136,16 @@ static int qemu_rbd_open(BlockDriverState *bs, QDict *options, int flags, if (opts->encrypt) { #ifdef LIBRBD_SUPPORTS_ENCRYPTION - r = qemu_rbd_encryption_load(s->image, opts->encrypt, errp); + if (opts->encrypt->parent) { +#ifdef LIBRBD_SUPPORTS_ENCRYPTION_LOAD2 + r = qemu_rbd_encryption_load2(s->image, opts->encrypt, errp); +#else + r = -ENOTSUP; + error_setg(errp, "RBD library does not support layered encryption"); +#endif + } else { + r = qemu_rbd_encryption_load(s->image, opts->encrypt, errp); + } if (r < 0) { goto failed_post_open; } @@ -1296,6 +1437,16 @@ static ImageInfoSpecific *qemu_rbd_get_specific_info(BlockDriverState *bs, spec_info->u.rbd.data->encryption_format = RBD_IMAGE_ENCRYPTION_FORMAT_LUKS2; spec_info->u.rbd.data->has_encryption_format = true; + } else if (memcmp(buf, rbd_layered_luks_header_verification, + RBD_ENCRYPTION_LUKS_HEADER_VERIFICATION_LEN) == 0) { + spec_info->u.rbd.data->encryption_format = + RBD_IMAGE_ENCRYPTION_FORMAT_LUKS; + spec_info->u.rbd.data->has_encryption_format = true; + } else if (memcmp(buf, rbd_layered_luks2_header_verification, + RBD_ENCRYPTION_LUKS_HEADER_VERIFICATION_LEN) == 0) { + spec_info->u.rbd.data->encryption_format = + RBD_IMAGE_ENCRYPTION_FORMAT_LUKS2; + spec_info->u.rbd.data->has_encryption_format = true; } else { spec_info->u.rbd.data->has_encryption_format = false; } diff --git a/qapi/block-core.json b/qapi/block-core.json index 5f09b1d31a..c05ad0c07e 100644 --- a/qapi/block-core.json +++ b/qapi/block-core.json @@ -3999,10 +3999,19 @@ ## # @RbdEncryptionOptions: # +# @format: Encryption format. +# +# @parent: Parent image encryption options (for cloned images). +# Can be left unspecified if this cloned image is encrypted +# using the same format and secret as its parent image (i.e. +# not explicitly formatted) or if its parent image is not +# encrypted. (Since 8.0) +# # Since: 6.1 ## { 'union': 'RbdEncryptionOptions', - 'base': { 'format': 'RbdImageEncryptionFormat' }, + 'base': { 'format': 'RbdImageEncryptionFormat', + '*parent': 'RbdEncryptionOptions' }, 'discriminator': 'format', 'data': { 'luks': 'RbdEncryptionOptionsLUKS', 'luks2': 'RbdEncryptionOptionsLUKS2', From 0e660142ca085284c31b8418104b22b18d33bc22 Mon Sep 17 00:00:00 2001 From: Frank Chang Date: Wed, 8 Feb 2023 14:32:08 +0800 Subject: [PATCH 067/129] target/riscv: Remove privileged spec version restriction for RVV The RVV specification does not require that the core needs to support the privileged specification v1.12.0 to support RVV, and there is no dependency from ISA level. This commit removes the restriction from both RVV CSRs and extension CPU ISA string. Signed-off-by: Frank Chang Reviewed-by: Bin Meng Reviewed-by: LIU Zhiwei Acked-by: Alistair Francis Message-Id: <20230208063209.27279-1-frank.chang@sifive.com> Signed-off-by: Alistair Francis Signed-off-by: Palmer Dabbelt --- target/riscv/cpu.c | 2 +- target/riscv/csr.c | 21 +++++++-------------- 2 files changed, 8 insertions(+), 15 deletions(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 0dd2f0c753..93b52b826c 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -73,7 +73,7 @@ struct isa_ext_data { */ static const struct isa_ext_data isa_edata_arr[] = { ISA_EXT_DATA_ENTRY(h, false, PRIV_VERSION_1_12_0, ext_h), - ISA_EXT_DATA_ENTRY(v, false, PRIV_VERSION_1_12_0, ext_v), + ISA_EXT_DATA_ENTRY(v, false, PRIV_VERSION_1_10_0, ext_v), ISA_EXT_DATA_ENTRY(zicsr, true, PRIV_VERSION_1_10_0, ext_icsr), ISA_EXT_DATA_ENTRY(zifencei, true, PRIV_VERSION_1_10_0, ext_ifencei), ISA_EXT_DATA_ENTRY(zihintpause, true, PRIV_VERSION_1_10_0, ext_zihintpause), diff --git a/target/riscv/csr.c b/target/riscv/csr.c index fa17d7770c..1b0a0c1693 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -3980,20 +3980,13 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = { [CSR_FRM] = { "frm", fs, read_frm, write_frm }, [CSR_FCSR] = { "fcsr", fs, read_fcsr, write_fcsr }, /* Vector CSRs */ - [CSR_VSTART] = { "vstart", vs, read_vstart, write_vstart, - .min_priv_ver = PRIV_VERSION_1_12_0 }, - [CSR_VXSAT] = { "vxsat", vs, read_vxsat, write_vxsat, - .min_priv_ver = PRIV_VERSION_1_12_0 }, - [CSR_VXRM] = { "vxrm", vs, read_vxrm, write_vxrm, - .min_priv_ver = PRIV_VERSION_1_12_0 }, - [CSR_VCSR] = { "vcsr", vs, read_vcsr, write_vcsr, - .min_priv_ver = PRIV_VERSION_1_12_0 }, - [CSR_VL] = { "vl", vs, read_vl, - .min_priv_ver = PRIV_VERSION_1_12_0 }, - [CSR_VTYPE] = { "vtype", vs, read_vtype, - .min_priv_ver = PRIV_VERSION_1_12_0 }, - [CSR_VLENB] = { "vlenb", vs, read_vlenb, - .min_priv_ver = PRIV_VERSION_1_12_0 }, + [CSR_VSTART] = { "vstart", vs, read_vstart, write_vstart }, + [CSR_VXSAT] = { "vxsat", vs, read_vxsat, write_vxsat }, + [CSR_VXRM] = { "vxrm", vs, read_vxrm, write_vxrm }, + [CSR_VCSR] = { "vcsr", vs, read_vcsr, write_vcsr }, + [CSR_VL] = { "vl", vs, read_vl }, + [CSR_VTYPE] = { "vtype", vs, read_vtype }, + [CSR_VLENB] = { "vlenb", vs, read_vlenb }, /* User Timers and Counters */ [CSR_CYCLE] = { "cycle", ctr, read_hpmcounter }, [CSR_INSTRET] = { "instret", ctr, read_hpmcounter }, From a3ae8d46c04364148a6ea814140dff3b9b29ba1b Mon Sep 17 00:00:00 2001 From: Alistair Francis Date: Thu, 9 Feb 2023 10:33:08 +1000 Subject: [PATCH 068/129] MAINTAINERS: Add some RISC-V reviewers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch adds some active RISC-V members as reviewers to the MAINTAINERS file. Signed-off-by: Alistair Francis Acked-by: LIU Zhiwei Acked-by: Weiwei Li Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Bin Meng Reviewed-by: Daniel Henrique Barboza Reviewed-by: Frank Chang Message-Id: <20230209003308.738237-1-alistair.francis@opensource.wdc.com> Signed-off-by: Palmer Dabbelt --- MAINTAINERS | 3 +++ 1 file changed, 3 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 96e25f62ac..847bc7f131 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -287,6 +287,9 @@ RISC-V TCG CPUs M: Palmer Dabbelt M: Alistair Francis M: Bin Meng +R: Weiwei Li +R: Daniel Henrique Barboza +R: Liu Zhiwei L: qemu-riscv@nongnu.org S: Supported F: target/riscv/ From 90b1fafce0602d46243a40d8eea3006ef57e24d8 Mon Sep 17 00:00:00 2001 From: Himanshu Chauhan Date: Thu, 9 Feb 2023 11:22:06 +0530 Subject: [PATCH 069/129] target/riscv: Smepmp: Skip applying default rules when address matches When MSECCFG.MML is set, after checking the address range in PMP if the asked permissions are not same as programmed in PMP, the default permissions are applied. This should only be the case when there is no matching address is found. This patch skips applying default rules when matching address range is found. It returns the index of the match PMP entry. Fixes: 824cac681c3 (target/riscv: Fix PMP propagation for tlb) Signed-off-by: Himanshu Chauhan Reviewed-by: Daniel Henrique Barboza Reviewed-by: Alistair Francis Message-Id: <20230209055206.229392-1-hchauhan@ventanamicro.com> Signed-off-by: Alistair Francis Signed-off-by: Palmer Dabbelt --- target/riscv/pmp.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/target/riscv/pmp.c b/target/riscv/pmp.c index d1126a6066..4bc4113531 100644 --- a/target/riscv/pmp.c +++ b/target/riscv/pmp.c @@ -441,9 +441,12 @@ int pmp_hart_has_privs(CPURISCVState *env, target_ulong addr, } } - if ((privs & *allowed_privs) == privs) { - ret = i; - } + /* + * If matching address range was found, the protection bits + * defined with PMP must be used. We shouldn't fallback on + * finding default privileges. + */ + ret = i; break; } } From 718942aed69d42f0d982824b2469331ff77edcb2 Mon Sep 17 00:00:00 2001 From: Daniel Henrique Barboza Date: Fri, 10 Feb 2023 09:38:36 -0300 Subject: [PATCH 070/129] target/riscv: avoid env_archcpu() in cpu_get_tb_cpu_state() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We have a RISCVCPU *cpu pointer available at the start of the function. Signed-off-by: Daniel Henrique Barboza Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Weiwei Li Message-ID: <20230210123836.506286-1-dbarboza@ventanamicro.com> Signed-off-by: Palmer Dabbelt --- 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 ad8d82662c..3a9472a2ff 100644 --- a/target/riscv/cpu_helper.c +++ b/target/riscv/cpu_helper.c @@ -60,7 +60,7 @@ void cpu_get_tb_cpu_state(CPURISCVState *env, target_ulong *pc, * which is not supported by GVEC. So we set vl_eq_vlmax flag to true * only when maxsz >= 8 bytes. */ - uint32_t vlmax = vext_get_vlmax(env_archcpu(env), env->vtype); + uint32_t vlmax = vext_get_vlmax(cpu, env->vtype); uint32_t sew = FIELD_EX64(env->vtype, VTYPE, VSEW); uint32_t maxsz = vlmax << sew; bool vl_eq_vlmax = (env->vstart == 0) && (vlmax == env->vl) && From 8c89d50c10afdd98da82642ca5e9d7af4f1c18bd Mon Sep 17 00:00:00 2001 From: LIU Zhiwei Date: Mon, 13 Feb 2023 17:45:50 +0800 Subject: [PATCH 071/129] target/riscv: Fix vslide1up.vf and vslide1down.vf vslide1up_##BITWIDTH is used by the vslide1up.vx and vslide1up.vf. So its scalar input should be uint64_t to hold the 64 bits float register.And the same for vslide1down_##BITWIDTH. This bug is caught when run these instructions on qemu-riscv32. Signed-off-by: LIU Zhiwei Reviewed-by: Weiwei Li Reviewed-by: Frank Chang Message-ID: <20230213094550.29621-1-zhiwei_liu@linux.alibaba.com> Signed-off-by: Palmer Dabbelt --- target/riscv/vector_helper.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/target/riscv/vector_helper.c b/target/riscv/vector_helper.c index 00de879787..3073c54871 100644 --- a/target/riscv/vector_helper.c +++ b/target/riscv/vector_helper.c @@ -5038,7 +5038,7 @@ GEN_VEXT_VSLIDEDOWN_VX(vslidedown_vx_w, uint32_t, H4) GEN_VEXT_VSLIDEDOWN_VX(vslidedown_vx_d, uint64_t, H8) #define GEN_VEXT_VSLIE1UP(BITWIDTH, H) \ -static void vslide1up_##BITWIDTH(void *vd, void *v0, target_ulong s1, \ +static void vslide1up_##BITWIDTH(void *vd, void *v0, uint64_t s1, \ void *vs2, CPURISCVState *env, uint32_t desc) \ { \ typedef uint##BITWIDTH##_t ETYPE; \ @@ -5086,7 +5086,7 @@ GEN_VEXT_VSLIDE1UP_VX(vslide1up_vx_w, 32) GEN_VEXT_VSLIDE1UP_VX(vslide1up_vx_d, 64) #define GEN_VEXT_VSLIDE1DOWN(BITWIDTH, H) \ -static void vslide1down_##BITWIDTH(void *vd, void *v0, target_ulong s1, \ +static void vslide1down_##BITWIDTH(void *vd, void *v0, uint64_t s1, \ void *vs2, CPURISCVState *env, uint32_t desc) \ { \ typedef uint##BITWIDTH##_t ETYPE; \ From 5ebecf207293014dca147f6a56200f918532f34c Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Wed, 15 Feb 2023 13:41:22 +0100 Subject: [PATCH 072/129] tests/qtest/rtl8139-test: Make the test less verbose by default MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We are facing the issues that some test logs in the gitlab CI are too big (and thus cut off). The rtl8139-test is one of the few qtests that prints many lines of output by default when running with V=1, so it contributes to this problem. Almost all other qtests are silent with V=1 and only print debug messages with V=2 and higher. Thus let's change the rtl8139-test to behave more like the other tests and only print the debug messages with V=2 (or higher). Message-Id: <20230215124122.72037-1-thuth@redhat.com> Reviewed-by: Daniel P. Berrangé Signed-off-by: Thomas Huth --- tests/qtest/rtl8139-test.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/tests/qtest/rtl8139-test.c b/tests/qtest/rtl8139-test.c index 8fa3313cc3..1beb83805c 100644 --- a/tests/qtest/rtl8139-test.c +++ b/tests/qtest/rtl8139-test.c @@ -12,6 +12,8 @@ #include "libqos/pci-pc.h" #include "qemu/timer.h" +static int verbosity_level; + /* Tests only initialization so far. TODO: Replace with functional tests */ static void nop(void) { @@ -45,12 +47,16 @@ static QPCIDevice *get_device(void) static unsigned __attribute__((unused)) in_##name(void) \ { \ unsigned res = qpci_io_read##len(dev, dev_bar, (val)); \ - g_test_message("*%s -> %x", #name, res); \ + if (verbosity_level >= 2) { \ + g_test_message("*%s -> %x", #name, res); \ + } \ return res; \ } \ static void out_##name(unsigned v) \ { \ - g_test_message("%x -> *%s", v, #name); \ + if (verbosity_level >= 2) { \ + g_test_message("%x -> *%s", v, #name); \ + } \ qpci_io_write##len(dev, dev_bar, (val), v); \ } @@ -195,6 +201,11 @@ static void test_init(void) int main(int argc, char **argv) { int ret; + char *v_env = getenv("V"); + + if (v_env) { + verbosity_level = atoi(v_env); + } qtest_start("-device rtl8139"); From f0830823d017af1a4e7dad228e5870cad7eb764b Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Thu, 16 Feb 2023 15:29:15 +0100 Subject: [PATCH 073/129] Do not include hw/hw.h if it is not necessary MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit hw.h only contains the protoype of one function nowadays, hw_error(), so all files that do not use this function anymore also do not need to include this header anymore. Message-Id: <20230216142915.304481-1-thuth@redhat.com> Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Thomas Huth --- hw/pci-host/mv64361.c | 1 - hw/ppc/pegasos2.c | 1 - hw/sensor/dps310.c | 1 - include/hw/ssi/ibex_spi_host.h | 1 - include/hw/tricore/tricore_testdevice.h | 1 - 5 files changed, 5 deletions(-) diff --git a/hw/pci-host/mv64361.c b/hw/pci-host/mv64361.c index f43f33fbd9..298564f1f5 100644 --- a/hw/pci-host/mv64361.c +++ b/hw/pci-host/mv64361.c @@ -11,7 +11,6 @@ #include "qemu/osdep.h" #include "qemu/units.h" #include "qapi/error.h" -#include "hw/hw.h" #include "hw/sysbus.h" #include "hw/pci/pci_device.h" #include "hw/pci/pci_host.h" diff --git a/hw/ppc/pegasos2.c b/hw/ppc/pegasos2.c index a9563f4fb2..7cc375df05 100644 --- a/hw/ppc/pegasos2.c +++ b/hw/ppc/pegasos2.c @@ -10,7 +10,6 @@ #include "qemu/osdep.h" #include "qemu/units.h" #include "qapi/error.h" -#include "hw/hw.h" #include "hw/ppc/ppc.h" #include "hw/sysbus.h" #include "hw/pci/pci_host.h" diff --git a/hw/sensor/dps310.c b/hw/sensor/dps310.c index d60a18ac41..addee99b19 100644 --- a/hw/sensor/dps310.c +++ b/hw/sensor/dps310.c @@ -9,7 +9,6 @@ #include "qemu/osdep.h" #include "qemu/log.h" -#include "hw/hw.h" #include "hw/i2c/i2c.h" #include "qapi/error.h" #include "qapi/visitor.h" diff --git a/include/hw/ssi/ibex_spi_host.h b/include/hw/ssi/ibex_spi_host.h index 8089cc1c31..5bd5557b9a 100644 --- a/include/hw/ssi/ibex_spi_host.h +++ b/include/hw/ssi/ibex_spi_host.h @@ -28,7 +28,6 @@ #define IBEX_SPI_HOST_H #include "hw/sysbus.h" -#include "hw/hw.h" #include "hw/ssi/ssi.h" #include "qemu/fifo8.h" #include "qom/object.h" diff --git a/include/hw/tricore/tricore_testdevice.h b/include/hw/tricore/tricore_testdevice.h index 1e2b8942ac..8b4fe15f24 100644 --- a/include/hw/tricore/tricore_testdevice.h +++ b/include/hw/tricore/tricore_testdevice.h @@ -19,7 +19,6 @@ #define HW_TRICORE_TESTDEVICE_H #include "hw/sysbus.h" -#include "hw/hw.h" #define TYPE_TRICORE_TESTDEVICE "tricore_testdevice" #define TRICORE_TESTDEVICE(obj) \ From 4c8a2054e78780622f5d005a52e0bc000f87eb93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Mon, 13 Feb 2023 18:01:41 +0100 Subject: [PATCH 074/129] hw/vfio/ccw: Simplify using DEVICE() macro MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit QOM parenthood relationship is: VFIOCCWDevice -> S390CCWDevice -> CcwDevice -> DeviceState We can directly use the QOM DEVICE() macro to get the parent object. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Eric Farman Message-Id: <20230213170145.45666-3-philmd@linaro.org> Signed-off-by: Thomas Huth --- hw/vfio/ccw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/vfio/ccw.c b/hw/vfio/ccw.c index 0354737666..503de94ce1 100644 --- a/hw/vfio/ccw.c +++ b/hw/vfio/ccw.c @@ -618,7 +618,7 @@ static void vfio_ccw_get_device(VFIOGroup *group, VFIOCCWDevice *vcdev, vcdev->vdev.ops = &vfio_ccw_ops; vcdev->vdev.type = VFIO_DEVICE_TYPE_CCW; vcdev->vdev.name = name; - vcdev->vdev.dev = &vcdev->cdev.parent_obj.parent_obj; + vcdev->vdev.dev = DEVICE(vcdev); return; From 011da22c5c53910239e7c13394bdeca90c729b09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Mon, 13 Feb 2023 18:01:42 +0100 Subject: [PATCH 075/129] hw/vfio/ccw: Use intermediate S390CCWDevice variable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 'cdev' is VFIOCCWDevice's private parent object. Access it using the S390_CCW_DEVICE() QOM macro. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Eric Farman Message-Id: <20230213170145.45666-4-philmd@linaro.org> Signed-off-by: Thomas Huth --- hw/vfio/ccw.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/hw/vfio/ccw.c b/hw/vfio/ccw.c index 503de94ce1..2c20e3c202 100644 --- a/hw/vfio/ccw.c +++ b/hw/vfio/ccw.c @@ -588,9 +588,10 @@ static void vfio_ccw_put_device(VFIOCCWDevice *vcdev) static void vfio_ccw_get_device(VFIOGroup *group, VFIOCCWDevice *vcdev, Error **errp) { - char *name = g_strdup_printf("%x.%x.%04x", vcdev->cdev.hostid.cssid, - vcdev->cdev.hostid.ssid, - vcdev->cdev.hostid.devid); + S390CCWDevice *cdev = S390_CCW_DEVICE(vcdev); + char *name = g_strdup_printf("%x.%x.%04x", cdev->hostid.cssid, + cdev->hostid.ssid, + cdev->hostid.devid); VFIODevice *vbasedev; QLIST_FOREACH(vbasedev, &group->device_list, next) { @@ -611,7 +612,7 @@ static void vfio_ccw_get_device(VFIOGroup *group, VFIOCCWDevice *vcdev, */ vcdev->vdev.ram_block_discard_allowed = true; - if (vfio_get_device(group, vcdev->cdev.mdevid, &vcdev->vdev, errp)) { + if (vfio_get_device(group, cdev->mdevid, &vcdev->vdev, errp)) { goto out_err; } From 0cea1f62a872c22af362acab05beb947a1fdee77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Mon, 13 Feb 2023 18:01:43 +0100 Subject: [PATCH 076/129] hw/vfio/ccw: Replace DO_UPCAST(S390CCWDevice) by S390_CCW_DEVICE() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use the S390_CCW_DEVICE() QOM type-checking macro to avoid DO_UPCAST(). Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Thomas Huth Message-Id: <20230213170145.45666-5-philmd@linaro.org> Signed-off-by: Thomas Huth --- hw/vfio/ccw.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/hw/vfio/ccw.c b/hw/vfio/ccw.c index 2c20e3c202..2ea7b4a63c 100644 --- a/hw/vfio/ccw.c +++ b/hw/vfio/ccw.c @@ -251,8 +251,7 @@ again: static void vfio_ccw_reset(DeviceState *dev) { - CcwDevice *ccw_dev = DO_UPCAST(CcwDevice, parent_obj, dev); - S390CCWDevice *cdev = DO_UPCAST(S390CCWDevice, parent_obj, ccw_dev); + S390CCWDevice *cdev = S390_CCW_DEVICE(dev); VFIOCCWDevice *vcdev = DO_UPCAST(VFIOCCWDevice, cdev, cdev); ioctl(vcdev->vdev.fd, VFIO_DEVICE_RESET); @@ -657,8 +656,7 @@ static VFIOGroup *vfio_ccw_get_group(S390CCWDevice *cdev, Error **errp) static void vfio_ccw_realize(DeviceState *dev, Error **errp) { VFIOGroup *group; - CcwDevice *ccw_dev = DO_UPCAST(CcwDevice, parent_obj, dev); - S390CCWDevice *cdev = DO_UPCAST(S390CCWDevice, parent_obj, ccw_dev); + S390CCWDevice *cdev = S390_CCW_DEVICE(dev); VFIOCCWDevice *vcdev = DO_UPCAST(VFIOCCWDevice, cdev, cdev); S390CCWDeviceClass *cdc = S390_CCW_DEVICE_GET_CLASS(cdev); Error *err = NULL; @@ -729,8 +727,7 @@ out_err_propagate: 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); + S390CCWDevice *cdev = S390_CCW_DEVICE(dev); VFIOCCWDevice *vcdev = DO_UPCAST(VFIOCCWDevice, cdev, cdev); S390CCWDeviceClass *cdc = S390_CCW_DEVICE_GET_CLASS(cdev); VFIOGroup *group = vcdev->vdev.group; From 4b447883ede2d75960f2c02856e68710d6155268 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Mon, 13 Feb 2023 18:01:44 +0100 Subject: [PATCH 077/129] hw/vfio/ccw: Remove pointless S390CCWDevice variable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit QOM parenthood relationship is: VFIOCCWDevice -> S390CCWDevice -> CcwDevice -> DeviceState No need to double-cast, call CCW_DEVICE() on VFIOCCWDevice. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Eric Farman Message-Id: <20230213170145.45666-6-philmd@linaro.org> Signed-off-by: Thomas Huth --- hw/vfio/ccw.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/hw/vfio/ccw.c b/hw/vfio/ccw.c index 2ea7b4a63c..cd66b66742 100644 --- a/hw/vfio/ccw.c +++ b/hw/vfio/ccw.c @@ -314,8 +314,7 @@ static void vfio_ccw_io_notifier_handler(void *opaque) { VFIOCCWDevice *vcdev = opaque; struct ccw_io_region *region = vcdev->io_region; - S390CCWDevice *cdev = S390_CCW_DEVICE(vcdev); - CcwDevice *ccw_dev = CCW_DEVICE(cdev); + CcwDevice *ccw_dev = CCW_DEVICE(vcdev); SubchDev *sch = ccw_dev->sch; SCHIB *schib = &sch->curr_status; SCSW s; From ecba64689596614112b662d0579d097fa5cfd5d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Mon, 13 Feb 2023 18:01:45 +0100 Subject: [PATCH 078/129] hw/vfio/ccw: Replace DO_UPCAST(VFIOCCWDevice) by VFIO_CCW() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use the VFIO_CCW() QOM type-checking macro to avoid DO_UPCAST(). Reviewed-by: Eric Farman Signed-off-by: Philippe Mathieu-Daudé Message-Id: <20230213170145.45666-7-philmd@linaro.org> Signed-off-by: Thomas Huth --- hw/vfio/ccw.c | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/hw/vfio/ccw.c b/hw/vfio/ccw.c index cd66b66742..1e2fce83b0 100644 --- a/hw/vfio/ccw.c +++ b/hw/vfio/ccw.c @@ -76,8 +76,7 @@ struct VFIODeviceOps vfio_ccw_ops = { static IOInstEnding vfio_ccw_handle_request(SubchDev *sch) { - S390CCWDevice *cdev = sch->driver_data; - VFIOCCWDevice *vcdev = DO_UPCAST(VFIOCCWDevice, cdev, cdev); + VFIOCCWDevice *vcdev = VFIO_CCW(sch->driver_data); struct ccw_io_region *region = vcdev->io_region; int ret; @@ -125,8 +124,7 @@ again: static IOInstEnding vfio_ccw_handle_store(SubchDev *sch) { - S390CCWDevice *cdev = sch->driver_data; - VFIOCCWDevice *vcdev = DO_UPCAST(VFIOCCWDevice, cdev, cdev); + VFIOCCWDevice *vcdev = VFIO_CCW(sch->driver_data); SCHIB *schib = &sch->curr_status; struct ccw_schib_region *region = vcdev->schib_region; SCHIB *s; @@ -170,8 +168,7 @@ static IOInstEnding vfio_ccw_handle_store(SubchDev *sch) static int vfio_ccw_handle_clear(SubchDev *sch) { - S390CCWDevice *cdev = sch->driver_data; - VFIOCCWDevice *vcdev = DO_UPCAST(VFIOCCWDevice, cdev, cdev); + VFIOCCWDevice *vcdev = VFIO_CCW(sch->driver_data); struct ccw_cmd_region *region = vcdev->async_cmd_region; int ret; @@ -210,8 +207,7 @@ again: static int vfio_ccw_handle_halt(SubchDev *sch) { - S390CCWDevice *cdev = sch->driver_data; - VFIOCCWDevice *vcdev = DO_UPCAST(VFIOCCWDevice, cdev, cdev); + VFIOCCWDevice *vcdev = VFIO_CCW(sch->driver_data); struct ccw_cmd_region *region = vcdev->async_cmd_region; int ret; @@ -251,8 +247,7 @@ again: static void vfio_ccw_reset(DeviceState *dev) { - S390CCWDevice *cdev = S390_CCW_DEVICE(dev); - VFIOCCWDevice *vcdev = DO_UPCAST(VFIOCCWDevice, cdev, cdev); + VFIOCCWDevice *vcdev = VFIO_CCW(dev); ioctl(vcdev->vdev.fd, VFIO_DEVICE_RESET); } @@ -656,7 +651,7 @@ static void vfio_ccw_realize(DeviceState *dev, Error **errp) { VFIOGroup *group; S390CCWDevice *cdev = S390_CCW_DEVICE(dev); - VFIOCCWDevice *vcdev = DO_UPCAST(VFIOCCWDevice, cdev, cdev); + VFIOCCWDevice *vcdev = VFIO_CCW(cdev); S390CCWDeviceClass *cdc = S390_CCW_DEVICE_GET_CLASS(cdev); Error *err = NULL; @@ -727,7 +722,7 @@ out_err_propagate: static void vfio_ccw_unrealize(DeviceState *dev) { S390CCWDevice *cdev = S390_CCW_DEVICE(dev); - VFIOCCWDevice *vcdev = DO_UPCAST(VFIOCCWDevice, cdev, cdev); + VFIOCCWDevice *vcdev = VFIO_CCW(cdev); S390CCWDeviceClass *cdc = S390_CCW_DEVICE_GET_CLASS(cdev); VFIOGroup *group = vcdev->vdev.group; From eb60026120081430d554c9cabaa36c4ac271fce0 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Tue, 14 Feb 2023 15:10:56 +0100 Subject: [PATCH 079/129] target/s390x/arch_dump: Fix memory corruption in s390x_write_elf64_notes() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit "note_size" can be smaller than sizeof(note), so unconditionally calling memset(notep, 0, sizeof(note)) could cause a memory corruption here in case notep has been allocated dynamically, thus let's use note_size as length argument for memset() instead. Reported-by: Sebastian Mitterle Fixes: 113d8f4e95 ("s390x: pv: Add dump support") Message-Id: <20230214141056.680969-1-thuth@redhat.com> Reviewed-by: Janosch Frank Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Thomas Huth --- target/s390x/arch_dump.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/s390x/arch_dump.c b/target/s390x/arch_dump.c index a2329141e8..a7c44ba49d 100644 --- a/target/s390x/arch_dump.c +++ b/target/s390x/arch_dump.c @@ -248,7 +248,7 @@ static int s390x_write_elf64_notes(const char *note_name, notep = g_malloc(note_size); } - memset(notep, 0, sizeof(note)); + memset(notep, 0, note_size); /* Setup note header data */ notep->hdr.n_descsz = cpu_to_be32(content_size); From 4376a770c719f480dd6fad130db8eceeda8cdcb7 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Wed, 15 Feb 2023 09:57:03 +0100 Subject: [PATCH 080/129] target/s390x/arch_dump: Simplify memory allocation in s390x_write_elf64_notes() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We are not on a hot path here, so there is no real need for the logic here with the split heap and stack space allocation. Simplify it by always allocating memory from the heap. Suggested-by: Philippe Mathieu-Daudé Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20230215085703.746788-1-thuth@redhat.com> Signed-off-by: Thomas Huth --- target/s390x/arch_dump.c | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/target/s390x/arch_dump.c b/target/s390x/arch_dump.c index a7c44ba49d..cb98f4894d 100644 --- a/target/s390x/arch_dump.c +++ b/target/s390x/arch_dump.c @@ -227,25 +227,25 @@ static int s390x_write_elf64_notes(const char *note_name, DumpState *s, const NoteFuncDesc *funcs) { - Note note, *notep; + g_autofree Note *notep = NULL; const NoteFuncDesc *nf; - int note_size, content_size; + int note_size, prev_size = 0, content_size; int ret = -1; - assert(strlen(note_name) < sizeof(note.name)); + assert(strlen(note_name) < sizeof(notep->name)); for (nf = funcs; nf->note_contents_func; nf++) { - notep = ¬e; if (nf->pvonly && !s390_is_pv()) { continue; } content_size = nf->note_size_func ? nf->note_size_func() : nf->contents_size; - note_size = sizeof(note) - sizeof(notep->contents) + content_size; + note_size = sizeof(Note) - sizeof(notep->contents) + content_size; - /* Notes with dynamic sizes need to allocate a note */ - if (nf->note_size_func) { + if (prev_size < note_size) { + g_free(notep); notep = g_malloc(note_size); + prev_size = note_size; } memset(notep, 0, note_size); @@ -258,15 +258,9 @@ static int s390x_write_elf64_notes(const char *note_name, /* Get contents and write them out */ (*nf->note_contents_func)(notep, cpu, id); ret = f(notep, note_size, s); - - if (nf->note_size_func) { - g_free(notep); - } - if (ret < 0) { return -1; } - } return 0; From 40494314789ba87dc118b91e8a8964a99809a5fb Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 9 Jan 2023 12:18:50 -0800 Subject: [PATCH 081/129] target/s390x: Fix s390_probe_access for user-only In db9aab5783a2 we broke the contract of s390_probe_access, in that it no longer returned an exception code, nor set __excp_addr. Fix both. Reported-by: David Hildenbrand Signed-off-by: Richard Henderson Reviewed-by: David Hildenbrand Message-Id: <20230109201856.3916639-2-richard.henderson@linaro.org> Signed-off-by: Thomas Huth --- target/s390x/tcg/mem_helper.c | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/target/s390x/tcg/mem_helper.c b/target/s390x/tcg/mem_helper.c index d6725fd18c..9a6dce4cda 100644 --- a/target/s390x/tcg/mem_helper.c +++ b/target/s390x/tcg/mem_helper.c @@ -138,23 +138,27 @@ typedef struct S390Access { * For !CONFIG_USER_ONLY, the TEC is stored stored to env->tlb_fill_tec. * For CONFIG_USER_ONLY, the faulting address is stored to env->__excp_addr. */ -static int s390_probe_access(CPUArchState *env, target_ulong addr, int size, - MMUAccessType access_type, int mmu_idx, - bool nonfault, void **phost, uintptr_t ra) +static inline int s390_probe_access(CPUArchState *env, target_ulong addr, + int size, MMUAccessType access_type, + int mmu_idx, bool nonfault, + void **phost, uintptr_t ra) { -#if defined(CONFIG_USER_ONLY) - return probe_access_flags(env, addr, access_type, mmu_idx, - nonfault, phost, ra); -#else - int flags; + int flags = probe_access_flags(env, addr, access_type, mmu_idx, + nonfault, phost, ra); - env->tlb_fill_exc = 0; - flags = probe_access_flags(env, addr, access_type, mmu_idx, nonfault, phost, - ra); - if (env->tlb_fill_exc) { + if (unlikely(flags & TLB_INVALID_MASK)) { + assert(!nonfault); +#ifdef CONFIG_USER_ONLY + /* Address is in TEC in system mode; see s390_cpu_record_sigsegv. */ + env->__excp_addr = addr & TARGET_PAGE_MASK; + return (page_get_flags(addr) & PAGE_VALID + ? PGM_PROTECTION : PGM_ADDRESSING); +#else return env->tlb_fill_exc; +#endif } +#ifndef CONFIG_USER_ONLY if (unlikely(flags & TLB_WATCHPOINT)) { /* S390 does not presently use transaction attributes. */ cpu_check_watchpoint(env_cpu(env), addr, size, @@ -162,8 +166,9 @@ static int s390_probe_access(CPUArchState *env, target_ulong addr, int size, (access_type == MMU_DATA_STORE ? BP_MEM_WRITE : BP_MEM_READ), ra); } - return 0; #endif + + return 0; } static int access_prepare_nf(S390Access *access, CPUS390XState *env, From 7ba5da818a73048a9a2e4949bb971708b2f4259c Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 9 Jan 2023 12:18:51 -0800 Subject: [PATCH 082/129] target/s390x: Pass S390Access pointer into access_prepare Passing a pointer from the caller down to access_prepare_nf eliminates a structure copy. Signed-off-by: Richard Henderson Reviewed-by: David Hildenbrand Message-Id: <20230109201856.3916639-3-richard.henderson@linaro.org> Signed-off-by: Thomas Huth --- target/s390x/tcg/mem_helper.c | 100 +++++++++++++++++----------------- 1 file changed, 50 insertions(+), 50 deletions(-) diff --git a/target/s390x/tcg/mem_helper.c b/target/s390x/tcg/mem_helper.c index 9a6dce4cda..28bf3bd53c 100644 --- a/target/s390x/tcg/mem_helper.c +++ b/target/s390x/tcg/mem_helper.c @@ -212,15 +212,14 @@ static int access_prepare_nf(S390Access *access, CPUS390XState *env, return 0; } -static S390Access access_prepare(CPUS390XState *env, vaddr vaddr, int size, - MMUAccessType access_type, int mmu_idx, - uintptr_t ra) +static inline void access_prepare(S390Access *ret, CPUS390XState *env, + vaddr vaddr, int size, + MMUAccessType access_type, int mmu_idx, + uintptr_t ra) { - S390Access ret; - int exc = access_prepare_nf(&ret, env, false, vaddr, size, + int exc = access_prepare_nf(ret, env, false, vaddr, size, access_type, mmu_idx, ra); assert(!exc); - return ret; } /* Helper to handle memset on a single page. */ @@ -412,9 +411,9 @@ static uint32_t do_helper_nc(CPUS390XState *env, uint32_t l, uint64_t dest, /* NC always processes one more byte than specified - maximum is 256 */ l++; - srca1 = access_prepare(env, src, l, MMU_DATA_LOAD, mmu_idx, ra); - srca2 = access_prepare(env, dest, l, MMU_DATA_LOAD, mmu_idx, ra); - desta = access_prepare(env, dest, l, MMU_DATA_STORE, mmu_idx, ra); + access_prepare(&srca1, env, src, l, MMU_DATA_LOAD, mmu_idx, ra); + access_prepare(&srca2, env, dest, l, MMU_DATA_LOAD, mmu_idx, ra); + access_prepare(&desta, env, dest, l, MMU_DATA_STORE, mmu_idx, ra); for (i = 0; i < l; i++) { const uint8_t x = access_get_byte(env, &srca1, i, ra) & access_get_byte(env, &srca2, i, ra); @@ -446,9 +445,9 @@ static uint32_t do_helper_xc(CPUS390XState *env, uint32_t l, uint64_t dest, /* XC always processes one more byte than specified - maximum is 256 */ l++; - srca1 = access_prepare(env, src, l, MMU_DATA_LOAD, mmu_idx, ra); - srca2 = access_prepare(env, dest, l, MMU_DATA_LOAD, mmu_idx, ra); - desta = access_prepare(env, dest, l, MMU_DATA_STORE, mmu_idx, ra); + access_prepare(&srca1, env, src, l, MMU_DATA_LOAD, mmu_idx, ra); + access_prepare(&srca2, env, dest, l, MMU_DATA_LOAD, mmu_idx, ra); + access_prepare(&desta, env, dest, l, MMU_DATA_STORE, mmu_idx, ra); /* xor with itself is the same as memset(0) */ if (src == dest) { @@ -487,9 +486,9 @@ static uint32_t do_helper_oc(CPUS390XState *env, uint32_t l, uint64_t dest, /* OC always processes one more byte than specified - maximum is 256 */ l++; - srca1 = access_prepare(env, src, l, MMU_DATA_LOAD, mmu_idx, ra); - srca2 = access_prepare(env, dest, l, MMU_DATA_LOAD, mmu_idx, ra); - desta = access_prepare(env, dest, l, MMU_DATA_STORE, mmu_idx, ra); + access_prepare(&srca1, env, src, l, MMU_DATA_LOAD, mmu_idx, ra); + access_prepare(&srca2, env, dest, l, MMU_DATA_LOAD, mmu_idx, ra); + access_prepare(&desta, env, dest, l, MMU_DATA_STORE, mmu_idx, ra); for (i = 0; i < l; i++) { const uint8_t x = access_get_byte(env, &srca1, i, ra) | access_get_byte(env, &srca2, i, ra); @@ -520,8 +519,8 @@ static uint32_t do_helper_mvc(CPUS390XState *env, uint32_t l, uint64_t dest, /* MVC always copies one more byte than specified - maximum is 256 */ l++; - srca = access_prepare(env, src, l, MMU_DATA_LOAD, mmu_idx, ra); - desta = access_prepare(env, dest, l, MMU_DATA_STORE, mmu_idx, ra); + access_prepare(&srca, env, src, l, MMU_DATA_LOAD, mmu_idx, ra); + access_prepare(&desta, env, dest, l, MMU_DATA_STORE, mmu_idx, ra); /* * "When the operands overlap, the result is obtained as if the operands @@ -559,8 +558,8 @@ void HELPER(mvcrl)(CPUS390XState *env, uint64_t l, uint64_t dest, uint64_t src) /* MVCRL always copies one more byte than specified - maximum is 256 */ l++; - srca = access_prepare(env, src, l, MMU_DATA_LOAD, mmu_idx, ra); - desta = access_prepare(env, dest, l, MMU_DATA_STORE, mmu_idx, ra); + access_prepare(&srca, env, src, l, MMU_DATA_LOAD, mmu_idx, ra); + access_prepare(&desta, env, dest, l, MMU_DATA_STORE, mmu_idx, ra); for (i = l - 1; i >= 0; i--) { uint8_t byte = access_get_byte(env, &srca, i, ra); @@ -580,8 +579,8 @@ void HELPER(mvcin)(CPUS390XState *env, uint32_t l, uint64_t dest, uint64_t src) l++; src = wrap_address(env, src - l + 1); - srca = access_prepare(env, src, l, MMU_DATA_LOAD, mmu_idx, ra); - desta = access_prepare(env, dest, l, MMU_DATA_STORE, mmu_idx, ra); + access_prepare(&srca, env, src, l, MMU_DATA_LOAD, mmu_idx, ra); + access_prepare(&desta, env, dest, l, MMU_DATA_STORE, mmu_idx, ra); for (i = 0; i < l; i++) { const uint8_t x = access_get_byte(env, &srca, l - i - 1, ra); @@ -600,9 +599,9 @@ void HELPER(mvn)(CPUS390XState *env, uint32_t l, uint64_t dest, uint64_t src) /* MVN always copies one more byte than specified - maximum is 256 */ l++; - srca1 = access_prepare(env, src, l, MMU_DATA_LOAD, mmu_idx, ra); - srca2 = access_prepare(env, dest, l, MMU_DATA_LOAD, mmu_idx, ra); - desta = access_prepare(env, dest, l, MMU_DATA_STORE, mmu_idx, ra); + access_prepare(&srca1, env, src, l, MMU_DATA_LOAD, mmu_idx, ra); + access_prepare(&srca2, env, dest, l, MMU_DATA_LOAD, mmu_idx, ra); + access_prepare(&desta, env, dest, l, MMU_DATA_STORE, mmu_idx, ra); for (i = 0; i < l; i++) { const uint8_t x = (access_get_byte(env, &srca1, i, ra) & 0x0f) | (access_get_byte(env, &srca2, i, ra) & 0xf0); @@ -623,8 +622,8 @@ void HELPER(mvo)(CPUS390XState *env, uint32_t l, uint64_t dest, uint64_t src) S390Access srca, desta; int i, j; - srca = access_prepare(env, src, len_src, MMU_DATA_LOAD, mmu_idx, ra); - desta = access_prepare(env, dest, len_dest, MMU_DATA_STORE, mmu_idx, ra); + access_prepare(&srca, env, src, len_src, MMU_DATA_LOAD, mmu_idx, ra); + access_prepare(&desta, env, dest, len_dest, MMU_DATA_STORE, mmu_idx, ra); /* Handle rightmost byte */ byte_dest = cpu_ldub_data_ra(env, dest + len_dest - 1, ra); @@ -656,9 +655,9 @@ void HELPER(mvz)(CPUS390XState *env, uint32_t l, uint64_t dest, uint64_t src) /* MVZ always copies one more byte than specified - maximum is 256 */ l++; - srca1 = access_prepare(env, src, l, MMU_DATA_LOAD, mmu_idx, ra); - srca2 = access_prepare(env, dest, l, MMU_DATA_LOAD, mmu_idx, ra); - desta = access_prepare(env, dest, l, MMU_DATA_STORE, mmu_idx, ra); + access_prepare(&srca1, env, src, l, MMU_DATA_LOAD, mmu_idx, ra); + access_prepare(&srca2, env, dest, l, MMU_DATA_LOAD, mmu_idx, ra); + access_prepare(&desta, env, dest, l, MMU_DATA_STORE, mmu_idx, ra); for (i = 0; i < l; i++) { const uint8_t x = (access_get_byte(env, &srca1, i, ra) & 0xf0) | (access_get_byte(env, &srca2, i, ra) & 0x0f); @@ -1002,8 +1001,8 @@ uint32_t HELPER(mvst)(CPUS390XState *env, uint32_t r1, uint32_t r2) * this point). We might over-indicate watchpoints within the pages * (if we ever care, we have to limit processing to a single byte). */ - srca = access_prepare(env, s, len, MMU_DATA_LOAD, mmu_idx, ra); - desta = access_prepare(env, d, len, MMU_DATA_STORE, mmu_idx, ra); + access_prepare(&srca, env, s, len, MMU_DATA_LOAD, mmu_idx, ra); + access_prepare(&desta, env, d, len, MMU_DATA_STORE, mmu_idx, ra); for (i = 0; i < len; i++) { const uint8_t v = access_get_byte(env, &srca, i, ra); @@ -1090,19 +1089,19 @@ static inline uint32_t do_mvcl(CPUS390XState *env, len = MIN(MIN(*srclen, -(*src | TARGET_PAGE_MASK)), len); *destlen -= len; *srclen -= len; - srca = access_prepare(env, *src, len, MMU_DATA_LOAD, mmu_idx, ra); - desta = access_prepare(env, *dest, len, MMU_DATA_STORE, mmu_idx, ra); + access_prepare(&srca, env, *src, len, MMU_DATA_LOAD, mmu_idx, ra); + access_prepare(&desta, env, *dest, len, MMU_DATA_STORE, mmu_idx, ra); access_memmove(env, &desta, &srca, ra); *src = wrap_address(env, *src + len); *dest = wrap_address(env, *dest + len); } else if (wordsize == 1) { /* Pad the remaining area */ *destlen -= len; - desta = access_prepare(env, *dest, len, MMU_DATA_STORE, mmu_idx, ra); + access_prepare(&desta, env, *dest, len, MMU_DATA_STORE, mmu_idx, ra); access_memset(env, &desta, pad, ra); *dest = wrap_address(env, *dest + len); } else { - desta = access_prepare(env, *dest, len, MMU_DATA_STORE, mmu_idx, ra); + access_prepare(&desta, env, *dest, len, MMU_DATA_STORE, mmu_idx, ra); /* The remaining length selects the padding byte. */ for (i = 0; i < len; (*destlen)--, i++) { @@ -1158,16 +1157,16 @@ uint32_t HELPER(mvcl)(CPUS390XState *env, uint32_t r1, uint32_t r2) while (destlen) { cur_len = MIN(destlen, -(dest | TARGET_PAGE_MASK)); if (!srclen) { - desta = access_prepare(env, dest, cur_len, MMU_DATA_STORE, mmu_idx, - ra); + access_prepare(&desta, env, dest, cur_len, + MMU_DATA_STORE, mmu_idx, ra); access_memset(env, &desta, pad, ra); } else { cur_len = MIN(MIN(srclen, -(src | TARGET_PAGE_MASK)), cur_len); - srca = access_prepare(env, src, cur_len, MMU_DATA_LOAD, mmu_idx, - ra); - desta = access_prepare(env, dest, cur_len, MMU_DATA_STORE, mmu_idx, - ra); + access_prepare(&srca, env, src, cur_len, + MMU_DATA_LOAD, mmu_idx, ra); + access_prepare(&desta, env, dest, cur_len, + MMU_DATA_STORE, mmu_idx, ra); access_memmove(env, &desta, &srca, ra); src = wrap_address(env, src + cur_len); srclen -= cur_len; @@ -2272,8 +2271,8 @@ uint32_t HELPER(mvcs)(CPUS390XState *env, uint64_t l, uint64_t a1, uint64_t a2, return cc; } - srca = access_prepare(env, a2, l, MMU_DATA_LOAD, MMU_PRIMARY_IDX, ra); - desta = access_prepare(env, a1, l, MMU_DATA_STORE, MMU_SECONDARY_IDX, ra); + access_prepare(&srca, env, a2, l, MMU_DATA_LOAD, MMU_PRIMARY_IDX, ra); + access_prepare(&desta, env, a1, l, MMU_DATA_STORE, MMU_SECONDARY_IDX, ra); access_memmove(env, &desta, &srca, ra); return cc; } @@ -2306,9 +2305,8 @@ uint32_t HELPER(mvcp)(CPUS390XState *env, uint64_t l, uint64_t a1, uint64_t a2, } else if (!l) { return cc; } - - srca = access_prepare(env, a2, l, MMU_DATA_LOAD, MMU_SECONDARY_IDX, ra); - desta = access_prepare(env, a1, l, MMU_DATA_STORE, MMU_PRIMARY_IDX, ra); + access_prepare(&srca, env, a2, l, MMU_DATA_LOAD, MMU_SECONDARY_IDX, ra); + access_prepare(&desta, env, a1, l, MMU_DATA_STORE, MMU_PRIMARY_IDX, ra); access_memmove(env, &desta, &srca, ra); return cc; } @@ -2649,10 +2647,12 @@ uint32_t HELPER(mvcos)(CPUS390XState *env, uint64_t dest, uint64_t src, /* FIXME: Access using correct keys and AR-mode */ if (len) { - S390Access srca = access_prepare(env, src, len, MMU_DATA_LOAD, - mmu_idx_from_as(src_as), ra); - S390Access desta = access_prepare(env, dest, len, MMU_DATA_STORE, - mmu_idx_from_as(dest_as), ra); + S390Access srca, desta; + + access_prepare(&srca, env, src, len, MMU_DATA_LOAD, + mmu_idx_from_as(src_as), ra); + access_prepare(&desta, env, dest, len, MMU_DATA_STORE, + mmu_idx_from_as(dest_as), ra); access_memmove(env, &desta, &srca, ra); } From bebc8ade7014ca1f8afbc9d1bd297460f2e88461 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 9 Jan 2023 12:18:52 -0800 Subject: [PATCH 083/129] target/s390x: Use void* for haddr in S390Access The interface from probe_access_flags is void*, and matching that will be helpful. We already rely on the gcc extension for byte arithmetic on void*. Signed-off-by: Richard Henderson Reviewed-by: David Hildenbrand Message-Id: <20230109201856.3916639-4-richard.henderson@linaro.org> Signed-off-by: Thomas Huth --- target/s390x/tcg/mem_helper.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/target/s390x/tcg/mem_helper.c b/target/s390x/tcg/mem_helper.c index 28bf3bd53c..4d157ba9cf 100644 --- a/target/s390x/tcg/mem_helper.c +++ b/target/s390x/tcg/mem_helper.c @@ -114,8 +114,8 @@ static inline void cpu_stsize_data_ra(CPUS390XState *env, uint64_t addr, typedef struct S390Access { target_ulong vaddr1; target_ulong vaddr2; - char *haddr1; - char *haddr2; + void *haddr1; + void *haddr2; uint16_t size1; uint16_t size2; /* @@ -268,8 +268,9 @@ static void access_memset(CPUS390XState *env, S390Access *desta, desta->mmu_idx, ra); } -static uint8_t do_access_get_byte(CPUS390XState *env, vaddr vaddr, char **haddr, - int offset, int mmu_idx, uintptr_t ra) +static uint8_t do_access_get_byte(CPUS390XState *env, vaddr vaddr, + void **haddr, int offset, + int mmu_idx, uintptr_t ra) { #ifdef CONFIG_USER_ONLY return ldub_p(*haddr + offset); @@ -301,7 +302,7 @@ static uint8_t access_get_byte(CPUS390XState *env, S390Access *access, offset - access->size1, access->mmu_idx, ra); } -static void do_access_set_byte(CPUS390XState *env, vaddr vaddr, char **haddr, +static void do_access_set_byte(CPUS390XState *env, vaddr vaddr, void **haddr, int offset, uint8_t byte, int mmu_idx, uintptr_t ra) { From fb391b0b474c316d841f5e27fd094832a91f77f4 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 9 Jan 2023 12:18:53 -0800 Subject: [PATCH 084/129] target/s390x: Tidy access_prepare_nf Assign to access struct immediately, rather than waiting until the end of the function. This means we can pass address of haddr struct members instead of allocating extra space on the local stack. Signed-off-by: Richard Henderson Reviewed-by: David Hildenbrand Message-Id: <20230109201856.3916639-5-richard.henderson@linaro.org> Signed-off-by: Thomas Huth --- target/s390x/tcg/mem_helper.c | 30 +++++++++++++----------------- 1 file changed, 13 insertions(+), 17 deletions(-) diff --git a/target/s390x/tcg/mem_helper.c b/target/s390x/tcg/mem_helper.c index 4d157ba9cf..dc9b5ff088 100644 --- a/target/s390x/tcg/mem_helper.c +++ b/target/s390x/tcg/mem_helper.c @@ -176,39 +176,35 @@ static int access_prepare_nf(S390Access *access, CPUS390XState *env, MMUAccessType access_type, int mmu_idx, uintptr_t ra) { - void *haddr1, *haddr2 = NULL; int size1, size2, exc; - vaddr vaddr2 = 0; assert(size > 0 && size <= 4096); size1 = MIN(size, -(vaddr1 | TARGET_PAGE_MASK)), size2 = size - size1; + memset(access, 0, sizeof(*access)); + access->vaddr1 = vaddr1; + access->size1 = size1; + access->size2 = size2; + access->mmu_idx = mmu_idx; + exc = s390_probe_access(env, vaddr1, size1, access_type, mmu_idx, nonfault, - &haddr1, ra); - if (exc) { + &access->haddr1, ra); + if (unlikely(exc)) { return exc; } if (unlikely(size2)) { /* The access crosses page boundaries. */ - vaddr2 = wrap_address(env, vaddr1 + size1); + vaddr vaddr2 = wrap_address(env, vaddr1 + size1); + + access->vaddr2 = vaddr2; exc = s390_probe_access(env, vaddr2, size2, access_type, mmu_idx, - nonfault, &haddr2, ra); - if (exc) { + nonfault, &access->haddr2, ra); + if (unlikely(exc)) { return exc; } } - - *access = (S390Access) { - .vaddr1 = vaddr1, - .vaddr2 = vaddr2, - .haddr1 = haddr1, - .haddr2 = haddr2, - .size1 = size1, - .size2 = size2, - .mmu_idx = mmu_idx - }; return 0; } From 96b1416fda52cb37eaa6d2316d9946b1078c6210 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 9 Jan 2023 12:18:54 -0800 Subject: [PATCH 085/129] target/s390x: Remove TLB_NOTDIRTY workarounds When this code was written, it was using tlb_vaddr_to_host, which does not handle TLB_DIRTY. Since then, it has been converted to probe_access_flags, which does. Signed-off-by: Richard Henderson Acked-by: David Hildenbrand Message-Id: <20230109201856.3916639-6-richard.henderson@linaro.org> Signed-off-by: Thomas Huth --- target/s390x/tcg/mem_helper.c | 74 +++++++++++------------------------ 1 file changed, 22 insertions(+), 52 deletions(-) diff --git a/target/s390x/tcg/mem_helper.c b/target/s390x/tcg/mem_helper.c index dc9b5ff088..e9d54b1dd5 100644 --- a/target/s390x/tcg/mem_helper.c +++ b/target/s390x/tcg/mem_helper.c @@ -122,11 +122,7 @@ typedef struct S390Access { * If we can't access the host page directly, we'll have to do I/O access * via ld/st helpers. These are internal details, so we store the * mmu idx to do the access here instead of passing it around in the - * helpers. Maybe, one day we can get rid of ld/st access - once we can - * handle TLB_NOTDIRTY differently. We don't expect these special accesses - * to trigger exceptions - only if we would have TLB_NOTDIRTY on LAP - * pages, we might trigger a new MMU translation - very unlikely that - * the mapping changes in between and we would trigger a fault. + * helpers. */ int mmu_idx; } S390Access; @@ -224,28 +220,14 @@ static void do_access_memset(CPUS390XState *env, vaddr vaddr, char *haddr, uintptr_t ra) { #ifdef CONFIG_USER_ONLY - g_assert(haddr); memset(haddr, byte, size); #else - MemOpIdx oi = make_memop_idx(MO_UB, mmu_idx); - int i; - if (likely(haddr)) { memset(haddr, byte, size); } else { - /* - * Do a single access and test if we can then get access to the - * page. This is especially relevant to speed up TLB_NOTDIRTY. - */ - g_assert(size > 0); - cpu_stb_mmu(env, vaddr, byte, oi, ra); - haddr = tlb_vaddr_to_host(env, vaddr, MMU_DATA_STORE, mmu_idx); - if (likely(haddr)) { - memset(haddr + 1, byte, size - 1); - } else { - for (i = 1; i < size; i++) { - cpu_stb_mmu(env, vaddr + i, byte, oi, ra); - } + MemOpIdx oi = make_memop_idx(MO_UB, mmu_idx); + for (int i = 0; i < size; i++) { + cpu_stb_mmu(env, vaddr + i, byte, oi, ra); } } #endif @@ -265,25 +247,18 @@ static void access_memset(CPUS390XState *env, S390Access *desta, } static uint8_t do_access_get_byte(CPUS390XState *env, vaddr vaddr, - void **haddr, int offset, + void *haddr, int offset, int mmu_idx, uintptr_t ra) { #ifdef CONFIG_USER_ONLY - return ldub_p(*haddr + offset); + return ldub_p(haddr + offset); #else - MemOpIdx oi = make_memop_idx(MO_UB, mmu_idx); - uint8_t byte; - - if (likely(*haddr)) { - return ldub_p(*haddr + offset); + if (likely(haddr)) { + return ldub_p(haddr + offset); + } else { + MemOpIdx oi = make_memop_idx(MO_UB, mmu_idx); + return cpu_ldb_mmu(env, vaddr + offset, oi, ra); } - /* - * Do a single access and test if we can then get access to the - * page. This is especially relevant to speed up TLB_NOTDIRTY. - */ - byte = cpu_ldb_mmu(env, vaddr + offset, oi, ra); - *haddr = tlb_vaddr_to_host(env, vaddr, MMU_DATA_LOAD, mmu_idx); - return byte; #endif } @@ -291,32 +266,27 @@ static uint8_t access_get_byte(CPUS390XState *env, S390Access *access, int offset, uintptr_t ra) { if (offset < access->size1) { - return do_access_get_byte(env, access->vaddr1, &access->haddr1, + return do_access_get_byte(env, access->vaddr1, access->haddr1, offset, access->mmu_idx, ra); } - return do_access_get_byte(env, access->vaddr2, &access->haddr2, + return do_access_get_byte(env, access->vaddr2, access->haddr2, offset - access->size1, access->mmu_idx, ra); } -static void do_access_set_byte(CPUS390XState *env, vaddr vaddr, void **haddr, +static void do_access_set_byte(CPUS390XState *env, vaddr vaddr, void *haddr, int offset, uint8_t byte, int mmu_idx, uintptr_t ra) { #ifdef CONFIG_USER_ONLY - stb_p(*haddr + offset, byte); + stb_p(haddr + offset, byte); #else - MemOpIdx oi = make_memop_idx(MO_UB, mmu_idx); - if (likely(*haddr)) { - stb_p(*haddr + offset, byte); - return; + if (likely(haddr)) { + stb_p(haddr + offset, byte); + } else { + MemOpIdx oi = make_memop_idx(MO_UB, mmu_idx); + cpu_stb_mmu(env, vaddr + offset, byte, oi, ra); } - /* - * Do a single access and test if we can then get access to the - * page. This is especially relevant to speed up TLB_NOTDIRTY. - */ - cpu_stb_mmu(env, vaddr + offset, byte, oi, ra); - *haddr = tlb_vaddr_to_host(env, vaddr, MMU_DATA_STORE, mmu_idx); #endif } @@ -324,10 +294,10 @@ static void access_set_byte(CPUS390XState *env, S390Access *access, int offset, uint8_t byte, uintptr_t ra) { if (offset < access->size1) { - do_access_set_byte(env, access->vaddr1, &access->haddr1, offset, byte, + do_access_set_byte(env, access->vaddr1, access->haddr1, offset, byte, access->mmu_idx, ra); } else { - do_access_set_byte(env, access->vaddr2, &access->haddr2, + do_access_set_byte(env, access->vaddr2, access->haddr2, offset - access->size1, byte, access->mmu_idx, ra); } } From 61dee10ff00720e6e056824b4548c914632ef6fe Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 9 Jan 2023 12:18:55 -0800 Subject: [PATCH 086/129] target/s390x: Inline do_access_{get,set}_byte Inline into the parent functions with a simple test to select the page, and a new define to remove ifdefs. Signed-off-by: Richard Henderson Reviewed-by: David Hildenbrand Message-Id: <20230109201856.3916639-7-richard.henderson@linaro.org> Signed-off-by: Thomas Huth --- target/s390x/tcg/mem_helper.c | 70 +++++++++++++++-------------------- 1 file changed, 30 insertions(+), 40 deletions(-) diff --git a/target/s390x/tcg/mem_helper.c b/target/s390x/tcg/mem_helper.c index e9d54b1dd5..f28126fde6 100644 --- a/target/s390x/tcg/mem_helper.c +++ b/target/s390x/tcg/mem_helper.c @@ -35,6 +35,12 @@ #include "hw/boards.h" #endif +#ifdef CONFIG_USER_ONLY +# define user_or_likely(X) true +#else +# define user_or_likely(X) likely(X) +#endif + /*****************************************************************************/ /* Softmmu support */ @@ -246,59 +252,43 @@ static void access_memset(CPUS390XState *env, S390Access *desta, desta->mmu_idx, ra); } -static uint8_t do_access_get_byte(CPUS390XState *env, vaddr vaddr, - void *haddr, int offset, - int mmu_idx, uintptr_t ra) -{ -#ifdef CONFIG_USER_ONLY - return ldub_p(haddr + offset); -#else - if (likely(haddr)) { - return ldub_p(haddr + offset); - } else { - MemOpIdx oi = make_memop_idx(MO_UB, mmu_idx); - return cpu_ldb_mmu(env, vaddr + offset, oi, ra); - } -#endif -} - static uint8_t access_get_byte(CPUS390XState *env, S390Access *access, int offset, uintptr_t ra) { - if (offset < access->size1) { - return do_access_get_byte(env, access->vaddr1, access->haddr1, - offset, access->mmu_idx, ra); + target_ulong vaddr = access->vaddr1; + void *haddr = access->haddr1; + + if (unlikely(offset >= access->size1)) { + offset -= access->size1; + vaddr = access->vaddr2; + haddr = access->haddr2; } - return do_access_get_byte(env, access->vaddr2, access->haddr2, - offset - access->size1, access->mmu_idx, ra); -} -static void do_access_set_byte(CPUS390XState *env, vaddr vaddr, void *haddr, - int offset, uint8_t byte, int mmu_idx, - uintptr_t ra) -{ -#ifdef CONFIG_USER_ONLY - stb_p(haddr + offset, byte); -#else - - if (likely(haddr)) { - stb_p(haddr + offset, byte); + if (user_or_likely(haddr)) { + return ldub_p(haddr + offset); } else { - MemOpIdx oi = make_memop_idx(MO_UB, mmu_idx); - cpu_stb_mmu(env, vaddr + offset, byte, oi, ra); + MemOpIdx oi = make_memop_idx(MO_UB, access->mmu_idx); + return cpu_ldb_mmu(env, vaddr + offset, oi, ra); } -#endif } static void access_set_byte(CPUS390XState *env, S390Access *access, int offset, uint8_t byte, uintptr_t ra) { - if (offset < access->size1) { - do_access_set_byte(env, access->vaddr1, access->haddr1, offset, byte, - access->mmu_idx, ra); + target_ulong vaddr = access->vaddr1; + void *haddr = access->haddr1; + + if (unlikely(offset >= access->size1)) { + offset -= access->size1; + vaddr = access->vaddr2; + haddr = access->haddr2; + } + + if (user_or_likely(haddr)) { + stb_p(haddr + offset, byte); } else { - do_access_set_byte(env, access->vaddr2, access->haddr2, - offset - access->size1, byte, access->mmu_idx, ra); + MemOpIdx oi = make_memop_idx(MO_UB, access->mmu_idx); + cpu_stb_mmu(env, vaddr + offset, byte, oi, ra); } } From e73a0f4075a78de9a62beeddb41c54a4090e0777 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 9 Jan 2023 12:18:56 -0800 Subject: [PATCH 087/129] target/s390x: Hoist some computation in access_memmove Ensure that the total length is in a local variable across the byte loop. Compute size1 difference once. Signed-off-by: Richard Henderson Reviewed-by: David Hildenbrand Message-Id: <20230109201856.3916639-8-richard.henderson@linaro.org> Signed-off-by: Thomas Huth --- target/s390x/tcg/mem_helper.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/target/s390x/tcg/mem_helper.c b/target/s390x/tcg/mem_helper.c index f28126fde6..e51a0db0fe 100644 --- a/target/s390x/tcg/mem_helper.c +++ b/target/s390x/tcg/mem_helper.c @@ -299,16 +299,17 @@ static void access_set_byte(CPUS390XState *env, S390Access *access, static void access_memmove(CPUS390XState *env, S390Access *desta, S390Access *srca, uintptr_t ra) { + int len = desta->size1 + desta->size2; int diff; - g_assert(desta->size1 + desta->size2 == srca->size1 + srca->size2); + assert(len == srca->size1 + srca->size2); /* Fallback to slow access in case we don't have access to all host pages */ if (unlikely(!desta->haddr1 || (desta->size2 && !desta->haddr2) || !srca->haddr1 || (srca->size2 && !srca->haddr2))) { int i; - for (i = 0; i < desta->size1 + desta->size2; i++) { + for (i = 0; i < len; i++) { uint8_t byte = access_get_byte(env, srca, i, ra); access_set_byte(env, desta, i, byte, ra); @@ -316,20 +317,20 @@ static void access_memmove(CPUS390XState *env, S390Access *desta, return; } - if (srca->size1 == desta->size1) { + diff = desta->size1 - srca->size1; + if (likely(diff == 0)) { memmove(desta->haddr1, srca->haddr1, srca->size1); if (unlikely(srca->size2)) { memmove(desta->haddr2, srca->haddr2, srca->size2); } - } else if (srca->size1 < desta->size1) { - diff = desta->size1 - srca->size1; + } else if (diff > 0) { memmove(desta->haddr1, srca->haddr1, srca->size1); memmove(desta->haddr1 + srca->size1, srca->haddr2, diff); if (likely(desta->size2)) { memmove(desta->haddr2, srca->haddr2 + diff, desta->size2); } } else { - diff = srca->size1 - desta->size1; + diff = -diff; memmove(desta->haddr1, srca->haddr1, desta->size1); memmove(desta->haddr2, srca->haddr1 + desta->size1, diff); if (likely(srca->size2)) { From c3a073c6109dfa34ed4d3b5d8238b97e696aaf20 Mon Sep 17 00:00:00 2001 From: Claudio Imbrenda Date: Tue, 14 Feb 2023 17:30:35 +0100 Subject: [PATCH 088/129] s390x/pv: Add support for asynchronous teardown for reboot This patch adds support for the asynchronous teardown for reboot for protected VMs. When attempting to tear down a protected VM, try to use the new asynchronous interface first. If that fails, fall back to the classic synchronous one. The asynchronous interface involves invoking the new KVM_PV_ASYNC_DISABLE_PREPARE command for the KVM_S390_PV_COMMAND ioctl. This will prepare the current protected VM for asynchronous teardown. Once the protected VM is prepared for teardown, execution can continue immediately. Once the protected VM has been prepared, a new thread is started to actually perform the teardown. The new thread uses the new KVM_PV_ASYNC_DISABLE command for the KVM_S390_PV_COMMAND ioctl. The previously prepared protected VM is torn down in the new thread. Once KVM_PV_ASYNC_DISABLE is invoked, it is possible to use KVM_PV_ASYNC_DISABLE_PREPARE again. If a protected VM has already been prepared and its cleanup has not started, it will not be possible to prepare a new VM. In that case the classic synchronous teardown has to be performed. The synchronous teardown will now also clean up any prepared VMs whose asynchronous teardown has not been initiated yet. This considerably speeds up the reboot of a protected VM; for large VMs especially, it could take a long time to perform a reboot with the traditional synchronous teardown, while with this patch it is almost immediate. Signed-off-by: Claudio Imbrenda Reviewed-by: Thomas Huth Message-Id: <20230214163035.44104-3-imbrenda@linux.ibm.com> Signed-off-by: Thomas Huth --- hw/s390x/pv.c | 28 ++++++++++++++++++++++++++++ hw/s390x/s390-virtio-ccw.c | 5 ++++- include/hw/s390x/pv.h | 2 ++ 3 files changed, 34 insertions(+), 1 deletion(-) diff --git a/hw/s390x/pv.c b/hw/s390x/pv.c index 8a1c71436b..49ea38236c 100644 --- a/hw/s390x/pv.c +++ b/hw/s390x/pv.c @@ -16,6 +16,7 @@ #include "qapi/error.h" #include "qemu/error-report.h" #include "sysemu/kvm.h" +#include "sysemu/cpus.h" #include "qom/object_interfaces.h" #include "exec/confidential-guest-support.h" #include "hw/s390x/ipl.h" @@ -108,6 +109,33 @@ void s390_pv_vm_disable(void) s390_pv_cmd_exit(KVM_PV_DISABLE, NULL); } +static void *s390_pv_do_unprot_async_fn(void *p) +{ + s390_pv_cmd_exit(KVM_PV_ASYNC_CLEANUP_PERFORM, NULL); + return NULL; +} + +bool s390_pv_vm_try_disable_async(void) +{ + /* + * t is only needed to create the thread; once qemu_thread_create + * returns, it can safely be discarded. + */ + QemuThread t; + + if (!kvm_check_extension(kvm_state, KVM_CAP_S390_PROTECTED_ASYNC_DISABLE)) { + return false; + } + if (s390_pv_cmd(KVM_PV_ASYNC_CLEANUP_PREPARE, NULL) != 0) { + return false; + } + + qemu_thread_create(&t, "async_cleanup", s390_pv_do_unprot_async_fn, NULL, + QEMU_THREAD_DETACHED); + + return true; +} + int s390_pv_set_sec_parms(uint64_t origin, uint64_t length) { struct kvm_s390_pv_sec_parm args = { diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c index f22f61b8b6..503f212a31 100644 --- a/hw/s390x/s390-virtio-ccw.c +++ b/hw/s390x/s390-virtio-ccw.c @@ -41,6 +41,7 @@ #include "hw/qdev-properties.h" #include "hw/s390x/tod.h" #include "sysemu/sysemu.h" +#include "sysemu/cpus.h" #include "hw/s390x/pv.h" #include "migration/blocker.h" #include "qapi/visitor.h" @@ -329,7 +330,9 @@ static inline void s390_do_cpu_ipl(CPUState *cs, run_on_cpu_data arg) static void s390_machine_unprotect(S390CcwMachineState *ms) { - s390_pv_vm_disable(); + if (!s390_pv_vm_try_disable_async()) { + s390_pv_vm_disable(); + } ms->pv = false; migrate_del_blocker(pv_mig_blocker); error_free_or_abort(&pv_mig_blocker); diff --git a/include/hw/s390x/pv.h b/include/hw/s390x/pv.h index 9360aa1091..966306a9db 100644 --- a/include/hw/s390x/pv.h +++ b/include/hw/s390x/pv.h @@ -41,6 +41,7 @@ static inline bool s390_is_pv(void) int s390_pv_query_info(void); int s390_pv_vm_enable(void); void s390_pv_vm_disable(void); +bool s390_pv_vm_try_disable_async(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_prep_reset(void); @@ -60,6 +61,7 @@ static inline bool s390_is_pv(void) { return false; } static inline int s390_pv_query_info(void) { return 0; } static inline int s390_pv_vm_enable(void) { return 0; } static inline void s390_pv_vm_disable(void) {} +static inline bool s390_pv_vm_try_disable_async(void) { return false; } 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_prep_reset(void) {} From f1ea739bd598db3d8801566ae86e4eb76ab44436 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 20 Feb 2023 08:40:26 -1000 Subject: [PATCH 089/129] target/s390x: Use tcg_constant_* in local contexts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace tcg_const_* with tcg_constant_* in contexts where the free to remove is nearby. Signed-off-by: Richard Henderson Reviewed-by: Ilya Leoshkevich Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20230220184052.163465-2-richard.henderson@linaro.org> Signed-off-by: Thomas Huth --- target/s390x/tcg/translate.c | 410 +++++++++++++---------------------- 1 file changed, 147 insertions(+), 263 deletions(-) diff --git a/target/s390x/tcg/translate.c b/target/s390x/tcg/translate.c index ac5bd98f04..35e844ef3c 100644 --- a/target/s390x/tcg/translate.c +++ b/target/s390x/tcg/translate.c @@ -171,8 +171,6 @@ static uint64_t inline_branch_miss[CC_OP_MAX]; static void pc_to_link_info(TCGv_i64 out, DisasContext *s, uint64_t pc) { - TCGv_i64 tmp; - if (s->base.tb->flags & FLAG_MASK_32) { if (s->base.tb->flags & FLAG_MASK_64) { tcg_gen_movi_i64(out, pc); @@ -181,9 +179,7 @@ static void pc_to_link_info(TCGv_i64 out, DisasContext *s, uint64_t pc) pc |= 0x80000000; } assert(!(s->base.tb->flags & FLAG_MASK_64)); - tmp = tcg_const_i64(pc); - tcg_gen_deposit_i64(out, out, tmp, 0, 32); - tcg_temp_free_i64(tmp); + tcg_gen_deposit_i64(out, out, tcg_constant_i64(pc), 0, 32); } static TCGv_i64 psw_addr; @@ -360,11 +356,8 @@ static void per_branch(DisasContext *s, bool to_next) tcg_gen_movi_i64(gbea, s->base.pc_next); if (s->base.tb->flags & FLAG_MASK_PER) { - TCGv_i64 next_pc = to_next ? tcg_const_i64(s->pc_tmp) : psw_addr; + TCGv_i64 next_pc = to_next ? tcg_constant_i64(s->pc_tmp) : psw_addr; gen_helper_per_branch(cpu_env, gbea, next_pc); - if (to_next) { - tcg_temp_free_i64(next_pc); - } } #endif } @@ -382,9 +375,8 @@ static void per_branch_cond(DisasContext *s, TCGCond cond, gen_set_label(lab); } else { - TCGv_i64 pc = tcg_const_i64(s->base.pc_next); + TCGv_i64 pc = tcg_constant_i64(s->base.pc_next); tcg_gen_movcond_i64(cond, gbea, arg1, arg2, gbea, pc); - tcg_temp_free_i64(pc); } #endif } @@ -438,23 +430,17 @@ static int get_mem_index(DisasContext *s) static void gen_exception(int excp) { - TCGv_i32 tmp = tcg_const_i32(excp); - gen_helper_exception(cpu_env, tmp); - tcg_temp_free_i32(tmp); + gen_helper_exception(cpu_env, tcg_constant_i32(excp)); } static void gen_program_exception(DisasContext *s, int code) { - TCGv_i32 tmp; + /* Remember what pgm exeption this was. */ + tcg_gen_st_i32(tcg_constant_i32(code), cpu_env, + offsetof(CPUS390XState, int_pgm_code)); - /* Remember what pgm exception this was. */ - tmp = tcg_const_i32(code); - tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUS390XState, int_pgm_code)); - tcg_temp_free_i32(tmp); - - tmp = tcg_const_i32(s->ilen); - tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUS390XState, int_pgm_ilen)); - tcg_temp_free_i32(tmp); + tcg_gen_st_i32(tcg_constant_i32(s->ilen), cpu_env, + offsetof(CPUS390XState, int_pgm_ilen)); /* update the psw */ update_psw_addr(s); @@ -473,9 +459,7 @@ static inline void gen_illegal_opcode(DisasContext *s) static inline void gen_data_exception(uint8_t dxc) { - TCGv_i32 tmp = tcg_const_i32(dxc); - gen_helper_data_exception(cpu_env, tmp); - tcg_temp_free_i32(tmp); + gen_helper_data_exception(cpu_env, tcg_constant_i32(dxc)); } static inline void gen_trap(DisasContext *s) @@ -596,13 +580,13 @@ static void gen_op_calc_cc(DisasContext *s) switch (s->cc_op) { default: - dummy = tcg_const_i64(0); + dummy = tcg_constant_i64(0); /* FALLTHRU */ case CC_OP_ADD_64: case CC_OP_SUB_64: case CC_OP_ADD_32: case CC_OP_SUB_32: - local_cc_op = tcg_const_i32(s->cc_op); + local_cc_op = tcg_constant_i32(s->cc_op); break; case CC_OP_CONST0: case CC_OP_CONST1: @@ -675,13 +659,6 @@ static void gen_op_calc_cc(DisasContext *s) tcg_abort(); } - if (local_cc_op) { - tcg_temp_free_i32(local_cc_op); - } - if (dummy) { - tcg_temp_free_i64(dummy); - } - /* We now have cc in cc_op as constant */ set_cc_static(s); } @@ -1300,9 +1277,9 @@ static DisasJumpType help_branch(DisasContext *s, DisasCompare *c, Most commonly we're single-stepping or some other condition that disables all use of goto_tb. Just update the PC and exit. */ - TCGv_i64 next = tcg_const_i64(s->pc_tmp); + TCGv_i64 next = tcg_constant_i64(s->pc_tmp); if (is_imm) { - cdest = tcg_const_i64(dest); + cdest = tcg_constant_i64(dest); } if (c->is_64) { @@ -1312,21 +1289,15 @@ static DisasJumpType help_branch(DisasContext *s, DisasCompare *c, } else { TCGv_i32 t0 = tcg_temp_new_i32(); TCGv_i64 t1 = tcg_temp_new_i64(); - TCGv_i64 z = tcg_const_i64(0); + TCGv_i64 z = tcg_constant_i64(0); tcg_gen_setcond_i32(c->cond, t0, c->u.s32.a, c->u.s32.b); tcg_gen_extu_i32_i64(t1, t0); tcg_temp_free_i32(t0); tcg_gen_movcond_i64(TCG_COND_NE, psw_addr, t1, z, cdest, next); per_branch_cond(s, TCG_COND_NE, t1, z); tcg_temp_free_i64(t1); - tcg_temp_free_i64(z); } - if (is_imm) { - tcg_temp_free_i64(cdest); - } - tcg_temp_free_i64(next); - ret = DISAS_PC_UPDATED; } @@ -1410,10 +1381,9 @@ static DisasJumpType op_addc64(DisasContext *s, DisasOps *o) { compute_carry(s); - TCGv_i64 zero = tcg_const_i64(0); + TCGv_i64 zero = tcg_constant_i64(0); tcg_gen_add2_i64(o->out, cc_src, o->in1, zero, cc_src, zero); tcg_gen_add2_i64(o->out, cc_src, o->out, cc_src, o->in2, zero); - tcg_temp_free_i64(zero); return DISAS_NEXT; } @@ -2092,9 +2062,8 @@ static DisasJumpType op_clc(DisasContext *s, DisasOps *o) tcg_gen_qemu_ld64(cc_dst, o->in2, get_mem_index(s)); break; default: - vl = tcg_const_i32(l); + vl = tcg_constant_i32(l); gen_helper_clc(cc_op, cpu_env, vl, o->addr1, o->in2); - tcg_temp_free_i32(vl); set_cc_static(s); return DISAS_NEXT; } @@ -2114,11 +2083,9 @@ static DisasJumpType op_clcl(DisasContext *s, DisasOps *o) return DISAS_NORETURN; } - t1 = tcg_const_i32(r1); - t2 = tcg_const_i32(r2); + t1 = tcg_constant_i32(r1); + t2 = tcg_constant_i32(r2); gen_helper_clcl(cc_op, cpu_env, t1, t2); - tcg_temp_free_i32(t1); - tcg_temp_free_i32(t2); set_cc_static(s); return DISAS_NEXT; } @@ -2135,11 +2102,9 @@ static DisasJumpType op_clcle(DisasContext *s, DisasOps *o) return DISAS_NORETURN; } - t1 = tcg_const_i32(r1); - t3 = tcg_const_i32(r3); + t1 = tcg_constant_i32(r1); + t3 = tcg_constant_i32(r3); gen_helper_clcle(cc_op, cpu_env, t1, o->in2, t3); - tcg_temp_free_i32(t1); - tcg_temp_free_i32(t3); set_cc_static(s); return DISAS_NEXT; } @@ -2156,24 +2121,22 @@ static DisasJumpType op_clclu(DisasContext *s, DisasOps *o) return DISAS_NORETURN; } - t1 = tcg_const_i32(r1); - t3 = tcg_const_i32(r3); + t1 = tcg_constant_i32(r1); + t3 = tcg_constant_i32(r3); gen_helper_clclu(cc_op, cpu_env, t1, o->in2, t3); - tcg_temp_free_i32(t1); - tcg_temp_free_i32(t3); set_cc_static(s); return DISAS_NEXT; } static DisasJumpType op_clm(DisasContext *s, DisasOps *o) { - TCGv_i32 m3 = tcg_const_i32(get_field(s, m3)); + TCGv_i32 m3 = tcg_constant_i32(get_field(s, m3)); TCGv_i32 t1 = tcg_temp_new_i32(); + tcg_gen_extrl_i64_i32(t1, o->in1); gen_helper_clm(cc_op, cpu_env, t1, m3, o->in2); set_cc_static(s); tcg_temp_free_i32(t1); - tcg_temp_free_i32(m3); return DISAS_NEXT; } @@ -2251,14 +2214,13 @@ static DisasJumpType op_cdsg(DisasContext *s, DisasOps *o) static DisasJumpType op_csst(DisasContext *s, DisasOps *o) { int r3 = get_field(s, r3); - TCGv_i32 t_r3 = tcg_const_i32(r3); + TCGv_i32 t_r3 = tcg_constant_i32(r3); if (tb_cflags(s->base.tb) & CF_PARALLEL) { gen_helper_csst_parallel(cc_op, cpu_env, t_r3, o->addr1, o->in2); } else { gen_helper_csst(cc_op, cpu_env, t_r3, o->addr1, o->in2); } - tcg_temp_free_i32(t_r3); set_cc_static(s); return DISAS_NEXT; @@ -2356,9 +2318,9 @@ static DisasJumpType op_cuXX(DisasContext *s, DisasOps *o) m3 = 0; } - tr1 = tcg_const_i32(r1); - tr2 = tcg_const_i32(r2); - chk = tcg_const_i32(m3); + tr1 = tcg_constant_i32(r1); + tr2 = tcg_constant_i32(r2); + chk = tcg_constant_i32(m3); switch (s->insn->data) { case 12: @@ -2383,9 +2345,6 @@ static DisasJumpType op_cuXX(DisasContext *s, DisasOps *o) g_assert_not_reached(); } - tcg_temp_free_i32(tr1); - tcg_temp_free_i32(tr2); - tcg_temp_free_i32(chk); set_cc_static(s); return DISAS_NEXT; } @@ -2393,15 +2352,11 @@ static DisasJumpType op_cuXX(DisasContext *s, DisasOps *o) #ifndef CONFIG_USER_ONLY static DisasJumpType op_diag(DisasContext *s, DisasOps *o) { - TCGv_i32 r1 = tcg_const_i32(get_field(s, r1)); - TCGv_i32 r3 = tcg_const_i32(get_field(s, r3)); - TCGv_i32 func_code = tcg_const_i32(get_field(s, i2)); + TCGv_i32 r1 = tcg_constant_i32(get_field(s, r1)); + TCGv_i32 r3 = tcg_constant_i32(get_field(s, r3)); + TCGv_i32 func_code = tcg_constant_i32(get_field(s, i2)); gen_helper_diag(cpu_env, r1, r3, func_code); - - tcg_temp_free_i32(func_code); - tcg_temp_free_i32(r3); - tcg_temp_free_i32(r1); return DISAS_NEXT; } #endif @@ -2512,18 +2467,13 @@ static DisasJumpType op_ex(DisasContext *s, DisasOps *o) update_cc_op(s); if (r1 == 0) { - v1 = tcg_const_i64(0); + v1 = tcg_constant_i64(0); } else { v1 = regs[r1]; } - ilen = tcg_const_i32(s->ilen); + ilen = tcg_constant_i32(s->ilen); gen_helper_ex(cpu_env, ilen, v1, o->in2); - tcg_temp_free_i32(ilen); - - if (r1 == 0) { - tcg_temp_free_i64(v1); - } return DISAS_PC_CC_UPDATED; } @@ -2674,12 +2624,11 @@ static DisasJumpType op_idte(DisasContext *s, DisasOps *o) TCGv_i32 m4; if (s390_has_feat(S390_FEAT_LOCAL_TLB_CLEARING)) { - m4 = tcg_const_i32(get_field(s, m4)); + m4 = tcg_constant_i32(get_field(s, m4)); } else { - m4 = tcg_const_i32(0); + m4 = tcg_constant_i32(0); } gen_helper_idte(cpu_env, o->in1, o->in2, m4); - tcg_temp_free_i32(m4); return DISAS_NEXT; } @@ -2688,12 +2637,11 @@ static DisasJumpType op_ipte(DisasContext *s, DisasOps *o) TCGv_i32 m4; if (s390_has_feat(S390_FEAT_LOCAL_TLB_CLEARING)) { - m4 = tcg_const_i32(get_field(s, m4)); + m4 = tcg_constant_i32(get_field(s, m4)); } else { - m4 = tcg_const_i32(0); + m4 = tcg_constant_i32(0); } gen_helper_ipte(cpu_env, o->in1, o->in2, m4); - tcg_temp_free_i32(m4); return DISAS_NEXT; } @@ -2749,16 +2697,12 @@ static DisasJumpType op_msa(DisasContext *s, DisasOps *o) g_assert_not_reached(); }; - t_r1 = tcg_const_i32(r1); - t_r2 = tcg_const_i32(r2); - t_r3 = tcg_const_i32(r3); - type = tcg_const_i32(s->insn->data); + t_r1 = tcg_constant_i32(r1); + t_r2 = tcg_constant_i32(r2); + t_r3 = tcg_constant_i32(r3); + type = tcg_constant_i32(s->insn->data); gen_helper_msa(cc_op, cpu_env, t_r1, t_r2, t_r3, type); set_cc_static(s); - tcg_temp_free_i32(t_r1); - tcg_temp_free_i32(t_r2); - tcg_temp_free_i32(t_r3); - tcg_temp_free_i32(type); return DISAS_NEXT; } @@ -3017,10 +2961,9 @@ static DisasJumpType op_loc(DisasContext *s, DisasOps *o) tcg_gen_extu_i32_i64(t, t32); tcg_temp_free_i32(t32); - z = tcg_const_i64(0); + z = tcg_constant_i64(0); tcg_gen_movcond_i64(TCG_COND_NE, o->out, t, z, o->in2, o->in1); tcg_temp_free_i64(t); - tcg_temp_free_i64(z); } return DISAS_NEXT; @@ -3029,11 +2972,10 @@ static DisasJumpType op_loc(DisasContext *s, DisasOps *o) #ifndef CONFIG_USER_ONLY static DisasJumpType op_lctl(DisasContext *s, DisasOps *o) { - TCGv_i32 r1 = tcg_const_i32(get_field(s, r1)); - TCGv_i32 r3 = tcg_const_i32(get_field(s, r3)); + TCGv_i32 r1 = tcg_constant_i32(get_field(s, r1)); + TCGv_i32 r3 = tcg_constant_i32(get_field(s, r3)); + gen_helper_lctl(cpu_env, r1, o->in2, r3); - tcg_temp_free_i32(r1); - tcg_temp_free_i32(r3); /* Exit to main loop to reevaluate s390_cpu_exec_interrupt. */ s->exit_to_mainloop = true; return DISAS_TOO_MANY; @@ -3041,11 +2983,10 @@ static DisasJumpType op_lctl(DisasContext *s, DisasOps *o) static DisasJumpType op_lctlg(DisasContext *s, DisasOps *o) { - TCGv_i32 r1 = tcg_const_i32(get_field(s, r1)); - TCGv_i32 r3 = tcg_const_i32(get_field(s, r3)); + TCGv_i32 r1 = tcg_constant_i32(get_field(s, r1)); + TCGv_i32 r3 = tcg_constant_i32(get_field(s, r3)); + gen_helper_lctlg(cpu_env, r1, o->in2, r3); - tcg_temp_free_i32(r1); - tcg_temp_free_i32(r3); /* Exit to main loop to reevaluate s390_cpu_exec_interrupt. */ s->exit_to_mainloop = true; return DISAS_TOO_MANY; @@ -3105,11 +3046,10 @@ static DisasJumpType op_lpswe(DisasContext *s, DisasOps *o) static DisasJumpType op_lam(DisasContext *s, DisasOps *o) { - TCGv_i32 r1 = tcg_const_i32(get_field(s, r1)); - TCGv_i32 r3 = tcg_const_i32(get_field(s, r3)); + TCGv_i32 r1 = tcg_constant_i32(get_field(s, r1)); + TCGv_i32 r3 = tcg_constant_i32(get_field(s, r3)); + gen_helper_lam(cpu_env, r1, o->in2, r3); - tcg_temp_free_i32(r1); - tcg_temp_free_i32(r3); return DISAS_NEXT; } @@ -3319,9 +3259,6 @@ static DisasJumpType op_lcbb(DisasContext *s, DisasOps *o) static DisasJumpType op_mc(DisasContext *s, DisasOps *o) { -#if !defined(CONFIG_USER_ONLY) - TCGv_i32 i2; -#endif const uint16_t monitor_class = get_field(s, i2); if (monitor_class & 0xff00) { @@ -3330,9 +3267,8 @@ static DisasJumpType op_mc(DisasContext *s, DisasOps *o) } #if !defined(CONFIG_USER_ONLY) - i2 = tcg_const_i32(monitor_class); - gen_helper_monitor_call(cpu_env, o->addr1, i2); - tcg_temp_free_i32(i2); + gen_helper_monitor_call(cpu_env, o->addr1, + tcg_constant_i32(monitor_class)); #endif /* Defaults to a NOP. */ return DISAS_NEXT; @@ -3396,9 +3332,9 @@ static DisasJumpType op_movx(DisasContext *s, DisasOps *o) static DisasJumpType op_mvc(DisasContext *s, DisasOps *o) { - TCGv_i32 l = tcg_const_i32(get_field(s, l1)); + TCGv_i32 l = tcg_constant_i32(get_field(s, l1)); + gen_helper_mvc(cpu_env, l, o->addr1, o->in2); - tcg_temp_free_i32(l); return DISAS_NEXT; } @@ -3410,9 +3346,9 @@ static DisasJumpType op_mvcrl(DisasContext *s, DisasOps *o) static DisasJumpType op_mvcin(DisasContext *s, DisasOps *o) { - TCGv_i32 l = tcg_const_i32(get_field(s, l1)); + TCGv_i32 l = tcg_constant_i32(get_field(s, l1)); + gen_helper_mvcin(cpu_env, l, o->addr1, o->in2); - tcg_temp_free_i32(l); return DISAS_NEXT; } @@ -3428,11 +3364,9 @@ static DisasJumpType op_mvcl(DisasContext *s, DisasOps *o) return DISAS_NORETURN; } - t1 = tcg_const_i32(r1); - t2 = tcg_const_i32(r2); + t1 = tcg_constant_i32(r1); + t2 = tcg_constant_i32(r2); gen_helper_mvcl(cc_op, cpu_env, t1, t2); - tcg_temp_free_i32(t1); - tcg_temp_free_i32(t2); set_cc_static(s); return DISAS_NEXT; } @@ -3449,11 +3383,9 @@ static DisasJumpType op_mvcle(DisasContext *s, DisasOps *o) return DISAS_NORETURN; } - t1 = tcg_const_i32(r1); - t3 = tcg_const_i32(r3); + t1 = tcg_constant_i32(r1); + t3 = tcg_constant_i32(r3); gen_helper_mvcle(cc_op, cpu_env, t1, o->in2, t3); - tcg_temp_free_i32(t1); - tcg_temp_free_i32(t3); set_cc_static(s); return DISAS_NEXT; } @@ -3470,11 +3402,9 @@ static DisasJumpType op_mvclu(DisasContext *s, DisasOps *o) return DISAS_NORETURN; } - t1 = tcg_const_i32(r1); - t3 = tcg_const_i32(r3); + t1 = tcg_constant_i32(r1); + t3 = tcg_constant_i32(r3); gen_helper_mvclu(cc_op, cpu_env, t1, o->in2, t3); - tcg_temp_free_i32(t1); - tcg_temp_free_i32(t3); set_cc_static(s); return DISAS_NEXT; } @@ -3509,49 +3439,45 @@ static DisasJumpType op_mvcs(DisasContext *s, DisasOps *o) static DisasJumpType op_mvn(DisasContext *s, DisasOps *o) { - TCGv_i32 l = tcg_const_i32(get_field(s, l1)); + TCGv_i32 l = tcg_constant_i32(get_field(s, l1)); + gen_helper_mvn(cpu_env, l, o->addr1, o->in2); - tcg_temp_free_i32(l); return DISAS_NEXT; } static DisasJumpType op_mvo(DisasContext *s, DisasOps *o) { - TCGv_i32 l = tcg_const_i32(get_field(s, l1)); + TCGv_i32 l = tcg_constant_i32(get_field(s, l1)); + gen_helper_mvo(cpu_env, l, o->addr1, o->in2); - tcg_temp_free_i32(l); return DISAS_NEXT; } static DisasJumpType op_mvpg(DisasContext *s, DisasOps *o) { - TCGv_i32 t1 = tcg_const_i32(get_field(s, r1)); - TCGv_i32 t2 = tcg_const_i32(get_field(s, r2)); + TCGv_i32 t1 = tcg_constant_i32(get_field(s, r1)); + TCGv_i32 t2 = tcg_constant_i32(get_field(s, r2)); gen_helper_mvpg(cc_op, cpu_env, regs[0], t1, t2); - tcg_temp_free_i32(t1); - tcg_temp_free_i32(t2); set_cc_static(s); return DISAS_NEXT; } static DisasJumpType op_mvst(DisasContext *s, DisasOps *o) { - TCGv_i32 t1 = tcg_const_i32(get_field(s, r1)); - TCGv_i32 t2 = tcg_const_i32(get_field(s, r2)); + TCGv_i32 t1 = tcg_constant_i32(get_field(s, r1)); + TCGv_i32 t2 = tcg_constant_i32(get_field(s, r2)); gen_helper_mvst(cc_op, cpu_env, t1, t2); - tcg_temp_free_i32(t1); - tcg_temp_free_i32(t2); set_cc_static(s); return DISAS_NEXT; } static DisasJumpType op_mvz(DisasContext *s, DisasOps *o) { - TCGv_i32 l = tcg_const_i32(get_field(s, l1)); + TCGv_i32 l = tcg_constant_i32(get_field(s, l1)); + gen_helper_mvz(cpu_env, l, o->addr1, o->in2); - tcg_temp_free_i32(l); return DISAS_NEXT; } @@ -3637,13 +3563,12 @@ static DisasJumpType op_msdb(DisasContext *s, DisasOps *o) static DisasJumpType op_nabs(DisasContext *s, DisasOps *o) { - TCGv_i64 z, n; - z = tcg_const_i64(0); - n = tcg_temp_new_i64(); + TCGv_i64 z = tcg_constant_i64(0); + TCGv_i64 n = tcg_temp_new_i64(); + tcg_gen_neg_i64(n, o->in2); tcg_gen_movcond_i64(TCG_COND_GE, o->out, o->in2, z, n, o->in2); tcg_temp_free_i64(n); - tcg_temp_free_i64(z); return DISAS_NEXT; } @@ -3668,9 +3593,9 @@ static DisasJumpType op_nabsf128(DisasContext *s, DisasOps *o) static DisasJumpType op_nc(DisasContext *s, DisasOps *o) { - TCGv_i32 l = tcg_const_i32(get_field(s, l1)); + TCGv_i32 l = tcg_constant_i32(get_field(s, l1)); + gen_helper_nc(cc_op, cpu_env, l, o->addr1, o->in2); - tcg_temp_free_i32(l); set_cc_static(s); return DISAS_NEXT; } @@ -3702,9 +3627,9 @@ static DisasJumpType op_negf128(DisasContext *s, DisasOps *o) static DisasJumpType op_oc(DisasContext *s, DisasOps *o) { - TCGv_i32 l = tcg_const_i32(get_field(s, l1)); + TCGv_i32 l = tcg_constant_i32(get_field(s, l1)); + gen_helper_oc(cc_op, cpu_env, l, o->addr1, o->in2); - tcg_temp_free_i32(l); set_cc_static(s); return DISAS_NEXT; } @@ -3754,9 +3679,9 @@ static DisasJumpType op_oi(DisasContext *s, DisasOps *o) static DisasJumpType op_pack(DisasContext *s, DisasOps *o) { - TCGv_i32 l = tcg_const_i32(get_field(s, l1)); + TCGv_i32 l = tcg_constant_i32(get_field(s, l1)); + gen_helper_pack(cpu_env, l, o->addr1, o->in2); - tcg_temp_free_i32(l); return DISAS_NEXT; } @@ -3770,9 +3695,8 @@ static DisasJumpType op_pka(DisasContext *s, DisasOps *o) gen_program_exception(s, PGM_SPECIFICATION); return DISAS_NORETURN; } - l = tcg_const_i32(l2); + l = tcg_constant_i32(l2); gen_helper_pka(cpu_env, o->addr1, o->in2, l); - tcg_temp_free_i32(l); return DISAS_NEXT; } @@ -3786,9 +3710,8 @@ static DisasJumpType op_pku(DisasContext *s, DisasOps *o) gen_program_exception(s, PGM_SPECIFICATION); return DISAS_NORETURN; } - l = tcg_const_i32(l2); + l = tcg_constant_i32(l2); gen_helper_pku(cpu_env, o->addr1, o->in2, l); - tcg_temp_free_i32(l); return DISAS_NEXT; } @@ -4035,9 +3958,8 @@ static DisasJumpType op_sam(DisasContext *s, DisasOps *o) } s->pc_tmp &= mask; - tsam = tcg_const_i64(sam); + tsam = tcg_constant_i64(sam); tcg_gen_deposit_i64(psw_mask, psw_mask, tsam, 31, 2); - tcg_temp_free_i64(tsam); /* Always exit the TB, since we (may have) changed execution mode. */ return DISAS_TOO_MANY; @@ -4096,12 +4018,11 @@ static DisasJumpType op_servc(DisasContext *s, DisasOps *o) static DisasJumpType op_sigp(DisasContext *s, DisasOps *o) { - TCGv_i32 r1 = tcg_const_i32(get_field(s, r1)); - TCGv_i32 r3 = tcg_const_i32(get_field(s, r3)); + TCGv_i32 r1 = tcg_constant_i32(get_field(s, r1)); + TCGv_i32 r3 = tcg_constant_i32(get_field(s, r3)); + gen_helper_sigp(cc_op, cpu_env, o->in2, r1, r3); set_cc_static(s); - tcg_temp_free_i32(r1); - tcg_temp_free_i32(r3); return DISAS_NEXT; } #endif @@ -4370,21 +4291,19 @@ static DisasJumpType op_stckc(DisasContext *s, DisasOps *o) static DisasJumpType op_stctg(DisasContext *s, DisasOps *o) { - TCGv_i32 r1 = tcg_const_i32(get_field(s, r1)); - TCGv_i32 r3 = tcg_const_i32(get_field(s, r3)); + TCGv_i32 r1 = tcg_constant_i32(get_field(s, r1)); + TCGv_i32 r3 = tcg_constant_i32(get_field(s, r3)); + gen_helper_stctg(cpu_env, r1, o->in2, r3); - tcg_temp_free_i32(r1); - tcg_temp_free_i32(r3); return DISAS_NEXT; } static DisasJumpType op_stctl(DisasContext *s, DisasOps *o) { - TCGv_i32 r1 = tcg_const_i32(get_field(s, r1)); - TCGv_i32 r3 = tcg_const_i32(get_field(s, r3)); + TCGv_i32 r1 = tcg_constant_i32(get_field(s, r1)); + TCGv_i32 r3 = tcg_constant_i32(get_field(s, r3)); + gen_helper_stctl(cpu_env, r1, o->in2, r3); - tcg_temp_free_i32(r1); - tcg_temp_free_i32(r3); return DISAS_NEXT; } @@ -4611,11 +4530,10 @@ static DisasJumpType op_st64(DisasContext *s, DisasOps *o) static DisasJumpType op_stam(DisasContext *s, DisasOps *o) { - TCGv_i32 r1 = tcg_const_i32(get_field(s, r1)); - TCGv_i32 r3 = tcg_const_i32(get_field(s, r3)); + TCGv_i32 r1 = tcg_constant_i32(get_field(s, r1)); + TCGv_i32 r3 = tcg_constant_i32(get_field(s, r3)); + gen_helper_stam(cpu_env, r1, o->in2, r3); - tcg_temp_free_i32(r1); - tcg_temp_free_i32(r3); return DISAS_NEXT; } @@ -4673,7 +4591,7 @@ static DisasJumpType op_stm(DisasContext *s, DisasOps *o) int r1 = get_field(s, r1); int r3 = get_field(s, r3); int size = s->insn->data; - TCGv_i64 tsize = tcg_const_i64(size); + TCGv_i64 tsize = tcg_constant_i64(size); while (1) { if (size == 8) { @@ -4688,7 +4606,6 @@ static DisasJumpType op_stm(DisasContext *s, DisasOps *o) r1 = (r1 + 1) & 15; } - tcg_temp_free_i64(tsize); return DISAS_NEXT; } @@ -4697,8 +4614,8 @@ static DisasJumpType op_stmh(DisasContext *s, DisasOps *o) int r1 = get_field(s, r1); int r3 = get_field(s, r3); TCGv_i64 t = tcg_temp_new_i64(); - TCGv_i64 t4 = tcg_const_i64(4); - TCGv_i64 t32 = tcg_const_i64(32); + TCGv_i64 t4 = tcg_constant_i64(4); + TCGv_i64 t32 = tcg_constant_i64(32); while (1) { tcg_gen_shl_i64(t, regs[r1], t32); @@ -4711,8 +4628,6 @@ static DisasJumpType op_stmh(DisasContext *s, DisasOps *o) } tcg_temp_free_i64(t); - tcg_temp_free_i64(t4); - tcg_temp_free_i64(t32); return DISAS_NEXT; } @@ -4731,26 +4646,20 @@ static DisasJumpType op_stpq(DisasContext *s, DisasOps *o) static DisasJumpType op_srst(DisasContext *s, DisasOps *o) { - TCGv_i32 r1 = tcg_const_i32(get_field(s, r1)); - TCGv_i32 r2 = tcg_const_i32(get_field(s, r2)); + TCGv_i32 r1 = tcg_constant_i32(get_field(s, r1)); + TCGv_i32 r2 = tcg_constant_i32(get_field(s, r2)); gen_helper_srst(cpu_env, r1, r2); - - tcg_temp_free_i32(r1); - tcg_temp_free_i32(r2); set_cc_static(s); return DISAS_NEXT; } static DisasJumpType op_srstu(DisasContext *s, DisasOps *o) { - TCGv_i32 r1 = tcg_const_i32(get_field(s, r1)); - TCGv_i32 r2 = tcg_const_i32(get_field(s, r2)); + TCGv_i32 r1 = tcg_constant_i32(get_field(s, r1)); + TCGv_i32 r2 = tcg_constant_i32(get_field(s, r2)); gen_helper_srstu(cpu_env, r1, r2); - - tcg_temp_free_i32(r1); - tcg_temp_free_i32(r2); set_cc_static(s); return DISAS_NEXT; } @@ -4808,10 +4717,9 @@ static DisasJumpType op_subb64(DisasContext *s, DisasOps *o) * Borrow is {0, -1}, so add to subtract; replicate the * borrow input to produce 128-bit -1 for the addition. */ - TCGv_i64 zero = tcg_const_i64(0); + TCGv_i64 zero = tcg_constant_i64(0); tcg_gen_add2_i64(o->out, cc_src, o->in1, zero, cc_src, cc_src); tcg_gen_sub2_i64(o->out, cc_src, o->out, cc_src, o->in2, zero); - tcg_temp_free_i64(zero); return DISAS_NEXT; } @@ -4823,13 +4731,11 @@ static DisasJumpType op_svc(DisasContext *s, DisasOps *o) update_psw_addr(s); update_cc_op(s); - t = tcg_const_i32(get_field(s, i1) & 0xff); + t = tcg_constant_i32(get_field(s, i1) & 0xff); tcg_gen_st_i32(t, cpu_env, offsetof(CPUS390XState, int_svc_code)); - tcg_temp_free_i32(t); - t = tcg_const_i32(s->ilen); + t = tcg_constant_i32(s->ilen); tcg_gen_st_i32(t, cpu_env, offsetof(CPUS390XState, int_svc_ilen)); - tcg_temp_free_i32(t); gen_exception(EXCP_SVC); return DISAS_NORETURN; @@ -4886,18 +4792,18 @@ static DisasJumpType op_tprot(DisasContext *s, DisasOps *o) static DisasJumpType op_tp(DisasContext *s, DisasOps *o) { - TCGv_i32 l1 = tcg_const_i32(get_field(s, l1) + 1); + TCGv_i32 l1 = tcg_constant_i32(get_field(s, l1) + 1); + gen_helper_tp(cc_op, cpu_env, o->addr1, l1); - tcg_temp_free_i32(l1); set_cc_static(s); return DISAS_NEXT; } static DisasJumpType op_tr(DisasContext *s, DisasOps *o) { - TCGv_i32 l = tcg_const_i32(get_field(s, l1)); + TCGv_i32 l = tcg_constant_i32(get_field(s, l1)); + gen_helper_tr(cpu_env, l, o->addr1, o->in2); - tcg_temp_free_i32(l); set_cc_static(s); return DISAS_NEXT; } @@ -4915,27 +4821,27 @@ static DisasJumpType op_tre(DisasContext *s, DisasOps *o) static DisasJumpType op_trt(DisasContext *s, DisasOps *o) { - TCGv_i32 l = tcg_const_i32(get_field(s, l1)); + TCGv_i32 l = tcg_constant_i32(get_field(s, l1)); + gen_helper_trt(cc_op, cpu_env, l, o->addr1, o->in2); - tcg_temp_free_i32(l); set_cc_static(s); return DISAS_NEXT; } static DisasJumpType op_trtr(DisasContext *s, DisasOps *o) { - TCGv_i32 l = tcg_const_i32(get_field(s, l1)); + TCGv_i32 l = tcg_constant_i32(get_field(s, l1)); + gen_helper_trtr(cc_op, cpu_env, l, o->addr1, o->in2); - tcg_temp_free_i32(l); set_cc_static(s); return DISAS_NEXT; } static DisasJumpType op_trXX(DisasContext *s, DisasOps *o) { - TCGv_i32 r1 = tcg_const_i32(get_field(s, r1)); - TCGv_i32 r2 = tcg_const_i32(get_field(s, r2)); - TCGv_i32 sizes = tcg_const_i32(s->insn->opc & 3); + TCGv_i32 r1 = tcg_constant_i32(get_field(s, r1)); + TCGv_i32 r2 = tcg_constant_i32(get_field(s, r2)); + TCGv_i32 sizes = tcg_constant_i32(s->insn->opc & 3); TCGv_i32 tst = tcg_temp_new_i32(); int m3 = get_field(s, m3); @@ -4954,9 +4860,6 @@ static DisasJumpType op_trXX(DisasContext *s, DisasOps *o) } gen_helper_trXX(cc_op, cpu_env, r1, r2, tst, sizes); - tcg_temp_free_i32(r1); - tcg_temp_free_i32(r2); - tcg_temp_free_i32(sizes); tcg_temp_free_i32(tst); set_cc_static(s); return DISAS_NEXT; @@ -4964,19 +4867,19 @@ static DisasJumpType op_trXX(DisasContext *s, DisasOps *o) static DisasJumpType op_ts(DisasContext *s, DisasOps *o) { - TCGv_i32 t1 = tcg_const_i32(0xff); + TCGv_i32 t1 = tcg_constant_i32(0xff); + tcg_gen_atomic_xchg_i32(t1, o->in2, t1, get_mem_index(s), MO_UB); tcg_gen_extract_i32(cc_op, t1, 7, 1); - tcg_temp_free_i32(t1); set_cc_static(s); return DISAS_NEXT; } static DisasJumpType op_unpk(DisasContext *s, DisasOps *o) { - TCGv_i32 l = tcg_const_i32(get_field(s, l1)); + TCGv_i32 l = tcg_constant_i32(get_field(s, l1)); + gen_helper_unpk(cpu_env, l, o->addr1, o->in2); - tcg_temp_free_i32(l); return DISAS_NEXT; } @@ -4990,9 +4893,8 @@ static DisasJumpType op_unpka(DisasContext *s, DisasOps *o) gen_program_exception(s, PGM_SPECIFICATION); return DISAS_NORETURN; } - l = tcg_const_i32(l1); + l = tcg_constant_i32(l1); gen_helper_unpka(cc_op, cpu_env, o->addr1, l, o->in2); - tcg_temp_free_i32(l); set_cc_static(s); return DISAS_NEXT; } @@ -5007,9 +4909,8 @@ static DisasJumpType op_unpku(DisasContext *s, DisasOps *o) gen_program_exception(s, PGM_SPECIFICATION); return DISAS_NORETURN; } - l = tcg_const_i32(l1); + l = tcg_constant_i32(l1); gen_helper_unpku(cc_op, cpu_env, o->addr1, l, o->in2); - tcg_temp_free_i32(l); set_cc_static(s); return DISAS_NEXT; } @@ -5028,7 +4929,7 @@ static DisasJumpType op_xc(DisasContext *s, DisasOps *o) /* If the addresses are identical, this is a store/memset of zero. */ if (b1 == b2 && d1 == d2 && (l + 1) <= 32) { - o->in2 = tcg_const_i64(0); + o->in2 = tcg_constant_i64(0); l++; while (l >= 8) { @@ -5061,9 +4962,8 @@ static DisasJumpType op_xc(DisasContext *s, DisasOps *o) /* But in general we'll defer to a helper. */ o->in2 = get_address(s, 0, b2, d2); - t32 = tcg_const_i32(l); + t32 = tcg_constant_i32(l); gen_helper_xc(cc_op, cpu_env, t32, o->addr1, o->in2); - tcg_temp_free_i32(t32); set_cc_static(s); return DISAS_NEXT; } @@ -5128,46 +5028,39 @@ static DisasJumpType op_zero2(DisasContext *s, DisasOps *o) #ifndef CONFIG_USER_ONLY static DisasJumpType op_clp(DisasContext *s, DisasOps *o) { - TCGv_i32 r2 = tcg_const_i32(get_field(s, r2)); + TCGv_i32 r2 = tcg_constant_i32(get_field(s, r2)); gen_helper_clp(cpu_env, r2); - tcg_temp_free_i32(r2); set_cc_static(s); return DISAS_NEXT; } static DisasJumpType op_pcilg(DisasContext *s, DisasOps *o) { - TCGv_i32 r1 = tcg_const_i32(get_field(s, r1)); - TCGv_i32 r2 = tcg_const_i32(get_field(s, r2)); + TCGv_i32 r1 = tcg_constant_i32(get_field(s, r1)); + TCGv_i32 r2 = tcg_constant_i32(get_field(s, r2)); gen_helper_pcilg(cpu_env, r1, r2); - tcg_temp_free_i32(r1); - tcg_temp_free_i32(r2); set_cc_static(s); return DISAS_NEXT; } static DisasJumpType op_pcistg(DisasContext *s, DisasOps *o) { - TCGv_i32 r1 = tcg_const_i32(get_field(s, r1)); - TCGv_i32 r2 = tcg_const_i32(get_field(s, r2)); + TCGv_i32 r1 = tcg_constant_i32(get_field(s, r1)); + TCGv_i32 r2 = tcg_constant_i32(get_field(s, r2)); gen_helper_pcistg(cpu_env, r1, r2); - tcg_temp_free_i32(r1); - tcg_temp_free_i32(r2); set_cc_static(s); return DISAS_NEXT; } static DisasJumpType op_stpcifc(DisasContext *s, DisasOps *o) { - TCGv_i32 r1 = tcg_const_i32(get_field(s, r1)); - TCGv_i32 ar = tcg_const_i32(get_field(s, b2)); + TCGv_i32 r1 = tcg_constant_i32(get_field(s, r1)); + TCGv_i32 ar = tcg_constant_i32(get_field(s, b2)); gen_helper_stpcifc(cpu_env, r1, o->addr1, ar); - tcg_temp_free_i32(ar); - tcg_temp_free_i32(r1); set_cc_static(s); return DISAS_NEXT; } @@ -5180,38 +5073,31 @@ static DisasJumpType op_sic(DisasContext *s, DisasOps *o) static DisasJumpType op_rpcit(DisasContext *s, DisasOps *o) { - TCGv_i32 r1 = tcg_const_i32(get_field(s, r1)); - TCGv_i32 r2 = tcg_const_i32(get_field(s, r2)); + TCGv_i32 r1 = tcg_constant_i32(get_field(s, r1)); + TCGv_i32 r2 = tcg_constant_i32(get_field(s, r2)); gen_helper_rpcit(cpu_env, r1, r2); - tcg_temp_free_i32(r1); - tcg_temp_free_i32(r2); set_cc_static(s); return DISAS_NEXT; } static DisasJumpType op_pcistb(DisasContext *s, DisasOps *o) { - TCGv_i32 r1 = tcg_const_i32(get_field(s, r1)); - TCGv_i32 r3 = tcg_const_i32(get_field(s, r3)); - TCGv_i32 ar = tcg_const_i32(get_field(s, b2)); + TCGv_i32 r1 = tcg_constant_i32(get_field(s, r1)); + TCGv_i32 r3 = tcg_constant_i32(get_field(s, r3)); + TCGv_i32 ar = tcg_constant_i32(get_field(s, b2)); gen_helper_pcistb(cpu_env, r1, r3, o->addr1, ar); - tcg_temp_free_i32(ar); - tcg_temp_free_i32(r1); - tcg_temp_free_i32(r3); set_cc_static(s); return DISAS_NEXT; } static DisasJumpType op_mpcifc(DisasContext *s, DisasOps *o) { - TCGv_i32 r1 = tcg_const_i32(get_field(s, r1)); - TCGv_i32 ar = tcg_const_i32(get_field(s, b2)); + TCGv_i32 r1 = tcg_constant_i32(get_field(s, r1)); + TCGv_i32 ar = tcg_constant_i32(get_field(s, b2)); gen_helper_mpcifc(cpu_env, r1, o->addr1, ar); - tcg_temp_free_i32(ar); - tcg_temp_free_i32(r1); set_cc_static(s); return DISAS_NEXT; } @@ -6378,16 +6264,15 @@ static const DisasInsn *extract_insn(CPUS390XState *env, DisasContext *s) if (unlikely(s->ex_value)) { /* Drop the EX data now, so that it's clear on exception paths. */ - TCGv_i64 zero = tcg_const_i64(0); - int i; - tcg_gen_st_i64(zero, cpu_env, offsetof(CPUS390XState, ex_value)); - tcg_temp_free_i64(zero); + tcg_gen_st_i64(tcg_constant_i64(0), cpu_env, + offsetof(CPUS390XState, ex_value)); /* Extract the values saved by EXECUTE. */ insn = s->ex_value & 0xffffffffffff0000ull; ilen = s->ex_value & 0xf; - /* register insn bytes with translator so plugins work */ - for (i = 0; i < ilen; i++) { + + /* Register insn bytes with translator so plugins work. */ + for (int i = 0; i < ilen; i++) { uint8_t byte = extract64(insn, 56 - (i * 8), 8); translator_fake_ldb(byte, pc + i); } @@ -6512,9 +6397,8 @@ static DisasJumpType translate_one(CPUS390XState *env, DisasContext *s) #ifndef CONFIG_USER_ONLY if (s->base.tb->flags & FLAG_MASK_PER) { - TCGv_i64 addr = tcg_const_i64(s->base.pc_next); + TCGv_i64 addr = tcg_constant_i64(s->base.pc_next); gen_helper_per_ifetch(cpu_env, addr); - tcg_temp_free_i64(addr); } #endif From f5d7b0e2e05526585e9cad9284ca265838fd1799 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 20 Feb 2023 08:40:27 -1000 Subject: [PATCH 090/129] target/s390x: Use tcg_constant_* for DisasCompare MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The a and b fields are not modified by the consumer, and while we need not free a constant, tcg will quietly ignore such frees, so free_compare need not be changed. Signed-off-by: Richard Henderson Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Ilya Leoshkevich Message-Id: <20230220184052.163465-3-richard.henderson@linaro.org> Signed-off-by: Thomas Huth --- target/s390x/tcg/translate.c | 44 ++++++++++++++++++------------------ 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/target/s390x/tcg/translate.c b/target/s390x/tcg/translate.c index 35e844ef3c..a534419073 100644 --- a/target/s390x/tcg/translate.c +++ b/target/s390x/tcg/translate.c @@ -845,7 +845,7 @@ static void disas_jcc(DisasContext *s, DisasCompare *c, uint32_t mask) c->is_64 = false; c->u.s32.a = tcg_temp_new_i32(); tcg_gen_extrl_i64_i32(c->u.s32.a, cc_dst); - c->u.s32.b = tcg_const_i32(0); + c->u.s32.b = tcg_constant_i32(0); break; case CC_OP_LTGT_32: case CC_OP_LTUGTU_32: @@ -860,7 +860,7 @@ static void disas_jcc(DisasContext *s, DisasCompare *c, uint32_t mask) case CC_OP_NZ: case CC_OP_FLOGR: c->u.s64.a = cc_dst; - c->u.s64.b = tcg_const_i64(0); + c->u.s64.b = tcg_constant_i64(0); c->g1 = true; break; case CC_OP_LTGT_64: @@ -874,14 +874,14 @@ static void disas_jcc(DisasContext *s, DisasCompare *c, uint32_t mask) case CC_OP_TM_64: case CC_OP_ICM: c->u.s64.a = tcg_temp_new_i64(); - c->u.s64.b = tcg_const_i64(0); + c->u.s64.b = tcg_constant_i64(0); tcg_gen_and_i64(c->u.s64.a, cc_src, cc_dst); break; case CC_OP_ADDU: case CC_OP_SUBU: c->is_64 = true; - c->u.s64.b = tcg_const_i64(0); + c->u.s64.b = tcg_constant_i64(0); c->g1 = true; switch (mask) { case 8 | 2: @@ -904,65 +904,65 @@ static void disas_jcc(DisasContext *s, DisasCompare *c, uint32_t mask) switch (mask) { case 0x8 | 0x4 | 0x2: /* cc != 3 */ cond = TCG_COND_NE; - c->u.s32.b = tcg_const_i32(3); + c->u.s32.b = tcg_constant_i32(3); break; case 0x8 | 0x4 | 0x1: /* cc != 2 */ cond = TCG_COND_NE; - c->u.s32.b = tcg_const_i32(2); + c->u.s32.b = tcg_constant_i32(2); break; case 0x8 | 0x2 | 0x1: /* cc != 1 */ cond = TCG_COND_NE; - c->u.s32.b = tcg_const_i32(1); + c->u.s32.b = tcg_constant_i32(1); break; case 0x8 | 0x2: /* cc == 0 || cc == 2 => (cc & 1) == 0 */ cond = TCG_COND_EQ; c->g1 = false; c->u.s32.a = tcg_temp_new_i32(); - c->u.s32.b = tcg_const_i32(0); + c->u.s32.b = tcg_constant_i32(0); tcg_gen_andi_i32(c->u.s32.a, cc_op, 1); break; case 0x8 | 0x4: /* cc < 2 */ cond = TCG_COND_LTU; - c->u.s32.b = tcg_const_i32(2); + c->u.s32.b = tcg_constant_i32(2); break; case 0x8: /* cc == 0 */ cond = TCG_COND_EQ; - c->u.s32.b = tcg_const_i32(0); + c->u.s32.b = tcg_constant_i32(0); break; case 0x4 | 0x2 | 0x1: /* cc != 0 */ cond = TCG_COND_NE; - c->u.s32.b = tcg_const_i32(0); + c->u.s32.b = tcg_constant_i32(0); break; case 0x4 | 0x1: /* cc == 1 || cc == 3 => (cc & 1) != 0 */ cond = TCG_COND_NE; c->g1 = false; c->u.s32.a = tcg_temp_new_i32(); - c->u.s32.b = tcg_const_i32(0); + c->u.s32.b = tcg_constant_i32(0); tcg_gen_andi_i32(c->u.s32.a, cc_op, 1); break; case 0x4: /* cc == 1 */ cond = TCG_COND_EQ; - c->u.s32.b = tcg_const_i32(1); + c->u.s32.b = tcg_constant_i32(1); break; case 0x2 | 0x1: /* cc > 1 */ cond = TCG_COND_GTU; - c->u.s32.b = tcg_const_i32(1); + c->u.s32.b = tcg_constant_i32(1); break; case 0x2: /* cc == 2 */ cond = TCG_COND_EQ; - c->u.s32.b = tcg_const_i32(2); + c->u.s32.b = tcg_constant_i32(2); break; case 0x1: /* cc == 3 */ cond = TCG_COND_EQ; - c->u.s32.b = tcg_const_i32(3); + c->u.s32.b = tcg_constant_i32(3); break; default: /* CC is masked by something else: (8 >> cc) & mask. */ cond = TCG_COND_NE; c->g1 = false; - c->u.s32.a = tcg_const_i32(8); - c->u.s32.b = tcg_const_i32(0); - tcg_gen_shr_i32(c->u.s32.a, c->u.s32.a, cc_op); + c->u.s32.a = tcg_temp_new_i32(); + c->u.s32.b = tcg_constant_i32(0); + tcg_gen_shr_i32(c->u.s32.a, tcg_constant_i32(8), cc_op); tcg_gen_andi_i32(c->u.s32.a, c->u.s32.a, mask); break; } @@ -1619,7 +1619,7 @@ static DisasJumpType op_bct32(DisasContext *s, DisasOps *o) tcg_gen_subi_i64(t, regs[r1], 1); store_reg32_i64(r1, t); c.u.s32.a = tcg_temp_new_i32(); - c.u.s32.b = tcg_const_i32(0); + c.u.s32.b = tcg_constant_i32(0); tcg_gen_extrl_i64_i32(c.u.s32.a, t); tcg_temp_free_i64(t); @@ -1643,7 +1643,7 @@ static DisasJumpType op_bcth(DisasContext *s, DisasOps *o) tcg_gen_subi_i64(t, t, 1); store_reg32h_i64(r1, t); c.u.s32.a = tcg_temp_new_i32(); - c.u.s32.b = tcg_const_i32(0); + c.u.s32.b = tcg_constant_i32(0); tcg_gen_extrl_i64_i32(c.u.s32.a, t); tcg_temp_free_i64(t); @@ -1664,7 +1664,7 @@ static DisasJumpType op_bct64(DisasContext *s, DisasOps *o) tcg_gen_subi_i64(regs[r1], regs[r1], 1); c.u.s64.a = regs[r1]; - c.u.s64.b = tcg_const_i64(0); + c.u.s64.b = tcg_constant_i64(0); return help_branch(s, &c, is_imm, imm, o->in2); } From 6276d93faa5546e5c616eecc333d9ea397b763ac Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 20 Feb 2023 08:40:28 -1000 Subject: [PATCH 091/129] target/s390x: Use tcg_constant_i32 for fpinst_extract_m34 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Return a constant or NULL, which means the free may be removed from all callers of fpinst_extract_m34. Signed-off-by: Richard Henderson Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Ilya Leoshkevich Message-Id: <20230220184052.163465-4-richard.henderson@linaro.org> Signed-off-by: Thomas Huth --- target/s390x/tcg/translate.c | 26 +------------------------- 1 file changed, 1 insertion(+), 25 deletions(-) diff --git a/target/s390x/tcg/translate.c b/target/s390x/tcg/translate.c index a534419073..faa6f737ba 100644 --- a/target/s390x/tcg/translate.c +++ b/target/s390x/tcg/translate.c @@ -1790,7 +1790,7 @@ static TCGv_i32 fpinst_extract_m34(DisasContext *s, bool m3_with_fpe, return NULL; } - return tcg_const_i32(deposit32(m3, 4, 4, m4)); + return tcg_constant_i32(deposit32(m3, 4, 4, m4)); } static DisasJumpType op_cfeb(DisasContext *s, DisasOps *o) @@ -1801,7 +1801,6 @@ static DisasJumpType op_cfeb(DisasContext *s, DisasOps *o) return DISAS_NORETURN; } gen_helper_cfeb(o->out, cpu_env, o->in2, m34); - tcg_temp_free_i32(m34); set_cc_static(s); return DISAS_NEXT; } @@ -1814,7 +1813,6 @@ static DisasJumpType op_cfdb(DisasContext *s, DisasOps *o) return DISAS_NORETURN; } gen_helper_cfdb(o->out, cpu_env, o->in2, m34); - tcg_temp_free_i32(m34); set_cc_static(s); return DISAS_NEXT; } @@ -1827,7 +1825,6 @@ static DisasJumpType op_cfxb(DisasContext *s, DisasOps *o) return DISAS_NORETURN; } gen_helper_cfxb(o->out, cpu_env, o->in2_128, m34); - tcg_temp_free_i32(m34); set_cc_static(s); return DISAS_NEXT; } @@ -1840,7 +1837,6 @@ static DisasJumpType op_cgeb(DisasContext *s, DisasOps *o) return DISAS_NORETURN; } gen_helper_cgeb(o->out, cpu_env, o->in2, m34); - tcg_temp_free_i32(m34); set_cc_static(s); return DISAS_NEXT; } @@ -1853,7 +1849,6 @@ static DisasJumpType op_cgdb(DisasContext *s, DisasOps *o) return DISAS_NORETURN; } gen_helper_cgdb(o->out, cpu_env, o->in2, m34); - tcg_temp_free_i32(m34); set_cc_static(s); return DISAS_NEXT; } @@ -1866,7 +1861,6 @@ static DisasJumpType op_cgxb(DisasContext *s, DisasOps *o) return DISAS_NORETURN; } gen_helper_cgxb(o->out, cpu_env, o->in2_128, m34); - tcg_temp_free_i32(m34); set_cc_static(s); return DISAS_NEXT; } @@ -1879,7 +1873,6 @@ static DisasJumpType op_clfeb(DisasContext *s, DisasOps *o) return DISAS_NORETURN; } gen_helper_clfeb(o->out, cpu_env, o->in2, m34); - tcg_temp_free_i32(m34); set_cc_static(s); return DISAS_NEXT; } @@ -1892,7 +1885,6 @@ static DisasJumpType op_clfdb(DisasContext *s, DisasOps *o) return DISAS_NORETURN; } gen_helper_clfdb(o->out, cpu_env, o->in2, m34); - tcg_temp_free_i32(m34); set_cc_static(s); return DISAS_NEXT; } @@ -1905,7 +1897,6 @@ static DisasJumpType op_clfxb(DisasContext *s, DisasOps *o) return DISAS_NORETURN; } gen_helper_clfxb(o->out, cpu_env, o->in2_128, m34); - tcg_temp_free_i32(m34); set_cc_static(s); return DISAS_NEXT; } @@ -1918,7 +1909,6 @@ static DisasJumpType op_clgeb(DisasContext *s, DisasOps *o) return DISAS_NORETURN; } gen_helper_clgeb(o->out, cpu_env, o->in2, m34); - tcg_temp_free_i32(m34); set_cc_static(s); return DISAS_NEXT; } @@ -1931,7 +1921,6 @@ static DisasJumpType op_clgdb(DisasContext *s, DisasOps *o) return DISAS_NORETURN; } gen_helper_clgdb(o->out, cpu_env, o->in2, m34); - tcg_temp_free_i32(m34); set_cc_static(s); return DISAS_NEXT; } @@ -1944,7 +1933,6 @@ static DisasJumpType op_clgxb(DisasContext *s, DisasOps *o) return DISAS_NORETURN; } gen_helper_clgxb(o->out, cpu_env, o->in2_128, m34); - tcg_temp_free_i32(m34); set_cc_static(s); return DISAS_NEXT; } @@ -1957,7 +1945,6 @@ static DisasJumpType op_cegb(DisasContext *s, DisasOps *o) return DISAS_NORETURN; } gen_helper_cegb(o->out, cpu_env, o->in2, m34); - tcg_temp_free_i32(m34); return DISAS_NEXT; } @@ -1969,7 +1956,6 @@ static DisasJumpType op_cdgb(DisasContext *s, DisasOps *o) return DISAS_NORETURN; } gen_helper_cdgb(o->out, cpu_env, o->in2, m34); - tcg_temp_free_i32(m34); return DISAS_NEXT; } @@ -1981,7 +1967,6 @@ static DisasJumpType op_cxgb(DisasContext *s, DisasOps *o) return DISAS_NORETURN; } gen_helper_cxgb(o->out_128, cpu_env, o->in2, m34); - tcg_temp_free_i32(m34); return DISAS_NEXT; } @@ -1993,7 +1978,6 @@ static DisasJumpType op_celgb(DisasContext *s, DisasOps *o) return DISAS_NORETURN; } gen_helper_celgb(o->out, cpu_env, o->in2, m34); - tcg_temp_free_i32(m34); return DISAS_NEXT; } @@ -2005,7 +1989,6 @@ static DisasJumpType op_cdlgb(DisasContext *s, DisasOps *o) return DISAS_NORETURN; } gen_helper_cdlgb(o->out, cpu_env, o->in2, m34); - tcg_temp_free_i32(m34); return DISAS_NEXT; } @@ -2017,7 +2000,6 @@ static DisasJumpType op_cxlgb(DisasContext *s, DisasOps *o) return DISAS_NORETURN; } gen_helper_cxlgb(o->out_128, cpu_env, o->in2, m34); - tcg_temp_free_i32(m34); return DISAS_NEXT; } @@ -2486,7 +2468,6 @@ static DisasJumpType op_fieb(DisasContext *s, DisasOps *o) return DISAS_NORETURN; } gen_helper_fieb(o->out, cpu_env, o->in2, m34); - tcg_temp_free_i32(m34); return DISAS_NEXT; } @@ -2498,7 +2479,6 @@ static DisasJumpType op_fidb(DisasContext *s, DisasOps *o) return DISAS_NORETURN; } gen_helper_fidb(o->out, cpu_env, o->in2, m34); - tcg_temp_free_i32(m34); return DISAS_NEXT; } @@ -2510,7 +2490,6 @@ static DisasJumpType op_fixb(DisasContext *s, DisasOps *o) return DISAS_NORETURN; } gen_helper_fixb(o->out_128, cpu_env, o->in2_128, m34); - tcg_temp_free_i32(m34); return DISAS_NEXT; } @@ -2785,7 +2764,6 @@ static DisasJumpType op_ledb(DisasContext *s, DisasOps *o) return DISAS_NORETURN; } gen_helper_ledb(o->out, cpu_env, o->in2, m34); - tcg_temp_free_i32(m34); return DISAS_NEXT; } @@ -2797,7 +2775,6 @@ static DisasJumpType op_ldxb(DisasContext *s, DisasOps *o) return DISAS_NORETURN; } gen_helper_ldxb(o->out, cpu_env, o->in2_128, m34); - tcg_temp_free_i32(m34); return DISAS_NEXT; } @@ -2809,7 +2786,6 @@ static DisasJumpType op_lexb(DisasContext *s, DisasOps *o) return DISAS_NORETURN; } gen_helper_lexb(o->out, cpu_env, o->in2_128, m34); - tcg_temp_free_i32(m34); return DISAS_NEXT; } From 2b0fa727f7d02176a2c620093810402cc744072b Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 20 Feb 2023 08:40:29 -1000 Subject: [PATCH 092/129] target/s390x: Use tcg_constant_* in translate_vx.c.inc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In most cases, this is a simple local allocate and free replaced by tcg_constant_*. In three cases, a variable temp was initialized with a constant value -- reorg to localize the constant. In gen_acc, this fixes a leak. Signed-off-by: Richard Henderson Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Ilya Leoshkevich Message-Id: <20230220184052.163465-5-richard.henderson@linaro.org> Signed-off-by: Thomas Huth --- target/s390x/tcg/translate_vx.c.inc | 45 +++++++++++++---------------- 1 file changed, 20 insertions(+), 25 deletions(-) diff --git a/target/s390x/tcg/translate_vx.c.inc b/target/s390x/tcg/translate_vx.c.inc index d39ee81cd6..3fadc82e5c 100644 --- a/target/s390x/tcg/translate_vx.c.inc +++ b/target/s390x/tcg/translate_vx.c.inc @@ -319,12 +319,10 @@ static void gen_gvec128_4_i64(gen_gvec128_4_i64_fn fn, uint8_t d, uint8_t a, static void gen_addi2_i64(TCGv_i64 dl, TCGv_i64 dh, TCGv_i64 al, TCGv_i64 ah, uint64_t b) { - TCGv_i64 bl = tcg_const_i64(b); - TCGv_i64 bh = tcg_const_i64(0); + TCGv_i64 bl = tcg_constant_i64(b); + TCGv_i64 bh = tcg_constant_i64(0); tcg_gen_add2_i64(dl, dh, al, ah, bl, bh); - tcg_temp_free_i64(bl); - tcg_temp_free_i64(bh); } static DisasJumpType op_vbperm(DisasContext *s, DisasOps *o) @@ -609,9 +607,8 @@ static DisasJumpType op_vlei(DisasContext *s, DisasOps *o) return DISAS_NORETURN; } - tmp = tcg_const_i64((int16_t)get_field(s, i2)); + tmp = tcg_constant_i64((int16_t)get_field(s, i2)); write_vec_element_i64(tmp, get_field(s, v1), enr, es); - tcg_temp_free_i64(tmp); return DISAS_NEXT; } @@ -1107,11 +1104,13 @@ static DisasJumpType op_vseg(DisasContext *s, DisasOps *o) static DisasJumpType op_vst(DisasContext *s, DisasOps *o) { - TCGv_i64 tmp = tcg_const_i64(16); + TCGv_i64 tmp; /* Probe write access before actually modifying memory */ - gen_helper_probe_write_access(cpu_env, o->addr1, tmp); + gen_helper_probe_write_access(cpu_env, o->addr1, + tcg_constant_i64(16)); + tmp = tcg_temp_new_i64(); read_vec_element_i64(tmp, get_field(s, v1), 0, ES_64); tcg_gen_qemu_st_i64(tmp, o->addr1, get_mem_index(s), MO_TEUQ); gen_addi_and_wrap_i64(s, o->addr1, o->addr1, 8); @@ -1270,9 +1269,10 @@ static DisasJumpType op_vstm(DisasContext *s, DisasOps *o) } /* Probe write access before actually modifying memory */ - tmp = tcg_const_i64((v3 - v1 + 1) * 16); - gen_helper_probe_write_access(cpu_env, o->addr1, tmp); + gen_helper_probe_write_access(cpu_env, o->addr1, + tcg_constant_i64((v3 - v1 + 1) * 16)); + tmp = tcg_temp_new_i64(); for (;; v1++) { read_vec_element_i64(tmp, v1, 0, ES_64); tcg_gen_qemu_st_i64(tmp, o->addr1, get_mem_index(s), MO_TEUQ); @@ -1359,7 +1359,7 @@ static DisasJumpType op_va(DisasContext *s, DisasOps *o) static void gen_acc(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b, uint8_t es) { const uint8_t msb_bit_nr = NUM_VEC_ELEMENT_BITS(es) - 1; - TCGv_i64 msb_mask = tcg_const_i64(dup_const(es, 1ull << msb_bit_nr)); + TCGv_i64 msb_mask = tcg_constant_i64(dup_const(es, 1ull << msb_bit_nr)); TCGv_i64 t1 = tcg_temp_new_i64(); TCGv_i64 t2 = tcg_temp_new_i64(); TCGv_i64 t3 = tcg_temp_new_i64(); @@ -1416,7 +1416,7 @@ static void gen_acc2_i64(TCGv_i64 dl, TCGv_i64 dh, TCGv_i64 al, { TCGv_i64 th = tcg_temp_new_i64(); TCGv_i64 tl = tcg_temp_new_i64(); - TCGv_i64 zero = tcg_const_i64(0); + TCGv_i64 zero = tcg_constant_i64(0); tcg_gen_add2_i64(tl, th, al, zero, bl, zero); tcg_gen_add2_i64(tl, th, th, zero, ah, zero); @@ -1425,7 +1425,6 @@ static void gen_acc2_i64(TCGv_i64 dl, TCGv_i64 dh, TCGv_i64 al, tcg_temp_free_i64(th); tcg_temp_free_i64(tl); - tcg_temp_free_i64(zero); } static DisasJumpType op_vacc(DisasContext *s, DisasOps *o) @@ -1455,15 +1454,14 @@ static void gen_ac2_i64(TCGv_i64 dl, TCGv_i64 dh, TCGv_i64 al, TCGv_i64 ah, TCGv_i64 bl, TCGv_i64 bh, TCGv_i64 cl, TCGv_i64 ch) { TCGv_i64 tl = tcg_temp_new_i64(); - TCGv_i64 th = tcg_const_i64(0); + TCGv_i64 zero = tcg_constant_i64(0); /* extract the carry only */ tcg_gen_extract_i64(tl, cl, 0, 1); tcg_gen_add2_i64(dl, dh, al, ah, bl, bh); - tcg_gen_add2_i64(dl, dh, dl, dh, tl, th); + tcg_gen_add2_i64(dl, dh, dl, dh, tl, zero); tcg_temp_free_i64(tl); - tcg_temp_free_i64(th); } static DisasJumpType op_vac(DisasContext *s, DisasOps *o) @@ -1484,7 +1482,7 @@ static void gen_accc2_i64(TCGv_i64 dl, TCGv_i64 dh, TCGv_i64 al, TCGv_i64 ah, { TCGv_i64 tl = tcg_temp_new_i64(); TCGv_i64 th = tcg_temp_new_i64(); - TCGv_i64 zero = tcg_const_i64(0); + TCGv_i64 zero = tcg_constant_i64(0); tcg_gen_andi_i64(tl, cl, 1); tcg_gen_add2_i64(tl, th, tl, zero, al, zero); @@ -1495,7 +1493,6 @@ static void gen_accc2_i64(TCGv_i64 dl, TCGv_i64 dh, TCGv_i64 al, TCGv_i64 ah, tcg_temp_free_i64(tl); tcg_temp_free_i64(th); - tcg_temp_free_i64(zero); } static DisasJumpType op_vaccc(DisasContext *s, DisasOps *o) @@ -1597,14 +1594,13 @@ static void gen_avgl_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b) static void gen_avgl_i64(TCGv_i64 dl, TCGv_i64 al, TCGv_i64 bl) { TCGv_i64 dh = tcg_temp_new_i64(); - TCGv_i64 zero = tcg_const_i64(0); + TCGv_i64 zero = tcg_constant_i64(0); tcg_gen_add2_i64(dl, dh, al, zero, bl, zero); gen_addi2_i64(dl, dh, dl, dh, 1); tcg_gen_extract2_i64(dl, dl, dh, 1); tcg_temp_free_i64(dh); - tcg_temp_free_i64(zero); } static DisasJumpType op_vavgl(DisasContext *s, DisasOps *o) @@ -2440,7 +2436,7 @@ static void gen_scbi2_i64(TCGv_i64 dl, TCGv_i64 dh, TCGv_i64 al, { TCGv_i64 th = tcg_temp_new_i64(); TCGv_i64 tl = tcg_temp_new_i64(); - TCGv_i64 zero = tcg_const_i64(0); + TCGv_i64 zero = tcg_constant_i64(0); tcg_gen_sub2_i64(tl, th, al, zero, bl, zero); tcg_gen_andi_i64(th, th, 1); @@ -2452,7 +2448,6 @@ static void gen_scbi2_i64(TCGv_i64 dl, TCGv_i64 dh, TCGv_i64 al, tcg_temp_free_i64(th); tcg_temp_free_i64(tl); - tcg_temp_free_i64(zero); } static DisasJumpType op_vscbi(DisasContext *s, DisasOps *o) @@ -2572,11 +2567,12 @@ static DisasJumpType op_vsumq(DisasContext *s, DisasOps *o) return DISAS_NORETURN; } - sumh = tcg_const_i64(0); + sumh = tcg_temp_new_i64(); suml = tcg_temp_new_i64(); - zero = tcg_const_i64(0); + zero = tcg_constant_i64(0); tmpl = tcg_temp_new_i64(); + tcg_gen_mov_i64(sumh, zero); read_vec_element_i64(suml, get_field(s, v3), max_idx, es); for (idx = 0; idx <= max_idx; idx++) { read_vec_element_i64(tmpl, get_field(s, v2), idx, es); @@ -2587,7 +2583,6 @@ static DisasJumpType op_vsumq(DisasContext *s, DisasOps *o) tcg_temp_free_i64(sumh); tcg_temp_free_i64(suml); - tcg_temp_free_i64(zero); tcg_temp_free_i64(tmpl); return DISAS_NEXT; } From c78d9269755dce56ac8d16181af46aa969aa7755 Mon Sep 17 00:00:00 2001 From: Ilya Leoshkevich Date: Mon, 20 Feb 2023 08:40:30 -1000 Subject: [PATCH 093/129] tests/tcg/s390x: Add bal.S Add a small test to prevent regressions. Signed-off-by: Ilya Leoshkevich Signed-off-by: Richard Henderson Message-Id: <20221103130011.2670186-1-iii@linux.ibm.com> Message-Id: <20230220184052.163465-6-richard.henderson@linaro.org> Signed-off-by: Thomas Huth --- tests/tcg/s390x/Makefile.softmmu-target | 1 + tests/tcg/s390x/bal.S | 24 ++++++++++++++++++++++++ 2 files changed, 25 insertions(+) create mode 100644 tests/tcg/s390x/bal.S diff --git a/tests/tcg/s390x/Makefile.softmmu-target b/tests/tcg/s390x/Makefile.softmmu-target index 50c1b88065..bcbe9367ef 100644 --- a/tests/tcg/s390x/Makefile.softmmu-target +++ b/tests/tcg/s390x/Makefile.softmmu-target @@ -7,3 +7,4 @@ QEMU_OPTS=-action panic=exit-failure -kernel -Wl,--build-id=none $< -o $@ TESTS += unaligned-lowcore +TESTS += bal diff --git a/tests/tcg/s390x/bal.S b/tests/tcg/s390x/bal.S new file mode 100644 index 0000000000..e54d8874ff --- /dev/null +++ b/tests/tcg/s390x/bal.S @@ -0,0 +1,24 @@ + .org 0x200 /* lowcore padding */ + .globl _start +_start: + lpswe start24_psw +_start24: + lgrl %r0,initial_r0 + lgrl %r1,expected_r0 + bal %r0,0f +0: + cgrjne %r0,%r1,1f + lpswe success_psw +1: + lpswe failure_psw + .align 8 +start24_psw: + .quad 0x160000000000,_start24 /* 24-bit mode, cc = 1, pm = 6 */ +initial_r0: + .quad 0x1234567887654321 +expected_r0: + .quad 0x1234567896000000 + 0b /* ilc = 2, cc = 1, pm = 6 */ +success_psw: + .quad 0x2000000000000,0xfff /* see is_special_wait_psw() */ +failure_psw: + .quad 0x2000000000000,0 /* disabled wait */ From c8db90b86d0849b59452b8cac5b477bb65dcb6a1 Mon Sep 17 00:00:00 2001 From: Ilya Leoshkevich Date: Mon, 20 Feb 2023 08:40:31 -1000 Subject: [PATCH 094/129] tests/tcg/s390x: Add sam.S Add a small test to prevent regressions. Signed-off-by: Ilya Leoshkevich Signed-off-by: Richard Henderson Message-Id: <20221129015328.55439-1-iii@linux.ibm.com> Message-Id: <20230220184052.163465-7-richard.henderson@linaro.org> Signed-off-by: Thomas Huth --- tests/tcg/s390x/Makefile.softmmu-target | 1 + tests/tcg/s390x/sam.S | 67 +++++++++++++++++++++++++ 2 files changed, 68 insertions(+) create mode 100644 tests/tcg/s390x/sam.S diff --git a/tests/tcg/s390x/Makefile.softmmu-target b/tests/tcg/s390x/Makefile.softmmu-target index bcbe9367ef..725b6c598d 100644 --- a/tests/tcg/s390x/Makefile.softmmu-target +++ b/tests/tcg/s390x/Makefile.softmmu-target @@ -8,3 +8,4 @@ QEMU_OPTS=-action panic=exit-failure -kernel TESTS += unaligned-lowcore TESTS += bal +TESTS += sam diff --git a/tests/tcg/s390x/sam.S b/tests/tcg/s390x/sam.S new file mode 100644 index 0000000000..4cab2dd200 --- /dev/null +++ b/tests/tcg/s390x/sam.S @@ -0,0 +1,67 @@ +/* DAT on, home-space mode, 64-bit mode */ +#define DAT_PSWM 0x400c00180000000 +#define VIRTUAL_BASE 0x123456789abcd000 + + .org 0x8e +program_interruption_code: + .org 0x150 +program_old_psw: + .org 0x1d0 /* program new PSW */ + .quad 0,pgm_handler + .org 0x200 /* lowcore padding */ + + .globl _start +_start: + lctlg %c13,%c13,hasce + lpswe dat_psw +start_dat: + sam24 +sam24_suppressed: + /* sam24 should fail */ +fail: + basr %r12,%r0 + lpswe failure_psw-.(%r12) +pgm_handler: + chhsi program_interruption_code,6 /* specification exception? */ + jne fail + clc suppressed_psw(16),program_old_psw /* correct location? */ + jne fail + lpswe success_psw + + .align 8 +dat_psw: + .quad DAT_PSWM,VIRTUAL_BASE+start_dat +suppressed_psw: + .quad DAT_PSWM,VIRTUAL_BASE+sam24_suppressed +success_psw: + .quad 0x2000000000000,0xfff /* see is_special_wait_psw() */ +failure_psw: + .quad 0x2000000000000,0 /* disabled wait */ +hasce: + /* DT = 0b11 (region-first-table), TL = 3 (2k entries) */ + .quad region_first_table + (3 << 2) + 3 + .align 0x1000 +region_first_table: + .org region_first_table + ((VIRTUAL_BASE >> 53) & 0x7ff) * 8 + /* TT = 0b11 (region-first-table), TL = 3 (2k entries) */ + .quad region_second_table + (3 << 2) + 3 + .org region_first_table + 0x800 * 8 +region_second_table: + .org region_second_table + ((VIRTUAL_BASE >> 42) & 0x7ff) * 8 + /* TT = 0b10 (region-second-table), TL = 3 (2k entries) */ + .quad region_third_table + (2 << 2) + 3 + .org region_second_table + 0x800 * 8 +region_third_table: + .org region_third_table + ((VIRTUAL_BASE >> 31) & 0x7ff) * 8 + /* TT = 0b01 (region-third-table), TL = 3 (2k entries) */ + .quad segment_table + (1 << 2) + 3 + .org region_third_table + 0x800 * 8 +segment_table: + .org segment_table + ((VIRTUAL_BASE >> 20) & 0x7ff) * 8 + /* TT = 0b00 (segment-table) */ + .quad page_table + .org segment_table + 0x800 * 8 +page_table: + .org page_table + ((VIRTUAL_BASE >> 12) & 0xff) * 8 + .quad 0 + .org page_table + 0x100 * 8 From f160a5b25b33b69b089815cfd435aa3199497984 Mon Sep 17 00:00:00 2001 From: Dinah Baum Date: Tue, 21 Feb 2023 06:06:30 -0500 Subject: [PATCH 095/129] configure: Add 'mkdir build' check MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit QEMU configure script goes into an infinite error printing loop when in read only directory due to 'build' dir never being created. Checking if 'mkdir dir' succeeds prevents this error. Resolves: https://gitlab.com/qemu-project/qemu/-/issues/321 Reviewed-by: Peter Maydell Signed-off-by: Dinah Baum Message-Id: <20230221110631.4142-1-dinahbaum123@gmail.com> Reviewed-by: Thomas Huth Reviewed-by: Philippe Mathieu-Daudé [thuth: Remove second "touch $MARKER"] Signed-off-by: Thomas Huth --- configure | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/configure b/configure index cf6db3d551..dccb5d4f96 100755 --- a/configure +++ b/configure @@ -31,8 +31,12 @@ then fi fi - mkdir build - touch $MARKER + if ! mkdir build || ! touch $MARKER + then + echo "ERROR: Could not create ./build directory. Check the permissions on" + echo "your source directory, or try doing an out-of-tree build." + exit 1 + fi cat > GNUmakefile <<'EOF' # This file is auto-generated by configure to support in-source tree From 5c70adbfbbf98c22d43fb4df1bac6802b6c61034 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Tue, 21 Feb 2023 12:07:10 +0100 Subject: [PATCH 096/129] qemu-keymap: Silence memory leak warning from Clang's sanitizer When compiling QEMU with "--enable-sanitizers --enable-xkbcommon --cc=clang" there is a memory leak warning when running qemu-keymap: $ ./qemu-keymap -f pc-bios/keymaps/de -l de ================================================================= ==610321==ERROR: LeakSanitizer: detected memory leaks Direct leak of 136 byte(s) in 1 object(s) allocated from: #0 0x5642830d0820 in __interceptor_calloc.part.11 asan_malloc_linux.cpp.o #1 0x7f31873b8d2b in xkb_state_new (/lib64/libxkbcommon.so.0+0x1dd2b) (BuildId: dd32581e2248833243f3f646324ae9b98469f025) SUMMARY: AddressSanitizer: 136 byte(s) leaked in 1 allocation(s). It can be silenced by properly releasing the "state" again after it has been used. Message-Id: <20230221122440.612281-1-thuth@redhat.com> Reviewed-by: Peter Maydell Signed-off-by: Thomas Huth --- qemu-keymap.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/qemu-keymap.c b/qemu-keymap.c index 4095b654a6..229866e004 100644 --- a/qemu-keymap.c +++ b/qemu-keymap.c @@ -226,6 +226,8 @@ int main(int argc, char *argv[]) state = xkb_state_new(map); xkb_keymap_key_for_each(map, walk_map, state); + xkb_state_unref(state); + state = NULL; /* add quirks */ fprintf(outfile, From adf4c9bd2e274968e1abc2430376349eb3f3d392 Mon Sep 17 00:00:00 2001 From: Steve Sistare Date: Mon, 6 Feb 2023 10:34:02 -0800 Subject: [PATCH 097/129] meson: fix dependency on qemu-keymap MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When qemu-keymap is not available on the host, and enable-xkbcommon is specified, parallel make fails with: % make clean ... % make -j 32 ... FAILED: pc-bios/keymaps/is ./qemu-keymap -f pc-bios/keymaps/is -l is /bin/sh: ./qemu-keymap: No such file or directory ... many similar messages ... The code always runs find_program, rather than waiting to build qemu-keymap, because it looks for CONFIG_XKBCOMMON in config_host rather than config_host_data. Making serially succeeds, by soft linking files from pc-bios/keymaps, but that is not the desired result for enable-xkbcommon. Examining all occurrences of 'in config_host' for similar bugs shows one instance in the docs, which is also fixed here. Fixes: 4113f4cfee ("meson: move xkbcommon to meson") Signed-off-by: Steve Sistare Reviewed-by: Marc-André Lureau Message-Id: <1675708442-74966-1-git-send-email-steven.sistare@oracle.com> Signed-off-by: Thomas Huth --- docs/devel/kconfig.rst | 2 +- pc-bios/keymaps/meson.build | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/devel/kconfig.rst b/docs/devel/kconfig.rst index 69674d008a..cc1a456edf 100644 --- a/docs/devel/kconfig.rst +++ b/docs/devel/kconfig.rst @@ -306,6 +306,6 @@ variable:: host_kconfig = \ (have_tpm ? ['CONFIG_TPM=y'] : []) + \ - ('CONFIG_SPICE' in config_host ? ['CONFIG_SPICE=y'] : []) + \ + ('CONFIG_LINUX' in config_host ? ['CONFIG_LINUX=y'] : []) + \ (have_ivshmem ? ['CONFIG_IVSHMEM=y'] : []) + \ ... diff --git a/pc-bios/keymaps/meson.build b/pc-bios/keymaps/meson.build index 06c75e646b..158a3b410c 100644 --- a/pc-bios/keymaps/meson.build +++ b/pc-bios/keymaps/meson.build @@ -33,7 +33,7 @@ keymaps = { 'tr': '-l tr', } -if meson.is_cross_build() or 'CONFIG_XKBCOMMON' not in config_host +if meson.is_cross_build() or not xkbcommon.found() native_qemu_keymap = find_program('qemu-keymap', required: false, disabler: true) else native_qemu_keymap = qemu_keymap From 0c201cc17fef05f9fa771b462ad979d8b2f4f526 Mon Sep 17 00:00:00 2001 From: Khadija Kamran Date: Mon, 20 Feb 2023 07:01:09 +0000 Subject: [PATCH 098/129] Updated the FSF address to The Free Software Foundation moved to a new address and some sources in QEMU referred to their old location. The address should be updated and replaced by a pointer to Resolves: https://gitlab.com/qemu-project/qemu/-/issues/379 Signed-off-by: Khadija Kamran Message-Id: <576ee9203fdac99d7251a98faa66b9ce1e7febc5.1675941486.git.kkamran.bese16seecs@seecs.edu.pk> Reviewed-by: Stefan Weil Signed-off-by: Thomas Huth --- contrib/gitdm/filetypes.txt | 3 +-- hw/scsi/viosrp.h | 3 +-- hw/sh4/sh7750_regs.h | 3 +-- include/hw/arm/raspi_platform.h | 3 +-- include/qemu/uri.h | 3 +-- tests/qemu-iotests/022 | 4 +--- tests/unit/rcutorture.c | 3 +-- tests/unit/test-rcu-list.c | 3 +-- util/uri.c | 3 +-- 9 files changed, 9 insertions(+), 19 deletions(-) diff --git a/contrib/gitdm/filetypes.txt b/contrib/gitdm/filetypes.txt index d2d6f6db8d..b1d01c0992 100644 --- a/contrib/gitdm/filetypes.txt +++ b/contrib/gitdm/filetypes.txt @@ -12,8 +12,7 @@ # GNU Library General Public License for more details. # # You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# along with this program. If not, see . # # Authors : Gregorio Robles # Authors : Germán Póo-Caamaño diff --git a/hw/scsi/viosrp.h b/hw/scsi/viosrp.h index e5f9768e8f..58c29aa925 100644 --- a/hw/scsi/viosrp.h +++ b/hw/scsi/viosrp.h @@ -16,8 +16,7 @@ /* 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, write to the Free Software */ -/* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +/* along with this program. If not, see . */ /* */ /* */ /* This file contains structures and definitions for IBM RPA (RS/6000 */ diff --git a/hw/sh4/sh7750_regs.h b/hw/sh4/sh7750_regs.h index beb571d5e9..94043431e6 100644 --- a/hw/sh4/sh7750_regs.h +++ b/hw/sh4/sh7750_regs.h @@ -22,8 +22,7 @@ * 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 RTEMS; see - * file COPYING. If not, write to the Free Software Foundation, 675 - * Mass Ave, Cambridge, MA 02139, USA. + * file COPYING. If not, see . * * As a special exception, including RTEMS header files in a file, * instantiating RTEMS generics or templates, or linking other files diff --git a/include/hw/arm/raspi_platform.h b/include/hw/arm/raspi_platform.h index e0e6c8ce94..4a56dd4b89 100644 --- a/include/hw/arm/raspi_platform.h +++ b/include/hw/arm/raspi_platform.h @@ -18,8 +18,7 @@ * 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, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * along with this program. If not, see . * * Various undocumented addresses and names come from Herman Hermitage's VC4 * documentation: diff --git a/include/qemu/uri.h b/include/qemu/uri.h index db5218c39e..3ad211d676 100644 --- a/include/qemu/uri.h +++ b/include/qemu/uri.h @@ -41,8 +41,7 @@ * 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, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * License along with this library. If not, see . * * Authors: * Richard W.M. Jones diff --git a/tests/qemu-iotests/022 b/tests/qemu-iotests/022 index a116cfe255..d98d1ea90f 100755 --- a/tests/qemu-iotests/022 +++ b/tests/qemu-iotests/022 @@ -16,9 +16,7 @@ # 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, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 -# USA +# along with this program. If not, see . # # creator diff --git a/tests/unit/rcutorture.c b/tests/unit/rcutorture.c index 495a4e6f42..7662081683 100644 --- a/tests/unit/rcutorture.c +++ b/tests/unit/rcutorture.c @@ -50,8 +50,7 @@ * 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * along with this program. If not, see . * * Copyright (c) 2008 Paul E. McKenney, IBM Corporation. */ diff --git a/tests/unit/test-rcu-list.c b/tests/unit/test-rcu-list.c index 64b81ae058..9964171da4 100644 --- a/tests/unit/test-rcu-list.c +++ b/tests/unit/test-rcu-list.c @@ -14,8 +14,7 @@ * 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * along with this program. If not, see . * * Copyright (c) 2013 Mike D. Day, IBM Corporation. */ diff --git a/util/uri.c b/util/uri.c index ff72c6005f..dcb3305236 100644 --- a/util/uri.c +++ b/util/uri.c @@ -43,8 +43,7 @@ * 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, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * License along with this library. If not, see . * * Authors: * Richard W.M. Jones From 6eda5ef5f8f43ee992586a29d4323f3359695650 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Tue, 7 Feb 2023 21:14:44 +0100 Subject: [PATCH 099/129] gitlab-ci.d/buildtest: Remove aarch64-softmmu from the build-system-ubuntu job MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit aarch64-softmmu is also checked on the same version of Ubuntu in the gcov job, so it is redundant to check again in the normal ubuntu job. Message-Id: <20230207201447.566661-3-thuth@redhat.com> Reviewed-by: David Woodhouse Reviewed-by: Daniel P. Berrangé Signed-off-by: Thomas Huth --- .gitlab-ci.d/buildtest.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.d/buildtest.yml b/.gitlab-ci.d/buildtest.yml index 8f332fc36f..8fff961b44 100644 --- a/.gitlab-ci.d/buildtest.yml +++ b/.gitlab-ci.d/buildtest.yml @@ -42,7 +42,7 @@ build-system-ubuntu: variables: IMAGE: ubuntu2004 CONFIGURE_ARGS: --enable-docs --enable-fdt=system --enable-capstone - TARGETS: aarch64-softmmu alpha-softmmu cris-softmmu hppa-softmmu + TARGETS: alpha-softmmu cris-softmmu hppa-softmmu microblazeel-softmmu mips64el-softmmu MAKE_CHECK_ARGS: check-build artifacts: From 2f5a375f6033fcb4cedd6874852ff3def5841c95 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Tue, 7 Feb 2023 21:14:45 +0100 Subject: [PATCH 100/129] gitlab-ci.d/buildtest: Disintegrate the build-coroutine-sigaltstack job MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We can get rid of the build-coroutine-sigaltstack job by moving the configure flags that should be tested here to other jobs: Move --with-coroutine=sigaltstack to the build-system-debian job (where the coroutines should get some more test coverage with "make check-block", too) and --enable-trace-backends=ftrace to the cross-s390x-kvm-only job. Message-Id: <20230207201447.566661-4-thuth@redhat.com> Reviewed-by: David Woodhouse Reviewed-by: Daniel P. Berrangé Signed-off-by: Thomas Huth --- .gitlab-ci.d/buildtest.yml | 13 +------------ .gitlab-ci.d/crossbuilds.yml | 2 +- 2 files changed, 2 insertions(+), 13 deletions(-) diff --git a/.gitlab-ci.d/buildtest.yml b/.gitlab-ci.d/buildtest.yml index 8fff961b44..8697c61072 100644 --- a/.gitlab-ci.d/buildtest.yml +++ b/.gitlab-ci.d/buildtest.yml @@ -74,6 +74,7 @@ build-system-debian: job: amd64-debian-container variables: IMAGE: debian-amd64 + CONFIGURE_ARGS: --with-coroutine=sigaltstack TARGETS: arm-softmmu avr-softmmu i386-softmmu mipsel-softmmu riscv64-softmmu sh4eb-softmmu sparc-softmmu xtensaeb-softmmu MAKE_CHECK_ARGS: check-build @@ -534,18 +535,6 @@ build-tci: - QTEST_QEMU_BINARY="./qemu-system-s390x" ./tests/qtest/pxe-test -m slow - make check-tcg -# Alternate coroutines implementations are only really of interest to KVM users -# However we can't test against KVM on Gitlab-CI so we can only run unit tests -build-coroutine-sigaltstack: - extends: .native_build_job_template - needs: - job: amd64-ubuntu2004-container - variables: - IMAGE: ubuntu2004 - CONFIGURE_ARGS: --with-coroutine=sigaltstack --disable-tcg - --enable-trace-backends=ftrace - MAKE_CHECK_ARGS: check-unit - # Check our reduced build configurations build-without-defaults: extends: .native_build_job_template diff --git a/.gitlab-ci.d/crossbuilds.yml b/.gitlab-ci.d/crossbuilds.yml index 74d6259b90..57637c5127 100644 --- a/.gitlab-ci.d/crossbuilds.yml +++ b/.gitlab-ci.d/crossbuilds.yml @@ -159,7 +159,7 @@ cross-s390x-kvm-only: job: s390x-debian-cross-container variables: IMAGE: debian-s390x-cross - EXTRA_CONFIGURE_OPTS: --disable-tcg + EXTRA_CONFIGURE_OPTS: --disable-tcg --enable-trace-backends=ftrace cross-mips64el-kvm-only: extends: .cross_accel_build_job From 22ebcba061f882c4cc4a77124d1e9f13cd3b1a07 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Tue, 7 Feb 2023 21:14:46 +0100 Subject: [PATCH 101/129] gitlab-ci.d/buildtest-template: Simplify the configure step It's easier to use ${TARGETS:+--target-list="$TARGETS"} to add a --target-list parameter depending on whether the TARGETS variable is set or not. Message-Id: <20230207201447.566661-5-thuth@redhat.com> Reviewed-by: David Woodhouse Signed-off-by: Thomas Huth --- .gitlab-ci.d/buildtest-template.yml | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/.gitlab-ci.d/buildtest-template.yml b/.gitlab-ci.d/buildtest-template.yml index 73ecfabb8d..4a922d9c33 100644 --- a/.gitlab-ci.d/buildtest-template.yml +++ b/.gitlab-ci.d/buildtest-template.yml @@ -11,12 +11,10 @@ fi - mkdir build - cd build - - if test -n "$TARGETS"; - then - ../configure --enable-werror --disable-docs ${LD_JOBS:+--meson=git} $CONFIGURE_ARGS --target-list="$TARGETS" ; - else - ../configure --enable-werror --disable-docs ${LD_JOBS:+--meson=git} $CONFIGURE_ARGS ; - fi || { cat config.log meson-logs/meson-log.txt && exit 1; } + - ../configure --enable-werror --disable-docs + ${LD_JOBS:+--meson=git} ${TARGETS:+--target-list="$TARGETS"} + $CONFIGURE_ARGS || + { cat config.log meson-logs/meson-log.txt && exit 1; } - if test -n "$LD_JOBS"; then ../meson/meson.py configure . -Dbackend_max_links="$LD_JOBS" ; From eda2321d7f807d3cc5a98aea34bbab82e2e8a7e6 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Tue, 7 Feb 2023 21:14:47 +0100 Subject: [PATCH 102/129] gitlab-ci.d: Build with --enable-fdt=system by default MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit By using --enable-fdt=system we can make sure that the configure script does not try to check out the "dtc" submodule. This should help to safe some precious CI minutes in the long run. While we're at it, also drop some now-redundant --enable-slirp and --enable-capstone statements. These used to have the "=system" suffix in the past, too, which has been dropped when the their corresponding submodules had been removed. Since these features are auto-enabled anyway now (since the containers have the right libraries installed), we do not need the explicit --enable-... statements anymore. Message-Id: <20230207201447.566661-6-thuth@redhat.com> Reviewed-by: Daniel P. Berrangé Signed-off-by: Thomas Huth --- .gitlab-ci.d/buildtest-template.yml | 2 +- .gitlab-ci.d/buildtest.yml | 9 +++------ .gitlab-ci.d/crossbuild-template.yml | 5 +++-- .gitlab-ci.d/crossbuilds.yml | 2 ++ .gitlab-ci.d/windows.yml | 7 +++++-- 5 files changed, 14 insertions(+), 11 deletions(-) diff --git a/.gitlab-ci.d/buildtest-template.yml b/.gitlab-ci.d/buildtest-template.yml index 4a922d9c33..cb96b55c3f 100644 --- a/.gitlab-ci.d/buildtest-template.yml +++ b/.gitlab-ci.d/buildtest-template.yml @@ -11,7 +11,7 @@ fi - mkdir build - cd build - - ../configure --enable-werror --disable-docs + - ../configure --enable-werror --disable-docs --enable-fdt=system ${LD_JOBS:+--meson=git} ${TARGETS:+--target-list="$TARGETS"} $CONFIGURE_ARGS || { cat config.log meson-logs/meson-log.txt && exit 1; } diff --git a/.gitlab-ci.d/buildtest.yml b/.gitlab-ci.d/buildtest.yml index 8697c61072..d903c42798 100644 --- a/.gitlab-ci.d/buildtest.yml +++ b/.gitlab-ci.d/buildtest.yml @@ -41,7 +41,7 @@ build-system-ubuntu: job: amd64-ubuntu2004-container variables: IMAGE: ubuntu2004 - CONFIGURE_ARGS: --enable-docs --enable-fdt=system --enable-capstone + CONFIGURE_ARGS: --enable-docs TARGETS: alpha-softmmu cris-softmmu hppa-softmmu microblazeel-softmmu mips64el-softmmu MAKE_CHECK_ARGS: check-build @@ -120,7 +120,6 @@ build-system-fedora: variables: IMAGE: fedora CONFIGURE_ARGS: --disable-gcrypt --enable-nettle --enable-docs - --enable-fdt=system --enable-slirp --enable-capstone TARGETS: tricore-softmmu microblaze-softmmu mips-softmmu xtensa-softmmu m68k-softmmu riscv32-softmmu ppc-softmmu sparc64-softmmu MAKE_CHECK_ARGS: check-build @@ -166,9 +165,8 @@ build-system-centos: job: amd64-centos8-container variables: IMAGE: centos8 - CONFIGURE_ARGS: --disable-nettle --enable-gcrypt --enable-fdt=system + CONFIGURE_ARGS: --disable-nettle --enable-gcrypt --enable-vfio-user-server --enable-modules --enable-trace-backends=dtrace --enable-docs - --enable-vfio-user-server TARGETS: ppc64-softmmu or1k-softmmu s390x-softmmu x86_64-softmmu rx-softmmu sh4-softmmu nios2-softmmu MAKE_CHECK_ARGS: check-build @@ -201,7 +199,6 @@ build-system-opensuse: job: amd64-opensuse-leap-container variables: IMAGE: opensuse-leap - CONFIGURE_ARGS: --enable-fdt=system TARGETS: s390x-softmmu x86_64-softmmu aarch64-softmmu MAKE_CHECK_ARGS: check-build artifacts: @@ -464,7 +461,7 @@ tsan-build: variables: IMAGE: ubuntu2004 CONFIGURE_ARGS: --enable-tsan --cc=clang-10 --cxx=clang++-10 - --enable-trace-backends=ust --enable-fdt=system --disable-slirp + --enable-trace-backends=ust --disable-slirp TARGETS: x86_64-softmmu ppc64-softmmu riscv64-softmmu x86_64-linux-user MAKE_CHECK_ARGS: bench V=1 diff --git a/.gitlab-ci.d/crossbuild-template.yml b/.gitlab-ci.d/crossbuild-template.yml index 6d709628f1..d07989e3b0 100644 --- a/.gitlab-ci.d/crossbuild-template.yml +++ b/.gitlab-ci.d/crossbuild-template.yml @@ -6,8 +6,9 @@ script: - mkdir build - cd build - - ../configure --enable-werror --disable-docs $QEMU_CONFIGURE_OPTS - --disable-user --target-list-exclude="arm-softmmu cris-softmmu + - ../configure --enable-werror --disable-docs --enable-fdt=system + --disable-user $QEMU_CONFIGURE_OPTS $EXTRA_CONFIGURE_OPTS + --target-list-exclude="arm-softmmu cris-softmmu i386-softmmu microblaze-softmmu mips-softmmu mipsel-softmmu mips64-softmmu ppc-softmmu riscv32-softmmu sh4-softmmu sparc-softmmu xtensa-softmmu $CROSS_SKIP_TARGETS" diff --git a/.gitlab-ci.d/crossbuilds.yml b/.gitlab-ci.d/crossbuilds.yml index 57637c5127..101416080c 100644 --- a/.gitlab-ci.d/crossbuilds.yml +++ b/.gitlab-ci.d/crossbuilds.yml @@ -175,6 +175,7 @@ cross-win32-system: job: win32-fedora-cross-container variables: IMAGE: fedora-win32-cross + EXTRA_CONFIGURE_OPTS: --enable-fdt=internal CROSS_SKIP_TARGETS: alpha-softmmu avr-softmmu hppa-softmmu m68k-softmmu microblazeel-softmmu mips64el-softmmu nios2-softmmu artifacts: @@ -187,6 +188,7 @@ cross-win64-system: job: win64-fedora-cross-container variables: IMAGE: fedora-win64-cross + EXTRA_CONFIGURE_OPTS: --enable-fdt=internal CROSS_SKIP_TARGETS: alpha-softmmu avr-softmmu hppa-softmmu m68k-softmmu microblazeel-softmmu nios2-softmmu or1k-softmmu rx-softmmu sh4eb-softmmu sparc64-softmmu diff --git a/.gitlab-ci.d/windows.yml b/.gitlab-ci.d/windows.yml index cf445b77f6..87235e43b4 100644 --- a/.gitlab-ci.d/windows.yml +++ b/.gitlab-ci.d/windows.yml @@ -38,6 +38,7 @@ msys2-64bit: mingw-w64-x86_64-capstone mingw-w64-x86_64-curl mingw-w64-x86_64-cyrus-sasl + mingw-w64-x86_64-dtc mingw-w64-x86_64-gcc mingw-w64-x86_64-glib2 mingw-w64-x86_64-gnutls @@ -71,7 +72,7 @@ msys2-64bit: # for the msys2 64-bit job, due to the build could not complete within # the project timeout. - ..\msys64\usr\bin\bash -lc '../configure --target-list=x86_64-softmmu - --without-default-devices' + --without-default-devices --enable-fdt=system' - ..\msys64\usr\bin\bash -lc 'make' # qTests don't run successfully with "--without-default-devices", # so let's exclude the qtests from CI for now. @@ -86,6 +87,7 @@ msys2-32bit: mingw-w64-i686-capstone mingw-w64-i686-curl mingw-w64-i686-cyrus-sasl + mingw-w64-i686-dtc mingw-w64-i686-gcc mingw-w64-i686-glib2 mingw-w64-i686-gnutls @@ -113,7 +115,8 @@ msys2-32bit: - $env:MSYS = 'winsymlinks:native' # Enable native Windows symlink - mkdir output - cd output - - ..\msys64\usr\bin\bash -lc '../configure --target-list=ppc64-softmmu' + - ..\msys64\usr\bin\bash -lc '../configure --target-list=ppc64-softmmu + --enable-fdt=system' - ..\msys64\usr\bin\bash -lc 'make' - ..\msys64\usr\bin\bash -lc 'make check MTESTARGS=\"--no-suite qtest\" || { cat meson-logs/testlog.txt; exit 1; }' From e97a9b8ce6aaefcd2523010946609245b8a1bd8c Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Thu, 23 Feb 2023 20:13:43 +0100 Subject: [PATCH 103/129] gitlab-ci.d/base: Mark jobs as interruptible by default When handling pull requests in the staging branch, it often happens that one of the job fails due to a problem, so that the pull request can't be merged. Peter/Richard/Stefan then informs the sender of the pull request and continues by pushing the next pending pull request from another subsystem maintainer. Now the problem is that there might still be lots of other running jobs in the pipeline of the first pull request, eating up precious CI minutes though the pipeline is not needed anymore. We can avoid this by marking the jobs as "interruptible". With this setting, the jobs from previous pipelines are automatically terminated when pushing a new one. If someone does not like this auto- matic termination, it can still be disabled in the settings of the repository. See this URL for details: https://docs.gitlab.com/ee/ci/yaml/index.html#interruptible Message-Id: <20230223191343.1064274-1-thuth@redhat.com> Signed-off-by: Thomas Huth --- .gitlab-ci.d/base.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitlab-ci.d/base.yml b/.gitlab-ci.d/base.yml index 50fb59e147..0274228de8 100644 --- a/.gitlab-ci.d/base.yml +++ b/.gitlab-ci.d/base.yml @@ -11,6 +11,8 @@ # and show the duration of each line. FF_SCRIPT_SECTIONS: 1 + interruptible: true + rules: ############################################################# # Stage 1: exclude scenarios where we definitely don't From fffa36b68e2f266c8b03ef3fdd242aa9a9181a87 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Fri, 24 Feb 2023 10:05:43 +0100 Subject: [PATCH 104/129] Deprecate the "-no-acpi" command line switch MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Similar to "-no-hpet", the "-no-acpi" switch is a legacy command line option that should be replaced with the "acpi" machine parameter nowadays. Message-Id: <20230224090543.1129677-1-thuth@redhat.com> Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Peter Krempa Reviewed-by: Igor Mammedov Reviewed-by: Sunil V L Signed-off-by: Thomas Huth --- docs/about/deprecated.rst | 6 ++++++ softmmu/vl.c | 1 + 2 files changed, 7 insertions(+) diff --git a/docs/about/deprecated.rst b/docs/about/deprecated.rst index ee95bcb1a6..15084f7bea 100644 --- a/docs/about/deprecated.rst +++ b/docs/about/deprecated.rst @@ -99,6 +99,12 @@ form is preferred. The HPET setting has been turned into a machine property. Use ``-machine hpet=off`` instead. +``-no-acpi`` (since 8.0) +'''''''''''''''''''''''' + +The ``-no-acpi`` setting has been turned into a machine property. +Use ``-machine acpi=off`` instead. + ``-accel hax`` (since 8.0) '''''''''''''''''''''''''' diff --git a/softmmu/vl.c b/softmmu/vl.c index 6e526d95bb..f29e4c4dc3 100644 --- a/softmmu/vl.c +++ b/softmmu/vl.c @@ -3264,6 +3264,7 @@ void qemu_init(int argc, char **argv) vnc_parse(optarg); break; case QEMU_OPTION_no_acpi: + warn_report("-no-acpi is deprecated, use '-machine acpi=off' instead"); qdict_put_str(machine_opts_dict, "acpi", "off"); break; case QEMU_OPTION_no_hpet: From 212154821e6dc400315a67ad8204f5e5c4b3023c Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Tue, 21 Feb 2023 13:37:14 +0000 Subject: [PATCH 105/129] include/hw/arm/allwinner-a10.h: Remove superfluous includes from the header MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit pci_device.h is not needed at all in allwinner-a10.h, and serial.h is only needed by the corresponding .c file. Signed-off-by: Thomas Huth Reviewed-by: Alex Bennée Message-id: 20230215152233.210024-1-thuth@redhat.com Signed-off-by: Peter Maydell --- hw/arm/allwinner-a10.c | 1 + include/hw/arm/allwinner-a10.h | 2 -- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/hw/arm/allwinner-a10.c b/hw/arm/allwinner-a10.c index dc1966ff7a..b7ca795c71 100644 --- a/hw/arm/allwinner-a10.c +++ b/hw/arm/allwinner-a10.c @@ -18,6 +18,7 @@ #include "qemu/osdep.h" #include "qapi/error.h" #include "qemu/module.h" +#include "hw/char/serial.h" #include "hw/sysbus.h" #include "hw/arm/allwinner-a10.h" #include "hw/misc/unimp.h" diff --git a/include/hw/arm/allwinner-a10.h b/include/hw/arm/allwinner-a10.h index 79e0c80568..095afb225d 100644 --- a/include/hw/arm/allwinner-a10.h +++ b/include/hw/arm/allwinner-a10.h @@ -1,9 +1,7 @@ #ifndef HW_ARM_ALLWINNER_A10_H #define HW_ARM_ALLWINNER_A10_H -#include "hw/char/serial.h" #include "hw/arm/boot.h" -#include "hw/pci/pci_device.h" #include "hw/timer/allwinner-a10-pit.h" #include "hw/intc/allwinner-a10-pic.h" #include "hw/net/allwinner_emac.h" From fa05d1abb998a3272f97a70db2f8a01852ebc06c Mon Sep 17 00:00:00 2001 From: Fabiano Rosas Date: Fri, 17 Feb 2023 17:11:27 -0300 Subject: [PATCH 106/129] target/arm: Wrap breakpoint/watchpoint updates with tcg_enabled This is in preparation for restricting compilation of some parts of debug_helper.c to TCG only. Signed-off-by: Fabiano Rosas Reviewed-by: Richard Henderson Signed-off-by: Peter Maydell --- target/arm/cpu.c | 6 ++++-- target/arm/debug_helper.c | 16 ++++++++++++---- target/arm/machine.c | 7 +++++-- 3 files changed, 21 insertions(+), 8 deletions(-) diff --git a/target/arm/cpu.c b/target/arm/cpu.c index 876ab8f3bf..da416f7b1c 100644 --- a/target/arm/cpu.c +++ b/target/arm/cpu.c @@ -539,8 +539,10 @@ static void arm_cpu_reset_hold(Object *obj) } #endif - hw_breakpoint_update_all(cpu); - hw_watchpoint_update_all(cpu); + if (tcg_enabled()) { + hw_breakpoint_update_all(cpu); + hw_watchpoint_update_all(cpu); + } arm_rebuild_hflags(env); } diff --git a/target/arm/debug_helper.c b/target/arm/debug_helper.c index 3c671c88c1..3325eb9d7d 100644 --- a/target/arm/debug_helper.c +++ b/target/arm/debug_helper.c @@ -939,7 +939,9 @@ static void dbgwvr_write(CPUARMState *env, const ARMCPRegInfo *ri, value &= ~3ULL; raw_write(env, ri, value); - hw_watchpoint_update(cpu, i); + if (tcg_enabled()) { + hw_watchpoint_update(cpu, i); + } } static void dbgwcr_write(CPUARMState *env, const ARMCPRegInfo *ri, @@ -949,7 +951,9 @@ static void dbgwcr_write(CPUARMState *env, const ARMCPRegInfo *ri, int i = ri->crm; raw_write(env, ri, value); - hw_watchpoint_update(cpu, i); + if (tcg_enabled()) { + hw_watchpoint_update(cpu, i); + } } void hw_breakpoint_update(ARMCPU *cpu, int n) @@ -1062,7 +1066,9 @@ static void dbgbvr_write(CPUARMState *env, const ARMCPRegInfo *ri, int i = ri->crm; raw_write(env, ri, value); - hw_breakpoint_update(cpu, i); + if (tcg_enabled()) { + hw_breakpoint_update(cpu, i); + } } static void dbgbcr_write(CPUARMState *env, const ARMCPRegInfo *ri, @@ -1079,7 +1085,9 @@ static void dbgbcr_write(CPUARMState *env, const ARMCPRegInfo *ri, value = deposit64(value, 8, 1, extract64(value, 7, 1)); raw_write(env, ri, value); - hw_breakpoint_update(cpu, i); + if (tcg_enabled()) { + hw_breakpoint_update(cpu, i); + } } void define_debug_regs(ARMCPU *cpu) diff --git a/target/arm/machine.c b/target/arm/machine.c index b4c3850570..fd6323f6d8 100644 --- a/target/arm/machine.c +++ b/target/arm/machine.c @@ -2,6 +2,7 @@ #include "cpu.h" #include "qemu/error-report.h" #include "sysemu/kvm.h" +#include "sysemu/tcg.h" #include "kvm_arm.h" #include "internals.h" #include "migration/cpu.h" @@ -848,8 +849,10 @@ static int cpu_post_load(void *opaque, int version_id) return -1; } - hw_breakpoint_update_all(cpu); - hw_watchpoint_update_all(cpu); + if (tcg_enabled()) { + hw_breakpoint_update_all(cpu); + hw_watchpoint_update_all(cpu); + } /* * TCG gen_update_fp_context() relies on the invariant that From 2059ec754f9040a6a9f62a9abfeb76a9d8655e11 Mon Sep 17 00:00:00 2001 From: Fabiano Rosas Date: Fri, 17 Feb 2023 17:11:28 -0300 Subject: [PATCH 107/129] target/arm: Wrap TCG-only code in debug_helper.c The next few patches will move helpers under CONFIG_TCG. We'd prefer to keep the debug helpers and debug registers close together, so rearrange the file a bit to be able to wrap the helpers with a TCG ifdef. Signed-off-by: Fabiano Rosas Reviewed-by: Richard Henderson Signed-off-by: Peter Maydell --- target/arm/debug_helper.c | 476 +++++++++++++++++++------------------- 1 file changed, 239 insertions(+), 237 deletions(-) diff --git a/target/arm/debug_helper.c b/target/arm/debug_helper.c index 3325eb9d7d..dfc8b2a1a5 100644 --- a/target/arm/debug_helper.c +++ b/target/arm/debug_helper.c @@ -12,8 +12,9 @@ #include "cpregs.h" #include "exec/exec-all.h" #include "exec/helper-proto.h" +#include "sysemu/tcg.h" - +#ifdef CONFIG_TCG /* Return the Exception Level targeted by debug exceptions. */ static int arm_debug_target_el(CPUARMState *env) { @@ -536,6 +537,243 @@ void HELPER(exception_swstep)(CPUARMState *env, uint32_t syndrome) raise_exception_debug(env, EXCP_UDEF, syndrome); } +void hw_watchpoint_update(ARMCPU *cpu, int n) +{ + CPUARMState *env = &cpu->env; + vaddr len = 0; + vaddr wvr = env->cp15.dbgwvr[n]; + uint64_t wcr = env->cp15.dbgwcr[n]; + int mask; + int flags = BP_CPU | BP_STOP_BEFORE_ACCESS; + + if (env->cpu_watchpoint[n]) { + cpu_watchpoint_remove_by_ref(CPU(cpu), env->cpu_watchpoint[n]); + env->cpu_watchpoint[n] = NULL; + } + + if (!FIELD_EX64(wcr, DBGWCR, E)) { + /* E bit clear : watchpoint disabled */ + return; + } + + switch (FIELD_EX64(wcr, DBGWCR, LSC)) { + case 0: + /* LSC 00 is reserved and must behave as if the wp is disabled */ + return; + case 1: + flags |= BP_MEM_READ; + break; + case 2: + flags |= BP_MEM_WRITE; + break; + case 3: + flags |= BP_MEM_ACCESS; + break; + } + + /* + * Attempts to use both MASK and BAS fields simultaneously are + * CONSTRAINED UNPREDICTABLE; we opt to ignore BAS in this case, + * thus generating a watchpoint for every byte in the masked region. + */ + mask = FIELD_EX64(wcr, DBGWCR, MASK); + if (mask == 1 || mask == 2) { + /* + * Reserved values of MASK; we must act as if the mask value was + * some non-reserved value, or as if the watchpoint were disabled. + * We choose the latter. + */ + return; + } else if (mask) { + /* Watchpoint covers an aligned area up to 2GB in size */ + len = 1ULL << mask; + /* + * If masked bits in WVR are not zero it's CONSTRAINED UNPREDICTABLE + * whether the watchpoint fires when the unmasked bits match; we opt + * to generate the exceptions. + */ + wvr &= ~(len - 1); + } else { + /* Watchpoint covers bytes defined by the byte address select bits */ + int bas = FIELD_EX64(wcr, DBGWCR, BAS); + int basstart; + + if (extract64(wvr, 2, 1)) { + /* + * Deprecated case of an only 4-aligned address. BAS[7:4] are + * ignored, and BAS[3:0] define which bytes to watch. + */ + bas &= 0xf; + } + + if (bas == 0) { + /* This must act as if the watchpoint is disabled */ + return; + } + + /* + * The BAS bits are supposed to be programmed to indicate a contiguous + * range of bytes. Otherwise it is CONSTRAINED UNPREDICTABLE whether + * we fire for each byte in the word/doubleword addressed by the WVR. + * We choose to ignore any non-zero bits after the first range of 1s. + */ + basstart = ctz32(bas); + len = cto32(bas >> basstart); + wvr += basstart; + } + + cpu_watchpoint_insert(CPU(cpu), wvr, len, flags, + &env->cpu_watchpoint[n]); +} + +void hw_watchpoint_update_all(ARMCPU *cpu) +{ + int i; + CPUARMState *env = &cpu->env; + + /* + * Completely clear out existing QEMU watchpoints and our array, to + * avoid possible stale entries following migration load. + */ + cpu_watchpoint_remove_all(CPU(cpu), BP_CPU); + memset(env->cpu_watchpoint, 0, sizeof(env->cpu_watchpoint)); + + for (i = 0; i < ARRAY_SIZE(cpu->env.cpu_watchpoint); i++) { + hw_watchpoint_update(cpu, i); + } +} + +void hw_breakpoint_update(ARMCPU *cpu, int n) +{ + CPUARMState *env = &cpu->env; + uint64_t bvr = env->cp15.dbgbvr[n]; + uint64_t bcr = env->cp15.dbgbcr[n]; + vaddr addr; + int bt; + int flags = BP_CPU; + + if (env->cpu_breakpoint[n]) { + cpu_breakpoint_remove_by_ref(CPU(cpu), env->cpu_breakpoint[n]); + env->cpu_breakpoint[n] = NULL; + } + + if (!extract64(bcr, 0, 1)) { + /* E bit clear : watchpoint disabled */ + return; + } + + bt = extract64(bcr, 20, 4); + + switch (bt) { + case 4: /* unlinked address mismatch (reserved if AArch64) */ + case 5: /* linked address mismatch (reserved if AArch64) */ + qemu_log_mask(LOG_UNIMP, + "arm: address mismatch breakpoint types not implemented\n"); + return; + case 0: /* unlinked address match */ + case 1: /* linked address match */ + { + /* + * Bits [1:0] are RES0. + * + * It is IMPLEMENTATION DEFINED whether bits [63:49] + * ([63:53] for FEAT_LVA) are hardwired to a copy of the sign bit + * of the VA field ([48] or [52] for FEAT_LVA), or whether the + * value is read as written. It is CONSTRAINED UNPREDICTABLE + * whether the RESS bits are ignored when comparing an address. + * Therefore we are allowed to compare the entire register, which + * lets us avoid considering whether FEAT_LVA is actually enabled. + * + * The BAS field is used to allow setting breakpoints on 16-bit + * wide instructions; it is CONSTRAINED UNPREDICTABLE whether + * a bp will fire if the addresses covered by the bp and the addresses + * covered by the insn overlap but the insn doesn't start at the + * start of the bp address range. We choose to require the insn and + * the bp to have the same address. The constraints on writing to + * BAS enforced in dbgbcr_write mean we have only four cases: + * 0b0000 => no breakpoint + * 0b0011 => breakpoint on addr + * 0b1100 => breakpoint on addr + 2 + * 0b1111 => breakpoint on addr + * See also figure D2-3 in the v8 ARM ARM (DDI0487A.c). + */ + int bas = extract64(bcr, 5, 4); + addr = bvr & ~3ULL; + if (bas == 0) { + return; + } + if (bas == 0xc) { + addr += 2; + } + break; + } + case 2: /* unlinked context ID match */ + case 8: /* unlinked VMID match (reserved if no EL2) */ + case 10: /* unlinked context ID and VMID match (reserved if no EL2) */ + qemu_log_mask(LOG_UNIMP, + "arm: unlinked context breakpoint types not implemented\n"); + return; + case 9: /* linked VMID match (reserved if no EL2) */ + case 11: /* linked context ID and VMID match (reserved if no EL2) */ + case 3: /* linked context ID match */ + default: + /* + * We must generate no events for Linked context matches (unless + * they are linked to by some other bp/wp, which is handled in + * updates for the linking bp/wp). We choose to also generate no events + * for reserved values. + */ + return; + } + + cpu_breakpoint_insert(CPU(cpu), addr, flags, &env->cpu_breakpoint[n]); +} + +void hw_breakpoint_update_all(ARMCPU *cpu) +{ + int i; + CPUARMState *env = &cpu->env; + + /* + * Completely clear out existing QEMU breakpoints and our array, to + * avoid possible stale entries following migration load. + */ + cpu_breakpoint_remove_all(CPU(cpu), BP_CPU); + memset(env->cpu_breakpoint, 0, sizeof(env->cpu_breakpoint)); + + for (i = 0; i < ARRAY_SIZE(cpu->env.cpu_breakpoint); i++) { + hw_breakpoint_update(cpu, i); + } +} + +#if !defined(CONFIG_USER_ONLY) + +vaddr arm_adjust_watchpoint_address(CPUState *cs, vaddr addr, int len) +{ + ARMCPU *cpu = ARM_CPU(cs); + CPUARMState *env = &cpu->env; + + /* + * In BE32 system mode, target memory is stored byteswapped (on a + * little-endian host system), and by the time we reach here (via an + * opcode helper) the addresses of subword accesses have been adjusted + * to account for that, which means that watchpoints will not match. + * Undo the adjustment here. + */ + if (arm_sctlr_b(env)) { + if (len == 1) { + addr ^= 3; + } else if (len == 2) { + addr ^= 2; + } + } + + return addr; +} + +#endif /* !CONFIG_USER_ONLY */ +#endif /* CONFIG_TCG */ + /* * Check for traps to "powerdown debug" registers, which are controlled * by MDCR.TDOSA @@ -813,112 +1051,6 @@ static const ARMCPRegInfo debug_lpae_cp_reginfo[] = { .access = PL0_R, .type = ARM_CP_CONST | ARM_CP_64BIT, .resetvalue = 0 }, }; -void hw_watchpoint_update(ARMCPU *cpu, int n) -{ - CPUARMState *env = &cpu->env; - vaddr len = 0; - vaddr wvr = env->cp15.dbgwvr[n]; - uint64_t wcr = env->cp15.dbgwcr[n]; - int mask; - int flags = BP_CPU | BP_STOP_BEFORE_ACCESS; - - if (env->cpu_watchpoint[n]) { - cpu_watchpoint_remove_by_ref(CPU(cpu), env->cpu_watchpoint[n]); - env->cpu_watchpoint[n] = NULL; - } - - if (!FIELD_EX64(wcr, DBGWCR, E)) { - /* E bit clear : watchpoint disabled */ - return; - } - - switch (FIELD_EX64(wcr, DBGWCR, LSC)) { - case 0: - /* LSC 00 is reserved and must behave as if the wp is disabled */ - return; - case 1: - flags |= BP_MEM_READ; - break; - case 2: - flags |= BP_MEM_WRITE; - break; - case 3: - flags |= BP_MEM_ACCESS; - break; - } - - /* - * Attempts to use both MASK and BAS fields simultaneously are - * CONSTRAINED UNPREDICTABLE; we opt to ignore BAS in this case, - * thus generating a watchpoint for every byte in the masked region. - */ - mask = FIELD_EX64(wcr, DBGWCR, MASK); - if (mask == 1 || mask == 2) { - /* - * Reserved values of MASK; we must act as if the mask value was - * some non-reserved value, or as if the watchpoint were disabled. - * We choose the latter. - */ - return; - } else if (mask) { - /* Watchpoint covers an aligned area up to 2GB in size */ - len = 1ULL << mask; - /* - * If masked bits in WVR are not zero it's CONSTRAINED UNPREDICTABLE - * whether the watchpoint fires when the unmasked bits match; we opt - * to generate the exceptions. - */ - wvr &= ~(len - 1); - } else { - /* Watchpoint covers bytes defined by the byte address select bits */ - int bas = FIELD_EX64(wcr, DBGWCR, BAS); - int basstart; - - if (extract64(wvr, 2, 1)) { - /* - * Deprecated case of an only 4-aligned address. BAS[7:4] are - * ignored, and BAS[3:0] define which bytes to watch. - */ - bas &= 0xf; - } - - if (bas == 0) { - /* This must act as if the watchpoint is disabled */ - return; - } - - /* - * The BAS bits are supposed to be programmed to indicate a contiguous - * range of bytes. Otherwise it is CONSTRAINED UNPREDICTABLE whether - * we fire for each byte in the word/doubleword addressed by the WVR. - * We choose to ignore any non-zero bits after the first range of 1s. - */ - basstart = ctz32(bas); - len = cto32(bas >> basstart); - wvr += basstart; - } - - cpu_watchpoint_insert(CPU(cpu), wvr, len, flags, - &env->cpu_watchpoint[n]); -} - -void hw_watchpoint_update_all(ARMCPU *cpu) -{ - int i; - CPUARMState *env = &cpu->env; - - /* - * Completely clear out existing QEMU watchpoints and our array, to - * avoid possible stale entries following migration load. - */ - cpu_watchpoint_remove_all(CPU(cpu), BP_CPU); - memset(env->cpu_watchpoint, 0, sizeof(env->cpu_watchpoint)); - - for (i = 0; i < ARRAY_SIZE(cpu->env.cpu_watchpoint); i++) { - hw_watchpoint_update(cpu, i); - } -} - static void dbgwvr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) { @@ -956,109 +1088,6 @@ static void dbgwcr_write(CPUARMState *env, const ARMCPRegInfo *ri, } } -void hw_breakpoint_update(ARMCPU *cpu, int n) -{ - CPUARMState *env = &cpu->env; - uint64_t bvr = env->cp15.dbgbvr[n]; - uint64_t bcr = env->cp15.dbgbcr[n]; - vaddr addr; - int bt; - int flags = BP_CPU; - - if (env->cpu_breakpoint[n]) { - cpu_breakpoint_remove_by_ref(CPU(cpu), env->cpu_breakpoint[n]); - env->cpu_breakpoint[n] = NULL; - } - - if (!extract64(bcr, 0, 1)) { - /* E bit clear : watchpoint disabled */ - return; - } - - bt = extract64(bcr, 20, 4); - - switch (bt) { - case 4: /* unlinked address mismatch (reserved if AArch64) */ - case 5: /* linked address mismatch (reserved if AArch64) */ - qemu_log_mask(LOG_UNIMP, - "arm: address mismatch breakpoint types not implemented\n"); - return; - case 0: /* unlinked address match */ - case 1: /* linked address match */ - { - /* - * Bits [1:0] are RES0. - * - * It is IMPLEMENTATION DEFINED whether bits [63:49] - * ([63:53] for FEAT_LVA) are hardwired to a copy of the sign bit - * of the VA field ([48] or [52] for FEAT_LVA), or whether the - * value is read as written. It is CONSTRAINED UNPREDICTABLE - * whether the RESS bits are ignored when comparing an address. - * Therefore we are allowed to compare the entire register, which - * lets us avoid considering whether FEAT_LVA is actually enabled. - * - * The BAS field is used to allow setting breakpoints on 16-bit - * wide instructions; it is CONSTRAINED UNPREDICTABLE whether - * a bp will fire if the addresses covered by the bp and the addresses - * covered by the insn overlap but the insn doesn't start at the - * start of the bp address range. We choose to require the insn and - * the bp to have the same address. The constraints on writing to - * BAS enforced in dbgbcr_write mean we have only four cases: - * 0b0000 => no breakpoint - * 0b0011 => breakpoint on addr - * 0b1100 => breakpoint on addr + 2 - * 0b1111 => breakpoint on addr - * See also figure D2-3 in the v8 ARM ARM (DDI0487A.c). - */ - int bas = extract64(bcr, 5, 4); - addr = bvr & ~3ULL; - if (bas == 0) { - return; - } - if (bas == 0xc) { - addr += 2; - } - break; - } - case 2: /* unlinked context ID match */ - case 8: /* unlinked VMID match (reserved if no EL2) */ - case 10: /* unlinked context ID and VMID match (reserved if no EL2) */ - qemu_log_mask(LOG_UNIMP, - "arm: unlinked context breakpoint types not implemented\n"); - return; - case 9: /* linked VMID match (reserved if no EL2) */ - case 11: /* linked context ID and VMID match (reserved if no EL2) */ - case 3: /* linked context ID match */ - default: - /* - * We must generate no events for Linked context matches (unless - * they are linked to by some other bp/wp, which is handled in - * updates for the linking bp/wp). We choose to also generate no events - * for reserved values. - */ - return; - } - - cpu_breakpoint_insert(CPU(cpu), addr, flags, &env->cpu_breakpoint[n]); -} - -void hw_breakpoint_update_all(ARMCPU *cpu) -{ - int i; - CPUARMState *env = &cpu->env; - - /* - * Completely clear out existing QEMU breakpoints and our array, to - * avoid possible stale entries following migration load. - */ - cpu_breakpoint_remove_all(CPU(cpu), BP_CPU); - memset(env->cpu_breakpoint, 0, sizeof(env->cpu_breakpoint)); - - for (i = 0; i < ARRAY_SIZE(cpu->env.cpu_breakpoint); i++) { - hw_breakpoint_update(cpu, i); - } -} - static void dbgbvr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) { @@ -1210,30 +1239,3 @@ void define_debug_regs(ARMCPU *cpu) g_free(dbgwcr_el1_name); } } - -#if !defined(CONFIG_USER_ONLY) - -vaddr arm_adjust_watchpoint_address(CPUState *cs, vaddr addr, int len) -{ - ARMCPU *cpu = ARM_CPU(cs); - CPUARMState *env = &cpu->env; - - /* - * In BE32 system mode, target memory is stored byteswapped (on a - * little-endian host system), and by the time we reach here (via an - * opcode helper) the addresses of subword accesses have been adjusted - * to account for that, which means that watchpoints will not match. - * Undo the adjustment here. - */ - if (arm_sctlr_b(env)) { - if (len == 1) { - addr ^= 3; - } else if (len == 2) { - addr ^= 2; - } - } - - return addr; -} - -#endif From f0984d4040c328d1c021ae6680479cbbe13c485b Mon Sep 17 00:00:00 2001 From: Fabiano Rosas Date: Fri, 17 Feb 2023 17:11:29 -0300 Subject: [PATCH 108/129] target/arm: move translate modules to tcg/ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Introduce the target/arm/tcg directory. Its purpose is to hold the TCG code that is selected by CONFIG_TCG. Signed-off-by: Claudio Fontana Signed-off-by: Fabiano Rosas Reviewed-by: Richard Henderson Reviewed-by: Alex Bennée Reviewed-by: Philippe Mathieu-Daudé Tested-by: Philippe Mathieu-Daudé Signed-off-by: Peter Maydell --- MAINTAINERS | 1 + target/arm/meson.build | 30 ++++------------------- target/arm/{ => tcg}/a32-uncond.decode | 0 target/arm/{ => tcg}/a32.decode | 0 target/arm/{ => tcg}/m-nocp.decode | 0 target/arm/tcg/meson.build | 32 +++++++++++++++++++++++++ target/arm/{ => tcg}/mve.decode | 0 target/arm/{ => tcg}/neon-dp.decode | 0 target/arm/{ => tcg}/neon-ls.decode | 0 target/arm/{ => tcg}/neon-shared.decode | 0 target/arm/{ => tcg}/sme-fa64.decode | 0 target/arm/{ => tcg}/sme.decode | 0 target/arm/{ => tcg}/sve.decode | 0 target/arm/{ => tcg}/t16.decode | 0 target/arm/{ => tcg}/t32.decode | 0 target/arm/{ => tcg}/translate-a64.c | 0 target/arm/{ => tcg}/translate-a64.h | 0 target/arm/{ => tcg}/translate-m-nocp.c | 0 target/arm/{ => tcg}/translate-mve.c | 0 target/arm/{ => tcg}/translate-neon.c | 0 target/arm/{ => tcg}/translate-sme.c | 0 target/arm/{ => tcg}/translate-sve.c | 0 target/arm/{ => tcg}/translate-vfp.c | 0 target/arm/{ => tcg}/translate.c | 0 target/arm/{ => tcg}/translate.h | 0 target/arm/{ => tcg}/vfp-uncond.decode | 0 target/arm/{ => tcg}/vfp.decode | 0 27 files changed, 37 insertions(+), 26 deletions(-) rename target/arm/{ => tcg}/a32-uncond.decode (100%) rename target/arm/{ => tcg}/a32.decode (100%) rename target/arm/{ => tcg}/m-nocp.decode (100%) create mode 100644 target/arm/tcg/meson.build rename target/arm/{ => tcg}/mve.decode (100%) rename target/arm/{ => tcg}/neon-dp.decode (100%) rename target/arm/{ => tcg}/neon-ls.decode (100%) rename target/arm/{ => tcg}/neon-shared.decode (100%) rename target/arm/{ => tcg}/sme-fa64.decode (100%) rename target/arm/{ => tcg}/sme.decode (100%) rename target/arm/{ => tcg}/sve.decode (100%) rename target/arm/{ => tcg}/t16.decode (100%) rename target/arm/{ => tcg}/t32.decode (100%) rename target/arm/{ => tcg}/translate-a64.c (100%) rename target/arm/{ => tcg}/translate-a64.h (100%) rename target/arm/{ => tcg}/translate-m-nocp.c (100%) rename target/arm/{ => tcg}/translate-mve.c (100%) rename target/arm/{ => tcg}/translate-neon.c (100%) rename target/arm/{ => tcg}/translate-sme.c (100%) rename target/arm/{ => tcg}/translate-sve.c (100%) rename target/arm/{ => tcg}/translate-vfp.c (100%) rename target/arm/{ => tcg}/translate.c (100%) rename target/arm/{ => tcg}/translate.h (100%) rename target/arm/{ => tcg}/vfp-uncond.decode (100%) rename target/arm/{ => tcg}/vfp.decode (100%) diff --git a/MAINTAINERS b/MAINTAINERS index 5c1ee41139..c6e6549f06 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -161,6 +161,7 @@ M: Peter Maydell L: qemu-arm@nongnu.org S: Maintained F: target/arm/ +F: target/arm/tcg/ F: tests/tcg/arm/ F: tests/tcg/aarch64/ F: tests/qtest/arm-cpu-features.c diff --git a/target/arm/meson.build b/target/arm/meson.build index 87e911b27f..b2904b676b 100644 --- a/target/arm/meson.build +++ b/target/arm/meson.build @@ -1,22 +1,4 @@ -gen = [ - decodetree.process('sve.decode', extra_args: '--decode=disas_sve'), - decodetree.process('sme.decode', extra_args: '--decode=disas_sme'), - decodetree.process('sme-fa64.decode', extra_args: '--static-decode=disas_sme_fa64'), - decodetree.process('neon-shared.decode', extra_args: '--decode=disas_neon_shared'), - decodetree.process('neon-dp.decode', extra_args: '--decode=disas_neon_dp'), - decodetree.process('neon-ls.decode', extra_args: '--decode=disas_neon_ls'), - decodetree.process('vfp.decode', extra_args: '--decode=disas_vfp'), - decodetree.process('vfp-uncond.decode', extra_args: '--decode=disas_vfp_uncond'), - decodetree.process('m-nocp.decode', extra_args: '--decode=disas_m_nocp'), - decodetree.process('mve.decode', extra_args: '--decode=disas_mve'), - decodetree.process('a32.decode', extra_args: '--static-decode=disas_a32'), - decodetree.process('a32-uncond.decode', extra_args: '--static-decode=disas_a32_uncond'), - decodetree.process('t32.decode', extra_args: '--static-decode=disas_t32'), - decodetree.process('t16.decode', extra_args: ['-w', '16', '--static-decode=disas_t16']), -] - arm_ss = ss.source_set() -arm_ss.add(gen) arm_ss.add(files( 'cpu.c', 'crypto_helper.c', @@ -29,11 +11,6 @@ arm_ss.add(files( 'neon_helper.c', 'op_helper.c', 'tlb_helper.c', - 'translate.c', - 'translate-m-nocp.c', - 'translate-mve.c', - 'translate-neon.c', - 'translate-vfp.c', 'vec_helper.c', 'vfp_helper.c', 'cpu_tcg.c', @@ -50,9 +27,6 @@ arm_ss.add(when: 'TARGET_AARCH64', if_true: files( 'pauth_helper.c', 'sve_helper.c', 'sme_helper.c', - 'translate-a64.c', - 'translate-sve.c', - 'translate-sme.c', )) arm_softmmu_ss = ss.source_set() @@ -67,5 +41,9 @@ arm_softmmu_ss.add(files( subdir('hvf') +if 'CONFIG_TCG' in config_all + subdir('tcg') +endif + target_arch += {'arm': arm_ss} target_softmmu_arch += {'arm': arm_softmmu_ss} diff --git a/target/arm/a32-uncond.decode b/target/arm/tcg/a32-uncond.decode similarity index 100% rename from target/arm/a32-uncond.decode rename to target/arm/tcg/a32-uncond.decode diff --git a/target/arm/a32.decode b/target/arm/tcg/a32.decode similarity index 100% rename from target/arm/a32.decode rename to target/arm/tcg/a32.decode diff --git a/target/arm/m-nocp.decode b/target/arm/tcg/m-nocp.decode similarity index 100% rename from target/arm/m-nocp.decode rename to target/arm/tcg/m-nocp.decode diff --git a/target/arm/tcg/meson.build b/target/arm/tcg/meson.build new file mode 100644 index 0000000000..044561bd4d --- /dev/null +++ b/target/arm/tcg/meson.build @@ -0,0 +1,32 @@ +gen = [ + decodetree.process('sve.decode', extra_args: '--decode=disas_sve'), + decodetree.process('sme.decode', extra_args: '--decode=disas_sme'), + decodetree.process('sme-fa64.decode', extra_args: '--static-decode=disas_sme_fa64'), + decodetree.process('neon-shared.decode', extra_args: '--decode=disas_neon_shared'), + decodetree.process('neon-dp.decode', extra_args: '--decode=disas_neon_dp'), + decodetree.process('neon-ls.decode', extra_args: '--decode=disas_neon_ls'), + decodetree.process('vfp.decode', extra_args: '--decode=disas_vfp'), + decodetree.process('vfp-uncond.decode', extra_args: '--decode=disas_vfp_uncond'), + decodetree.process('m-nocp.decode', extra_args: '--decode=disas_m_nocp'), + decodetree.process('mve.decode', extra_args: '--decode=disas_mve'), + decodetree.process('a32.decode', extra_args: '--static-decode=disas_a32'), + decodetree.process('a32-uncond.decode', extra_args: '--static-decode=disas_a32_uncond'), + decodetree.process('t32.decode', extra_args: '--static-decode=disas_t32'), + decodetree.process('t16.decode', extra_args: ['-w', '16', '--static-decode=disas_t16']), +] + +arm_ss.add(gen) + +arm_ss.add(files( + 'translate.c', + 'translate-m-nocp.c', + 'translate-mve.c', + 'translate-neon.c', + 'translate-vfp.c', +)) + +arm_ss.add(when: 'TARGET_AARCH64', if_true: files( + 'translate-a64.c', + 'translate-sve.c', + 'translate-sme.c', +)) diff --git a/target/arm/mve.decode b/target/arm/tcg/mve.decode similarity index 100% rename from target/arm/mve.decode rename to target/arm/tcg/mve.decode diff --git a/target/arm/neon-dp.decode b/target/arm/tcg/neon-dp.decode similarity index 100% rename from target/arm/neon-dp.decode rename to target/arm/tcg/neon-dp.decode diff --git a/target/arm/neon-ls.decode b/target/arm/tcg/neon-ls.decode similarity index 100% rename from target/arm/neon-ls.decode rename to target/arm/tcg/neon-ls.decode diff --git a/target/arm/neon-shared.decode b/target/arm/tcg/neon-shared.decode similarity index 100% rename from target/arm/neon-shared.decode rename to target/arm/tcg/neon-shared.decode diff --git a/target/arm/sme-fa64.decode b/target/arm/tcg/sme-fa64.decode similarity index 100% rename from target/arm/sme-fa64.decode rename to target/arm/tcg/sme-fa64.decode diff --git a/target/arm/sme.decode b/target/arm/tcg/sme.decode similarity index 100% rename from target/arm/sme.decode rename to target/arm/tcg/sme.decode diff --git a/target/arm/sve.decode b/target/arm/tcg/sve.decode similarity index 100% rename from target/arm/sve.decode rename to target/arm/tcg/sve.decode diff --git a/target/arm/t16.decode b/target/arm/tcg/t16.decode similarity index 100% rename from target/arm/t16.decode rename to target/arm/tcg/t16.decode diff --git a/target/arm/t32.decode b/target/arm/tcg/t32.decode similarity index 100% rename from target/arm/t32.decode rename to target/arm/tcg/t32.decode diff --git a/target/arm/translate-a64.c b/target/arm/tcg/translate-a64.c similarity index 100% rename from target/arm/translate-a64.c rename to target/arm/tcg/translate-a64.c diff --git a/target/arm/translate-a64.h b/target/arm/tcg/translate-a64.h similarity index 100% rename from target/arm/translate-a64.h rename to target/arm/tcg/translate-a64.h diff --git a/target/arm/translate-m-nocp.c b/target/arm/tcg/translate-m-nocp.c similarity index 100% rename from target/arm/translate-m-nocp.c rename to target/arm/tcg/translate-m-nocp.c diff --git a/target/arm/translate-mve.c b/target/arm/tcg/translate-mve.c similarity index 100% rename from target/arm/translate-mve.c rename to target/arm/tcg/translate-mve.c diff --git a/target/arm/translate-neon.c b/target/arm/tcg/translate-neon.c similarity index 100% rename from target/arm/translate-neon.c rename to target/arm/tcg/translate-neon.c diff --git a/target/arm/translate-sme.c b/target/arm/tcg/translate-sme.c similarity index 100% rename from target/arm/translate-sme.c rename to target/arm/tcg/translate-sme.c diff --git a/target/arm/translate-sve.c b/target/arm/tcg/translate-sve.c similarity index 100% rename from target/arm/translate-sve.c rename to target/arm/tcg/translate-sve.c diff --git a/target/arm/translate-vfp.c b/target/arm/tcg/translate-vfp.c similarity index 100% rename from target/arm/translate-vfp.c rename to target/arm/tcg/translate-vfp.c diff --git a/target/arm/translate.c b/target/arm/tcg/translate.c similarity index 100% rename from target/arm/translate.c rename to target/arm/tcg/translate.c diff --git a/target/arm/translate.h b/target/arm/tcg/translate.h similarity index 100% rename from target/arm/translate.h rename to target/arm/tcg/translate.h diff --git a/target/arm/vfp-uncond.decode b/target/arm/tcg/vfp-uncond.decode similarity index 100% rename from target/arm/vfp-uncond.decode rename to target/arm/tcg/vfp-uncond.decode diff --git a/target/arm/vfp.decode b/target/arm/tcg/vfp.decode similarity index 100% rename from target/arm/vfp.decode rename to target/arm/tcg/vfp.decode From a3ef070ea9b2d9af95422b38b022f11d8c302d2e Mon Sep 17 00:00:00 2001 From: Claudio Fontana Date: Fri, 17 Feb 2023 17:11:30 -0300 Subject: [PATCH 109/129] target/arm: move helpers to tcg/ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Claudio Fontana Signed-off-by: Fabiano Rosas Reviewed-by: Richard Henderson Reviewed-by: Philippe Mathieu-Daudé Tested-by: Philippe Mathieu-Daudé Signed-off-by: Peter Maydell --- target/arm/meson.build | 15 ++------------- target/arm/tcg-stubs.c | 23 +++++++++++++++++++++++ target/arm/{ => tcg}/crypto_helper.c | 0 target/arm/{ => tcg}/helper-a64.c | 0 target/arm/{ => tcg}/iwmmxt_helper.c | 0 target/arm/{ => tcg}/m_helper.c | 0 target/arm/tcg/meson.build | 13 +++++++++++++ target/arm/{ => tcg}/mte_helper.c | 0 target/arm/{ => tcg}/mve_helper.c | 0 target/arm/{ => tcg}/neon_helper.c | 0 target/arm/{ => tcg}/op_helper.c | 0 target/arm/{ => tcg}/pauth_helper.c | 0 target/arm/{ => tcg}/sme_helper.c | 0 target/arm/{ => tcg}/sve_helper.c | 0 target/arm/{ => tcg}/tlb_helper.c | 0 target/arm/{ => tcg}/vec_helper.c | 0 target/arm/{ => tcg}/vec_internal.h | 0 17 files changed, 38 insertions(+), 13 deletions(-) create mode 100644 target/arm/tcg-stubs.c rename target/arm/{ => tcg}/crypto_helper.c (100%) rename target/arm/{ => tcg}/helper-a64.c (100%) rename target/arm/{ => tcg}/iwmmxt_helper.c (100%) rename target/arm/{ => tcg}/m_helper.c (100%) rename target/arm/{ => tcg}/mte_helper.c (100%) rename target/arm/{ => tcg}/mve_helper.c (100%) rename target/arm/{ => tcg}/neon_helper.c (100%) rename target/arm/{ => tcg}/op_helper.c (100%) rename target/arm/{ => tcg}/pauth_helper.c (100%) rename target/arm/{ => tcg}/sme_helper.c (100%) rename target/arm/{ => tcg}/sve_helper.c (100%) rename target/arm/{ => tcg}/tlb_helper.c (100%) rename target/arm/{ => tcg}/vec_helper.c (100%) rename target/arm/{ => tcg}/vec_internal.h (100%) diff --git a/target/arm/meson.build b/target/arm/meson.build index b2904b676b..3e2f403005 100644 --- a/target/arm/meson.build +++ b/target/arm/meson.build @@ -1,17 +1,9 @@ arm_ss = ss.source_set() arm_ss.add(files( 'cpu.c', - 'crypto_helper.c', 'debug_helper.c', 'gdbstub.c', 'helper.c', - 'iwmmxt_helper.c', - 'm_helper.c', - 'mve_helper.c', - 'neon_helper.c', - 'op_helper.c', - 'tlb_helper.c', - 'vec_helper.c', 'vfp_helper.c', 'cpu_tcg.c', )) @@ -22,11 +14,6 @@ arm_ss.add(when: 'CONFIG_KVM', if_true: files('kvm.c', 'kvm64.c'), if_false: fil arm_ss.add(when: 'TARGET_AARCH64', if_true: files( 'cpu64.c', 'gdbstub64.c', - 'helper-a64.c', - 'mte_helper.c', - 'pauth_helper.c', - 'sve_helper.c', - 'sme_helper.c', )) arm_softmmu_ss = ss.source_set() @@ -43,6 +30,8 @@ subdir('hvf') if 'CONFIG_TCG' in config_all subdir('tcg') +else + arm_ss.add(files('tcg-stubs.c')) endif target_arch += {'arm': arm_ss} diff --git a/target/arm/tcg-stubs.c b/target/arm/tcg-stubs.c new file mode 100644 index 0000000000..1a7ddb3664 --- /dev/null +++ b/target/arm/tcg-stubs.c @@ -0,0 +1,23 @@ +/* + * QEMU ARM stubs for some TCG helper functions + * + * Copyright 2021 SUSE LLC + * + * 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 "cpu.h" +#include "internals.h" + +void write_v7m_exception(CPUARMState *env, uint32_t new_exc) +{ + g_assert_not_reached(); +} + +void raise_exception_ra(CPUARMState *env, uint32_t excp, uint32_t syndrome, + uint32_t target_el, uintptr_t ra) +{ + g_assert_not_reached(); +} diff --git a/target/arm/crypto_helper.c b/target/arm/tcg/crypto_helper.c similarity index 100% rename from target/arm/crypto_helper.c rename to target/arm/tcg/crypto_helper.c diff --git a/target/arm/helper-a64.c b/target/arm/tcg/helper-a64.c similarity index 100% rename from target/arm/helper-a64.c rename to target/arm/tcg/helper-a64.c diff --git a/target/arm/iwmmxt_helper.c b/target/arm/tcg/iwmmxt_helper.c similarity index 100% rename from target/arm/iwmmxt_helper.c rename to target/arm/tcg/iwmmxt_helper.c diff --git a/target/arm/m_helper.c b/target/arm/tcg/m_helper.c similarity index 100% rename from target/arm/m_helper.c rename to target/arm/tcg/m_helper.c diff --git a/target/arm/tcg/meson.build b/target/arm/tcg/meson.build index 044561bd4d..1f27ba1272 100644 --- a/target/arm/tcg/meson.build +++ b/target/arm/tcg/meson.build @@ -23,10 +23,23 @@ arm_ss.add(files( 'translate-mve.c', 'translate-neon.c', 'translate-vfp.c', + 'crypto_helper.c', + 'iwmmxt_helper.c', + 'm_helper.c', + 'mve_helper.c', + 'neon_helper.c', + 'op_helper.c', + 'tlb_helper.c', + 'vec_helper.c', )) arm_ss.add(when: 'TARGET_AARCH64', if_true: files( 'translate-a64.c', 'translate-sve.c', 'translate-sme.c', + 'helper-a64.c', + 'mte_helper.c', + 'pauth_helper.c', + 'sme_helper.c', + 'sve_helper.c', )) diff --git a/target/arm/mte_helper.c b/target/arm/tcg/mte_helper.c similarity index 100% rename from target/arm/mte_helper.c rename to target/arm/tcg/mte_helper.c diff --git a/target/arm/mve_helper.c b/target/arm/tcg/mve_helper.c similarity index 100% rename from target/arm/mve_helper.c rename to target/arm/tcg/mve_helper.c diff --git a/target/arm/neon_helper.c b/target/arm/tcg/neon_helper.c similarity index 100% rename from target/arm/neon_helper.c rename to target/arm/tcg/neon_helper.c diff --git a/target/arm/op_helper.c b/target/arm/tcg/op_helper.c similarity index 100% rename from target/arm/op_helper.c rename to target/arm/tcg/op_helper.c diff --git a/target/arm/pauth_helper.c b/target/arm/tcg/pauth_helper.c similarity index 100% rename from target/arm/pauth_helper.c rename to target/arm/tcg/pauth_helper.c diff --git a/target/arm/sme_helper.c b/target/arm/tcg/sme_helper.c similarity index 100% rename from target/arm/sme_helper.c rename to target/arm/tcg/sme_helper.c diff --git a/target/arm/sve_helper.c b/target/arm/tcg/sve_helper.c similarity index 100% rename from target/arm/sve_helper.c rename to target/arm/tcg/sve_helper.c diff --git a/target/arm/tlb_helper.c b/target/arm/tcg/tlb_helper.c similarity index 100% rename from target/arm/tlb_helper.c rename to target/arm/tcg/tlb_helper.c diff --git a/target/arm/vec_helper.c b/target/arm/tcg/vec_helper.c similarity index 100% rename from target/arm/vec_helper.c rename to target/arm/tcg/vec_helper.c diff --git a/target/arm/vec_internal.h b/target/arm/tcg/vec_internal.h similarity index 100% rename from target/arm/vec_internal.h rename to target/arm/tcg/vec_internal.h From 9def656e7a23515d5afd5e5e350574d1dfb7fcc9 Mon Sep 17 00:00:00 2001 From: Claudio Fontana Date: Fri, 17 Feb 2023 17:11:31 -0300 Subject: [PATCH 110/129] target/arm: Move psci.c into the tcg directory MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Claudio Fontana Signed-off-by: Fabiano Rosas Reviewed-by: Richard Henderson Reviewed-by: Alex Bennée Tested-by: Philippe Mathieu-Daudé Signed-off-by: Peter Maydell --- target/arm/meson.build | 1 - target/arm/tcg/meson.build | 4 ++++ target/arm/{ => tcg}/psci.c | 0 3 files changed, 4 insertions(+), 1 deletion(-) rename target/arm/{ => tcg}/psci.c (100%) diff --git a/target/arm/meson.build b/target/arm/meson.build index 3e2f403005..a5191b57e1 100644 --- a/target/arm/meson.build +++ b/target/arm/meson.build @@ -22,7 +22,6 @@ arm_softmmu_ss.add(files( 'arm-powerctl.c', 'machine.c', 'monitor.c', - 'psci.c', 'ptw.c', )) diff --git a/target/arm/tcg/meson.build b/target/arm/tcg/meson.build index 1f27ba1272..fa8a9eab93 100644 --- a/target/arm/tcg/meson.build +++ b/target/arm/tcg/meson.build @@ -43,3 +43,7 @@ arm_ss.add(when: 'TARGET_AARCH64', if_true: files( 'sme_helper.c', 'sve_helper.c', )) + +arm_softmmu_ss.add(files( + 'psci.c', +)) diff --git a/target/arm/psci.c b/target/arm/tcg/psci.c similarity index 100% rename from target/arm/psci.c rename to target/arm/tcg/psci.c From 2b77ad4de615542dd8f6b9886a816e744b0abffd Mon Sep 17 00:00:00 2001 From: Fabiano Rosas Date: Fri, 17 Feb 2023 17:11:32 -0300 Subject: [PATCH 111/129] target/arm: Wrap arm_rebuild_hflags calls with tcg_enabled MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is in preparation to moving the hflags code into its own file under the tcg/ directory. Signed-off-by: Fabiano Rosas Reviewed-by: Richard Henderson Tested-by: Philippe Mathieu-Daudé Signed-off-by: Peter Maydell --- hw/arm/boot.c | 6 +++++- hw/intc/armv7m_nvic.c | 20 +++++++++++++------- target/arm/arm-powerctl.c | 7 +++++-- target/arm/cpu.c | 3 ++- target/arm/helper.c | 18 +++++++++++++----- target/arm/machine.c | 5 ++++- 6 files changed, 42 insertions(+), 17 deletions(-) diff --git a/hw/arm/boot.c b/hw/arm/boot.c index 3d7d11f782..1e021c4a34 100644 --- a/hw/arm/boot.c +++ b/hw/arm/boot.c @@ -15,6 +15,7 @@ #include "hw/arm/boot.h" #include "hw/arm/linux-boot-if.h" #include "sysemu/kvm.h" +#include "sysemu/tcg.h" #include "sysemu/sysemu.h" #include "sysemu/numa.h" #include "hw/boards.h" @@ -827,7 +828,10 @@ static void do_cpu_reset(void *opaque) info->secondary_cpu_reset_hook(cpu, info); } } - arm_rebuild_hflags(env); + + if (tcg_enabled()) { + arm_rebuild_hflags(env); + } } } diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c index e54553283f..8e289051a4 100644 --- a/hw/intc/armv7m_nvic.c +++ b/hw/intc/armv7m_nvic.c @@ -18,6 +18,7 @@ #include "hw/intc/armv7m_nvic.h" #include "hw/irq.h" #include "hw/qdev-properties.h" +#include "sysemu/tcg.h" #include "sysemu/runstate.h" #include "target/arm/cpu.h" #include "exec/exec-all.h" @@ -2454,8 +2455,10 @@ static MemTxResult nvic_sysreg_write(void *opaque, hwaddr addr, /* This is UNPREDICTABLE; treat as RAZ/WI */ exit_ok: - /* Ensure any changes made are reflected in the cached hflags. */ - arm_rebuild_hflags(&s->cpu->env); + if (tcg_enabled()) { + /* Ensure any changes made are reflected in the cached hflags. */ + arm_rebuild_hflags(&s->cpu->env); + } return MEMTX_OK; } @@ -2636,11 +2639,14 @@ static void armv7m_nvic_reset(DeviceState *dev) } } - /* - * We updated state that affects the CPU's MMUidx and thus its hflags; - * and we can't guarantee that we run before the CPU reset function. - */ - arm_rebuild_hflags(&s->cpu->env); + if (tcg_enabled()) { + /* + * We updated state that affects the CPU's MMUidx and thus its + * hflags; and we can't guarantee that we run before the CPU + * reset function. + */ + arm_rebuild_hflags(&s->cpu->env); + } } static void nvic_systick_trigger(void *opaque, int n, int level) diff --git a/target/arm/arm-powerctl.c b/target/arm/arm-powerctl.c index b75f813b40..326a03153d 100644 --- a/target/arm/arm-powerctl.c +++ b/target/arm/arm-powerctl.c @@ -15,6 +15,7 @@ #include "arm-powerctl.h" #include "qemu/log.h" #include "qemu/main-loop.h" +#include "sysemu/tcg.h" #ifndef DEBUG_ARM_POWERCTL #define DEBUG_ARM_POWERCTL 0 @@ -127,8 +128,10 @@ static void arm_set_cpu_on_async_work(CPUState *target_cpu_state, target_cpu->env.regs[0] = info->context_id; } - /* CP15 update requires rebuilding hflags */ - arm_rebuild_hflags(&target_cpu->env); + if (tcg_enabled()) { + /* CP15 update requires rebuilding hflags */ + arm_rebuild_hflags(&target_cpu->env); + } /* Start the new CPU at the requested address */ cpu_set_pc(target_cpu_state, info->entry); diff --git a/target/arm/cpu.c b/target/arm/cpu.c index da416f7b1c..0b333a749f 100644 --- a/target/arm/cpu.c +++ b/target/arm/cpu.c @@ -542,8 +542,9 @@ static void arm_cpu_reset_hold(Object *obj) if (tcg_enabled()) { hw_breakpoint_update_all(cpu); hw_watchpoint_update_all(cpu); + + arm_rebuild_hflags(env); } - arm_rebuild_hflags(env); } #if defined(CONFIG_TCG) && !defined(CONFIG_USER_ONLY) diff --git a/target/arm/helper.c b/target/arm/helper.c index 07d4100365..af72e6d16c 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -5173,7 +5173,7 @@ static void sctlr_write(CPUARMState *env, const ARMCPRegInfo *ri, /* This may enable/disable the MMU, so do a TLB flush. */ tlb_flush(CPU(cpu)); - if (ri->type & ARM_CP_SUPPRESS_TB_END) { + if (tcg_enabled() && ri->type & ARM_CP_SUPPRESS_TB_END) { /* * Normally we would always end the TB on an SCTLR write; see the * comment in ARMCPRegInfo sctlr initialization below for why Xscale @@ -6841,7 +6841,9 @@ void aarch64_set_svcr(CPUARMState *env, uint64_t new, uint64_t mask) memset(env->zarray, 0, sizeof(env->zarray)); } - arm_rebuild_hflags(env); + if (tcg_enabled()) { + arm_rebuild_hflags(env); + } } static void svcr_write(CPUARMState *env, const ARMCPRegInfo *ri, @@ -9886,7 +9888,7 @@ void cpsr_write(CPUARMState *env, uint32_t val, uint32_t mask, } mask &= ~CACHED_CPSR_BITS; env->uncached_cpsr = (env->uncached_cpsr & ~mask) | (val & mask); - if (rebuild_hflags) { + if (tcg_enabled() && rebuild_hflags) { arm_rebuild_hflags(env); } } @@ -10445,7 +10447,10 @@ static void take_aarch32_exception(CPUARMState *env, int new_mode, env->regs[14] = env->regs[15] + offset; } env->regs[15] = newpc; - arm_rebuild_hflags(env); + + if (tcg_enabled()) { + arm_rebuild_hflags(env); + } } static void arm_cpu_do_interrupt_aarch32_hyp(CPUState *cs) @@ -11001,7 +11006,10 @@ static void arm_cpu_do_interrupt_aarch64(CPUState *cs) pstate_write(env, PSTATE_DAIF | new_mode); env->aarch64 = true; aarch64_restore_sp(env, new_el); - helper_rebuild_hflags_a64(env, new_el); + + if (tcg_enabled()) { + helper_rebuild_hflags_a64(env, new_el); + } env->pc = addr; diff --git a/target/arm/machine.c b/target/arm/machine.c index fd6323f6d8..fc4a4a4064 100644 --- a/target/arm/machine.c +++ b/target/arm/machine.c @@ -871,7 +871,10 @@ static int cpu_post_load(void *opaque, int version_id) if (!kvm_enabled()) { pmu_op_finish(&cpu->env); } - arm_rebuild_hflags(&cpu->env); + + if (tcg_enabled()) { + arm_rebuild_hflags(&cpu->env); + } return 0; } From 671efad16a242b3fb5fb5111e9981d56887f7755 Mon Sep 17 00:00:00 2001 From: Fabiano Rosas Date: Fri, 17 Feb 2023 17:11:33 -0300 Subject: [PATCH 112/129] target/arm: Move hflags code into the tcg directory MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The hflags are used only for TCG code, so introduce a new file hflags.c to keep that code. Signed-off-by: Fabiano Rosas Reviewed-by: Richard Henderson Tested-by: Philippe Mathieu-Daudé Signed-off-by: Peter Maydell --- target/arm/helper.c | 393 +----------------------------------- target/arm/internals.h | 2 + target/arm/tcg-stubs.c | 4 + target/arm/tcg/hflags.c | 403 +++++++++++++++++++++++++++++++++++++ target/arm/tcg/meson.build | 1 + 5 files changed, 411 insertions(+), 392 deletions(-) create mode 100644 target/arm/tcg/hflags.c diff --git a/target/arm/helper.c b/target/arm/helper.c index af72e6d16c..14af7ba095 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -6669,32 +6669,6 @@ int sme_exception_el(CPUARMState *env, int el) return 0; } -/* This corresponds to the ARM pseudocode function IsFullA64Enabled(). */ -static bool sme_fa64(CPUARMState *env, int el) -{ - if (!cpu_isar_feature(aa64_sme_fa64, env_archcpu(env))) { - return false; - } - - if (el <= 1 && !el_is_in_host(env, el)) { - if (!FIELD_EX64(env->vfp.smcr_el[1], SMCR, FA64)) { - return false; - } - } - if (el <= 2 && arm_is_el2_enabled(env)) { - if (!FIELD_EX64(env->vfp.smcr_el[2], SMCR, FA64)) { - return false; - } - } - if (arm_feature(env, ARM_FEATURE_EL3)) { - if (!FIELD_EX64(env->vfp.smcr_el[3], SMCR, FA64)) { - return false; - } - } - - return true; -} - /* * Given that SVE is enabled, return the vector length for EL. */ @@ -11150,7 +11124,7 @@ int aa64_va_parameter_tbid(uint64_t tcr, ARMMMUIdx mmu_idx) } } -static int aa64_va_parameter_tcma(uint64_t tcr, ARMMMUIdx mmu_idx) +int aa64_va_parameter_tcma(uint64_t tcr, ARMMMUIdx mmu_idx) { if (regime_has_2_ranges(mmu_idx)) { return extract64(tcr, 57, 2); @@ -11861,371 +11835,6 @@ ARMMMUIdx arm_mmu_idx(CPUARMState *env) return arm_mmu_idx_el(env, arm_current_el(env)); } -static inline bool fgt_svc(CPUARMState *env, int el) -{ - /* - * Assuming fine-grained-traps are active, return true if we - * should be trapping on SVC instructions. Only AArch64 can - * trap on an SVC at EL1, but we don't need to special-case this - * because if this is AArch32 EL1 then arm_fgt_active() is false. - * We also know el is 0 or 1. - */ - return el == 0 ? - FIELD_EX64(env->cp15.fgt_exec[FGTREG_HFGITR], HFGITR_EL2, SVC_EL0) : - FIELD_EX64(env->cp15.fgt_exec[FGTREG_HFGITR], HFGITR_EL2, SVC_EL1); -} - -static CPUARMTBFlags rebuild_hflags_common(CPUARMState *env, int fp_el, - ARMMMUIdx mmu_idx, - CPUARMTBFlags flags) -{ - DP_TBFLAG_ANY(flags, FPEXC_EL, fp_el); - DP_TBFLAG_ANY(flags, MMUIDX, arm_to_core_mmu_idx(mmu_idx)); - - if (arm_singlestep_active(env)) { - DP_TBFLAG_ANY(flags, SS_ACTIVE, 1); - } - - return flags; -} - -static CPUARMTBFlags rebuild_hflags_common_32(CPUARMState *env, int fp_el, - ARMMMUIdx mmu_idx, - CPUARMTBFlags flags) -{ - bool sctlr_b = arm_sctlr_b(env); - - if (sctlr_b) { - DP_TBFLAG_A32(flags, SCTLR__B, 1); - } - if (arm_cpu_data_is_big_endian_a32(env, sctlr_b)) { - DP_TBFLAG_ANY(flags, BE_DATA, 1); - } - DP_TBFLAG_A32(flags, NS, !access_secure_reg(env)); - - return rebuild_hflags_common(env, fp_el, mmu_idx, flags); -} - -static CPUARMTBFlags rebuild_hflags_m32(CPUARMState *env, int fp_el, - ARMMMUIdx mmu_idx) -{ - CPUARMTBFlags flags = {}; - uint32_t ccr = env->v7m.ccr[env->v7m.secure]; - - /* Without HaveMainExt, CCR.UNALIGN_TRP is RES1. */ - if (ccr & R_V7M_CCR_UNALIGN_TRP_MASK) { - DP_TBFLAG_ANY(flags, ALIGN_MEM, 1); - } - - if (arm_v7m_is_handler_mode(env)) { - DP_TBFLAG_M32(flags, HANDLER, 1); - } - - /* - * v8M always applies stack limit checks unless CCR.STKOFHFNMIGN - * is suppressing them because the requested execution priority - * is less than 0. - */ - if (arm_feature(env, ARM_FEATURE_V8) && - !((mmu_idx & ARM_MMU_IDX_M_NEGPRI) && - (ccr & R_V7M_CCR_STKOFHFNMIGN_MASK))) { - DP_TBFLAG_M32(flags, STACKCHECK, 1); - } - - if (arm_feature(env, ARM_FEATURE_M_SECURITY) && env->v7m.secure) { - DP_TBFLAG_M32(flags, SECURE, 1); - } - - return rebuild_hflags_common_32(env, fp_el, mmu_idx, flags); -} - -static CPUARMTBFlags rebuild_hflags_a32(CPUARMState *env, int fp_el, - ARMMMUIdx mmu_idx) -{ - CPUARMTBFlags flags = {}; - int el = arm_current_el(env); - - if (arm_sctlr(env, el) & SCTLR_A) { - DP_TBFLAG_ANY(flags, ALIGN_MEM, 1); - } - - if (arm_el_is_aa64(env, 1)) { - DP_TBFLAG_A32(flags, VFPEN, 1); - } - - if (el < 2 && env->cp15.hstr_el2 && arm_is_el2_enabled(env) && - (arm_hcr_el2_eff(env) & (HCR_E2H | HCR_TGE)) != (HCR_E2H | HCR_TGE)) { - DP_TBFLAG_A32(flags, HSTR_ACTIVE, 1); - } - - if (arm_fgt_active(env, el)) { - DP_TBFLAG_ANY(flags, FGT_ACTIVE, 1); - if (fgt_svc(env, el)) { - DP_TBFLAG_ANY(flags, FGT_SVC, 1); - } - } - - if (env->uncached_cpsr & CPSR_IL) { - DP_TBFLAG_ANY(flags, PSTATE__IL, 1); - } - - /* - * The SME exception we are testing for is raised via - * AArch64.CheckFPAdvSIMDEnabled(), as called from - * AArch32.CheckAdvSIMDOrFPEnabled(). - */ - if (el == 0 - && FIELD_EX64(env->svcr, SVCR, SM) - && (!arm_is_el2_enabled(env) - || (arm_el_is_aa64(env, 2) && !(env->cp15.hcr_el2 & HCR_TGE))) - && arm_el_is_aa64(env, 1) - && !sme_fa64(env, el)) { - DP_TBFLAG_A32(flags, SME_TRAP_NONSTREAMING, 1); - } - - return rebuild_hflags_common_32(env, fp_el, mmu_idx, flags); -} - -static CPUARMTBFlags rebuild_hflags_a64(CPUARMState *env, int el, int fp_el, - ARMMMUIdx mmu_idx) -{ - CPUARMTBFlags flags = {}; - ARMMMUIdx stage1 = stage_1_mmu_idx(mmu_idx); - uint64_t tcr = regime_tcr(env, mmu_idx); - uint64_t sctlr; - int tbii, tbid; - - DP_TBFLAG_ANY(flags, AARCH64_STATE, 1); - - /* Get control bits for tagged addresses. */ - tbid = aa64_va_parameter_tbi(tcr, mmu_idx); - tbii = tbid & ~aa64_va_parameter_tbid(tcr, mmu_idx); - - DP_TBFLAG_A64(flags, TBII, tbii); - DP_TBFLAG_A64(flags, TBID, tbid); - - if (cpu_isar_feature(aa64_sve, env_archcpu(env))) { - int sve_el = sve_exception_el(env, el); - - /* - * If either FP or SVE are disabled, translator does not need len. - * If SVE EL > FP EL, FP exception has precedence, and translator - * does not need SVE EL. Save potential re-translations by forcing - * the unneeded data to zero. - */ - if (fp_el != 0) { - if (sve_el > fp_el) { - sve_el = 0; - } - } else if (sve_el == 0) { - DP_TBFLAG_A64(flags, VL, sve_vqm1_for_el(env, el)); - } - DP_TBFLAG_A64(flags, SVEEXC_EL, sve_el); - } - if (cpu_isar_feature(aa64_sme, env_archcpu(env))) { - int sme_el = sme_exception_el(env, el); - bool sm = FIELD_EX64(env->svcr, SVCR, SM); - - DP_TBFLAG_A64(flags, SMEEXC_EL, sme_el); - if (sme_el == 0) { - /* Similarly, do not compute SVL if SME is disabled. */ - int svl = sve_vqm1_for_el_sm(env, el, true); - DP_TBFLAG_A64(flags, SVL, svl); - if (sm) { - /* If SVE is disabled, we will not have set VL above. */ - DP_TBFLAG_A64(flags, VL, svl); - } - } - if (sm) { - DP_TBFLAG_A64(flags, PSTATE_SM, 1); - DP_TBFLAG_A64(flags, SME_TRAP_NONSTREAMING, !sme_fa64(env, el)); - } - DP_TBFLAG_A64(flags, PSTATE_ZA, FIELD_EX64(env->svcr, SVCR, ZA)); - } - - sctlr = regime_sctlr(env, stage1); - - if (sctlr & SCTLR_A) { - DP_TBFLAG_ANY(flags, ALIGN_MEM, 1); - } - - if (arm_cpu_data_is_big_endian_a64(el, sctlr)) { - DP_TBFLAG_ANY(flags, BE_DATA, 1); - } - - if (cpu_isar_feature(aa64_pauth, env_archcpu(env))) { - /* - * In order to save space in flags, we record only whether - * pauth is "inactive", meaning all insns are implemented as - * a nop, or "active" when some action must be performed. - * The decision of which action to take is left to a helper. - */ - if (sctlr & (SCTLR_EnIA | SCTLR_EnIB | SCTLR_EnDA | SCTLR_EnDB)) { - DP_TBFLAG_A64(flags, PAUTH_ACTIVE, 1); - } - } - - if (cpu_isar_feature(aa64_bti, env_archcpu(env))) { - /* Note that SCTLR_EL[23].BT == SCTLR_BT1. */ - if (sctlr & (el == 0 ? SCTLR_BT0 : SCTLR_BT1)) { - DP_TBFLAG_A64(flags, BT, 1); - } - } - - /* Compute the condition for using AccType_UNPRIV for LDTR et al. */ - if (!(env->pstate & PSTATE_UAO)) { - switch (mmu_idx) { - case ARMMMUIdx_E10_1: - case ARMMMUIdx_E10_1_PAN: - /* TODO: ARMv8.3-NV */ - DP_TBFLAG_A64(flags, UNPRIV, 1); - break; - case ARMMMUIdx_E20_2: - case ARMMMUIdx_E20_2_PAN: - /* - * Note that EL20_2 is gated by HCR_EL2.E2H == 1, but EL20_0 is - * gated by HCR_EL2. == '11', and so is LDTR. - */ - if (env->cp15.hcr_el2 & HCR_TGE) { - DP_TBFLAG_A64(flags, UNPRIV, 1); - } - break; - default: - break; - } - } - - if (env->pstate & PSTATE_IL) { - DP_TBFLAG_ANY(flags, PSTATE__IL, 1); - } - - if (arm_fgt_active(env, el)) { - DP_TBFLAG_ANY(flags, FGT_ACTIVE, 1); - if (FIELD_EX64(env->cp15.fgt_exec[FGTREG_HFGITR], HFGITR_EL2, ERET)) { - DP_TBFLAG_A64(flags, FGT_ERET, 1); - } - if (fgt_svc(env, el)) { - DP_TBFLAG_ANY(flags, FGT_SVC, 1); - } - } - - if (cpu_isar_feature(aa64_mte, env_archcpu(env))) { - /* - * Set MTE_ACTIVE if any access may be Checked, and leave clear - * if all accesses must be Unchecked: - * 1) If no TBI, then there are no tags in the address to check, - * 2) If Tag Check Override, then all accesses are Unchecked, - * 3) If Tag Check Fail == 0, then Checked access have no effect, - * 4) If no Allocation Tag Access, then all accesses are Unchecked. - */ - if (allocation_tag_access_enabled(env, el, sctlr)) { - DP_TBFLAG_A64(flags, ATA, 1); - if (tbid - && !(env->pstate & PSTATE_TCO) - && (sctlr & (el == 0 ? SCTLR_TCF0 : SCTLR_TCF))) { - DP_TBFLAG_A64(flags, MTE_ACTIVE, 1); - } - } - /* And again for unprivileged accesses, if required. */ - if (EX_TBFLAG_A64(flags, UNPRIV) - && tbid - && !(env->pstate & PSTATE_TCO) - && (sctlr & SCTLR_TCF0) - && allocation_tag_access_enabled(env, 0, sctlr)) { - DP_TBFLAG_A64(flags, MTE0_ACTIVE, 1); - } - /* Cache TCMA as well as TBI. */ - DP_TBFLAG_A64(flags, TCMA, aa64_va_parameter_tcma(tcr, mmu_idx)); - } - - return rebuild_hflags_common(env, fp_el, mmu_idx, flags); -} - -static CPUARMTBFlags rebuild_hflags_internal(CPUARMState *env) -{ - int el = arm_current_el(env); - int fp_el = fp_exception_el(env, el); - ARMMMUIdx mmu_idx = arm_mmu_idx_el(env, el); - - if (is_a64(env)) { - return rebuild_hflags_a64(env, el, fp_el, mmu_idx); - } else if (arm_feature(env, ARM_FEATURE_M)) { - return rebuild_hflags_m32(env, fp_el, mmu_idx); - } else { - return rebuild_hflags_a32(env, fp_el, mmu_idx); - } -} - -void arm_rebuild_hflags(CPUARMState *env) -{ - env->hflags = rebuild_hflags_internal(env); -} - -/* - * If we have triggered a EL state change we can't rely on the - * translator having passed it to us, we need to recompute. - */ -void HELPER(rebuild_hflags_m32_newel)(CPUARMState *env) -{ - int el = arm_current_el(env); - int fp_el = fp_exception_el(env, el); - ARMMMUIdx mmu_idx = arm_mmu_idx_el(env, el); - - env->hflags = rebuild_hflags_m32(env, fp_el, mmu_idx); -} - -void HELPER(rebuild_hflags_m32)(CPUARMState *env, int el) -{ - int fp_el = fp_exception_el(env, el); - ARMMMUIdx mmu_idx = arm_mmu_idx_el(env, el); - - env->hflags = rebuild_hflags_m32(env, fp_el, mmu_idx); -} - -/* - * If we have triggered a EL state change we can't rely on the - * translator having passed it to us, we need to recompute. - */ -void HELPER(rebuild_hflags_a32_newel)(CPUARMState *env) -{ - int el = arm_current_el(env); - int fp_el = fp_exception_el(env, el); - ARMMMUIdx mmu_idx = arm_mmu_idx_el(env, el); - env->hflags = rebuild_hflags_a32(env, fp_el, mmu_idx); -} - -void HELPER(rebuild_hflags_a32)(CPUARMState *env, int el) -{ - int fp_el = fp_exception_el(env, el); - ARMMMUIdx mmu_idx = arm_mmu_idx_el(env, el); - - env->hflags = rebuild_hflags_a32(env, fp_el, mmu_idx); -} - -void HELPER(rebuild_hflags_a64)(CPUARMState *env, int el) -{ - int fp_el = fp_exception_el(env, el); - ARMMMUIdx mmu_idx = arm_mmu_idx_el(env, el); - - env->hflags = rebuild_hflags_a64(env, el, fp_el, mmu_idx); -} - -static inline void assert_hflags_rebuild_correctly(CPUARMState *env) -{ -#ifdef CONFIG_DEBUG_TCG - CPUARMTBFlags c = env->hflags; - CPUARMTBFlags r = rebuild_hflags_internal(env); - - if (unlikely(c.flags != r.flags || c.flags2 != r.flags2)) { - fprintf(stderr, "TCG hflags mismatch " - "(current:(0x%08x,0x" TARGET_FMT_lx ")" - " rebuilt:(0x%08x,0x" TARGET_FMT_lx ")\n", - c.flags, c.flags2, r.flags, r.flags2); - abort(); - } -#endif -} - static bool mve_no_pred(CPUARMState *env) { /* diff --git a/target/arm/internals.h b/target/arm/internals.h index 759b70c646..ed48f8c9a6 100644 --- a/target/arm/internals.h +++ b/target/arm/internals.h @@ -1073,6 +1073,7 @@ ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va, int aa64_va_parameter_tbi(uint64_t tcr, ARMMMUIdx mmu_idx); int aa64_va_parameter_tbid(uint64_t tcr, ARMMMUIdx mmu_idx); +int aa64_va_parameter_tcma(uint64_t tcr, ARMMMUIdx mmu_idx); /* Determine if allocation tags are available. */ static inline bool allocation_tag_access_enabled(CPUARMState *env, int el, @@ -1383,4 +1384,5 @@ static inline bool arm_fgt_active(CPUARMState *env, int el) (!arm_feature(env, ARM_FEATURE_EL3) || (env->cp15.scr_el3 & SCR_FGTEN)); } +void assert_hflags_rebuild_correctly(CPUARMState *env); #endif diff --git a/target/arm/tcg-stubs.c b/target/arm/tcg-stubs.c index 1a7ddb3664..152b172e24 100644 --- a/target/arm/tcg-stubs.c +++ b/target/arm/tcg-stubs.c @@ -21,3 +21,7 @@ void raise_exception_ra(CPUARMState *env, uint32_t excp, uint32_t syndrome, { g_assert_not_reached(); } +/* Temporarily while cpu_get_tb_cpu_state() is still in common code */ +void assert_hflags_rebuild_correctly(CPUARMState *env) +{ +} diff --git a/target/arm/tcg/hflags.c b/target/arm/tcg/hflags.c new file mode 100644 index 0000000000..b2ccd77cff --- /dev/null +++ b/target/arm/tcg/hflags.c @@ -0,0 +1,403 @@ +/* + * ARM hflags + * + * 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" +#include "exec/helper-proto.h" +#include "cpregs.h" + +static inline bool fgt_svc(CPUARMState *env, int el) +{ + /* + * Assuming fine-grained-traps are active, return true if we + * should be trapping on SVC instructions. Only AArch64 can + * trap on an SVC at EL1, but we don't need to special-case this + * because if this is AArch32 EL1 then arm_fgt_active() is false. + * We also know el is 0 or 1. + */ + return el == 0 ? + FIELD_EX64(env->cp15.fgt_exec[FGTREG_HFGITR], HFGITR_EL2, SVC_EL0) : + FIELD_EX64(env->cp15.fgt_exec[FGTREG_HFGITR], HFGITR_EL2, SVC_EL1); +} + +static CPUARMTBFlags rebuild_hflags_common(CPUARMState *env, int fp_el, + ARMMMUIdx mmu_idx, + CPUARMTBFlags flags) +{ + DP_TBFLAG_ANY(flags, FPEXC_EL, fp_el); + DP_TBFLAG_ANY(flags, MMUIDX, arm_to_core_mmu_idx(mmu_idx)); + + if (arm_singlestep_active(env)) { + DP_TBFLAG_ANY(flags, SS_ACTIVE, 1); + } + + return flags; +} + +static CPUARMTBFlags rebuild_hflags_common_32(CPUARMState *env, int fp_el, + ARMMMUIdx mmu_idx, + CPUARMTBFlags flags) +{ + bool sctlr_b = arm_sctlr_b(env); + + if (sctlr_b) { + DP_TBFLAG_A32(flags, SCTLR__B, 1); + } + if (arm_cpu_data_is_big_endian_a32(env, sctlr_b)) { + DP_TBFLAG_ANY(flags, BE_DATA, 1); + } + DP_TBFLAG_A32(flags, NS, !access_secure_reg(env)); + + return rebuild_hflags_common(env, fp_el, mmu_idx, flags); +} + +static CPUARMTBFlags rebuild_hflags_m32(CPUARMState *env, int fp_el, + ARMMMUIdx mmu_idx) +{ + CPUARMTBFlags flags = {}; + uint32_t ccr = env->v7m.ccr[env->v7m.secure]; + + /* Without HaveMainExt, CCR.UNALIGN_TRP is RES1. */ + if (ccr & R_V7M_CCR_UNALIGN_TRP_MASK) { + DP_TBFLAG_ANY(flags, ALIGN_MEM, 1); + } + + if (arm_v7m_is_handler_mode(env)) { + DP_TBFLAG_M32(flags, HANDLER, 1); + } + + /* + * v8M always applies stack limit checks unless CCR.STKOFHFNMIGN + * is suppressing them because the requested execution priority + * is less than 0. + */ + if (arm_feature(env, ARM_FEATURE_V8) && + !((mmu_idx & ARM_MMU_IDX_M_NEGPRI) && + (ccr & R_V7M_CCR_STKOFHFNMIGN_MASK))) { + DP_TBFLAG_M32(flags, STACKCHECK, 1); + } + + if (arm_feature(env, ARM_FEATURE_M_SECURITY) && env->v7m.secure) { + DP_TBFLAG_M32(flags, SECURE, 1); + } + + return rebuild_hflags_common_32(env, fp_el, mmu_idx, flags); +} + +/* This corresponds to the ARM pseudocode function IsFullA64Enabled(). */ +static bool sme_fa64(CPUARMState *env, int el) +{ + if (!cpu_isar_feature(aa64_sme_fa64, env_archcpu(env))) { + return false; + } + + if (el <= 1 && !el_is_in_host(env, el)) { + if (!FIELD_EX64(env->vfp.smcr_el[1], SMCR, FA64)) { + return false; + } + } + if (el <= 2 && arm_is_el2_enabled(env)) { + if (!FIELD_EX64(env->vfp.smcr_el[2], SMCR, FA64)) { + return false; + } + } + if (arm_feature(env, ARM_FEATURE_EL3)) { + if (!FIELD_EX64(env->vfp.smcr_el[3], SMCR, FA64)) { + return false; + } + } + + return true; +} + +static CPUARMTBFlags rebuild_hflags_a32(CPUARMState *env, int fp_el, + ARMMMUIdx mmu_idx) +{ + CPUARMTBFlags flags = {}; + int el = arm_current_el(env); + + if (arm_sctlr(env, el) & SCTLR_A) { + DP_TBFLAG_ANY(flags, ALIGN_MEM, 1); + } + + if (arm_el_is_aa64(env, 1)) { + DP_TBFLAG_A32(flags, VFPEN, 1); + } + + if (el < 2 && env->cp15.hstr_el2 && arm_is_el2_enabled(env) && + (arm_hcr_el2_eff(env) & (HCR_E2H | HCR_TGE)) != (HCR_E2H | HCR_TGE)) { + DP_TBFLAG_A32(flags, HSTR_ACTIVE, 1); + } + + if (arm_fgt_active(env, el)) { + DP_TBFLAG_ANY(flags, FGT_ACTIVE, 1); + if (fgt_svc(env, el)) { + DP_TBFLAG_ANY(flags, FGT_SVC, 1); + } + } + + if (env->uncached_cpsr & CPSR_IL) { + DP_TBFLAG_ANY(flags, PSTATE__IL, 1); + } + + /* + * The SME exception we are testing for is raised via + * AArch64.CheckFPAdvSIMDEnabled(), as called from + * AArch32.CheckAdvSIMDOrFPEnabled(). + */ + if (el == 0 + && FIELD_EX64(env->svcr, SVCR, SM) + && (!arm_is_el2_enabled(env) + || (arm_el_is_aa64(env, 2) && !(env->cp15.hcr_el2 & HCR_TGE))) + && arm_el_is_aa64(env, 1) + && !sme_fa64(env, el)) { + DP_TBFLAG_A32(flags, SME_TRAP_NONSTREAMING, 1); + } + + return rebuild_hflags_common_32(env, fp_el, mmu_idx, flags); +} + +static CPUARMTBFlags rebuild_hflags_a64(CPUARMState *env, int el, int fp_el, + ARMMMUIdx mmu_idx) +{ + CPUARMTBFlags flags = {}; + ARMMMUIdx stage1 = stage_1_mmu_idx(mmu_idx); + uint64_t tcr = regime_tcr(env, mmu_idx); + uint64_t sctlr; + int tbii, tbid; + + DP_TBFLAG_ANY(flags, AARCH64_STATE, 1); + + /* Get control bits for tagged addresses. */ + tbid = aa64_va_parameter_tbi(tcr, mmu_idx); + tbii = tbid & ~aa64_va_parameter_tbid(tcr, mmu_idx); + + DP_TBFLAG_A64(flags, TBII, tbii); + DP_TBFLAG_A64(flags, TBID, tbid); + + if (cpu_isar_feature(aa64_sve, env_archcpu(env))) { + int sve_el = sve_exception_el(env, el); + + /* + * If either FP or SVE are disabled, translator does not need len. + * If SVE EL > FP EL, FP exception has precedence, and translator + * does not need SVE EL. Save potential re-translations by forcing + * the unneeded data to zero. + */ + if (fp_el != 0) { + if (sve_el > fp_el) { + sve_el = 0; + } + } else if (sve_el == 0) { + DP_TBFLAG_A64(flags, VL, sve_vqm1_for_el(env, el)); + } + DP_TBFLAG_A64(flags, SVEEXC_EL, sve_el); + } + if (cpu_isar_feature(aa64_sme, env_archcpu(env))) { + int sme_el = sme_exception_el(env, el); + bool sm = FIELD_EX64(env->svcr, SVCR, SM); + + DP_TBFLAG_A64(flags, SMEEXC_EL, sme_el); + if (sme_el == 0) { + /* Similarly, do not compute SVL if SME is disabled. */ + int svl = sve_vqm1_for_el_sm(env, el, true); + DP_TBFLAG_A64(flags, SVL, svl); + if (sm) { + /* If SVE is disabled, we will not have set VL above. */ + DP_TBFLAG_A64(flags, VL, svl); + } + } + if (sm) { + DP_TBFLAG_A64(flags, PSTATE_SM, 1); + DP_TBFLAG_A64(flags, SME_TRAP_NONSTREAMING, !sme_fa64(env, el)); + } + DP_TBFLAG_A64(flags, PSTATE_ZA, FIELD_EX64(env->svcr, SVCR, ZA)); + } + + sctlr = regime_sctlr(env, stage1); + + if (sctlr & SCTLR_A) { + DP_TBFLAG_ANY(flags, ALIGN_MEM, 1); + } + + if (arm_cpu_data_is_big_endian_a64(el, sctlr)) { + DP_TBFLAG_ANY(flags, BE_DATA, 1); + } + + if (cpu_isar_feature(aa64_pauth, env_archcpu(env))) { + /* + * In order to save space in flags, we record only whether + * pauth is "inactive", meaning all insns are implemented as + * a nop, or "active" when some action must be performed. + * The decision of which action to take is left to a helper. + */ + if (sctlr & (SCTLR_EnIA | SCTLR_EnIB | SCTLR_EnDA | SCTLR_EnDB)) { + DP_TBFLAG_A64(flags, PAUTH_ACTIVE, 1); + } + } + + if (cpu_isar_feature(aa64_bti, env_archcpu(env))) { + /* Note that SCTLR_EL[23].BT == SCTLR_BT1. */ + if (sctlr & (el == 0 ? SCTLR_BT0 : SCTLR_BT1)) { + DP_TBFLAG_A64(flags, BT, 1); + } + } + + /* Compute the condition for using AccType_UNPRIV for LDTR et al. */ + if (!(env->pstate & PSTATE_UAO)) { + switch (mmu_idx) { + case ARMMMUIdx_E10_1: + case ARMMMUIdx_E10_1_PAN: + /* TODO: ARMv8.3-NV */ + DP_TBFLAG_A64(flags, UNPRIV, 1); + break; + case ARMMMUIdx_E20_2: + case ARMMMUIdx_E20_2_PAN: + /* + * Note that EL20_2 is gated by HCR_EL2.E2H == 1, but EL20_0 is + * gated by HCR_EL2. == '11', and so is LDTR. + */ + if (env->cp15.hcr_el2 & HCR_TGE) { + DP_TBFLAG_A64(flags, UNPRIV, 1); + } + break; + default: + break; + } + } + + if (env->pstate & PSTATE_IL) { + DP_TBFLAG_ANY(flags, PSTATE__IL, 1); + } + + if (arm_fgt_active(env, el)) { + DP_TBFLAG_ANY(flags, FGT_ACTIVE, 1); + if (FIELD_EX64(env->cp15.fgt_exec[FGTREG_HFGITR], HFGITR_EL2, ERET)) { + DP_TBFLAG_A64(flags, FGT_ERET, 1); + } + if (fgt_svc(env, el)) { + DP_TBFLAG_ANY(flags, FGT_SVC, 1); + } + } + + if (cpu_isar_feature(aa64_mte, env_archcpu(env))) { + /* + * Set MTE_ACTIVE if any access may be Checked, and leave clear + * if all accesses must be Unchecked: + * 1) If no TBI, then there are no tags in the address to check, + * 2) If Tag Check Override, then all accesses are Unchecked, + * 3) If Tag Check Fail == 0, then Checked access have no effect, + * 4) If no Allocation Tag Access, then all accesses are Unchecked. + */ + if (allocation_tag_access_enabled(env, el, sctlr)) { + DP_TBFLAG_A64(flags, ATA, 1); + if (tbid + && !(env->pstate & PSTATE_TCO) + && (sctlr & (el == 0 ? SCTLR_TCF0 : SCTLR_TCF))) { + DP_TBFLAG_A64(flags, MTE_ACTIVE, 1); + } + } + /* And again for unprivileged accesses, if required. */ + if (EX_TBFLAG_A64(flags, UNPRIV) + && tbid + && !(env->pstate & PSTATE_TCO) + && (sctlr & SCTLR_TCF0) + && allocation_tag_access_enabled(env, 0, sctlr)) { + DP_TBFLAG_A64(flags, MTE0_ACTIVE, 1); + } + /* Cache TCMA as well as TBI. */ + DP_TBFLAG_A64(flags, TCMA, aa64_va_parameter_tcma(tcr, mmu_idx)); + } + + return rebuild_hflags_common(env, fp_el, mmu_idx, flags); +} + +static CPUARMTBFlags rebuild_hflags_internal(CPUARMState *env) +{ + int el = arm_current_el(env); + int fp_el = fp_exception_el(env, el); + ARMMMUIdx mmu_idx = arm_mmu_idx_el(env, el); + + if (is_a64(env)) { + return rebuild_hflags_a64(env, el, fp_el, mmu_idx); + } else if (arm_feature(env, ARM_FEATURE_M)) { + return rebuild_hflags_m32(env, fp_el, mmu_idx); + } else { + return rebuild_hflags_a32(env, fp_el, mmu_idx); + } +} + +void arm_rebuild_hflags(CPUARMState *env) +{ + env->hflags = rebuild_hflags_internal(env); +} + +/* + * If we have triggered a EL state change we can't rely on the + * translator having passed it to us, we need to recompute. + */ +void HELPER(rebuild_hflags_m32_newel)(CPUARMState *env) +{ + int el = arm_current_el(env); + int fp_el = fp_exception_el(env, el); + ARMMMUIdx mmu_idx = arm_mmu_idx_el(env, el); + + env->hflags = rebuild_hflags_m32(env, fp_el, mmu_idx); +} + +void HELPER(rebuild_hflags_m32)(CPUARMState *env, int el) +{ + int fp_el = fp_exception_el(env, el); + ARMMMUIdx mmu_idx = arm_mmu_idx_el(env, el); + + env->hflags = rebuild_hflags_m32(env, fp_el, mmu_idx); +} + +/* + * If we have triggered a EL state change we can't rely on the + * translator having passed it to us, we need to recompute. + */ +void HELPER(rebuild_hflags_a32_newel)(CPUARMState *env) +{ + int el = arm_current_el(env); + int fp_el = fp_exception_el(env, el); + ARMMMUIdx mmu_idx = arm_mmu_idx_el(env, el); + env->hflags = rebuild_hflags_a32(env, fp_el, mmu_idx); +} + +void HELPER(rebuild_hflags_a32)(CPUARMState *env, int el) +{ + int fp_el = fp_exception_el(env, el); + ARMMMUIdx mmu_idx = arm_mmu_idx_el(env, el); + + env->hflags = rebuild_hflags_a32(env, fp_el, mmu_idx); +} + +void HELPER(rebuild_hflags_a64)(CPUARMState *env, int el) +{ + int fp_el = fp_exception_el(env, el); + ARMMMUIdx mmu_idx = arm_mmu_idx_el(env, el); + + env->hflags = rebuild_hflags_a64(env, el, fp_el, mmu_idx); +} + +void assert_hflags_rebuild_correctly(CPUARMState *env) +{ +#ifdef CONFIG_DEBUG_TCG + CPUARMTBFlags c = env->hflags; + CPUARMTBFlags r = rebuild_hflags_internal(env); + + if (unlikely(c.flags != r.flags || c.flags2 != r.flags2)) { + fprintf(stderr, "TCG hflags mismatch " + "(current:(0x%08x,0x" TARGET_FMT_lx ")" + " rebuilt:(0x%08x,0x" TARGET_FMT_lx ")\n", + c.flags, c.flags2, r.flags, r.flags2); + abort(); + } +#endif +} diff --git a/target/arm/tcg/meson.build b/target/arm/tcg/meson.build index fa8a9eab93..d27e76af6c 100644 --- a/target/arm/tcg/meson.build +++ b/target/arm/tcg/meson.build @@ -24,6 +24,7 @@ arm_ss.add(files( 'translate-neon.c', 'translate-vfp.c', 'crypto_helper.c', + 'hflags.c', 'iwmmxt_helper.c', 'm_helper.c', 'mve_helper.c', From 2ea2998f27da92ae1225c1da95cee51a4a6783af Mon Sep 17 00:00:00 2001 From: Fabiano Rosas Date: Fri, 17 Feb 2023 17:11:34 -0300 Subject: [PATCH 113/129] target/arm: Move regime_using_lpae_format into internal.h MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This function is needed by common code (ptw.c), so move it along with the other regime_* functions in internal.h. When we enable the build without TCG, the tlb_helper.c file will not be present. Signed-off-by: Fabiano Rosas Reviewed-by: Richard Henderson Tested-by: Philippe Mathieu-Daudé Signed-off-by: Peter Maydell --- target/arm/internals.h | 21 ++++++++++++++++++--- target/arm/tcg/tlb_helper.c | 18 ------------------ 2 files changed, 18 insertions(+), 21 deletions(-) diff --git a/target/arm/internals.h b/target/arm/internals.h index ed48f8c9a6..680c574717 100644 --- a/target/arm/internals.h +++ b/target/arm/internals.h @@ -600,9 +600,6 @@ int arm_mmu_idx_to_el(ARMMMUIdx mmu_idx); /* Return the MMU index for a v7M CPU in the specified security state */ ARMMMUIdx arm_v7m_mmu_idx_for_secstate(CPUARMState *env, bool secstate); -/* Return true if the translation regime is using LPAE format page tables */ -bool regime_using_lpae_format(CPUARMState *env, ARMMMUIdx mmu_idx); - /* * Return true if the stage 1 translation regime is using LPAE * format page tables @@ -767,6 +764,24 @@ static inline uint64_t regime_tcr(CPUARMState *env, ARMMMUIdx mmu_idx) return env->cp15.tcr_el[regime_el(env, mmu_idx)]; } +/* Return true if the translation regime is using LPAE format page tables */ +static inline bool regime_using_lpae_format(CPUARMState *env, ARMMMUIdx mmu_idx) +{ + int el = regime_el(env, mmu_idx); + if (el == 2 || arm_el_is_aa64(env, el)) { + return true; + } + if (arm_feature(env, ARM_FEATURE_PMSA) && + arm_feature(env, ARM_FEATURE_V8)) { + return true; + } + if (arm_feature(env, ARM_FEATURE_LPAE) + && (regime_tcr(env, mmu_idx) & TTBCR_EAE)) { + return true; + } + return false; +} + /** * arm_num_brps: Return number of implemented breakpoints. * Note that the ID register BRPS field is "number of bps - 1", diff --git a/target/arm/tcg/tlb_helper.c b/target/arm/tcg/tlb_helper.c index 60abcbebe6..31eb77f7df 100644 --- a/target/arm/tcg/tlb_helper.c +++ b/target/arm/tcg/tlb_helper.c @@ -12,24 +12,6 @@ #include "exec/helper-proto.h" -/* Return true if the translation regime is using LPAE format page tables */ -bool regime_using_lpae_format(CPUARMState *env, ARMMMUIdx mmu_idx) -{ - int el = regime_el(env, mmu_idx); - if (el == 2 || arm_el_is_aa64(env, el)) { - return true; - } - if (arm_feature(env, ARM_FEATURE_PMSA) && - arm_feature(env, ARM_FEATURE_V8)) { - return true; - } - if (arm_feature(env, ARM_FEATURE_LPAE) - && (regime_tcr(env, mmu_idx) & TTBCR_EAE)) { - return true; - } - return false; -} - /* * Returns true if the stage 1 translation regime is using LPAE format page * tables. Used when raising alignment exceptions, whose FSR changes depending From 0d3de77a07f4f774f7a9248afa8ea497ad5f2ae5 Mon Sep 17 00:00:00 2001 From: Fabiano Rosas Date: Fri, 17 Feb 2023 17:11:35 -0300 Subject: [PATCH 114/129] target/arm: Don't access TCG code when debugging with KVM MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When TCG is disabled this part of the code should not be reachable, so wrap it with an ifdef for now. Signed-off-by: Fabiano Rosas Reviewed-by: Richard Henderson Tested-by: Philippe Mathieu-Daudé Signed-off-by: Peter Maydell --- target/arm/ptw.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/target/arm/ptw.c b/target/arm/ptw.c index 2b125fff44..be0cc6bc15 100644 --- a/target/arm/ptw.c +++ b/target/arm/ptw.c @@ -254,6 +254,7 @@ static bool S1_ptw_translate(CPUARMState *env, S1Translate *ptw, ptw->out_host = NULL; ptw->out_rw = false; } else { +#ifdef CONFIG_TCG CPUTLBEntryFull *full; int flags; @@ -270,6 +271,9 @@ static bool S1_ptw_translate(CPUARMState *env, S1Translate *ptw, ptw->out_rw = full->prot & PAGE_WRITE; pte_attrs = full->pte_attrs; pte_secure = full->attrs.secure; +#else + g_assert_not_reached(); +#endif } if (regime_is_stage2(s2_mmu_idx)) { From 4cb884e994a85a86e4e305ea3e6296434f4af0df Mon Sep 17 00:00:00 2001 From: Fabiano Rosas Date: Fri, 17 Feb 2023 17:11:36 -0300 Subject: [PATCH 115/129] cpu-defs.h: Expose CPUTLBEntryFull to non-TCG code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This struct has no dependencies on TCG code and it is being used in target/arm/ptw.c to simplify the passing around of page table walk results. Those routines can be reached by KVM code via the gdbstub breakpoint code, so take the structure out of CONFIG_TCG to make it visible when building with --disable-tcg. Signed-off-by: Fabiano Rosas Reviewed-by: Richard Henderson Reviewed-by: Philippe Mathieu-Daudé Tested-by: Philippe Mathieu-Daudé Signed-off-by: Peter Maydell --- include/exec/cpu-defs.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/include/exec/cpu-defs.h b/include/exec/cpu-defs.h index 21309cf567..d5a4f30717 100644 --- a/include/exec/cpu-defs.h +++ b/include/exec/cpu-defs.h @@ -135,6 +135,10 @@ typedef struct CPUTLBEntry { QEMU_BUILD_BUG_ON(sizeof(CPUTLBEntry) != (1 << CPU_TLB_ENTRY_BITS)); + +#endif /* !CONFIG_USER_ONLY && CONFIG_TCG */ + +#if !defined(CONFIG_USER_ONLY) /* * The full TLB entry, which is not accessed by generated TCG code, * so the layout is not as critical as that of CPUTLBEntry. This is @@ -176,7 +180,9 @@ typedef struct CPUTLBEntryFull { TARGET_PAGE_ENTRY_EXTRA #endif } CPUTLBEntryFull; +#endif /* !CONFIG_USER_ONLY */ +#if !defined(CONFIG_USER_ONLY) && defined(CONFIG_TCG) /* * Data elements that are per MMU mode, minus the bits accessed by * the TCG fast path. From 9880e9bc63efcaf3f5230c2f93fb03068df2e465 Mon Sep 17 00:00:00 2001 From: Fabiano Rosas Date: Fri, 17 Feb 2023 17:11:46 -0300 Subject: [PATCH 116/129] tests/avocado: add machine:none tag to version.py MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This test currently fails when run on a host for which the QEMU target has no default machine set: ERROR| Output: qemu-system-aarch64: No machine specified, and there is no default Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Fabiano Rosas Signed-off-by: Peter Maydell --- tests/avocado/version.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/avocado/version.py b/tests/avocado/version.py index ded7f039c1..dd775955eb 100644 --- a/tests/avocado/version.py +++ b/tests/avocado/version.py @@ -15,6 +15,7 @@ from avocado_qemu import QemuSystemTest class Version(QemuSystemTest): """ :avocado: tags=quick + :avocado: tags=machine:none """ def test_qmp_human_info_version(self): self.vm.add_args('-nodefaults') From cb4c33f014925d860387ecef4d74a7f03cab6626 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Mon, 20 Feb 2023 12:51:07 +0100 Subject: [PATCH 117/129] hw/gpio/max7310: Simplify max7310_realize() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since &I2C_SLAVE(dev)->qdev == dev, no need to go back and forth with QOM type casting. Directly use 'dev'. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Message-id: 20230220115114.25237-2-philmd@linaro.org Signed-off-by: Peter Maydell --- hw/gpio/max7310.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/hw/gpio/max7310.c b/hw/gpio/max7310.c index db6b5e3d76..031482d939 100644 --- a/hw/gpio/max7310.c +++ b/hw/gpio/max7310.c @@ -183,11 +183,10 @@ static void max7310_gpio_set(void *opaque, int line, int level) * but also accepts sequences that are not SMBus so return an I2C device. */ static void max7310_realize(DeviceState *dev, Error **errp) { - I2CSlave *i2c = I2C_SLAVE(dev); MAX7310State *s = MAX7310(dev); - qdev_init_gpio_in(&i2c->qdev, max7310_gpio_set, 8); - qdev_init_gpio_out(&i2c->qdev, s->handler, 8); + qdev_init_gpio_in(dev, max7310_gpio_set, ARRAY_SIZE(s->handler)); + qdev_init_gpio_out(dev, s->handler, ARRAY_SIZE(s->handler)); } static void max7310_class_init(ObjectClass *klass, void *data) From 11f2ee1db6ed333a74a71fa38ce66fda926e230d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Mon, 20 Feb 2023 12:51:08 +0100 Subject: [PATCH 118/129] hw/char/pl011: Un-inline pl011_create() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit pl011_create() is only used in DeviceRealize handlers, not a hot-path. Inlining is not justified. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Alex Bennée Reviewed-by: Richard Henderson Message-id: 20230220115114.25237-3-philmd@linaro.org Signed-off-by: Peter Maydell --- hw/char/pl011.c | 17 +++++++++++++++++ include/hw/char/pl011.h | 19 +------------------ 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/hw/char/pl011.c b/hw/char/pl011.c index c15cb7af20..77bbc2a982 100644 --- a/hw/char/pl011.c +++ b/hw/char/pl011.c @@ -19,10 +19,12 @@ */ #include "qemu/osdep.h" +#include "qapi/error.h" #include "hw/char/pl011.h" #include "hw/irq.h" #include "hw/sysbus.h" #include "hw/qdev-clock.h" +#include "hw/qdev-properties.h" #include "hw/qdev-properties-system.h" #include "migration/vmstate.h" #include "chardev/char-fe.h" @@ -31,6 +33,21 @@ #include "qemu/module.h" #include "trace.h" +DeviceState *pl011_create(hwaddr addr, qemu_irq irq, Chardev *chr) +{ + DeviceState *dev; + SysBusDevice *s; + + dev = qdev_new("pl011"); + s = SYS_BUS_DEVICE(dev); + qdev_prop_set_chr(dev, "chardev", chr); + sysbus_realize_and_unref(s, &error_fatal); + sysbus_mmio_map(s, 0, addr); + sysbus_connect_irq(s, 0, irq); + + return dev; +} + #define PL011_INT_TX 0x20 #define PL011_INT_RX 0x10 diff --git a/include/hw/char/pl011.h b/include/hw/char/pl011.h index 926322e242..d82870c006 100644 --- a/include/hw/char/pl011.h +++ b/include/hw/char/pl011.h @@ -15,10 +15,8 @@ #ifndef HW_PL011_H #define HW_PL011_H -#include "hw/qdev-properties.h" #include "hw/sysbus.h" #include "chardev/char-fe.h" -#include "qapi/error.h" #include "qom/object.h" #define TYPE_PL011 "pl011" @@ -57,22 +55,7 @@ struct PL011State { const unsigned char *id; }; -static inline DeviceState *pl011_create(hwaddr addr, - qemu_irq irq, - Chardev *chr) -{ - DeviceState *dev; - SysBusDevice *s; - - dev = qdev_new("pl011"); - s = SYS_BUS_DEVICE(dev); - qdev_prop_set_chr(dev, "chardev", chr); - sysbus_realize_and_unref(s, &error_fatal); - sysbus_mmio_map(s, 0, addr); - sysbus_connect_irq(s, 0, irq); - - return dev; -} +DeviceState *pl011_create(hwaddr addr, qemu_irq irq, Chardev *chr); static inline DeviceState *pl011_luminary_create(hwaddr addr, qemu_irq irq, From b7f93098d1899c88eec4026b0a2118c94cbdefc9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Mon, 20 Feb 2023 12:51:09 +0100 Subject: [PATCH 119/129] hw/char/pl011: Open-code pl011_luminary_create() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit pl011_luminary_create() is only used for the Stellaris board, open-code it. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Alex Bennée Reviewed-by: Richard Henderson Message-id: 20230220115114.25237-4-philmd@linaro.org Signed-off-by: Peter Maydell --- hw/arm/stellaris.c | 11 ++++++++--- include/hw/char/pl011.h | 17 ----------------- 2 files changed, 8 insertions(+), 20 deletions(-) diff --git a/hw/arm/stellaris.c b/hw/arm/stellaris.c index 67a2293d35..f7e99baf62 100644 --- a/hw/arm/stellaris.c +++ b/hw/arm/stellaris.c @@ -1146,9 +1146,14 @@ static void stellaris_init(MachineState *ms, stellaris_board_info *board) for (i = 0; i < 4; i++) { if (board->dc2 & (1 << i)) { - pl011_luminary_create(0x4000c000 + i * 0x1000, - qdev_get_gpio_in(nvic, uart_irq[i]), - serial_hd(i)); + SysBusDevice *sbd; + + dev = qdev_new("pl011_luminary"); + sbd = SYS_BUS_DEVICE(dev); + qdev_prop_set_chr(dev, "chardev", serial_hd(i)); + sysbus_realize_and_unref(sbd, &error_fatal); + sysbus_mmio_map(sbd, 0, 0x4000c000 + i * 0x1000); + sysbus_connect_irq(sbd, 0, qdev_get_gpio_in(nvic, uart_irq[i])); } } if (board->dc2 & (1 << 4)) { diff --git a/include/hw/char/pl011.h b/include/hw/char/pl011.h index d82870c006..d853802132 100644 --- a/include/hw/char/pl011.h +++ b/include/hw/char/pl011.h @@ -57,21 +57,4 @@ struct PL011State { DeviceState *pl011_create(hwaddr addr, qemu_irq irq, Chardev *chr); -static inline DeviceState *pl011_luminary_create(hwaddr addr, - qemu_irq irq, - Chardev *chr) -{ - DeviceState *dev; - SysBusDevice *s; - - dev = qdev_new("pl011_luminary"); - s = SYS_BUS_DEVICE(dev); - qdev_prop_set_chr(dev, "chardev", chr); - sysbus_realize_and_unref(s, &error_fatal); - sysbus_mmio_map(s, 0, addr); - sysbus_connect_irq(s, 0, irq); - - return dev; -} - #endif From 3440a4a93aebb2abe9d9ed6ba4a0f8db86b2a6ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Mon, 20 Feb 2023 12:51:10 +0100 Subject: [PATCH 120/129] hw/char/xilinx_uartlite: Expose XILINX_UARTLITE QOM type MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Alex Bennée Reviewed-by: Richard Henderson Message-id: 20230220115114.25237-5-philmd@linaro.org Signed-off-by: Peter Maydell --- hw/char/xilinx_uartlite.c | 4 +--- include/hw/char/xilinx_uartlite.h | 6 +++++- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/hw/char/xilinx_uartlite.c b/hw/char/xilinx_uartlite.c index 99b9a6f851..180bb97202 100644 --- a/hw/char/xilinx_uartlite.c +++ b/hw/char/xilinx_uartlite.c @@ -24,6 +24,7 @@ #include "qemu/osdep.h" #include "qemu/log.h" +#include "hw/char/xilinx_uartlite.h" #include "hw/irq.h" #include "hw/qdev-properties.h" #include "hw/qdev-properties-system.h" @@ -53,9 +54,6 @@ #define CONTROL_RST_RX 0x02 #define CONTROL_IE 0x10 -#define TYPE_XILINX_UARTLITE "xlnx.xps-uartlite" -OBJECT_DECLARE_SIMPLE_TYPE(XilinxUARTLite, XILINX_UARTLITE) - struct XilinxUARTLite { SysBusDevice parent_obj; diff --git a/include/hw/char/xilinx_uartlite.h b/include/hw/char/xilinx_uartlite.h index dd09c06801..753d3a453e 100644 --- a/include/hw/char/xilinx_uartlite.h +++ b/include/hw/char/xilinx_uartlite.h @@ -18,6 +18,10 @@ #include "hw/qdev-properties.h" #include "hw/sysbus.h" #include "qapi/error.h" +#include "qom/object.h" + +#define TYPE_XILINX_UARTLITE "xlnx.xps-uartlite" +OBJECT_DECLARE_SIMPLE_TYPE(XilinxUARTLite, XILINX_UARTLITE) static inline DeviceState *xilinx_uartlite_create(hwaddr addr, qemu_irq irq, @@ -26,7 +30,7 @@ static inline DeviceState *xilinx_uartlite_create(hwaddr addr, DeviceState *dev; SysBusDevice *s; - dev = qdev_new("xlnx.xps-uartlite"); + dev = qdev_new(TYPE_XILINX_UARTLITE); s = SYS_BUS_DEVICE(dev); qdev_prop_set_chr(dev, "chardev", chr); sysbus_realize_and_unref(s, &error_fatal); From dc1daf392c7cc6d1481bd9ce40a5594e624e7b47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Mon, 20 Feb 2023 12:51:11 +0100 Subject: [PATCH 121/129] hw/char/xilinx_uartlite: Open-code xilinx_uartlite_create() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Open-code the single use of xilinx_uartlite_create(). Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Alex Bennée Reviewed-by: Richard Henderson Message-id: 20230220115114.25237-6-philmd@linaro.org Signed-off-by: Peter Maydell --- hw/microblaze/petalogix_s3adsp1800_mmu.c | 7 +++++-- include/hw/char/xilinx_uartlite.h | 20 -------------------- 2 files changed, 5 insertions(+), 22 deletions(-) diff --git a/hw/microblaze/petalogix_s3adsp1800_mmu.c b/hw/microblaze/petalogix_s3adsp1800_mmu.c index 9d959d1ad8..505639c298 100644 --- a/hw/microblaze/petalogix_s3adsp1800_mmu.c +++ b/hw/microblaze/petalogix_s3adsp1800_mmu.c @@ -100,8 +100,11 @@ petalogix_s3adsp1800_init(MachineState *machine) irq[i] = qdev_get_gpio_in(dev, i); } - xilinx_uartlite_create(UARTLITE_BASEADDR, irq[UARTLITE_IRQ], - serial_hd(0)); + dev = qdev_new(TYPE_XILINX_UARTLITE); + qdev_prop_set_chr(dev, "chardev", serial_hd(0)); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); + sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, UARTLITE_BASEADDR); + sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, irq[UARTLITE_IRQ]); /* 2 timers at irq 2 @ 62 Mhz. */ dev = qdev_new("xlnx.xps-timer"); diff --git a/include/hw/char/xilinx_uartlite.h b/include/hw/char/xilinx_uartlite.h index 753d3a453e..36d4e8444d 100644 --- a/include/hw/char/xilinx_uartlite.h +++ b/include/hw/char/xilinx_uartlite.h @@ -15,29 +15,9 @@ #ifndef XILINX_UARTLITE_H #define XILINX_UARTLITE_H -#include "hw/qdev-properties.h" -#include "hw/sysbus.h" -#include "qapi/error.h" #include "qom/object.h" #define TYPE_XILINX_UARTLITE "xlnx.xps-uartlite" OBJECT_DECLARE_SIMPLE_TYPE(XilinxUARTLite, XILINX_UARTLITE) -static inline DeviceState *xilinx_uartlite_create(hwaddr addr, - qemu_irq irq, - Chardev *chr) -{ - DeviceState *dev; - SysBusDevice *s; - - dev = qdev_new(TYPE_XILINX_UARTLITE); - s = SYS_BUS_DEVICE(dev); - qdev_prop_set_chr(dev, "chardev", chr); - sysbus_realize_and_unref(s, &error_fatal); - sysbus_mmio_map(s, 0, addr); - sysbus_connect_irq(s, 0, irq); - - return dev; -} - #endif From 4ab694b9a81df82f3ac7ce1e59f7855c57af2eb1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Mon, 20 Feb 2023 12:51:12 +0100 Subject: [PATCH 122/129] hw/char/cmsdk-apb-uart: Open-code cmsdk_apb_uart_create() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit cmsdk_apb_uart_create() is only used twice in the same file. Open-code it. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Peter Maydell Message-id: 20230220115114.25237-7-philmd@linaro.org Signed-off-by: Peter Maydell --- hw/arm/mps2.c | 41 +++++++++++++++++++++----------- include/hw/char/cmsdk-apb-uart.h | 34 -------------------------- 2 files changed, 27 insertions(+), 48 deletions(-) diff --git a/hw/arm/mps2.c b/hw/arm/mps2.c index a86a994dba..d92fd60684 100644 --- a/hw/arm/mps2.c +++ b/hw/arm/mps2.c @@ -35,6 +35,7 @@ #include "hw/boards.h" #include "exec/address-spaces.h" #include "sysemu/sysemu.h" +#include "hw/qdev-properties.h" #include "hw/misc/unimp.h" #include "hw/char/cmsdk-apb-uart.h" #include "hw/timer/cmsdk-apb-timer.h" @@ -282,6 +283,9 @@ static void mps2_common_init(MachineState *machine) qdev_connect_gpio_out(orgate_dev, 0, qdev_get_gpio_in(armv7m, 12)); for (i = 0; i < 5; i++) { + DeviceState *dev; + SysBusDevice *s; + static const hwaddr uartbase[] = {0x40004000, 0x40005000, 0x40006000, 0x40007000, 0x40009000}; @@ -294,12 +298,16 @@ static void mps2_common_init(MachineState *machine) rxovrint = qdev_get_gpio_in(orgate_dev, i * 2 + 1); } - cmsdk_apb_uart_create(uartbase[i], - qdev_get_gpio_in(armv7m, uartirq[i] + 1), - qdev_get_gpio_in(armv7m, uartirq[i]), - txovrint, rxovrint, - NULL, - serial_hd(i), SYSCLK_FRQ); + dev = qdev_new(TYPE_CMSDK_APB_UART); + s = SYS_BUS_DEVICE(dev); + qdev_prop_set_chr(dev, "chardev", serial_hd(i)); + qdev_prop_set_uint32(dev, "pclk-frq", SYSCLK_FRQ); + sysbus_realize_and_unref(s, &error_fatal); + sysbus_mmio_map(s, 0, uartbase[i]); + sysbus_connect_irq(s, 0, qdev_get_gpio_in(armv7m, uartirq[i] + 1)); + sysbus_connect_irq(s, 1, qdev_get_gpio_in(armv7m, uartirq[i])); + sysbus_connect_irq(s, 2, txovrint); + sysbus_connect_irq(s, 3, rxovrint); } break; } @@ -324,7 +332,8 @@ static void mps2_common_init(MachineState *machine) 0x4002c000, 0x4002d000, 0x4002e000}; Object *txrx_orgate; - DeviceState *txrx_orgate_dev; + DeviceState *txrx_orgate_dev, *dev; + SysBusDevice *s; txrx_orgate = object_new(TYPE_OR_IRQ); object_property_set_int(txrx_orgate, "num-lines", 2, &error_fatal); @@ -332,13 +341,17 @@ static void mps2_common_init(MachineState *machine) txrx_orgate_dev = DEVICE(txrx_orgate); qdev_connect_gpio_out(txrx_orgate_dev, 0, qdev_get_gpio_in(armv7m, uart_txrx_irqno[i])); - cmsdk_apb_uart_create(uartbase[i], - qdev_get_gpio_in(txrx_orgate_dev, 0), - qdev_get_gpio_in(txrx_orgate_dev, 1), - qdev_get_gpio_in(orgate_dev, i * 2), - qdev_get_gpio_in(orgate_dev, i * 2 + 1), - NULL, - serial_hd(i), SYSCLK_FRQ); + + dev = qdev_new(TYPE_CMSDK_APB_UART); + s = SYS_BUS_DEVICE(dev); + qdev_prop_set_chr(dev, "chardev", serial_hd(i)); + qdev_prop_set_uint32(dev, "pclk-frq", SYSCLK_FRQ); + sysbus_realize_and_unref(s, &error_fatal); + sysbus_mmio_map(s, 0, uartbase[i]); + sysbus_connect_irq(s, 0, qdev_get_gpio_in(txrx_orgate_dev, 0)); + sysbus_connect_irq(s, 1, qdev_get_gpio_in(txrx_orgate_dev, 1)); + sysbus_connect_irq(s, 2, qdev_get_gpio_in(orgate_dev, i * 2)); + sysbus_connect_irq(s, 3, qdev_get_gpio_in(orgate_dev, i * 2 + 1)); } break; } diff --git a/include/hw/char/cmsdk-apb-uart.h b/include/hw/char/cmsdk-apb-uart.h index 64b0a3d534..7de8f8d1b9 100644 --- a/include/hw/char/cmsdk-apb-uart.h +++ b/include/hw/char/cmsdk-apb-uart.h @@ -12,10 +12,8 @@ #ifndef CMSDK_APB_UART_H #define CMSDK_APB_UART_H -#include "hw/qdev-properties.h" #include "hw/sysbus.h" #include "chardev/char-fe.h" -#include "qapi/error.h" #include "qom/object.h" #define TYPE_CMSDK_APB_UART "cmsdk-apb-uart" @@ -45,36 +43,4 @@ struct CMSDKAPBUART { uint8_t rxbuf; }; -/** - * cmsdk_apb_uart_create - convenience function to create TYPE_CMSDK_APB_UART - * @addr: location in system memory to map registers - * @chr: Chardev backend to connect UART to, or NULL if no backend - * @pclk_frq: frequency in Hz of the PCLK clock (used for calculating baud rate) - */ -static inline DeviceState *cmsdk_apb_uart_create(hwaddr addr, - qemu_irq txint, - qemu_irq rxint, - qemu_irq txovrint, - qemu_irq rxovrint, - qemu_irq uartint, - Chardev *chr, - uint32_t pclk_frq) -{ - DeviceState *dev; - SysBusDevice *s; - - dev = qdev_new(TYPE_CMSDK_APB_UART); - s = SYS_BUS_DEVICE(dev); - qdev_prop_set_chr(dev, "chardev", chr); - qdev_prop_set_uint32(dev, "pclk-frq", pclk_frq); - sysbus_realize_and_unref(s, &error_fatal); - sysbus_mmio_map(s, 0, addr); - sysbus_connect_irq(s, 0, txint); - sysbus_connect_irq(s, 1, rxint); - sysbus_connect_irq(s, 2, txovrint); - sysbus_connect_irq(s, 3, rxovrint); - sysbus_connect_irq(s, 4, uartint); - return dev; -} - #endif From 7c72f2196ac3d1fe46e4f0bff103beef2b555633 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Mon, 20 Feb 2023 12:51:13 +0100 Subject: [PATCH 123/129] hw/timer/cmsdk-apb-timer: Remove unused 'qdev-properties.h' header MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Alex Bennée Message-id: 20230220115114.25237-8-philmd@linaro.org Signed-off-by: Peter Maydell --- include/hw/timer/cmsdk-apb-timer.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/hw/timer/cmsdk-apb-timer.h b/include/hw/timer/cmsdk-apb-timer.h index c4c7eae849..2dd615d1be 100644 --- a/include/hw/timer/cmsdk-apb-timer.h +++ b/include/hw/timer/cmsdk-apb-timer.h @@ -12,7 +12,6 @@ #ifndef CMSDK_APB_TIMER_H #define CMSDK_APB_TIMER_H -#include "hw/qdev-properties.h" #include "hw/sysbus.h" #include "hw/ptimer.h" #include "hw/clock.h" From d4fb55a6083c8535ad7b46019ae3cbc1be5497e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Mon, 20 Feb 2023 12:51:14 +0100 Subject: [PATCH 124/129] hw/intc/armv7m_nvic: Use QOM cast CPU() macro MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Avoid accessing 'parent_obj' directly. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Alex Bennée Message-id: 20230220115114.25237-9-philmd@linaro.org Signed-off-by: Peter Maydell --- hw/intc/armv7m_nvic.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c index 8e289051a4..63afe1fdf5 100644 --- a/hw/intc/armv7m_nvic.c +++ b/hw/intc/armv7m_nvic.c @@ -578,7 +578,7 @@ static void do_armv7m_nvic_set_pending(void *opaque, int irq, bool secure, * which saves having to have an extra argument is_terminal * that we'd only use in one place. */ - cpu_abort(&s->cpu->parent_obj, + cpu_abort(CPU(s->cpu), "Lockup: can't take terminal derived exception " "(original exception priority %d)\n", s->vectpending_prio); @@ -644,7 +644,7 @@ static void do_armv7m_nvic_set_pending(void *opaque, int irq, bool secure, * Lockup condition due to a guest bug. We don't model * Lockup, so report via cpu_abort() instead. */ - cpu_abort(&s->cpu->parent_obj, + cpu_abort(CPU(s->cpu), "Lockup: can't escalate %d to HardFault " "(current priority %d)\n", irq, running); } @@ -742,7 +742,7 @@ void armv7m_nvic_set_pending_lazyfp(NVICState *s, int irq, bool secure) * We want to escalate to HardFault but the context the * FP state belongs to prevents the exception pre-empting. */ - cpu_abort(&s->cpu->parent_obj, + cpu_abort(CPU(s->cpu), "Lockup: can't escalate to HardFault during " "lazy FP register stacking\n"); } From 799d6a3c9923308f8ae7d12438e0723c4eadd124 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Mon, 9 Jan 2023 10:26:09 +0100 Subject: [PATCH 125/129] hw/arm/musicpal: Remove unused dummy MemoryRegion MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Signed-off-by: Peter Maydell --- hw/arm/musicpal.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/hw/arm/musicpal.c b/hw/arm/musicpal.c index 89b66606c3..06d9add7c7 100644 --- a/hw/arm/musicpal.c +++ b/hw/arm/musicpal.c @@ -1072,7 +1072,6 @@ struct musicpal_key_state { SysBusDevice parent_obj; /*< public >*/ - MemoryRegion iomem; uint32_t kbd_extended; uint32_t pressed_keys; qemu_irq out[8]; @@ -1161,9 +1160,6 @@ static void musicpal_key_init(Object *obj) DeviceState *dev = DEVICE(sbd); musicpal_key_state *s = MUSICPAL_KEY(dev); - memory_region_init(&s->iomem, obj, "dummy", 0); - sysbus_init_mmio(sbd, &s->iomem); - s->kbd_extended = 0; s->pressed_keys = 0; From dc892d1e4c8d3682d624725d7cfeee90f35d6eff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Fri, 13 Jan 2023 21:01:35 +0100 Subject: [PATCH 126/129] iothread: Remove unused IOThreadClass / IOTHREAD_CLASS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since commit be8d853766 ("iothread: add I/O thread object") we never used IOThreadClass / IOTHREAD_CLASS() / IOTHREAD_GET_CLASS(), remove these definitions. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Stefan Hajnoczi Reviewed-by: Alistair Francis Message-id: 20230113200138.52869-2-philmd@linaro.org Signed-off-by: Peter Maydell --- iothread.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/iothread.c b/iothread.c index 3862a64471..b41c305bd9 100644 --- a/iothread.c +++ b/iothread.c @@ -25,10 +25,6 @@ #include "qemu/rcu.h" #include "qemu/main-loop.h" -typedef ObjectClass IOThreadClass; - -DECLARE_CLASS_CHECKERS(IOThreadClass, IOTHREAD, - TYPE_IOTHREAD) #ifdef CONFIG_POSIX /* Benchmark results from 2016 on NVMe SSD drives show max polling times around From 4703f6c2f7a982ccc6e970ad3010bfe1203a828d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Fri, 13 Jan 2023 21:01:36 +0100 Subject: [PATCH 127/129] hw/irq: Declare QOM macros using OBJECT_DECLARE_SIMPLE_TYPE() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit QOM *DECLARE* macros expect a typedef as first argument, not a structure. Replace 'struct IRQState' by 'IRQState' to avoid when modifying the macros: ../hw/core/irq.c:29:1: error: declaration of anonymous struct must be a definition DECLARE_INSTANCE_CHECKER(struct IRQState, IRQ, ^ Use OBJECT_DECLARE_SIMPLE_TYPE instead of DECLARE_INSTANCE_CHECKER. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Stefan Hajnoczi Reviewed-by: Alistair Francis Message-id: 20230113200138.52869-3-philmd@linaro.org Signed-off-by: Peter Maydell --- hw/core/irq.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/hw/core/irq.c b/hw/core/irq.c index 3623f711fe..3f14e2dda7 100644 --- a/hw/core/irq.c +++ b/hw/core/irq.c @@ -26,8 +26,7 @@ #include "hw/irq.h" #include "qom/object.h" -DECLARE_INSTANCE_CHECKER(struct IRQState, IRQ, - TYPE_IRQ) +OBJECT_DECLARE_SIMPLE_TYPE(IRQState, IRQ) struct IRQState { Object parent_obj; @@ -68,7 +67,7 @@ qemu_irq *qemu_allocate_irqs(qemu_irq_handler handler, void *opaque, int n) qemu_irq qemu_allocate_irq(qemu_irq_handler handler, void *opaque, int n) { - struct IRQState *irq; + IRQState *irq; irq = IRQ(object_new(TYPE_IRQ)); irq->handler = handler; @@ -94,7 +93,7 @@ void qemu_free_irq(qemu_irq irq) static void qemu_notirq(void *opaque, int line, int level) { - struct IRQState *irq = opaque; + IRQState *irq = opaque; irq->handler(irq->opaque, irq->n, !level); } @@ -120,7 +119,7 @@ void qemu_irq_intercept_in(qemu_irq *gpio_in, qemu_irq_handler handler, int n) static const TypeInfo irq_type_info = { .name = TYPE_IRQ, .parent = TYPE_OBJECT, - .instance_size = sizeof(struct IRQState), + .instance_size = sizeof(IRQState), }; static void irq_register_types(void) From 60d3ccfbe119974d3adda799de85cdae698c5434 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Fri, 13 Jan 2023 21:01:37 +0100 Subject: [PATCH 128/129] hw/or-irq: Declare QOM macros using OBJECT_DECLARE_SIMPLE_TYPE() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Missed during automatic conversion from commit 8063396bf3 ("Use OBJECT_DECLARE_SIMPLE_TYPE when possible"). Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Stefan Hajnoczi Reviewed-by: Alistair Francis Message-id: 20230113200138.52869-4-philmd@linaro.org Signed-off-by: Peter Maydell --- include/hw/or-irq.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/include/hw/or-irq.h b/include/hw/or-irq.h index f2f0a27381..131abc2e0c 100644 --- a/include/hw/or-irq.h +++ b/include/hw/or-irq.h @@ -37,8 +37,7 @@ typedef struct OrIRQState qemu_or_irq; -DECLARE_INSTANCE_CHECKER(qemu_or_irq, OR_IRQ, - TYPE_OR_IRQ) +OBJECT_DECLARE_SIMPLE_TYPE(OrIRQState, OR_IRQ) struct OrIRQState { DeviceState parent_obj; From e844f0c5d0bd2c4d8d3c1622eb2a88586c9c4677 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Fri, 13 Jan 2023 21:01:38 +0100 Subject: [PATCH 129/129] hw: Replace qemu_or_irq typedef by OrIRQState MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit OBJECT_DECLARE_SIMPLE_TYPE() macro provides the OrIRQState declaration for free. Besides, the QOM code style is to use the structure name as typedef, and QEMU style is to use Camel Case, so rename qemu_or_irq as OrIRQState. Mechanical change using: $ sed -i -e 's/qemu_or_irq/OrIRQState/g' $(git grep -l qemu_or_irq) Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Stefan Hajnoczi Reviewed-by: Alistair Francis Message-id: 20230113200138.52869-5-philmd@linaro.org Signed-off-by: Peter Maydell --- hw/arm/exynos4210.c | 4 ++-- hw/arm/mps2-tz.c | 2 +- hw/core/or-irq.c | 18 +++++++++--------- hw/pci-host/raven.c | 2 +- include/hw/arm/armsse.h | 6 +++--- include/hw/arm/bcm2835_peripherals.h | 2 +- include/hw/arm/exynos4210.h | 4 ++-- include/hw/arm/stm32f205_soc.h | 2 +- include/hw/arm/stm32f405_soc.h | 2 +- include/hw/arm/xlnx-versal.h | 6 +++--- include/hw/arm/xlnx-zynqmp.h | 2 +- include/hw/or-irq.h | 2 -- 12 files changed, 25 insertions(+), 27 deletions(-) diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c index 8dafa2215b..6f2dda13f6 100644 --- a/hw/arm/exynos4210.c +++ b/hw/arm/exynos4210.c @@ -507,7 +507,7 @@ static uint64_t exynos4210_calc_affinity(int cpu) return (0x9 << ARM_AFF1_SHIFT) | cpu; } -static DeviceState *pl330_create(uint32_t base, qemu_or_irq *orgate, +static DeviceState *pl330_create(uint32_t base, OrIRQState *orgate, qemu_irq irq, int nreq, int nevents, int width) { SysBusDevice *busdev; @@ -806,7 +806,7 @@ static void exynos4210_init(Object *obj) for (i = 0; i < ARRAY_SIZE(s->pl330_irq_orgate); i++) { char *name = g_strdup_printf("pl330-irq-orgate%d", i); - qemu_or_irq *orgate = &s->pl330_irq_orgate[i]; + OrIRQState *orgate = &s->pl330_irq_orgate[i]; object_initialize_child(obj, name, orgate, TYPE_OR_IRQ); g_free(name); diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c index 284c09c91d..07aecd9497 100644 --- a/hw/arm/mps2-tz.c +++ b/hw/arm/mps2-tz.c @@ -152,7 +152,7 @@ struct MPS2TZMachineState { TZMSC msc[4]; CMSDKAPBUART uart[6]; SplitIRQ sec_resp_splitter; - qemu_or_irq uart_irq_orgate; + OrIRQState uart_irq_orgate; DeviceState *lan9118; SplitIRQ cpu_irq_splitter[MPS2TZ_NUMIRQ_MAX]; Clock *sysclk; diff --git a/hw/core/or-irq.c b/hw/core/or-irq.c index d8f3754e96..1df4bc05a7 100644 --- a/hw/core/or-irq.c +++ b/hw/core/or-irq.c @@ -31,7 +31,7 @@ static void or_irq_handler(void *opaque, int n, int level) { - qemu_or_irq *s = OR_IRQ(opaque); + OrIRQState *s = OR_IRQ(opaque); int or_level = 0; int i; @@ -46,7 +46,7 @@ static void or_irq_handler(void *opaque, int n, int level) static void or_irq_reset(DeviceState *dev) { - qemu_or_irq *s = OR_IRQ(dev); + OrIRQState *s = OR_IRQ(dev); int i; for (i = 0; i < MAX_OR_LINES; i++) { @@ -56,7 +56,7 @@ static void or_irq_reset(DeviceState *dev) static void or_irq_realize(DeviceState *dev, Error **errp) { - qemu_or_irq *s = OR_IRQ(dev); + OrIRQState *s = OR_IRQ(dev); assert(s->num_lines <= MAX_OR_LINES); @@ -65,7 +65,7 @@ static void or_irq_realize(DeviceState *dev, Error **errp) static void or_irq_init(Object *obj) { - qemu_or_irq *s = OR_IRQ(obj); + OrIRQState *s = OR_IRQ(obj); qdev_init_gpio_out(DEVICE(obj), &s->out_irq, 1); } @@ -84,7 +84,7 @@ static void or_irq_init(Object *obj) static bool vmstate_extras_needed(void *opaque) { - qemu_or_irq *s = OR_IRQ(opaque); + OrIRQState *s = OR_IRQ(opaque); return s->num_lines >= OLD_MAX_OR_LINES; } @@ -95,7 +95,7 @@ static const VMStateDescription vmstate_or_irq_extras = { .minimum_version_id = 1, .needed = vmstate_extras_needed, .fields = (VMStateField[]) { - VMSTATE_VARRAY_UINT16_UNSAFE(levels, qemu_or_irq, num_lines, 0, + VMSTATE_VARRAY_UINT16_UNSAFE(levels, OrIRQState, num_lines, 0, vmstate_info_bool, bool), VMSTATE_END_OF_LIST(), }, @@ -106,7 +106,7 @@ static const VMStateDescription vmstate_or_irq = { .version_id = 1, .minimum_version_id = 1, .fields = (VMStateField[]) { - VMSTATE_BOOL_SUB_ARRAY(levels, qemu_or_irq, 0, OLD_MAX_OR_LINES), + VMSTATE_BOOL_SUB_ARRAY(levels, OrIRQState, 0, OLD_MAX_OR_LINES), VMSTATE_END_OF_LIST(), }, .subsections = (const VMStateDescription*[]) { @@ -116,7 +116,7 @@ static const VMStateDescription vmstate_or_irq = { }; static Property or_irq_properties[] = { - DEFINE_PROP_UINT16("num-lines", qemu_or_irq, num_lines, 1), + DEFINE_PROP_UINT16("num-lines", OrIRQState, num_lines, 1), DEFINE_PROP_END_OF_LIST(), }; @@ -136,7 +136,7 @@ static void or_irq_class_init(ObjectClass *klass, void *data) static const TypeInfo or_irq_type_info = { .name = TYPE_OR_IRQ, .parent = TYPE_DEVICE, - .instance_size = sizeof(qemu_or_irq), + .instance_size = sizeof(OrIRQState), .instance_init = or_irq_init, .class_init = or_irq_class_init, }; diff --git a/hw/pci-host/raven.c b/hw/pci-host/raven.c index cdfb62ac2e..072ffe3c5e 100644 --- a/hw/pci-host/raven.c +++ b/hw/pci-host/raven.c @@ -60,7 +60,7 @@ DECLARE_INSTANCE_CHECKER(PREPPCIState, RAVEN_PCI_HOST_BRIDGE, struct PRePPCIState { PCIHostState parent_obj; - qemu_or_irq *or_irq; + OrIRQState *or_irq; qemu_irq pci_irqs[PCI_NUM_PINS]; PCIBus pci_bus; AddressSpace pci_io_as; diff --git a/include/hw/arm/armsse.h b/include/hw/arm/armsse.h index 9648e7a419..cd0931d0a0 100644 --- a/include/hw/arm/armsse.h +++ b/include/hw/arm/armsse.h @@ -155,12 +155,12 @@ struct ARMSSE { TZPPC apb_ppc[NUM_INTERNAL_PPCS]; TZMPC mpc[IOTS_NUM_MPC]; CMSDKAPBTimer timer[3]; - qemu_or_irq ppc_irq_orgate; + OrIRQState ppc_irq_orgate; SplitIRQ sec_resp_splitter; SplitIRQ ppc_irq_splitter[NUM_PPCS]; SplitIRQ mpc_irq_splitter[IOTS_NUM_EXP_MPC + IOTS_NUM_MPC]; - qemu_or_irq mpc_irq_orgate; - qemu_or_irq nmi_orgate; + OrIRQState mpc_irq_orgate; + OrIRQState nmi_orgate; SplitIRQ cpu_irq_splitter[NUM_SSE_IRQS]; diff --git a/include/hw/arm/bcm2835_peripherals.h b/include/hw/arm/bcm2835_peripherals.h index c9d25d493e..d724a2fc28 100644 --- a/include/hw/arm/bcm2835_peripherals.h +++ b/include/hw/arm/bcm2835_peripherals.h @@ -56,7 +56,7 @@ struct BCM2835PeripheralState { BCM2835AuxState aux; BCM2835FBState fb; BCM2835DMAState dma; - qemu_or_irq orgated_dma_irq; + OrIRQState orgated_dma_irq; BCM2835ICState ic; BCM2835PropertyState property; BCM2835RngState rng; diff --git a/include/hw/arm/exynos4210.h b/include/hw/arm/exynos4210.h index 97353f1c02..68db19f0cb 100644 --- a/include/hw/arm/exynos4210.h +++ b/include/hw/arm/exynos4210.h @@ -96,8 +96,8 @@ struct Exynos4210State { MemoryRegion boot_secondary; MemoryRegion bootreg_mem; I2CBus *i2c_if[EXYNOS4210_I2C_NUMBER]; - qemu_or_irq pl330_irq_orgate[EXYNOS4210_NUM_DMA]; - qemu_or_irq cpu_irq_orgate[EXYNOS4210_NCPUS]; + OrIRQState pl330_irq_orgate[EXYNOS4210_NUM_DMA]; + OrIRQState cpu_irq_orgate[EXYNOS4210_NCPUS]; A9MPPrivState a9mpcore; Exynos4210GicState ext_gic; Exynos4210CombinerState int_combiner; diff --git a/include/hw/arm/stm32f205_soc.h b/include/hw/arm/stm32f205_soc.h index 849d3ed889..5a4f776264 100644 --- a/include/hw/arm/stm32f205_soc.h +++ b/include/hw/arm/stm32f205_soc.h @@ -63,7 +63,7 @@ struct STM32F205State { STM32F2XXADCState adc[STM_NUM_ADCS]; STM32F2XXSPIState spi[STM_NUM_SPIS]; - qemu_or_irq *adc_irqs; + OrIRQState *adc_irqs; MemoryRegion sram; MemoryRegion flash; diff --git a/include/hw/arm/stm32f405_soc.h b/include/hw/arm/stm32f405_soc.h index 249ab5434e..c968ce3ab2 100644 --- a/include/hw/arm/stm32f405_soc.h +++ b/include/hw/arm/stm32f405_soc.h @@ -63,7 +63,7 @@ struct STM32F405State { STM32F4xxExtiState exti; STM32F2XXUsartState usart[STM_NUM_USARTS]; STM32F2XXTimerState timer[STM_NUM_TIMERS]; - qemu_or_irq adc_irqs; + OrIRQState adc_irqs; STM32F2XXADCState adc[STM_NUM_ADCS]; STM32F2XXSPIState spi[STM_NUM_SPIS]; diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h index cbe8a19c10..b6786e9832 100644 --- a/include/hw/arm/xlnx-versal.h +++ b/include/hw/arm/xlnx-versal.h @@ -85,7 +85,7 @@ struct Versal { } rpu; struct { - qemu_or_irq irq_orgate; + OrIRQState irq_orgate; XlnxXramCtrl ctrl[XLNX_VERSAL_NR_XRAM]; } xram; @@ -103,7 +103,7 @@ struct Versal { XlnxCSUDMA dma_src; XlnxCSUDMA dma_dst; MemoryRegion linear_mr; - qemu_or_irq irq_orgate; + OrIRQState irq_orgate; } ospi; } iou; @@ -113,7 +113,7 @@ struct Versal { XlnxVersalEFuseCtrl efuse_ctrl; XlnxVersalEFuseCache efuse_cache; - qemu_or_irq apb_irq_orgate; + OrIRQState apb_irq_orgate; } pmc; struct { diff --git a/include/hw/arm/xlnx-zynqmp.h b/include/hw/arm/xlnx-zynqmp.h index 20bdf894aa..687c75e3b0 100644 --- a/include/hw/arm/xlnx-zynqmp.h +++ b/include/hw/arm/xlnx-zynqmp.h @@ -130,7 +130,7 @@ struct XlnxZynqMPState { XlnxZDMA gdma[XLNX_ZYNQMP_NUM_GDMA_CH]; XlnxZDMA adma[XLNX_ZYNQMP_NUM_ADMA_CH]; XlnxCSUDMA qspi_dma; - qemu_or_irq qspi_irq_orgate; + OrIRQState qspi_irq_orgate; XlnxZynqMPAPUCtrl apu_ctrl; XlnxZynqMPCRF crf; CadenceTTCState ttc[XLNX_ZYNQMP_NUM_TTC]; diff --git a/include/hw/or-irq.h b/include/hw/or-irq.h index 131abc2e0c..c0a42f3711 100644 --- a/include/hw/or-irq.h +++ b/include/hw/or-irq.h @@ -35,8 +35,6 @@ */ #define MAX_OR_LINES 48 -typedef struct OrIRQState qemu_or_irq; - OBJECT_DECLARE_SIMPLE_TYPE(OrIRQState, OR_IRQ) struct OrIRQState {