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 13exception_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 25static 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 33exception_t Arch_decodeIRQControlInvocation(word_t invLabel, word_t length, 34 cte_t *srcSlot, extra_caps_t excaps, 35 word_t *buffer) 36{ 37 if (invLabel == RISCVIRQIssueIRQHandlerTrigger) { 38 if (length < 4 || excaps.excaprefs[0] == NULL) { 39 current_syscall_error.type = seL4_TruncatedMessage; 40 return EXCEPTION_SYSCALL_ERROR; 41 } 42 43 if (!config_set(HAVE_SET_TRIGGER)) { 44 userError("This platform does not support setting the IRQ trigger"); 45 current_syscall_error.type = seL4_IllegalOperation; 46 return EXCEPTION_SYSCALL_ERROR; 47 } 48 49 word_t irq_w = getSyscallArg(0, buffer); 50 irq_t irq = (irq_t) irq_w; 51 bool_t trigger = !!getSyscallArg(1, buffer); 52 word_t index = getSyscallArg(2, buffer); 53 word_t depth = getSyscallArg(3, buffer); 54 55 cap_t cnodeCap = excaps.excaprefs[0]->cap; 56 57 exception_t status = Arch_checkIRQ(irq_w); 58 if (status != EXCEPTION_NONE) { 59 return status; 60 } 61 62 if (isIRQActive(irq)) { 63 current_syscall_error.type = seL4_RevokeFirst; 64 userError("Rejecting request for IRQ %u. Already active.", (int)irq); 65 return EXCEPTION_SYSCALL_ERROR; 66 } 67 68 lookupSlot_ret_t lu_ret = lookupTargetSlot(cnodeCap, index, depth); 69 if (lu_ret.status != EXCEPTION_NONE) { 70 userError("Target slot for new IRQ Handler cap invalid: cap %lu, IRQ %u.", 71 getExtraCPtr(buffer, 0), (int)irq); 72 return lu_ret.status; 73 } 74 75 cte_t *destSlot = lu_ret.slot; 76 77 status = ensureEmptySlot(destSlot); 78 if (status != EXCEPTION_NONE) { 79 userError("Target slot for new IRQ Handler cap not empty: cap %lu, IRQ %u.", 80 getExtraCPtr(buffer, 0), (int)irq); 81 return status; 82 } 83 84 setThreadState(NODE_STATE(ksCurThread), ThreadState_Restart); 85 return Arch_invokeIRQControl(irq, destSlot, srcSlot, trigger); 86 } else { 87 current_syscall_error.type = seL4_IllegalOperation; 88 return EXCEPTION_SYSCALL_ERROR; 89 } 90} 91