mirror of https://gitee.com/openkylin/qemu.git
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 -----BEGIN PGP SIGNATURE----- iQEzBAABCgAdFiEEZoWumedRZ7yvyN81+9DbCVqeKkQFAmGDzqsACgkQ+9DbCVqe KkSu3Qf9Ffs7hGZUc++RZxdKt7lkrTHdUxcK1Lj9BGXppGhfTBgC4mMJLYBCiI7b jxhZeGl5LcLjnDdWRkeTgy/hG8JZ26hURxFimdA6Jt4i3JNTQXxjdH6PmOGYCivE dO2Ji5yGErZhr1wEXYWaXvyaU5g/Jzuvwi/duUDilpb2dm4ZuPUCM41vsBLVbcT3 kZ6aT1oJuM+hd2PLbzDP4KTiFWszLMMLYEfrhYPIjtzbrI+v5ACs/pblsYVqfi5o Hfu0FaEbAHg9RnVeXWrurq4VheiByyjceQWG7/E6nAz1IaXttGOaV24B6KpQY7ji zRkZNcu2o3pNQ7n+QM8dEeJKW7LcYQ== =R54t -----END PGP SIGNATURE----- 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>
This commit is contained in:
commit
18e356a53a
|
@ -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>
|
||||
|
|
|
@ -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);
|
||||
|
||||
/*
|
||||
|
|
|
@ -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; \
|
||||
}
|
||||
|
||||
|
|
|
@ -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':
|
||||
|
|
|
@ -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 GMutex *dcache_locks;
|
||||
static GMutex *icache_locks;
|
||||
static bool use_l2;
|
||||
static Cache **l2_ucaches;
|
||||
|
||||
static uint64_t all_dmem_accesses;
|
||||
static uint64_t all_imem_accesses;
|
||||
static uint64_t all_imisses;
|
||||
static uint64_t all_dmisses;
|
||||
static GMutex *l1_dcache_locks;
|
||||
static GMutex *l1_icache_locks;
|
||||
static GMutex *l2_ucache_locks;
|
||||
|
||||
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->dmisses, 1, __ATOMIC_SEQ_CST);
|
||||
dcaches[cache_idx]->misses++;
|
||||
__atomic_fetch_add(&insn->l1_dmisses, 1, __ATOMIC_SEQ_CST);
|
||||
l1_dcaches[cache_idx]->misses++;
|
||||
}
|
||||
dcaches[cache_idx]->accesses++;
|
||||
g_mutex_unlock(&dcache_locks[cache_idx]);
|
||||
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->l2_misses, 1, __ATOMIC_SEQ_CST);
|
||||
l2_ucaches[cache_idx]->misses++;
|
||||
}
|
||||
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->imisses, 1, __ATOMIC_SEQ_CST);
|
||||
icaches[cache_idx]->misses++;
|
||||
__atomic_fetch_add(&insn->l1_imisses, 1, __ATOMIC_SEQ_CST);
|
||||
l1_icaches[cache_idx]->misses++;
|
||||
}
|
||||
icaches[cache_idx]->accesses++;
|
||||
g_mutex_unlock(&icache_locks[cache_idx]);
|
||||
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->l2_misses, 1, __ATOMIC_SEQ_CST);
|
||||
l2_ucaches[cache_idx]->misses++;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
static void append_stats_line(GString *line, uint64_t daccess, uint64_t dmisses,
|
||||
uint64_t iaccess, uint64_t imisses)
|
||||
{
|
||||
double dmiss_rate, imiss_rate;
|
||||
|
||||
dmiss_rate = ((double) dmisses) / (daccess) * 100.0;
|
||||
imiss_rate = ((double) imisses) / (iaccess) * 100.0;
|
||||
l1_dmiss_rate = ((double) l1_dmisses) / (l1_daccess) * 100.0;
|
||||
l1_imiss_rate = ((double) l1_imisses) / (l1_iaccess) * 100.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);
|
||||
" %9.4lf%%",
|
||||
l1_daccess,
|
||||
l1_dmisses,
|
||||
l1_daccess ? l1_dmiss_rate : 0.0,
|
||||
l1_iaccess,
|
||||
l1_imisses,
|
||||
l1_iaccess ? l1_imiss_rate : 0.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(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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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++) {
|
||||
|
|
|
@ -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'))
|
||||
|
|
|
@ -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'))
|
||||
|
|
|
@ -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();
|
||||
}
|
|
@ -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) \
|
||||
|
|
|
@ -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 ..
|
|
@ -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 ..
|
|
@ -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
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
#
|
||||
|
|
|
@ -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)
|
|
@ -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")
|
|
@ -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")
|
||||
|
|
|
@ -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")
|
||||
|
|
Loading…
Reference in New Issue