Out-of-band stage

This section discusses the operations manipulating the out-of-band interrupt stage, along with the current execution stage of an arbitrary routine.

Installing the out-of-band stage

Before you can direct the incoming interrupt flow to out-of-band handlers, you need to install the out-of-band interrupt stage. Conversely, you need to remove the out-of-band stage from the interrupt pipeline when you are done with receiving out-of-band events.


int enable_oob_stage(const char *name)

  • name

    A symbolic name describing the high priority interrupt stage which is being installed. This information is merely used in kernel messages, so it should be short but descriptive enough. For instance, the EVL core installs the “EVL” stage.

  • This call enables the out-of-band stage context in the interrupt pipeline, which in turn allows an autonomous core to install out-of-band handlers for interrupts. It returns zero on success, or a negated error code if something went wrong:

    -EBUSY The out-of-band stage is already enabled.


    void disable_oob_stage(void)

    This call disables the out-of-band stage context in the interrupt pipeline. From that point, the interrupt flow is exclusively directed to the in-band stage.

    This call does not perform any serialization with ongoing interrupt handling on remote CPUs whatsoever. The autonomous core must synchronize with remote CPUs before calling disable_oob_stage() to prevent them from running out-of-band handlers while the out-of-band stage is being dismantled. This is particularly important if these handlers belong to a dynamically loaded module which might be unloaded right after disable_oob_stage() returns. In that case, you certainly don’t want the .text section containing interrupt handlers to vanish while they are still running.


    Stage escalation

    Sometimes you may need to escalate the current execution stage from in-band to out-of-band, only for running a particular routine. This can be done using run_oob_call(). For instance, the EVL core is using this service to escalate calls to its rescheduling procedure to the out-of-band stage, as described in the discussion about switching task contexts with Dovetail’s support for alternate scheduling.


    int run_oob_call(int (*fn)(void *arg), void *arg)

  • fn

    The address of the routine to execute on the out-of-band stage.

  • arg

    The routine argument.

  • run_oob_call() first switches the current execution stage to out-of-band - if need be - then calls the routine with hard interrupts disabled (i.e. disabled in the CPU). Upon return, the integer value returned by fn() is passed back to the caller.

    Because the routine may switch the execution stage back to in-band for the calling context, run_oob_call() restores the original stage only if it did not change in the meantime. In addition, the interrupt log of the current CPU is synchronized before returning to the caller. The following matrix describes the logic for determining which epilogue should be performed before leaving run_oob_call(), depending on the active stage on entry to the latter and on return from fn():

    On entry to run_oob_call() At exit from fn() Epilogue
    out-of-band out-of-band sync current stage if not stalled
    in-band out-of-band switch to in-band + sync both stages
    out-of-band in-band sync both stages
    in-band in-band sync both stages

    run_oob_call() is a lightweight operation that switches the CPU to the out-of-band interrupt stage for the duration of the call, whatever the underlying context may be. This is different from switching a task context to the out-of-band stage by offloading it to the autonomous core for scheduling. The latter operation would involve a more complex procedure.


    Last modified: Tue, 29 Oct 2024 14:58:31 +0100