PatchworkOS  da8a090
A non-POSIX operating system.
Loading...
Searching...
No Matches
ipi.h
Go to the documentation of this file.
1#pragma once
2
4#include <kernel/cpu/irq.h>
5#include <kernel/sync/lock.h>
7
8#include <stdbool.h>
9#include <stdint.h>
10#include <sys/list.h>
11
12typedef struct cpu cpu_t;
13
14/**
15 * @brief Inter-Processor Interrupts (IPIs)
16 * @defgroup kernel_cpu_ipi IPI
17 * @ingroup kernel_cpu
18 *
19 * Inter-Processor Interrupts are a way to remotely interrupt another CPU, this could be done with any interrupt vector,
20 * but for the sake of simplicity we reserve a single interrupt vector `VECTOR_IPI` for IPIs which, when received,
21 * will cause the CPU to check its IPI queue for any pending IPIs to execute.
22 *
23 * The actual remote interrupt invocation of the IPI is handled by a "IPI chip", usually the local APIC, which is
24 * implemented in a module.
25 *
26 * @{
27 */
28
29/**
30 * @brief Inter-Processor Interrupt (IPI) chip structure.
31 * @struct ipi_chip_t
32 *
33 * Represents a implemented hardware IPI controller, such as the local APIC.
34 */
35typedef struct ipi_chip
36{
37 const char* name;
38 /**
39 * @brief Should interrupt the given CPU with the given virtual IRQ.
40 *
41 * Should panic on failure.
42 *
43 * @param cpu The target CPU.
44 * @param virt The virtual IRQ to interrupt the CPU with.
45 */
46 void (*interrupt)(cpu_t* cpu, irq_virt_t virt);
47 void (*ack)(cpu_t* cpu);
48 void (*eoi)(cpu_t* cpu);
50
51/**
52 * @brief IPI function data structure.
53 * @struct ipi_func_data_t
54 *
55 * Data passed to an IPI function when invoked.
56 */
57typedef struct
58{
60 void* private;
62
63/**
64 * @brief IPI function type.
65 */
67
68/**
69 * @brief IPI structure.
70 * @struct ipi_t
71 *
72 * Represents a single IPI to be executed on a CPU.
73 */
74typedef struct ipi
75{
77 void* private;
78} ipi_t;
79
80/**
81 * @brief IPI queue size.
82 */
83#define IPI_QUEUE_SIZE 16
84
85/**
86 * @brief Per-CPU IPI context.
87 * @struct ipi_cpu_ctx_t
88 *
89 * Stores the IPIs received by the owner CPU.
90 */
98
99/**
100 * @brief IPI flags.
101 * @enum ipi_flags_t
102 */
103typedef enum
104{
105 IPI_SINGLE = 0 << 0, ///< Send the IPI to the specified CPU.
106 IPI_BROADCAST = 1 << 0, ///< Send the IPI to all CPUs, specified CPU ignored.
107 IPI_OTHERS = 2 << 0, ///< Send the IPI to all CPUs except the specified CPU.
109
110/**
111 * @brief Initialize per-CPU IPI context.
112 *
113 * @param ctx The IPI context to initialize.
114 */
116
117/**
118 * @brief Handle pending IPIs on the current CPU.
119 *
120 * @param frame The interrupt frame.
121 * @param self The current CPU.
122 */
123void ipi_handle_pending(interrupt_frame_t* frame, cpu_t* self);
124
125/**
126 * @brief Register an IPI chip.
127 *
128 * There can only be a single IPI chip registered at a time.
129 *
130 * @param chip The IPI chip to register.
131 * @return On success, `0`. On failure, `ERR` and `errno` is set to:
132 * - `EINVAL`: Invalid parameters.
133 * - `EBUSY`: An IPI chip is already registered.
134 */
136
137/**
138 * @brief Unregister the IPI chip.
139 *
140 * If the given chip is not the registered chip, this is a no-op.
141 *
142 * @param chip The IPI chip to unregister, or `NULL` for no-op.
143 */
145
146/**
147 * @brief Get the number of registered IPI chips.
148 *
149 * Will always be `0` or `1`.
150 *
151 * @return The number of registered IPI chips.
152 */
154
155/**
156 * @brief Send an IPI to one or more CPUs.
157 *
158 * The CPU(s) is notified of the IPI by receiving a `VECTOR_IPI` interrupt.
159 *
160 * @param cpu The specified CPU, check `ipi_flags_t`.
161 * @param flags The flags for how to send the IPI.
162 * @param func The function to execute on target CPU(s).
163 * @param private The private data to pass to the function, will be found in `irq_func_data_t->private`.
164 * @return On success, `0`. On failure, `ERR` and `errno` is set to:
165 * - `EINVAL`: Invalid parameters.
166 * - `ENODEV`: No IPI chip is registered.
167 * - `ENOSYS`: The registered IPI chip does not have a `notify` function.
168 * - `EBUSY`: The target CPU's IPI queue is full, some or all IPIs could not be sent.
169 * - Other errors returned by the IPI chip's `notify` function.
170 */
171uint64_t ipi_send(cpu_t* cpu, ipi_flags_t flags, ipi_func_t func, void* private);
172
173/**
174 * @brief Wake up one or more CPUs.
175 *
176 * A wake-up IPI is an IPI with no function to execute, used to wake up a CPU that may be idle or sleeping and to prompt
177 * it to check for pending IPIs, notes, etc.
178 *
179 * @param cpu The specified CPU, check `ipi_flags_t`.
180 * @param flags The flags for how to send the IPI.
181 */
183
184/**
185 * @brief Invoke a IPI interrupt on the current CPU.
186 *
187 * Will use `IRQ_INVOKE(VECTOR_IPI)` to trigger the IPI interrupt, causing the CPU to enter an interrupt context and
188 * handle any pending IPIs, notes and potentially scheduling.
189 */
190void ipi_invoke(void);
191
192/** @} */
static fd_t data
Definition dwm.c:21
#define IPI_QUEUE_SIZE
IPI queue size.
Definition ipi.h:83
void ipi_cpu_ctx_init(ipi_cpu_ctx_t *ctx)
Initialize per-CPU IPI context.
Definition ipi.c:15
ipi_flags_t
IPI flags.
Definition ipi.h:104
void ipi_handle_pending(interrupt_frame_t *frame, cpu_t *self)
Handle pending IPIs on the current CPU.
Definition ipi.c:23
void ipi_invoke(void)
Invoke a IPI interrupt on the current CPU.
Definition ipi.c:267
void ipi_wake_up(cpu_t *cpu, ipi_flags_t flags)
Wake up one or more CPUs.
Definition ipi.c:213
void(* ipi_func_t)(ipi_func_data_t *data)
IPI function type.
Definition ipi.h:66
uint64_t ipi_chip_register(ipi_chip_t *chip)
Register an IPI chip.
Definition ipi.c:63
uint64_t ipi_chip_amount(void)
Get the number of registered IPI chips.
Definition ipi.c:102
uint64_t ipi_send(cpu_t *cpu, ipi_flags_t flags, ipi_func_t func, void *private)
Send an IPI to one or more CPUs.
Definition ipi.c:138
void ipi_chip_unregister(ipi_chip_t *chip)
Unregister the IPI chip.
Definition ipi.c:84
@ IPI_OTHERS
Send the IPI to all CPUs except the specified CPU.
Definition ipi.h:107
@ IPI_SINGLE
Send the IPI to the specified CPU.
Definition ipi.h:105
@ IPI_BROADCAST
Send the IPI to all CPUs, specified CPU ignored.
Definition ipi.h:106
uint8_t irq_virt_t
Virtual IRQ numbers.
Definition irq.h:57
static const path_flag_t flags[]
Definition path.c:42
__UINT64_TYPE__ uint64_t
Definition stdint.h:17
CPU structure.
Definition cpu.h:122
Trap Frame Structure.
Definition interrupt.h:143
Inter-Processor Interrupt (IPI) chip structure.
Definition ipi.h:36
const char * name
Definition ipi.h:37
Per-CPU IPI context.
Definition ipi.h:92
uint64_t writeIndex
Definition ipi.h:95
lock_t lock
Definition ipi.h:96
uint64_t readIndex
Definition ipi.h:94
IPI function data structure.
Definition ipi.h:58
cpu_t * self
Definition ipi.h:59
IPI structure.
Definition ipi.h:75
ipi_func_t func
Definition ipi.h:76
A simple ticket lock implementation.
Definition lock.h:43