diff options
29 files changed, 423 insertions, 112 deletions
diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs new file mode 100644 index 0000000000..93718ef425 --- /dev/null +++ b/.git-blame-ignore-revs @@ -0,0 +1,21 @@ +# +# List of code-formatting clean ups the git blame can ignore +# +# git blame --ignore-revs-file .git-blame-ignore-revs +# +# or +# +# git config blame.ignoreRevsFile .git-blame-ignore-revs +# + +# gdbstub: clean-up indents +ad9e4585b3c7425759d3eea697afbca71d2c2082 + +# e1000e: fix code style +0eadd56bf53ab196a16d492d7dd31c62e1c24c32 + +# target/riscv: coding style fixes +8c7feddddd9218b407792120bcfda0347ed16205 + +# replace TABs with spaces +48805df9c22a0700fba4b3b548fafaa21726ca68 diff --git a/.gitlab-ci.d/base.yml b/.gitlab-ci.d/base.yml index 0274228de8..2fbb58d2a3 100644 --- a/.gitlab-ci.d/base.yml +++ b/.gitlab-ci.d/base.yml @@ -75,5 +75,5 @@ - if: '$QEMU_CI != "2" && $CI_PROJECT_NAMESPACE != "qemu-project"' when: manual - # Jobs can run if any jobs they depend on were successfull + # Jobs can run if any jobs they depend on were successful - when: on_success diff --git a/MAINTAINERS b/MAINTAINERS index ef45b5e71e..2c2068ea5c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -64,6 +64,20 @@ L: qemu-devel@nongnu.org F: * F: */ +Project policy and developer guides +R: Alex Bennée <alex.bennee@linaro.org> +R: Daniel P. Berrangé <berrange@redhat.com> +R: Thomas Huth <thuth@redhat.com> +R: Markus Armbruster <armbru@redhat.com> +R: Philippe Mathieu-Daudé <philmd@linaro.org> +W: https://www.qemu.org/docs/master/devel/index.html +S: Odd Fixes +F: docs/devel/style.rst +F: docs/devel/code-of-conduct.rst +F: docs/devel/conflict-resolution.rst +F: docs/devel/submitting-a-patch.rst +F: docs/devel/submitting-a-pull-request.rst + Responsible Disclosure, Reporting Security Issues ------------------------------------------------- W: https://wiki.qemu.org/SecurityProcess @@ -2119,7 +2133,6 @@ T: git https://github.com/borntraeger/qemu.git s390-next L: qemu-s390x@nongnu.org virtiofs -M: Dr. David Alan Gilbert <dgilbert@redhat.com> M: Stefan Hajnoczi <stefanha@redhat.com> S: Supported F: hw/virtio/vhost-user-fs* @@ -2863,7 +2876,7 @@ F: tests/unit/test-rcu-*.c F: util/rcu.c Human Monitor (HMP) -M: Dr. David Alan Gilbert <dgilbert@redhat.com> +M: Dr. David Alan Gilbert <dave@treblig.org> S: Maintained F: monitor/monitor-internal.h F: monitor/misc.c @@ -3136,7 +3149,6 @@ F: scripts/checkpatch.pl Migration M: Juan Quintela <quintela@redhat.com> -M: Dr. David Alan Gilbert <dgilbert@redhat.com> S: Maintained F: hw/core/vmstate-if.c F: include/hw/vmstate-if.h @@ -3908,3 +3920,8 @@ Performance Tools and Tests M: Ahmed Karaman <ahmedkhaledkaraman@gmail.com> S: Maintained F: scripts/performance/ + +Code Coverage Tools +M: Alex Bennée <alex.bennee@linaro.org> +S: Odd Fixes +F: scripts/coverage/ diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c index c815f2dbfd..8370c92c05 100644 --- a/accel/tcg/cpu-exec.c +++ b/accel/tcg/cpu-exec.c @@ -257,7 +257,7 @@ static inline TranslationBlock *tb_lookup(CPUState *cpu, target_ulong pc, if (cflags & CF_PCREL) { /* Use acquire to ensure current load of pc from jc. */ - tb = qatomic_load_acquire(&jc->array[hash].tb); + tb = qatomic_load_acquire(&jc->array[hash].tb); if (likely(tb && jc->array[hash].pc == pc && @@ -272,7 +272,7 @@ static inline TranslationBlock *tb_lookup(CPUState *cpu, target_ulong pc, return NULL; } jc->array[hash].pc = pc; - /* Use store_release on tb to ensure pc is written first. */ + /* Ensure pc is written first. */ qatomic_store_release(&jc->array[hash].tb, tb); } else { /* Use rcu_read to ensure current load of pc from *tb. */ @@ -971,18 +971,27 @@ cpu_exec_loop(CPUState *cpu, SyncClocks *sc) tb = tb_lookup(cpu, pc, cs_base, flags, cflags); if (tb == NULL) { + CPUJumpCache *jc; uint32_t h; mmap_lock(); tb = tb_gen_code(cpu, pc, cs_base, flags, cflags); mmap_unlock(); + /* * We add the TB in the virtual pc hash table * for the fast lookup */ h = tb_jmp_cache_hash_func(pc); - /* Use the pc value already stored in tb->pc. */ - qatomic_set(&cpu->tb_jmp_cache->array[h].tb, tb); + jc = cpu->tb_jmp_cache; + if (cflags & CF_PCREL) { + jc->array[h].pc = pc; + /* Ensure pc is written first. */ + qatomic_store_release(&jc->array[h].tb, tb); + } else { + /* Use the pc value already stored in tb->pc. */ + qatomic_set(&jc->array[h].tb, tb); + } } #ifndef CONFIG_USER_ONLY diff --git a/accel/tcg/tcg-accel-ops.c b/accel/tcg/tcg-accel-ops.c index af35e0d092..58c8e64096 100644 --- a/accel/tcg/tcg-accel-ops.c +++ b/accel/tcg/tcg-accel-ops.c @@ -59,7 +59,7 @@ void tcg_cpu_init_cflags(CPUState *cpu, bool parallel) cflags |= parallel ? CF_PARALLEL : 0; cflags |= icount_enabled() ? CF_USE_ICOUNT : 0; - cpu->tcg_cflags = cflags; + cpu->tcg_cflags |= cflags; } void tcg_cpus_destroy(CPUState *cpu) diff --git a/block/dmg-lzfse.c b/block/dmg-lzfse.c index 6798cf4fbf..4ea0b9b20d 100644 --- a/block/dmg-lzfse.c +++ b/block/dmg-lzfse.c @@ -23,7 +23,12 @@ */ #include "qemu/osdep.h" #include "dmg.h" + +/* Work around a -Wstrict-prototypes warning in LZFSE headers */ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wstrict-prototypes" #include <lzfse.h> +#pragma GCC diagnostic pop static int dmg_uncompress_lzfse_do(char *next_in, unsigned int avail_in, char *next_out, unsigned int avail_out) diff --git a/gdbstub/gdbstub.c b/gdbstub/gdbstub.c index 2a66371aa5..0760d78685 100644 --- a/gdbstub/gdbstub.c +++ b/gdbstub/gdbstub.c @@ -1468,7 +1468,7 @@ static void handle_query_supported(GArray *params, void *user_ctx) ";ReverseStep+;ReverseContinue+"); } -#ifdef CONFIG_USER_ONLY +#if defined(CONFIG_USER_ONLY) && defined(CONFIG_LINUX) if (gdbserver_state.c_cpu->opaque) { g_string_append(gdbserver_state.str_buf, ";qXfer:auxv:read+"); } diff --git a/gdbstub/meson.build b/gdbstub/meson.build index bd5c5cd67d..cdb4d28691 100644 --- a/gdbstub/meson.build +++ b/gdbstub/meson.build @@ -20,11 +20,13 @@ gdb_softmmu_ss = gdb_softmmu_ss.apply(config_host, strict: false) libgdb_user = static_library('gdb_user', gdb_user_ss.sources() + genh, name_suffix: 'fa', - c_args: '-DCONFIG_USER_ONLY') + c_args: '-DCONFIG_USER_ONLY', + build_by_default: have_user) libgdb_softmmu = static_library('gdb_softmmu', gdb_softmmu_ss.sources() + genh, - name_suffix: 'fa') + name_suffix: 'fa', + build_by_default: have_system) gdb_user = declare_dependency(link_whole: libgdb_user) user_ss.add(gdb_user) diff --git a/hw/arm/boot.c b/hw/arm/boot.c index 50e5141116..54f6a3e0b3 100644 --- a/hw/arm/boot.c +++ b/hw/arm/boot.c @@ -689,7 +689,10 @@ int arm_load_dtb(hwaddr addr, const struct arm_boot_info *binfo, qemu_register_reset_nosnapshotload(qemu_fdt_randomize_seeds, rom_ptr_for_as(as, addr, size)); - g_free(fdt); + if (fdt != ms->fdt) { + g_free(ms->fdt); + ms->fdt = fdt; + } return size; diff --git a/hw/i2c/pmbus_device.c b/hw/i2c/pmbus_device.c index c3d6046784..44fe4eddbb 100644 --- a/hw/i2c/pmbus_device.c +++ b/hw/i2c/pmbus_device.c @@ -94,6 +94,13 @@ void pmbus_send64(PMBusDevice *pmdev, uint64_t data) void pmbus_send_string(PMBusDevice *pmdev, const char *data) { + if (!data) { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: %s: uninitialised read from 0x%02x\n", + __func__, DEVICE(pmdev)->canonical_path, pmdev->code); + return; + } + size_t len = strlen(data); g_assert(len > 0); g_assert(len + pmdev->out_buf_len < SMBUS_DATA_MAX_LEN); diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c index b702c3f51e..f4bf14c1c8 100644 --- a/hw/loongarch/virt.c +++ b/hw/loongarch/virt.c @@ -399,7 +399,7 @@ static struct _loaderparams { static uint64_t cpu_loongarch_virt_to_phys(void *opaque, uint64_t addr) { - return addr & 0x1fffffffll; + return addr & MAKE_64BIT_MASK(0, TARGET_PHYS_ADDR_SPACE_BITS); } static int64_t load_kernel_info(void) diff --git a/hw/pci-host/gt64120.c b/hw/pci-host/gt64120.c index f226d03420..82c15edb46 100644 --- a/hw/pci-host/gt64120.c +++ b/hw/pci-host/gt64120.c @@ -321,9 +321,6 @@ static void gt64120_isd_mapping(GT64120State *s) static void gt64120_update_pci_cfgdata_mapping(GT64120State *s) { /* Indexed on MByteSwap bit, see Table 158: PCI_0 Command, Offset: 0xc00 */ - static const MemoryRegionOps *pci_host_conf_ops[] = { - &pci_host_conf_be_ops, &pci_host_conf_le_ops - }; static const MemoryRegionOps *pci_host_data_ops[] = { &pci_host_data_be_ops, &pci_host_data_le_ops }; @@ -339,15 +336,6 @@ static void gt64120_update_pci_cfgdata_mapping(GT64120State *s) * - Table 16: 32-bit PCI Transaction Endianess * - Table 158: PCI_0 Command, Offset: 0xc00 */ - if (memory_region_is_mapped(&phb->conf_mem)) { - memory_region_del_subregion(&s->ISD_mem, &phb->conf_mem); - object_unparent(OBJECT(&phb->conf_mem)); - } - memory_region_init_io(&phb->conf_mem, OBJECT(phb), - pci_host_conf_ops[s->regs[GT_PCI0_CMD] & 1], - s, "pci-conf-idx", 4); - memory_region_add_subregion_overlap(&s->ISD_mem, GT_PCI0_CFGADDR << 2, - &phb->conf_mem, 1); if (memory_region_is_mapped(&phb->data_mem)) { memory_region_del_subregion(&s->ISD_mem, &phb->data_mem); @@ -1208,6 +1196,12 @@ static void gt64120_realize(DeviceState *dev, Error **errp) PCI_DEVFN(18, 0), TYPE_PCI_BUS); pci_create_simple(phb->bus, PCI_DEVFN(0, 0), "gt64120_pci"); + memory_region_init_io(&phb->conf_mem, OBJECT(phb), + &pci_host_conf_le_ops, + s, "pci-conf-idx", 4); + memory_region_add_subregion_overlap(&s->ISD_mem, GT_PCI0_CFGADDR << 2, + &phb->conf_mem, 1); + /* * The whole address space decoded by the GT-64120A doesn't generate diff --git a/hw/ssi/xilinx_spi.c b/hw/ssi/xilinx_spi.c index 552927622f..d4de2e7aab 100644 --- a/hw/ssi/xilinx_spi.c +++ b/hw/ssi/xilinx_spi.c @@ -156,6 +156,7 @@ static void xlx_spi_do_reset(XilinxSPI *s) txfifo_reset(s); s->regs[R_SPISSR] = ~0; + s->regs[R_SPICR] = R_SPICR_MTI; xlx_spi_update_irq(s); xlx_spi_update_cs(s); } diff --git a/linux-user/elfload.c b/linux-user/elfload.c index b96b3e566b..f1370a7a8b 100644 --- a/linux-user/elfload.c +++ b/linux-user/elfload.c @@ -423,32 +423,12 @@ enum { static bool init_guest_commpage(void) { - ARMCPU *cpu = ARM_CPU(thread_cpu); - abi_ptr want = HI_COMMPAGE & TARGET_PAGE_MASK; - abi_ptr addr; - - /* - * M-profile allocates maximum of 2GB address space, so can never - * allocate the commpage. Skip it. - */ - if (arm_feature(&cpu->env, ARM_FEATURE_M)) { - return true; - } - - /* - * If reserved_va does not cover the commpage, we get an assert - * in page_set_flags. Produce an intelligent error instead. - */ - if (reserved_va != 0 && want + TARGET_PAGE_SIZE - 1 > reserved_va) { - error_report("Allocating guest commpage: -R 0x%" PRIx64 " too small", - (uint64_t)reserved_va + 1); - exit(EXIT_FAILURE); - } - - addr = target_mmap(want, TARGET_PAGE_SIZE, PROT_READ | PROT_WRITE, - MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED, -1, 0); + abi_ptr commpage = HI_COMMPAGE & -qemu_host_page_size; + void *want = g2h_untagged(commpage); + void *addr = mmap(want, qemu_host_page_size, PROT_READ | PROT_WRITE, + MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED, -1, 0); - if (addr == -1) { + if (addr == MAP_FAILED) { perror("Allocating guest commpage"); exit(EXIT_FAILURE); } @@ -457,12 +437,15 @@ static bool init_guest_commpage(void) } /* Set kernel helper versions; rest of page is 0. */ - put_user_u32(5, 0xffff0ffcu); + __put_user(5, (uint32_t *)g2h_untagged(0xffff0ffcu)); - if (target_mprotect(addr, qemu_host_page_size, PROT_READ | PROT_EXEC)) { + if (mprotect(addr, qemu_host_page_size, PROT_READ)) { perror("Protecting guest commpage"); exit(EXIT_FAILURE); } + + page_set_flags(commpage, commpage | ~qemu_host_page_mask, + PAGE_READ | PAGE_EXEC | PAGE_VALID); return true; } diff --git a/linux-user/mips/target_elf.h b/linux-user/mips/target_elf.h index a98c9bd6ad..b965e86b2b 100644 --- a/linux-user/mips/target_elf.h +++ b/linux-user/mips/target_elf.h @@ -15,6 +15,9 @@ static inline const char *cpu_get_model(uint32_t eflags) if ((eflags & EF_MIPS_MACH) == EF_MIPS_MACH_5900) { return "R5900"; } + if (eflags & EF_MIPS_NAN2008) { + return "P5600"; + } return "24Kf"; } #endif diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h index 614a1cbc8e..cc37054cb5 100644 --- a/linux-user/syscall_defs.h +++ b/linux-user/syscall_defs.h @@ -61,7 +61,7 @@ #if (defined(TARGET_I386) && defined(TARGET_ABI32)) \ || (defined(TARGET_ARM) && defined(TARGET_ABI32)) \ - || defined(TARGET_SPARC) \ + || (defined(TARGET_SPARC) && defined(TARGET_ABI32)) \ || defined(TARGET_M68K) || defined(TARGET_SH4) || defined(TARGET_CRIS) /* 16 bit uid wrappers emulation */ #define USE_UID16 diff --git a/nbd/server.c b/nbd/server.c index 848836d414..3d8d0d81df 100644 --- a/nbd/server.c +++ b/nbd/server.c @@ -2758,6 +2758,7 @@ void nbd_client_new(QIOChannelSocket *sioc, } client->tlsauthz = g_strdup(tlsauthz); client->sioc = sioc; + qio_channel_set_delay(QIO_CHANNEL(sioc), false); object_ref(OBJECT(client->sioc)); client->ioc = QIO_CHANNEL(sioc); object_ref(OBJECT(client->ioc)); diff --git a/scripts/coverage/compare_gcov_json.py b/scripts/coverage/compare_gcov_json.py new file mode 100755 index 0000000000..1b92dc2c8c --- /dev/null +++ b/scripts/coverage/compare_gcov_json.py @@ -0,0 +1,119 @@ +#!/usr/bin/env python3 +# +# Compare output of two gcovr JSON reports and report differences. To +# generate the required output first: +# - create two build dirs with --enable-gcov +# - run set of tests in each +# - run make coverage-html in each +# - run gcovr --json --exclude-unreachable-branches \ +# --print-summary -o coverage.json --root ../../ . *.p +# +# Author: Alex Bennée <alex.bennee@linaro.org> +# +# SPDX-License-Identifier: GPL-2.0-or-later +# + +import argparse +import json +import sys +from pathlib import Path + +def create_parser(): + parser = argparse.ArgumentParser( + prog='compare_gcov_json', + description='analyse the differences in coverage between two runs') + + parser.add_argument('-a', type=Path, default=None, + help=('First file to check')) + + parser.add_argument('-b', type=Path, default=None, + help=('Second file to check')) + + parser.add_argument('--verbose', action='store_true', default=False, + help=('A minimal verbosity level that prints the ' + 'overall result of the check/wait')) + return parser + + +# See https://gcovr.com/en/stable/output/json.html#json-format-reference +def load_json(json_file_path: Path, verbose = False) -> dict[str, set[int]]: + + with open(json_file_path) as f: + data = json.load(f) + + root_dir = json_file_path.absolute().parent + covered_lines = dict() + + for filecov in data["files"]: + file_path = Path(filecov["file"]) + + # account for generated files - map into src tree + resolved_path = Path(file_path).absolute() + if resolved_path.is_relative_to(root_dir): + file_path = resolved_path.relative_to(root_dir) + # print(f"remapped {resolved_path} to {file_path}") + + lines = filecov["lines"] + + executed_lines = set( + linecov["line_number"] + for linecov in filecov["lines"] + if linecov["count"] != 0 and not linecov["gcovr/noncode"] + ) + + # if this file has any coverage add it to the system + if len(executed_lines) > 0: + if verbose: + print(f"file {file_path} {len(executed_lines)}/{len(lines)}") + covered_lines[str(file_path)] = executed_lines + + return covered_lines + +def find_missing_files(first, second): + """ + Return a list of files not covered in the second set + """ + missing_files = [] + for f in sorted(first): + file_a = first[f] + try: + file_b = second[f] + except KeyError: + missing_files.append(f) + + return missing_files + +def main(): + """ + Script entry point + """ + parser = create_parser() + args = parser.parse_args() + + if not args.a or not args.b: + print("We need two files to compare") + sys.exit(1) + + first_coverage = load_json(args.a, args.verbose) + second_coverage = load_json(args.b, args.verbose) + + first_missing = find_missing_files(first_coverage, + second_coverage) + + second_missing = find_missing_files(second_coverage, + first_coverage) + + a_name = args.a.parent.name + b_name = args.b.parent.name + + print(f"{b_name} missing coverage in {len(first_missing)} files") + for f in first_missing: + print(f" {f}") + + print(f"{a_name} missing coverage in {len(second_missing)} files") + for f in second_missing: + print(f" {f}") + + +if __name__ == '__main__': + main() diff --git a/target/arm/gdbstub64.c b/target/arm/gdbstub64.c index ec1e07f139..c1f7e8c934 100644 --- a/target/arm/gdbstub64.c +++ b/target/arm/gdbstub64.c @@ -230,8 +230,11 @@ int aarch64_gdb_get_pauth_reg(CPUARMState *env, GByteArray *buf, int reg) { bool is_data = !(reg & 1); bool is_high = reg & 2; - uint64_t mask = pauth_ptr_mask(env, -is_high, is_data); - return gdb_get_reg64(buf, mask); + ARMMMUIdx mmu_idx = arm_stage1_mmu_idx(env); + ARMVAParameters param; + + param = aa64_va_parameters(env, -is_high, mmu_idx, is_data); + return gdb_get_reg64(buf, pauth_ptr_mask(param)); } default: return 0; diff --git a/target/arm/internals.h b/target/arm/internals.h index 673519a24a..c2c70d5918 100644 --- a/target/arm/internals.h +++ b/target/arm/internals.h @@ -1391,13 +1391,18 @@ bool arm_generate_debug_exceptions(CPUARMState *env); /** * pauth_ptr_mask: - * @env: cpu context - * @ptr: selects between TTBR0 and TTBR1 - * @data: selects between TBI and TBID + * @param: parameters defining the MMU setup * - * Return a mask of the bits of @ptr that contain the authentication code. + * Return a mask of the address bits that contain the authentication code, + * given the MMU config defined by @param. */ -uint64_t pauth_ptr_mask(CPUARMState *env, uint64_t ptr, bool data); +static inline uint64_t pauth_ptr_mask(ARMVAParameters param) +{ + int bot_pac_bit = 64 - param.tsz; + int top_pac_bit = 64 - 8 * param.tbi; + + return MAKE_64BIT_MASK(bot_pac_bit, top_pac_bit - bot_pac_bit); +} /* Add the cpreg definitions for debug related system registers */ void define_debug_regs(ARMCPU *cpu); diff --git a/target/arm/tcg/pauth_helper.c b/target/arm/tcg/pauth_helper.c index 20f347332d..de067fa716 100644 --- a/target/arm/tcg/pauth_helper.c +++ b/target/arm/tcg/pauth_helper.c @@ -339,17 +339,9 @@ static uint64_t pauth_addpac(CPUARMState *env, uint64_t ptr, uint64_t modifier, return pac | ext | ptr; } -static uint64_t pauth_ptr_mask_internal(ARMVAParameters param) -{ - int bot_pac_bit = 64 - param.tsz; - int top_pac_bit = 64 - 8 * param.tbi; - - return MAKE_64BIT_MASK(bot_pac_bit, top_pac_bit - bot_pac_bit); -} - static uint64_t pauth_original_ptr(uint64_t ptr, ARMVAParameters param) { - uint64_t mask = pauth_ptr_mask_internal(param); + uint64_t mask = pauth_ptr_mask(param); /* Note that bit 55 is used whether or not the regime has 2 ranges. */ if (extract64(ptr, 55, 1)) { @@ -359,14 +351,6 @@ static uint64_t pauth_original_ptr(uint64_t ptr, ARMVAParameters param) } } -uint64_t pauth_ptr_mask(CPUARMState *env, uint64_t ptr, bool data) -{ - ARMMMUIdx mmu_idx = arm_stage1_mmu_idx(env); - ARMVAParameters param = aa64_va_parameters(env, ptr, mmu_idx, data); - - return pauth_ptr_mask_internal(param); -} - static uint64_t pauth_auth(CPUARMState *env, uint64_t ptr, uint64_t modifier, ARMPACKey *key, bool data, int keynumber) { diff --git a/target/arm/tcg/translate.c b/target/arm/tcg/translate.c index 2cb9368b1b..3c8401e908 100644 --- a/target/arm/tcg/translate.c +++ b/target/arm/tcg/translate.c @@ -4623,6 +4623,12 @@ static void do_coproc_insn(DisasContext *s, int cpnum, int is64, tcg_gen_brcondi_i32(TCG_COND_EQ, t, 0, over.label); gen_exception_insn(s, 0, EXCP_UDEF, syndrome); + /* + * gen_exception_insn() will set is_jmp to DISAS_NORETURN, + * but since we're conditionally branching over it, we want + * to assume continue-to-next-instruction. + */ + s->base.is_jmp = DISAS_NEXT; set_disas_label(s, over); } } diff --git a/target/loongarch/translate.c b/target/loongarch/translate.c index f443b5822f..21d86077f4 100644 --- a/target/loongarch/translate.c +++ b/target/loongarch/translate.c @@ -177,7 +177,7 @@ static void loongarch_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) CPULoongArchState *env = cs->env_ptr; DisasContext *ctx = container_of(dcbase, DisasContext, base); - ctx->opcode = cpu_ldl_code(env, ctx->base.pc_next); + ctx->opcode = translator_ldl(env, &ctx->base, ctx->base.pc_next); if (!decode(ctx, ctx->opcode)) { qemu_log_mask(LOG_UNIMP, "Error: unknown opcode. " diff --git a/tcg/sparc64/tcg-target.c.inc b/tcg/sparc64/tcg-target.c.inc index ccc4144f7c..694f2b9dd4 100644 --- a/tcg/sparc64/tcg-target.c.inc +++ b/tcg/sparc64/tcg-target.c.inc @@ -1445,12 +1445,12 @@ static void tcg_out_goto_tb(TCGContext *s, int which) { ptrdiff_t off = tcg_tbrel_diff(s, (void *)get_jmp_target_addr(s, which)); - /* Direct branch will be patched by tb_target_set_jmp_target. */ + /* Load link and indirect branch. */ set_jmp_insn_offset(s, which); - tcg_out32(s, CALL); - /* delay slot */ - tcg_debug_assert(check_fit_ptr(off, 13)); tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TB, TCG_REG_TB, off); + tcg_out_arithi(s, TCG_REG_G0, TCG_REG_TB, 0, JMPL); + /* delay slot */ + tcg_out_nop(s); set_jmp_reset_offset(s, which); /* @@ -1469,28 +1469,6 @@ static void tcg_out_goto_tb(TCGContext *s, int which) void tb_target_set_jmp_target(const TranslationBlock *tb, int n, uintptr_t jmp_rx, uintptr_t jmp_rw) { - uintptr_t addr = tb->jmp_target_addr[n]; - intptr_t br_disp = (intptr_t)(addr - jmp_rx) >> 2; - tcg_insn_unit insn; - - br_disp >>= 2; - if (check_fit_ptr(br_disp, 19)) { - /* ba,pt %icc, addr */ - insn = deposit32(INSN_OP(0) | INSN_OP2(1) | INSN_COND(COND_A) - | BPCC_ICC | BPCC_PT, 0, 19, br_disp); - } else if (check_fit_ptr(br_disp, 22)) { - /* ba addr */ - insn = deposit32(INSN_OP(0) | INSN_OP2(2) | INSN_COND(COND_A), - 0, 22, br_disp); - } else { - /* The code_gen_buffer can't be larger than 2GB. */ - tcg_debug_assert(check_fit_ptr(br_disp, 30)); - /* call addr */ - insn = deposit32(CALL, 0, 30, br_disp); - } - - qatomic_set((uint32_t *)jmp_rw, insn); - flush_idcache_range(jmp_rx, jmp_rw, 4); } static void tcg_out_op(TCGContext *s, TCGOpcode opc, diff --git a/tests/avocado/kvm_xen_guest.py b/tests/avocado/kvm_xen_guest.py new file mode 100644 index 0000000000..5391283113 --- /dev/null +++ b/tests/avocado/kvm_xen_guest.py @@ -0,0 +1,171 @@ +# KVM Xen guest functional tests +# +# Copyright © 2021 Red Hat, Inc. +# Copyright © 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved. +# +# Author: +# David Woodhouse <dwmw2@infradead.org> +# Alex Bennée <alex.bennee@linaro.org> +# +# SPDX-License-Identifier: GPL-2.0-or-later + +import os + +from qemu.machine import machine + +from avocado_qemu import LinuxSSHMixIn +from avocado_qemu import QemuSystemTest +from avocado_qemu import wait_for_console_pattern + +class KVMXenGuest(QemuSystemTest, LinuxSSHMixIn): + """ + :avocado: tags=arch:x86_64 + :avocado: tags=machine:q35 + :avocado: tags=accel:kvm + :avocado: tags=kvm_xen_guest + """ + + KERNEL_DEFAULT = 'printk.time=0 root=/dev/xvda console=ttyS0' + + kernel_path = None + kernel_params = None + + # Fetch assets from the kvm-xen-guest subdir of my shared test + # images directory on fileserver.linaro.org where you can find + # build instructions for how they where assembled. + def get_asset(self, name, sha1): + base_url = ('https://fileserver.linaro.org/s/' + 'kE4nCFLdQcoBF9t/download?' + 'path=%2Fkvm-xen-guest&files=' ) + url = base_url + name + # use explicit name rather than failing to neatly parse the + # URL into a unique one + return self.fetch_asset(name=name, locations=(url), asset_hash=sha1) + + def common_vm_setup(self): + # We also catch lack of KVM_XEN support if we fail to launch + self.require_accelerator("kvm") + + self.vm.set_console() + + self.vm.add_args("-accel", "kvm,xen-version=0x4000a,kernel-irqchip=split") + self.vm.add_args("-smp", "2") + + self.kernel_path = self.get_asset("bzImage", + "367962983d0d32109998a70b45dcee4672d0b045") + self.rootfs = self.get_asset("rootfs.ext4", + "f1478401ea4b3fa2ea196396be44315bab2bb5e4") + + def run_and_check(self): + self.vm.add_args('-kernel', self.kernel_path, + '-append', self.kernel_params, + '-drive', f"file={self.rootfs},if=none,format=raw,id=drv0", + '-device', 'xen-disk,drive=drv0,vdev=xvda', + '-device', 'virtio-net-pci,netdev=unet', + '-netdev', 'user,id=unet,hostfwd=:127.0.0.1:0-:22') + + try: + self.vm.launch() + except machine.VMLaunchFailure as e: + if "Xen HVM guest support not present" in e.output: + self.cancel("KVM Xen support is not present " + "(need v5.12+ kernel with CONFIG_KVM_XEN)") + elif "Property 'kvm-accel.xen-version' not found" in e.output: + self.cancel("QEMU not built with CONFIG_XEN_EMU support") + else: + raise e + + self.log.info('VM launched, waiting for sshd') + console_pattern = 'Starting dropbear sshd: OK' + wait_for_console_pattern(self, console_pattern, 'Oops') + self.log.info('sshd ready') + self.ssh_connect('root', '', False) + + self.ssh_command('cat /proc/cmdline') + self.ssh_command('dmesg | grep -e "Grant table initialized"') + + def test_kvm_xen_guest(self): + """ + :avocado: tags=kvm_xen_guest + """ + + self.common_vm_setup() + + self.kernel_params = (self.KERNEL_DEFAULT + + ' xen_emul_unplug=ide-disks') + self.run_and_check() + self.ssh_command('grep xen-pirq.*msi /proc/interrupts') + + def test_kvm_xen_guest_nomsi(self): + """ + :avocado: tags=kvm_xen_guest_nomsi + """ + + self.common_vm_setup() + + self.kernel_params = (self.KERNEL_DEFAULT + + ' xen_emul_unplug=ide-disks pci=nomsi') + self.run_and_check() + self.ssh_command('grep xen-pirq.* /proc/interrupts') + + def test_kvm_xen_guest_noapic_nomsi(self): + """ + :avocado: tags=kvm_xen_guest_noapic_nomsi + """ + + self.common_vm_setup() + + self.kernel_params = (self.KERNEL_DEFAULT + + ' xen_emul_unplug=ide-disks noapic pci=nomsi') + self.run_and_check() + self.ssh_command('grep xen-pirq /proc/interrupts') + + def test_kvm_xen_guest_vapic(self): + """ + :avocado: tags=kvm_xen_guest_vapic + """ + + self.common_vm_setup() + self.vm.add_args('-cpu', 'host,+xen-vapic') + self.kernel_params = (self.KERNEL_DEFAULT + + ' xen_emul_unplug=ide-disks') + self.run_and_check() + self.ssh_command('grep xen-pirq /proc/interrupts') + self.ssh_command('grep PCI-MSI /proc/interrupts') + + def test_kvm_xen_guest_novector(self): + """ + :avocado: tags=kvm_xen_guest_novector + """ + + self.common_vm_setup() + self.kernel_params = (self.KERNEL_DEFAULT + + ' xen_emul_unplug=ide-disks' + + ' xen_no_vector_callback') + self.run_and_check() + self.ssh_command('grep xen-platform-pci /proc/interrupts') + + def test_kvm_xen_guest_novector_nomsi(self): + """ + :avocado: tags=kvm_xen_guest_novector_nomsi + """ + + self.common_vm_setup() + + self.kernel_params = (self.KERNEL_DEFAULT + + ' xen_emul_unplug=ide-disks pci=nomsi' + + ' xen_no_vector_callback') + self.run_and_check() + self.ssh_command('grep xen-platform-pci /proc/interrupts') + + def test_kvm_xen_guest_novector_noapic(self): + """ + :avocado: tags=kvm_xen_guest_novector_noapic + """ + + self.common_vm_setup() + self.kernel_params = (self.KERNEL_DEFAULT + + ' xen_emul_unplug=ide-disks' + + ' xen_no_vector_callback noapic') + self.run_and_check() + self.ssh_command('grep xen-platform-pci /proc/interrupts') diff --git a/tests/avocado/tuxrun_baselines.py b/tests/avocado/tuxrun_baselines.py index c3fb67f5dc..d343376faa 100644 --- a/tests/avocado/tuxrun_baselines.py +++ b/tests/avocado/tuxrun_baselines.py @@ -270,7 +270,6 @@ class TuxRunBaselineTest(QemuSystemTest): """ self.common_tuxrun(drive="driver=ide-hd,bus=ide.0,unit=0") - @skip("QEMU currently broken") # regression against stable QEMU def test_mips64(self): """ :avocado: tags=arch:mips64 diff --git a/tests/docker/dockerfiles/debian-hexagon-cross.docker b/tests/docker/dockerfiles/debian-hexagon-cross.docker index 5308ccb8fe..b99d99f943 100644 --- a/tests/docker/dockerfiles/debian-hexagon-cross.docker +++ b/tests/docker/dockerfiles/debian-hexagon-cross.docker @@ -27,7 +27,7 @@ RUN apt-get update && \ ENV TOOLCHAIN_INSTALL /opt -ENV TOOLCHAIN_RELEASE 15.0.3 +ENV TOOLCHAIN_RELEASE 16.0.0 ENV TOOLCHAIN_BASENAME "clang+llvm-${TOOLCHAIN_RELEASE}-cross-hexagon-unknown-linux-musl" ENV TOOLCHAIN_URL https://codelinaro.jfrog.io/artifactory/codelinaro-toolchain-for-hexagon/v${TOOLCHAIN_RELEASE}/${TOOLCHAIN_BASENAME}.tar.xz diff --git a/tests/qemu-iotests/meson.build b/tests/qemu-iotests/meson.build index a162f683ef..9735071a29 100644 --- a/tests/qemu-iotests/meson.build +++ b/tests/qemu-iotests/meson.build @@ -47,19 +47,20 @@ foreach format, speed: qemu_iotests_formats endif rc = run_command( - [qemu_iotests_check_cmd] + args + ['-n'], + [python, qemu_iotests_check_cmd] + args + ['-n'], check: true, ) foreach item: rc.stdout().strip().split() - args = ['-tap', '-' + format, item, + args = [qemu_iotests_check_cmd, + '-tap', '-' + format, item, '--source-dir', meson.current_source_dir(), '--build-dir', meson.current_build_dir()] # Some individual tests take as long as 45 seconds # Bump the timeout to 3 minutes for some headroom # on slow machines to minimize spurious failures test('io-' + format + '-' + item, - qemu_iotests_check_cmd, + python, args: args, depends: qemu_iotests_binaries, env: qemu_iotests_env, diff --git a/tests/vm/netbsd b/tests/vm/netbsd index aa54338dfa..0b9536ca17 100755 --- a/tests/vm/netbsd +++ b/tests/vm/netbsd @@ -30,7 +30,6 @@ class NetBSDVM(basevm.BaseVM): "git-base", "pkgconf", "xz", - "python37", "ninja-build", # gnu tools @@ -66,7 +65,7 @@ class NetBSDVM(basevm.BaseVM): mkdir src build; cd src; tar -xf /dev/rld1a; cd ../build - ../src/configure --python=python3.7 --disable-opengl {configure_opts}; + ../src/configure --disable-opengl {configure_opts}; gmake --output-sync -j{jobs} {target} {verbose}; """ poweroff = "/sbin/poweroff" |