Updated: October 28, 2024 |
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.
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.
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:
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.
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.