Some registers should be marked as read-only from a plugin API
perspective, as writing to them via qemu_plugin_write_register has no
effect. This includes the program counter, and we expose this fact to
the plugins with this patch.
Signed-off-by: Florian Hofhammer <florian.hofhammer@epfl.ch>
---
include/plugins/qemu-plugin.h | 2 ++
plugins/api.c | 16 ++++++++++++++++
2 files changed, 18 insertions(+)
diff --git a/include/plugins/qemu-plugin.h b/include/plugins/qemu-plugin.h
index 04c884e82b..ae711758f1 100644
--- a/include/plugins/qemu-plugin.h
+++ b/include/plugins/qemu-plugin.h
@@ -979,11 +979,13 @@ struct qemu_plugin_register;
* writing value with qemu_plugin_write_register
* @name: register name
* @feature: optional feature descriptor, can be NULL
+ * @is_readonly: true if the register cannot be written via qemu_plugin_write_register
*/
typedef struct {
struct qemu_plugin_register *handle;
const char *name;
const char *feature;
+ bool is_readonly;
} qemu_plugin_reg_descriptor;
/**
diff --git a/plugins/api.c b/plugins/api.c
index ca3e93a194..b2c52d2a09 100644
--- a/plugins/api.c
+++ b/plugins/api.c
@@ -410,6 +410,12 @@ bool qemu_plugin_bool_parse(const char *name, const char *value, bool *ret)
* ancillary data the plugin might find useful.
*/
+static const char pc_str[] = "pc"; // generic name for program counter
+static const char eip_str[] = "eip"; // x86 specific name for program counter
+static const char rip_str[] = "rip"; // x86_64 specific name for program counter
+static const char pswa_str[] = "pswa"; // s390x specific name for program counter
+static const char iaoq_str[] = "iaoq"; // HP/PA specific name for program counter
+static const char rpc_str[] = "rpc"; // microblaze specific name for program counter
static GArray *create_register_handles(GArray *gdbstub_regs)
{
GArray *find_data = g_array_new(true, true,
@@ -427,6 +433,16 @@ static GArray *create_register_handles(GArray *gdbstub_regs)
/* Create a record for the plugin */
desc.handle = GINT_TO_POINTER(grd->gdb_reg + 1);
desc.name = g_intern_string(grd->name);
+ desc.is_readonly = false;
+ if (g_strcmp0(desc.name, pc_str) == 0
+ || g_strcmp0(desc.name, eip_str) == 0
+ || g_strcmp0(desc.name, rip_str) == 0
+ || g_strcmp0(desc.name, pswa_str) == 0
+ || g_strcmp0(desc.name, iaoq_str) == 0
+ || g_strcmp0(desc.name, rpc_str) == 0
+ ) {
+ desc.is_readonly = true;
+ }
desc.feature = g_intern_string(grd->feature_name);
g_array_append_val(find_data, desc);
}
--
2.53.0
On 24/02/2026 16:53, Florian Hofhammer wrote:
> Some registers should be marked as read-only from a plugin API
> perspective, as writing to them via qemu_plugin_write_register has no
> effect. This includes the program counter, and we expose this fact to
> the plugins with this patch.
>
> Signed-off-by: Florian Hofhammer <florian.hofhammer@epfl.ch>
> ---
> include/plugins/qemu-plugin.h | 2 ++
> plugins/api.c | 16 ++++++++++++++++
> 2 files changed, 18 insertions(+)
>
> diff --git a/include/plugins/qemu-plugin.h b/include/plugins/qemu-plugin.h
> index 04c884e82b..ae711758f1 100644
> --- a/include/plugins/qemu-plugin.h
> +++ b/include/plugins/qemu-plugin.h
> @@ -979,11 +979,13 @@ struct qemu_plugin_register;
> * writing value with qemu_plugin_write_register
> * @name: register name
> * @feature: optional feature descriptor, can be NULL
> + * @is_readonly: true if the register cannot be written via qemu_plugin_write_register
> */
> typedef struct {
> struct qemu_plugin_register *handle;
> const char *name;
> const char *feature;
> + bool is_readonly;
> } qemu_plugin_reg_descriptor;
>
> /**
> diff --git a/plugins/api.c b/plugins/api.c
> index ca3e93a194..b2c52d2a09 100644
> --- a/plugins/api.c
> +++ b/plugins/api.c
> @@ -410,6 +410,12 @@ bool qemu_plugin_bool_parse(const char *name, const char *value, bool *ret)
> * ancillary data the plugin might find useful.
> */
>
> +static const char pc_str[] = "pc"; // generic name for program counter
> +static const char eip_str[] = "eip"; // x86 specific name for program counter
> +static const char rip_str[] = "rip"; // x86_64 specific name for program counter
> +static const char pswa_str[] = "pswa"; // s390x specific name for program counter
> +static const char iaoq_str[] = "iaoq"; // HP/PA specific name for program counter
> +static const char rpc_str[] = "rpc"; // microblaze specific name for program counter
> static GArray *create_register_handles(GArray *gdbstub_regs)
> {
> GArray *find_data = g_array_new(true, true,
> @@ -427,6 +433,16 @@ static GArray *create_register_handles(GArray *gdbstub_regs)
> /* Create a record for the plugin */
> desc.handle = GINT_TO_POINTER(grd->gdb_reg + 1);
> desc.name = g_intern_string(grd->name);
> + desc.is_readonly = false;
> + if (g_strcmp0(desc.name, pc_str) == 0
> + || g_strcmp0(desc.name, eip_str) == 0
> + || g_strcmp0(desc.name, rip_str) == 0
> + || g_strcmp0(desc.name, pswa_str) == 0
> + || g_strcmp0(desc.name, iaoq_str) == 0
> + || g_strcmp0(desc.name, rpc_str) == 0
> + ) {
> + desc.is_readonly = true;
> + }
> desc.feature = g_intern_string(grd->feature_name);
> g_array_append_val(find_data, desc);
> }
While extending the tests for my patches, I noticed that there are other
registers that are effectively read-only as well, such as the vg (vector
granule) register on aarch64. I wonder whether there should be a more
generic support in QEMU for this or whether this is something that
should be handled by GDB instead.
The difference to the pc in that case is that the pc architecturally is
read-write and it was just QEMU who silently swallowed the writes to it.
For the vg register in the example, as far as I understand correctly,
this is not an actual architectural register, but something that GDB
exposes as a read-only register for easier debugging, and QEMU therefore
also exposes this register. However, writes to it with
gdb_write_register and by proxy qemu_plugin_write_register are silently
ignored.
I'm not sure this is something that should be handled in this patch
series but I'm wondering whether this is something you already had on
your radar or whether this should be taken care of in a follow-up patch
series. I'd be happy to get your thoughts on this!
Best regards,
Florian
Florian Hofhammer <florian.hofhammer@epfl.ch> writes:
> On 24/02/2026 16:53, Florian Hofhammer wrote:
>> Some registers should be marked as read-only from a plugin API
>> perspective, as writing to them via qemu_plugin_write_register has no
>> effect. This includes the program counter, and we expose this fact to
>> the plugins with this patch.
>>
>> Signed-off-by: Florian Hofhammer <florian.hofhammer@epfl.ch>
>> ---
>> include/plugins/qemu-plugin.h | 2 ++
>> plugins/api.c | 16 ++++++++++++++++
>> 2 files changed, 18 insertions(+)
>>
>> diff --git a/include/plugins/qemu-plugin.h b/include/plugins/qemu-plugin.h
>> index 04c884e82b..ae711758f1 100644
>> --- a/include/plugins/qemu-plugin.h
>> +++ b/include/plugins/qemu-plugin.h
>> @@ -979,11 +979,13 @@ struct qemu_plugin_register;
>> * writing value with qemu_plugin_write_register
>> * @name: register name
>> * @feature: optional feature descriptor, can be NULL
>> + * @is_readonly: true if the register cannot be written via qemu_plugin_write_register
>> */
>> typedef struct {
>> struct qemu_plugin_register *handle;
>> const char *name;
>> const char *feature;
>> + bool is_readonly;
>> } qemu_plugin_reg_descriptor;
>>
>> /**
>> diff --git a/plugins/api.c b/plugins/api.c
>> index ca3e93a194..b2c52d2a09 100644
>> --- a/plugins/api.c
>> +++ b/plugins/api.c
>> @@ -410,6 +410,12 @@ bool qemu_plugin_bool_parse(const char *name, const char *value, bool *ret)
>> * ancillary data the plugin might find useful.
>> */
>>
>> +static const char pc_str[] = "pc"; // generic name for program counter
>> +static const char eip_str[] = "eip"; // x86 specific name for program counter
>> +static const char rip_str[] = "rip"; // x86_64 specific name for program counter
>> +static const char pswa_str[] = "pswa"; // s390x specific name for program counter
>> +static const char iaoq_str[] = "iaoq"; // HP/PA specific name for program counter
>> +static const char rpc_str[] = "rpc"; // microblaze specific name for program counter
>> static GArray *create_register_handles(GArray *gdbstub_regs)
>> {
>> GArray *find_data = g_array_new(true, true,
>> @@ -427,6 +433,16 @@ static GArray *create_register_handles(GArray *gdbstub_regs)
>> /* Create a record for the plugin */
>> desc.handle = GINT_TO_POINTER(grd->gdb_reg + 1);
>> desc.name = g_intern_string(grd->name);
>> + desc.is_readonly = false;
>> + if (g_strcmp0(desc.name, pc_str) == 0
>> + || g_strcmp0(desc.name, eip_str) == 0
>> + || g_strcmp0(desc.name, rip_str) == 0
>> + || g_strcmp0(desc.name, pswa_str) == 0
>> + || g_strcmp0(desc.name, iaoq_str) == 0
>> + || g_strcmp0(desc.name, rpc_str) == 0
>> + ) {
>> + desc.is_readonly = true;
>> + }
>> desc.feature = g_intern_string(grd->feature_name);
>> g_array_append_val(find_data, desc);
>> }
>
> While extending the tests for my patches, I noticed that there are other
> registers that are effectively read-only as well, such as the vg (vector
> granule) register on aarch64. I wonder whether there should be a more
> generic support in QEMU for this or whether this is something that
> should be handled by GDB instead.
I was chatting to Pierrick about this yesterday. There are also
additional registers I'd like to make available as pure read-only and as
they go through the gdbstub machinery that seems the obvious place to
deal with them.
> The difference to the pc in that case is that the pc architecturally is
> read-write and it was just QEMU who silently swallowed the writes to it.
> For the vg register in the example, as far as I understand correctly,
> this is not an actual architectural register, but something that GDB
> exposes as a read-only register for easier debugging, and QEMU therefore
> also exposes this register. However, writes to it with
> gdb_write_register and by proxy qemu_plugin_write_register are silently
> ignored.
>
> I'm not sure this is something that should be handled in this patch
> series but I'm wondering whether this is something you already had on
> your radar or whether this should be taken care of in a follow-up patch
> series. I'd be happy to get your thoughts on this!
I think this is fine for now - for future enhancements we should extend
the gdb machinery and then reflect that in the exported plugin
registers.
>
> Best regards,
> Florian
--
Alex Bennée
Virtualisation Tech Lead @ Linaro
On 2/26/26 6:33 AM, Alex Bennée wrote:
> Florian Hofhammer <florian.hofhammer@epfl.ch> writes:
>
>> On 24/02/2026 16:53, Florian Hofhammer wrote:
>>> Some registers should be marked as read-only from a plugin API
>>> perspective, as writing to them via qemu_plugin_write_register has no
>>> effect. This includes the program counter, and we expose this fact to
>>> the plugins with this patch.
>>>
>>> Signed-off-by: Florian Hofhammer <florian.hofhammer@epfl.ch>
>>> ---
>>> include/plugins/qemu-plugin.h | 2 ++
>>> plugins/api.c | 16 ++++++++++++++++
>>> 2 files changed, 18 insertions(+)
>>>
>>> diff --git a/include/plugins/qemu-plugin.h b/include/plugins/qemu-plugin.h
>>> index 04c884e82b..ae711758f1 100644
>>> --- a/include/plugins/qemu-plugin.h
>>> +++ b/include/plugins/qemu-plugin.h
>>> @@ -979,11 +979,13 @@ struct qemu_plugin_register;
>>> * writing value with qemu_plugin_write_register
>>> * @name: register name
>>> * @feature: optional feature descriptor, can be NULL
>>> + * @is_readonly: true if the register cannot be written via qemu_plugin_write_register
>>> */
>>> typedef struct {
>>> struct qemu_plugin_register *handle;
>>> const char *name;
>>> const char *feature;
>>> + bool is_readonly;
>>> } qemu_plugin_reg_descriptor;
>>>
>>> /**
>>> diff --git a/plugins/api.c b/plugins/api.c
>>> index ca3e93a194..b2c52d2a09 100644
>>> --- a/plugins/api.c
>>> +++ b/plugins/api.c
>>> @@ -410,6 +410,12 @@ bool qemu_plugin_bool_parse(const char *name, const char *value, bool *ret)
>>> * ancillary data the plugin might find useful.
>>> */
>>>
>>> +static const char pc_str[] = "pc"; // generic name for program counter
>>> +static const char eip_str[] = "eip"; // x86 specific name for program counter
>>> +static const char rip_str[] = "rip"; // x86_64 specific name for program counter
>>> +static const char pswa_str[] = "pswa"; // s390x specific name for program counter
>>> +static const char iaoq_str[] = "iaoq"; // HP/PA specific name for program counter
>>> +static const char rpc_str[] = "rpc"; // microblaze specific name for program counter
>>> static GArray *create_register_handles(GArray *gdbstub_regs)
>>> {
>>> GArray *find_data = g_array_new(true, true,
>>> @@ -427,6 +433,16 @@ static GArray *create_register_handles(GArray *gdbstub_regs)
>>> /* Create a record for the plugin */
>>> desc.handle = GINT_TO_POINTER(grd->gdb_reg + 1);
>>> desc.name = g_intern_string(grd->name);
>>> + desc.is_readonly = false;
>>> + if (g_strcmp0(desc.name, pc_str) == 0
>>> + || g_strcmp0(desc.name, eip_str) == 0
>>> + || g_strcmp0(desc.name, rip_str) == 0
>>> + || g_strcmp0(desc.name, pswa_str) == 0
>>> + || g_strcmp0(desc.name, iaoq_str) == 0
>>> + || g_strcmp0(desc.name, rpc_str) == 0
>>> + ) {
>>> + desc.is_readonly = true;
>>> + }
>>> desc.feature = g_intern_string(grd->feature_name);
>>> g_array_append_val(find_data, desc);
>>> }
>>
>> While extending the tests for my patches, I noticed that there are other
>> registers that are effectively read-only as well, such as the vg (vector
>> granule) register on aarch64. I wonder whether there should be a more
>> generic support in QEMU for this or whether this is something that
>> should be handled by GDB instead.
>
> I was chatting to Pierrick about this yesterday. There are also
> additional registers I'd like to make available as pure read-only and as
> they go through the gdbstub machinery that seems the obvious place to
> deal with them.
>
In addition, it seems that the set of register who might be readonly
could be different between plugins and gdb.
For instance, it can be convenient to set pc by writing to register in
gdb, even though that's not something supported by plugins.
So I would *very* prudent to change gdbstub default as a side effect.
For now, and the for the plugins, the current scope is fine.
>> The difference to the pc in that case is that the pc architecturally is
>> read-write and it was just QEMU who silently swallowed the writes to it.
>> For the vg register in the example, as far as I understand correctly,
>> this is not an actual architectural register, but something that GDB
>> exposes as a read-only register for easier debugging, and QEMU therefore
>> also exposes this register. However, writes to it with
>> gdb_write_register and by proxy qemu_plugin_write_register are silently
>> ignored.
>>
>> I'm not sure this is something that should be handled in this patch
>> series but I'm wondering whether this is something you already had on
>> your radar or whether this should be taken care of in a follow-up patch
>> series. I'd be happy to get your thoughts on this!
>
> I think this is fine for now - for future enhancements we should extend
> the gdb machinery and then reflect that in the exported plugin
> registers.
>
>
>>
>> Best regards,
>> Florian
>
Florian Hofhammer <florian.hofhammer@epfl.ch> writes: > Some registers should be marked as read-only from a plugin API > perspective, as writing to them via qemu_plugin_write_register has no > effect. This includes the program counter, and we expose this fact to > the plugins with this patch. > > Signed-off-by: Florian Hofhammer <florian.hofhammer@epfl.ch> Reviewed-by: Alex Bennée <alex.bennee@linaro.org> -- Alex Bennée Virtualisation Tech Lead @ Linaro
© 2016 - 2026 Red Hat, Inc.