diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2021-02-18 13:27:03 +0000 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2021-02-18 13:27:03 +0000 |
commit | 91416a4254015e1e3f602f2b241b9ddb7879c10b (patch) | |
tree | 928b2ee36460116a33446935931e866260b98dff /tests | |
parent | 1af5629673bb5c1592d993f9fb6119a62845f576 (diff) | |
parent | df55e2a701d02bc01b9425843c667fd0cb4cdfa9 (diff) | |
download | qemu-91416a4254015e1e3f602f2b241b9ddb7879c10b.zip qemu-91416a4254015e1e3f602f2b241b9ddb7879c10b.tar.gz qemu-91416a4254015e1e3f602f2b241b9ddb7879c10b.tar.bz2 |
Merge remote-tracking branch 'remotes/stsquad/tags/pull-plugin-updates-180221-1' into staging
Plugin updates:
- expose vdev name in PCI memory registration
- new hwprofile plugin
- bunch of style cleanups to contrib/plugins
- fix call signature of inline instrumentation
- re-factor the io_recompile code to push specialisation into hooks
- add some acceptance tests for the plugins
- clean-up and remove CF_NOCACHE handling from TCG
- fix instrumentation of cpu_io_recompile sections
- expand tests to check inline and cb count the same
# gpg: Signature made Thu 18 Feb 2021 08:24:57 GMT
# gpg: using RSA key 6685AE99E75167BCAFC8DF35FBD0DB095A9E2A44
# gpg: Good signature from "Alex Bennée (Master Work Key) <alex.bennee@linaro.org>" [full]
# Primary key fingerprint: 6685 AE99 E751 67BC AFC8 DF35 FBD0 DB09 5A9E 2A44
* remotes/stsquad/tags/pull-plugin-updates-180221-1: (23 commits)
tests/acceptance: add a memory callback check
tests/plugin: allow memory plugin to do both inline and callbacks
tests/acceptance: add a new tests to detect counting errors
accel/tcg: allow plugin instrumentation to be disable via cflags
accel/tcg: remove CF_NOCACHE and special cases
accel/tcg: re-factor non-RAM execution code
accel/tcg: cache single instruction TB on pending replay exception
accel/tcg: actually cache our partial icount TB
tests/acceptance: add a new set of tests to exercise plugins
tests/plugin: expand insn test to detect duplicate instructions
target/sh4: Create superh_io_recompile_replay_branch
target/mips: Create mips_io_recompile_replay_branch
accel/tcg: Create io_recompile_replay_branch hook
exec: Move TranslationBlock typedef to qemu/typedefs.h
accel/tcg/plugin-gen: fix the call signature for inline callbacks
contrib: Open brace '{' following struct go on the same line
contrib: space required after that ','
contrib: Add spaces around operator
contrib: Fix some code style problems, ERROR: "foo * bar" should be "foo *bar"
contrib: Don't use '#' flag of printf format
...
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'tests')
-rw-r--r-- | tests/acceptance/tcg_plugins.py | 148 | ||||
-rw-r--r-- | tests/plugin/insn.c | 12 | ||||
-rw-r--r-- | tests/plugin/mem.c | 27 | ||||
-rw-r--r-- | tests/tcg/i386/Makefile.softmmu-target | 10 | ||||
-rw-r--r-- | tests/tcg/i386/Makefile.target | 7 | ||||
-rw-r--r-- | tests/tcg/x86_64/Makefile.softmmu-target | 10 |
6 files changed, 206 insertions, 8 deletions
diff --git a/tests/acceptance/tcg_plugins.py b/tests/acceptance/tcg_plugins.py new file mode 100644 index 0000000..c21bf9e --- /dev/null +++ b/tests/acceptance/tcg_plugins.py @@ -0,0 +1,148 @@ +# TCG Plugins tests +# +# These are a little more involved than the basic tests run by check-tcg. +# +# Copyright (c) 2021 Linaro +# +# Author: +# Alex Bennée <alex.bennee@linaro.org> +# +# SPDX-License-Identifier: GPL-2.0-or-later + +import tempfile +import mmap +import re + +from boot_linux_console import LinuxKernelTest + + +class PluginKernelBase(LinuxKernelTest): + """ + Boots a Linux kernel with a TCG plugin enabled. + """ + + timeout = 120 + KERNEL_COMMON_COMMAND_LINE = 'printk.time=1 panic=-1 ' + + def run_vm(self, kernel_path, kernel_command_line, + plugin, plugin_log, console_pattern, args): + + vm = self.get_vm() + vm.set_console() + vm.add_args('-kernel', kernel_path, + '-append', kernel_command_line, + '-plugin', plugin, + '-d', 'plugin', + '-D', plugin_log, + '-net', 'none', + '-no-reboot') + if args: + vm.add_args(*args) + + try: + vm.launch() + except: + # TODO: probably fails because plugins not enabled but we + # can't currently probe for the feature. + self.cancel("TCG Plugins not enabled?") + + self.wait_for_console_pattern(console_pattern, vm) + # ensure logs are flushed + vm.shutdown() + + +class PluginKernelNormal(PluginKernelBase): + + def _grab_aarch64_kernel(self): + kernel_url = ('http://security.debian.org/' + 'debian-security/pool/updates/main/l/linux-signed-arm64/' + 'linux-image-4.19.0-12-arm64_4.19.152-1_arm64.deb') + kernel_sha1 = '2036c2792f80ac9c4ccaae742b2e0a28385b6010' + kernel_deb = self.fetch_asset(kernel_url, asset_hash=kernel_sha1) + kernel_path = self.extract_from_deb(kernel_deb, + "/boot/vmlinuz-4.19.0-12-arm64") + return kernel_path + + def test_aarch64_virt_insn(self): + """ + :avocado: tags=accel:tcg + :avocado: tags=arch:aarch64 + :avocado: tags=machine:virt + :avocado: tags=cpu:cortex-a57 + """ + kernel_path = self._grab_aarch64_kernel() + kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + + 'console=ttyAMA0') + console_pattern = 'Kernel panic - not syncing: VFS:' + + plugin_log = tempfile.NamedTemporaryFile(mode="r+t", prefix="plugin", + suffix=".log") + + self.run_vm(kernel_path, kernel_command_line, + "tests/plugin/libinsn.so", plugin_log.name, + console_pattern, + args=('-cpu', 'cortex-a53')) + + with plugin_log as lf, \ + mmap.mmap(lf.fileno(), 0, access=mmap.ACCESS_READ) as s: + + m = re.search(br"insns: (?P<count>\d+)", s) + if "count" not in m.groupdict(): + self.fail("Failed to find instruction count") + + def test_aarch64_virt_insn_icount(self): + """ + :avocado: tags=accel:tcg + :avocado: tags=arch:aarch64 + :avocado: tags=machine:virt + :avocado: tags=cpu:cortex-a57 + """ + kernel_path = self._grab_aarch64_kernel() + kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + + 'console=ttyAMA0') + console_pattern = 'Kernel panic - not syncing: VFS:' + + plugin_log = tempfile.NamedTemporaryFile(mode="r+t", prefix="plugin", + suffix=".log") + + self.run_vm(kernel_path, kernel_command_line, + "tests/plugin/libinsn.so", plugin_log.name, + console_pattern, + args=('-cpu', 'cortex-a53', '-icount', 'shift=1')) + + with plugin_log as lf, \ + mmap.mmap(lf.fileno(), 0, access=mmap.ACCESS_READ) as s: + m = re.search(br"detected repeat execution @ (?P<addr>0x[0-9A-Fa-f]+)", s) + if m is not None and "addr" in m.groupdict(): + self.fail("detected repeated instructions") + + def test_aarch64_virt_mem_icount(self): + """ + :avocado: tags=accel:tcg + :avocado: tags=arch:aarch64 + :avocado: tags=machine:virt + :avocado: tags=cpu:cortex-a57 + """ + kernel_path = self._grab_aarch64_kernel() + kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + + 'console=ttyAMA0') + console_pattern = 'Kernel panic - not syncing: VFS:' + + plugin_log = tempfile.NamedTemporaryFile(mode="r+t", prefix="plugin", + suffix=".log") + + self.run_vm(kernel_path, kernel_command_line, + "tests/plugin/libmem.so,arg=both", plugin_log.name, + console_pattern, + args=('-cpu', 'cortex-a53', '-icount', 'shift=1')) + + with plugin_log as lf, \ + mmap.mmap(lf.fileno(), 0, access=mmap.ACCESS_READ) as s: + m = re.findall(br"mem accesses: (?P<count>\d+)", s) + if m is None or len(m) != 2: + self.fail("no memory access counts found") + else: + inline = int(m[0]) + callback = int(m[1]) + if inline != callback: + self.fail("mismatched access counts") diff --git a/tests/plugin/insn.c b/tests/plugin/insn.c index a9a6e41..c253980 100644 --- a/tests/plugin/insn.c +++ b/tests/plugin/insn.c @@ -21,6 +21,14 @@ static bool do_inline; static void vcpu_insn_exec_before(unsigned int cpu_index, void *udata) { + static uint64_t last_pc; + uint64_t this_pc = GPOINTER_TO_UINT(udata); + if (this_pc == last_pc) { + g_autofree gchar *out = g_strdup_printf("detected repeat execution @ 0x%" + PRIx64 "\n", this_pc); + qemu_plugin_outs(out); + } + last_pc = this_pc; insn_count++; } @@ -36,8 +44,10 @@ static void vcpu_tb_trans(qemu_plugin_id_t id, struct qemu_plugin_tb *tb) qemu_plugin_register_vcpu_insn_exec_inline( insn, QEMU_PLUGIN_INLINE_ADD_U64, &insn_count, 1); } else { + uint64_t vaddr = qemu_plugin_insn_vaddr(insn); qemu_plugin_register_vcpu_insn_exec_cb( - insn, vcpu_insn_exec_before, QEMU_PLUGIN_CB_NO_REGS, NULL); + insn, vcpu_insn_exec_before, QEMU_PLUGIN_CB_NO_REGS, + GUINT_TO_POINTER(vaddr)); } } } diff --git a/tests/plugin/mem.c b/tests/plugin/mem.c index 4725bd8..afd1d27 100644 --- a/tests/plugin/mem.c +++ b/tests/plugin/mem.c @@ -16,9 +16,10 @@ QEMU_PLUGIN_EXPORT int qemu_plugin_version = QEMU_PLUGIN_VERSION; -static uint64_t mem_count; +static uint64_t inline_mem_count; +static uint64_t cb_mem_count; static uint64_t io_count; -static bool do_inline; +static bool do_inline, do_callback; static bool do_haddr; static enum qemu_plugin_mem_rw rw = QEMU_PLUGIN_MEM_RW; @@ -26,7 +27,12 @@ static void plugin_exit(qemu_plugin_id_t id, void *p) { g_autoptr(GString) out = g_string_new(""); - g_string_printf(out, "mem accesses: %" PRIu64 "\n", mem_count); + if (do_inline) { + g_string_printf(out, "inline mem accesses: %" PRIu64 "\n", inline_mem_count); + } + if (do_callback) { + g_string_append_printf(out, "callback mem accesses: %" PRIu64 "\n", cb_mem_count); + } if (do_haddr) { g_string_append_printf(out, "io accesses: %" PRIu64 "\n", io_count); } @@ -42,10 +48,10 @@ static void vcpu_mem(unsigned int cpu_index, qemu_plugin_meminfo_t meminfo, if (qemu_plugin_hwaddr_is_io(hwaddr)) { io_count++; } else { - mem_count++; + cb_mem_count++; } } else { - mem_count++; + cb_mem_count++; } } @@ -60,8 +66,9 @@ static void vcpu_tb_trans(qemu_plugin_id_t id, struct qemu_plugin_tb *tb) if (do_inline) { qemu_plugin_register_vcpu_mem_inline(insn, rw, QEMU_PLUGIN_INLINE_ADD_U64, - &mem_count, 1); - } else { + &inline_mem_count, 1); + } + if (do_callback) { qemu_plugin_register_vcpu_mem_cb(insn, vcpu_mem, QEMU_PLUGIN_CB_NO_REGS, rw, NULL); @@ -90,6 +97,12 @@ QEMU_PLUGIN_EXPORT int qemu_plugin_install(qemu_plugin_id_t id, } if (!strcmp(argv[0], "inline")) { do_inline = true; + do_callback = false; + } else if (!strcmp(argv[0], "both")) { + do_inline = true; + do_callback = true; + } else { + do_callback = true; } } diff --git a/tests/tcg/i386/Makefile.softmmu-target b/tests/tcg/i386/Makefile.softmmu-target index 5266f23..fa9b1b9 100644 --- a/tests/tcg/i386/Makefile.softmmu-target +++ b/tests/tcg/i386/Makefile.softmmu-target @@ -33,5 +33,15 @@ EXTRA_RUNS+=$(MULTIARCH_RUNS) memory: CFLAGS+=-DCHECK_UNALIGNED=1 +# non-inline runs will trigger the duplicate instruction heuristics in libinsn.so +run-plugin-%-with-libinsn.so: + $(call run-test, $@, \ + $(QEMU) -monitor none -display none \ + -chardev file$(COMMA)path=$@.out$(COMMA)id=output \ + -plugin ../../plugin/libinsn.so$(COMMA)arg=inline \ + -d plugin -D $*-with-libinsn.so.pout \ + $(QEMU_OPTS) $*, \ + "$* on $(TARGET_NAME)") + # Running QEMU_OPTS+=-device isa-debugcon,chardev=output -device isa-debug-exit,iobase=0xf4,iosize=0x4 -kernel diff --git a/tests/tcg/i386/Makefile.target b/tests/tcg/i386/Makefile.target index ad187cb..c4a6f91 100644 --- a/tests/tcg/i386/Makefile.target +++ b/tests/tcg/i386/Makefile.target @@ -48,6 +48,13 @@ else SKIP_I386_TESTS+=test-i386-fprem endif +# non-inline runs will trigger the duplicate instruction heuristics in libinsn.so +run-plugin-%-with-libinsn.so: + $(call run-test, $@, $(QEMU) $(QEMU_OPTS) \ + -plugin ../../plugin/libinsn.so$(COMMA)arg=inline \ + -d plugin -D $*-with-libinsn.so.pout $*, \ + "$* (inline) on $(TARGET_NAME)") + # Update TESTS I386_TESTS:=$(filter-out $(SKIP_I386_TESTS), $(ALL_X86_TESTS)) TESTS=$(MULTIARCH_TESTS) $(I386_TESTS) diff --git a/tests/tcg/x86_64/Makefile.softmmu-target b/tests/tcg/x86_64/Makefile.softmmu-target index 1bd763f..9896319 100644 --- a/tests/tcg/x86_64/Makefile.softmmu-target +++ b/tests/tcg/x86_64/Makefile.softmmu-target @@ -33,5 +33,15 @@ EXTRA_RUNS+=$(MULTIARCH_RUNS) memory: CFLAGS+=-DCHECK_UNALIGNED=1 +# non-inline runs will trigger the duplicate instruction heuristics in libinsn.so +run-plugin-%-with-libinsn.so: + $(call run-test, $@, \ + $(QEMU) -monitor none -display none \ + -chardev file$(COMMA)path=$@.out$(COMMA)id=output \ + -plugin ../../plugin/libinsn.so$(COMMA)arg=inline \ + -d plugin -D $*-with-libinsn.so.pout \ + $(QEMU_OPTS) $*, \ + "$* on $(TARGET_NAME)") + # Running QEMU_OPTS+=-device isa-debugcon,chardev=output -device isa-debug-exit,iobase=0xf4,iosize=0x4 -kernel |