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:
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user