Minor bug fixes and documentation cleanups:
- display packages in CI builds to catch changes - stop compiler complaining about exec stacks in test cases - stop loongarch compiler complaining about rwx in test cases - improve docs on running TCG tests - remove old unneeded avocado test for memory callback testing - move test plugins into tcg testing dir - clean-up and move plugin documentation to emulation section - remove dead code from cache modelling plugin - add compatibility workaround for lockstep plugin - make some noise when building contrib plugins -----BEGIN PGP SIGNATURE----- iQEzBAABCgAdFiEEZoWumedRZ7yvyN81+9DbCVqeKkQFAmaoxmwACgkQ+9DbCVqe KkTOGwgAhAqwEQIIwridsih//+3NYB2QQ9SmbCW7ss/idVN0DfWEQLcEfiBz9sWl Vh0CeptupLvtQlbbcnTdIG7sF6Aj9+XbTbYy4dS0nl4TGPmUoWqJy4QdZtpMlSBp s3FyC2g6UxXKkbI64RPSkdGaMEdb8ACvlGrQqb2LvrH+6tmlEfSQ05jLFrm1L0Db LjsxeFq50aVVIP2y91Cvc7FZmFgv0dqjTVlIMi9JGiW5cDKAwLDHv5AvQqT6oiv8 yyknMlnf8pvNiJpsJYXHIbl/029C87n6NeStHjfrMA9yUC4hWqYb4qzXFu4k7fuo 2s5WdRFK+QAXEgi9MhS2p7eXVVlMpw== =8gOM -----END PGP SIGNATURE----- Merge tag 'pull-maintainer-9.1-rc1-300724-1' of https://gitlab.com/stsquad/qemu into staging Minor bug fixes and documentation cleanups: - display packages in CI builds to catch changes - stop compiler complaining about exec stacks in test cases - stop loongarch compiler complaining about rwx in test cases - improve docs on running TCG tests - remove old unneeded avocado test for memory callback testing - move test plugins into tcg testing dir - clean-up and move plugin documentation to emulation section - remove dead code from cache modelling plugin - add compatibility workaround for lockstep plugin - make some noise when building contrib plugins # -----BEGIN PGP SIGNATURE----- # # iQEzBAABCgAdFiEEZoWumedRZ7yvyN81+9DbCVqeKkQFAmaoxmwACgkQ+9DbCVqe # KkTOGwgAhAqwEQIIwridsih//+3NYB2QQ9SmbCW7ss/idVN0DfWEQLcEfiBz9sWl # Vh0CeptupLvtQlbbcnTdIG7sF6Aj9+XbTbYy4dS0nl4TGPmUoWqJy4QdZtpMlSBp # s3FyC2g6UxXKkbI64RPSkdGaMEdb8ACvlGrQqb2LvrH+6tmlEfSQ05jLFrm1L0Db # LjsxeFq50aVVIP2y91Cvc7FZmFgv0dqjTVlIMi9JGiW5cDKAwLDHv5AvQqT6oiv8 # yyknMlnf8pvNiJpsJYXHIbl/029C87n6NeStHjfrMA9yUC4hWqYb4qzXFu4k7fuo # 2s5WdRFK+QAXEgi9MhS2p7eXVVlMpw== # =8gOM # -----END PGP SIGNATURE----- # gpg: Signature made Tue 30 Jul 2024 08:54:36 PM AEST # gpg: using RSA key 6685AE99E75167BCAFC8DF35FBD0DB095A9E2A44 # gpg: Good signature from "Alex Bennée (Master Work Key) <alex.bennee@linaro.org>" [full] * tag 'pull-maintainer-9.1-rc1-300724-1' of https://gitlab.com/stsquad/qemu: plugin/loader: handle basic help query contrib/plugins: add compat for g_memdup2 contrib/plugins: be more vocal building contrib/plugins/cache.c: Remove redundant check of l2_access docs: split TCG plugin usage from devel section tests/tcg: move test plugins into tcg subdir tests/avocado: remove tcg_plugins virt_mem_icount test docs/devel: document how to run individual TCG tests docs/devel: update the testing introduction tests/tcg: update README tests/tcg/loongarch64: Use --no-warn-rwx-segments to link system tests tests/tcg: Use --noexecstack with assembler files gitlab: display /packages.txt in build jobs gitlab: record installed packages in /packages.txt in containers Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
commit
40a770ea8b
@ -9,6 +9,7 @@
|
|||||||
when: always
|
when: always
|
||||||
before_script:
|
before_script:
|
||||||
- JOBS=$(expr $(nproc) + 1)
|
- JOBS=$(expr $(nproc) + 1)
|
||||||
|
- cat /packages.txt
|
||||||
script:
|
script:
|
||||||
- export CCACHE_BASEDIR="$(pwd)"
|
- export CCACHE_BASEDIR="$(pwd)"
|
||||||
- export CCACHE_DIR="$CCACHE_BASEDIR/ccache"
|
- export CCACHE_DIR="$CCACHE_BASEDIR/ccache"
|
||||||
|
@ -8,6 +8,8 @@
|
|||||||
key: "$CI_JOB_NAME"
|
key: "$CI_JOB_NAME"
|
||||||
when: always
|
when: always
|
||||||
timeout: 80m
|
timeout: 80m
|
||||||
|
before_script:
|
||||||
|
- cat /packages.txt
|
||||||
script:
|
script:
|
||||||
- export CCACHE_BASEDIR="$(pwd)"
|
- export CCACHE_BASEDIR="$(pwd)"
|
||||||
- export CCACHE_DIR="$CCACHE_BASEDIR/ccache"
|
- export CCACHE_DIR="$CCACHE_BASEDIR/ccache"
|
||||||
|
@ -3751,7 +3751,7 @@ R: Pierrick Bouvier <pierrick.bouvier@linaro.org>
|
|||||||
S: Maintained
|
S: Maintained
|
||||||
F: docs/devel/tcg-plugins.rst
|
F: docs/devel/tcg-plugins.rst
|
||||||
F: plugins/
|
F: plugins/
|
||||||
F: tests/plugin/
|
F: tests/tcg/plugins/
|
||||||
F: tests/avocado/tcg_plugins.py
|
F: tests/avocado/tcg_plugins.py
|
||||||
F: contrib/plugins/
|
F: contrib/plugins/
|
||||||
|
|
||||||
|
@ -39,26 +39,41 @@ endif
|
|||||||
|
|
||||||
SONAMES := $(addsuffix $(SO_SUFFIX),$(addprefix lib,$(NAMES)))
|
SONAMES := $(addsuffix $(SO_SUFFIX),$(addprefix lib,$(NAMES)))
|
||||||
|
|
||||||
# The main QEMU uses Glib extensively so it's perfectly fine to use it
|
# The main QEMU uses Glib extensively so it is perfectly fine to use it
|
||||||
# in plugins (which many example do).
|
# in plugins (which many example do).
|
||||||
PLUGIN_CFLAGS := $(shell $(PKG_CONFIG) --cflags glib-2.0)
|
PLUGIN_CFLAGS := $(shell $(PKG_CONFIG) --cflags glib-2.0)
|
||||||
PLUGIN_CFLAGS += -fPIC -Wall
|
PLUGIN_CFLAGS += -fPIC -Wall
|
||||||
PLUGIN_CFLAGS += -I$(TOP_SRC_PATH)/include/qemu
|
PLUGIN_CFLAGS += -I$(TOP_SRC_PATH)/include/qemu
|
||||||
|
|
||||||
|
# Helper that honours V=1 so we get some output when compiling
|
||||||
|
quiet-@ = $(if $(V),,@$(if $1,printf " %-7s %s\n" "$(strip $1)" "$(strip $2)" && ))
|
||||||
|
quiet-command = $(call quiet-@,$2,$3)$1
|
||||||
|
|
||||||
|
# for including , in command strings
|
||||||
|
COMMA := ,
|
||||||
|
|
||||||
all: $(SONAMES)
|
all: $(SONAMES)
|
||||||
|
|
||||||
%.o: %.c
|
%.o: %.c
|
||||||
$(CC) $(CFLAGS) $(PLUGIN_CFLAGS) -c -o $@ $<
|
$(call quiet-command, \
|
||||||
|
$(CC) $(CFLAGS) $(PLUGIN_CFLAGS) -c -o $@ $<, \
|
||||||
|
BUILD, plugin $@)
|
||||||
|
|
||||||
ifeq ($(CONFIG_WIN32),y)
|
ifeq ($(CONFIG_WIN32),y)
|
||||||
lib%$(SO_SUFFIX): %.o win32_linker.o ../../plugins/libqemu_plugin_api.a
|
lib%$(SO_SUFFIX): %.o win32_linker.o ../../plugins/libqemu_plugin_api.a
|
||||||
$(CC) -shared -o $@ $^ $(LDLIBS)
|
$(call quiet-command, \
|
||||||
|
$(CC) -shared -o $@ $^ $(LDLIBS), \
|
||||||
|
LINK, plugin $@)
|
||||||
else ifeq ($(CONFIG_DARWIN),y)
|
else ifeq ($(CONFIG_DARWIN),y)
|
||||||
lib%$(SO_SUFFIX): %.o
|
lib%$(SO_SUFFIX): %.o
|
||||||
$(CC) -bundle -Wl,-undefined,dynamic_lookup -o $@ $^ $(LDLIBS)
|
$(call quiet-command, \
|
||||||
|
$(CC) -bundle -Wl$(COMMA)-undefined$(COMMA)dynamic_lookup -o $@ $^ $(LDLIBS), \
|
||||||
|
LINK, plugin $@)
|
||||||
else
|
else
|
||||||
lib%$(SO_SUFFIX): %.o
|
lib%$(SO_SUFFIX): %.o
|
||||||
$(CC) -shared -o $@ $^ $(LDLIBS)
|
$(call quiet-command, \
|
||||||
|
$(CC) -shared -o $@ $^ $(LDLIBS), \
|
||||||
|
LINK, plugin $@)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
|
||||||
|
@ -558,7 +558,7 @@ static void append_stats_line(GString *line,
|
|||||||
" %-12" PRIu64 " %-11" PRIu64 " %10.4lf%%",
|
" %-12" PRIu64 " %-11" PRIu64 " %10.4lf%%",
|
||||||
l2_access,
|
l2_access,
|
||||||
l2_misses,
|
l2_misses,
|
||||||
l2_access ? l2_miss_rate : 0.0);
|
l2_miss_rate);
|
||||||
}
|
}
|
||||||
|
|
||||||
g_string_append(line, "\n");
|
g_string_append(line, "\n");
|
||||||
|
@ -101,6 +101,31 @@ static void plugin_exit(qemu_plugin_id_t id, void *p)
|
|||||||
plugin_cleanup(id);
|
plugin_cleanup(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* g_memdup has been deprecated in Glib since 2.68 and
|
||||||
|
* will complain about it if you try to use it. However until
|
||||||
|
* glib_req_ver for QEMU is bumped we make a copy of the glib-compat
|
||||||
|
* handler.
|
||||||
|
*/
|
||||||
|
static inline gpointer g_memdup2_qemu(gconstpointer mem, gsize byte_size)
|
||||||
|
{
|
||||||
|
#if GLIB_CHECK_VERSION(2, 68, 0)
|
||||||
|
return g_memdup2(mem, byte_size);
|
||||||
|
#else
|
||||||
|
gpointer new_mem;
|
||||||
|
|
||||||
|
if (mem && byte_size != 0) {
|
||||||
|
new_mem = g_malloc(byte_size);
|
||||||
|
memcpy(new_mem, mem, byte_size);
|
||||||
|
} else {
|
||||||
|
new_mem = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new_mem;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#define g_memdup2(m, s) g_memdup2_qemu(m, s)
|
||||||
|
|
||||||
static void report_divergance(ExecState *us, ExecState *them)
|
static void report_divergance(ExecState *us, ExecState *them)
|
||||||
{
|
{
|
||||||
DivergeState divrec = { log, 0 };
|
DivergeState divrec = { log, 0 };
|
||||||
|
@ -95,9 +95,6 @@ depending on the guest architecture.
|
|||||||
- Yes
|
- Yes
|
||||||
- A configurable 32 bit soft core now owned by Cadence
|
- A configurable 32 bit soft core now owned by Cadence
|
||||||
|
|
||||||
A number of features are only available when running under
|
|
||||||
emulation including :ref:`Record/Replay<replay>` and :ref:`TCG Plugins`.
|
|
||||||
|
|
||||||
.. _Semihosting:
|
.. _Semihosting:
|
||||||
|
|
||||||
Semihosting
|
Semihosting
|
||||||
@ -182,3 +179,567 @@ for that architecture.
|
|||||||
* - Xtensa
|
* - Xtensa
|
||||||
- System
|
- System
|
||||||
- Tensilica ISS SIMCALL
|
- Tensilica ISS SIMCALL
|
||||||
|
|
||||||
|
TCG Plugins
|
||||||
|
-----------
|
||||||
|
|
||||||
|
QEMU TCG plugins provide a way for users to run experiments taking
|
||||||
|
advantage of the total system control emulation can have over a guest.
|
||||||
|
It provides a mechanism for plugins to subscribe to events during
|
||||||
|
translation and execution and optionally callback into the plugin
|
||||||
|
during these events. TCG plugins are unable to change the system state
|
||||||
|
only monitor it passively. However they can do this down to an
|
||||||
|
individual instruction granularity including potentially subscribing
|
||||||
|
to all load and store operations.
|
||||||
|
|
||||||
|
See the developer section of the manual for details about
|
||||||
|
:ref:`writing plugins<TCG Plugins>`.
|
||||||
|
|
||||||
|
Usage
|
||||||
|
~~~~~
|
||||||
|
|
||||||
|
Any QEMU binary with TCG support has plugins enabled by default.
|
||||||
|
Earlier releases needed to be explicitly enabled with::
|
||||||
|
|
||||||
|
configure --enable-plugins
|
||||||
|
|
||||||
|
Once built a program can be run with multiple plugins loaded each with
|
||||||
|
their own arguments::
|
||||||
|
|
||||||
|
$QEMU $OTHER_QEMU_ARGS \
|
||||||
|
-plugin contrib/plugin/libhowvec.so,inline=on,count=hint \
|
||||||
|
-plugin contrib/plugin/libhotblocks.so
|
||||||
|
|
||||||
|
Arguments are plugin specific and can be used to modify their
|
||||||
|
behaviour. In this case the howvec plugin is being asked to use inline
|
||||||
|
ops to count and break down the hint instructions by type.
|
||||||
|
|
||||||
|
Linux user-mode emulation also evaluates the environment variable
|
||||||
|
``QEMU_PLUGIN``::
|
||||||
|
|
||||||
|
QEMU_PLUGIN="file=contrib/plugins/libhowvec.so,inline=on,count=hint" $QEMU
|
||||||
|
|
||||||
|
Example Plugins
|
||||||
|
~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
There are a number of plugins included with QEMU and you are
|
||||||
|
encouraged to contribute your own plugins plugins upstream. There is a
|
||||||
|
``contrib/plugins`` directory where they can go. There are also some
|
||||||
|
basic plugins that are used to test and exercise the API during the
|
||||||
|
``make check-tcg`` target in ``tests/tcg/plugins`` that are never the
|
||||||
|
less useful for basic analysis.
|
||||||
|
|
||||||
|
Empty
|
||||||
|
.....
|
||||||
|
|
||||||
|
``tests/tcg/plugins/empty.c``
|
||||||
|
|
||||||
|
Purely a test plugin for measuring the overhead of the plugins system
|
||||||
|
itself. Does no instrumentation.
|
||||||
|
|
||||||
|
Basic Blocks
|
||||||
|
............
|
||||||
|
|
||||||
|
``tests/tcg/plugins/bb.c``
|
||||||
|
|
||||||
|
A very basic plugin which will measure execution in coarse terms as
|
||||||
|
each basic block is executed. By default the results are shown once
|
||||||
|
execution finishes::
|
||||||
|
|
||||||
|
$ qemu-aarch64 -plugin tests/plugin/libbb.so \
|
||||||
|
-d plugin ./tests/tcg/aarch64-linux-user/sha1
|
||||||
|
SHA1=15dd99a1991e0b3826fede3deffc1feba42278e6
|
||||||
|
bb's: 2277338, insns: 158483046
|
||||||
|
|
||||||
|
Behaviour can be tweaked with the following arguments:
|
||||||
|
|
||||||
|
.. list-table:: Basic Block plugin arguments
|
||||||
|
:widths: 20 80
|
||||||
|
:header-rows: 1
|
||||||
|
|
||||||
|
* - Option
|
||||||
|
- Description
|
||||||
|
* - inline=true|false
|
||||||
|
- Use faster inline addition of a single counter. Not per-cpu and not
|
||||||
|
thread safe.
|
||||||
|
* - idle=true|false
|
||||||
|
- Dump the current execution stats whenever the guest vCPU idles
|
||||||
|
|
||||||
|
Instruction
|
||||||
|
...........
|
||||||
|
|
||||||
|
``tests/tcg/plugins/insn.c``
|
||||||
|
|
||||||
|
This is a basic instruction level instrumentation which can count the
|
||||||
|
number of instructions executed on each core/thread::
|
||||||
|
|
||||||
|
$ qemu-aarch64 -plugin tests/plugin/libinsn.so \
|
||||||
|
-d plugin ./tests/tcg/aarch64-linux-user/threadcount
|
||||||
|
Created 10 threads
|
||||||
|
Done
|
||||||
|
cpu 0 insns: 46765
|
||||||
|
cpu 1 insns: 3694
|
||||||
|
cpu 2 insns: 3694
|
||||||
|
cpu 3 insns: 2994
|
||||||
|
cpu 4 insns: 1497
|
||||||
|
cpu 5 insns: 1497
|
||||||
|
cpu 6 insns: 1497
|
||||||
|
cpu 7 insns: 1497
|
||||||
|
total insns: 63135
|
||||||
|
|
||||||
|
Behaviour can be tweaked with the following arguments:
|
||||||
|
|
||||||
|
.. list-table:: Instruction plugin arguments
|
||||||
|
:widths: 20 80
|
||||||
|
:header-rows: 1
|
||||||
|
|
||||||
|
* - Option
|
||||||
|
- Description
|
||||||
|
* - inline=true|false
|
||||||
|
- Use faster inline addition of a single counter.
|
||||||
|
* - sizes=true|false
|
||||||
|
- Give a summary of the instruction sizes for the execution
|
||||||
|
* - match=<string>
|
||||||
|
- Only instrument instructions matching the string prefix
|
||||||
|
|
||||||
|
The ``match`` option will show some basic stats including how many
|
||||||
|
instructions have executed since the last execution. For
|
||||||
|
example::
|
||||||
|
|
||||||
|
$ qemu-aarch64 -plugin tests/plugin/libinsn.so,match=bl \
|
||||||
|
-d plugin ./tests/tcg/aarch64-linux-user/sha512-vector
|
||||||
|
...
|
||||||
|
0x40069c, 'bl #0x4002b0', 10 hits, 1093 match hits, Δ+1257 since last match, 98 avg insns/match
|
||||||
|
0x4006ac, 'bl #0x403690', 10 hits, 1094 match hits, Δ+47 since last match, 98 avg insns/match
|
||||||
|
0x4037fc, 'bl #0x4002b0', 18 hits, 1095 match hits, Δ+22 since last match, 98 avg insns/match
|
||||||
|
0x400720, 'bl #0x403690', 10 hits, 1096 match hits, Δ+58 since last match, 98 avg insns/match
|
||||||
|
0x4037fc, 'bl #0x4002b0', 19 hits, 1097 match hits, Δ+22 since last match, 98 avg insns/match
|
||||||
|
0x400730, 'bl #0x403690', 10 hits, 1098 match hits, Δ+33 since last match, 98 avg insns/match
|
||||||
|
0x4037ac, 'bl #0x4002b0', 12 hits, 1099 match hits, Δ+20 since last match, 98 avg insns/match
|
||||||
|
...
|
||||||
|
|
||||||
|
For more detailed execution tracing see the ``execlog`` plugin for
|
||||||
|
other options.
|
||||||
|
|
||||||
|
Memory
|
||||||
|
......
|
||||||
|
|
||||||
|
``tests/tcg/plugins/mem.c``
|
||||||
|
|
||||||
|
Basic instruction level memory instrumentation::
|
||||||
|
|
||||||
|
$ qemu-aarch64 -plugin tests/plugin/libmem.so,inline=true \
|
||||||
|
-d plugin ./tests/tcg/aarch64-linux-user/sha1
|
||||||
|
SHA1=15dd99a1991e0b3826fede3deffc1feba42278e6
|
||||||
|
inline mem accesses: 79525013
|
||||||
|
|
||||||
|
Behaviour can be tweaked with the following arguments:
|
||||||
|
|
||||||
|
.. list-table:: Memory plugin arguments
|
||||||
|
:widths: 20 80
|
||||||
|
:header-rows: 1
|
||||||
|
|
||||||
|
* - Option
|
||||||
|
- Description
|
||||||
|
* - inline=true|false
|
||||||
|
- Use faster inline addition of a single counter
|
||||||
|
* - callback=true|false
|
||||||
|
- Use callbacks on each memory instrumentation.
|
||||||
|
* - hwaddr=true|false
|
||||||
|
- Count IO accesses (only for system emulation)
|
||||||
|
|
||||||
|
System Calls
|
||||||
|
............
|
||||||
|
|
||||||
|
``tests/tcg/plugins/syscall.c``
|
||||||
|
|
||||||
|
A basic syscall tracing plugin. This only works for user-mode. By
|
||||||
|
default it will give a summary of syscall stats at the end of the
|
||||||
|
run::
|
||||||
|
|
||||||
|
$ qemu-aarch64 -plugin tests/plugin/libsyscall \
|
||||||
|
-d plugin ./tests/tcg/aarch64-linux-user/threadcount
|
||||||
|
Created 10 threads
|
||||||
|
Done
|
||||||
|
syscall no. calls errors
|
||||||
|
226 12 0
|
||||||
|
99 11 11
|
||||||
|
115 11 0
|
||||||
|
222 11 0
|
||||||
|
93 10 0
|
||||||
|
220 10 0
|
||||||
|
233 10 0
|
||||||
|
215 8 0
|
||||||
|
214 4 0
|
||||||
|
134 2 0
|
||||||
|
64 2 0
|
||||||
|
96 1 0
|
||||||
|
94 1 0
|
||||||
|
80 1 0
|
||||||
|
261 1 0
|
||||||
|
78 1 0
|
||||||
|
160 1 0
|
||||||
|
135 1 0
|
||||||
|
|
||||||
|
Hot Blocks
|
||||||
|
..........
|
||||||
|
|
||||||
|
``contrib/plugins/hotblocks.c``
|
||||||
|
|
||||||
|
The hotblocks plugin allows you to examine the where hot paths of
|
||||||
|
execution are in your program. Once the program has finished you will
|
||||||
|
get a sorted list of blocks reporting the starting PC, translation
|
||||||
|
count, number of instructions and execution count. This will work best
|
||||||
|
with linux-user execution as system emulation tends to generate
|
||||||
|
re-translations as blocks from different programs get swapped in and
|
||||||
|
out of system memory.
|
||||||
|
|
||||||
|
If your program is single-threaded you can use the ``inline`` option for
|
||||||
|
slightly faster (but not thread safe) counters.
|
||||||
|
|
||||||
|
Example::
|
||||||
|
|
||||||
|
$ qemu-aarch64 \
|
||||||
|
-plugin contrib/plugins/libhotblocks.so -d plugin \
|
||||||
|
./tests/tcg/aarch64-linux-user/sha1
|
||||||
|
SHA1=15dd99a1991e0b3826fede3deffc1feba42278e6
|
||||||
|
collected 903 entries in the hash table
|
||||||
|
pc, tcount, icount, ecount
|
||||||
|
0x0000000041ed10, 1, 5, 66087
|
||||||
|
0x000000004002b0, 1, 4, 66087
|
||||||
|
...
|
||||||
|
|
||||||
|
|
||||||
|
Hot Pages
|
||||||
|
.........
|
||||||
|
|
||||||
|
``contrib/plugins/hotpages.c``
|
||||||
|
|
||||||
|
Similar to hotblocks but this time tracks memory accesses::
|
||||||
|
|
||||||
|
$ qemu-aarch64 \
|
||||||
|
-plugin contrib/plugins/libhotpages.so -d plugin \
|
||||||
|
./tests/tcg/aarch64-linux-user/sha1
|
||||||
|
SHA1=15dd99a1991e0b3826fede3deffc1feba42278e6
|
||||||
|
Addr, RCPUs, Reads, WCPUs, Writes
|
||||||
|
0x000055007fe000, 0x0001, 31747952, 0x0001, 8835161
|
||||||
|
0x000055007ff000, 0x0001, 29001054, 0x0001, 8780625
|
||||||
|
0x00005500800000, 0x0001, 687465, 0x0001, 335857
|
||||||
|
0x0000000048b000, 0x0001, 130594, 0x0001, 355
|
||||||
|
0x0000000048a000, 0x0001, 1826, 0x0001, 11
|
||||||
|
|
||||||
|
The hotpages plugin can be configured using the following arguments:
|
||||||
|
|
||||||
|
.. list-table:: Hot pages arguments
|
||||||
|
:widths: 20 80
|
||||||
|
:header-rows: 1
|
||||||
|
|
||||||
|
* - Option
|
||||||
|
- Description
|
||||||
|
* - sortby=reads|writes|address
|
||||||
|
- Log the data sorted by either the number of reads, the number of writes, or
|
||||||
|
memory address. (Default: entries are sorted by the sum of reads and writes)
|
||||||
|
* - io=on
|
||||||
|
- Track IO addresses. Only relevant to full system emulation. (Default: off)
|
||||||
|
* - pagesize=N
|
||||||
|
- The page size used. (Default: N = 4096)
|
||||||
|
|
||||||
|
Instruction Distribution
|
||||||
|
........................
|
||||||
|
|
||||||
|
``contrib/plugins/howvec.c``
|
||||||
|
|
||||||
|
This is an instruction classifier so can be used to count different
|
||||||
|
types of instructions. It has a number of options to refine which get
|
||||||
|
counted. You can give a value to the ``count`` argument for a class of
|
||||||
|
instructions to break it down fully, so for example to see all the system
|
||||||
|
registers accesses::
|
||||||
|
|
||||||
|
$ qemu-system-aarch64 $(QEMU_ARGS) \
|
||||||
|
-append "root=/dev/sda2 systemd.unit=benchmark.service" \
|
||||||
|
-smp 4 -plugin ./contrib/plugins/libhowvec.so,count=sreg -d plugin
|
||||||
|
|
||||||
|
which will lead to a sorted list after the class breakdown::
|
||||||
|
|
||||||
|
Instruction Classes:
|
||||||
|
Class: UDEF not counted
|
||||||
|
Class: SVE (68 hits)
|
||||||
|
Class: PCrel addr (47789483 hits)
|
||||||
|
Class: Add/Sub (imm) (192817388 hits)
|
||||||
|
Class: Logical (imm) (93852565 hits)
|
||||||
|
Class: Move Wide (imm) (76398116 hits)
|
||||||
|
Class: Bitfield (44706084 hits)
|
||||||
|
Class: Extract (5499257 hits)
|
||||||
|
Class: Cond Branch (imm) (147202932 hits)
|
||||||
|
Class: Exception Gen (193581 hits)
|
||||||
|
Class: NOP not counted
|
||||||
|
Class: Hints (6652291 hits)
|
||||||
|
Class: Barriers (8001661 hits)
|
||||||
|
Class: PSTATE (1801695 hits)
|
||||||
|
Class: System Insn (6385349 hits)
|
||||||
|
Class: System Reg counted individually
|
||||||
|
Class: Branch (reg) (69497127 hits)
|
||||||
|
Class: Branch (imm) (84393665 hits)
|
||||||
|
Class: Cmp & Branch (110929659 hits)
|
||||||
|
Class: Tst & Branch (44681442 hits)
|
||||||
|
Class: AdvSimd ldstmult (736 hits)
|
||||||
|
Class: ldst excl (9098783 hits)
|
||||||
|
Class: Load Reg (lit) (87189424 hits)
|
||||||
|
Class: ldst noalloc pair (3264433 hits)
|
||||||
|
Class: ldst pair (412526434 hits)
|
||||||
|
Class: ldst reg (imm) (314734576 hits)
|
||||||
|
Class: Loads & Stores (2117774 hits)
|
||||||
|
Class: Data Proc Reg (223519077 hits)
|
||||||
|
Class: Scalar FP (31657954 hits)
|
||||||
|
Individual Instructions:
|
||||||
|
Instr: mrs x0, sp_el0 (2682661 hits) (op=0xd5384100/ System Reg)
|
||||||
|
Instr: mrs x1, tpidr_el2 (1789339 hits) (op=0xd53cd041/ System Reg)
|
||||||
|
Instr: mrs x2, tpidr_el2 (1513494 hits) (op=0xd53cd042/ System Reg)
|
||||||
|
Instr: mrs x0, tpidr_el2 (1490823 hits) (op=0xd53cd040/ System Reg)
|
||||||
|
Instr: mrs x1, sp_el0 (933793 hits) (op=0xd5384101/ System Reg)
|
||||||
|
Instr: mrs x2, sp_el0 (699516 hits) (op=0xd5384102/ System Reg)
|
||||||
|
Instr: mrs x4, tpidr_el2 (528437 hits) (op=0xd53cd044/ System Reg)
|
||||||
|
Instr: mrs x30, ttbr1_el1 (480776 hits) (op=0xd538203e/ System Reg)
|
||||||
|
Instr: msr ttbr1_el1, x30 (480713 hits) (op=0xd518203e/ System Reg)
|
||||||
|
Instr: msr vbar_el1, x30 (480671 hits) (op=0xd518c01e/ System Reg)
|
||||||
|
...
|
||||||
|
|
||||||
|
To find the argument shorthand for the class you need to examine the
|
||||||
|
source code of the plugin at the moment, specifically the ``*opt``
|
||||||
|
argument in the InsnClassExecCount tables.
|
||||||
|
|
||||||
|
Lockstep Execution
|
||||||
|
..................
|
||||||
|
|
||||||
|
``contrib/plugins/lockstep.c``
|
||||||
|
|
||||||
|
This is a debugging tool for developers who want to find out when and
|
||||||
|
where execution diverges after a subtle change to TCG code generation.
|
||||||
|
It is not an exact science and results are likely to be mixed once
|
||||||
|
asynchronous events are introduced. While the use of -icount can
|
||||||
|
introduce determinism to the execution flow it doesn't always follow
|
||||||
|
the translation sequence will be exactly the same. Typically this is
|
||||||
|
caused by a timer firing to service the GUI causing a block to end
|
||||||
|
early. However in some cases it has proved to be useful in pointing
|
||||||
|
people at roughly where execution diverges. The only argument you need
|
||||||
|
for the plugin is a path for the socket the two instances will
|
||||||
|
communicate over::
|
||||||
|
|
||||||
|
|
||||||
|
$ qemu-system-sparc -monitor none -parallel none \
|
||||||
|
-net none -M SS-20 -m 256 -kernel day11/zImage.elf \
|
||||||
|
-plugin ./contrib/plugins/liblockstep.so,sockpath=lockstep-sparc.sock \
|
||||||
|
-d plugin,nochain
|
||||||
|
|
||||||
|
which will eventually report::
|
||||||
|
|
||||||
|
qemu-system-sparc: warning: nic lance.0 has no peer
|
||||||
|
@ 0x000000ffd06678 vs 0x000000ffd001e0 (2/1 since last)
|
||||||
|
@ 0x000000ffd07d9c vs 0x000000ffd06678 (3/1 since last)
|
||||||
|
Δ insn_count @ 0x000000ffd07d9c (809900609) vs 0x000000ffd06678 (809900612)
|
||||||
|
previously @ 0x000000ffd06678/10 (809900609 insns)
|
||||||
|
previously @ 0x000000ffd001e0/4 (809900599 insns)
|
||||||
|
previously @ 0x000000ffd080ac/2 (809900595 insns)
|
||||||
|
previously @ 0x000000ffd08098/5 (809900593 insns)
|
||||||
|
previously @ 0x000000ffd080c0/1 (809900588 insns)
|
||||||
|
|
||||||
|
|
||||||
|
Hardware Profile
|
||||||
|
................
|
||||||
|
|
||||||
|
``contrib/plugins/hwprofile.c``
|
||||||
|
|
||||||
|
The hwprofile tool can only be used with system emulation and allows
|
||||||
|
the user to see what hardware is accessed how often. It has a number of options:
|
||||||
|
|
||||||
|
.. list-table:: Hardware Profile arguments
|
||||||
|
:widths: 20 80
|
||||||
|
:header-rows: 1
|
||||||
|
|
||||||
|
* - Option
|
||||||
|
- Description
|
||||||
|
* - track=[read|write]
|
||||||
|
- By default the plugin tracks both reads and writes. You can use
|
||||||
|
this option to limit the tracking to just one class of accesses.
|
||||||
|
* - source
|
||||||
|
- Will include a detailed break down of what the guest PC that made the
|
||||||
|
access was. Not compatible with the pattern option. Example output::
|
||||||
|
|
||||||
|
cirrus-low-memory @ 0xfffffd00000a0000
|
||||||
|
pc:fffffc0000005cdc, 1, 256
|
||||||
|
pc:fffffc0000005ce8, 1, 256
|
||||||
|
pc:fffffc0000005cec, 1, 256
|
||||||
|
|
||||||
|
* - pattern
|
||||||
|
- Instead break down the accesses based on the offset into the HW
|
||||||
|
region. This can be useful for seeing the most used registers of
|
||||||
|
a device. Example output::
|
||||||
|
|
||||||
|
pci0-conf @ 0xfffffd01fe000000
|
||||||
|
off:00000004, 1, 1
|
||||||
|
off:00000010, 1, 3
|
||||||
|
off:00000014, 1, 3
|
||||||
|
off:00000018, 1, 2
|
||||||
|
off:0000001c, 1, 2
|
||||||
|
off:00000020, 1, 2
|
||||||
|
...
|
||||||
|
|
||||||
|
|
||||||
|
Execution Log
|
||||||
|
.............
|
||||||
|
|
||||||
|
``contrib/plugins/execlog.c``
|
||||||
|
|
||||||
|
The execlog tool traces executed instructions with memory access. It can be used
|
||||||
|
for debugging and security analysis purposes.
|
||||||
|
Please be aware that this will generate a lot of output.
|
||||||
|
|
||||||
|
The plugin needs default argument::
|
||||||
|
|
||||||
|
$ qemu-system-arm $(QEMU_ARGS) \
|
||||||
|
-plugin ./contrib/plugins/libexeclog.so -d plugin
|
||||||
|
|
||||||
|
which will output an execution trace following this structure::
|
||||||
|
|
||||||
|
# vCPU, vAddr, opcode, disassembly[, load/store, memory addr, device]...
|
||||||
|
0, 0xa12, 0xf8012400, "movs r4, #0"
|
||||||
|
0, 0xa14, 0xf87f42b4, "cmp r4, r6"
|
||||||
|
0, 0xa16, 0xd206, "bhs #0xa26"
|
||||||
|
0, 0xa18, 0xfff94803, "ldr r0, [pc, #0xc]", load, 0x00010a28, RAM
|
||||||
|
0, 0xa1a, 0xf989f000, "bl #0xd30"
|
||||||
|
0, 0xd30, 0xfff9b510, "push {r4, lr}", store, 0x20003ee0, RAM, store, 0x20003ee4, RAM
|
||||||
|
0, 0xd32, 0xf9893014, "adds r0, #0x14"
|
||||||
|
0, 0xd34, 0xf9c8f000, "bl #0x10c8"
|
||||||
|
0, 0x10c8, 0xfff96c43, "ldr r3, [r0, #0x44]", load, 0x200000e4, RAM
|
||||||
|
|
||||||
|
Please note that you need to configure QEMU with Capstone support to get disassembly.
|
||||||
|
|
||||||
|
The output can be filtered to only track certain instructions or
|
||||||
|
addresses using the ``ifilter`` or ``afilter`` options. You can stack the
|
||||||
|
arguments if required::
|
||||||
|
|
||||||
|
$ qemu-system-arm $(QEMU_ARGS) \
|
||||||
|
-plugin ./contrib/plugins/libexeclog.so,ifilter=st1w,afilter=0x40001808 -d plugin
|
||||||
|
|
||||||
|
This plugin can also dump registers when they change value. Specify the name of the
|
||||||
|
registers with multiple ``reg`` options. You can also use glob style matching if you wish::
|
||||||
|
|
||||||
|
$ qemu-system-arm $(QEMU_ARGS) \
|
||||||
|
-plugin ./contrib/plugins/libexeclog.so,reg=\*_el2,reg=sp -d plugin
|
||||||
|
|
||||||
|
Be aware that each additional register to check will slow down
|
||||||
|
execution quite considerably. You can optimise the number of register
|
||||||
|
checks done by using the rdisas option. This will only instrument
|
||||||
|
instructions that mention the registers in question in disassembly.
|
||||||
|
This is not foolproof as some instructions implicitly change
|
||||||
|
instructions. You can use the ifilter to catch these cases::
|
||||||
|
|
||||||
|
$ qemu-system-arm $(QEMU_ARGS) \
|
||||||
|
-plugin ./contrib/plugins/libexeclog.so,ifilter=msr,ifilter=blr,reg=x30,reg=\*_el1,rdisas=on
|
||||||
|
|
||||||
|
Cache Modelling
|
||||||
|
...............
|
||||||
|
|
||||||
|
``contrib/plugins/cache.c``
|
||||||
|
|
||||||
|
Cache modelling plugin that measures the performance of a given L1 cache
|
||||||
|
configuration, and optionally a unified L2 per-core cache when a given working
|
||||||
|
set is run::
|
||||||
|
|
||||||
|
$ qemu-x86_64 -plugin ./contrib/plugins/libcache.so \
|
||||||
|
-d plugin -D cache.log ./tests/tcg/x86_64-linux-user/float_convs
|
||||||
|
|
||||||
|
will report the following::
|
||||||
|
|
||||||
|
core #, data accesses, data misses, dmiss rate, insn accesses, insn misses, imiss rate
|
||||||
|
0 996695 508 0.0510% 2642799 18617 0.7044%
|
||||||
|
|
||||||
|
address, data misses, instruction
|
||||||
|
0x424f1e (_int_malloc), 109, movq %rax, 8(%rcx)
|
||||||
|
0x41f395 (_IO_default_xsputn), 49, movb %dl, (%rdi, %rax)
|
||||||
|
0x42584d (ptmalloc_init.part.0), 33, movaps %xmm0, (%rax)
|
||||||
|
0x454d48 (__tunables_init), 20, cmpb $0, (%r8)
|
||||||
|
...
|
||||||
|
|
||||||
|
address, fetch misses, instruction
|
||||||
|
0x4160a0 (__vfprintf_internal), 744, movl $1, %ebx
|
||||||
|
0x41f0a0 (_IO_setb), 744, endbr64
|
||||||
|
0x415882 (__vfprintf_internal), 744, movq %r12, %rdi
|
||||||
|
0x4268a0 (__malloc), 696, andq $0xfffffffffffffff0, %rax
|
||||||
|
...
|
||||||
|
|
||||||
|
The plugin has a number of arguments, all of them are optional:
|
||||||
|
|
||||||
|
.. list-table:: Cache modelling arguments
|
||||||
|
:widths: 20 80
|
||||||
|
:header-rows: 1
|
||||||
|
|
||||||
|
* - Option
|
||||||
|
- Description
|
||||||
|
* - limit=N
|
||||||
|
- Print top N icache and dcache thrashing instructions along with
|
||||||
|
their address, number of misses, and its disassembly. (default: 32)
|
||||||
|
* - icachesize=N
|
||||||
|
iblksize=B
|
||||||
|
iassoc=A
|
||||||
|
- Instruction cache configuration arguments. They specify the
|
||||||
|
cache size, block size, and associativity of the instruction
|
||||||
|
cache, respectively. (default: N = 16384, B = 64, A = 8)
|
||||||
|
* - dcachesize=N
|
||||||
|
- Data cache size (default: 16834)
|
||||||
|
* - dblksize=B
|
||||||
|
- Data cache block size (default: 64)
|
||||||
|
* - dassoc=A
|
||||||
|
- Data cache associativity (default: 8)
|
||||||
|
* - evict=POLICY
|
||||||
|
- Sets the eviction policy to POLICY. Available policies are:
|
||||||
|
``lru``, ``fifo``, and ``rand``. The plugin will use
|
||||||
|
the specified policy for both instruction and data caches.
|
||||||
|
(default: POLICY = ``lru``)
|
||||||
|
* - cores=N
|
||||||
|
- Sets the number of cores for which we maintain separate icache
|
||||||
|
and dcache. (default: for linux-user, N = 1, for full system
|
||||||
|
emulation: N = cores available to guest)
|
||||||
|
* - l2=on
|
||||||
|
- Simulates a unified L2 cache (stores blocks for both
|
||||||
|
instructions and data) using the default L2 configuration (cache
|
||||||
|
size = 2MB, associativity = 16-way, block size = 64B).
|
||||||
|
* - l2cachesize=N
|
||||||
|
- L2 cache size (default: 2097152 (2MB)), implies ``l2=on``
|
||||||
|
* - l2blksize=B
|
||||||
|
- L2 cache block size (default: 64), implies ``l2=on``
|
||||||
|
* - l2assoc=A
|
||||||
|
- L2 cache associativity (default: 16), implies ``l2=on``
|
||||||
|
|
||||||
|
Stop on Trigger
|
||||||
|
...............
|
||||||
|
|
||||||
|
``contrib/plugins/stoptrigger.c``
|
||||||
|
|
||||||
|
The stoptrigger plugin allows to setup triggers to stop emulation.
|
||||||
|
It can be used for research purposes to launch some code and precisely stop it
|
||||||
|
and understand where its execution flow went.
|
||||||
|
|
||||||
|
Two types of triggers can be configured: a count of instructions to stop at,
|
||||||
|
or an address to stop at. Multiple triggers can be set at once.
|
||||||
|
|
||||||
|
By default, QEMU will exit with return code 0. A custom return code can be
|
||||||
|
configured for each trigger using ``:CODE`` syntax.
|
||||||
|
|
||||||
|
For example, to stop at the 20-th instruction with return code 41, at address
|
||||||
|
0xd4 with return code 0 or at address 0xd8 with return code 42::
|
||||||
|
|
||||||
|
$ qemu-system-aarch64 $(QEMU_ARGS) \
|
||||||
|
-plugin ./contrib/plugins/libstoptrigger.so,icount=20:41,addr=0xd4,addr=0xd8:42 -d plugin
|
||||||
|
|
||||||
|
The plugin will log the reason of exit, for example::
|
||||||
|
|
||||||
|
0xd4 reached, exiting
|
||||||
|
|
||||||
|
Other emulation features
|
||||||
|
------------------------
|
||||||
|
|
||||||
|
When running system emulation you can also enable deterministic
|
||||||
|
execution which allows for repeatable record/replay debugging. See
|
||||||
|
:ref:`Record/Replay<replay>` for more details.
|
||||||
|
|
||||||
|
@ -8,38 +8,6 @@
|
|||||||
QEMU TCG Plugins
|
QEMU TCG Plugins
|
||||||
================
|
================
|
||||||
|
|
||||||
QEMU TCG plugins provide a way for users to run experiments taking
|
|
||||||
advantage of the total system control emulation can have over a guest.
|
|
||||||
It provides a mechanism for plugins to subscribe to events during
|
|
||||||
translation and execution and optionally callback into the plugin
|
|
||||||
during these events. TCG plugins are unable to change the system state
|
|
||||||
only monitor it passively. However they can do this down to an
|
|
||||||
individual instruction granularity including potentially subscribing
|
|
||||||
to all load and store operations.
|
|
||||||
|
|
||||||
Usage
|
|
||||||
-----
|
|
||||||
|
|
||||||
Any QEMU binary with TCG support has plugins enabled by default.
|
|
||||||
Earlier releases needed to be explicitly enabled with::
|
|
||||||
|
|
||||||
configure --enable-plugins
|
|
||||||
|
|
||||||
Once built a program can be run with multiple plugins loaded each with
|
|
||||||
their own arguments::
|
|
||||||
|
|
||||||
$QEMU $OTHER_QEMU_ARGS \
|
|
||||||
-plugin contrib/plugin/libhowvec.so,inline=on,count=hint \
|
|
||||||
-plugin contrib/plugin/libhotblocks.so
|
|
||||||
|
|
||||||
Arguments are plugin specific and can be used to modify their
|
|
||||||
behaviour. In this case the howvec plugin is being asked to use inline
|
|
||||||
ops to count and break down the hint instructions by type.
|
|
||||||
|
|
||||||
Linux user-mode emulation also evaluates the environment variable
|
|
||||||
``QEMU_PLUGIN``::
|
|
||||||
|
|
||||||
QEMU_PLUGIN="file=contrib/plugins/libhowvec.so,inline=on,count=hint" $QEMU
|
|
||||||
|
|
||||||
Writing plugins
|
Writing plugins
|
||||||
---------------
|
---------------
|
||||||
@ -191,479 +159,6 @@ which means callbacks may still occur after the uninstall operation is
|
|||||||
requested. The plugin isn't completely uninstalled until the safe work
|
requested. The plugin isn't completely uninstalled until the safe work
|
||||||
has executed while all vCPUs are quiescent.
|
has executed while all vCPUs are quiescent.
|
||||||
|
|
||||||
Example Plugins
|
|
||||||
===============
|
|
||||||
|
|
||||||
There are a number of plugins included with QEMU and you are
|
|
||||||
encouraged to contribute your own plugins plugins upstream. There is a
|
|
||||||
``contrib/plugins`` directory where they can go. There are also some
|
|
||||||
basic plugins that are used to test and exercise the API during the
|
|
||||||
``make check-tcg`` target in ``tests\plugins``.
|
|
||||||
|
|
||||||
- tests/plugins/empty.c
|
|
||||||
|
|
||||||
Purely a test plugin for measuring the overhead of the plugins system
|
|
||||||
itself. Does no instrumentation.
|
|
||||||
|
|
||||||
- tests/plugins/bb.c
|
|
||||||
|
|
||||||
A very basic plugin which will measure execution in course terms as
|
|
||||||
each basic block is executed. By default the results are shown once
|
|
||||||
execution finishes::
|
|
||||||
|
|
||||||
$ qemu-aarch64 -plugin tests/plugin/libbb.so \
|
|
||||||
-d plugin ./tests/tcg/aarch64-linux-user/sha1
|
|
||||||
SHA1=15dd99a1991e0b3826fede3deffc1feba42278e6
|
|
||||||
bb's: 2277338, insns: 158483046
|
|
||||||
|
|
||||||
Behaviour can be tweaked with the following arguments:
|
|
||||||
|
|
||||||
* inline=true|false
|
|
||||||
|
|
||||||
Use faster inline addition of a single counter. Not per-cpu and not
|
|
||||||
thread safe.
|
|
||||||
|
|
||||||
* idle=true|false
|
|
||||||
|
|
||||||
Dump the current execution stats whenever the guest vCPU idles
|
|
||||||
|
|
||||||
- tests/plugins/insn.c
|
|
||||||
|
|
||||||
This is a basic instruction level instrumentation which can count the
|
|
||||||
number of instructions executed on each core/thread::
|
|
||||||
|
|
||||||
$ qemu-aarch64 -plugin tests/plugin/libinsn.so \
|
|
||||||
-d plugin ./tests/tcg/aarch64-linux-user/threadcount
|
|
||||||
Created 10 threads
|
|
||||||
Done
|
|
||||||
cpu 0 insns: 46765
|
|
||||||
cpu 1 insns: 3694
|
|
||||||
cpu 2 insns: 3694
|
|
||||||
cpu 3 insns: 2994
|
|
||||||
cpu 4 insns: 1497
|
|
||||||
cpu 5 insns: 1497
|
|
||||||
cpu 6 insns: 1497
|
|
||||||
cpu 7 insns: 1497
|
|
||||||
total insns: 63135
|
|
||||||
|
|
||||||
Behaviour can be tweaked with the following arguments:
|
|
||||||
|
|
||||||
* inline=true|false
|
|
||||||
|
|
||||||
Use faster inline addition of a single counter. Not per-cpu and not
|
|
||||||
thread safe.
|
|
||||||
|
|
||||||
* sizes=true|false
|
|
||||||
|
|
||||||
Give a summary of the instruction sizes for the execution
|
|
||||||
|
|
||||||
* match=<string>
|
|
||||||
|
|
||||||
Only instrument instructions matching the string prefix. Will show
|
|
||||||
some basic stats including how many instructions have executed since
|
|
||||||
the last execution. For example::
|
|
||||||
|
|
||||||
$ qemu-aarch64 -plugin tests/plugin/libinsn.so,match=bl \
|
|
||||||
-d plugin ./tests/tcg/aarch64-linux-user/sha512-vector
|
|
||||||
...
|
|
||||||
0x40069c, 'bl #0x4002b0', 10 hits, 1093 match hits, Δ+1257 since last match, 98 avg insns/match
|
|
||||||
0x4006ac, 'bl #0x403690', 10 hits, 1094 match hits, Δ+47 since last match, 98 avg insns/match
|
|
||||||
0x4037fc, 'bl #0x4002b0', 18 hits, 1095 match hits, Δ+22 since last match, 98 avg insns/match
|
|
||||||
0x400720, 'bl #0x403690', 10 hits, 1096 match hits, Δ+58 since last match, 98 avg insns/match
|
|
||||||
0x4037fc, 'bl #0x4002b0', 19 hits, 1097 match hits, Δ+22 since last match, 98 avg insns/match
|
|
||||||
0x400730, 'bl #0x403690', 10 hits, 1098 match hits, Δ+33 since last match, 98 avg insns/match
|
|
||||||
0x4037ac, 'bl #0x4002b0', 12 hits, 1099 match hits, Δ+20 since last match, 98 avg insns/match
|
|
||||||
...
|
|
||||||
|
|
||||||
For more detailed execution tracing see the ``execlog`` plugin for
|
|
||||||
other options.
|
|
||||||
|
|
||||||
- tests/plugins/mem.c
|
|
||||||
|
|
||||||
Basic instruction level memory instrumentation::
|
|
||||||
|
|
||||||
$ qemu-aarch64 -plugin tests/plugin/libmem.so,inline=true \
|
|
||||||
-d plugin ./tests/tcg/aarch64-linux-user/sha1
|
|
||||||
SHA1=15dd99a1991e0b3826fede3deffc1feba42278e6
|
|
||||||
inline mem accesses: 79525013
|
|
||||||
|
|
||||||
Behaviour can be tweaked with the following arguments:
|
|
||||||
|
|
||||||
* inline=true|false
|
|
||||||
|
|
||||||
Use faster inline addition of a single counter. Not per-cpu and not
|
|
||||||
thread safe.
|
|
||||||
|
|
||||||
* callback=true|false
|
|
||||||
|
|
||||||
Use callbacks on each memory instrumentation.
|
|
||||||
|
|
||||||
* hwaddr=true|false
|
|
||||||
|
|
||||||
Count IO accesses (only for system emulation)
|
|
||||||
|
|
||||||
- tests/plugins/syscall.c
|
|
||||||
|
|
||||||
A basic syscall tracing plugin. This only works for user-mode. By
|
|
||||||
default it will give a summary of syscall stats at the end of the
|
|
||||||
run::
|
|
||||||
|
|
||||||
$ qemu-aarch64 -plugin tests/plugin/libsyscall \
|
|
||||||
-d plugin ./tests/tcg/aarch64-linux-user/threadcount
|
|
||||||
Created 10 threads
|
|
||||||
Done
|
|
||||||
syscall no. calls errors
|
|
||||||
226 12 0
|
|
||||||
99 11 11
|
|
||||||
115 11 0
|
|
||||||
222 11 0
|
|
||||||
93 10 0
|
|
||||||
220 10 0
|
|
||||||
233 10 0
|
|
||||||
215 8 0
|
|
||||||
214 4 0
|
|
||||||
134 2 0
|
|
||||||
64 2 0
|
|
||||||
96 1 0
|
|
||||||
94 1 0
|
|
||||||
80 1 0
|
|
||||||
261 1 0
|
|
||||||
78 1 0
|
|
||||||
160 1 0
|
|
||||||
135 1 0
|
|
||||||
|
|
||||||
- contrib/plugins/hotblocks.c
|
|
||||||
|
|
||||||
The hotblocks plugin allows you to examine the where hot paths of
|
|
||||||
execution are in your program. Once the program has finished you will
|
|
||||||
get a sorted list of blocks reporting the starting PC, translation
|
|
||||||
count, number of instructions and execution count. This will work best
|
|
||||||
with linux-user execution as system emulation tends to generate
|
|
||||||
re-translations as blocks from different programs get swapped in and
|
|
||||||
out of system memory.
|
|
||||||
|
|
||||||
If your program is single-threaded you can use the ``inline`` option for
|
|
||||||
slightly faster (but not thread safe) counters.
|
|
||||||
|
|
||||||
Example::
|
|
||||||
|
|
||||||
$ qemu-aarch64 \
|
|
||||||
-plugin contrib/plugins/libhotblocks.so -d plugin \
|
|
||||||
./tests/tcg/aarch64-linux-user/sha1
|
|
||||||
SHA1=15dd99a1991e0b3826fede3deffc1feba42278e6
|
|
||||||
collected 903 entries in the hash table
|
|
||||||
pc, tcount, icount, ecount
|
|
||||||
0x0000000041ed10, 1, 5, 66087
|
|
||||||
0x000000004002b0, 1, 4, 66087
|
|
||||||
...
|
|
||||||
|
|
||||||
- contrib/plugins/hotpages.c
|
|
||||||
|
|
||||||
Similar to hotblocks but this time tracks memory accesses::
|
|
||||||
|
|
||||||
$ qemu-aarch64 \
|
|
||||||
-plugin contrib/plugins/libhotpages.so -d plugin \
|
|
||||||
./tests/tcg/aarch64-linux-user/sha1
|
|
||||||
SHA1=15dd99a1991e0b3826fede3deffc1feba42278e6
|
|
||||||
Addr, RCPUs, Reads, WCPUs, Writes
|
|
||||||
0x000055007fe000, 0x0001, 31747952, 0x0001, 8835161
|
|
||||||
0x000055007ff000, 0x0001, 29001054, 0x0001, 8780625
|
|
||||||
0x00005500800000, 0x0001, 687465, 0x0001, 335857
|
|
||||||
0x0000000048b000, 0x0001, 130594, 0x0001, 355
|
|
||||||
0x0000000048a000, 0x0001, 1826, 0x0001, 11
|
|
||||||
|
|
||||||
The hotpages plugin can be configured using the following arguments:
|
|
||||||
|
|
||||||
* sortby=reads|writes|address
|
|
||||||
|
|
||||||
Log the data sorted by either the number of reads, the number of writes, or
|
|
||||||
memory address. (Default: entries are sorted by the sum of reads and writes)
|
|
||||||
|
|
||||||
* io=on
|
|
||||||
|
|
||||||
Track IO addresses. Only relevant to full system emulation. (Default: off)
|
|
||||||
|
|
||||||
* pagesize=N
|
|
||||||
|
|
||||||
The page size used. (Default: N = 4096)
|
|
||||||
|
|
||||||
- contrib/plugins/howvec.c
|
|
||||||
|
|
||||||
This is an instruction classifier so can be used to count different
|
|
||||||
types of instructions. It has a number of options to refine which get
|
|
||||||
counted. You can give a value to the ``count`` argument for a class of
|
|
||||||
instructions to break it down fully, so for example to see all the system
|
|
||||||
registers accesses::
|
|
||||||
|
|
||||||
$ qemu-system-aarch64 $(QEMU_ARGS) \
|
|
||||||
-append "root=/dev/sda2 systemd.unit=benchmark.service" \
|
|
||||||
-smp 4 -plugin ./contrib/plugins/libhowvec.so,count=sreg -d plugin
|
|
||||||
|
|
||||||
which will lead to a sorted list after the class breakdown::
|
|
||||||
|
|
||||||
Instruction Classes:
|
|
||||||
Class: UDEF not counted
|
|
||||||
Class: SVE (68 hits)
|
|
||||||
Class: PCrel addr (47789483 hits)
|
|
||||||
Class: Add/Sub (imm) (192817388 hits)
|
|
||||||
Class: Logical (imm) (93852565 hits)
|
|
||||||
Class: Move Wide (imm) (76398116 hits)
|
|
||||||
Class: Bitfield (44706084 hits)
|
|
||||||
Class: Extract (5499257 hits)
|
|
||||||
Class: Cond Branch (imm) (147202932 hits)
|
|
||||||
Class: Exception Gen (193581 hits)
|
|
||||||
Class: NOP not counted
|
|
||||||
Class: Hints (6652291 hits)
|
|
||||||
Class: Barriers (8001661 hits)
|
|
||||||
Class: PSTATE (1801695 hits)
|
|
||||||
Class: System Insn (6385349 hits)
|
|
||||||
Class: System Reg counted individually
|
|
||||||
Class: Branch (reg) (69497127 hits)
|
|
||||||
Class: Branch (imm) (84393665 hits)
|
|
||||||
Class: Cmp & Branch (110929659 hits)
|
|
||||||
Class: Tst & Branch (44681442 hits)
|
|
||||||
Class: AdvSimd ldstmult (736 hits)
|
|
||||||
Class: ldst excl (9098783 hits)
|
|
||||||
Class: Load Reg (lit) (87189424 hits)
|
|
||||||
Class: ldst noalloc pair (3264433 hits)
|
|
||||||
Class: ldst pair (412526434 hits)
|
|
||||||
Class: ldst reg (imm) (314734576 hits)
|
|
||||||
Class: Loads & Stores (2117774 hits)
|
|
||||||
Class: Data Proc Reg (223519077 hits)
|
|
||||||
Class: Scalar FP (31657954 hits)
|
|
||||||
Individual Instructions:
|
|
||||||
Instr: mrs x0, sp_el0 (2682661 hits) (op=0xd5384100/ System Reg)
|
|
||||||
Instr: mrs x1, tpidr_el2 (1789339 hits) (op=0xd53cd041/ System Reg)
|
|
||||||
Instr: mrs x2, tpidr_el2 (1513494 hits) (op=0xd53cd042/ System Reg)
|
|
||||||
Instr: mrs x0, tpidr_el2 (1490823 hits) (op=0xd53cd040/ System Reg)
|
|
||||||
Instr: mrs x1, sp_el0 (933793 hits) (op=0xd5384101/ System Reg)
|
|
||||||
Instr: mrs x2, sp_el0 (699516 hits) (op=0xd5384102/ System Reg)
|
|
||||||
Instr: mrs x4, tpidr_el2 (528437 hits) (op=0xd53cd044/ System Reg)
|
|
||||||
Instr: mrs x30, ttbr1_el1 (480776 hits) (op=0xd538203e/ System Reg)
|
|
||||||
Instr: msr ttbr1_el1, x30 (480713 hits) (op=0xd518203e/ System Reg)
|
|
||||||
Instr: msr vbar_el1, x30 (480671 hits) (op=0xd518c01e/ System Reg)
|
|
||||||
...
|
|
||||||
|
|
||||||
To find the argument shorthand for the class you need to examine the
|
|
||||||
source code of the plugin at the moment, specifically the ``*opt``
|
|
||||||
argument in the InsnClassExecCount tables.
|
|
||||||
|
|
||||||
- contrib/plugins/lockstep.c
|
|
||||||
|
|
||||||
This is a debugging tool for developers who want to find out when and
|
|
||||||
where execution diverges after a subtle change to TCG code generation.
|
|
||||||
It is not an exact science and results are likely to be mixed once
|
|
||||||
asynchronous events are introduced. While the use of -icount can
|
|
||||||
introduce determinism to the execution flow it doesn't always follow
|
|
||||||
the translation sequence will be exactly the same. Typically this is
|
|
||||||
caused by a timer firing to service the GUI causing a block to end
|
|
||||||
early. However in some cases it has proved to be useful in pointing
|
|
||||||
people at roughly where execution diverges. The only argument you need
|
|
||||||
for the plugin is a path for the socket the two instances will
|
|
||||||
communicate over::
|
|
||||||
|
|
||||||
|
|
||||||
$ qemu-system-sparc -monitor none -parallel none \
|
|
||||||
-net none -M SS-20 -m 256 -kernel day11/zImage.elf \
|
|
||||||
-plugin ./contrib/plugins/liblockstep.so,sockpath=lockstep-sparc.sock \
|
|
||||||
-d plugin,nochain
|
|
||||||
|
|
||||||
which will eventually report::
|
|
||||||
|
|
||||||
qemu-system-sparc: warning: nic lance.0 has no peer
|
|
||||||
@ 0x000000ffd06678 vs 0x000000ffd001e0 (2/1 since last)
|
|
||||||
@ 0x000000ffd07d9c vs 0x000000ffd06678 (3/1 since last)
|
|
||||||
Δ insn_count @ 0x000000ffd07d9c (809900609) vs 0x000000ffd06678 (809900612)
|
|
||||||
previously @ 0x000000ffd06678/10 (809900609 insns)
|
|
||||||
previously @ 0x000000ffd001e0/4 (809900599 insns)
|
|
||||||
previously @ 0x000000ffd080ac/2 (809900595 insns)
|
|
||||||
previously @ 0x000000ffd08098/5 (809900593 insns)
|
|
||||||
previously @ 0x000000ffd080c0/1 (809900588 insns)
|
|
||||||
|
|
||||||
- contrib/plugins/hwprofile.c
|
|
||||||
|
|
||||||
The hwprofile tool can only be used with system emulation and allows
|
|
||||||
the user to see what hardware is accessed how often. It has a number of options:
|
|
||||||
|
|
||||||
* track=read or track=write
|
|
||||||
|
|
||||||
By default the plugin tracks both reads and writes. You can use one
|
|
||||||
of these options to limit the tracking to just one class of accesses.
|
|
||||||
|
|
||||||
* source
|
|
||||||
|
|
||||||
Will include a detailed break down of what the guest PC that made the
|
|
||||||
access was. Not compatible with the pattern option. Example output::
|
|
||||||
|
|
||||||
cirrus-low-memory @ 0xfffffd00000a0000
|
|
||||||
pc:fffffc0000005cdc, 1, 256
|
|
||||||
pc:fffffc0000005ce8, 1, 256
|
|
||||||
pc:fffffc0000005cec, 1, 256
|
|
||||||
|
|
||||||
* pattern
|
|
||||||
|
|
||||||
Instead break down the accesses based on the offset into the HW
|
|
||||||
region. This can be useful for seeing the most used registers of a
|
|
||||||
device. Example output::
|
|
||||||
|
|
||||||
pci0-conf @ 0xfffffd01fe000000
|
|
||||||
off:00000004, 1, 1
|
|
||||||
off:00000010, 1, 3
|
|
||||||
off:00000014, 1, 3
|
|
||||||
off:00000018, 1, 2
|
|
||||||
off:0000001c, 1, 2
|
|
||||||
off:00000020, 1, 2
|
|
||||||
...
|
|
||||||
|
|
||||||
- contrib/plugins/execlog.c
|
|
||||||
|
|
||||||
The execlog tool traces executed instructions with memory access. It can be used
|
|
||||||
for debugging and security analysis purposes.
|
|
||||||
Please be aware that this will generate a lot of output.
|
|
||||||
|
|
||||||
The plugin needs default argument::
|
|
||||||
|
|
||||||
$ qemu-system-arm $(QEMU_ARGS) \
|
|
||||||
-plugin ./contrib/plugins/libexeclog.so -d plugin
|
|
||||||
|
|
||||||
which will output an execution trace following this structure::
|
|
||||||
|
|
||||||
# vCPU, vAddr, opcode, disassembly[, load/store, memory addr, device]...
|
|
||||||
0, 0xa12, 0xf8012400, "movs r4, #0"
|
|
||||||
0, 0xa14, 0xf87f42b4, "cmp r4, r6"
|
|
||||||
0, 0xa16, 0xd206, "bhs #0xa26"
|
|
||||||
0, 0xa18, 0xfff94803, "ldr r0, [pc, #0xc]", load, 0x00010a28, RAM
|
|
||||||
0, 0xa1a, 0xf989f000, "bl #0xd30"
|
|
||||||
0, 0xd30, 0xfff9b510, "push {r4, lr}", store, 0x20003ee0, RAM, store, 0x20003ee4, RAM
|
|
||||||
0, 0xd32, 0xf9893014, "adds r0, #0x14"
|
|
||||||
0, 0xd34, 0xf9c8f000, "bl #0x10c8"
|
|
||||||
0, 0x10c8, 0xfff96c43, "ldr r3, [r0, #0x44]", load, 0x200000e4, RAM
|
|
||||||
|
|
||||||
Please note that you need to configure QEMU with Capstone support to get disassembly.
|
|
||||||
|
|
||||||
The output can be filtered to only track certain instructions or
|
|
||||||
addresses using the ``ifilter`` or ``afilter`` options. You can stack the
|
|
||||||
arguments if required::
|
|
||||||
|
|
||||||
$ qemu-system-arm $(QEMU_ARGS) \
|
|
||||||
-plugin ./contrib/plugins/libexeclog.so,ifilter=st1w,afilter=0x40001808 -d plugin
|
|
||||||
|
|
||||||
This plugin can also dump registers when they change value. Specify the name of the
|
|
||||||
registers with multiple ``reg`` options. You can also use glob style matching if you wish::
|
|
||||||
|
|
||||||
$ qemu-system-arm $(QEMU_ARGS) \
|
|
||||||
-plugin ./contrib/plugins/libexeclog.so,reg=\*_el2,reg=sp -d plugin
|
|
||||||
|
|
||||||
Be aware that each additional register to check will slow down
|
|
||||||
execution quite considerably. You can optimise the number of register
|
|
||||||
checks done by using the rdisas option. This will only instrument
|
|
||||||
instructions that mention the registers in question in disassembly.
|
|
||||||
This is not foolproof as some instructions implicitly change
|
|
||||||
instructions. You can use the ifilter to catch these cases:
|
|
||||||
|
|
||||||
$ qemu-system-arm $(QEMU_ARGS) \
|
|
||||||
-plugin ./contrib/plugins/libexeclog.so,ifilter=msr,ifilter=blr,reg=x30,reg=\*_el1,rdisas=on
|
|
||||||
|
|
||||||
- contrib/plugins/cache.c
|
|
||||||
|
|
||||||
Cache modelling plugin that measures the performance of a given L1 cache
|
|
||||||
configuration, and optionally a unified L2 per-core cache when a given working
|
|
||||||
set is run::
|
|
||||||
|
|
||||||
$ qemu-x86_64 -plugin ./contrib/plugins/libcache.so \
|
|
||||||
-d plugin -D cache.log ./tests/tcg/x86_64-linux-user/float_convs
|
|
||||||
|
|
||||||
will report the following::
|
|
||||||
|
|
||||||
core #, data accesses, data misses, dmiss rate, insn accesses, insn misses, imiss rate
|
|
||||||
0 996695 508 0.0510% 2642799 18617 0.7044%
|
|
||||||
|
|
||||||
address, data misses, instruction
|
|
||||||
0x424f1e (_int_malloc), 109, movq %rax, 8(%rcx)
|
|
||||||
0x41f395 (_IO_default_xsputn), 49, movb %dl, (%rdi, %rax)
|
|
||||||
0x42584d (ptmalloc_init.part.0), 33, movaps %xmm0, (%rax)
|
|
||||||
0x454d48 (__tunables_init), 20, cmpb $0, (%r8)
|
|
||||||
...
|
|
||||||
|
|
||||||
address, fetch misses, instruction
|
|
||||||
0x4160a0 (__vfprintf_internal), 744, movl $1, %ebx
|
|
||||||
0x41f0a0 (_IO_setb), 744, endbr64
|
|
||||||
0x415882 (__vfprintf_internal), 744, movq %r12, %rdi
|
|
||||||
0x4268a0 (__malloc), 696, andq $0xfffffffffffffff0, %rax
|
|
||||||
...
|
|
||||||
|
|
||||||
The plugin has a number of arguments, all of them are optional:
|
|
||||||
|
|
||||||
* limit=N
|
|
||||||
|
|
||||||
Print top N icache and dcache thrashing instructions along with their
|
|
||||||
address, number of misses, and its disassembly. (default: 32)
|
|
||||||
|
|
||||||
* icachesize=N
|
|
||||||
* iblksize=B
|
|
||||||
* iassoc=A
|
|
||||||
|
|
||||||
Instruction cache configuration arguments. They specify the cache size, block
|
|
||||||
size, and associativity of the instruction cache, respectively.
|
|
||||||
(default: N = 16384, B = 64, A = 8)
|
|
||||||
|
|
||||||
* dcachesize=N
|
|
||||||
* dblksize=B
|
|
||||||
* dassoc=A
|
|
||||||
|
|
||||||
Data cache configuration arguments. They specify the cache size, block size,
|
|
||||||
and associativity of the data cache, respectively.
|
|
||||||
(default: N = 16384, B = 64, A = 8)
|
|
||||||
|
|
||||||
* evict=POLICY
|
|
||||||
|
|
||||||
Sets the eviction policy to POLICY. Available policies are: :code:`lru`,
|
|
||||||
:code:`fifo`, and :code:`rand`. The plugin will use the specified policy for
|
|
||||||
both instruction and data caches. (default: POLICY = :code:`lru`)
|
|
||||||
|
|
||||||
* cores=N
|
|
||||||
|
|
||||||
Sets the number of cores for which we maintain separate icache and dcache.
|
|
||||||
(default: for linux-user, N = 1, for full system emulation: N = cores
|
|
||||||
available to guest)
|
|
||||||
|
|
||||||
* l2=on
|
|
||||||
|
|
||||||
Simulates a unified L2 cache (stores blocks for both instructions and data)
|
|
||||||
using the default L2 configuration (cache size = 2MB, associativity = 16-way,
|
|
||||||
block size = 64B).
|
|
||||||
|
|
||||||
* l2cachesize=N
|
|
||||||
* l2blksize=B
|
|
||||||
* l2assoc=A
|
|
||||||
|
|
||||||
L2 cache configuration arguments. They specify the cache size, block size, and
|
|
||||||
associativity of the L2 cache, respectively. Setting any of the L2
|
|
||||||
configuration arguments implies ``l2=on``.
|
|
||||||
(default: N = 2097152 (2MB), B = 64, A = 16)
|
|
||||||
|
|
||||||
- contrib/plugins/stoptrigger.c
|
|
||||||
|
|
||||||
The stoptrigger plugin allows to setup triggers to stop emulation.
|
|
||||||
It can be used for research purposes to launch some code and precisely stop it
|
|
||||||
and understand where its execution flow went.
|
|
||||||
|
|
||||||
Two types of triggers can be configured: a count of instructions to stop at,
|
|
||||||
or an address to stop at. Multiple triggers can be set at once.
|
|
||||||
|
|
||||||
By default, QEMU will exit with return code 0. A custom return code can be
|
|
||||||
configured for each trigger using ``:CODE`` syntax.
|
|
||||||
|
|
||||||
For example, to stop at the 20-th instruction with return code 41, at address
|
|
||||||
0xd4 with return code 0 or at address 0xd8 with return code 42::
|
|
||||||
|
|
||||||
$ qemu-system-aarch64 $(QEMU_ARGS) \
|
|
||||||
-plugin ./contrib/plugins/libstoptrigger.so,icount=20:41,addr=0xd4,addr=0xd8:42 -d plugin
|
|
||||||
|
|
||||||
The plugin will log the reason of exit, for example::
|
|
||||||
|
|
||||||
0xd4 reached, exiting
|
|
||||||
|
|
||||||
Plugin API
|
Plugin API
|
||||||
==========
|
==========
|
||||||
|
|
||||||
|
@ -3,13 +3,28 @@
|
|||||||
Testing in QEMU
|
Testing in QEMU
|
||||||
===============
|
===============
|
||||||
|
|
||||||
This document describes the testing infrastructure in QEMU.
|
QEMU's testing infrastructure is fairly complex as it covers
|
||||||
|
everything from unit testing and exercising specific sub-systems all
|
||||||
|
the way to full blown acceptance tests. To get an overview of the
|
||||||
|
tests you can run ``make check-help`` from either the source or build
|
||||||
|
tree.
|
||||||
|
|
||||||
|
Most (but not all) tests are also integrated into the meson build
|
||||||
|
system so can be run directly from the build tree, for example:
|
||||||
|
|
||||||
|
.. code::
|
||||||
|
|
||||||
|
[./pyvenv/bin/]meson test --suite qemu:softfloat
|
||||||
|
|
||||||
|
will run just the softfloat tests.
|
||||||
|
|
||||||
|
The rest of this document will cover the details for specific test
|
||||||
|
groups.
|
||||||
|
|
||||||
Testing with "make check"
|
Testing with "make check"
|
||||||
-------------------------
|
-------------------------
|
||||||
|
|
||||||
The "make check" testing family includes most of the C based tests in QEMU. For
|
The "make check" testing family includes most of the C based tests in QEMU.
|
||||||
a quick help, run ``make check-help`` from the source tree.
|
|
||||||
|
|
||||||
The usual way to run these tests is:
|
The usual way to run these tests is:
|
||||||
|
|
||||||
@ -1475,6 +1490,19 @@ And run with::
|
|||||||
Adding ``V=1`` to the invocation will show the details of how to
|
Adding ``V=1`` to the invocation will show the details of how to
|
||||||
invoke QEMU for the test which is useful for debugging tests.
|
invoke QEMU for the test which is useful for debugging tests.
|
||||||
|
|
||||||
|
Running individual tests
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Tests can also be run directly from the test build directory. If you
|
||||||
|
run ``make help`` from the test build directory you will get a list of
|
||||||
|
all the tests that can be run. Please note that same binaries are used
|
||||||
|
in multiple tests, for example::
|
||||||
|
|
||||||
|
make run-plugin-test-mmap-with-libinline.so
|
||||||
|
|
||||||
|
will run the mmap test with the ``libinline.so`` TCG plugin. The
|
||||||
|
gdbstub tests also re-use the test binaries but while exercising gdb.
|
||||||
|
|
||||||
TCG test dependencies
|
TCG test dependencies
|
||||||
~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
#include "qemu/osdep.h"
|
#include "qemu/osdep.h"
|
||||||
#include "qemu/error-report.h"
|
#include "qemu/error-report.h"
|
||||||
#include "qemu/config-file.h"
|
#include "qemu/config-file.h"
|
||||||
|
#include "qemu/help_option.h"
|
||||||
#include "qapi/error.h"
|
#include "qapi/error.h"
|
||||||
#include "qemu/lockable.h"
|
#include "qemu/lockable.h"
|
||||||
#include "qemu/option.h"
|
#include "qemu/option.h"
|
||||||
@ -98,7 +99,12 @@ static int plugin_add(void *opaque, const char *name, const char *value,
|
|||||||
bool is_on;
|
bool is_on;
|
||||||
char *fullarg;
|
char *fullarg;
|
||||||
|
|
||||||
if (strcmp(name, "file") == 0) {
|
if (is_help_option(value)) {
|
||||||
|
printf("Plugin options\n");
|
||||||
|
printf(" file=<path/to/plugin.so>\n");
|
||||||
|
printf(" plugin specific arguments\n");
|
||||||
|
exit(0);
|
||||||
|
} else if (strcmp(name, "file") == 0) {
|
||||||
if (strcmp(value, "") == 0) {
|
if (strcmp(value, "") == 0) {
|
||||||
error_setg(errp, "requires a non-empty argument");
|
error_setg(errp, "requires a non-empty argument");
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -77,7 +77,7 @@ class PluginKernelNormal(PluginKernelBase):
|
|||||||
suffix=".log")
|
suffix=".log")
|
||||||
|
|
||||||
self.run_vm(kernel_path, kernel_command_line,
|
self.run_vm(kernel_path, kernel_command_line,
|
||||||
"tests/plugin/libinsn.so", plugin_log.name,
|
"tests/tcg/plugins/libinsn.so", plugin_log.name,
|
||||||
console_pattern)
|
console_pattern)
|
||||||
|
|
||||||
with plugin_log as lf, \
|
with plugin_log as lf, \
|
||||||
@ -107,7 +107,7 @@ class PluginKernelNormal(PluginKernelBase):
|
|||||||
suffix=".log")
|
suffix=".log")
|
||||||
|
|
||||||
self.run_vm(kernel_path, kernel_command_line,
|
self.run_vm(kernel_path, kernel_command_line,
|
||||||
"tests/plugin/libinsn.so", plugin_log.name,
|
"tests/tcg/plugins/libinsn.so", plugin_log.name,
|
||||||
console_pattern,
|
console_pattern,
|
||||||
args=('-icount', 'shift=1'))
|
args=('-icount', 'shift=1'))
|
||||||
|
|
||||||
@ -120,36 +120,3 @@ class PluginKernelNormal(PluginKernelBase):
|
|||||||
else:
|
else:
|
||||||
count = int(m.group("count"))
|
count = int(m.group("count"))
|
||||||
self.log.info(f"Counted: {count} instructions")
|
self.log.info(f"Counted: {count} instructions")
|
||||||
|
|
||||||
def test_aarch64_virt_mem_icount(self):
|
|
||||||
"""
|
|
||||||
:avocado: tags=accel:tcg
|
|
||||||
:avocado: tags=arch:aarch64
|
|
||||||
:avocado: tags=machine:virt
|
|
||||||
:avocado: tags=cpu:cortex-a53
|
|
||||||
"""
|
|
||||||
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,inline=true,callback=true", plugin_log.name,
|
|
||||||
console_pattern,
|
|
||||||
args=('-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")
|
|
||||||
else:
|
|
||||||
self.log.info(f"Counted {inline} memory accesses")
|
|
||||||
|
@ -62,7 +62,8 @@ RUN DEBIAN_FRONTEND=noninteractive eatmydata \
|
|||||||
gcc-s390x-linux-gnu \
|
gcc-s390x-linux-gnu \
|
||||||
libc6-dev-s390x-cross \
|
libc6-dev-s390x-cross \
|
||||||
gcc-sparc64-linux-gnu \
|
gcc-sparc64-linux-gnu \
|
||||||
libc6-dev-sparc64-cross
|
libc6-dev-sparc64-cross && \
|
||||||
|
dpkg-query --showformat '${Package}_${Version}_${Architecture}\n' --show > /packages.txt
|
||||||
|
|
||||||
|
|
||||||
ENV QEMU_CONFIGURE_OPTS --disable-system --disable-docs --disable-tools
|
ENV QEMU_CONFIGURE_OPTS --disable-system --disable-docs --disable-tools
|
||||||
|
@ -33,7 +33,8 @@ RUN apt-get update && \
|
|||||||
ln -s /usr/bin/ccache /usr/libexec/ccache-wrappers/c++ && \
|
ln -s /usr/bin/ccache /usr/libexec/ccache-wrappers/c++ && \
|
||||||
ln -s /usr/bin/ccache /usr/libexec/ccache-wrappers/cc && \
|
ln -s /usr/bin/ccache /usr/libexec/ccache-wrappers/cc && \
|
||||||
ln -s /usr/bin/ccache /usr/libexec/ccache-wrappers/g++ && \
|
ln -s /usr/bin/ccache /usr/libexec/ccache-wrappers/g++ && \
|
||||||
ln -s /usr/bin/ccache /usr/libexec/ccache-wrappers/gcc
|
ln -s /usr/bin/ccache /usr/libexec/ccache-wrappers/gcc && \
|
||||||
|
dpkg-query --showformat '${Package}_${Version}_${Architecture}\n' --show > /packages.txt
|
||||||
|
|
||||||
RUN /usr/bin/pip3 install tomli
|
RUN /usr/bin/pip3 install tomli
|
||||||
|
|
||||||
|
@ -36,7 +36,8 @@ RUN DEBIAN_FRONTEND=noninteractive eatmydata \
|
|||||||
python3-pip \
|
python3-pip \
|
||||||
python3-setuptools \
|
python3-setuptools \
|
||||||
python3-venv \
|
python3-venv \
|
||||||
python3-wheel
|
python3-wheel && \
|
||||||
|
dpkg-query --showformat '${Package}_${Version}_${Architecture}\n' --show > /packages.txt
|
||||||
|
|
||||||
RUN /usr/bin/pip3 install tomli
|
RUN /usr/bin/pip3 install tomli
|
||||||
|
|
||||||
|
@ -32,7 +32,8 @@ RUN apt-get update && \
|
|||||||
python3-pip \
|
python3-pip \
|
||||||
python3-setuptools \
|
python3-setuptools \
|
||||||
python3-venv \
|
python3-venv \
|
||||||
python3-wheel
|
python3-wheel && \
|
||||||
|
dpkg-query --showformat '${Package}_${Version}_${Architecture}\n' --show > /packages.txt
|
||||||
|
|
||||||
RUN /usr/bin/pip3 install tomli
|
RUN /usr/bin/pip3 install tomli
|
||||||
|
|
||||||
|
@ -34,7 +34,8 @@ RUN apt update && \
|
|||||||
python3-pip \
|
python3-pip \
|
||||||
python3-setuptools \
|
python3-setuptools \
|
||||||
python3-wheel \
|
python3-wheel \
|
||||||
python3-venv
|
python3-venv && \
|
||||||
|
dpkg-query --showformat '${Package}_${Version}_${Architecture}\n' --show > /packages.txt
|
||||||
|
|
||||||
RUN /usr/bin/pip3 install tomli
|
RUN /usr/bin/pip3 install tomli
|
||||||
|
|
||||||
|
@ -16,7 +16,8 @@ RUN apt-get update && \
|
|||||||
curl \
|
curl \
|
||||||
gettext \
|
gettext \
|
||||||
git \
|
git \
|
||||||
python3-minimal
|
python3-minimal && \
|
||||||
|
dpkg-query --showformat '${Package}_${Version}_${Architecture}\n' --show > /packages.txt
|
||||||
|
|
||||||
ENV CPU_LIST dc232b dc233c de233_fpu dsp3400
|
ENV CPU_LIST dc232b dc233c de233_fpu dsp3400
|
||||||
ENV TOOLCHAIN_RELEASE 2020.07
|
ENV TOOLCHAIN_RELEASE 2020.07
|
||||||
|
@ -78,7 +78,7 @@ subdir('decode')
|
|||||||
|
|
||||||
if 'CONFIG_TCG' in config_all_accel
|
if 'CONFIG_TCG' in config_all_accel
|
||||||
subdir('fp')
|
subdir('fp')
|
||||||
subdir('plugin')
|
subdir('tcg/plugins')
|
||||||
endif
|
endif
|
||||||
|
|
||||||
subdir('unit')
|
subdir('unit')
|
||||||
|
@ -115,7 +115,7 @@ endif
|
|||||||
%: %.c
|
%: %.c
|
||||||
$(CC) $(CFLAGS) $(EXTRA_CFLAGS) $< -o $@ $(LDFLAGS)
|
$(CC) $(CFLAGS) $(EXTRA_CFLAGS) $< -o $@ $(LDFLAGS)
|
||||||
%: %.S
|
%: %.S
|
||||||
$(CC) $(CFLAGS) $(EXTRA_CFLAGS) $< -o $@ $(LDFLAGS)
|
$(CC) $(CFLAGS) $(EXTRA_CFLAGS) -Wa,--noexecstack $< -o $@ $(LDFLAGS)
|
||||||
else
|
else
|
||||||
# For system targets we include a different Makefile fragment as the
|
# For system targets we include a different Makefile fragment as the
|
||||||
# build options for bare programs are usually pretty different. They
|
# build options for bare programs are usually pretty different. They
|
||||||
@ -142,8 +142,8 @@ RUN_TESTS=$(patsubst %,run-%, $(TESTS))
|
|||||||
|
|
||||||
# If plugins exist also include those in the tests
|
# If plugins exist also include those in the tests
|
||||||
ifeq ($(CONFIG_PLUGIN),y)
|
ifeq ($(CONFIG_PLUGIN),y)
|
||||||
PLUGIN_SRC=$(SRC_PATH)/tests/plugin
|
PLUGIN_SRC=$(SRC_PATH)/tests/tcg/plugins
|
||||||
PLUGIN_LIB=../../plugin
|
PLUGIN_LIB=../plugins
|
||||||
VPATH+=$(PLUGIN_LIB)
|
VPATH+=$(PLUGIN_LIB)
|
||||||
PLUGINS=$(patsubst %.c, lib%.so, $(notdir $(wildcard $(PLUGIN_SRC)/*.c)))
|
PLUGINS=$(patsubst %.c, lib%.so, $(notdir $(wildcard $(PLUGIN_SRC)/*.c)))
|
||||||
|
|
||||||
|
@ -1,9 +1,14 @@
|
|||||||
This directory contains various interesting guest programs for
|
This directory contains various interesting guest binaries for
|
||||||
regression testing. Tests are either multi-arch, meaning they can be
|
regression testing the Tiny Code Generator doing system and user-mode
|
||||||
built for all guest architectures that support linux-user executable,
|
emulation.
|
||||||
or they are architecture specific.
|
|
||||||
|
|
||||||
CRIS
|
The multiarch directory contains shared code for tests that can be
|
||||||
====
|
built for all guest architectures. Architecture specific code can be
|
||||||
The testsuite for CRIS is in tests/tcg/cris. You can run it
|
found in their respective directories.
|
||||||
with "make test-cris".
|
|
||||||
|
System mode tests will be under the "system" subdirectories.
|
||||||
|
|
||||||
|
GDB scripts for exercising the gdbstub on specific tests will be found
|
||||||
|
under the "gdbstb" subdirectories.
|
||||||
|
|
||||||
|
See the developer guide for more instructions on "make check-tcg"
|
||||||
|
@ -28,7 +28,7 @@ config-cc.mak: Makefile
|
|||||||
.PRECIOUS: $(CRT_OBJS)
|
.PRECIOUS: $(CRT_OBJS)
|
||||||
|
|
||||||
%.o: $(CRT_PATH)/%.S
|
%.o: $(CRT_PATH)/%.S
|
||||||
$(CC) $(CFLAGS) $(EXTRA_CFLAGS) -x assembler-with-cpp -c $< -o $@
|
$(CC) $(CFLAGS) $(EXTRA_CFLAGS) -x assembler-with-cpp -Wa,--noexecstack -c $< -o $@
|
||||||
|
|
||||||
# Build and link the tests
|
# Build and link the tests
|
||||||
%: %.c $(LINK_SCRIPT) $(CRT_OBJS) $(MINILIB_OBJS)
|
%: %.c $(LINK_SCRIPT) $(CRT_OBJS) $(MINILIB_OBJS)
|
||||||
|
@ -22,7 +22,7 @@ LDFLAGS+=-static -nostdlib $(CRT_OBJS) $(MINILIB_OBJS) -lgcc
|
|||||||
.PRECIOUS: $(CRT_OBJS)
|
.PRECIOUS: $(CRT_OBJS)
|
||||||
|
|
||||||
%.o: $(CRT_PATH)/%.S
|
%.o: $(CRT_PATH)/%.S
|
||||||
$(CC) $(CFLAGS) $(EXTRA_CFLAGS) -x assembler-with-cpp -c $< -o $@
|
$(CC) $(CFLAGS) $(EXTRA_CFLAGS) -x assembler-with-cpp -Wa,--noexecstack -c $< -o $@
|
||||||
|
|
||||||
# Build and link the tests
|
# Build and link the tests
|
||||||
%: %.c $(LINK_SCRIPT) $(CRT_OBJS) $(MINILIB_OBJS)
|
%: %.c $(LINK_SCRIPT) $(CRT_OBJS) $(MINILIB_OBJS)
|
||||||
|
@ -36,7 +36,7 @@ LDFLAGS+=-static -nostdlib $(CRT_OBJS) $(MINILIB_OBJS) -lgcc
|
|||||||
.PRECIOUS: $(CRT_OBJS)
|
.PRECIOUS: $(CRT_OBJS)
|
||||||
|
|
||||||
%.o: $(ARM_SRC)/%.S
|
%.o: $(ARM_SRC)/%.S
|
||||||
$(CC) $(CFLAGS) $(EXTRA_CFLAGS) -x assembler-with-cpp -c $< -o $@
|
$(CC) $(CFLAGS) $(EXTRA_CFLAGS) -x assembler-with-cpp -Wa,--noexecstack -c $< -o $@
|
||||||
|
|
||||||
# Build and link the tests
|
# Build and link the tests
|
||||||
%: %.c $(LINK_SCRIPT) $(CRT_OBJS) $(MINILIB_OBJS)
|
%: %.c $(LINK_SCRIPT) $(CRT_OBJS) $(MINILIB_OBJS)
|
||||||
|
@ -25,7 +25,7 @@ ARM_TESTS += test-arm-iwmmxt
|
|||||||
# Clang assembler does not support IWMXT, so use the external assembler.
|
# Clang assembler does not support IWMXT, so use the external assembler.
|
||||||
test-arm-iwmmxt: CFLAGS += -marm -march=iwmmxt -mabi=aapcs -mfpu=fpv4-sp-d16 $(CROSS_CC_HAS_FNIA)
|
test-arm-iwmmxt: CFLAGS += -marm -march=iwmmxt -mabi=aapcs -mfpu=fpv4-sp-d16 $(CROSS_CC_HAS_FNIA)
|
||||||
test-arm-iwmmxt: test-arm-iwmmxt.S
|
test-arm-iwmmxt: test-arm-iwmmxt.S
|
||||||
$(CC) $(CFLAGS) $< -o $@ $(LDFLAGS)
|
$(CC) $(CFLAGS) -Wa,--noexecstack $< -o $@ $(LDFLAGS)
|
||||||
|
|
||||||
# Float-convert Tests
|
# Float-convert Tests
|
||||||
ARM_TESTS += fcvt
|
ARM_TESTS += fcvt
|
||||||
|
@ -25,7 +25,7 @@ EXTRA_RUNS+=$(MULTIARCH_RUNS)
|
|||||||
.PRECIOUS: $(CRT_OBJS)
|
.PRECIOUS: $(CRT_OBJS)
|
||||||
|
|
||||||
%.o: $(CRT_PATH)/%.S
|
%.o: $(CRT_PATH)/%.S
|
||||||
$(CC) $(CFLAGS) $(EXTRA_CFLAGS) -c $< -o $@
|
$(CC) $(CFLAGS) $(EXTRA_CFLAGS) -Wa,--noexecstack -c $< -o $@
|
||||||
|
|
||||||
# Build and link the tests
|
# Build and link the tests
|
||||||
%: %.c $(LINK_SCRIPT) $(CRT_OBJS) $(MINILIB_OBJS)
|
%: %.c $(LINK_SCRIPT) $(CRT_OBJS) $(MINILIB_OBJS)
|
||||||
|
@ -16,13 +16,13 @@ LINK_SCRIPT=$(LOONGARCH64_SYSTEM_SRC)/kernel.ld
|
|||||||
LDFLAGS=-Wl,-T$(LINK_SCRIPT)
|
LDFLAGS=-Wl,-T$(LINK_SCRIPT)
|
||||||
TESTS+=$(LOONGARCH64_TESTS) $(MULTIARCH_TESTS)
|
TESTS+=$(LOONGARCH64_TESTS) $(MULTIARCH_TESTS)
|
||||||
CFLAGS+=-nostdlib -g -O1 -march=loongarch64 -mabi=lp64d $(MINILIB_INC)
|
CFLAGS+=-nostdlib -g -O1 -march=loongarch64 -mabi=lp64d $(MINILIB_INC)
|
||||||
LDFLAGS+=-static -nostdlib $(CRT_OBJS) $(MINILIB_OBJS) -lgcc
|
LDFLAGS+=-static -nostdlib $(CRT_OBJS) $(MINILIB_OBJS) -lgcc -Wl,--no-warn-rwx-segments
|
||||||
|
|
||||||
# building head blobs
|
# building head blobs
|
||||||
.PRECIOUS: $(CRT_OBJS)
|
.PRECIOUS: $(CRT_OBJS)
|
||||||
|
|
||||||
%.o: $(CRT_PATH)/%.S
|
%.o: $(CRT_PATH)/%.S
|
||||||
$(CC) $(CFLAGS) $(EXTRA_CFLAGS) -x assembler-with-cpp -c $< -o $@
|
$(CC) $(CFLAGS) $(EXTRA_CFLAGS) -x assembler-with-cpp -Wa,--noexecstack -c $< -o $@
|
||||||
|
|
||||||
# Build and link the tests
|
# Build and link the tests
|
||||||
%: %.c $(LINK_SCRIPT) $(CRT_OBJS) $(MINILIB_OBJS)
|
%: %.c $(LINK_SCRIPT) $(CRT_OBJS) $(MINILIB_OBJS)
|
||||||
|
@ -2,15 +2,15 @@ t = []
|
|||||||
if get_option('plugins')
|
if get_option('plugins')
|
||||||
foreach i : ['bb', 'empty', 'inline', 'insn', 'mem', 'syscall']
|
foreach i : ['bb', 'empty', 'inline', 'insn', 'mem', 'syscall']
|
||||||
if host_os == 'windows'
|
if host_os == 'windows'
|
||||||
t += shared_module(i, files(i + '.c') + '../../contrib/plugins/win32_linker.c',
|
t += shared_module(i, files(i + '.c') + '../../../contrib/plugins/win32_linker.c',
|
||||||
include_directories: '../../include/qemu',
|
include_directories: '../../../include/qemu',
|
||||||
link_depends: [win32_qemu_plugin_api_lib],
|
link_depends: [win32_qemu_plugin_api_lib],
|
||||||
link_args: ['-Lplugins', '-lqemu_plugin_api'],
|
link_args: ['-Lplugins', '-lqemu_plugin_api'],
|
||||||
dependencies: glib)
|
dependencies: glib)
|
||||||
|
|
||||||
else
|
else
|
||||||
t += shared_module(i, files(i + '.c'),
|
t += shared_module(i, files(i + '.c'),
|
||||||
include_directories: '../../include/qemu',
|
include_directories: '../../../include/qemu',
|
||||||
dependencies: glib)
|
dependencies: glib)
|
||||||
endif
|
endif
|
||||||
endforeach
|
endforeach
|
@ -10,7 +10,7 @@ LDFLAGS = -T $(LINK_SCRIPT)
|
|||||||
CFLAGS += -g -Og
|
CFLAGS += -g -Og
|
||||||
|
|
||||||
%.o: %.S
|
%.o: %.S
|
||||||
$(CC) $(CFLAGS) $< -c -o $@
|
$(CC) $(CFLAGS) $< -Wa,--noexecstack -c -o $@
|
||||||
%: %.o $(LINK_SCRIPT)
|
%: %.o $(LINK_SCRIPT)
|
||||||
$(LD) $(LDFLAGS) $< -o $@
|
$(LD) $(LDFLAGS) $< -o $@
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@ CFLAGS+=-ggdb -O0
|
|||||||
LDFLAGS=-nostdlib -static
|
LDFLAGS=-nostdlib -static
|
||||||
|
|
||||||
%.o: %.S
|
%.o: %.S
|
||||||
$(CC) -march=z13 -m64 -c $< -o $@
|
$(CC) -march=z13 -m64 -Wa,--noexecstack -c $< -o $@
|
||||||
|
|
||||||
%.o: %.c
|
%.o: %.c
|
||||||
$(CC) $(CFLAGS) $(EXTRA_CFLAGS) -march=z13 -m64 -c $< -o $@
|
$(CC) $(CFLAGS) $(EXTRA_CFLAGS) -march=z13 -m64 -c $< -o $@
|
||||||
|
@ -25,7 +25,7 @@ EXTRA_RUNS+=$(MULTIARCH_RUNS)
|
|||||||
.PRECIOUS: $(CRT_OBJS)
|
.PRECIOUS: $(CRT_OBJS)
|
||||||
|
|
||||||
%.o: $(CRT_PATH)/%.S
|
%.o: $(CRT_PATH)/%.S
|
||||||
$(CC) $(CFLAGS) $(EXTRA_CFLAGS) -c $< -o $@
|
$(CC) $(CFLAGS) $(EXTRA_CFLAGS) -Wa,--noexecstack -c $< -o $@
|
||||||
|
|
||||||
# Build and link the tests
|
# Build and link the tests
|
||||||
%: %.c $(LINK_SCRIPT) $(CRT_OBJS) $(MINILIB_OBJS)
|
%: %.c $(LINK_SCRIPT) $(CRT_OBJS) $(MINILIB_OBJS)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user