1 /*
2 * Copyright 2020, Data61, CSIRO (ABN 41 687 119 230)
3 * Copyright 2015, 2016 Hesham Almatary <heshamelmatary@gmail.com>
4 *
5 * SPDX-License-Identifier: GPL-2.0-only
6 */
7
8 #include <types.h>
9 #include <api/failures.h>
10
11 #include <arch/object/interrupt.h>
12
Arch_checkIRQ(word_t irq)13 exception_t Arch_checkIRQ(word_t irq)
14 {
15 if (irq > maxIRQ || irq == irqInvalid) {
16 current_syscall_error.type = seL4_RangeError;
17 current_syscall_error.rangeErrorMin = 1;
18 current_syscall_error.rangeErrorMax = maxIRQ;
19 userError("Rejecting request for IRQ %u. IRQ is out of range [1..maxIRQ].", (int)irq);
20 return EXCEPTION_SYSCALL_ERROR;
21 }
22 return EXCEPTION_NONE;
23 }
24
Arch_invokeIRQControl(irq_t irq,cte_t * handlerSlot,cte_t * controlSlot,bool_t trigger)25 static exception_t Arch_invokeIRQControl(irq_t irq, cte_t *handlerSlot, cte_t *controlSlot, bool_t trigger)
26 {
27 #ifdef HAVE_SET_TRIGGER
28 setIRQTrigger(irq, trigger);
29 #endif
30 return invokeIRQControl(irq, handlerSlot, controlSlot);
31 }
32
Arch_decodeIRQControlInvocation(word_t invLabel,word_t length,cte_t * srcSlot,word_t * buffer)33 exception_t Arch_decodeIRQControlInvocation(word_t invLabel, word_t length,
34 cte_t *srcSlot, word_t *buffer)
35 {
36 if (invLabel == RISCVIRQIssueIRQHandlerTrigger) {
37 if (length < 4 || current_extra_caps.excaprefs[0] == NULL) {
38 current_syscall_error.type = seL4_TruncatedMessage;
39 return EXCEPTION_SYSCALL_ERROR;
40 }
41
42 if (!config_set(HAVE_SET_TRIGGER)) {
43 userError("This platform does not support setting the IRQ trigger");
44 current_syscall_error.type = seL4_IllegalOperation;
45 return EXCEPTION_SYSCALL_ERROR;
46 }
47
48 word_t irq_w = getSyscallArg(0, buffer);
49 irq_t irq = (irq_t) irq_w;
50 bool_t trigger = !!getSyscallArg(1, buffer);
51 word_t index = getSyscallArg(2, buffer);
52 word_t depth = getSyscallArg(3, buffer);
53
54 cap_t cnodeCap = current_extra_caps.excaprefs[0]->cap;
55
56 exception_t status = Arch_checkIRQ(irq_w);
57 if (status != EXCEPTION_NONE) {
58 return status;
59 }
60
61 if (isIRQActive(irq)) {
62 current_syscall_error.type = seL4_RevokeFirst;
63 userError("Rejecting request for IRQ %u. Already active.", (int)irq);
64 return EXCEPTION_SYSCALL_ERROR;
65 }
66
67 lookupSlot_ret_t lu_ret = lookupTargetSlot(cnodeCap, index, depth);
68 if (lu_ret.status != EXCEPTION_NONE) {
69 userError("Target slot for new IRQ Handler cap invalid: cap %lu, IRQ %u.",
70 getExtraCPtr(buffer, 0), (int)irq);
71 return lu_ret.status;
72 }
73
74 cte_t *destSlot = lu_ret.slot;
75
76 status = ensureEmptySlot(destSlot);
77 if (status != EXCEPTION_NONE) {
78 userError("Target slot for new IRQ Handler cap not empty: cap %lu, IRQ %u.",
79 getExtraCPtr(buffer, 0), (int)irq);
80 return status;
81 }
82
83 setThreadState(NODE_STATE(ksCurThread), ThreadState_Restart);
84 return Arch_invokeIRQControl(irq, destSlot, srcSlot, trigger);
85 } else {
86 current_syscall_error.type = seL4_IllegalOperation;
87 return EXCEPTION_SYSCALL_ERROR;
88 }
89 }
90