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