Kernel debug

The kernel uses the debug callouts when it needs to print out some internal debugging information or encounters a fault.

The kernel uses these callouts to interact with a serial port, console, or other device to output debug or instrumentation information. For example, a display_msg command in a boot image startup script can cause procnto to use a debug kernel callout to output a message similar to the following one:

Running default

We recommend that when you are working on a startup program you start by getting a debug kernel callout working. The ability to output messages to a device helps you debug code as you add or modify it.

Kernel callouts

Check if a break has been detected.
Receive a char from the kernel and output it to UART or other device.
Pass a char to the kernel, if available (e.g. in r3). If no char is available, pass back -1.

The kernel uses these callouts when it needs to interact with a serial port, console, or other device. Only the display_char() callout is required; the others are optional.


This kernel callout takes the char (character) passed into it in the r4 register, and outputs it to the serial controller.

The CALLOUT_START macro's third argument invokes the patch_debug() routine. This routine replaces the 0x1234 and 0x5678 with the base address of the serial controller register.

The lis (load immediate and shift) and the ori (OR immediate) instructions load the base address of the UART registers into r6:

CALLOUT_START display_char_5200, 0, patch_debug
lis   %r6,0x1234
ori   %r6,%r6,0x5678

Disable interrupts:

loadi  %r9,PPC_MSR_EE
mfmsr  %r8
andc   %r9,%r8,%r9
mtmsr  %r9

Loop until the Transmit Ready bit has been set:

lwz    %r0,MGT5200_PSC_SR(%r6)
andis. %r0,%r0,MGT5200_PSC_SR_TXRDY
beq    1b

Store byte (the char passed in by kernel in r4) in the Transmit Byte register:

stb    %r4,MGT5200_PSC_TB(%r6)

Re-enable interrupts, then branch to the link register and continue executing at the instruction that follows the call to this routine:

mtmsr  %r8

End of callout marker:

CALLOUT_END display_char_5200
Note: The startup code must look after some specific debug tasks in addition to those handled by the kernel callouts (see Debug in the Startup Programs chapter).