blob: 86cd404b6545821e6d3c203b347c524f59e76d2c [file] [log] [blame]
/*
* Copyright 2019, Data61, CSIRO (ABN 41 687 119 230)
*
* SPDX-License-Identifier: BSD-2-Clause
*/
/**
* The IRQ server helps to manage the IRQs in a system. There are 2 API levels
* in the design:
* 1. [irq server thread] An IRQ server node is a standalone thread which waits
* for the arrival of any IRQ that is being managed by a
* particular irq server node. When an IRQ is received,
* the irq server thread will either forward the irq
* information to a registered synchronous endpoint, or
* call the appropriate handler function directly.
* 2. [irq server] A dynamic collection of server threads. When
* registering an IRQ call back function, the irq server
* will attempt to deligate the IRQ to an irq server node
* that has not yet reached capacity. If no node can accept
* the IRQ, it will alert the user that a new irq server
* thread needs to be created to support the additional demand.
*
* ++ Special notes ++
*
* Performance
* The application can achieve greater performance by configuring the irq
* server, or irq server threads, to call the IRQ handler functions directly.
* This is done by not providing an endpoint in the creation of an irq server
* interface. The application must take care to ensure that all concurrency
* issues are addressed.
*
* Resource availability
* The irq server API family accept resource allocators as arguments to some
* function calls. These resource allocators
* must be kept available indefinitely.
*/
#pragma once
#include <autoconf.h>
#include <sel4utils/gen_config.h>
#include <sel4/sel4.h>
#include <vspace/vspace.h>
#include <vka/vka.h>
#include <simple/simple.h>
#include <platsupport/io.h>
#include <platsupport/irq.h>
#include <sel4platsupport/irq.h>
typedef struct irq_server irq_server_t;
typedef int thread_id_t;
/**
* Initialises an IRQ server. The server will manage threads that are
* explicitly created by the user to handle incoming IRQs. The server
* delegates most of the IRQ cap creation and pairing to the IRQ interface in
* libsel4platsupport.
* @param[in] vspace The current vspace
* @param[in] vka Allocator for creating kernel objects
* @param[in] priority The priority of spawned threads
* @param[in] simple A simple interface for creating IRQ caps
* @param[in] cspace The cspace of the current thread
* @param[in] delivery_ep The endpoint to send alerts about IRQ's to
* @param[in] label A label to use when sending to an IPC to an endpoint
* @param[in] nirqs The maximum number of irqs to support
* @return A valid pointer to an irq_server_t instance, otherwise NULL
*/
irq_server_t *irq_server_new(vspace_t *vspace, vka_t *vka, seL4_Word priority,
simple_t *simple, seL4_CPtr cspace, seL4_CPtr delivery_ep,
seL4_Word label, size_t num_irqs, ps_malloc_ops_t *malloc_ops);
/**
* Creates a new thread to wait on IRQs.
* Upon receiving a signal that an IRQ has arrived, the thread will send an IPC message
* through to the endpoint that was registered with the IRQ server, if any. Otherwise,
* it will call 'irq_server_handle_irq_ipc' to handle the interrupt.
*
* The user can provide a notification for the thread to use, and can mark which bits
* of the badge that the thread can use for IRQs. If a null cap was provided,
* the IRQ server can create a notification cap on behalf of the user, the 'usable_mask'
* parameter will be ignored in this case.
*
* A ID will be assigned to this thread and
* returned to the user, but the user can provide a 'hint' to IRQ server. The server will
* attempt to assign an ID with the same value as the hint.
* @param[in] irq_server A handle to the IRQ server
* @param[in] provided_ntfn Notification cap to be provided to thread, can be
* 'seL4_CapNull'
* @param[in] usable_mask Mask of bits indicating which bits of the badge space
* the thread can use, will be ignore if 'provided_ntfn' is
* 'null'
* @param[in] id_hint 'Hint' to be passed to the IRQ server when assigning an
* ID, >= 0 for a valid hint, -1 otherwise
*/
thread_id_t irq_server_thread_new(irq_server_t *irq_server, seL4_CPtr provided_ntfn,
seL4_Word usable_mask, thread_id_t id_hint);
/**
* Enable an IRQ and register a callback function. This functionality is
* delegated to the IRQ interface in libplatsupport.
* @param[in] irq_server The IRQ server which shall be responsible for the IRQ
* @param[in] irq Information about the IRQ that will be registered
* @param[in] callback A callback function to call when the requested IRQ arrives
* @param[in] callback_data Client data which should be passed to the registered call
* back function
* @return On success, returns an ID for the IRQ that was assigned by
* the IRQ interface in libsel4platsuport. Otherwise, returns
* an error code
*/
irq_id_t irq_server_register_irq(irq_server_t *irq_server, ps_irq_t irq,
irq_callback_fn_t callback, void *callback_data);
/**
* Redirects control to the IRQ subsystem to process an arriving IRQ. The
* server will read the appropriate message registers to retrieve the
* information that it needs. This should be called only when an IPC message
* with the designated label was received on an endpoint that was given to an
* IRQ server instance.
* @param[in] irq_server The IRQ server which is responsible for the received IRQ
* @param[in] msginfo An IPC message info header of an IPC message received on
* an endpoint registered with an IRQ server
*/
void irq_server_handle_irq_ipc(irq_server_t *irq_server, seL4_MessageInfo_t msginfo);
/**
* Waits on the IRQ delivery endpoint for the next IRQ. If an IPC is received, but the
* label does not match that which was assigned to the IRQ server, the message info and
* badge are returned to the caller, much like seL4_Recv(...). If the label does match,
* irq_server_handle_irq_ipc(...) will be called before returning.
*
* If an endpoint was not registered with the IRQ server that is passed in, this function
* is essentially a no-op.
* @param[in] irq_server A handle to the IRQ server
* @param[out] ret_badge If badge_ret is not NULL, the received badge will be
* written to badge_ret.
* @return The seL4_MessageInfo_t structure as provided by the
* seL4 kernel in response to a seL4_Recv call. The
* caller may check that the label matches that which
* was registered for the IRQ server in order to
* determine if the received event was destined for the
* IRQ server or if the thread was activated by some
* other IPC event.
* On the error case where the IRQ server passed
* in does not have an endpoint passed in, an empty
* seL4_MessageInfo_t struct will be returned.
*/
seL4_MessageInfo_t irq_server_wait_for_irq(irq_server_t *irq_server, seL4_Word *ret_badge);