Page MenuHomeFreeBSD

[PPC64] Enable opal console use as a GDB DBGPORT
ClosedPublic

Authored by luporl on Dec 3 2019, 8:41 PM.
Referenced Files
Unknown Object (File)
Oct 8 2024, 8:26 PM
Unknown Object (File)
Sep 30 2024, 1:25 AM
Unknown Object (File)
Sep 30 2024, 1:25 AM
Unknown Object (File)
Sep 30 2024, 1:14 AM
Unknown Object (File)
Sep 20 2024, 2:43 PM
Unknown Object (File)
Sep 19 2024, 1:54 AM
Unknown Object (File)
Sep 15 2024, 3:37 AM
Unknown Object (File)
Sep 15 2024, 3:37 AM
Subscribers

Details

Summary

This change makes it possible to use OPAL console as a GDB debug port.

Similar to uart and uart_phyp debug ports, it has to be enabled by
setting the hw.uart.dbgport variable to the serial console node
of the device tree.

Test Plan

This was tested using the console provided by IPMI over LAN.
(The setup may be simpler when the console is attached to a physical serial port).

The test goal is to be able to perform basic remote debugging, using 2 machines with the same FreeBSD version.
For the debuggee, a physical POWER8 machine was used.
For the debugger, a POWER8 VM emulated by QEMU was used.

Note: for now, this was tested only with ELFv1 systems and with /usr/libexec/kgdb, as recent gdb/kgdb versions fail to attach to a remote FreeBSD target.

Below are the steps needed to establish a debug connection between the 2 machines:

  1. QEMU is invoked to start the debugger VM. An extra serial port is added to it and connected to a pseudo-terminal (-serial pty). QEMU prints the path to the allocated pseudo-terminal (pty).
  1. On another host terminal, use the screen command to attach to the pty. Ex: screen /dev/pts/3.

Next, execute the ipmitool command needed to activate a console to the debuggee machine, redirecting its I/O to the pty.
Inside screen, this can be achieved by the following command: C-a : then exec !::/path/to/ipmi.sh, where ipmi.sh is a script that runs ipmitool with all needed args and flags.
! connects ipmitool's stdin to the pty and : connects its output to both the pty and screen output (see screen(1) for more details).

  1. On the VM, start minicom or a similar program, to start controlling the remote machine through the serial port.

When Petitboot is reached, start FreeBSD in debug mode and specify the debug port path.
Ex: kexec -l kernel -c 'hw.uart.dbgport=/ibm,opal/consoles/serial@0 -d' -e.

  1. FreeBSD kernel should detect the OPAL DGBPORT and stop at DDB prompt. Type gdb to switch to the gdb backend.
  1. Then, either close minicom or open another terminal on the VM to start kgdb and attach to the remote machine.

Ex: kgdb kernel then target remote /dev/cuau0.

After the final step, the debug connection should (finally) be established, allowing debug commands to be executed.
At the moment, kgdb on PowerPC is unable to properly adjust the symbol locations to match those of the loaded kernel, resulting in wrong symbol resolution.

While this is not fixed, a temporary workaround is to manually reload the symbols, specifying the actual load addresses of the sections.
Ex: add-symbol-file kernel.debug <text_addr> -s .data <data_addr> ....
(kexec's -d flag can be used to print the base kernel load address)

Diff Detail

Repository
rS FreeBSD src repository - subversion
Lint
Lint Not Applicable
Unit
Tests Not Applicable

Event Timeline

Overall looks fine.

sys/powerpc/powernv/opal_dbg.c
61 ↗(On Diff #65171)

Why not use uart_getenv() here, instead?

sys/powerpc/powernv/opal_dbg.c
61 ↗(On Diff #65171)

Well, uart_getenv() doesn't seem to do what I want, that is simply get the DT path to the serial node that should be used as a dbgport.
It will fail to parse a DT path.
Besides, it requires and fills a uart_devinfo struct, that isn't needed in opal_dbg and a uart_class, that could be possibly obtained from uart_devclass, but also isn't needed by opal_dbg.

My inspiration for using hw.uart_opal.dbgport this way actually came from uart_cpu_getdev() at dev/uart/uart_cpu_powerpc.c, that is similar to this implementation of uart_opal_dbg_probe(), although it also requires a uart_devinfo and a uart_class to be set based on the compatible property.

So, basically, uart_getenv() doesn't fit, while uart_cpu_getdev() requires too many things to be worth of use in a simple debug port implementation.

However, it would be possible to use the existing hw.uart.dbgport variable instead of creating a new one. What do you think?

Yes, at least use the existing environment variable that others already use. That keeps it more uniform. uart_cpu_getdev() looks a bit clunky in its implementation, I'd love it if we could eventually make it support the OPAL console without needing even more cases.

  • Merge with 'master'
  • Address review comments
luporl edited the summary of this revision. (Show Details)
luporl edited the test plan for this revision. (Show Details)
This revision is now accepted and ready to land.Dec 8 2019, 4:47 AM
This revision was automatically updated to reflect the committed changes.