On 2/24/26 7:46 AM, Florian Hofhammer wrote:
> Hi,
>
> This patch series builds on top of the discussion from the thread at
> https://lore.kernel.org/qemu-devel/e9bcd7c7-2d67-469e-b2f3-d1a68e456b2b@epfl.ch/
> and adds a plugin API function to set the program counter of the guest,
> as just writing to it via qemu_plugin_write_register() has no direct
> effect.
>
> Based on the discussion in the above thread, the series also introduces
> a means to declare registers as read-only from the plugin side, which
> prevents plugins from writing to them via qemu_plugin_write_register().
> This for now is only applied to the PC, and finding the PC register is
> done via some rather hacky strcmp()s. In the above thread, we also
> discussed encoding the read-only property in a custom attribute in the
> GDB XMLs, but that would (1) make syncing with GDB harder, (2) not cover
> all architectures, as there's not an XML description of all
> architectures available in the gdb-xml/ directory, and (3) require quite
> some changes to the whole GDB infrastructure in gdbstub/ to even encode
> the attribute in the correct structs and pass them on over the different
> layers up into the plugin API.
>
> This version v4 of the patch series is more about small refactorings and
> cleanups than changes in functionality.
>
> Best regards,
> Florian
>
> Changes:
> v4:
> - switch strcmp out in favor of g_strcmp0
> - split the patch introducing the qemu_plugin_set_pc() API into three
> patches, two for preparing the plugin infrastructure and the syscall
> handling code and a third introducing the actual plugin API
> v3:
> - make PC registers read-only across architectures
> - add tests for read-only registers
> - adjust test structure for qemu_plugin_set_pc() by moving
> architecture-specific tests into corresponding directories
> v2:
> - add setjmp() in syscall handling path to allow PC redirection from
> syscall callbacks (via longjmp(), the cpu_loop()'s setjmp() for
> exiting a TB would not be live anymore in syscall handlers)
> - add flags to ensure the qemu_plugin_set_pc() API is only called from
> contexts where the CPU is live
> - add test for qemu_plugin_set_pc() API
> v1:
> - initial version
>
>
> Florian Hofhammer (7):
> plugins: add flag to specify whether PC is rw
> linux-user: make syscall emulation interruptible
> plugins: add PC diversion API function
> tests/tcg: add test for qemu_plugin_set_pc API
> plugins: add read-only property for registers
> plugins: prohibit writing to read-only registers
> tests/tcg/plugins: test register readonly feature
>
> include/plugins/qemu-plugin.h | 18 +++++
> linux-user/aarch64/cpu_loop.c | 2 +-
> linux-user/alpha/cpu_loop.c | 2 +-
> linux-user/arm/cpu_loop.c | 2 +-
> linux-user/hexagon/cpu_loop.c | 2 +-
> linux-user/hppa/cpu_loop.c | 4 ++
> linux-user/i386/cpu_loop.c | 8 ++-
> linux-user/include/special-errno.h | 8 +++
> linux-user/loongarch64/cpu_loop.c | 5 +-
> linux-user/m68k/cpu_loop.c | 2 +-
> linux-user/microblaze/cpu_loop.c | 2 +-
> linux-user/mips/cpu_loop.c | 5 +-
> linux-user/or1k/cpu_loop.c | 2 +-
> linux-user/ppc/cpu_loop.c | 6 +-
> linux-user/riscv/cpu_loop.c | 2 +-
> linux-user/s390x/cpu_loop.c | 2 +-
> linux-user/sh4/cpu_loop.c | 2 +-
> linux-user/sparc/cpu_loop.c | 4 +-
> linux-user/syscall.c | 16 +++++
> linux-user/xtensa/cpu_loop.c | 3 +
> plugins/api.c | 43 ++++++++++--
> plugins/core.c | 29 ++++----
> tests/tcg/arm/Makefile.target | 6 ++
> tests/tcg/hexagon/Makefile.target | 7 ++
> tests/tcg/mips/Makefile.target | 6 +-
> tests/tcg/mips64/Makefile.target | 15 ++++
> tests/tcg/mips64el/Makefile.target | 15 ++++
> tests/tcg/mipsel/Makefile.target | 15 ++++
> tests/tcg/multiarch/Makefile.target | 22 +++++-
> .../{ => plugin}/check-plugin-output.sh | 0
> .../{ => plugin}/test-plugin-mem-access.c | 0
> .../plugin/test-plugin-skip-syscalls.c | 26 +++++++
> tests/tcg/plugins/meson.build | 1 +
> tests/tcg/plugins/registers.c | 68 +++++++++++++++++++
> tests/tcg/plugins/syscall.c | 6 ++
> tests/tcg/sparc64/Makefile.target | 16 +++++
> 36 files changed, 331 insertions(+), 41 deletions(-)
> create mode 100644 tests/tcg/mips64/Makefile.target
> create mode 100644 tests/tcg/mips64el/Makefile.target
> create mode 100644 tests/tcg/mipsel/Makefile.target
> rename tests/tcg/multiarch/{ => plugin}/check-plugin-output.sh (100%)
> rename tests/tcg/multiarch/{ => plugin}/test-plugin-mem-access.c (100%)
> create mode 100644 tests/tcg/multiarch/plugin/test-plugin-skip-syscalls.c
> create mode 100644 tests/tcg/plugins/registers.c
> create mode 100644 tests/tcg/sparc64/Makefile.target
>
>
> base-commit: afe653676dc6dfd49f0390239ff90b2f0052c2b8
A few small nits reported by checkpatch.
$ ./scripts/checkpatch.pl $(git merge-base upstream/master HEAD)..HEAD
1/8 Checking commit 23b2901d559b (plugins: add flag to specify whether
PC is rw)
2/8 Checking commit cf46ff49010c (linux-user: make syscall emulation
interruptible)
WARNING: Block comments use a leading /* on a separate line
#217: FILE: linux-user/mips/cpu_loop.c:144:
+ /* Returning from a successful sigreturn syscall or from
WARNING: Block comments use * on subsequent lines
#218: FILE: linux-user/mips/cpu_loop.c:145:
+ /* Returning from a successful sigreturn syscall or from
+ control flow diversion in a plugin callback.
WARNING: Block comments use a leading /* on a separate line
#247: FILE: linux-user/ppc/cpu_loop.c:345:
+ /* Returning from a successful sigreturn syscall or from
WARNING: Block comments use * on subsequent lines
#248: FILE: linux-user/ppc/cpu_loop.c:346:
+ /* Returning from a successful sigreturn syscall or from
+ control flow diversion in a plugin callback.
3/8 Checking commit 2bb085851ee5 (plugins: add PC diversion API function)
4/8 Checking commit 3001ad67e7e5 (tests/tcg: add test for
qemu_plugin_set_pc API)
ERROR: New file 'tests/tcg/mips64/Makefile.target' requires
'SPDX-License-Identifier'
ERROR: New file 'tests/tcg/mips64el/Makefile.target' requires
'SPDX-License-Identifier'
ERROR: New file 'tests/tcg/mipsel/Makefile.target' requires
'SPDX-License-Identifier'
ERROR: open brace '{' following function declarations go on the next line
#216: FILE: tests/tcg/multiarch/plugin/test-plugin-skip-syscalls.c:15:
+void exit_success(void) {
ERROR: open brace '{' following function declarations go on the next line
#220: FILE: tests/tcg/multiarch/plugin/test-plugin-skip-syscalls.c:19:
+int main(int argc, char *argv[]) {
ERROR: New file 'tests/tcg/sparc64/Makefile.target' requires
'SPDX-License-Identifier'
5/8 Checking commit c85ae80717dc (plugins: add read-only property for
registers)
ERROR: do not use C99 // comments
#45: FILE: plugins/api.c:413:
+static const char pc_str[] = "pc"; // generic name for program counter
ERROR: do not use C99 // comments
#46: FILE: plugins/api.c:414:
+static const char eip_str[] = "eip"; // x86 specific name for program
counter
ERROR: do not use C99 // comments
#47: FILE: plugins/api.c:415:
+static const char rip_str[] = "rip"; // x86_64 specific name for
program counter
ERROR: do not use C99 // comments
#48: FILE: plugins/api.c:416:
+static const char pswa_str[] = "pswa"; // s390x specific name for
program counter
ERROR: do not use C99 // comments
#49: FILE: plugins/api.c:417:
+static const char iaoq_str[] = "iaoq"; // HP/PA specific name for
program counter
ERROR: do not use C99 // comments
#50: FILE: plugins/api.c:418:
+static const char rpc_str[] = "rpc"; // microblaze specific name for
program counter
6/8 Checking commit 156dc74ab9a5 (plugins: prohibit writing to read-only
registers)
7/8 Checking commit dba748c1e46c (tests/tcg/plugins: test register
readonly feature)
ERROR: New file 'tests/tcg/plugins/registers.c' requires
'SPDX-License-Identifier'
ERROR: New file 'tests/tcg/plugins/registers.c' must not have license
boilerplate header text, only the SPDX-License-Identifier, unless this
file was copied from existing code already having such text.
Regards,
Pierrick