[PATCH v4 0/7] Enable PC diversion via the plugin API

Florian Hofhammer posted 7 patches 1 month, 2 weeks ago
Patches applied successfully (tree, apply log)
git fetch https://github.com/patchew-project/qemu tags/patchew/909b0a4f-9759-4e27-bba8-997ae2f41bd6@epfl.ch
Maintainers: Laurent Vivier <laurent@vivier.eu>, Pierrick Bouvier <pierrick.bouvier@linaro.org>, Brian Cain <brian.cain@oss.qualcomm.com>, "Alex Bennée" <alex.bennee@linaro.org>, Alexandre Iooss <erdnaxe@crans.org>, Mahmoud Mandour <ma.mandourr@gmail.com>, Peter Maydell <peter.maydell@linaro.org>, "Philippe Mathieu-Daudé" <philmd@linaro.org>, Aurelien Jarno <aurelien@aurel32.net>, Jiaxun Yang <jiaxun.yang@flygoat.com>, Aleksandar Rikalo <arikalo@gmail.com>, Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>, Artyom Tarasenko <atar4qemu@gmail.com>
There is a newer version of this series
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
[PATCH v4 0/7] Enable PC diversion via the plugin API
Posted by Florian Hofhammer 1 month, 2 weeks ago
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
-- 
2.53.0
Re: [PATCH v4 0/7] Enable PC diversion via the plugin API
Posted by Pierrick Bouvier 1 month, 2 weeks ago
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