1 /*
2  * Copyright 2020, Data61, CSIRO (ABN 41 687 119 230)
3  *
4  * SPDX-License-Identifier: GPL-2.0-only
5  */
6 
7 #pragma once
8 
9 #include <basic_types.h>
10 
11 
12 
13 /**
14  * irq_t is an identifier that represents a hardware interrupt.
15  * irq handler capabilities refer to an irq_t which is then used by the
16  * kernel to track irq state. An irq_t is also used to interface with an
17  * interrupt controller driver using the functions below.
18  * For most configurations an irq_t is a word_t type and the irq_t values
19  * directly map to harware irq numbers and are also used as indexes into the
20  * kernel's irq cnode that it uses for tracking state.
21  * However on SMP configurations where there can be multiple irq_t identifiers
22  * for a single hardware irq number, such as when there are core local interrupts,
23  * irq_t cannot be assumed to be only a hardware irq number.
24  * In this case, irq_t can be defined as a struct containing additional information.
25  *
26  * Macros are provided to hide this structural difference across configurations:
27  * CORE_IRQ_TO_IRQT: converts from a core id and hw irq number to an irq_t
28  * IRQT_TO_IDX: converts an irq_t to an index in the irq cnode. It is also used
29  *   to encode the irq_t as a single word_t type for sending over IPIs.
30  * IDX_TO_IRQT: converts an index in the irq cnode to an irq_t
31  * IRQT_TO_CORE: extracts the core out of an irq_t
32  * IRQT_TO_IRQL extracts a hw irq out of an irq_t.
33  *
34  * It is expected that interrupt controller drivers that support SMP provide
35  * implementations of these Macros.
36  * Currently only Arm SMP configurations use this scheme.
37  */
38 #if defined(ENABLE_SMP_SUPPORT) && defined(CONFIG_ARCH_ARM)
39 typedef struct {
40     word_t irq;
41     word_t target_core;
42 } irq_t;
43 #else
44 typedef word_t irq_t;
45 #define CORE_IRQ_TO_IRQT(tgt, irq) (irq)
46 #define IRQT_TO_IDX(irq) (irq)
47 #define IDX_TO_IRQT(idx) (idx)
48 #define IRQT_TO_CORE(irqt) 0
49 #define IRQT_TO_IRQ(irqt) (irqt)
50 #endif
51 
52 /**
53  * Return a currently pending IRQ.
54  *
55  * This function can be called multiple times and needs to return the same IRQ
56  * until ackInterrupt is called. getActiveIRQ returns irqInvalid if no interrupt
57  * is pending. It is assumed that if isIRQPending is true, then getActiveIRQ
58  * will not return irqInvalid. irqInvalid is a per platform constant that cannot
59  * correspond to an actual IRQ raised by the platform.
60  *
61  * @return     The active IRQ. irqInvalid if no IRQ is pending.
62  */
63 static inline irq_t getActiveIRQ(void);
64 
65 /**
66  * Checks if an IRQ is currently pending in the hardware.
67  *
68  * isIRQPending is used to determine whether to preempt long running operations
69  * at various preemption points throughout the kernel. If this returns true, it
70  * means that if the Kernel were to return to user mode, it would then
71  * immediately take an interrupt.
72  *
73  * @return     True if irq pending, False otherwise.
74  */
75 static inline bool_t isIRQPending(void);
76 
77 /**
78  * maskInterrupt disables and enables IRQs.
79  *
80  * When an IRQ is disabled, it should not raise an interrupt on the processor.
81  *
82  * @param[in]  disable  True to disable IRQ, False to enable IRQ
83  * @param[in]  irq      The irq to modify
84  */
85 static inline void maskInterrupt(bool_t disable, irq_t irq);
86 
87 /**
88  * Acks the interrupt
89  *
90  * ackInterrupt is used by the kernel to indicate it has processed the interrupt
91  * delivery and getActiveIRQ is now able to return a different IRQ number. Note
92  * that this is called after a notification has been signalled to user level,
93  * but before user level has handled the cause and does not imply that the cause
94  * of the interrupt has been handled.
95  *
96  * @param[in]  irq   irq to ack
97  */
98 static inline void ackInterrupt(irq_t irq);
99 
100 /**
101  * Called when getActiveIRQ returns irqInvalid while the kernel is handling an
102  * interrupt entry. An implementation is not required to do anything here, but
103  * can report the spurious IRQ or try prevent it from reoccuring.
104  */
105 static inline void handleSpuriousIRQ(void);
106 
107 /**
108  * Handle a platform-reserved IRQ.
109  *
110  * Platform specific implementation for handling IRQs for interrupts that are
111  * reserved and not made available to user-level. Will be called if getActiveIRQ
112  * returns an IRQ number that is reserved. After this function returns,
113  * ackInterrupt will likely be immediately called after.
114  *
115  * @param[in]  irq   The irq
116  */
117 static inline void handleReservedIRQ(irq_t irq);
118 
119