Kernel Callouts

The QNX Neutrino RTOS kernel and process manager (procnto) is designed to be as platform-independent as possible. Each release provides a procnto version for each supported hardware architecture (see procnto* in the Utilities Reference).

The kernel callouts are standalone pieces of code (or code fragments) that the kernel uses to perform hardware-specific functions. These callouts don't need to be statically linked to the kernel.

The startup code can include multiple versions of the same kernel callout. For example, it can include a generic kernel callout as well as kernel callouts that are specific to an architecture and board. During hardware discovery, the startup can determine which kernel callout is most appropriate for the current hardware and make that version of the callout available to the kernel. However, it is simpler and more efficient to eliminate the discovery process and include only a single version of each kernel callout in the startup code and have the startup code tell the kernel which callouts to use.

Note:

Note the following about how kernel callout code is used:

  • The startup program copies the kernel callout code from the startup program into the system page. When this copy is complete, the memory used for the startup program is freed up.
  • For all but two routines, the kernel uses normal function-calling conventions to invoke the kernel callouts. For information about these two exceptions, see interrupt_id_*() and interrupt_eoi_*().

Common characteristics

For information about the different categories of kernel callouts and what they are used for, see Kernel callout categories in this chapter.

All kernel callouts share some common characteristcs, including:

Assembly code

Kernel callouts are written in assembly because:

  • They must be position-independent (see Interrupt controller below).
  • There is no portable method for controlling preamble and postamble creation, or code generation; a change to an Application binary interface (ABI) or build configuration problem might create a latent bug in code that isn't fully self-contained and position independent.
Position independent code (PIC)
Position independence is required because kernel callouts are provided in the startup code, which is overwritten when the kernel starts up.
To keep the kernel callouts after the kernel has started, the startup library copies them to a location where they won't be overwritten when the kernel starts. Since after this copy the kernel callouts are in a location other than the one where they were loaded, they must be written to be position-independent. This position independence requires that they be written in assembly.
In-line in kernel source
Kernel callouts are copied in-line to the kernel code and don't use the C language return keyword. However, they can provide the kernel with information in CPU registers.
Interrupt ID and EOI
The interrupt ID and EOI used for kernel callouts are specific to kernel callouts.
No static read/write storage
Kernel callouts can't specify any static read/write storage space for themselves. However, you can allocate a small amount of storage space in the system page for a specific kernel callout.

Passing data to and from kernel callouts

The kernel uses the SoC's Application Binary Interface (ABI) to pass data to and get data from kernel callouts. You should become familiar with the ABI documentation for your board before you attempt to write kernel callouts for the board.

In many cases, the kernel puts inputs to kernel callouts in general purpose registers. You can also use INTR_GENFLAG_* flags to have the kernel pass in additional input values. These and other flags are in the intrinfo structure that is set up by the init_intrinfo() function.

Similarly, you may need to have kernel callouts place their output into registers.

Note: QNX kernel callout source code usually has comments right in the source code files that provide details about which registers to use for kernel callout input and output. If these comments are absent or unclear, refer to the ABI documentation for your board.