[7/7] btrace: Add support for UINTR and UIRET events.
Checks
Context |
Check |
Description |
linaro-tcwg-bot/tcwg_gdb_build--master-aarch64 |
success
|
Build passed
|
linaro-tcwg-bot/tcwg_gdb_build--master-arm |
success
|
Build passed
|
linaro-tcwg-bot/tcwg_gdb_check--master-aarch64 |
success
|
Test passed
|
Commit Message
This is similar to the previous events that we added.
---
gdb/btrace.c | 29 ++++++
gdb/testsuite/gdb.btrace/uli.c | 132 ++++++++++++++++++++++++
gdb/testsuite/gdb.btrace/uli_events.exp | 51 +++++++++
3 files changed, 212 insertions(+)
create mode 100644 gdb/testsuite/gdb.btrace/uli.c
create mode 100644 gdb/testsuite/gdb.btrace/uli_events.exp
Comments
Hello Felix,
>+#define UINTR_HANDLER_REG_SYSCALL 471
>+#define UINTR_HANDLER_UNREG_SYSCALL 472
>+#define UINTR_CREATE_FD_SYSCALL 473
>+#define UINTR_SEND_REG_SYSCALL 474
>+#define UINTR_SEND_UNREG_SYSCALL 475
Shouldn't those be defined in syscall.h (or unistd.h)?
If they are not defined, the system likely does not support user
interrupts and we should skip this test.
>+int
>+uintr_register_handler (void *ui_handler, unsigned int flags)
>+{
>+ return syscall (UINTR_HANDLER_REG_SYSCALL, ui_handler, flags);
>+}
On systems that define those syscalls, there probably also is a glibc
wrapper. If there is, we should use it.
>+ /* Do some other work */
>+ while (!uintr_received); /* bp3 */
Could we set a limit to avoid waiting indefinitely if something goes
wrong? Maybe sleep inside a loop for a fixed number of iterations.
>+set opts [list debug "additional_flags=-muintr -mgeneral-regs-only -minline-
>all-stringops"]
>+
>+standard_testfile uli.c
>+if {[gdb_compile_pthreads "$srcdir/$subdir/$srcfile" "$binfile" executable
>$opts] != ""} {
>+ return -1
>+}
>+clean_restart $testfile
Can't we use prepare_for_testing? We could use the pthreads option.
>+# Test function call history.
>+# ui_handler can be preceded by any function depending on the scheduling.
>+gdb_test_sequence "record function-call-history" "function-call-history" {
>+ "\\\[uintr: vector = 0x\[0-9a-fA-F\]+( \\\(#\[a-z\]+\\\))?, ip = 0x\[0-9a-fA-
>F\]+\\\]"
Can we use $hex?
What does '( \\\(#\[a-z\]+\\\))?' mean? There is no mnemonic for user interrupts.
Regards,
Markus.
Intel Deutschland GmbH
Registered Address: Am Campeon 10, 85579 Neubiberg, Germany
Tel: +49 89 99 8853-0, www.intel.de
Managing Directors: Sean Fennelly, Jeffrey Schneiderman, Tiffany Doon Silva
Chairperson of the Supervisory Board: Nicole Lau
Registered Office: Munich
Commercial Register: Amtsgericht Muenchen HRB 186928
> -----Original Message-----
> From: Metzger, Markus T <markus.t.metzger@intel.com>
> Sent: Dienstag, 10. September 2024 17:12
> To: Willgerodt, Felix <felix.willgerodt@intel.com>
> Cc: gdb-patches@sourceware.org
> Subject: RE: [PATCH 7/7] btrace: Add support for UINTR and UIRET events.
>
> Hello Felix,
>
> >+#define UINTR_HANDLER_REG_SYSCALL 471
> >+#define UINTR_HANDLER_UNREG_SYSCALL 472
> >+#define UINTR_CREATE_FD_SYSCALL 473
> >+#define UINTR_SEND_REG_SYSCALL 474
> >+#define UINTR_SEND_UNREG_SYSCALL 475
>
> Shouldn't those be defined in syscall.h (or unistd.h)?
>
> If they are not defined, the system likely does not support user
> interrupts and we should skip this test.
>
> >+int
> >+uintr_register_handler (void *ui_handler, unsigned int flags)
> >+{
> >+ return syscall (UINTR_HANDLER_REG_SYSCALL, ui_handler, flags);
> >+}
>
> On systems that define those syscalls, there probably also is a glibc
> wrapper. If there is, we should use it.
>
>
> >+ /* Do some other work */
> >+ while (!uintr_received); /* bp3 */
>
> Could we set a limit to avoid waiting indefinitely if something goes
> wrong? Maybe sleep inside a loop for a fixed number of iterations.
>
> >+set opts [list debug "additional_flags=-muintr -mgeneral-regs-only -minline-
> >all-stringops"]
> >+
> >+standard_testfile uli.c
> >+if {[gdb_compile_pthreads "$srcdir/$subdir/$srcfile" "$binfile" executable
> >$opts] != ""} {
> >+ return -1
> >+}
> >+clean_restart $testfile
>
> Can't we use prepare_for_testing? We could use the pthreads option.
>
> >+# Test function call history.
> >+# ui_handler can be preceded by any function depending on the scheduling.
> >+gdb_test_sequence "record function-call-history" "function-call-history" {
> >+ "\\\[uintr: vector = 0x\[0-9a-fA-F\]+( \\\(#\[a-z\]+\\\))?, ip = 0x\[0-9a-fA-
> >F\]+\\\]"
>
> Can we use $hex?
>
> What does '( \\\(#\[a-z\]+\\\))?' mean? There is no mnemonic for user interrupts.
>
> Regards,
> Markus.
Hi Markus,
Thanks for the feedback. As a lot of these comments are about dependencies,
I researched the state of user interrupts a bit. It seems like there hasn't been much
movement on the LKML for 2-3 years, there is only this archived repo:
https://github.com/intel/uintr-linux-kernel
GCC support is upstream, I didn't check glibc.
But that leads me to conclude that we probably shouldn't merge these tests to
GDB for now, as no one can run them without using these kernel patches.
And as I don't know if the tests would ever work like they do now, if the feature
ever lands in upstream Linux.
Therefore I will remove the test and merge the btrace.c bits of this commit with
the previous commit, which has all the events that lack tests.
Regards,
Felix
Intel Deutschland GmbH
Registered Address: Am Campeon 10, 85579 Neubiberg, Germany
Tel: +49 89 99 8853-0, www.intel.de
Managing Directors: Sean Fennelly, Jeffrey Schneiderman, Tiffany Doon Silva
Chairperson of the Supervisory Board: Nicole Lau
Registered Office: Munich
Commercial Register: Amtsgericht Muenchen HRB 186928
Hello Felix,
>Thanks for the feedback. As a lot of these comments are about dependencies,
>I researched the state of user interrupts a bit. It seems like there hasn't been
>much
>movement on the LKML for 2-3 years, there is only this archived repo:
>https://github.com/intel/uintr-linux-kernel
>GCC support is upstream, I didn't check glibc.
>
>But that leads me to conclude that we probably shouldn't merge these tests to
>GDB for now, as no one can run them without using these kernel patches.
>And as I don't know if the tests would ever work like they do now, if the
>feature
>ever lands in upstream Linux.
>
>Therefore I will remove the test and merge the btrace.c bits of this commit
>with
>the previous commit, which has all the events that lack tests.
OK, that makes sense to me.
regards,
Markus.
Intel Deutschland GmbH
Registered Address: Am Campeon 10, 85579 Neubiberg, Germany
Tel: +49 89 99 8853-0, www.intel.de
Managing Directors: Sean Fennelly, Jeffrey Schneiderman, Tiffany Doon Silva
Chairperson of the Supervisory Board: Nicole Lau
Registered Office: Munich
Commercial Register: Amtsgericht Muenchen HRB 186928
@@ -1552,6 +1552,35 @@ handle_pt_insn_events (struct btrace_thread_info *btinfo,
handle_pt_aux_insn (btinfo, aux_string, pc);
break;
}
+
+ case ptev_uintr:
+ {
+ std::string aux_string = std::string (_("uintr: vector = "))
+ + hex_string (event.variant.uintr.vector);
+
+ if (event.ip_suppressed == 0)
+ {
+ pc = event.variant.uintr.ip;
+ aux_string += std::string (", ip = ") + hex_string (pc);
+ }
+
+ handle_pt_aux_insn (btinfo, aux_string, pc);
+ break;
+ }
+
+ case ptev_uiret:
+ {
+ std::string aux_string = std::string (_("uiret"));
+
+ if (event.ip_suppressed == 0)
+ {
+ pc = event.variant.uiret.ip;
+ aux_string += std::string (": ip = ") + hex_string (pc);
+ }
+
+ handle_pt_aux_insn (btinfo, aux_string, pc);
+ break;
+ }
#endif /* defined (LIBIPT_VERSION >= 0x201) */
}
}
new file mode 100644
@@ -0,0 +1,132 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2021-2024 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <syscall.h>
+#include <unistd.h>
+#include <x86gprintrin.h>
+
+#define UINTR_HANDLER_REG_SYSCALL 471
+#define UINTR_HANDLER_UNREG_SYSCALL 472
+#define UINTR_CREATE_FD_SYSCALL 473
+#define UINTR_SEND_REG_SYSCALL 474
+#define UINTR_SEND_UNREG_SYSCALL 475
+
+unsigned long uintr_received;
+unsigned int uintr_fd;
+
+int
+uintr_register_handler (void *ui_handler, unsigned int flags)
+{
+ return syscall (UINTR_HANDLER_REG_SYSCALL, ui_handler, flags);
+}
+
+int
+uintr_unregister_handler (unsigned int flags)
+{
+ return syscall (UINTR_HANDLER_UNREG_SYSCALL, flags);
+}
+
+int
+uintr_create_fd (int vector, unsigned int flags)
+{
+ return syscall (UINTR_CREATE_FD_SYSCALL, vector, flags);
+}
+
+int
+uintr_register_sender (int uintr_fd, unsigned int flags)
+{
+ return syscall (UINTR_SEND_REG_SYSCALL, uintr_fd, flags);
+}
+
+int
+uintr_unregister_sender (int uintr_fd, unsigned int flags)
+{
+ return syscall (UINTR_SEND_UNREG_SYSCALL, uintr_fd, flags);
+}
+
+void __attribute__ ((interrupt))
+ui_handler (struct __uintr_frame *ui_frame, unsigned long long vector)
+{
+ static const char print[] = "\t-- User Interrupt handler --\n";
+
+ write (STDOUT_FILENO, print, sizeof (print) - 1); /* bp4 */
+ uintr_received = 1;
+}
+
+void *
+sender_thread (void *arg)
+{
+ int uipi_index;
+
+ uipi_index = uintr_register_sender (uintr_fd, 0);
+ if (uipi_index < 0)
+ {
+ printf ("Sender register error\n");
+ exit (EXIT_FAILURE);
+ }
+
+ printf ("Sending IPI from sender thread\n");
+ _senduipi (uipi_index); /* bp2 */
+
+ uintr_unregister_sender (uintr_fd, 0);
+
+ return NULL;
+}
+
+int
+main ()
+{
+ pthread_t pt;
+ int ret;
+
+ if (uintr_register_handler (ui_handler, 0))
+ {
+ printf ("Interrupt handler register error\n");
+ exit (EXIT_FAILURE);
+ }
+
+ ret = uintr_create_fd (0, 0);
+ if (ret < 0)
+ {
+ printf ("Interrupt vector allocation error\n");
+ exit (EXIT_FAILURE);
+ }
+
+ uintr_fd = ret;
+
+ _stui ();
+ printf ("Receiver enabled interrupts\n");
+
+ if (pthread_create (&pt, NULL, &sender_thread, NULL))
+ {
+ printf ("Error creating sender thread\n");
+ exit (EXIT_FAILURE);
+ }
+
+ /* Do some other work */
+ while (!uintr_received); /* bp3 */
+
+ pthread_join (pt, NULL); /* bp1 */
+ close (uintr_fd);
+ uintr_unregister_handler (0);
+
+ printf ("Success\n");
+ exit (EXIT_SUCCESS);
+}
new file mode 100644
@@ -0,0 +1,51 @@
+# This testcase is part of GDB, the GNU debugger.
+#
+# Copyright 2024 Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# Test UIRET and UINTR events.
+
+require allow_btrace_tests allow_btrace_event_trace_tests
+
+set opts [list debug "additional_flags=-muintr -mgeneral-regs-only -minline-all-stringops"]
+
+standard_testfile uli.c
+if {[gdb_compile_pthreads "$srcdir/$subdir/$srcfile" "$binfile" executable $opts] != ""} {
+ return -1
+}
+clean_restart $testfile
+
+if ![runto_main] {
+ untested "failed to run to main"
+ return -1
+}
+
+set bp_1 [gdb_get_line_number "bp1"]
+
+gdb_breakpoint $bp_1
+
+gdb_test_no_output "set record function-call-history-size unlimited"
+gdb_test_no_output "set record btrace pt event-tracing on"
+gdb_test_no_output "record btrace pt"
+gdb_continue_to_breakpoint "break at bp_1" ".*$srcfile:$bp_1.*"
+
+# Test function call history.
+# ui_handler can be preceded by any function depending on the scheduling.
+gdb_test_sequence "record function-call-history" "function-call-history" {
+ "\\\[uintr: vector = 0x\[0-9a-fA-F\]+( \\\(#\[a-z\]+\\\))?, ip = 0x\[0-9a-fA-F\]+\\\]"
+ "\[0-9\]+\tui_handler"
+ "\\\[uiret(: ip = 0x\[0-9a-fA-F\]+)?\\\]"
+ "\[0-9\]+\tmain"
+}