1 // © 2021 Qualcomm Innovation Center, Inc. All rights reserved.
2 //
3 // SPDX-License-Identifier: BSD-3-Clause
4 
5 // Interfaces for managing virtual interrupt controllers.
6 //
7 // Virtual IRQs are delivered by a virtual interrupt controller (VIC), which is
8 // a first-class object with defined relationships to a set of VCPUs. The VIC
9 // may implement a hypercall-based VM interface and/or emulate a hardware
10 // interrupt controller's register interface for delivering these interrupts.
11 //
12 // Each VIRQ uses one of two two routing types, specified by the VIRQ source
13 // when registering it with the controller, to select a VCPU to deliver to.
14 // These routing types are:
15 //
16 // - Private: targeted at a pre-determined VCPU, and with assertion state that
17 //   is specific ta that VCPU.
18 //
19 // - Shared: there is a single common state shared by all VCPUs. A target VCPU
20 //   is selected at runtime, based on implementation-defined criteria which may
21 //   be modified by the VM. Note that this may include affinity to a particular
22 //   VCPU, but unlike private routing this affinity is not an inherent property
23 //   of the VIRQ: it may be modifiable at runtime, may target more than one
24 //   VCPU, and may be influenced by the current state of the target VCPU.
25 //
26 // Note that the implementation may restrict shared and/or private VIRQ numbers
27 // to specific ranges which may or may not overlap. This interface does not
28 // provide any means of querying those ranges; the caller must either know them,
29 // or obtain VIRQ numbers from a resource manager VM that knows them.
30 //
31 // To register a VIRQ, call one of the vic_bind_* functions with a source
32 // structure owner by the caller, specifying an interrupt controller object,
33 // a VIRQ number in an appropriate range, and a triggering type defined by the
34 // caller. The type value will be used as a selector for the virq_check_pending
35 // event, which is triggered when a level-sensitive interrupt is synchronised.
36 //
37 // The caller is responsible for calling vic_unbind() on the source structure
38 // in the cleanup handler of the object containing the source structure.
39 //
40 // The caller must either hold references to all specified object(s) (including
41 // the object that contains the VIRQ source structure), or else be in an RCU
42 // read-side critical section.
43 
44 // Get a pointer to a thread's vic
45 vic_t *
46 vic_get_vic(const thread_t *vcpu);
47 
48 // Exclusively claim a shared VIRQ on the specified VIC.
49 //
50 // This prevents the VIRQ being claimed by any other source, and allows calls
51 // to virq_assert() and virq_clear().
52 //
53 // Note that this does not take a reference to the VIC. If the VIC is later
54 // freed, calls to virq_assert() will fail.
55 //
56 // This function should be used in preference to vic_bind_private_*() for any
57 // VIRQ that is not inherently bound to a VCPU. This includes nearly all VIRQs
58 // generated by first class objects other than the VCPU itself.
59 //
60 // Returns ERROR_VIRQ_BOUND if the specified source object has previously been
61 // bound to VIRQ, and not subsequently unbound by calling vic_unbind_sync().
62 // Returns ERROR_BUSY if the specified VIRQ has already been claimed. Returns
63 // ERROR_ARGUMENT_INVALID if the specified VIRQ number is out of range.
64 error_t
65 vic_bind_shared(virq_source_t *source, vic_t *vic, virq_t virq,
66 		virq_trigger_t trigger);
67 
68 // Exclusively claim a private VIRQ on the specified VCPU.
69 //
70 // There are two variants of this function which differ only in the way the
71 // target is specified: one accepts a VCPU object pointer, the other a VIC
72 // object pointer and a VCPU attachment index.
73 //
74 // This operates the same way as vic_bind_shared(), but for private
75 // (VCPU-local) VIRQs. Note that it must be called for each VCPU that will
76 // receive the interrupt, with separate source objects. It is strongly
77 // recommended to repeat this call for every VCPU in the VM, using the same VIRQ
78 // number each time.
79 //
80 // Normally this function should only be used for VIRQs that are inherently
81 // associated with a particular VCPU and can only reasonably be handled by that
82 // VCPU; e.g. local timers or performance monitors. Anything else should use the
83 // shared version instead.
84 //
85 // Returns ERROR_VIRQ_BOUND if the specified source object has previously been
86 // bound to VIRQ, and not subsequently unbound by calling vic_unbind_sync().
87 // Returns ERROR_BUSY if the specified VIRQ has already been claimed. Returns
88 // ERROR_ARGUMENT_INVALID if the specified VIRQ number is out of range. Returns
89 // ERROR_OBJECT_CONFIG if the specified index does not have an associated VCPU
90 // or the attachment between the VCPU and VIC is concurrently broken.
91 error_t
92 vic_bind_private_vcpu(virq_source_t *source, thread_t *vcpu, virq_t virq,
93 		      virq_trigger_t trigger);
94 error_t
95 vic_bind_private_index(virq_source_t *source, vic_t *vic, index_t index,
96 		       virq_t virq, virq_trigger_t trigger);
97 
98 // Release an exclusive claim to a VIRQ.
99 //
100 // Note that if the VIRQ source is currently pending, it will be cleared, as if
101 // virq_clear() was called. However, like virq_clear(), this function does not
102 // wait for cancellation of the specified VIRQ on every registered VCPU. If the
103 // VIRQ is currently asserted and routed to a VCPU that is active on a remote
104 // physical CPU, the interrupt may be spuriously delivered to the VM shortly
105 // after this function returns.
106 //
107 // The caller must ensure that an RCU grace period elapses between the return
108 // of this function and the deallocation of the storage containing the source
109 // structure. Note that this requirement is satisfied by calling this function
110 // from the enclosing first-class object's deactivate event handler.
111 //
112 // Any attempt to reuse the source structure for a new vic_bind_*() call is
113 // permitted to fail as if this function had not been called, even if an RCU
114 // grace period has elapsed.
115 //
116 // If the source has not claimed a VIRQ, or was claimed for a VIC or VCPU that
117 // has since been destroyed, this function has no effect.
118 void
119 vic_unbind(virq_source_t *source);
120 
121 // Release an exclusive claim to a VIRQ and make the source ready for reuse.
122 //
123 // This function performs the same operation as vic_unbind(); additionally, it
124 // waits for the implicit virq_clear() operation to complete, and then resets
125 // the source so that it may be used by a subsequent vic_bind_*() call.
126 //
127 // This function may call the scheduler, and therefore must not be called from
128 // an RCU read-side critical section or a spinlock.
129 void
130 vic_unbind_sync(virq_source_t *source);
131