aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Henderson <richard.henderson@linaro.org>2021-11-04 08:33:46 -0400
committerRichard Henderson <richard.henderson@linaro.org>2021-11-04 08:33:46 -0400
commit18e356a53a2926a15343b914db64324d63748f25 (patch)
treeb4da84fdfec10103fa82301f5dfb4e06b94430c5
parentc88da1f3dac9681b29a0d23016a7acbbc2c8c517 (diff)
parentb31b3fd0c0e17b95b9b0e05e0d67d0cd3ca081da (diff)
downloadqemu-18e356a53a2926a15343b914db64324d63748f25.zip
qemu-18e356a53a2926a15343b914db64324d63748f25.tar.gz
qemu-18e356a53a2926a15343b914db64324d63748f25.tar.bz2
Merge remote-tracking branch 'remotes/stsquad/tags/pull-for-6.2-041121-2' into staging
Testing, gdbstub and plugin updates for 6.2 - add microblaze and nios2 compiler docker images - fix test cross compiler detection for some targets - don't try and link ebf to user targets - add L2 tracking to cache plugin - exit cleanly on C-a x - clean up debug output in check-tcg - switch to thread on break in gdbstub - update openbsd VM to 7.0 # gpg: Signature made Thu 04 Nov 2021 08:14:35 AM EDT # gpg: using RSA key 6685AE99E75167BCAFC8DF35FBD0DB095A9E2A44 # gpg: Good signature from "Alex Bennée (Master Work Key) <alex.bennee@linaro.org>" [full] * remotes/stsquad/tags/pull-for-6.2-041121-2: tests/vm/openbsd: Update to release 7.0 tests/tcg: remove debug polluting make output gdbstub: Switch to the thread receiving a signal tests/tcg: remove duplicate EXTRA_RUNS plugins: try and make plugin_insn_append more ergonomic tests/plugins: extend the insn plugin to track opcode sizes chardev: don't exit() straight away on C-a x docs/tcg-plugins: add L2 arguments to cache docs plugins/cache: make L2 emulation optional through args plugins/cache: split command line arguments into name and value plugins/cache: implement unified L2 cache emulation plugins/cache: freed heap-allocated mutexes ebpf: really include it only in system emulators tests/tcg: enable debian-nios2-cross for test building tests/docker: split PARTIAL into PARTIAL and VIRTUAL images tests/tcg: Fix some targets default cross compiler path tests/tcg: Enable container_cross_cc for microblaze tests/docker: Add debian-microblaze-cross image tests/docker: Add debian-nios2-cross image Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
-rw-r--r--MAINTAINERS3
-rw-r--r--accel/tcg/plugin-gen.c3
-rw-r--r--accel/tcg/translator.c2
-rw-r--r--chardev/char-mux.c3
-rw-r--r--contrib/plugins/cache.c318
-rw-r--r--docs/devel/tcg-plugins.rst20
-rw-r--r--gdbstub.c8
-rw-r--r--include/exec/plugin-gen.h12
-rw-r--r--include/qemu/plugin.h7
-rw-r--r--meson.build2
-rw-r--r--stubs/meson.build1
-rw-r--r--stubs/qmp-quit.c8
-rw-r--r--tests/docker/Makefile.include39
-rwxr-xr-xtests/docker/dockerfiles/debian-microblaze-cross.d/build-toolchain.sh88
-rwxr-xr-xtests/docker/dockerfiles/debian-nios2-cross.d/build-toolchain.sh87
-rw-r--r--tests/docker/dockerfiles/debian-toolchain.docker36
-rw-r--r--tests/plugin/insn.c37
-rwxr-xr-xtests/tcg/configure.sh26
-rw-r--r--tests/tcg/multiarch/Makefile.target13
-rw-r--r--tests/tcg/multiarch/gdbstub/test-thread-breakpoint.py60
-rw-r--r--tests/tcg/nios2/Makefile.target11
-rw-r--r--tests/tcg/sh4/Makefile.target6
-rwxr-xr-xtests/vm/openbsd7
23 files changed, 670 insertions, 127 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
index 7e31135..797be5b 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -225,6 +225,8 @@ S: Maintained
F: target/microblaze/
F: hw/microblaze/
F: disas/microblaze.c
+F: tests/docker/dockerfiles/debian-microblaze-cross.d/build-toolchain.sh
+F: tests/tcg/nios2/Makefile.target
MIPS TCG CPUs
M: Philippe Mathieu-Daudé <f4bug@amsat.org>
@@ -250,6 +252,7 @@ F: target/nios2/
F: hw/nios2/
F: disas/nios2.c
F: configs/devices/nios2-softmmu/default.mak
+F: tests/docker/dockerfiles/debian-nios2-cross.d/build-toolchain.sh
OpenRISC TCG CPUs
M: Stafford Horne <shorne@gmail.com>
diff --git a/accel/tcg/plugin-gen.c b/accel/tcg/plugin-gen.c
index 61be64b..22d95fe 100644
--- a/accel/tcg/plugin-gen.c
+++ b/accel/tcg/plugin-gen.c
@@ -876,9 +876,8 @@ void plugin_gen_insn_start(CPUState *cpu, const DisasContextBase *db)
struct qemu_plugin_tb *ptb = tcg_ctx->plugin_tb;
struct qemu_plugin_insn *pinsn;
- pinsn = qemu_plugin_tb_insn_get(ptb);
+ pinsn = qemu_plugin_tb_insn_get(ptb, db->pc_next);
tcg_ctx->plugin_insn = pinsn;
- pinsn->vaddr = db->pc_next;
plugin_gen_empty_callback(PLUGIN_GEN_FROM_INSN);
/*
diff --git a/accel/tcg/translator.c b/accel/tcg/translator.c
index 390bd9d..f06c314 100644
--- a/accel/tcg/translator.c
+++ b/accel/tcg/translator.c
@@ -169,7 +169,7 @@ static inline void translator_maybe_page_protect(DisasContextBase *dcbase,
if (do_swap) { \
ret = swap_fn(ret); \
} \
- plugin_insn_append(&ret, sizeof(ret)); \
+ plugin_insn_append(pc, &ret, sizeof(ret)); \
return ret; \
}
diff --git a/chardev/char-mux.c b/chardev/char-mux.c
index ada0c68..ee2d47b 100644
--- a/chardev/char-mux.c
+++ b/chardev/char-mux.c
@@ -28,6 +28,7 @@
#include "qemu/option.h"
#include "chardev/char.h"
#include "sysemu/block-backend.h"
+#include "qapi/qapi-commands-control.h"
#include "chardev-internal.h"
/* MUX driver for serial I/O splitting */
@@ -157,7 +158,7 @@ static int mux_proc_byte(Chardev *chr, MuxChardev *d, int ch)
{
const char *term = "QEMU: Terminated\n\r";
qemu_chr_write_all(chr, (uint8_t *)term, strlen(term));
- exit(0);
+ qmp_quit(NULL);
break;
}
case 's':
diff --git a/contrib/plugins/cache.c b/contrib/plugins/cache.c
index a1e03ca..b9226e7 100644
--- a/contrib/plugins/cache.c
+++ b/contrib/plugins/cache.c
@@ -11,6 +11,8 @@
#include <qemu-plugin.h>
+#define STRTOLL(x) g_ascii_strtoll(x, NULL, 10)
+
QEMU_PLUGIN_EXPORT int qemu_plugin_version = QEMU_PLUGIN_VERSION;
static enum qemu_plugin_mem_rw rw = QEMU_PLUGIN_MEM_RW;
@@ -82,8 +84,9 @@ typedef struct {
char *disas_str;
const char *symbol;
uint64_t addr;
- uint64_t dmisses;
- uint64_t imisses;
+ uint64_t l1_dmisses;
+ uint64_t l1_imisses;
+ uint64_t l2_misses;
} InsnData;
void (*update_hit)(Cache *cache, int set, int blk);
@@ -93,15 +96,22 @@ void (*metadata_init)(Cache *cache);
void (*metadata_destroy)(Cache *cache);
static int cores;
-static Cache **dcaches, **icaches;
+static Cache **l1_dcaches, **l1_icaches;
+
+static bool use_l2;
+static Cache **l2_ucaches;
-static GMutex *dcache_locks;
-static GMutex *icache_locks;
+static GMutex *l1_dcache_locks;
+static GMutex *l1_icache_locks;
+static GMutex *l2_ucache_locks;
-static uint64_t all_dmem_accesses;
-static uint64_t all_imem_accesses;
-static uint64_t all_imisses;
-static uint64_t all_dmisses;
+static uint64_t l1_dmem_accesses;
+static uint64_t l1_imem_accesses;
+static uint64_t l1_imisses;
+static uint64_t l1_dmisses;
+
+static uint64_t l2_mem_accesses;
+static uint64_t l2_misses;
static int pow_of_two(int num)
{
@@ -382,6 +392,7 @@ static void vcpu_mem_access(unsigned int vcpu_index, qemu_plugin_meminfo_t info,
struct qemu_plugin_hwaddr *hwaddr;
int cache_idx;
InsnData *insn;
+ bool hit_in_l1;
hwaddr = qemu_plugin_get_hwaddr(info, vaddr);
if (hwaddr && qemu_plugin_hwaddr_is_io(hwaddr)) {
@@ -391,14 +402,29 @@ static void vcpu_mem_access(unsigned int vcpu_index, qemu_plugin_meminfo_t info,
effective_addr = hwaddr ? qemu_plugin_hwaddr_phys_addr(hwaddr) : vaddr;
cache_idx = vcpu_index % cores;
- g_mutex_lock(&dcache_locks[cache_idx]);
- if (!access_cache(dcaches[cache_idx], effective_addr)) {
+ g_mutex_lock(&l1_dcache_locks[cache_idx]);
+ hit_in_l1 = access_cache(l1_dcaches[cache_idx], effective_addr);
+ if (!hit_in_l1) {
+ insn = (InsnData *) userdata;
+ __atomic_fetch_add(&insn->l1_dmisses, 1, __ATOMIC_SEQ_CST);
+ l1_dcaches[cache_idx]->misses++;
+ }
+ l1_dcaches[cache_idx]->accesses++;
+ g_mutex_unlock(&l1_dcache_locks[cache_idx]);
+
+ if (hit_in_l1 || !use_l2) {
+ /* No need to access L2 */
+ return;
+ }
+
+ g_mutex_lock(&l2_ucache_locks[cache_idx]);
+ if (!access_cache(l2_ucaches[cache_idx], effective_addr)) {
insn = (InsnData *) userdata;
- __atomic_fetch_add(&insn->dmisses, 1, __ATOMIC_SEQ_CST);
- dcaches[cache_idx]->misses++;
+ __atomic_fetch_add(&insn->l2_misses, 1, __ATOMIC_SEQ_CST);
+ l2_ucaches[cache_idx]->misses++;
}
- dcaches[cache_idx]->accesses++;
- g_mutex_unlock(&dcache_locks[cache_idx]);
+ l2_ucaches[cache_idx]->accesses++;
+ g_mutex_unlock(&l2_ucache_locks[cache_idx]);
}
static void vcpu_insn_exec(unsigned int vcpu_index, void *userdata)
@@ -406,18 +432,34 @@ static void vcpu_insn_exec(unsigned int vcpu_index, void *userdata)
uint64_t insn_addr;
InsnData *insn;
int cache_idx;
+ bool hit_in_l1;
insn_addr = ((InsnData *) userdata)->addr;
cache_idx = vcpu_index % cores;
- g_mutex_lock(&icache_locks[cache_idx]);
- if (!access_cache(icaches[cache_idx], insn_addr)) {
+ g_mutex_lock(&l1_icache_locks[cache_idx]);
+ hit_in_l1 = access_cache(l1_icaches[cache_idx], insn_addr);
+ if (!hit_in_l1) {
+ insn = (InsnData *) userdata;
+ __atomic_fetch_add(&insn->l1_imisses, 1, __ATOMIC_SEQ_CST);
+ l1_icaches[cache_idx]->misses++;
+ }
+ l1_icaches[cache_idx]->accesses++;
+ g_mutex_unlock(&l1_icache_locks[cache_idx]);
+
+ if (hit_in_l1 || !use_l2) {
+ /* No need to access L2 */
+ return;
+ }
+
+ g_mutex_lock(&l2_ucache_locks[cache_idx]);
+ if (!access_cache(l2_ucaches[cache_idx], insn_addr)) {
insn = (InsnData *) userdata;
- __atomic_fetch_add(&insn->imisses, 1, __ATOMIC_SEQ_CST);
- icaches[cache_idx]->misses++;
+ __atomic_fetch_add(&insn->l2_misses, 1, __ATOMIC_SEQ_CST);
+ l2_ucaches[cache_idx]->misses++;
}
- icaches[cache_idx]->accesses++;
- g_mutex_unlock(&icache_locks[cache_idx]);
+ l2_ucaches[cache_idx]->accesses++;
+ g_mutex_unlock(&l2_ucache_locks[cache_idx]);
}
static void vcpu_tb_trans(qemu_plugin_id_t id, struct qemu_plugin_tb *tb)
@@ -493,30 +535,34 @@ static void caches_free(Cache **caches)
}
}
-static int dcmp(gconstpointer a, gconstpointer b)
+static void append_stats_line(GString *line, uint64_t l1_daccess,
+ uint64_t l1_dmisses, uint64_t l1_iaccess,
+ uint64_t l1_imisses, uint64_t l2_access,
+ uint64_t l2_misses)
{
- InsnData *insn_a = (InsnData *) a;
- InsnData *insn_b = (InsnData *) b;
+ double l1_dmiss_rate, l1_imiss_rate, l2_miss_rate;
- return insn_a->dmisses < insn_b->dmisses ? 1 : -1;
-}
+ l1_dmiss_rate = ((double) l1_dmisses) / (l1_daccess) * 100.0;
+ l1_imiss_rate = ((double) l1_imisses) / (l1_iaccess) * 100.0;
-static void append_stats_line(GString *line, uint64_t daccess, uint64_t dmisses,
- uint64_t iaccess, uint64_t imisses)
-{
- double dmiss_rate, imiss_rate;
+ g_string_append_printf(line, "%-14lu %-12lu %9.4lf%% %-14lu %-12lu"
+ " %9.4lf%%",
+ l1_daccess,
+ l1_dmisses,
+ l1_daccess ? l1_dmiss_rate : 0.0,
+ l1_iaccess,
+ l1_imisses,
+ l1_iaccess ? l1_imiss_rate : 0.0);
- dmiss_rate = ((double) dmisses) / (daccess) * 100.0;
- imiss_rate = ((double) imisses) / (iaccess) * 100.0;
+ if (use_l2) {
+ l2_miss_rate = ((double) l2_misses) / (l2_access) * 100.0;
+ g_string_append_printf(line, " %-12lu %-11lu %10.4lf%%",
+ l2_access,
+ l2_misses,
+ l2_access ? l2_miss_rate : 0.0);
+ }
- g_string_append_printf(line, "%-14lu %-12lu %9.4lf%% %-14lu %-12lu"
- " %9.4lf%%\n",
- daccess,
- dmisses,
- daccess ? dmiss_rate : 0.0,
- iaccess,
- imisses,
- iaccess ? imiss_rate : 0.0);
+ g_string_append(line, "\n");
}
static void sum_stats(void)
@@ -525,43 +571,74 @@ static void sum_stats(void)
g_assert(cores > 1);
for (i = 0; i < cores; i++) {
- all_imisses += icaches[i]->misses;
- all_dmisses += dcaches[i]->misses;
- all_imem_accesses += icaches[i]->accesses;
- all_dmem_accesses += dcaches[i]->accesses;
+ l1_imisses += l1_icaches[i]->misses;
+ l1_dmisses += l1_dcaches[i]->misses;
+ l1_imem_accesses += l1_icaches[i]->accesses;
+ l1_dmem_accesses += l1_dcaches[i]->accesses;
+
+ if (use_l2) {
+ l2_misses += l2_ucaches[i]->misses;
+ l2_mem_accesses += l2_ucaches[i]->accesses;
+ }
}
}
+static int dcmp(gconstpointer a, gconstpointer b)
+{
+ InsnData *insn_a = (InsnData *) a;
+ InsnData *insn_b = (InsnData *) b;
+
+ return insn_a->l1_dmisses < insn_b->l1_dmisses ? 1 : -1;
+}
+
static int icmp(gconstpointer a, gconstpointer b)
{
InsnData *insn_a = (InsnData *) a;
InsnData *insn_b = (InsnData *) b;
- return insn_a->imisses < insn_b->imisses ? 1 : -1;
+ return insn_a->l1_imisses < insn_b->l1_imisses ? 1 : -1;
+}
+
+static int l2_cmp(gconstpointer a, gconstpointer b)
+{
+ InsnData *insn_a = (InsnData *) a;
+ InsnData *insn_b = (InsnData *) b;
+
+ return insn_a->l2_misses < insn_b->l2_misses ? 1 : -1;
}
static void log_stats(void)
{
int i;
- Cache *icache, *dcache;
+ Cache *icache, *dcache, *l2_cache;
g_autoptr(GString) rep = g_string_new("core #, data accesses, data misses,"
" dmiss rate, insn accesses,"
- " insn misses, imiss rate\n");
+ " insn misses, imiss rate");
+
+ if (use_l2) {
+ g_string_append(rep, ", l2 accesses, l2 misses, l2 miss rate");
+ }
+
+ g_string_append(rep, "\n");
for (i = 0; i < cores; i++) {
g_string_append_printf(rep, "%-8d", i);
- dcache = dcaches[i];
- icache = icaches[i];
+ dcache = l1_dcaches[i];
+ icache = l1_icaches[i];
+ l2_cache = use_l2 ? l2_ucaches[i] : NULL;
append_stats_line(rep, dcache->accesses, dcache->misses,
- icache->accesses, icache->misses);
+ icache->accesses, icache->misses,
+ l2_cache ? l2_cache->accesses : 0,
+ l2_cache ? l2_cache->misses : 0);
}
if (cores > 1) {
sum_stats();
g_string_append_printf(rep, "%-8s", "sum");
- append_stats_line(rep, all_dmem_accesses, all_dmisses,
- all_imem_accesses, all_imisses);
+ append_stats_line(rep, l1_dmem_accesses, l1_dmisses,
+ l1_imem_accesses, l1_imisses,
+ l2_cache ? l2_mem_accesses : 0, l2_cache ? l2_misses : 0);
}
g_string_append(rep, "\n");
@@ -585,7 +662,7 @@ static void log_top_insns(void)
if (insn->symbol) {
g_string_append_printf(rep, " (%s)", insn->symbol);
}
- g_string_append_printf(rep, ", %ld, %s\n", insn->dmisses,
+ g_string_append_printf(rep, ", %ld, %s\n", insn->l1_dmisses,
insn->disas_str);
}
@@ -598,10 +675,28 @@ static void log_top_insns(void)
if (insn->symbol) {
g_string_append_printf(rep, " (%s)", insn->symbol);
}
- g_string_append_printf(rep, ", %ld, %s\n", insn->imisses,
+ g_string_append_printf(rep, ", %ld, %s\n", insn->l1_imisses,
insn->disas_str);
}
+ if (!use_l2) {
+ goto finish;
+ }
+
+ miss_insns = g_list_sort(miss_insns, l2_cmp);
+ g_string_append_printf(rep, "%s", "\naddress, L2 misses, instruction\n");
+
+ for (curr = miss_insns, i = 0; curr && i < limit; i++, curr = curr->next) {
+ insn = (InsnData *) curr->data;
+ g_string_append_printf(rep, "0x%" PRIx64, insn->addr);
+ if (insn->symbol) {
+ g_string_append_printf(rep, " (%s)", insn->symbol);
+ }
+ g_string_append_printf(rep, ", %ld, %s\n", insn->l2_misses,
+ insn->disas_str);
+ }
+
+finish:
qemu_plugin_outs(rep->str);
g_list_free(miss_insns);
}
@@ -611,8 +706,16 @@ static void plugin_exit(qemu_plugin_id_t id, void *p)
log_stats();
log_top_insns();
- caches_free(dcaches);
- caches_free(icaches);
+ caches_free(l1_dcaches);
+ caches_free(l1_icaches);
+
+ g_free(l1_dcache_locks);
+ g_free(l1_icache_locks);
+
+ if (use_l2) {
+ caches_free(l2_ucaches);
+ g_free(l2_ucache_locks);
+ }
g_hash_table_destroy(miss_ht);
}
@@ -644,19 +747,24 @@ int qemu_plugin_install(qemu_plugin_id_t id, const qemu_info_t *info,
int argc, char **argv)
{
int i;
- int iassoc, iblksize, icachesize;
- int dassoc, dblksize, dcachesize;
+ int l1_iassoc, l1_iblksize, l1_icachesize;
+ int l1_dassoc, l1_dblksize, l1_dcachesize;
+ int l2_assoc, l2_blksize, l2_cachesize;
limit = 32;
sys = info->system_emulation;
- dassoc = 8;
- dblksize = 64;
- dcachesize = dblksize * dassoc * 32;
+ l1_dassoc = 8;
+ l1_dblksize = 64;
+ l1_dcachesize = l1_dblksize * l1_dassoc * 32;
- iassoc = 8;
- iblksize = 64;
- icachesize = iblksize * iassoc * 32;
+ l1_iassoc = 8;
+ l1_iblksize = 64;
+ l1_icachesize = l1_iblksize * l1_iassoc * 32;
+
+ l2_assoc = 16;
+ l2_blksize = 64;
+ l2_cachesize = l2_assoc * l2_blksize * 2048;
policy = LRU;
@@ -664,29 +772,44 @@ int qemu_plugin_install(qemu_plugin_id_t id, const qemu_info_t *info,
for (i = 0; i < argc; i++) {
char *opt = argv[i];
- if (g_str_has_prefix(opt, "iblksize=")) {
- iblksize = g_ascii_strtoll(opt + 9, NULL, 10);
- } else if (g_str_has_prefix(opt, "iassoc=")) {
- iassoc = g_ascii_strtoll(opt + 7, NULL, 10);
- } else if (g_str_has_prefix(opt, "icachesize=")) {
- icachesize = g_ascii_strtoll(opt + 11, NULL, 10);
- } else if (g_str_has_prefix(opt, "dblksize=")) {
- dblksize = g_ascii_strtoll(opt + 9, NULL, 10);
- } else if (g_str_has_prefix(opt, "dassoc=")) {
- dassoc = g_ascii_strtoll(opt + 7, NULL, 10);
- } else if (g_str_has_prefix(opt, "dcachesize=")) {
- dcachesize = g_ascii_strtoll(opt + 11, NULL, 10);
- } else if (g_str_has_prefix(opt, "limit=")) {
- limit = g_ascii_strtoll(opt + 6, NULL, 10);
- } else if (g_str_has_prefix(opt, "cores=")) {
- cores = g_ascii_strtoll(opt + 6, NULL, 10);
- } else if (g_str_has_prefix(opt, "evict=")) {
- gchar *p = opt + 6;
- if (g_strcmp0(p, "rand") == 0) {
+ g_autofree char **tokens = g_strsplit(opt, "=", 2);
+
+ if (g_strcmp0(tokens[0], "iblksize") == 0) {
+ l1_iblksize = STRTOLL(tokens[1]);
+ } else if (g_strcmp0(tokens[0], "iassoc") == 0) {
+ l1_iassoc = STRTOLL(tokens[1]);
+ } else if (g_strcmp0(tokens[0], "icachesize") == 0) {
+ l1_icachesize = STRTOLL(tokens[1]);
+ } else if (g_strcmp0(tokens[0], "dblksize") == 0) {
+ l1_dblksize = STRTOLL(tokens[1]);
+ } else if (g_strcmp0(tokens[0], "dassoc") == 0) {
+ l1_dassoc = STRTOLL(tokens[1]);
+ } else if (g_strcmp0(tokens[0], "dcachesize") == 0) {
+ l1_dcachesize = STRTOLL(tokens[1]);
+ } else if (g_strcmp0(tokens[0], "limit") == 0) {
+ limit = STRTOLL(tokens[1]);
+ } else if (g_strcmp0(tokens[0], "cores") == 0) {
+ cores = STRTOLL(tokens[1]);
+ } else if (g_strcmp0(tokens[0], "l2cachesize") == 0) {
+ use_l2 = true;
+ l2_cachesize = STRTOLL(tokens[1]);
+ } else if (g_strcmp0(tokens[0], "l2blksize") == 0) {
+ use_l2 = true;
+ l2_blksize = STRTOLL(tokens[1]);
+ } else if (g_strcmp0(tokens[0], "l2assoc") == 0) {
+ use_l2 = true;
+ l2_assoc = STRTOLL(tokens[1]);
+ } else if (g_strcmp0(tokens[0], "l2") == 0) {
+ if (!qemu_plugin_bool_parse(tokens[0], tokens[1], &use_l2)) {
+ fprintf(stderr, "boolean argument parsing failed: %s\n", opt);
+ return -1;
+ }
+ } else if (g_strcmp0(tokens[0], "evict") == 0) {
+ if (g_strcmp0(tokens[1], "rand") == 0) {
policy = RAND;
- } else if (g_strcmp0(p, "lru") == 0) {
+ } else if (g_strcmp0(tokens[1], "lru") == 0) {
policy = LRU;
- } else if (g_strcmp0(p, "fifo") == 0) {
+ } else if (g_strcmp0(tokens[1], "fifo") == 0) {
policy = FIFO;
} else {
fprintf(stderr, "invalid eviction policy: %s\n", opt);
@@ -700,24 +823,33 @@ int qemu_plugin_install(qemu_plugin_id_t id, const qemu_info_t *info,
policy_init();
- dcaches = caches_init(dblksize, dassoc, dcachesize);
- if (!dcaches) {
- const char *err = cache_config_error(dblksize, dassoc, dcachesize);
+ l1_dcaches = caches_init(l1_dblksize, l1_dassoc, l1_dcachesize);
+ if (!l1_dcaches) {
+ const char *err = cache_config_error(l1_dblksize, l1_dassoc, l1_dcachesize);
fprintf(stderr, "dcache cannot be constructed from given parameters\n");
fprintf(stderr, "%s\n", err);
return -1;
}
- icaches = caches_init(iblksize, iassoc, icachesize);
- if (!icaches) {
- const char *err = cache_config_error(iblksize, iassoc, icachesize);
+ l1_icaches = caches_init(l1_iblksize, l1_iassoc, l1_icachesize);
+ if (!l1_icaches) {
+ const char *err = cache_config_error(l1_iblksize, l1_iassoc, l1_icachesize);
fprintf(stderr, "icache cannot be constructed from given parameters\n");
fprintf(stderr, "%s\n", err);
return -1;
}
- dcache_locks = g_new0(GMutex, cores);
- icache_locks = g_new0(GMutex, cores);
+ l2_ucaches = use_l2 ? caches_init(l2_blksize, l2_assoc, l2_cachesize) : NULL;
+ if (!l2_ucaches && use_l2) {
+ const char *err = cache_config_error(l2_blksize, l2_assoc, l2_cachesize);
+ fprintf(stderr, "L2 cache cannot be constructed from given parameters\n");
+ fprintf(stderr, "%s\n", err);
+ return -1;
+ }
+
+ l1_dcache_locks = g_new0(GMutex, cores);
+ l1_icache_locks = g_new0(GMutex, cores);
+ l2_ucache_locks = use_l2 ? g_new0(GMutex, cores) : NULL;
qemu_plugin_register_vcpu_tb_trans_cb(id, vcpu_tb_trans);
qemu_plugin_register_atexit_cb(id, plugin_exit, NULL);
diff --git a/docs/devel/tcg-plugins.rst b/docs/devel/tcg-plugins.rst
index 842ae01..59a7d83 100644
--- a/docs/devel/tcg-plugins.rst
+++ b/docs/devel/tcg-plugins.rst
@@ -361,8 +361,9 @@ which will output an execution trace following this structure::
- contrib/plugins/cache.c
-Cache modelling plugin that measures the performance of a given cache
-configuration when a given working set is run::
+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
@@ -420,3 +421,18 @@ The plugin has a number of arguments, all of them are optional:
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)
diff --git a/gdbstub.c b/gdbstub.c
index 36b85aa..23baaef 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -3138,8 +3138,12 @@ gdb_handlesig(CPUState *cpu, int sig)
tb_flush(cpu);
if (sig != 0) {
- snprintf(buf, sizeof(buf), "S%02x", target_signal_to_gdb(sig));
- put_packet(buf);
+ gdb_set_stop_cpu(cpu);
+ g_string_printf(gdbserver_state.str_buf,
+ "T%02xthread:", target_signal_to_gdb(sig));
+ gdb_append_thread_id(cpu, gdbserver_state.str_buf);
+ g_string_append_c(gdbserver_state.str_buf, ';');
+ put_strbuf();
}
/* put_packet() might have detected that the peer terminated the
connection. */
diff --git a/include/exec/plugin-gen.h b/include/exec/plugin-gen.h
index b1b72b5..f92f169 100644
--- a/include/exec/plugin-gen.h
+++ b/include/exec/plugin-gen.h
@@ -27,13 +27,21 @@ void plugin_gen_insn_end(void);
void plugin_gen_disable_mem_helpers(void);
void plugin_gen_empty_mem_callback(TCGv addr, uint32_t info);
-static inline void plugin_insn_append(const void *from, size_t size)
+static inline void plugin_insn_append(abi_ptr pc, const void *from, size_t size)
{
struct qemu_plugin_insn *insn = tcg_ctx->plugin_insn;
+ abi_ptr off;
if (insn == NULL) {
return;
}
+ off = pc - insn->vaddr;
+ if (off < insn->data->len) {
+ g_byte_array_set_size(insn->data, off);
+ } else if (off > insn->data->len) {
+ /* we have an unexpected gap */
+ g_assert_not_reached();
+ }
insn->data = g_byte_array_append(insn->data, from, size);
}
@@ -62,7 +70,7 @@ static inline void plugin_gen_disable_mem_helpers(void)
static inline void plugin_gen_empty_mem_callback(TCGv addr, uint32_t info)
{ }
-static inline void plugin_insn_append(const void *from, size_t size)
+static inline void plugin_insn_append(abi_ptr pc, const void *from, size_t size)
{ }
#endif /* CONFIG_PLUGIN */
diff --git a/include/qemu/plugin.h b/include/qemu/plugin.h
index b3172b1..145f8a2 100644
--- a/include/qemu/plugin.h
+++ b/include/qemu/plugin.h
@@ -163,10 +163,12 @@ struct qemu_plugin_tb {
/**
* qemu_plugin_tb_insn_get(): get next plugin record for translation.
- *
+ * @tb: the internal tb context
+ * @pc: address of instruction
*/
static inline
-struct qemu_plugin_insn *qemu_plugin_tb_insn_get(struct qemu_plugin_tb *tb)
+struct qemu_plugin_insn *qemu_plugin_tb_insn_get(struct qemu_plugin_tb *tb,
+ uint64_t pc)
{
struct qemu_plugin_insn *insn;
int i, j;
@@ -179,6 +181,7 @@ struct qemu_plugin_insn *qemu_plugin_tb_insn_get(struct qemu_plugin_tb *tb)
g_byte_array_set_size(insn->data, 0);
insn->calls_helpers = false;
insn->mem_helper = false;
+ insn->vaddr = pc;
for (i = 0; i < PLUGIN_N_CB_TYPES; i++) {
for (j = 0; j < PLUGIN_N_CB_SUBTYPES; j++) {
diff --git a/meson.build b/meson.build
index c4aec73..47df10a 100644
--- a/meson.build
+++ b/meson.build
@@ -2597,8 +2597,6 @@ subdir('bsd-user')
subdir('linux-user')
subdir('ebpf')
-common_ss.add(libbpf)
-
specific_ss.add_all(when: 'CONFIG_BSD_USER', if_true: bsd_user_ss)
linux_user_ss.add(files('thunk.c'))
diff --git a/stubs/meson.build b/stubs/meson.build
index f6aa3aa..71469c1 100644
--- a/stubs/meson.build
+++ b/stubs/meson.build
@@ -31,6 +31,7 @@ stub_ss.add(files('pci-bus.c'))
stub_ss.add(files('qemu-timer-notify-cb.c'))
stub_ss.add(files('qmp_memory_device.c'))
stub_ss.add(files('qmp-command-available.c'))
+stub_ss.add(files('qmp-quit.c'))
stub_ss.add(files('qtest.c'))
stub_ss.add(files('ram-block.c'))
stub_ss.add(files('ramfb.c'))
diff --git a/stubs/qmp-quit.c b/stubs/qmp-quit.c
new file mode 100644
index 0000000..a3ff47f
--- /dev/null
+++ b/stubs/qmp-quit.c
@@ -0,0 +1,8 @@
+#include "qemu/osdep.h"
+#include "qapi/qapi-commands-control.h"
+#include "qapi/qmp/dispatch.h"
+
+void qmp_quit(Error **errp)
+{
+ g_assert_not_reached();
+}
diff --git a/tests/docker/Makefile.include b/tests/docker/Makefile.include
index b9d4094..7a63a3b 100644
--- a/tests/docker/Makefile.include
+++ b/tests/docker/Makefile.include
@@ -11,8 +11,10 @@ HOST_ARCH = $(if $(ARCH),$(ARCH),$(shell uname -m))
DOCKER_SUFFIX := .docker
DOCKER_FILES_DIR := $(SRC_PATH)/tests/docker/dockerfiles
# we don't run tests on intermediate images (used as base by another image)
-DOCKER_PARTIAL_IMAGES := debian10 debian11 debian-bootstrap empty
-DOCKER_IMAGES := $(sort $(notdir $(basename $(wildcard $(DOCKER_FILES_DIR)/*.docker))))
+DOCKER_PARTIAL_IMAGES := debian10 debian11
+# we don't directly build virtual images (they are used to build other images)
+DOCKER_VIRTUAL_IMAGES := debian-bootstrap debian-toolchain empty
+DOCKER_IMAGES := $(sort $(filter-out $(DOCKER_VIRTUAL_IMAGES), $(notdir $(basename $(wildcard $(DOCKER_FILES_DIR)/*.docker)))))
DOCKER_TARGETS := $(patsubst %,docker-image-%,$(DOCKER_IMAGES))
# Use a global constant ccache directory to speed up repetitive builds
DOCKER_CCACHE_DIR := $$HOME/.cache/qemu-docker-ccache
@@ -171,10 +173,39 @@ docker-image-debian-hexagon-cross: $(DOCKER_FILES_DIR)/debian-hexagon-cross.dock
qemu/debian-hexagon-cross --add-current-user, \
"PREPARE", "debian-hexagon-cross"))
+debian-toolchain-run = \
+ $(if $(NOCACHE), \
+ $(call quiet-command, \
+ $(DOCKER_SCRIPT) build -t qemu/$1 -f $< \
+ $(if $V,,--quiet) --no-cache \
+ --registry $(DOCKER_REGISTRY) --extra-files \
+ $(DOCKER_FILES_DIR)/$1.d/build-toolchain.sh, \
+ "BUILD", $1), \
+ $(call quiet-command, \
+ $(DOCKER_SCRIPT) fetch $(if $V,,--quiet) \
+ qemu/$1 $(DOCKER_REGISTRY), \
+ "FETCH", $1) \
+ $(call quiet-command, \
+ $(DOCKER_SCRIPT) update $(if $V,,--quiet) \
+ qemu/$1 \
+ $(if $(NOUSER),,--add-current-user) \
+ "PREPARE", $1))
+debian-toolchain = $(call debian-toolchain-run,$(patsubst docker-image-%,%,$1))
+
+docker-image-debian-microblaze-cross: $(DOCKER_FILES_DIR)/debian-toolchain.docker \
+ $(DOCKER_FILES_DIR)/debian-microblaze-cross.d/build-toolchain.sh
+ $(call debian-toolchain, $@)
+
+docker-image-debian-nios2-cross: $(DOCKER_FILES_DIR)/debian-toolchain.docker \
+ $(DOCKER_FILES_DIR)/debian-nios2-cross.d/build-toolchain.sh
+ $(call debian-toolchain, $@)
+
# Specialist build images, sometimes very limited tools
docker-image-debian-tricore-cross: docker-image-debian10
docker-image-debian-all-test-cross: docker-image-debian10
docker-image-debian-arm64-test-cross: docker-image-debian11
+docker-image-debian-microblaze-cross: docker-image-debian10
+docker-image-debian-nios2-cross: docker-image-debian10
docker-image-debian-powerpc-test-cross: docker-image-debian11
# These images may be good enough for building tests but not for test builds
@@ -183,6 +214,8 @@ DOCKER_PARTIAL_IMAGES += debian-arm64-test-cross
DOCKER_PARTIAL_IMAGES += debian-powerpc-test-cross
DOCKER_PARTIAL_IMAGES += debian-hppa-cross
DOCKER_PARTIAL_IMAGES += debian-m68k-cross debian-mips64-cross
+DOCKER_PARTIAL_IMAGES += debian-microblaze-cross
+DOCKER_PARTIAL_IMAGES += debian-nios2-cross
DOCKER_PARTIAL_IMAGES += debian-sh4-cross debian-sparc64-cross
DOCKER_PARTIAL_IMAGES += debian-tricore-cross
DOCKER_PARTIAL_IMAGES += debian-xtensa-cross
@@ -195,7 +228,7 @@ DOCKER_PARTIAL_IMAGES += fedora-cris-cross
# packages.
# Expand all the pre-requistes for each docker image and test combination
-$(foreach i,$(filter-out $(DOCKER_PARTIAL_IMAGES),$(DOCKER_IMAGES)), \
+$(foreach i,$(filter-out $(DOCKER_PARTIAL_IMAGES) $(DOCKER_VIRTUAL_IMAGES),$(DOCKER_IMAGES)), \
$(foreach t,$(DOCKER_TESTS), \
$(eval .PHONY: docker-$t@$i) \
$(eval docker-$t@$i: docker-image-$i docker-run-$t@$i) \
diff --git a/tests/docker/dockerfiles/debian-microblaze-cross.d/build-toolchain.sh b/tests/docker/dockerfiles/debian-microblaze-cross.d/build-toolchain.sh
new file mode 100755
index 0000000..23ec0aa
--- /dev/null
+++ b/tests/docker/dockerfiles/debian-microblaze-cross.d/build-toolchain.sh
@@ -0,0 +1,88 @@
+#!/bin/bash
+
+set -e
+
+TARGET=microblaze-linux-musl
+LINUX_ARCH=microblaze
+
+J=$(expr $(nproc) / 2)
+TOOLCHAIN_INSTALL=/usr/local
+TOOLCHAIN_BIN=${TOOLCHAIN_INSTALL}/bin
+CROSS_SYSROOT=${TOOLCHAIN_INSTALL}/$TARGET/sys-root
+
+export PATH=${TOOLCHAIN_BIN}:$PATH
+
+#
+# Grab all of the source for the toolchain bootstrap.
+#
+
+wget https://ftp.gnu.org/gnu/binutils/binutils-2.37.tar.xz
+wget https://ftp.gnu.org/gnu/gcc/gcc-11.2.0/gcc-11.2.0.tar.xz
+wget https://www.musl-libc.org/releases/musl-1.2.2.tar.gz
+wget https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.10.70.tar.xz
+
+tar axf binutils-2.37.tar.xz
+tar axf gcc-11.2.0.tar.xz
+tar axf musl-1.2.2.tar.gz
+tar axf linux-5.10.70.tar.xz
+
+mv binutils-2.37 src-binu
+mv gcc-11.2.0 src-gcc
+mv musl-1.2.2 src-musl
+mv linux-5.10.70 src-linux
+
+mkdir -p bld-hdr bld-binu bld-gcc bld-musl
+mkdir -p ${CROSS_SYSROOT}/usr/include
+
+#
+# Install kernel headers
+#
+
+cd src-linux
+make headers_install ARCH=${LINUX_ARCH} INSTALL_HDR_PATH=${CROSS_SYSROOT}/usr
+cd ..
+
+#
+# Build binutils
+#
+
+cd bld-binu
+../src-binu/configure --disable-werror \
+ --prefix=${TOOLCHAIN_INSTALL} --with-sysroot --target=${TARGET}
+make -j${J}
+make install
+cd ..
+
+#
+# Build gcc, just the compiler so far.
+#
+
+cd bld-gcc
+../src-gcc/configure --disable-werror --disable-shared \
+ --prefix=${TOOLCHAIN_INSTALL} --with-sysroot --target=${TARGET} \
+ --enable-languages=c --disable-libssp --disable-libsanitizer \
+ --disable-libatomic --disable-libgomp --disable-libquadmath
+make -j${J} all-gcc
+make install-gcc
+cd ..
+
+#
+# Build musl.
+# We won't go through the extra step of building shared libraries
+# because we don't actually use them in QEMU docker testing.
+#
+
+cd bld-musl
+../src-musl/configure --prefix=/usr --host=${TARGET} --disable-shared
+make -j${j}
+make install DESTDIR=${CROSS_SYSROOT}
+cd ..
+
+#
+# Go back and build the compiler runtime
+#
+
+cd bld-gcc
+make -j${j}
+make install
+cd ..
diff --git a/tests/docker/dockerfiles/debian-nios2-cross.d/build-toolchain.sh b/tests/docker/dockerfiles/debian-nios2-cross.d/build-toolchain.sh
new file mode 100755
index 0000000..ba3c9d8
--- /dev/null
+++ b/tests/docker/dockerfiles/debian-nios2-cross.d/build-toolchain.sh
@@ -0,0 +1,87 @@
+#!/bin/bash
+
+set -e
+
+TARGET=nios2-linux-gnu
+LINUX_ARCH=nios2
+
+J=$(expr $(nproc) / 2)
+TOOLCHAIN_INSTALL=/usr/local
+TOOLCHAIN_BIN=${TOOLCHAIN_INSTALL}/bin
+CROSS_SYSROOT=${TOOLCHAIN_INSTALL}/$TARGET/sys-root
+
+export PATH=${TOOLCHAIN_BIN}:$PATH
+
+#
+# Grab all of the source for the toolchain bootstrap.
+#
+
+wget https://ftp.gnu.org/gnu/binutils/binutils-2.37.tar.xz
+wget https://ftp.gnu.org/gnu/gcc/gcc-11.2.0/gcc-11.2.0.tar.xz
+wget https://ftp.gnu.org/gnu/glibc/glibc-2.34.tar.xz
+wget https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.10.70.tar.xz
+
+tar axf binutils-2.37.tar.xz
+tar axf gcc-11.2.0.tar.xz
+tar axf glibc-2.34.tar.xz
+tar axf linux-5.10.70.tar.xz
+
+mv binutils-2.37 src-binu
+mv gcc-11.2.0 src-gcc
+mv glibc-2.34 src-glibc
+mv linux-5.10.70 src-linux
+
+mkdir -p bld-hdr bld-binu bld-gcc bld-glibc
+mkdir -p ${CROSS_SYSROOT}/usr/include
+
+#
+# Install kernel and glibc headers
+#
+
+cd src-linux
+make headers_install ARCH=${LINUX_ARCH} INSTALL_HDR_PATH=${CROSS_SYSROOT}/usr
+cd ..
+
+cd bld-hdr
+../src-glibc/configure --prefix=/usr --host=${TARGET}
+make install-headers DESTDIR=${CROSS_SYSROOT}
+touch ${CROSS_SYSROOT}/usr/include/gnu/stubs.h
+cd ..
+
+#
+# Build binutils
+#
+
+cd bld-binu
+../src-binu/configure --disable-werror \
+ --prefix=${TOOLCHAIN_INSTALL} --with-sysroot --target=${TARGET}
+make -j${J}
+make install
+cd ..
+
+#
+# Build gcc, without shared libraries, because we do not yet
+# have a shared libc against which to link.
+#
+
+cd bld-gcc
+../src-gcc/configure --disable-werror --disable-shared \
+ --prefix=${TOOLCHAIN_INSTALL} --with-sysroot --target=${TARGET} \
+ --enable-languages=c --disable-libssp --disable-libsanitizer \
+ --disable-libatomic --disable-libgomp --disable-libquadmath
+make -j${J}
+make install
+cd ..
+
+#
+# Build glibc
+# There are a few random things that use c++ but we didn't build that
+# cross-compiler. We can get away without them. Disable CXX so that
+# glibc doesn't try to use the host c++ compiler.
+#
+
+cd bld-glibc
+CXX=false ../src-glibc/configure --prefix=/usr --host=${TARGET}
+make -j${j}
+make install DESTDIR=${CROSS_SYSROOT}
+cd ..
diff --git a/tests/docker/dockerfiles/debian-toolchain.docker b/tests/docker/dockerfiles/debian-toolchain.docker
new file mode 100644
index 0000000..738d808
--- /dev/null
+++ b/tests/docker/dockerfiles/debian-toolchain.docker
@@ -0,0 +1,36 @@
+#
+# Docker toolchain cross-compiler
+#
+# This dockerfile is used for building a cross-compiler toolchain.
+# The script for building the toolchain is supplied via extra-files.
+#
+FROM qemu/debian10
+
+# Install build utilities for building gcc and glibc.
+# ??? The build-dep isn't working, missing a number of
+# minimal build dependiencies, e.g. libmpc.
+
+RUN apt update && \
+ DEBIAN_FRONTEND=noninteractive apt install -yy eatmydata && \
+ DEBIAN_FRONTEND=noninteractive eatmydata \
+ apt install -y --no-install-recommends \
+ bison \
+ flex \
+ gawk \
+ libmpc-dev \
+ libmpfr-dev \
+ rsync \
+ texinfo \
+ wget && \
+ DEBIAN_FRONTEND=noninteractive eatmydata \
+ apt build-dep -yy --arch-only gcc glibc
+
+ADD build-toolchain.sh /root/build-toolchain.sh
+
+RUN cd /root && ./build-toolchain.sh
+
+# Throw away the extra toolchain build deps, the downloaded source,
+# and the build trees by restoring the original debian10 image,
+# then copying the built toolchain from stage 0.
+FROM qemu/debian10
+COPY --from=0 /usr/local /usr/local
diff --git a/tests/plugin/insn.c b/tests/plugin/insn.c
index 0f6a193..d229fdc 100644
--- a/tests/plugin/insn.c
+++ b/tests/plugin/insn.c
@@ -18,6 +18,8 @@ QEMU_PLUGIN_EXPORT int qemu_plugin_version = QEMU_PLUGIN_VERSION;
static uint64_t insn_count;
static bool do_inline;
+static bool do_size;
+static GArray *sizes;
static void vcpu_insn_exec_before(unsigned int cpu_index, void *udata)
{
@@ -49,13 +51,35 @@ static void vcpu_tb_trans(qemu_plugin_id_t id, struct qemu_plugin_tb *tb)
insn, vcpu_insn_exec_before, QEMU_PLUGIN_CB_NO_REGS,
GUINT_TO_POINTER(vaddr));
}
+
+ if (do_size) {
+ size_t sz = qemu_plugin_insn_size(insn);
+ if (sz > sizes->len) {
+ g_array_set_size(sizes, sz);
+ }
+ unsigned long *cnt = &g_array_index(sizes, unsigned long, sz);
+ (*cnt)++;
+ }
}
}
static void plugin_exit(qemu_plugin_id_t id, void *p)
{
- g_autofree gchar *out = g_strdup_printf("insns: %" PRIu64 "\n", insn_count);
- qemu_plugin_outs(out);
+ g_autoptr(GString) out = g_string_new(NULL);
+
+ if (do_size) {
+ int i;
+ for (i = 0; i <= sizes->len; i++) {
+ unsigned long *cnt = &g_array_index(sizes, unsigned long, i);
+ if (*cnt) {
+ g_string_append_printf(out,
+ "len %d bytes: %ld insns\n", i, *cnt);
+ }
+ }
+ } else {
+ g_string_append_printf(out, "insns: %" PRIu64 "\n", insn_count);
+ }
+ qemu_plugin_outs(out->str);
}
QEMU_PLUGIN_EXPORT int qemu_plugin_install(qemu_plugin_id_t id,
@@ -70,12 +94,21 @@ QEMU_PLUGIN_EXPORT int qemu_plugin_install(qemu_plugin_id_t id,
fprintf(stderr, "boolean argument parsing failed: %s\n", opt);
return -1;
}
+ } else if (g_strcmp0(tokens[0], "sizes") == 0) {
+ if (!qemu_plugin_bool_parse(tokens[0], tokens[1], &do_size)) {
+ fprintf(stderr, "boolean argument parsing failed: %s\n", opt);
+ return -1;
+ }
} else {
fprintf(stderr, "option parsing failed: %s\n", opt);
return -1;
}
}
+ if (do_size) {
+ sizes = g_array_new(true, true, sizeof(unsigned long));
+ }
+
qemu_plugin_register_vcpu_tb_trans_cb(id, vcpu_tb_trans);
qemu_plugin_register_atexit_cb(id, plugin_exit, NULL);
return 0;
diff --git a/tests/tcg/configure.sh b/tests/tcg/configure.sh
index 1f985cc..9b76f58 100755
--- a/tests/tcg/configure.sh
+++ b/tests/tcg/configure.sh
@@ -46,7 +46,7 @@ fi
: ${cross_cc_aarch64="aarch64-linux-gnu-gcc"}
: ${cross_cc_aarch64_be="$cross_cc_aarch64"}
: ${cross_cc_cflags_aarch64_be="-mbig-endian"}
-: $(cross_cc_alpha="alpha-linux-gnu-gcc")
+: ${cross_cc_alpha="alpha-linux-gnu-gcc"}
: ${cross_cc_arm="arm-linux-gnueabihf-gcc"}
: ${cross_cc_cflags_armeb="-mbig-endian"}
: ${cross_cc_hexagon="hexagon-unknown-linux-musl-clang"}
@@ -55,17 +55,19 @@ fi
: ${cross_cc_i386="i686-linux-gnu-gcc"}
: ${cross_cc_cflags_i386="-m32"}
: ${cross_cc_m68k="m68k-linux-gnu-gcc"}
-: $(cross_cc_mips64el="mips64el-linux-gnuabi64-gcc")
-: $(cross_cc_mips64="mips64-linux-gnuabi64-gcc")
-: $(cross_cc_mipsel="mipsel-linux-gnu-gcc")
-: $(cross_cc_mips="mips-linux-gnu-gcc")
+: ${cross_cc_microblaze="microblaze-linux-musl-gcc"}
+: ${cross_cc_mips64el="mips64el-linux-gnuabi64-gcc"}
+: ${cross_cc_mips64="mips64-linux-gnuabi64-gcc"}
+: ${cross_cc_mipsel="mipsel-linux-gnu-gcc"}
+: ${cross_cc_mips="mips-linux-gnu-gcc"}
+: ${cross_cc_nios2="nios2-linux-gnu-gcc"}
: ${cross_cc_ppc="powerpc-linux-gnu-gcc"}
: ${cross_cc_cflags_ppc="-m32"}
: ${cross_cc_ppc64="powerpc64-linux-gnu-gcc"}
: ${cross_cc_ppc64le="powerpc64le-linux-gnu-gcc"}
-: $(cross_cc_riscv64="riscv64-linux-gnu-gcc")
+: ${cross_cc_riscv64="riscv64-linux-gnu-gcc"}
: ${cross_cc_s390x="s390x-linux-gnu-gcc"}
-: $(cross_cc_sh4="sh4-linux-gnu-gcc")
+: ${cross_cc_sh4="sh4-linux-gnu-gcc"}
: ${cross_cc_cflags_sparc="-m32 -mv8plus -mcpu=ultrasparc"}
: ${cross_cc_sparc64="sparc64-linux-gnu-gcc"}
: ${cross_cc_cflags_sparc64="-m64 -mcpu=ultrasparc"}
@@ -133,6 +135,11 @@ for target in $target_list; do
container_image=debian-m68k-cross
container_cross_cc=m68k-linux-gnu-gcc
;;
+ microblaze-*)
+ container_hosts=x86_64
+ container_image=debian-microblaze-cross
+ container_cross_cc=microblaze-linux-musl-gcc
+ ;;
mips64el-*)
container_hosts=x86_64
container_image=debian-mips64el-cross
@@ -153,6 +160,11 @@ for target in $target_list; do
container_image=debian-mips-cross
container_cross_cc=mips-linux-gnu-gcc
;;
+ nios2-*)
+ container_hosts=x86_64
+ container_image=debian-nios2-cross
+ container_cross_cc=nios2-linux-gnu-gcc
+ ;;
ppc-*|ppc64abi32-*)
container_hosts=x86_64
container_image=debian-powerpc-test-cross
diff --git a/tests/tcg/multiarch/Makefile.target b/tests/tcg/multiarch/Makefile.target
index 6ccb592..a83efb4a 100644
--- a/tests/tcg/multiarch/Makefile.target
+++ b/tests/tcg/multiarch/Makefile.target
@@ -16,7 +16,6 @@ MULTIARCH_SRCS += $(notdir $(wildcard $(MULTIARCH_SRC)/linux/*.c))
endif
MULTIARCH_TESTS = $(MULTIARCH_SRCS:.c=)
-$(info SRCS=${MULTIARCH_SRCS} and ${MULTIARCH_TESTS})
#
# The following are any additional rules needed to build things
#
@@ -61,8 +60,6 @@ run-gdbstub-sha1: sha1
--bin $< --test $(MULTIARCH_SRC)/gdbstub/sha1.py, \
"basic gdbstub support")
-EXTRA_RUNS += run-gdbstub-sha1
-
run-gdbstub-qxfer-auxv-read: sha1
$(call run-test, $@, $(GDB_SCRIPT) \
--gdb $(HAVE_GDB_BIN) \
@@ -70,11 +67,19 @@ run-gdbstub-qxfer-auxv-read: sha1
--bin $< --test $(MULTIARCH_SRC)/gdbstub/test-qxfer-auxv-read.py, \
"basic gdbstub qXfer:auxv:read support")
+run-gdbstub-thread-breakpoint: testthread
+ $(call run-test, $@, $(GDB_SCRIPT) \
+ --gdb $(HAVE_GDB_BIN) \
+ --qemu $(QEMU) --qargs "$(QEMU_OPTS)" \
+ --bin $< --test $(MULTIARCH_SRC)/gdbstub/test-thread-breakpoint.py, \
+ "hitting a breakpoint on non-main thread")
+
else
run-gdbstub-%:
$(call skip-test, "gdbstub test $*", "need working gdb")
endif
-EXTRA_RUNS += run-gdbstub-sha1 run-gdbstub-qxfer-auxv-read
+EXTRA_RUNS += run-gdbstub-sha1 run-gdbstub-qxfer-auxv-read \
+ run-gdbstub-thread-breakpoint
# ARM Compatible Semi Hosting Tests
#
diff --git a/tests/tcg/multiarch/gdbstub/test-thread-breakpoint.py b/tests/tcg/multiarch/gdbstub/test-thread-breakpoint.py
new file mode 100644
index 0000000..798d508
--- /dev/null
+++ b/tests/tcg/multiarch/gdbstub/test-thread-breakpoint.py
@@ -0,0 +1,60 @@
+from __future__ import print_function
+#
+# Test auxiliary vector is loaded via gdbstub
+#
+# This is launched via tests/guest-debug/run-test.py
+#
+
+import gdb
+import sys
+
+failcount = 0
+
+def report(cond, msg):
+ "Report success/fail of test"
+ if cond:
+ print ("PASS: %s" % (msg))
+ else:
+ print ("FAIL: %s" % (msg))
+ global failcount
+ failcount += 1
+
+def run_test():
+ "Run through the tests one by one"
+
+ sym, ok = gdb.lookup_symbol("thread1_func")
+ gdb.execute("b thread1_func")
+ gdb.execute("c")
+
+ frame = gdb.selected_frame()
+ report(str(frame.function()) == "thread1_func", "break @ %s"%frame)
+
+#
+# This runs as the script it sourced (via -x, via run-test.py)
+#
+try:
+ inferior = gdb.selected_inferior()
+ arch = inferior.architecture()
+ print("ATTACHED: %s" % arch.name())
+except (gdb.error, AttributeError):
+ print("SKIPPING (not connected)", file=sys.stderr)
+ exit(0)
+
+if gdb.parse_and_eval('$pc') == 0:
+ print("SKIP: PC not set")
+ exit(0)
+
+try:
+ # These are not very useful in scripts
+ gdb.execute("set pagination off")
+ gdb.execute("set confirm off")
+
+ # Run the actual tests
+ run_test()
+except (gdb.error):
+ print ("GDB Exception: %s" % (sys.exc_info()[0]))
+ failcount += 1
+ pass
+
+print("All tests complete: %d failures" % failcount)
+exit(failcount)
diff --git a/tests/tcg/nios2/Makefile.target b/tests/tcg/nios2/Makefile.target
new file mode 100644
index 0000000..b38e235
--- /dev/null
+++ b/tests/tcg/nios2/Makefile.target
@@ -0,0 +1,11 @@
+# nios2 specific test tweaks
+
+# Currently nios2 signal handling is broken
+run-signals: signals
+ $(call skip-test, $<, "BROKEN")
+run-plugin-signals-with-%:
+ $(call skip-test, $<, "BROKEN")
+run-linux-test: linux-test
+ $(call skip-test, $<, "BROKEN")
+run-plugin-linux-test-with-%:
+ $(call skip-test, $<, "BROKEN")
diff --git a/tests/tcg/sh4/Makefile.target b/tests/tcg/sh4/Makefile.target
index 47c39a4..0e96aef 100644
--- a/tests/tcg/sh4/Makefile.target
+++ b/tests/tcg/sh4/Makefile.target
@@ -12,3 +12,9 @@ run-signals: signals
$(call skip-test, $<, "BROKEN")
run-plugin-signals-with-%:
$(call skip-test, $<, "BROKEN")
+
+# This test is currently broken: https://gitlab.com/qemu-project/qemu/-/issues/704
+run-linux-test: linux-test
+ $(call skip-test, $<, "BROKEN")
+run-plugin-linux-test-with-%:
+ $(call skip-test, $<, "BROKEN")
diff --git a/tests/vm/openbsd b/tests/vm/openbsd
index c4c78a8..337fe7c 100755
--- a/tests/vm/openbsd
+++ b/tests/vm/openbsd
@@ -22,8 +22,8 @@ class OpenBSDVM(basevm.BaseVM):
name = "openbsd"
arch = "x86_64"
- link = "https://cdn.openbsd.org/pub/OpenBSD/6.9/amd64/install69.iso"
- csum = "140d26548aec680e34bb5f82295414228e7f61e4f5e7951af066014fda2d6e43"
+ link = "https://cdn.openbsd.org/pub/OpenBSD/7.0/amd64/install70.iso"
+ csum = "1882f9a23c9800e5dba3dbd2cf0126f552605c915433ef4c5bb672610a4ca3a4"
size = "20G"
pkgs = [
# tools
@@ -95,10 +95,9 @@ class OpenBSDVM(basevm.BaseVM):
self.console_wait_send("Terminal type", "xterm\n")
self.console_wait_send("System hostname", "openbsd\n")
self.console_wait_send("Which network interface", "vio0\n")
- self.console_wait_send("IPv4 address", "dhcp\n")
+ self.console_wait_send("IPv4 address", "autoconf\n")
self.console_wait_send("IPv6 address", "none\n")
self.console_wait_send("Which network interface", "done\n")
- self.console_wait_send("DNS domain name", "localnet\n")
self.console_wait("Password for root account")
self.console_send("%s\n" % self._config["root_pass"])
self.console_wait("Password for root account")