Kernel callout categories

Updated: April 19, 2023

The startup library provides kernel callouts that look after different categories of tasks. You can use these callouts as models when you write your own.

Source code

The source code for kernel callouts is found in the BSP source code directories, originally installed in bsp_working_dir/src/hardware/startup/lib/. This directory and its subdirectories include generic code as well as processor-specific kernel callouts. Before you begin writing a kernel callout, check these directories to see if a callout is already available:

In the CPU-dependent level of the source file tree, look for files with names that match the pattern: callout_*.[sS]. These files are the callouts provided by the startup library. Whether a file ends in .s or .S depends on whether it's sent through the C preprocessor before being handed off to an assembler. For simplicity, we'll simply refer to both types as .s files.

The filenames break down further as follows: callout_category_device.s, where category is one of:

and where device identifies the unique hardware the callouts were written for.

Typically, the kernel uses all or none of the callouts in a particular source file. For example, the callout_debug_8250.s file contains the display_char_8250(), poll_key_8250(), and break_detect_8250() kernel callouts, which are all used for working with an 8250-style UART chip.

For more information, see Writing a kernel callout in this chapter.

Macros for kernel callouts

All kernel callouts use macros found in callout.ah to define their start and end. For example, the following excerpt describes the interrupt_id_405() kernel callout:

CALLOUT_START interrupt_id_405, 0, 0 
	li %r14,-1     
	mfdcr %r5,PPC405_DCR_UIC0_MSR 
	...
	andc %r4,%r4,%r5 
	mtdcr PPC405_DCR_UIC0_ER,%r4 
	1: 
CALLOUT_END interrupt_id_405 

The CALLOUT_START parameters specify the following information:

  • The name of the kernel callout (for example, interrupt_id_405)
  • The address of a variable that specifies the amount of static read/write storage the callout requires, or 0, if no storage is required
  • The name of a patch routine that modifies the callout code after the startup code copies it to kernel memory, or 0, if the callout requires no patch routine

CALLOUT_END specifies the CALLOUT_START to match (for example, interrupt_id_405).

For more information, see Kernel callout start and end macros and Patching the kernel callout code in this chapter.

Patch routines

Kernel callout code references addresses using routines that edit code after it has been copied into system memory. When a callout uses one of these routines, it is specified using the CALLOUT_START constant. If the callout code only needs to access CPU registers, a patch routine is not required.

For example, in the following excerpt from a display_char() kernel callout, the CALLOUT_START macro's third argument invokes the routine patch_debug(). This routine replaces the 0x1234 and 0x5678 memory locations with the base address of the serial controller register:

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

For further discussion of when these routines are necessary, see Patching the kernel callout code in this chapter.