Skip to content

Commit

Permalink
Merge tag 'pull-maintainer-updates-060324-1' of https://gitlab.com/st…
Browse files Browse the repository at this point in the history
…squad/qemu into staging

maintainer updates (tests, gdbstub, plugins):

  - expand QOS_PATH_MAX_ELEMENT_SIZE to avoid LTO issues
  - support fork-follow-mode in gdbstub
  - new thread-safe scoreboard API for TCG plugins
  - suppress showing opcodes in plugin disassembly

# -----BEGIN PGP SIGNATURE-----
#
# iQEzBAABCgAdFiEEZoWumedRZ7yvyN81+9DbCVqeKkQFAmXoY7oACgkQ+9DbCVqe
# KkTdTwf8D8nUB+Ee6LuglW36vtd1ETdMfUmfRis7RIBsXZZ0Tg4+8LyfKkNi1vCL
# UMdWQTkSW79RfXr21QEtETokwLZ0CWQMdxDAWfOiz4S+uDgQyBE+lwUsy0mHBmd7
# +J4SQb3adoZ+//9KMJhRU1wL9j3ygpEoKHVJonDObU6K5XuhE18JuBE44q7FqkWl
# 0VhoLDgNxrf2PqT+LLP/O3MFLDXPVKbzrZYQF0IoqBTlcqShCoaykhSwiwCZ4Sqq
# NO9hVwZIOFOcOF4F6ZqRXaZrwERldoBwG+BeIx1ah20vKFVT12y02dQqdP/oKwe+
# /PXFXDdzs4yMOghb4Go6SiKlKT5g4A==
# =s1lF
# -----END PGP SIGNATURE-----
# gpg: Signature made Wed 06 Mar 2024 12:38:18 GMT
# gpg:                using RSA key 6685AE99E75167BCAFC8DF35FBD0DB095A9E2A44
# gpg: Good signature from "Alex Bennée (Master Work Key) <alex.bennee@linaro.org>" [full]
# Primary key fingerprint: 6685 AE99 E751 67BC AFC8  DF35 FBD0 DB09 5A9E 2A44

* tag 'pull-maintainer-updates-060324-1' of https://gitlab.com/stsquad/qemu: (29 commits)
  target/riscv: honour show_opcodes when disassembling
  target/loongarch: honour show_opcodes when disassembling
  disas/hppa: honour show_opcodes
  disas: introduce show_opcodes
  plugins: cleanup codepath for previous inline operation
  plugins: remove non per_vcpu inline operation from API
  contrib/plugins/howvec: migrate to new per_vcpu API
  contrib/plugins/hotblocks: migrate to new per_vcpu API
  tests/plugin/bb: migrate to new per_vcpu API
  tests/plugin/insn: migrate to new per_vcpu API
  tests/plugin/mem: migrate to new per_vcpu API
  tests/plugin: add test plugin for inline operations
  plugins: add inline operation per vcpu
  plugins: implement inline operation relative to cpu_index
  plugins: define qemu_plugin_u64
  plugins: scoreboard API
  tests/tcg: Add two follow-fork-mode tests
  gdbstub: Implement follow-fork-mode child
  gdbstub: Introduce gdb_handle_detach_user()
  gdbstub: Introduce gdb_handle_set_thread_user()
  ...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
  • Loading branch information
pm215 committed Mar 6, 2024
2 parents db596ae + db7e8b1 commit 8f6330a
Show file tree
Hide file tree
Showing 57 changed files with 1,257 additions and 338 deletions.
69 changes: 57 additions & 12 deletions accel/tcg/plugin-gen.c
Original file line number Diff line number Diff line change
Expand Up @@ -133,16 +133,28 @@ static void gen_empty_udata_cb_no_rwg(void)
*/
static void gen_empty_inline_cb(void)
{
TCGv_i32 cpu_index = tcg_temp_ebb_new_i32();
TCGv_ptr cpu_index_as_ptr = tcg_temp_ebb_new_ptr();
TCGv_i64 val = tcg_temp_ebb_new_i64();
TCGv_ptr ptr = tcg_temp_ebb_new_ptr();

tcg_gen_ld_i32(cpu_index, tcg_env,
-offsetof(ArchCPU, env) + offsetof(CPUState, cpu_index));
/* second operand will be replaced by immediate value */
tcg_gen_mul_i32(cpu_index, cpu_index, cpu_index);
tcg_gen_ext_i32_ptr(cpu_index_as_ptr, cpu_index);

tcg_gen_movi_ptr(ptr, 0);
tcg_gen_add_ptr(ptr, ptr, cpu_index_as_ptr);
tcg_gen_ld_i64(val, ptr, 0);
/* pass an immediate != 0 so that it doesn't get optimized away */
tcg_gen_addi_i64(val, val, 0xdeadface);
/* second operand will be replaced by immediate value */
tcg_gen_add_i64(val, val, val);

tcg_gen_st_i64(val, ptr, 0);
tcg_temp_free_ptr(ptr);
tcg_temp_free_i64(val);
tcg_temp_free_ptr(cpu_index_as_ptr);
tcg_temp_free_i32(cpu_index);
}

static void gen_empty_mem_cb(TCGv_i64 addr, uint32_t info)
Expand Down Expand Up @@ -290,12 +302,37 @@ static TCGOp *copy_const_ptr(TCGOp **begin_op, TCGOp *op, void *ptr)
return op;
}

static TCGOp *copy_ld_i32(TCGOp **begin_op, TCGOp *op)
{
return copy_op(begin_op, op, INDEX_op_ld_i32);
}

static TCGOp *copy_ext_i32_ptr(TCGOp **begin_op, TCGOp *op)
{
if (UINTPTR_MAX == UINT32_MAX) {
op = copy_op(begin_op, op, INDEX_op_mov_i32);
} else {
op = copy_op(begin_op, op, INDEX_op_ext_i32_i64);
}
return op;
}

static TCGOp *copy_add_ptr(TCGOp **begin_op, TCGOp *op)
{
if (UINTPTR_MAX == UINT32_MAX) {
op = copy_op(begin_op, op, INDEX_op_add_i32);
} else {
op = copy_op(begin_op, op, INDEX_op_add_i64);
}
return op;
}

static TCGOp *copy_ld_i64(TCGOp **begin_op, TCGOp *op)
{
if (TCG_TARGET_REG_BITS == 32) {
/* 2x ld_i32 */
op = copy_op(begin_op, op, INDEX_op_ld_i32);
op = copy_op(begin_op, op, INDEX_op_ld_i32);
op = copy_ld_i32(begin_op, op);
op = copy_ld_i32(begin_op, op);
} else {
/* ld_i64 */
op = copy_op(begin_op, op, INDEX_op_ld_i64);
Expand Down Expand Up @@ -331,6 +368,13 @@ static TCGOp *copy_add_i64(TCGOp **begin_op, TCGOp *op, uint64_t v)
return op;
}

static TCGOp *copy_mul_i32(TCGOp **begin_op, TCGOp *op, uint32_t v)
{
op = copy_op(begin_op, op, INDEX_op_mul_i32);
op->args[2] = tcgv_i32_arg(tcg_constant_i32(v));
return op;
}

static TCGOp *copy_st_ptr(TCGOp **begin_op, TCGOp *op)
{
if (UINTPTR_MAX == UINT32_MAX) {
Expand Down Expand Up @@ -396,18 +440,19 @@ static TCGOp *append_inline_cb(const struct qemu_plugin_dyn_cb *cb,
TCGOp *begin_op, TCGOp *op,
int *unused)
{
/* const_ptr */
op = copy_const_ptr(&begin_op, op, cb->userp);
char *ptr = cb->inline_insn.entry.score->data->data;
size_t elem_size = g_array_get_element_size(
cb->inline_insn.entry.score->data);
size_t offset = cb->inline_insn.entry.offset;

/* ld_i64 */
op = copy_ld_i32(&begin_op, op);
op = copy_mul_i32(&begin_op, op, elem_size);
op = copy_ext_i32_ptr(&begin_op, op);
op = copy_const_ptr(&begin_op, op, ptr + offset);
op = copy_add_ptr(&begin_op, op);
op = copy_ld_i64(&begin_op, op);

/* add_i64 */
op = copy_add_i64(&begin_op, op, cb->inline_insn.imm);

/* st_i64 */
op = copy_st_i64(&begin_op, op);

return op;
}

Expand Down
2 changes: 1 addition & 1 deletion bsd-user/bsd-file.h
Original file line number Diff line number Diff line change
Expand Up @@ -641,7 +641,7 @@ static abi_long do_bsd_readlink(CPUArchState *env, abi_long arg1,
}
if (strcmp(p1, "/proc/curproc/file") == 0) {
CPUState *cpu = env_cpu(env);
TaskState *ts = (TaskState *)cpu->opaque;
TaskState *ts = get_task_state(cpu);
strncpy(p2, ts->bprm->fullpath, arg3);
ret = MIN((abi_long)strlen(ts->bprm->fullpath), arg3);
} else {
Expand Down
6 changes: 3 additions & 3 deletions bsd-user/freebsd/os-proc.h
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ static inline abi_long do_freebsd_fork(void *cpu_env)
*/
set_second_rval(cpu_env, child_flag);

fork_end(child_flag);
fork_end(ret);

return ret;
}
Expand Down Expand Up @@ -252,7 +252,7 @@ static inline abi_long do_freebsd_rfork(void *cpu_env, abi_long flags)
* value: 0 for parent process, 1 for child process.
*/
set_second_rval(cpu_env, child_flag);
fork_end(child_flag);
fork_end(ret);

return ret;

Expand Down Expand Up @@ -285,7 +285,7 @@ static inline abi_long do_freebsd_pdfork(void *cpu_env, abi_ulong target_fdp,
* value: 0 for parent process, 1 for child process.
*/
set_second_rval(cpu_env, child_flag);
fork_end(child_flag);
fork_end(ret);

return ret;
}
Expand Down
9 changes: 7 additions & 2 deletions bsd-user/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -113,10 +113,13 @@ void fork_start(void)
start_exclusive();
cpu_list_lock();
mmap_fork_start();
gdbserver_fork_start();
}

void fork_end(int child)
void fork_end(pid_t pid)
{
bool child = pid == 0;

if (child) {
CPUState *cpu, *next_cpu;
/*
Expand All @@ -134,10 +137,12 @@ void fork_end(int child)
* state, so we don't need to end_exclusive() here.
*/
qemu_init_cpu_list();
gdbserver_fork(thread_cpu);
get_task_state(thread_cpu)->ts_tid = qemu_get_thread_id();
gdbserver_fork_end(thread_cpu, pid);
} else {
mmap_fork_end(child);
cpu_list_unlock();
gdbserver_fork_end(thread_cpu, pid);
end_exclusive();
}
}
Expand Down
7 changes: 6 additions & 1 deletion bsd-user/qemu.h
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,11 @@ typedef struct TaskState {
struct target_sigaltstack sigaltstack_used;
} __attribute__((aligned(16))) TaskState;

static inline TaskState *get_task_state(CPUState *cs)
{
return cs->opaque;
}

void stop_all_tasks(void);
extern const char *interp_prefix;
extern const char *qemu_uname_release;
Expand Down Expand Up @@ -187,7 +192,7 @@ void cpu_loop(CPUArchState *env);
char *target_strerror(int err);
int get_osversion(void);
void fork_start(void);
void fork_end(int child);
void fork_end(pid_t pid);

#include "qemu/log.h"

Expand Down
20 changes: 10 additions & 10 deletions bsd-user/signal.c
Original file line number Diff line number Diff line change
Expand Up @@ -319,7 +319,7 @@ void host_to_target_siginfo(target_siginfo_t *tinfo, const siginfo_t *info)

int block_signals(void)
{
TaskState *ts = (TaskState *)thread_cpu->opaque;
TaskState *ts = get_task_state(thread_cpu);
sigset_t set;

/*
Expand Down Expand Up @@ -359,7 +359,7 @@ void dump_core_and_abort(int target_sig)
{
CPUState *cpu = thread_cpu;
CPUArchState *env = cpu_env(cpu);
TaskState *ts = cpu->opaque;
TaskState *ts = get_task_state(cpu);
int core_dumped = 0;
int host_sig;
struct sigaction act;
Expand Down Expand Up @@ -421,7 +421,7 @@ void queue_signal(CPUArchState *env, int sig, int si_type,
target_siginfo_t *info)
{
CPUState *cpu = env_cpu(env);
TaskState *ts = cpu->opaque;
TaskState *ts = get_task_state(cpu);

trace_user_queue_signal(env, sig);

Expand Down Expand Up @@ -476,7 +476,7 @@ void force_sig_fault(int sig, int code, abi_ulong addr)
static void host_signal_handler(int host_sig, siginfo_t *info, void *puc)
{
CPUState *cpu = thread_cpu;
TaskState *ts = cpu->opaque;
TaskState *ts = get_task_state(cpu);
target_siginfo_t tinfo;
ucontext_t *uc = puc;
struct emulated_sigtable *k;
Expand Down Expand Up @@ -585,7 +585,7 @@ static void host_signal_handler(int host_sig, siginfo_t *info, void *puc)
/* compare to kern/kern_sig.c sys_sigaltstack() and kern_sigaltstack() */
abi_long do_sigaltstack(abi_ulong uss_addr, abi_ulong uoss_addr, abi_ulong sp)
{
TaskState *ts = (TaskState *)thread_cpu->opaque;
TaskState *ts = get_task_state(thread_cpu);
int ret;
target_stack_t oss;

Expand Down Expand Up @@ -714,7 +714,7 @@ int do_sigaction(int sig, const struct target_sigaction *act,
static inline abi_ulong get_sigframe(struct target_sigaction *ka,
CPUArchState *env, size_t frame_size)
{
TaskState *ts = (TaskState *)thread_cpu->opaque;
TaskState *ts = get_task_state(thread_cpu);
abi_ulong sp;

/* Use default user stack */
Expand Down Expand Up @@ -789,7 +789,7 @@ static int reset_signal_mask(target_ucontext_t *ucontext)
int i;
sigset_t blocked;
target_sigset_t target_set;
TaskState *ts = (TaskState *)thread_cpu->opaque;
TaskState *ts = get_task_state(thread_cpu);

for (i = 0; i < TARGET_NSIG_WORDS; i++) {
__get_user(target_set.__bits[i], &ucontext->uc_sigmask.__bits[i]);
Expand Down Expand Up @@ -839,7 +839,7 @@ long do_sigreturn(CPUArchState *env, abi_ulong addr)

void signal_init(void)
{
TaskState *ts = (TaskState *)thread_cpu->opaque;
TaskState *ts = get_task_state(thread_cpu);
struct sigaction act;
struct sigaction oact;
int i;
Expand Down Expand Up @@ -878,7 +878,7 @@ static void handle_pending_signal(CPUArchState *env, int sig,
struct emulated_sigtable *k)
{
CPUState *cpu = env_cpu(env);
TaskState *ts = cpu->opaque;
TaskState *ts = get_task_state(cpu);
struct target_sigaction *sa;
int code;
sigset_t set;
Expand Down Expand Up @@ -967,7 +967,7 @@ void process_pending_signals(CPUArchState *env)
int sig;
sigset_t *blocked_set, set;
struct emulated_sigtable *k;
TaskState *ts = cpu->opaque;
TaskState *ts = get_task_state(cpu);

while (qatomic_read(&ts->signal_pending)) {
sigfillset(&set);
Expand Down
50 changes: 30 additions & 20 deletions contrib/plugins/hotblocks.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,16 +34,26 @@ static guint64 limit = 20;
*/
typedef struct {
uint64_t start_addr;
uint64_t exec_count;
int trans_count;
struct qemu_plugin_scoreboard *exec_count;
int trans_count;
unsigned long insns;
} ExecCount;

static gint cmp_exec_count(gconstpointer a, gconstpointer b)
{
ExecCount *ea = (ExecCount *) a;
ExecCount *eb = (ExecCount *) b;
return ea->exec_count > eb->exec_count ? -1 : 1;
uint64_t count_a =
qemu_plugin_u64_sum(qemu_plugin_scoreboard_u64(ea->exec_count));
uint64_t count_b =
qemu_plugin_u64_sum(qemu_plugin_scoreboard_u64(eb->exec_count));
return count_a > count_b ? -1 : 1;
}

static void exec_count_free(gpointer key, gpointer value, gpointer user_data)
{
ExecCount *cnt = value;
qemu_plugin_scoreboard_free(cnt->exec_count);
}

static void plugin_exit(qemu_plugin_id_t id, void *p)
Expand All @@ -52,7 +62,6 @@ static void plugin_exit(qemu_plugin_id_t id, void *p)
GList *counts, *it;
int i;

g_mutex_lock(&lock);
g_string_append_printf(report, "%d entries in the hash table\n",
g_hash_table_size(hotblocks));
counts = g_hash_table_get_values(hotblocks);
Expand All @@ -63,16 +72,21 @@ static void plugin_exit(qemu_plugin_id_t id, void *p)

for (i = 0; i < limit && it->next; i++, it = it->next) {
ExecCount *rec = (ExecCount *) it->data;
g_string_append_printf(report, "0x%016"PRIx64", %d, %ld, %"PRId64"\n",
rec->start_addr, rec->trans_count,
rec->insns, rec->exec_count);
g_string_append_printf(
report, "0x%016"PRIx64", %d, %ld, %"PRId64"\n",
rec->start_addr, rec->trans_count,
rec->insns,
qemu_plugin_u64_sum(
qemu_plugin_scoreboard_u64(rec->exec_count)));
}

g_list_free(it);
}
g_mutex_unlock(&lock);

qemu_plugin_outs(report->str);

g_hash_table_foreach(hotblocks, exec_count_free, NULL);
g_hash_table_destroy(hotblocks);
}

static void plugin_init(void)
Expand All @@ -82,15 +96,9 @@ static void plugin_init(void)

static void vcpu_tb_exec(unsigned int cpu_index, void *udata)
{
ExecCount *cnt;
uint64_t hash = (uint64_t) udata;

g_mutex_lock(&lock);
cnt = (ExecCount *) g_hash_table_lookup(hotblocks, (gconstpointer) hash);
/* should always succeed */
g_assert(cnt);
cnt->exec_count++;
g_mutex_unlock(&lock);
ExecCount *cnt = (ExecCount *)udata;
qemu_plugin_u64_add(qemu_plugin_scoreboard_u64(cnt->exec_count),
cpu_index, 1);
}

/*
Expand All @@ -114,18 +122,20 @@ static void vcpu_tb_trans(qemu_plugin_id_t id, struct qemu_plugin_tb *tb)
cnt->start_addr = pc;
cnt->trans_count = 1;
cnt->insns = insns;
cnt->exec_count = qemu_plugin_scoreboard_new(sizeof(uint64_t));
g_hash_table_insert(hotblocks, (gpointer) hash, (gpointer) cnt);
}

g_mutex_unlock(&lock);

if (do_inline) {
qemu_plugin_register_vcpu_tb_exec_inline(tb, QEMU_PLUGIN_INLINE_ADD_U64,
&cnt->exec_count, 1);
qemu_plugin_register_vcpu_tb_exec_inline_per_vcpu(
tb, QEMU_PLUGIN_INLINE_ADD_U64,
qemu_plugin_scoreboard_u64(cnt->exec_count), 1);
} else {
qemu_plugin_register_vcpu_tb_exec_cb(tb, vcpu_tb_exec,
QEMU_PLUGIN_CB_NO_REGS,
(void *)hash);
(void *)cnt);
}
}

Expand Down

0 comments on commit 8f6330a

Please sign in to comment.