contrib/plugins/uftrace: add riscv64 support

Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Link: https://lore.kernel.org/qemu-devel/20260210201344.1403613-5-pierrick.bouvier@linaro.org
Signed-off-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
This commit is contained in:
Pierrick Bouvier
2026-02-10 12:13:44 -08:00
parent 5f43899e76
commit e82d8af3da
2 changed files with 94 additions and 3 deletions

View File

@@ -99,6 +99,19 @@ typedef struct {
struct qemu_plugin_register *reg_cr0;
} X64Cpu;
typedef struct {
struct qemu_plugin_register *reg_fp;
struct qemu_plugin_register *reg_priv;
} Riscv64Cpu;
typedef enum {
RISCV64_USER,
RISCV64_SUPERVISOR,
RISCV64_RESERVED,
RISCV64_MACHINE,
RISCV64_PRIVILEGE_LEVEL_MAX,
} Riscv64PrivilegeLevel;
typedef struct {
uint64_t timestamp;
uint64_t data;
@@ -681,6 +694,78 @@ static CpuOps x64_ops = {
.does_insn_modify_frame_pointer = x64_does_insn_modify_frame_pointer,
};
static uint8_t riscv64_num_privilege_levels(void)
{
return RISCV64_PRIVILEGE_LEVEL_MAX;
}
static const char *riscv64_get_privilege_level_name(uint8_t pl)
{
switch (pl) {
case RISCV64_USER: return "User";
case RISCV64_SUPERVISOR: return "Supervisor";
case RISCV64_RESERVED: return "Unknown";
case RISCV64_MACHINE: return "Machine";
default:
g_assert_not_reached();
}
}
static uint8_t riscv64_get_privilege_level(Cpu *cpu_)
{
Riscv64Cpu *cpu = cpu_->arch;
return cpu_read_register64(cpu_, cpu->reg_priv);
}
static uint64_t riscv64_get_frame_pointer(Cpu *cpu_)
{
Riscv64Cpu *cpu = cpu_->arch;
return cpu_read_register64(cpu_, cpu->reg_fp);
}
static uint64_t riscv64_get_next_frame_pointer(Cpu *cpu_, uint64_t fp)
{
return cpu_read_memory64(cpu_, fp - 16);
}
static uint64_t riscv64_get_next_return_address(Cpu *cpu_, uint64_t fp)
{
return cpu_read_memory64(cpu_, fp - 8);
}
static void riscv64_init(Cpu *cpu_)
{
Riscv64Cpu *cpu = g_new0(Riscv64Cpu, 1);
cpu_->arch = cpu;
cpu->reg_fp = plugin_find_register("fp");
g_assert(cpu->reg_fp);
cpu->reg_priv = plugin_find_register("priv");
g_assert(cpu->reg_priv);
}
static void riscv64_end(Cpu *cpu)
{
g_free(cpu->arch);
}
static bool riscv64_does_insn_modify_frame_pointer(const char *disas)
{
/* fp is s0 in disassembly */
return strstr(disas, "s0");
}
static CpuOps riscv64_ops = {
.init = riscv64_init,
.end = riscv64_end,
.get_frame_pointer = riscv64_get_frame_pointer,
.get_next_frame_pointer = riscv64_get_next_frame_pointer,
.get_next_return_address = riscv64_get_next_return_address,
.get_privilege_level = riscv64_get_privilege_level,
.num_privilege_levels = riscv64_num_privilege_levels,
.get_privilege_level_name = riscv64_get_privilege_level_name,
.does_insn_modify_frame_pointer = riscv64_does_insn_modify_frame_pointer,
};
static void track_privilege_change(unsigned int cpu_index, void *udata)
{
Cpu *cpu = qemu_plugin_scoreboard_find(score, cpu_index);
@@ -890,6 +975,8 @@ QEMU_PLUGIN_EXPORT int qemu_plugin_install(qemu_plugin_id_t id,
arch_ops = aarch64_ops;
} else if (!strcmp(info->target_name, "x86_64")) {
arch_ops = x64_ops;
} else if (!strcmp(info->target_name, "riscv64")) {
arch_ops = riscv64_ops;
} else {
fprintf(stderr, "plugin uftrace: %s target is not supported\n",
info->target_name);

View File

@@ -836,8 +836,8 @@ Uftrace
This plugin generates a binary trace compatible with
`uftrace <https://github.com/namhyung/uftrace>`_.
Plugin supports aarch64 and x64, and works in user and system mode, allowing to
trace a system boot, which is not something possible usually.
Plugin supports aarch64, x64 and riscv64, and works in user and system mode,
allowing to trace a system boot, which is not something possible usually.
In user mode, the memory mapping is directly copied from ``/proc/self/maps`` at
the end of execution. Uftrace should be able to retrieve symbols by itself,
@@ -872,7 +872,7 @@ Performance wise, overhead compared to normal tcg execution is around x5-x15.
- Description
* - trace-privilege-level=[on|off]
- Generate separate traces for each privilege level (Exception Level +
Security State on aarch64, Rings on x64).
Security State on aarch64, Privilege levels on riscv64 and Rings on x64).
.. list-table:: uftrace_symbols.py arguments
:widths: 20 80
@@ -976,6 +976,10 @@ You can follow the exact same instructions for a x64 system, combining edk2,
Linux, and Ubuntu, simply by switching to
`x86_64 <https://github.com/pbo-linaro/qemu-linux-stack/tree/x86_64>`_ branch.
You can follow the exact same instructions for a riscv64 system, combining
opensbi, Linux, and Ubuntu, simply by switching to
`riscv64 <https://github.com/pbo-linaro/qemu-linux-stack/tree/riscv64>`_ branch.
To build and run the system::
# Install dependencies