contrib/plugins/uftrace.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-)
This adds RiscV virtual user and supervisor privilege levels to
uftrace plugin to avoid crashing with H extension guests.
Signed-off-by: Yanfeng Liu <yfliu2008@qq.com>
---
contrib/plugins/uftrace.c | 13 ++++++++++---
1 file changed, 10 insertions(+), 3 deletions(-)
diff --git a/contrib/plugins/uftrace.c b/contrib/plugins/uftrace.c
index 9b0a4963ae..063e32220b 100644
--- a/contrib/plugins/uftrace.c
+++ b/contrib/plugins/uftrace.c
@@ -109,6 +109,8 @@ typedef enum {
RISCV64_SUPERVISOR,
RISCV64_RESERVED,
RISCV64_MACHINE,
+ RISCV64_VUSER,
+ RISCV64_VSUPERVISOR,
RISCV64_PRIVILEGE_LEVEL_MAX,
} Riscv64PrivilegeLevel;
@@ -153,8 +155,10 @@ static void uftrace_write_map(bool system_emulation)
const char *path = "./uftrace.data/sid-0.map";
if (system_emulation && access(path, F_OK) == 0) {
- /* do not erase existing map in system emulation, as a custom one might
- * already have been generated by uftrace_symbols.py */
+ /*
+ * do not erase existing map in system emulation, as a custom one might
+ * already have been generated by uftrace_symbols.py
+ */
return;
}
@@ -706,6 +710,8 @@ static const char *riscv64_get_privilege_level_name(uint8_t pl)
case RISCV64_SUPERVISOR: return "Supervisor";
case RISCV64_RESERVED: return "Unknown";
case RISCV64_MACHINE: return "Machine";
+ case RISCV64_VUSER: return "VUser";
+ case RISCV64_VSUPERVISOR: return "VSupervisor";
default:
g_assert_not_reached();
}
@@ -986,7 +992,8 @@ QEMU_PLUGIN_EXPORT int qemu_plugin_install(qemu_plugin_id_t id,
score = qemu_plugin_scoreboard_new(sizeof(Cpu));
qemu_plugin_register_vcpu_init_cb(id, vcpu_init, NULL);
- qemu_plugin_register_atexit_cb(id, at_exit, (void *) info->system_emulation);
+ qemu_plugin_register_atexit_cb(id, at_exit,
+ (void *) info->system_emulation);
qemu_plugin_register_vcpu_tb_trans_cb(id, vcpu_tb_trans, NULL);
return 0;
--
2.34.1
On 7/12/2026 1:45 AM, Yanfeng Liu wrote:
> This adds RiscV virtual user and supervisor privilege levels to
> uftrace plugin to avoid crashing with H extension guests.
>
> Signed-off-by: Yanfeng Liu <yfliu2008@qq.com>
> ---
> contrib/plugins/uftrace.c | 13 ++++++++++---
> 1 file changed, 10 insertions(+), 3 deletions(-)
>
> diff --git a/contrib/plugins/uftrace.c b/contrib/plugins/uftrace.c
> index 9b0a4963ae..063e32220b 100644
> --- a/contrib/plugins/uftrace.c
> +++ b/contrib/plugins/uftrace.c
> @@ -109,6 +109,8 @@ typedef enum {
> RISCV64_SUPERVISOR,
> RISCV64_RESERVED,
> RISCV64_MACHINE,
> + RISCV64_VUSER,
> + RISCV64_VSUPERVISOR,
> RISCV64_PRIVILEGE_LEVEL_MAX,
> } Riscv64PrivilegeLevel;
>
> @@ -153,8 +155,10 @@ static void uftrace_write_map(bool system_emulation)
> const char *path = "./uftrace.data/sid-0.map";
>
> if (system_emulation && access(path, F_OK) == 0) {
> - /* do not erase existing map in system emulation, as a custom one might
> - * already have been generated by uftrace_symbols.py */
> + /*
> + * do not erase existing map in system emulation, as a custom one might
> + * already have been generated by uftrace_symbols.py
> + */
> return;
> }
>
> @@ -706,6 +710,8 @@ static const char *riscv64_get_privilege_level_name(uint8_t pl)
> case RISCV64_SUPERVISOR: return "Supervisor";
> case RISCV64_RESERVED: return "Unknown";
> case RISCV64_MACHINE: return "Machine";
> + case RISCV64_VUSER: return "VUser";
> + case RISCV64_VSUPERVISOR: return "VSupervisor";
> default:
> g_assert_not_reached();
> }
> @@ -986,7 +992,8 @@ QEMU_PLUGIN_EXPORT int qemu_plugin_install(qemu_plugin_id_t id,
>
> score = qemu_plugin_scoreboard_new(sizeof(Cpu));
> qemu_plugin_register_vcpu_init_cb(id, vcpu_init, NULL);
> - qemu_plugin_register_atexit_cb(id, at_exit, (void *) info->system_emulation);
> + qemu_plugin_register_atexit_cb(id, at_exit,
> + (void *) info->system_emulation);
> qemu_plugin_register_vcpu_tb_trans_cb(id, vcpu_tb_trans, NULL);
>
> return 0;
This was merged into master (c149f7b367fe85edd1c438ecfd876f0c80a6ab11).
Thank you for your contribution!
Regards,
Pierrick
Hi,
On 7/12/2026 1:45 AM, Yanfeng Liu wrote:
> This adds RiscV virtual user and supervisor privilege levels to
> uftrace plugin to avoid crashing with H extension guests.
>
> Signed-off-by: Yanfeng Liu <yfliu2008@qq.com>
> ---
> contrib/plugins/uftrace.c | 13 ++++++++++---
> 1 file changed, 10 insertions(+), 3 deletions(-)
>
> diff --git a/contrib/plugins/uftrace.c b/contrib/plugins/uftrace.c
> index 9b0a4963ae..063e32220b 100644
> --- a/contrib/plugins/uftrace.c
> +++ b/contrib/plugins/uftrace.c
> @@ -109,6 +109,8 @@ typedef enum {
> RISCV64_SUPERVISOR,
> RISCV64_RESERVED,
> RISCV64_MACHINE,
> + RISCV64_VUSER,
> + RISCV64_VSUPERVISOR,
> RISCV64_PRIVILEGE_LEVEL_MAX,
> } Riscv64PrivilegeLevel;
>
> @@ -153,8 +155,10 @@ static void uftrace_write_map(bool system_emulation)
> const char *path = "./uftrace.data/sid-0.map";
>
> if (system_emulation && access(path, F_OK) == 0) {
> - /* do not erase existing map in system emulation, as a custom one might
> - * already have been generated by uftrace_symbols.py */
> + /*
> + * do not erase existing map in system emulation, as a custom one might
> + * already have been generated by uftrace_symbols.py
> + */
> return;
> }
>
> @@ -706,6 +710,8 @@ static const char *riscv64_get_privilege_level_name(uint8_t pl)
> case RISCV64_SUPERVISOR: return "Supervisor";
> case RISCV64_RESERVED: return "Unknown";
> case RISCV64_MACHINE: return "Machine";
> + case RISCV64_VUSER: return "VUser";
> + case RISCV64_VSUPERVISOR: return "VSupervisor";
> default:
> g_assert_not_reached();
> }
> @@ -986,7 +992,8 @@ QEMU_PLUGIN_EXPORT int qemu_plugin_install(qemu_plugin_id_t id,
>
> score = qemu_plugin_scoreboard_new(sizeof(Cpu));
> qemu_plugin_register_vcpu_init_cb(id, vcpu_init, NULL);
> - qemu_plugin_register_atexit_cb(id, at_exit, (void *) info->system_emulation);
> + qemu_plugin_register_atexit_cb(id, at_exit,
> + (void *) info->system_emulation);
> qemu_plugin_register_vcpu_tb_trans_cb(id, vcpu_tb_trans, NULL);
>
> return 0;
Is that something we have implemented in upstream QEMU for riscv64
target? From what I can see, priv register only can have M,S,U values.
Regards,
Pierrick
On 7/13/2026 8:59 AM, Pierrick Bouvier wrote:
> Hi,
>
> On 7/12/2026 1:45 AM, Yanfeng Liu wrote:
>> This adds RiscV virtual user and supervisor privilege levels to
>> uftrace plugin to avoid crashing with H extension guests.
>>
>> Signed-off-by: Yanfeng Liu <yfliu2008@qq.com>
>> ---
>> contrib/plugins/uftrace.c | 13 ++++++++++---
>> 1 file changed, 10 insertions(+), 3 deletions(-)
>>
>> diff --git a/contrib/plugins/uftrace.c b/contrib/plugins/uftrace.c
>> index 9b0a4963ae..063e32220b 100644
>> --- a/contrib/plugins/uftrace.c
>> +++ b/contrib/plugins/uftrace.c
>> @@ -109,6 +109,8 @@ typedef enum {
>> RISCV64_SUPERVISOR,
>> RISCV64_RESERVED,
>> RISCV64_MACHINE,
>> + RISCV64_VUSER,
>> + RISCV64_VSUPERVISOR,
>> RISCV64_PRIVILEGE_LEVEL_MAX,
>> } Riscv64PrivilegeLevel;
>>
>> @@ -153,8 +155,10 @@ static void uftrace_write_map(bool system_emulation)
>> const char *path = "./uftrace.data/sid-0.map";
>>
>> if (system_emulation && access(path, F_OK) == 0) {
>> - /* do not erase existing map in system emulation, as a custom one might
>> - * already have been generated by uftrace_symbols.py */
>> + /*
>> + * do not erase existing map in system emulation, as a custom one might
>> + * already have been generated by uftrace_symbols.py
>> + */
>> return;
>> }
>>
>> @@ -706,6 +710,8 @@ static const char *riscv64_get_privilege_level_name(uint8_t pl)
>> case RISCV64_SUPERVISOR: return "Supervisor";
>> case RISCV64_RESERVED: return "Unknown";
>> case RISCV64_MACHINE: return "Machine";
>> + case RISCV64_VUSER: return "VUser";
>> + case RISCV64_VSUPERVISOR: return "VSupervisor";
>> default:
>> g_assert_not_reached();
>> }
>> @@ -986,7 +992,8 @@ QEMU_PLUGIN_EXPORT int qemu_plugin_install(qemu_plugin_id_t id,
>>
>> score = qemu_plugin_scoreboard_new(sizeof(Cpu));
>> qemu_plugin_register_vcpu_init_cb(id, vcpu_init, NULL);
>> - qemu_plugin_register_atexit_cb(id, at_exit, (void *) info->system_emulation);
>> + qemu_plugin_register_atexit_cb(id, at_exit,
>> + (void *) info->system_emulation);
>> qemu_plugin_register_vcpu_tb_trans_cb(id, vcpu_tb_trans, NULL);
>>
>> return 0;
>
>
> Is that something we have implemented in upstream QEMU for riscv64
> target? From what I can see, priv register only can have M,S,U values.
>
Found the answer here:
https://gitlab.com/qemu-project/qemu/-/blob/master/target/riscv/gdbstub.c?ref_type=heads#L213
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@oss.qualcomm.com>
I'll pull this, thanks.
Pierrick
On Sun, 2026-07-12 at 16:45 +0800, Yanfeng Liu wrote:
> This adds RiscV virtual user and supervisor privilege levels to
> uftrace plugin to avoid crashing with H extension guests.
>
> Signed-off-by: Yanfeng Liu <yfliu2008@qq.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Alistair
> ---
> contrib/plugins/uftrace.c | 13 ++++++++++---
> 1 file changed, 10 insertions(+), 3 deletions(-)
>
> diff --git a/contrib/plugins/uftrace.c b/contrib/plugins/uftrace.c
> index 9b0a4963ae..063e32220b 100644
> --- a/contrib/plugins/uftrace.c
> +++ b/contrib/plugins/uftrace.c
> @@ -109,6 +109,8 @@ typedef enum {
> RISCV64_SUPERVISOR,
> RISCV64_RESERVED,
> RISCV64_MACHINE,
> + RISCV64_VUSER,
> + RISCV64_VSUPERVISOR,
> RISCV64_PRIVILEGE_LEVEL_MAX,
> } Riscv64PrivilegeLevel;
>
> @@ -153,8 +155,10 @@ static void uftrace_write_map(bool
> system_emulation)
> const char *path = "./uftrace.data/sid-0.map";
>
> if (system_emulation && access(path, F_OK) == 0) {
> - /* do not erase existing map in system emulation, as a
> custom one might
> - * already have been generated by uftrace_symbols.py */
> + /*
> + * do not erase existing map in system emulation, as a
> custom one might
> + * already have been generated by uftrace_symbols.py
> + */
> return;
> }
>
> @@ -706,6 +710,8 @@ static const char
> *riscv64_get_privilege_level_name(uint8_t pl)
> case RISCV64_SUPERVISOR: return "Supervisor";
> case RISCV64_RESERVED: return "Unknown";
> case RISCV64_MACHINE: return "Machine";
> + case RISCV64_VUSER: return "VUser";
> + case RISCV64_VSUPERVISOR: return "VSupervisor";
> default:
> g_assert_not_reached();
> }
> @@ -986,7 +992,8 @@ QEMU_PLUGIN_EXPORT int
> qemu_plugin_install(qemu_plugin_id_t id,
>
> score = qemu_plugin_scoreboard_new(sizeof(Cpu));
> qemu_plugin_register_vcpu_init_cb(id, vcpu_init, NULL);
> - qemu_plugin_register_atexit_cb(id, at_exit, (void *) info-
> >system_emulation);
> + qemu_plugin_register_atexit_cb(id, at_exit,
> + (void *) info->system_emulation);
> qemu_plugin_register_vcpu_tb_trans_cb(id, vcpu_tb_trans, NULL);
>
> return 0;
© 2016 - 2026 Red Hat, Inc.