diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2019-06-03 18:26:21 +0100 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2019-06-03 18:26:21 +0100 |
commit | e2a58ff493a2e00db3e963c1839c5374500110f2 (patch) | |
tree | 1136df9621eb962326714fa330eaad310fb8de12 | |
parent | ad88e4252f09c2956b99c90de39e95bab2e8e7af (diff) | |
parent | c87759ce876a7a0b17c2bf4f0b964bd51f0ee871 (diff) |
Merge remote-tracking branch 'remotes/bonzini/tags/for-upstream' into staging
* Revert q35 to kernel irqchip (Alex)
* edu device fixes (Li Qiang)
* cleanups (Marc-André, Peter)
* Improvements to -accel help
* Better support for IA32_MISC_ENABLE MSR (Wanpeng)
* I2C test conversion to qgraph (Paolo)
# gpg: Signature made Mon 03 Jun 2019 14:20:12 BST
# gpg: using RSA key BFFBD25F78C7AE83
# gpg: Good signature from "Paolo Bonzini <bonzini@gnu.org>" [full]
# gpg: aka "Paolo Bonzini <pbonzini@redhat.com>" [full]
# Primary key fingerprint: 46F5 9FBD 57D6 12E7 BFD4 E2F7 7E15 100C CD36 69B1
# Subkey fingerprint: F133 3857 4B66 2389 866C 7682 BFFB D25F 78C7 AE83
* remotes/bonzini/tags/for-upstream: (24 commits)
q35: Revert to kernel irqchip
configure: remove tpm_passthrough & tpm_emulator
ci: store Patchew configuration in the tree
libqos: i2c: move address into QI2CDevice
tests: convert ds1338-test to qtest
tests: convert OMAP i2c tests to qgraph
libqos: add ARM imx25-pdk machine object
libqos: add ARM n800 machine object
libqos: convert I2C to qgraph
libqos: split I2CAdapter initialization and allocation
imx25-pdk: create ds1338 for qtest inside the test
pca9552-test: do not rely on state across tests
libqos: fix omap-i2c receiving more than 4 bytes
libqos: move common i2c code to libqos
qgraph: fix qos_node_contains with options
qgraph: allow extra_device_opts on contains nodes
edu: uses uint64_t in dma operation
edu: mmio: allow 64-bit access in read dispatch
edu: mmio: allow 64-bit access
i386: Enable IA32_MISC_ENABLE MWAIT bit when exposing mwait/monitor
...
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
-rw-r--r-- | .patchew.yml | 302 | ||||
-rwxr-xr-x | configure | 10 | ||||
-rw-r--r-- | hw/arm/imx25_pdk.c | 9 | ||||
-rw-r--r-- | hw/core/machine.c | 3 | ||||
-rw-r--r-- | hw/i386/pc.c | 3 | ||||
-rw-r--r-- | hw/i386/pc_q35.c | 16 | ||||
-rw-r--r-- | hw/misc/edu.c | 32 | ||||
-rw-r--r-- | include/exec/memory.h | 17 | ||||
-rw-r--r-- | include/hw/boards.h | 3 | ||||
-rw-r--r-- | include/hw/i386/pc.h | 3 | ||||
-rw-r--r-- | memory.c | 8 | ||||
-rwxr-xr-x | scripts/checkpatch.pl | 3 | ||||
-rw-r--r-- | target/i386/cpu.c | 3 | ||||
-rw-r--r-- | target/i386/cpu.h | 1 | ||||
-rw-r--r-- | tests/Makefile.include | 18 | ||||
-rw-r--r-- | tests/ds1338-test.c | 45 | ||||
-rw-r--r-- | tests/libqos/arm-imx25-pdk-machine.c | 92 | ||||
-rw-r--r-- | tests/libqos/arm-n800-machine.c | 92 | ||||
-rw-r--r-- | tests/libqos/i2c-imx.c | 40 | ||||
-rw-r--r-- | tests/libqos/i2c-omap.c | 70 | ||||
-rw-r--r-- | tests/libqos/i2c.c | 74 | ||||
-rw-r--r-- | tests/libqos/i2c.h | 63 | ||||
-rw-r--r-- | tests/libqos/qgraph.c | 12 | ||||
-rw-r--r-- | tests/libqos/qgraph.h | 15 | ||||
-rw-r--r-- | tests/pca9552-test.c | 91 | ||||
-rw-r--r-- | tests/qos-test.c | 17 | ||||
-rw-r--r-- | tests/test-thread-pool.c | 32 | ||||
-rw-r--r-- | tests/tmp105-test.c | 112 | ||||
-rw-r--r-- | vl.c | 18 |
29 files changed, 889 insertions, 315 deletions
diff --git a/.patchew.yml b/.patchew.yml new file mode 100644 index 0000000000..988c29261f --- /dev/null +++ b/.patchew.yml @@ -0,0 +1,302 @@ +--- +# Note: this file is still unused. It serves as a documentation for the +# Patchew configuration in case patchew.org disappears or has to be +# reinstalled. +# +# Patchew configuration is available to project administrators at +# https://patchew.org/api/v1/projects/1/config/ and can be configured +# to YAML using the following Python script: +# +# import json +# import sys +# import ruamel.yaml +# +# json_str = sys.stdin.read() +# yaml = ruamel.yaml.YAML() +# yaml.explicit_start = True +# data = json.loads(json_str, object_pairs_hook=ruamel.yaml.comments.CommentedMap) +# ruamel.yaml.scalarstring.walk_tree(data) +# yaml.dump(data, sys.stdout) + +email: + notifications: + timeouts: + event: TestingReport + enabled: true + to_user: false + reply_subject: true + set_reply_to: true + in_reply_to: true + reply_to_all: false + subject_template: none + to: fam@euphon.net + cc: '' + body_template: | + {% if not is_timeout %} {{ cancel }} {% endif %} + + Test '{{ test }}' timeout, log: + + {{ log }} + ENOSPC: + event: TestingReport + enabled: true + to_user: false + reply_subject: false + set_reply_to: false + in_reply_to: true + reply_to_all: false + subject_template: Out of space error + to: fam@euphon.net + cc: '' + body_template: | + {% if passed %} + {{ cancel }} + {% endif %} + + {% if 'No space left on device' in log %} + Tester {{ tester }} out of space when running {{ test }} + + {{ log }} + {% else %} + {{ cancel }} + {% endif %} + FailureShort: + event: TestingReport + enabled: true + to_user: false + reply_subject: true + set_reply_to: true + in_reply_to: true + reply_to_all: true + subject_template: Testing failed + to: '' + cc: '' + body_template: | + {% if passed or not obj.message_id or is_timeout %} + {{ cancel }} + {% endif %} + {% if 'No space left on device' in log %} + {{ cancel }} + {% endif %} + Patchew URL: https://patchew.org/QEMU/{{ obj.message_id }}/ + + {% ansi2text log as logtext %} + {% if test == "checkpatch" %} + Hi, + + This series seems to have some coding style problems. See output below for + more information: + + {{ logtext }} + {% elif test == "docker-mingw@fedora" or test == "docker-quick@centos7" or test == "asan" %} + Hi, + + This series failed the {{ test }} build test. Please find the testing commands and + their output below. If you have Docker installed, you can probably reproduce it + locally. + + {% lines_between logtext start="^=== TEST SCRIPT BEGIN ===$" stop="^=== TEST SCRIPT END ===$" %} + {% lines_between logtext start="^=== OUTPUT BEGIN ===$" stop="=== OUTPUT END ===$" as output %} + {% grep_C output regex="\b(FAIL|XPASS|ERROR|WARN|error:|warning:)" n=3 %} + {% elif test == "s390x" or test == "FreeBSD" or test == "ppcle" or test == "ppcbe" %} + Hi, + + This series failed build test on {{test}} host. Please find the details below. + + {% lines_between logtext start="^=== TEST SCRIPT BEGIN ===$" stop="^=== TEST SCRIPT END ===$" %} + {% lines_between logtext start="^=== OUTPUT BEGIN ===$" stop="=== OUTPUT END ===$" as output %} + {% grep_C output regex="\b(FAIL|XPASS|ERROR|WARN|error:|warning:)" n=3 %} + {% else %} + {{ cancel }} + {% endif %} + + The full log is available at + {{ log_url }}. + --- + Email generated automatically by Patchew [https://patchew.org/]. + Please send your feedback to patchew-devel@redhat.com +testing: + tests: + asan: + enabled: true + requirements: docker + timeout: 3600 + script: | + #!/bin/bash + time make docker-test-debug@fedora TARGET_LIST=x86_64-softmmu J=14 NETWORK=1 + docker-quick@centos7: + enabled: false + requirements: docker,x86_64 + timeout: 3600 + script: | + #!/bin/bash + time make docker-test-quick@centos7 SHOW_ENV=1 J=14 NETWORK=1 + checkpatch: + enabled: true + requirements: '' + timeout: 600 + script: | + #!/bin/bash + git rev-parse base > /dev/null || exit 0 + git config --local diff.renamelimit 0 + git config --local diff.renames True + git config --local diff.algorithm histogram + ./scripts/checkpatch.pl --mailback base.. + docker-mingw@fedora: + enabled: true + requirements: docker,x86_64 + timeout: 3600 + script: | + #! /bin/bash + test "$(uname -m)" = "x86_64" + ppcle: + enabled: false + requirements: ppcle + timeout: 3600 + script: | + #!/bin/bash + # Testing script will be invoked under the git checkout with + # HEAD pointing to a commit that has the patches applied on top of "base" + # branch + set -e + CC=$HOME/bin/cc + INSTALL=$PWD/install + BUILD=$PWD/build + mkdir -p $BUILD $INSTALL + SRC=$PWD + cd $BUILD + $SRC/configure --cc=$CC --prefix=$INSTALL + make -j4 + # XXX: we need reliable clean up + # make check -j4 V=1 + make install + + echo + echo "=== ENV ===" + env + + echo + echo "=== PACKAGES ===" + rpm -qa + ppcbe: + enabled: false + requirements: ppcbe + timeout: 3600 + script: | + #!/bin/bash + # Testing script will be invoked under the git checkout with + # HEAD pointing to a commit that has the patches applied on top of "base" + # branch + set -e + CC=$HOME/bin/cc + INSTALL=$PWD/install + BUILD=$PWD/build + mkdir -p $BUILD $INSTALL + SRC=$PWD + cd $BUILD + $SRC/configure --cc=$CC --prefix=$INSTALL + make -j4 + # XXX: we need reliable clean up + # make check -j4 V=1 + make install + + echo + echo "=== ENV ===" + env + + echo + echo "=== PACKAGES ===" + rpm -qa + FreeBSD: + enabled: true + requirements: qemu-x86,x86_64,git + timeout: 3600 + script: | + #!/bin/bash + # Testing script will be invoked under the git checkout with + # HEAD pointing to a commit that has the patches applied on top of "base" + # branch + if qemu-system-x86_64 --help >/dev/null 2>&1; then + QEMU=qemu-system-x86_64 + elif /usr/libexec/qemu-kvm --help >/dev/null 2>&1; then + QEMU=/usr/libexec/qemu-kvm + else + exit 1 + fi + make vm-build-freebsd J=21 QEMU=$QEMU + exit 0 + docker-clang@ubuntu: + enabled: true + requirements: docker,x86_64 + timeout: 3600 + script: | + #!/bin/bash + time make docker-test-clang@ubuntu SHOW_ENV=1 J=14 NETWORK=1 + s390x: + enabled: true + requirements: s390x + timeout: 3600 + script: | + #!/bin/bash + # Testing script will be invoked under the git checkout with + # HEAD pointing to a commit that has the patches applied on top of "base" + # branch + set -e + CC=$HOME/bin/cc + INSTALL=$PWD/install + BUILD=$PWD/build + mkdir -p $BUILD $INSTALL + SRC=$PWD + cd $BUILD + $SRC/configure --cc=$CC --prefix=$INSTALL + make -j4 + # XXX: we need reliable clean up + # make check -j4 V=1 + make install + + echo + echo "=== ENV ===" + env + + echo + echo "=== PACKAGES ===" + rpm -qa + requirements: + x86_64: + script: | + #! /bin/bash + test "$(uname -m)" = "x86_64" + qemu-x86: + script: | + #!/bin/bash + if qemu-system-x86_64 --help >/dev/null 2>&1; then + : + elif /usr/libexec/qemu-kvm --help >/dev/null 2>&1; then + : + else + exit 1 + fi + ppcle: + script: | + #!/bin/bash + test "$(uname -m)" = "ppc64le" + ppcbe: + script: | + #!/bin/bash + test "$(uname -m)" = "ppc64" + git: + script: | + #! /bin/bash + git config user.name > /dev/null 2>&1 + docker: + script: | + #!/bin/bash + docker ps || sudo -n docker ps + s390x: + script: | + #!/bin/bash + test "$(uname -m)" = "s390x" +git: + push_to: git@github.com:patchew-project/qemu + public_repo: https://github.com/patchew-project/qemu + url_template: https://github.com/patchew-project/qemu/tree/%t @@ -6452,8 +6452,6 @@ echo "gcov $gcov_tool" echo "gcov enabled $gcov" echo "TPM support $tpm" echo "libssh2 support $libssh2" -echo "TPM passthrough $tpm_passthrough" -echo "TPM emulator $tpm_emulator" echo "QOM debugging $qom_cast_debug" echo "Live block migration $live_block_migration" echo "lzo support $lzo" @@ -7158,14 +7156,6 @@ fi if test "$tpm" = "yes"; then echo 'CONFIG_TPM=$(CONFIG_SOFTMMU)' >> $config_host_mak - # TPM passthrough support? - if test "$tpm_passthrough" = "yes"; then - echo "CONFIG_TPM_PASSTHROUGH=y" >> $config_host_mak - fi - # TPM emulator support? - if test "$tpm_emulator" = "yes"; then - echo "CONFIG_TPM_EMULATOR=y" >> $config_host_mak - fi fi echo "TRACE_BACKENDS=$trace_backends" >> $config_host_mak diff --git a/hw/arm/imx25_pdk.c b/hw/arm/imx25_pdk.c index eef1b184b0..a0423ffb67 100644 --- a/hw/arm/imx25_pdk.c +++ b/hw/arm/imx25_pdk.c @@ -131,15 +131,6 @@ static void imx25_pdk_init(MachineState *machine) */ if (!qtest_enabled()) { arm_load_kernel(&s->soc.cpu, &imx25_pdk_binfo); - } else { - /* - * This I2C device doesn't exist on the real board. - * We add it here (only on qtest usage) to be able to do a bit - * of simple qtest. See "make check" for details. - */ - i2c_create_slave((I2CBus *)qdev_get_child_bus(DEVICE(&s->soc.i2c[0]), - "i2c-bus.0"), - "ds1338", 0x68); } } diff --git a/hw/core/machine.c b/hw/core/machine.c index 16ba667434..f1a0f45f9c 100644 --- a/hw/core/machine.c +++ b/hw/core/machine.c @@ -24,6 +24,9 @@ #include "hw/pci/pci.h" #include "hw/mem/nvdimm.h" +GlobalProperty hw_compat_4_0_1[] = {}; +const size_t hw_compat_4_0_1_len = G_N_ELEMENTS(hw_compat_4_0_1); + GlobalProperty hw_compat_4_0[] = {}; const size_t hw_compat_4_0_len = G_N_ELEMENTS(hw_compat_4_0); diff --git a/hw/i386/pc.c b/hw/i386/pc.c index 2632b73f80..edc240bcbf 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -110,6 +110,9 @@ struct hpet_fw_config hpet_cfg = {.count = UINT8_MAX}; /* Physical Address of PVH entry point read from kernel ELF NOTE */ static size_t pvh_start_addr; +GlobalProperty pc_compat_4_0_1[] = {}; +const size_t pc_compat_4_0_1_len = G_N_ELEMENTS(pc_compat_4_0_1); + GlobalProperty pc_compat_4_0[] = {}; const size_t pc_compat_4_0_len = G_N_ELEMENTS(pc_compat_4_0); diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c index 37dd350511..dcddc64662 100644 --- a/hw/i386/pc_q35.c +++ b/hw/i386/pc_q35.c @@ -357,7 +357,7 @@ static void pc_q35_machine_options(MachineClass *m) m->units_per_default_bus = 1; m->default_machine_opts = "firmware=bios-256k.bin"; m->default_display = "std"; - m->default_kernel_irqchip_split = true; + m->default_kernel_irqchip_split = false; m->no_floppy = 1; machine_class_allow_dynamic_sysbus_dev(m, TYPE_AMD_IOMMU_DEVICE); machine_class_allow_dynamic_sysbus_dev(m, TYPE_INTEL_IOMMU_DEVICE); @@ -374,10 +374,22 @@ static void pc_q35_4_1_machine_options(MachineClass *m) DEFINE_Q35_MACHINE(v4_1, "pc-q35-4.1", NULL, pc_q35_4_1_machine_options); -static void pc_q35_4_0_machine_options(MachineClass *m) +static void pc_q35_4_0_1_machine_options(MachineClass *m) { pc_q35_4_1_machine_options(m); m->alias = NULL; + compat_props_add(m->compat_props, hw_compat_4_0_1, hw_compat_4_0_1_len); + compat_props_add(m->compat_props, pc_compat_4_0_1, pc_compat_4_0_1_len); +} + +DEFINE_Q35_MACHINE(v4_0_1, "pc-q35-4.0.1", NULL, + pc_q35_4_0_1_machine_options); + +static void pc_q35_4_0_machine_options(MachineClass *m) +{ + pc_q35_4_0_1_machine_options(m); + m->default_kernel_irqchip_split = true; + m->alias = NULL; compat_props_add(m->compat_props, hw_compat_4_0, hw_compat_4_0_len); compat_props_add(m->compat_props, pc_compat_4_0, pc_compat_4_0_len); } diff --git a/hw/misc/edu.c b/hw/misc/edu.c index 91af452c9e..19e5545e2c 100644 --- a/hw/misc/edu.c +++ b/hw/misc/edu.c @@ -98,23 +98,24 @@ static void edu_lower_irq(EduState *edu, uint32_t val) } } -static bool within(uint32_t addr, uint32_t start, uint32_t end) +static bool within(uint64_t addr, uint64_t start, uint64_t end) { return start <= addr && addr < end; } -static void edu_check_range(uint32_t addr, uint32_t size1, uint32_t start, - uint32_t size2) +static void edu_check_range(uint64_t addr, uint64_t size1, uint64_t start, + uint64_t size2) { - uint32_t end1 = addr + size1; - uint32_t end2 = start + size2; + uint64_t end1 = addr + size1; + uint64_t end2 = start + size2; if (within(addr, start, end2) && end1 > addr && within(end1, start, end2)) { return; } - hw_error("EDU: DMA range 0x%.8x-0x%.8x out of bounds (0x%.8x-0x%.8x)!", + hw_error("EDU: DMA range 0x%016"PRIx64"-0x%016"PRIx64 + " out of bounds (0x%016"PRIx64"-0x%016"PRIx64")!", addr, end1 - 1, start, end2 - 1); } @@ -139,13 +140,13 @@ static void edu_dma_timer(void *opaque) } if (EDU_DMA_DIR(edu->dma.cmd) == EDU_DMA_FROM_PCI) { - uint32_t dst = edu->dma.dst; + uint64_t dst = edu->dma.dst; edu_check_range(dst, edu->dma.cnt, DMA_START, DMA_SIZE); dst -= DMA_START; pci_dma_read(&edu->pdev, edu_clamp_addr(edu, edu->dma.src), edu->dma_buf + dst, edu->dma.cnt); } else { - uint32_t src = edu->dma.src; + uint64_t src = edu->dma.src; edu_check_range(src, edu->dma.cnt, DMA_START, DMA_SIZE); src -= DMA_START; pci_dma_write(&edu->pdev, edu_clamp_addr(edu, edu->dma.dst), @@ -185,7 +186,11 @@ static uint64_t edu_mmio_read(void *opaque, hwaddr addr, unsigned size) EduState *edu = opaque; uint64_t val = ~0ULL; - if (size != 4) { + if (addr < 0x80 && size != 4) { + return val; + } + + if (addr >= 0x80 && size != 4 && size != 8) { return val; } @@ -289,6 +294,15 @@ static const MemoryRegionOps edu_mmio_ops = { .read = edu_mmio_read, .write = edu_mmio_write, .endianness = DEVICE_NATIVE_ENDIAN, + .valid = { + .min_access_size = 4, + .max_access_size = 8, + }, + .impl = { + .min_access_size = 4, + .max_access_size = 8, + }, + }; /* diff --git a/include/exec/memory.h b/include/exec/memory.h index 9144a47f57..e6140e8a04 100644 --- a/include/exec/memory.h +++ b/include/exec/memory.h @@ -1255,23 +1255,6 @@ void memory_region_ram_resize(MemoryRegion *mr, ram_addr_t newsize, void memory_region_set_log(MemoryRegion *mr, bool log, unsigned client); /** - * memory_region_get_dirty: Check whether a range of bytes is dirty - * for a specified client. - * - * Checks whether a range of bytes has been written to since the last - * call to memory_region_reset_dirty() with the same @client. Dirty logging - * must be enabled. - * - * @mr: the memory region being queried. - * @addr: the address (relative to the start of the region) being queried. - * @size: the size of the range being queried. - * @client: the user of the logging information; %DIRTY_MEMORY_MIGRATION or - * %DIRTY_MEMORY_VGA. - */ -bool memory_region_get_dirty(MemoryRegion *mr, hwaddr addr, - hwaddr size, unsigned client); - -/** * memory_region_set_dirty: Mark a range of bytes as dirty in a memory region. * * Marks a range of bytes as dirty, after it has been dirtied outside diff --git a/include/hw/boards.h b/include/hw/boards.h index 6f7916f88f..6ff02bf3e4 100644 --- a/include/hw/boards.h +++ b/include/hw/boards.h @@ -292,6 +292,9 @@ struct MachineState { } \ type_init(machine_initfn##_register_types) +extern GlobalProperty hw_compat_4_0_1[]; +extern const size_t hw_compat_4_0_1_len; + extern GlobalProperty hw_compat_4_0[]; extern const size_t hw_compat_4_0_len; diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h index 43df7230a2..5d5636241e 100644 --- a/include/hw/i386/pc.h +++ b/include/hw/i386/pc.h @@ -293,6 +293,9 @@ int e820_add_entry(uint64_t, uint64_t, uint32_t); int e820_get_num_entries(void); bool e820_get_entry(int, uint32_t, uint64_t *, uint64_t *); +extern GlobalProperty pc_compat_4_0_1[]; +extern const size_t pc_compat_4_0_1_len; + extern GlobalProperty pc_compat_4_0[]; extern const size_t pc_compat_4_0_len; @@ -2027,14 +2027,6 @@ void memory_region_set_log(MemoryRegion *mr, bool log, unsigned client) memory_region_transaction_commit(); } -bool memory_region_get_dirty(MemoryRegion *mr, hwaddr addr, - hwaddr size, unsigned client) -{ - assert(mr->ram_block); - return cpu_physical_memory_get_dirty(memory_region_get_ram_addr(mr) + addr, - size, client); -} - void memory_region_set_dirty(MemoryRegion *mr, hwaddr addr, hwaddr size) { diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index 88682cb0a9..c2aaf421da 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -1949,7 +1949,8 @@ sub process { } # no C99 // comments - if ($line =~ m{//}) { + if ($line =~ m{//} && + $rawline !~ m{// SPDX-License-Identifier: }) { ERROR("do not use C99 // comments\n" . $herecurr); } # Remove C99 comments. diff --git a/target/i386/cpu.c b/target/i386/cpu.c index 536d7d1520..c1ab86d63e 100644 --- a/target/i386/cpu.c +++ b/target/i386/cpu.c @@ -4730,6 +4730,9 @@ static void x86_cpu_reset(CPUState *s) env->pat = 0x0007040600070406ULL; env->msr_ia32_misc_enable = MSR_IA32_MISC_ENABLE_DEFAULT; + if (env->features[FEAT_1_ECX] & CPUID_EXT_MONITOR) { + env->msr_ia32_misc_enable |= MSR_IA32_MISC_ENABLE_MWAIT; + } memset(env->dr, 0, sizeof(env->dr)); env->dr[6] = DR6_FIXED_1; diff --git a/target/i386/cpu.h b/target/i386/cpu.h index fce6660bac..bd06523a53 100644 --- a/target/i386/cpu.h +++ b/target/i386/cpu.h @@ -387,6 +387,7 @@ typedef enum X86Seg { #define MSR_IA32_MISC_ENABLE 0x1a0 /* Indicates good rep/movs microcode on some processors: */ #define MSR_IA32_MISC_ENABLE_DEFAULT 1 +#define MSR_IA32_MISC_ENABLE_MWAIT (1ULL << 18) #define MSR_MTRRphysBase(reg) (0x200 + 2 * (reg)) #define MSR_MTRRphysMask(reg) (0x200 + 2 * (reg) + 1) diff --git a/tests/Makefile.include b/tests/Makefile.include index 1865f6b322..46a36c2c95 100644 --- a/tests/Makefile.include +++ b/tests/Makefile.include @@ -255,9 +255,6 @@ check-qtest-sparc64-$(CONFIG_ISA_TESTDEV) = tests/endianness-test$(EXESUF) check-qtest-sparc64-y += tests/prom-env-test$(EXESUF) check-qtest-sparc64-y += tests/boot-serial-test$(EXESUF) -check-qtest-arm-y += tests/tmp105-test$(EXESUF) -check-qtest-arm-y += tests/pca9552-test$(EXESUF) -check-qtest-arm-y += tests/ds1338-test$(EXESUF) check-qtest-arm-y += tests/microbit-test$(EXESUF) check-qtest-arm-y += tests/m25p80-test$(EXESUF) check-qtest-arm-y += tests/test-arm-mptimer$(EXESUF) @@ -678,7 +675,7 @@ libqgraph-obj-y = tests/libqos/qgraph.o libqos-obj-y = $(libqgraph-obj-y) tests/libqos/pci.o tests/libqos/fw_cfg.o libqos-obj-y += tests/libqos/malloc.o -libqos-obj-y += tests/libqos/i2c.o tests/libqos/libqos.o +libqos-obj-y += tests/libqos/libqos.o libqos-spapr-obj-y = $(libqos-obj-y) tests/libqos/malloc-spapr.o libqos-spapr-obj-y += tests/libqos/libqos-spapr.o libqos-spapr-obj-y += tests/libqos/rtas.o @@ -686,14 +683,15 @@ libqos-spapr-obj-y += tests/libqos/pci-spapr.o libqos-pc-obj-y = $(libqos-obj-y) tests/libqos/pci-pc.o libqos-pc-obj-y += tests/libqos/malloc-pc.o tests/libqos/libqos-pc.o libqos-pc-obj-y += tests/libqos/ahci.o -libqos-omap-obj-y = $(libqos-obj-y) tests/libqos/i2c-omap.o -libqos-imx-obj-y = $(libqos-obj-y) tests/libqos/i2c-imx.o libqos-usb-obj-y = $(libqos-spapr-obj-y) $(libqos-pc-obj-y) tests/libqos/usb.o # Devices qos-test-obj-y = tests/qos-test.o $(libqgraph-obj-y) qos-test-obj-y += $(libqos-pc-obj-y) $(libqos-spapr-obj-y) qos-test-obj-y += tests/libqos/e1000e.o +qos-test-obj-y += tests/libqos/i2c.o +qos-test-obj-y += tests/libqos/i2c-imx.o +qos-test-obj-y += tests/libqos/i2c-omap.o qos-test-obj-y += tests/libqos/sdhci.o qos-test-obj-y += tests/libqos/tpci200.o qos-test-obj-y += tests/libqos/virtio.o @@ -709,6 +707,8 @@ qos-test-obj-y += tests/libqos/virtio-serial.o # Machines qos-test-obj-y += tests/libqos/aarch64-xlnx-zcu102-machine.o +qos-test-obj-y += tests/libqos/arm-imx25-pdk-machine.o +qos-test-obj-y += tests/libqos/arm-n800-machine.o qos-test-obj-y += tests/libqos/arm-raspi2-machine.o qos-test-obj-y += tests/libqos/arm-sabrelite-machine.o qos-test-obj-y += tests/libqos/arm-smdkc210-machine.o @@ -719,6 +719,7 @@ qos-test-obj-y += tests/libqos/x86_64_pc-machine.o # Tests qos-test-obj-y += tests/ac97-test.o +qos-test-obj-y += tests/ds1338-test.o qos-test-obj-y += tests/e1000-test.o qos-test-obj-y += tests/e1000e-test.o qos-test-obj-y += tests/eepro100-test.o @@ -727,10 +728,12 @@ qos-test-obj-y += tests/ipoctal232-test.o qos-test-obj-y += tests/megasas-test.o qos-test-obj-y += tests/ne2000-test.o qos-test-obj-y += tests/nvme-test.o +qos-test-obj-y += tests/pca9552-test.o qos-test-obj-y += tests/pci-test.o qos-test-obj-y += tests/pcnet-test.o qos-test-obj-y += tests/sdhci-test.o qos-test-obj-y += tests/spapr-phb-test.o +qos-test-obj-y += tests/tmp105-test.o qos-test-obj-y += tests/usb-hcd-ohci-test.o $(libqos-usb-obj-y) qos-test-obj-$(CONFIG_VHOST_NET_USER) += tests/vhost-user-test.o $(chardev-obj-y) $(test-io-obj-y) qos-test-obj-y += tests/virtio-test.o @@ -768,9 +771,6 @@ tests/boot-serial-test$(EXESUF): tests/boot-serial-test.o $(libqos-obj-y) tests/bios-tables-test$(EXESUF): tests/bios-tables-test.o \ tests/boot-sector.o tests/acpi-utils.o $(libqos-obj-y) tests/pxe-test$(EXESUF): tests/pxe-test.o tests/boot-sector.o $(libqos-obj-y) -tests/tmp105-test$(EXESUF): tests/tmp105-test.o $(libqos-omap-obj-y) -tests/pca9552-test$(EXESUF): tests/pca9552-test.o $(libqos-omap-obj-y) -tests/ds1338-test$(EXESUF): tests/ds1338-test.o $(libqos-imx-obj-y) tests/microbit-test$(EXESUF): tests/microbit-test.o tests/m25p80-test$(EXESUF): tests/m25p80-test.o tests/i440fx-test$(EXESUF): tests/i440fx-test.o $(libqos-pc-obj-y) diff --git a/tests/ds1338-test.c b/tests/ds1338-test.c index 742dad9113..f6ade9a050 100644 --- a/tests/ds1338-test.c +++ b/tests/ds1338-test.c @@ -21,31 +21,22 @@ #include "libqtest.h" #include "libqos/i2c.h" -#define IMX25_I2C_0_BASE 0x43F80000 - #define DS1338_ADDR 0x68 -static I2CAdapter *i2c; -static uint8_t addr; - static inline uint8_t bcd2bin(uint8_t x) { return ((x) & 0x0f) + ((x) >> 4) * 10; } -static void send_and_receive(void) +static void send_and_receive(void *obj, void *data, QGuestAllocator *alloc) { - uint8_t cmd[1]; + QI2CDevice *i2cdev = (QI2CDevice *)obj; + uint8_t resp[7]; time_t now = time(NULL); struct tm *tm_ptr = gmtime(&now); - /* reset the index in the RTC memory */ - cmd[0] = 0; - i2c_send(i2c, addr, cmd, 1); - - /* retrieve the date */ - i2c_recv(i2c, addr, resp, 7); + i2c_read_block(i2cdev, 0, resp, sizeof(resp)); /* check retrieved time againt local time */ g_assert_cmpuint(bcd2bin(resp[4]), == , tm_ptr->tm_mday); @@ -53,23 +44,15 @@ static void send_and_receive(void) g_assert_cmpuint(2000 + bcd2bin(resp[6]), == , 1900 + tm_ptr->tm_year); } -int main(int argc, char **argv) +static void ds1338_register_nodes(void) { - QTestState *s = NULL; - int ret; - - g_test_init(&argc, &argv, NULL); - - s = qtest_start("-display none -machine imx25-pdk"); - i2c = imx_i2c_create(s, IMX25_I2C_0_BASE); - addr = DS1338_ADDR; - - qtest_add_func("/ds1338/tx-rx", send_and_receive); - - ret = g_test_run(); - - qtest_quit(s); - g_free(i2c); - - return ret; + QOSGraphEdgeOptions opts = { + .extra_device_opts = "address=0x68" + }; + add_qi2c_address(&opts, &(QI2CAddress) { DS1338_ADDR }); + + qos_node_create_driver("ds1338", i2c_device_create); + qos_node_consumes("ds1338", "i2c-bus", &opts); + qos_add_test("tx-rx", "ds1338", send_and_receive, NULL); } +libqos_init(ds1338_register_nodes); diff --git a/tests/libqos/arm-imx25-pdk-machine.c b/tests/libqos/arm-imx25-pdk-machine.c new file mode 100644 index 0000000000..25066fb8a9 --- /dev/null +++ b/tests/libqos/arm-imx25-pdk-machine.c @@ -0,0 +1,92 @@ +/* + * libqos driver framework + * + * Copyright (c) 2019 Red Hat, Inc. + * + * Author: Paolo Bonzini <pbonzini@redhat.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/> + */ + +#include "qemu/osdep.h" +#include "libqtest.h" +#include "libqos/malloc.h" +#include "libqos/qgraph.h" +#include "libqos/i2c.h" + +#define ARM_PAGE_SIZE 4096 +#define IMX25_PDK_RAM_START 0x80000000 +#define IMX25_PDK_RAM_END 0x88000000 + +typedef struct QIMX25PDKMachine QIMX25PDKMachine; + +struct QIMX25PDKMachine { + QOSGraphObject obj; + QGuestAllocator alloc; + IMXI2C i2c_1; +}; + +static void *imx25_pdk_get_driver(void *object, const char *interface) +{ + QIMX25PDKMachine *machine = object; + if (!g_strcmp0(interface, "memory")) { + return &machine->alloc; + } + + fprintf(stderr, "%s not present in arm/imx25_pdk\n", interface); + g_assert_not_reached(); +} + +static QOSGraphObject *imx25_pdk_get_device(void *obj, const char *device) +{ + QIMX25PDKMachine *machine = obj; + if (!g_strcmp0(device, "imx.i2c")) { + return &machine->i2c_1.obj; + } + + fprintf(stderr, "%s not present in arm/imx25_pdk\n", device); + g_assert_not_reached(); +} + +static void imx25_pdk_destructor(QOSGraphObject *obj) +{ + QIMX25PDKMachine *machine = (QIMX25PDKMachine *) obj; + alloc_destroy(&machine->alloc); +} + +static void *qos_create_machine_arm_imx25_pdk(QTestState *qts) +{ + QIMX25PDKMachine *machine = g_new0(QIMX25PDKMachine, 1); + + alloc_init(&machine->alloc, 0, + IMX25_PDK_RAM_START, + IMX25_PDK_RAM_END, + ARM_PAGE_SIZE); + machine->obj.get_device = imx25_pdk_get_device; + machine->obj.get_driver = imx25_pdk_get_driver; + machine->obj.destructor = imx25_pdk_destructor; + + imx_i2c_init(&machine->i2c_1, qts, 0x43f80000); + return &machine->obj; +} + +static void imx25_pdk_register_nodes(void) +{ + QOSGraphEdgeOptions edge = { + .extra_device_opts = "bus=i2c-bus.0" + }; + qos_node_create_machine("arm/imx25-pdk", qos_create_machine_arm_imx25_pdk); + qos_node_contains("arm/imx25-pdk", "imx.i2c", &edge, NULL); +} + +libqos_init(imx25_pdk_register_nodes); diff --git a/tests/libqos/arm-n800-machine.c b/tests/libqos/arm-n800-machine.c new file mode 100644 index 0000000000..87279bdb26 --- /dev/null +++ b/tests/libqos/arm-n800-machine.c @@ -0,0 +1,92 @@ +/* + * libqos driver framework + * + * Copyright (c) 2019 Red Hat, Inc. + * + * Author: Paolo Bonzini <pbonzini@redhat.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/> + */ + +#include "qemu/osdep.h" +#include "libqtest.h" +#include "libqos/malloc.h" +#include "libqos/qgraph.h" +#include "libqos/i2c.h" + +#define ARM_PAGE_SIZE 4096 +#define N800_RAM_START 0x80000000 +#define N800_RAM_END 0x88000000 + +typedef struct QN800Machine QN800Machine; + +struct QN800Machine { + QOSGraphObject obj; + QGuestAllocator alloc; + OMAPI2C i2c_1; +}; + +static void *n800_get_driver(void *object, const char *interface) +{ + QN800Machine *machine = object; + if (!g_strcmp0(interface, "memory")) { + return &machine->alloc; + } + + fprintf(stderr, "%s not present in arm/n800\n", interface); + g_assert_not_reached(); +} + +static QOSGraphObject *n800_get_device(void *obj, const char *device) +{ + QN800Machine *machine = obj; + if (!g_strcmp0(device, "omap_i2c")) { + return &machine->i2c_1.obj; + } + + fprintf(stderr, "%s not present in arm/n800\n", device); + g_assert_not_reached(); +} + +static void n800_destructor(QOSGraphObject *obj) +{ + QN800Machine *machine = (QN800Machine *) obj; + alloc_destroy(&machine->alloc); +} + +static void *qos_create_machine_arm_n800(QTestState *qts) +{ + QN800Machine *machine = g_new0(QN800Machine, 1); + + alloc_init(&machine->alloc, 0, + N800_RAM_START, + N800_RAM_END, + ARM_PAGE_SIZE); + machine->obj.get_device = n800_get_device; + machine->obj.get_driver = n800_get_driver; + machine->obj.destructor = n800_destructor; + + omap_i2c_init(&machine->i2c_1, qts, 0x48070000); + return &machine->obj; +} + +static void n800_register_nodes(void) +{ + QOSGraphEdgeOptions edge = { + .extra_device_opts = "bus=i2c-bus.0" + }; + qos_node_create_machine("arm/n800", qos_create_machine_arm_n800); + qos_node_contains("arm/n800", "omap_i2c", &edge, NULL); +} + +libqos_init(n800_register_nodes); diff --git a/tests/libqos/i2c-imx.c b/tests/libqos/i2c-imx.c index 0945f2ecdc..f33ece55a3 100644 --- a/tests/libqos/i2c-imx.c +++ b/tests/libqos/i2c-imx.c @@ -30,13 +30,6 @@ enum IMXI2CDirection { IMX_I2C_WRITE, }; -typedef struct IMXI2C { - I2CAdapter parent; - - uint64_t addr; -} IMXI2C; - - static void imx_i2c_set_slave_addr(IMXI2C *s, uint8_t addr, enum IMXI2CDirection direction) { @@ -47,7 +40,7 @@ static void imx_i2c_set_slave_addr(IMXI2C *s, uint8_t addr, static void imx_i2c_send(I2CAdapter *i2c, uint8_t addr, const uint8_t *buf, uint16_t len) { - IMXI2C *s = (IMXI2C *)i2c; + IMXI2C *s = container_of(i2c, IMXI2C, parent); uint8_t data; uint8_t status; uint16_t size = 0; @@ -107,7 +100,7 @@ static void imx_i2c_send(I2CAdapter *i2c, uint8_t addr, static void imx_i2c_recv(I2CAdapter *i2c, uint8_t addr, uint8_t *buf, uint16_t len) { - IMXI2C *s = (IMXI2C *)i2c; + IMXI2C *s = container_of(i2c, IMXI2C, parent); uint8_t data; uint8_t status; uint16_t size = 0; @@ -193,16 +186,31 @@ static void imx_i2c_recv(I2CAdapter *i2c, uint8_t addr, g_assert((status & I2SR_IBB) == 0); } -I2CAdapter *imx_i2c_create(QTestState *qts, uint64_t addr) +static void *imx_i2c_get_driver(void *obj, const char *interface) { - IMXI2C *s = g_malloc0(sizeof(*s)); - I2CAdapter *i2c = (I2CAdapter *)s; + IMXI2C *s = obj; + if (!g_strcmp0(interface, "i2c-bus")) { + return &s->parent; + } + fprintf(stderr, "%s not present in imx-i2c\n", interface); + g_assert_not_reached(); +} +void imx_i2c_init(IMXI2C *s, QTestState *qts, uint64_t addr) +{ s->addr = addr; - i2c->send = imx_i2c_send; - i2c->recv = imx_i2c_recv; - i2c->qts = qts; + s->obj.get_driver = imx_i2c_get_driver; - return i2c; + s->parent.send = imx_i2c_send; + s->parent.recv = imx_i2c_recv; + s->parent.qts = qts; } + +static void imx_i2c_register_nodes(void) +{ + qos_node_create_driver("imx.i2c", NULL); + qos_node_produces("imx.i2c", "i2c-bus"); +} + +libqos_init(imx_i2c_register_nodes); diff --git a/tests/libqos/i2c-omap.c b/tests/libqos/i2c-omap.c index 1ef6e7b200..9ae8214fa8 100644 --- a/tests/libqos/i2c-omap.c +++ b/tests/libqos/i2c-omap.c @@ -40,12 +40,6 @@ enum OMAPI2CCONBits { OMAP_I2C_CON_I2C_EN = 1 << 15, }; -typedef struct OMAPI2C { - I2CAdapter parent; - - uint64_t addr; -} OMAPI2C; - static void omap_i2c_set_slave_addr(OMAPI2C *s, uint8_t addr) { @@ -59,7 +53,7 @@ static void omap_i2c_set_slave_addr(OMAPI2C *s, uint8_t addr) static void omap_i2c_send(I2CAdapter *i2c, uint8_t addr, const uint8_t *buf, uint16_t len) { - OMAPI2C *s = (OMAPI2C *)i2c; + OMAPI2C *s = container_of(i2c, OMAPI2C, parent); uint16_t data; omap_i2c_set_slave_addr(s, addr); @@ -103,8 +97,9 @@ static void omap_i2c_send(I2CAdapter *i2c, uint8_t addr, static void omap_i2c_recv(I2CAdapter *i2c, uint8_t addr, uint8_t *buf, uint16_t len) { - OMAPI2C *s = (OMAPI2C *)i2c; + OMAPI2C *s = container_of(i2c, OMAPI2C, parent); uint16_t data, stat; + uint16_t orig_len = len; omap_i2c_set_slave_addr(s, addr); @@ -116,16 +111,24 @@ static void omap_i2c_recv(I2CAdapter *i2c, uint8_t addr, OMAP_I2C_CON_STT | OMAP_I2C_CON_STP; qtest_writew(i2c->qts, s->addr + OMAP_I2C_CON, data); - data = qtest_readw(i2c->qts, s->addr + OMAP_I2C_CON); - g_assert((data & OMAP_I2C_CON_STP) == 0); data = qtest_readw(i2c->qts, s->addr + OMAP_I2C_STAT); g_assert((data & OMAP_I2C_STAT_NACK) == 0); - data = qtest_readw(i2c->qts, s->addr + OMAP_I2C_CNT); - g_assert_cmpuint(data, ==, len); - while (len > 0) { + data = qtest_readw(i2c->qts, s->addr + OMAP_I2C_CON); + if (len <= 4) { + g_assert((data & OMAP_I2C_CON_STP) == 0); + + data = qtest_readw(i2c->qts, s->addr + OMAP_I2C_CNT); + g_assert_cmpuint(data, ==, orig_len); + } else { + g_assert((data & OMAP_I2C_CON_STP) != 0); + + data = qtest_readw(i2c->qts, s->addr + OMAP_I2C_CNT); + g_assert_cmpuint(data, ==, len - 4); + } + data = qtest_readw(i2c->qts, s->addr + OMAP_I2C_STAT); g_assert((data & OMAP_I2C_STAT_RRDY) != 0); g_assert((data & OMAP_I2C_STAT_ROVR) == 0); @@ -152,21 +155,42 @@ static void omap_i2c_recv(I2CAdapter *i2c, uint8_t addr, g_assert((data & OMAP_I2C_CON_STP) == 0); } -I2CAdapter *omap_i2c_create(QTestState *qts, uint64_t addr) +static void *omap_i2c_get_driver(void *obj, const char *interface) +{ + OMAPI2C *s = obj; + if (!g_strcmp0(interface, "i2c-bus")) { + return &s->parent; + } + fprintf(stderr, "%s not present in omap_i2c\n", interface); + g_assert_not_reached(); +} + +static void omap_i2c_start_hw(QOSGraphObject *object) { - OMAPI2C *s = g_malloc0(sizeof(*s)); - I2CAdapter *i2c = (I2CAdapter *)s; + OMAPI2C *s = (OMAPI2C *) object; uint16_t data; + /* verify the mmio address by looking for a known signature */ + data = qtest_readw(s->parent.qts, s->addr + OMAP_I2C_REV); + g_assert_cmphex(data, ==, 0x34); +} + +void omap_i2c_init(OMAPI2C *s, QTestState *qts, uint64_t addr) +{ s->addr = addr; - i2c->send = omap_i2c_send; - i2c->recv = omap_i2c_recv; - i2c->qts = qts; + s->obj.get_driver = omap_i2c_get_driver; + s->obj.start_hw = omap_i2c_start_hw; - /* verify the mmio address by looking for a known signature */ - data = qtest_readw(qts, addr + OMAP_I2C_REV); - g_assert_cmphex(data, ==, 0x34); + s->parent.send = omap_i2c_send; + s->parent.recv = omap_i2c_recv; + s->parent.qts = qts; +} - return i2c; +static void omap_i2c_register_nodes(void) +{ + qos_node_create_driver("omap_i2c", NULL); + qos_node_produces("omap_i2c", "i2c-bus"); } + +libqos_init(omap_i2c_register_nodes); diff --git a/tests/libqos/i2c.c b/tests/libqos/i2c.c index 23bc2a3eb2..156114e745 100644 --- a/tests/libqos/i2c.c +++ b/tests/libqos/i2c.c @@ -10,14 +10,76 @@ #include "libqos/i2c.h" #include "libqtest.h" -void i2c_send(I2CAdapter *i2c, uint8_t addr, - const uint8_t *buf, uint16_t len) +void i2c_send(QI2CDevice *i2cdev, const uint8_t *buf, uint16_t len) { - i2c->send(i2c, addr, buf, len); + i2cdev->bus->send(i2cdev->bus, i2cdev->addr, buf, len); } -void i2c_recv(I2CAdapter *i2c, uint8_t addr, - uint8_t *buf, uint16_t len) +void i2c_recv(QI2CDevice *i2cdev, uint8_t *buf, uint16_t len) { - i2c->recv(i2c, addr, buf, len); + i2cdev->bus->recv(i2cdev->bus, i2cdev->addr, buf, len); +} + +void i2c_read_block(QI2CDevice *i2cdev, uint8_t reg, + uint8_t *buf, uint16_t len) +{ + i2c_send(i2cdev, ®, 1); + i2c_recv(i2cdev, buf, len); +} + +void i2c_write_block(QI2CDevice *i2cdev, uint8_t reg, + const uint8_t *buf, uint16_t len) +{ + uint8_t *cmd = g_malloc(len + 1); + cmd[0] = reg; + memcpy(&cmd[1], buf, len); + i2c_send(i2cdev, cmd, len + 1); + g_free(cmd); +} + +uint8_t i2c_get8(QI2CDevice *i2cdev, uint8_t reg) +{ + uint8_t resp[1]; + i2c_read_block(i2cdev, reg, resp, sizeof(resp)); + return resp[0]; +} + +uint16_t i2c_get16(QI2CDevice *i2cdev, uint8_t reg) +{ + uint8_t resp[2]; + i2c_read_block(i2cdev, reg, resp, sizeof(resp)); + return (resp[0] << 8) | resp[1]; +} + +void i2c_set8(QI2CDevice *i2cdev, uint8_t reg, uint8_t value) +{ + i2c_write_block(i2cdev, reg, &value, 1); +} + +void i2c_set16(QI2CDevice *i2cdev, uint8_t reg, uint16_t value) +{ + uint8_t data[2]; + + data[0] = value >> 8; + data[1] = value & 255; + i2c_write_block(i2cdev, reg, data, sizeof(data)); +} + +void *i2c_device_create(void *i2c_bus, QGuestAllocator *alloc, void *addr) +{ + QI2CDevice *i2cdev = g_new0(QI2CDevice, 1); + + i2cdev->bus = i2c_bus; + if (addr) { + i2cdev->addr = ((QI2CAddress *)addr)->addr; + } + return &i2cdev->obj; +} + +void add_qi2c_address(QOSGraphEdgeOptions *opts, QI2CAddress *addr) +{ + g_assert(addr); + + opts->arg = addr; + opts->size_arg = sizeof(QI2CAddress); } diff --git a/tests/libqos/i2c.h b/tests/libqos/i2c.h index cc01358a9f..945b65b34c 100644 --- a/tests/libqos/i2c.h +++ b/tests/libqos/i2c.h @@ -10,6 +10,7 @@ #define LIBQOS_I2C_H #include "libqtest.h" +#include "libqos/qgraph.h" typedef struct I2CAdapter I2CAdapter; struct I2CAdapter { @@ -21,17 +22,61 @@ struct I2CAdapter { QTestState *qts; }; -#define OMAP2_I2C_1_BASE 0x48070000 +typedef struct QI2CAddress QI2CAddress; +struct QI2CAddress { + uint8_t addr; +}; + +typedef struct QI2CDevice QI2CDevice; +struct QI2CDevice { + /* + * For now, all devices are simple enough that there is no need for + * them to define their own constructor and get_driver functions. + * Therefore, QOSGraphObject is included directly in QI2CDevice; + * the tests expect to get a QI2CDevice rather than doing something + * like obj->get_driver("i2c-device"). + * + * In fact there is no i2c-device interface even, because there are + * no generic I2C tests). + */ + QOSGraphObject obj; + I2CAdapter *bus; + uint8_t addr; +}; + +void *i2c_device_create(void *i2c_bus, QGuestAllocator *alloc, void *addr); +void add_qi2c_address(QOSGraphEdgeOptions *opts, QI2CAddress *addr); + +void i2c_send(QI2CDevice *dev, const uint8_t *buf, uint16_t len); +void i2c_recv(QI2CDevice *dev, uint8_t *buf, uint16_t len); + +void i2c_read_block(QI2CDevice *dev, uint8_t reg, + uint8_t *buf, uint16_t len); +void i2c_write_block(QI2CDevice *dev, uint8_t reg, + const uint8_t *buf, uint16_t len); +uint8_t i2c_get8(QI2CDevice *dev, uint8_t reg); +uint16_t i2c_get16(QI2CDevice *dev, uint8_t reg); +void i2c_set8(QI2CDevice *dev, uint8_t reg, uint8_t value); +void i2c_set16(QI2CDevice *dev, uint8_t reg, uint16_t value); + +/* i2c-omap.c */ +typedef struct OMAPI2C { + QOSGraphObject obj; + I2CAdapter parent; + + uint64_t addr; +} OMAPI2C; + +void omap_i2c_init(OMAPI2C *s, QTestState *qts, uint64_t addr); -void i2c_send(I2CAdapter *i2c, uint8_t addr, - const uint8_t *buf, uint16_t len); -void i2c_recv(I2CAdapter *i2c, uint8_t addr, - uint8_t *buf, uint16_t len); +/* i2c-imx.c */ +typedef struct IMXI2C { + QOSGraphObject obj; + I2CAdapter parent; -/* libi2c-omap.c */ -I2CAdapter *omap_i2c_create(QTestState *qts, uint64_t addr); + uint64_t addr; +} IMXI2C; -/* libi2c-imx.c */ -I2CAdapter *imx_i2c_create(QTestState *qts, uint64_t addr); +void imx_i2c_init(IMXI2C *s, QTestState *qts, uint64_t addr); #endif diff --git a/tests/libqos/qgraph.c b/tests/libqos/qgraph.c index b149caaaa9..7a7ae2a19e 100644 --- a/tests/libqos/qgraph.c +++ b/tests/libqos/qgraph.c @@ -632,15 +632,19 @@ void qos_node_create_driver(const char *name, QOSCreateDriverFunc function) } void qos_node_contains(const char *container, const char *contained, - ...) + QOSGraphEdgeOptions *opts, ...) { va_list va; - va_start(va, contained); - QOSGraphEdgeOptions *opts; + if (opts == NULL) { + add_edge(container, contained, QEDGE_CONTAINS, NULL); + return; + } + + va_start(va, opts); do { - opts = va_arg(va, QOSGraphEdgeOptions *); add_edge(container, contained, QEDGE_CONTAINS, opts); + opts = va_arg(va, QOSGraphEdgeOptions *); } while (opts != NULL); va_end(va); diff --git a/tests/libqos/qgraph.h b/tests/libqos/qgraph.h index e799095b30..3a25dda4b2 100644 --- a/tests/libqos/qgraph.h +++ b/tests/libqos/qgraph.h @@ -453,14 +453,16 @@ void qos_node_create_machine_args(const char *name, void qos_node_create_driver(const char *name, QOSCreateDriverFunc function); /** - * qos_node_contains(): creates an edge of type QEDGE_CONTAINS and - * adds it to the edge list mapped to @container in the + * qos_node_contains(): creates one or more edges of type QEDGE_CONTAINS + * and adds them to the edge list mapped to @container in the * edge hash table. * - * This edge will have @container as source and @contained as destination. + * The edges will have @container as source and @contained as destination. * - * It also has the possibility to add optional NULL-terminated - * @opts parameters (see %QOSGraphEdgeOptions) + * If @opts is NULL, a single edge will be added with no options. + * If @opts is non-NULL, the arguments after @contained represent a + * NULL-terminated list of %QOSGraphEdgeOptions structs, and an + * edge will be added for each of them. * * This function can be useful when there are multiple devices * with the same node name contained in a machine/other node @@ -480,7 +482,8 @@ void qos_node_create_driver(const char *name, QOSCreateDriverFunc function); * For contains, op1.arg and op1.size_arg represent the arg to pass * to @contained constructor to properly initialize it. */ -void qos_node_contains(const char *container, const char *contained, ...); +void qos_node_contains(const char *container, const char *contained, + QOSGraphEdgeOptions *opts, ...); /** * qos_node_produces(): creates an edge of type QEDGE_PRODUCES and diff --git a/tests/pca9552-test.c b/tests/pca9552-test.c index 5466a67ed7..4b800d3c3e 100644 --- a/tests/pca9552-test.c +++ b/tests/pca9552-test.c @@ -10,107 +10,84 @@ #include "qemu/osdep.h" #include "libqtest.h" +#include "libqos/qgraph.h" #include "libqos/i2c.h" #include "hw/misc/pca9552_regs.h" #define PCA9552_TEST_ID "pca9552-test" #define PCA9552_TEST_ADDR 0x60 -static I2CAdapter *i2c; - -static uint8_t pca9552_get8(I2CAdapter *i2c, uint8_t addr, uint8_t reg) +static void pca9552_init(QI2CDevice *i2cdev) { - uint8_t resp[1]; - i2c_send(i2c, addr, ®, 1); - i2c_recv(i2c, addr, resp, 1); - return resp[0]; + /* Switch on LEDs 0 and 12 */ + i2c_set8(i2cdev, PCA9552_LS0, 0x54); + i2c_set8(i2cdev, PCA9552_LS3, 0x54); } -static void pca9552_set8(I2CAdapter *i2c, uint8_t addr, uint8_t reg, - uint8_t value) -{ - uint8_t cmd[2]; - uint8_t resp[1]; - - cmd[0] = reg; - cmd[1] = value; - i2c_send(i2c, addr, cmd, 2); - i2c_recv(i2c, addr, resp, 1); - g_assert_cmphex(resp[0], ==, cmd[1]); -} - -static void receive_autoinc(void) +static void receive_autoinc(void *obj, void *data, QGuestAllocator *alloc) { + QI2CDevice *i2cdev = (QI2CDevice *)obj; uint8_t resp; uint8_t reg = PCA9552_LS0 | PCA9552_AUTOINC; - i2c_send(i2c, PCA9552_TEST_ADDR, ®, 1); + pca9552_init(i2cdev); + + i2c_send(i2cdev, ®, 1); /* PCA9552_LS0 */ - i2c_recv(i2c, PCA9552_TEST_ADDR, &resp, 1); + i2c_recv(i2cdev, &resp, 1); g_assert_cmphex(resp, ==, 0x54); /* PCA9552_LS1 */ - i2c_recv(i2c, PCA9552_TEST_ADDR, &resp, 1); + i2c_recv(i2cdev, &resp, 1); g_assert_cmphex(resp, ==, 0x55); /* PCA9552_LS2 */ - i2c_recv(i2c, PCA9552_TEST_ADDR, &resp, 1); + i2c_recv(i2cdev, &resp, 1); g_assert_cmphex(resp, ==, 0x55); /* PCA9552_LS3 */ - i2c_recv(i2c, PCA9552_TEST_ADDR, &resp, 1); + i2c_recv(i2cdev, &resp, 1); g_assert_cmphex(resp, ==, 0x54); } -static void send_and_receive(void) +static void send_and_receive(void *obj, void *data, QGuestAllocator *alloc) { + QI2CDevice *i2cdev = (QI2CDevice *)obj; uint8_t value; - value = pca9552_get8(i2c, PCA9552_TEST_ADDR, PCA9552_LS0); + value = i2c_get8(i2cdev, PCA9552_LS0); g_assert_cmphex(value, ==, 0x55); - value = pca9552_get8(i2c, PCA9552_TEST_ADDR, PCA9552_INPUT0); + value = i2c_get8(i2cdev, PCA9552_INPUT0); g_assert_cmphex(value, ==, 0x0); - /* Switch on LED 0 */ - pca9552_set8(i2c, PCA9552_TEST_ADDR, PCA9552_LS0, 0x54); - value = pca9552_get8(i2c, PCA9552_TEST_ADDR, PCA9552_LS0); + pca9552_init(i2cdev); + + value = i2c_get8(i2cdev, PCA9552_LS0); g_assert_cmphex(value, ==, 0x54); - value = pca9552_get8(i2c, PCA9552_TEST_ADDR, PCA9552_INPUT0); + value = i2c_get8(i2cdev, PCA9552_INPUT0); g_assert_cmphex(value, ==, 0x01); - /* Switch on LED 12 */ - pca9552_set8(i2c, PCA9552_TEST_ADDR, PCA9552_LS3, 0x54); - value = pca9552_get8(i2c, PCA9552_TEST_ADDR, PCA9552_LS3); + value = i2c_get8(i2cdev, PCA9552_LS3); g_assert_cmphex(value, ==, 0x54); - value = pca9552_get8(i2c, PCA9552_TEST_ADDR, PCA9552_INPUT1); + value = i2c_get8(i2cdev, PCA9552_INPUT1); g_assert_cmphex(value, ==, 0x10); } -int main(int argc, char **argv) +static void pca9552_register_nodes(void) { - QTestState *s = NULL; - int ret; - - g_test_init(&argc, &argv, NULL); - - s = qtest_start("-machine n800 " - "-device pca9552,bus=i2c-bus.0,id=" PCA9552_TEST_ID - ",address=0x60"); - i2c = omap_i2c_create(s, OMAP2_I2C_1_BASE); - - qtest_add_func("/pca9552/tx-rx", send_and_receive); - qtest_add_func("/pca9552/rx-autoinc", receive_autoinc); - - ret = g_test_run(); + QOSGraphEdgeOptions opts = { + .extra_device_opts = "address=0x60" + }; + add_qi2c_address(&opts, &(QI2CAddress) { 0x60 }); - if (s) { - qtest_quit(s); - } - g_free(i2c); + qos_node_create_driver("pca9552", i2c_device_create); + qos_node_consumes("pca9552", "i2c-bus", &opts); - return ret; + qos_add_test("tx-rx", "pca9552", send_and_receive, NULL); + qos_add_test("rx-autoinc", "pca9552", receive_autoinc, NULL); } +libqos_init(pca9552_register_nodes); diff --git a/tests/qos-test.c b/tests/qos-test.c index ae2fb5de1c..01b2a22c08 100644 --- a/tests/qos-test.c +++ b/tests/qos-test.c @@ -340,7 +340,8 @@ static void walk_path(QOSGraphNode *orig_path, int len) char **path_vec = g_new0(char *, (QOS_PATH_MAX_ELEMENT_SIZE * 2)); int path_vec_size = 0; - char *after_cmd = NULL, *before_cmd = NULL, *after_device = NULL; + char *after_cmd, *before_cmd, *after_device; + GString *after_device_str = g_string_new(""); char *node_name = orig_path->name, *path_str; GString *cmd_line = g_string_new(""); @@ -363,9 +364,8 @@ static void walk_path(QOSGraphNode *orig_path, int len) /* append node command line + previous edge command line */ if (path->command_line && etype == QEDGE_CONSUMED_BY) { g_string_append(cmd_line, path->command_line); - if (after_device) { - g_string_append(cmd_line, after_device); - } + g_string_append(cmd_line, after_device_str->str); + g_string_truncate(after_device_str, 0); } path_vec[path_vec_size++] = qos_graph_edge_get_name(path->path_edge); @@ -382,12 +382,15 @@ static void walk_path(QOSGraphNode *orig_path, int len) if (after_cmd) { g_string_append(cmd_line2, after_cmd); } + if (after_device) { + g_string_append(after_device_str, after_device); + } } path_vec[path_vec_size++] = NULL; - if (after_device) { - g_string_append(cmd_line, after_device); - } + g_string_append(cmd_line, after_device_str->str); + g_string_free(after_device_str, true); + g_string_append(cmd_line, cmd_line2->str); g_string_free(cmd_line2, true); diff --git a/tests/test-thread-pool.c b/tests/test-thread-pool.c index 9cdccb3a47..0b675923f6 100644 --- a/tests/test-thread-pool.c +++ b/tests/test-thread-pool.c @@ -27,9 +27,10 @@ static int worker_cb(void *opaque) static int long_cb(void *opaque) { WorkerTestData *data = opaque; - atomic_inc(&data->n); - g_usleep(2000000); - atomic_inc(&data->n); + if (atomic_cmpxchg(&data->n, 0, 1) == 0) { + g_usleep(2000000); + atomic_or(&data->n, 2); + } return 0; } @@ -171,7 +172,7 @@ static void do_test_cancel(bool sync) /* Cancel the jobs that haven't been started yet. */ num_canceled = 0; for (i = 0; i < 100; i++) { - if (atomic_cmpxchg(&data[i].n, 0, 3) == 0) { + if (atomic_cmpxchg(&data[i].n, 0, 4) == 0) { data[i].ret = -ECANCELED; if (sync) { bdrv_aio_cancel(data[i].aiocb); @@ -185,7 +186,7 @@ static void do_test_cancel(bool sync) g_assert_cmpint(num_canceled, <, 100); for (i = 0; i < 100; i++) { - if (data[i].aiocb && data[i].n != 3) { + if (data[i].aiocb && atomic_read(&data[i].n) < 4) { if (sync) { /* Canceling the others will be a blocking operation. */ bdrv_aio_cancel(data[i].aiocb); @@ -201,13 +202,22 @@ static void do_test_cancel(bool sync) } g_assert_cmpint(active, ==, 0); for (i = 0; i < 100; i++) { - if (data[i].n == 3) { + g_assert(data[i].aiocb == NULL); + switch (data[i].n) { + case 0: + fprintf(stderr, "Callback not canceled but never started?\n"); + abort(); + case 3: + /* Couldn't be canceled asynchronously, must have completed. */ + g_assert_cmpint(data[i].ret, ==, 0); + break; + case 4: + /* Could be canceled asynchronously, never started. */ g_assert_cmpint(data[i].ret, ==, -ECANCELED); - g_assert(data[i].aiocb == NULL); - } else { - g_assert_cmpint(data[i].n, ==, 2); - g_assert(data[i].ret == 0 || data[i].ret == -ECANCELED); - g_assert(data[i].aiocb == NULL); + break; + default: + fprintf(stderr, "Callback aborted while running?\n"); + abort(); } } } diff --git a/tests/tmp105-test.c b/tests/tmp105-test.c index 34cae7a582..f599309a4a 100644 --- a/tests/tmp105-test.c +++ b/tests/tmp105-test.c @@ -10,6 +10,7 @@ #include "qemu/osdep.h" #include "libqtest.h" +#include "libqos/qgraph.h" #include "libqos/i2c.h" #include "qapi/qmp/qdict.h" #include "hw/misc/tmp105_regs.h" @@ -17,52 +18,6 @@ #define TMP105_TEST_ID "tmp105-test" #define TMP105_TEST_ADDR 0x49 -static I2CAdapter *i2c; - -static uint16_t tmp105_get8(I2CAdapter *i2c, uint8_t addr, uint8_t reg) -{ - uint8_t resp[1]; - i2c_send(i2c, addr, ®, 1); - i2c_recv(i2c, addr, resp, 1); - return resp[0]; -} - -static uint16_t tmp105_get16(I2CAdapter *i2c, uint8_t addr, uint8_t reg) -{ - uint8_t resp[2]; - i2c_send(i2c, addr, ®, 1); - i2c_recv(i2c, addr, resp, 2); - return (resp[0] << 8) | resp[1]; -} - -static void tmp105_set8(I2CAdapter *i2c, uint8_t addr, uint8_t reg, - uint8_t value) -{ - uint8_t cmd[2]; - uint8_t resp[1]; - - cmd[0] = reg; - cmd[1] = value; - i2c_send(i2c, addr, cmd, 2); - i2c_recv(i2c, addr, resp, 1); - g_assert_cmphex(resp[0], ==, cmd[1]); -} - -static void tmp105_set16(I2CAdapter *i2c, uint8_t addr, uint8_t reg, - uint16_t value) -{ - uint8_t cmd[3]; - uint8_t resp[2]; - - cmd[0] = reg; - cmd[1] = value >> 8; - cmd[2] = value & 255; - i2c_send(i2c, addr, cmd, 3); - i2c_recv(i2c, addr, resp, 2); - g_assert_cmphex(resp[0], ==, cmd[1]); - g_assert_cmphex(resp[1], ==, cmd[2]); -} - static int qmp_tmp105_get_temperature(const char *id) { QDict *response; @@ -87,21 +42,22 @@ static void qmp_tmp105_set_temperature(const char *id, int value) } #define TMP105_PRECISION (1000/16) -static void send_and_receive(void) +static void send_and_receive(void *obj, void *data, QGuestAllocator *alloc) { uint16_t value; + QI2CDevice *i2cdev = (QI2CDevice *)obj; value = qmp_tmp105_get_temperature(TMP105_TEST_ID); g_assert_cmpuint(value, ==, 0); - value = tmp105_get16(i2c, TMP105_TEST_ADDR, TMP105_REG_TEMPERATURE); + value = i2c_get16(i2cdev, TMP105_REG_TEMPERATURE); g_assert_cmphex(value, ==, 0); qmp_tmp105_set_temperature(TMP105_TEST_ID, 20000); value = qmp_tmp105_get_temperature(TMP105_TEST_ID); g_assert_cmpuint(value, ==, 20000); - value = tmp105_get16(i2c, TMP105_TEST_ADDR, TMP105_REG_TEMPERATURE); + value = i2c_get16(i2cdev, TMP105_REG_TEMPERATURE); g_assert_cmphex(value, ==, 0x1400); qmp_tmp105_set_temperature(TMP105_TEST_ID, 20938); /* 20 + 15/16 */ @@ -110,24 +66,27 @@ static void send_and_receive(void) g_assert_cmpuint(value, <, 20938 + TMP105_PRECISION/2); /* Set config */ - tmp105_set8(i2c, TMP105_TEST_ADDR, TMP105_REG_CONFIG, 0x60); - value = tmp105_get8(i2c, TMP105_TEST_ADDR, TMP105_REG_CONFIG); + i2c_set8(i2cdev, TMP105_REG_CONFIG, 0x60); + value = i2c_get8(i2cdev, TMP105_REG_CONFIG); g_assert_cmphex(value, ==, 0x60); - value = tmp105_get16(i2c, TMP105_TEST_ADDR, TMP105_REG_TEMPERATURE); + value = i2c_get16(i2cdev, TMP105_REG_TEMPERATURE); g_assert_cmphex(value, ==, 0x14f0); /* Set precision to 9, 10, 11 bits. */ - tmp105_set8(i2c, TMP105_TEST_ADDR, TMP105_REG_CONFIG, 0x00); - value = tmp105_get16(i2c, TMP105_TEST_ADDR, TMP105_REG_TEMPERATURE); + i2c_set8(i2cdev, TMP105_REG_CONFIG, 0x00); + g_assert_cmphex(i2c_get8(i2cdev, TMP105_REG_CONFIG), ==, 0x00); + value = i2c_get16(i2cdev, TMP105_REG_TEMPERATURE); g_assert_cmphex(value, ==, 0x1480); - tmp105_set8(i2c, TMP105_TEST_ADDR, TMP105_REG_CONFIG, 0x20); - value = tmp105_get16(i2c, TMP105_TEST_ADDR, TMP105_REG_TEMPERATURE); + i2c_set8(i2cdev, TMP105_REG_CONFIG, 0x20); + g_assert_cmphex(i2c_get8(i2cdev, TMP105_REG_CONFIG), ==, 0x20); + value = i2c_get16(i2cdev, TMP105_REG_TEMPERATURE); g_assert_cmphex(value, ==, 0x14c0); - tmp105_set8(i2c, TMP105_TEST_ADDR, TMP105_REG_CONFIG, 0x40); - value = tmp105_get16(i2c, TMP105_TEST_ADDR, TMP105_REG_TEMPERATURE); + i2c_set8(i2cdev, TMP105_REG_CONFIG, 0x40); + g_assert_cmphex(i2c_get8(i2cdev, TMP105_REG_CONFIG), ==, 0x40); + value = i2c_get16(i2cdev, TMP105_REG_TEMPERATURE); g_assert_cmphex(value, ==, 0x14e0); /* stored precision remains the same */ @@ -135,32 +94,27 @@ static void send_and_receive(void) g_assert_cmpuint(value, >=, 20938 - TMP105_PRECISION/2); g_assert_cmpuint(value, <, 20938 + TMP105_PRECISION/2); - tmp105_set8(i2c, TMP105_TEST_ADDR, TMP105_REG_CONFIG, 0x60); - value = tmp105_get16(i2c, TMP105_TEST_ADDR, TMP105_REG_TEMPERATURE); + i2c_set8(i2cdev, TMP105_REG_CONFIG, 0x60); + g_assert_cmphex(i2c_get8(i2cdev, TMP105_REG_CONFIG), ==, 0x60); + value = i2c_get16(i2cdev, TMP105_REG_TEMPERATURE); g_assert_cmphex(value, ==, 0x14f0); - tmp105_set16(i2c, TMP105_TEST_ADDR, TMP105_REG_T_LOW, 0x1234); - tmp105_set16(i2c, TMP105_TEST_ADDR, TMP105_REG_T_HIGH, 0x4231); + i2c_set16(i2cdev, TMP105_REG_T_LOW, 0x1234); + g_assert_cmphex(i2c_get16(i2cdev, TMP105_REG_T_LOW), ==, 0x1234); + i2c_set16(i2cdev, TMP105_REG_T_HIGH, 0x4231); + g_assert_cmphex(i2c_get16(i2cdev, TMP105_REG_T_HIGH), ==, 0x4231); } -int main(int argc, char **argv) +static void tmp105_register_nodes(void) { - QTestState *s = NULL; - int ret; - - g_test_init(&argc, &argv, NULL); + QOSGraphEdgeOptions opts = { + .extra_device_opts = "id=" TMP105_TEST_ID ",address=0x49" + }; + add_qi2c_address(&opts, &(QI2CAddress) { 0x49 }); - s = qtest_start("-machine n800 " - "-device tmp105,bus=i2c-bus.0,id=" TMP105_TEST_ID - ",address=0x49"); - i2c = omap_i2c_create(s, OMAP2_I2C_1_BASE); + qos_node_create_driver("tmp105", i2c_device_create); + qos_node_consumes("tmp105", "i2c-bus", &opts); - qtest_add_func("/tmp105/tx-rx", send_and_receive); - - ret = g_test_run(); - - qtest_quit(s); - g_free(i2c); - - return ret; + qos_add_test("tx-rx", "tmp105", send_and_receive, NULL); } +libqos_init(tmp105_register_nodes); @@ -3576,7 +3576,23 @@ int main(int argc, char **argv, char **envp) optarg, true); optarg = qemu_opt_get(accel_opts, "accel"); if (!optarg || is_help_option(optarg)) { - printf("Possible accelerators: kvm, xen, hax, tcg\n"); + printf("Accelerators supported in QEMU binary:\n"); + GSList *el, *accel_list = object_class_get_list(TYPE_ACCEL, + false); + for (el = accel_list; el; el = el->next) { + gchar *typename = g_strdup(object_class_get_name( + OBJECT_CLASS(el->data))); + /* omit qtest which is used for tests only */ + if (g_strcmp0(typename, ACCEL_CLASS_NAME("qtest")) && + g_str_has_suffix(typename, ACCEL_CLASS_SUFFIX)) { + gchar **optname = g_strsplit(typename, + ACCEL_CLASS_SUFFIX, 0); + printf("%s\n", optname[0]); + g_free(optname); + } + g_free(typename); + } + g_slist_free(accel_list); exit(0); } opts = qemu_opts_create(qemu_find_opts("machine"), NULL, |