KasperskyOS Community Edition 1.2

Managing interrupt processing (irq.h)

The API is defined in the header file sysroot-*-kos/include/coresrv/io/irq.h from the KasperskyOS SDK.

The API manages the handling of hardware interrupts. A hardware interrupt is a signal sent from a device to direct the processor to immediately pause execution of the current program and instead handle an event related to this device. For example, pressing a key on the keyboard invokes a hardware interrupt that ensures the required response to this pressed key (for example, input of a character).

A hardware interrupt occurs when the device queries the interrupt controller. This query can be transmitted through a hardware interrupt line between the device and the interrupt controller or through MMIO memory. In the second case, the device writes to MMIO memory by calling the Message Signaled Interrupt (MSI).

At present, no functions for managing the handling of MSI interrupts have been implemented.

Each hardware interrupt line corresponds to one interrupt with a unique number.

Information about API functions is provided in the table below.

Using the API

To attach an interrupt to its handler, complete the following steps:

  1. Registering an interrupt by calling the KnRegisterIrq() function.

    One interrupt can be registered multiple times in one or more processes.

    The handle of an interrupt can be transferred to another process via IPC.

  2. Attaching a thread to an interrupt by calling the KnIoAttachIrq() function.

    This step is performed by the thread in whose context the interrupt will be handled.

    When using the handle received from the KnRegisterIrq() function call, you can attach only one thread to an interrupt. To attach multiple threads in one or more processes to an interrupt, use different handles for this interrupt received from separate KnRegisterIrq() function calls. In this case, the KnIoAttachIrq() function must be called with the same flags in the flags parameter.

    A handle received when calling the KnIoAttachIrq() function cannot be transferred to another process via IPC.

To deny (mask) an interrupt, call the KnIoDisableIrq() function. To allow (unmask) an interrupt, call the KnIoEnableIrq() function. Even though these functions receive an interrupt handle that is used to attach only one thread to the interrupt, their action is applied to all threads that are attached to this interrupt. These functions must be called outside of the threads attached to the interrupt. After an interrupt is registered and a thread is attached to it, this interrupt does not require unmasking.

To initiate detachment of a thread from an interrupt, call the KnIoDetachIrq() function outside of the thread that is attached to the interrupt. Detachment is performed by the thread attached to the interrupt by calling the KnThreadDetachIrq() function declared in the header file sysroot-*-kos/include/coresrv/thread/thread_api.h from the KasperskyOS SDK.

Handling an interrupt

After attaching to an interrupt, a thread calls the Call() function declared in the header file sysroot-*-kos/include/coresrv/syscalls.h from the KasperskyOS SDK. The thread is locked as a result of this call. When an interrupt occurs or the KnIoDetachIrq() function is called, the KasperskyOS kernel sends an IPC message to the process that contains this thread. This IPC message contains a request to handle the interrupt or a request to detach the thread from the interrupt. When a process receives an IPC message, the Call() function in the thread attached to the interrupt returns control and provides the contents of the IPC message to the thread. The thread extracts the request from the IPC message and either processes the interrupt or detaches from the interrupt. If the interrupt is processed, information about its failure or success upon completion is added to the response IPC message that is sent to the kernel by the next Call() function call in the loop.

When processing an interrupt, use the IoGetIrqRequest() and IoSetIrqAnswer() functions that are declared in the header file sysroot-*-kos/include/io/io_irq.h from the KasperskyOS SDK. These functions let you extract data from IPC messages and add data to IPC messages for data exchange between the kernel and the thread attached to the interrupt.

The standard interrupt processing loop includes the following steps:

  1. Adding information about the failure or success of interrupt processing to an IPC message by calling the IoSetIrqAnswer() function.
  2. Sending the IPC message to the kernel and receiving an IPC message from the kernel.

    To complete this step, call the Call() functions. In the handle parameter, you must specify the handle that was received when the KnIoAttachIrq() function was called. You must use the msgOut parameter to define the IPC message that will be sent to the kernel, and use the msgIn parameter to define the IPC message that will be received from the kernel.

  3. Extracting a request from the IPC message received from the kernel by calling the IoGetIrqRequest() function.
  4. Processing the interrupt or detaching from the interrupt depending on the request.

    If the request requires detachment from the interrupt, exit the interrupt processing loop and call the KnThreadDetachIrq() function.

Deregistering an interrupt

To deregister an interrupt, complete the following steps:

  1. Detach the thread from the interrupt.

    To complete this step, call the KnThreadDetachIrq() function.

  2. Close the handle that was received when the KnIoAttachIrq() function was called.

    To complete this step, call the KnHandleClose() function. (The KnHandleClose() function is declared in the header file sysroot-*-kos/include/coresrv/handle/handle_api.h from the KasperskyOS SDK.)

  3. Close or revoke each interrupt handle in all processes that own these handles.

    To complete this step, use the KnHandleClose() and/or KnHandleRevoke() functions that are declared in the header file sysroot-*-kos/include/coresrv/handle/handle_api.h from the KasperskyOS SDK.

One interrupt can be registered multiple times, but completion of these steps cancels only one registration. The other registrations will remain active. Each registration of one interrupt must be canceled separately.

Information about API functions

irq.h functions

Function

Information about the function

KnRegisterIrq()

Purpose

Registers an interrupt.

Parameters

  • [in] irq – interrupt number.
  • [out] outRid – pointer to the interrupt handle.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KnIoAttachIrq()

Purpose

Attaches the calling thread to an interrupt.

Parameters

  • [in] rid – interrupt handle.
  • [in] flags – flags defining the interrupt parameters. Flags are defined in the header files sysroot-*-kos/include/io/io_irq.h and sysroot-*-kos/include/hal/irqmode.h from the KasperskyOS SDK.
  • [out] handle – pointer to the client IPC handle that is used by the interrupt handler.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

Additional information

In the flags parameter, you can specify the following flags:

  • IRQ_LEVEL_LOW – the interrupt occurs when the signal level is low.
  • IRQ_LEVEL_HIGH – the interrupt occurs when the signal level is high.
  • IRQ_EDGE_RAISE – the interrupt occurs when the signal level increases.
  • IRQ_EDGE_FALL – the interrupt occurs when the signal level decreases.
  • IRQ_PRIO_LOW – the interrupt has low priority.
  • IRQ_PRIO_NORMAL – the interrupt has medium priority.
  • IRQ_PRIO_HIGH – the interrupt has high priority.
  • IRQ_PRIO_RT – the interrupt has the highest priority.

KnIoDetachIrq()

Purpose

Sends a request to a thread. When this request is fulfilled, the thread must detach from the interrupt.

Parameters

  • [in] rid – interrupt handle.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KnIoEnableIrq()

Purpose

Allows (unmasks) an interrupt.

Parameters

  • [in] rid – interrupt handle.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KnIoDisableIrq()

Purpose

Denies (masks) an interrupt.

Parameters

  • [in] rid – interrupt handle.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.