1 // © 2021 Qualcomm Innovation Center, Inc. All rights reserved.
2 //
3 // SPDX-License-Identifier: BSD-3-Clause
4 
5 // Routines for handling inter-processor interrupts.
6 //
7 // Modules may register an IPI reason code, and an associated handler for the
8 // ipi_received event. When an IPI is targeted at an online CPU, and has not
9 // been masked by that CPU, the handler for the IPI's reason code will be run on
10 // the CPU. Handlers run with preemption disabled, and may run from the idle
11 // thread or an interrupt handler; they return a boolean value which indicates
12 // whether a reschedule is needed.
13 //
14 // Each handler call is preceded by an acquire barrier which synchronises with
15 // the release barrier that was performed when the IPI was sent. Any subsequent
16 // IPI send operation that does not synchronise with that acquire barrier is
17 // guaranteed to trigger another call to the handler. A duplicate IPI send that
18 // does synchronise with the handler's acquire barrier may or may not trigger
19 // another handler call.
20 //
21 // If a _relaxed function is used to send an IPI, the targeted CPU(s) will
22 // handle the IPI next time they switch contexts. There is no particular promise
23 // of timely handling, even on idle CPUs.
24 //
25 // If an _idle function is used to send an IPI, it is guaranteed to be handled
26 // quickly whenever the targeted CPU(s) are idle. It will avoid interrupting a
27 // busy CPU if possible. This may be an alias of the corresponding _relaxed
28 // function if relaxed IPIs are guaranteed to wake idle CPUs; otherwise it is an
29 // alias of the corresponding normal IPI function. The _idle functions in the
30 // IPI module interface cannot wake the target CPU from suspend, therefore,
31 // using these functions incorrectly may lead to an indefinite CPU suspend,
32 // causing the system to hang.
33 //
34 // All of the receive-side functions below must be called with preemption
35 // disabled, except where noted.
36 
37 // Send the specified IPI to all online CPUs other than the caller.
38 //
39 // This implies a release barrier.
40 void
41 ipi_others(ipi_reason_t ipi) REQUIRE_PREEMPT_DISABLED;
42 
43 // Send the specified IPI to all online CPUs other than the caller, with low
44 // priority.
45 //
46 // This implies a release barrier.
47 void
48 ipi_others_relaxed(ipi_reason_t ipi) REQUIRE_PREEMPT_DISABLED;
49 
50 // Send the specified IPI to all online CPUs other than the caller, with low
51 // priority, guaranteeing that idle CPUs will wake.
52 //
53 // This implies a release barrier.
54 //
55 // Do not use with the intention of waking a suspended CPU.
56 void
57 ipi_others_idle(ipi_reason_t ipi) REQUIRE_PREEMPT_DISABLED;
58 
59 // Send the specified IPI to a single CPU.
60 //
61 // This implies a release barrier.
62 void
63 ipi_one(ipi_reason_t ipi, cpu_index_t cpu);
64 
65 // Send the specified IPI to a single CPU, with low priority.
66 //
67 // This implies a release barrier.
68 void
69 ipi_one_relaxed(ipi_reason_t ipi, cpu_index_t cpu);
70 
71 // Send the specified IPI to a single CPU, with low priority, guaranteeing that
72 // it will wake if idle.
73 //
74 // This implies a release barrier.
75 //
76 // Do not use with the intention of waking a suspended CPU.
77 void
78 ipi_one_idle(ipi_reason_t ipi, cpu_index_t cpu);
79 
80 // Atomically check and clear the specified IPI reason.
81 //
82 // This can be used to prevent redundant invocations of an IPI handler. Call
83 // it immediately prior to taking the same action that the handler would take.
84 // However, note that it may incorrectly return false when called in an IPI
85 // handler, including a handler for a different IPI than the one being cleared.
86 //
87 // This function executes an acquire operation before returning true, equivalent
88 // to the acquire operation that is executed before calling a handler.
89 //
90 // If possible, this function will cancel any pending physical IPIs that other
91 // CPUs have asserted to signal the IPI, but note that not all interrupt
92 // controllers can reliably cancel an IPI without handling it.
93 //
94 // This function may be safely called with preemption enabled, from any context.
95 // However, its result must be ignored if it is called in an IPI handler or with
96 // preemption enabled.
97 bool
98 ipi_clear(ipi_reason_t ipi) REQUIRE_PREEMPT_DISABLED;
99 
100 // Atomically check and clear the specified IPI, assuming it was a relaxed IPI.
101 //
102 // This can be used to prevent redundant invocations of an IPI handler. Call
103 // it immediately prior to taking the same action that the handler would take.
104 //
105 // This function executes an acquire operation before returning true, equivalent
106 // to the acquire operation that is executed before calling a handler.
107 //
108 // This function does not attempt to cancel pending physical IPIs, and therefore
109 // can avoid the cost of interacting with the interrupt controller for IPIs that
110 // are always, or mostly, raised using the _relaxed functions.
111 bool
112 ipi_clear_relaxed(ipi_reason_t ipi) REQUIRE_PREEMPT_DISABLED;
113 
114 // Immediately handle any relaxed IPIs.
115 //
116 // Returns true if a reschedule is needed.
117 bool
118 ipi_handle_relaxed(void) REQUIRE_PREEMPT_DISABLED;
119