1/* 2 * Copyright 2014, General Dynamics C4 Systems 3 * 4 * This software may be distributed and modified according to the terms of 5 * the GNU General Public License version 2. Note that NO WARRANTY is provided. 6 * See "LICENSE_GPLv2.txt" for details. 7 * 8 * @TAG(GD_GPL) 9 */ 10 11#include <types.h> 12#include <api/failures.h> 13 14#include <arch/object/interrupt.h> 15 16static exception_t 17Arch_invokeIRQControl(irq_t irq, cte_t *handlerSlot, cte_t *controlSlot, bool_t trigger) 18{ 19#ifdef HAVE_SET_TRIGGER 20 setIRQTrigger(irq, trigger); 21#endif 22 return invokeIRQControl(irq, handlerSlot, controlSlot); 23} 24 25exception_t 26Arch_decodeIRQControlInvocation(word_t invLabel, word_t length, 27 cte_t *srcSlot, extra_caps_t excaps, 28 word_t *buffer) 29{ 30 if (invLabel == ARMIRQIssueIRQHandlerTrigger) { 31 if (length < 4 || excaps.excaprefs[0] == NULL) { 32 current_syscall_error.type = seL4_TruncatedMessage; 33 return EXCEPTION_SYSCALL_ERROR; 34 } 35 36 if (!config_set(HAVE_SET_TRIGGER)) { 37 userError("This platform does not support setting the IRQ trigger"); 38 current_syscall_error.type = seL4_IllegalOperation; 39 return EXCEPTION_SYSCALL_ERROR; 40 } 41 42 word_t irq_w = getSyscallArg(0, buffer); 43 irq_t irq = (irq_t) irq_w; 44 bool_t trigger = !!getSyscallArg(1, buffer); 45 word_t index = getSyscallArg(2, buffer); 46 word_t depth = getSyscallArg(3, buffer); 47 48 cap_t cnodeCap = excaps.excaprefs[0]->cap; 49 50 exception_t status = Arch_checkIRQ(irq_w); 51 if (status != EXCEPTION_NONE) { 52 return status; 53 } 54 55 if (isIRQActive(irq)) { 56 current_syscall_error.type = seL4_RevokeFirst; 57 userError("Rejecting request for IRQ %u. Already active.", (int)irq); 58 return EXCEPTION_SYSCALL_ERROR; 59 } 60 61 lookupSlot_ret_t lu_ret = lookupTargetSlot(cnodeCap, index, depth); 62 if (lu_ret.status != EXCEPTION_NONE) { 63 userError("Target slot for new IRQ Handler cap invalid: cap %lu, IRQ %u.", 64 getExtraCPtr(buffer, 0), (int)irq); 65 return lu_ret.status; 66 } 67 68 cte_t *destSlot = lu_ret.slot; 69 70 status = ensureEmptySlot(destSlot); 71 if (status != EXCEPTION_NONE) { 72 userError("Target slot for new IRQ Handler cap not empty: cap %lu, IRQ %u.", 73 getExtraCPtr(buffer, 0), (int)irq); 74 return status; 75 } 76 77 setThreadState(NODE_STATE(ksCurThread), ThreadState_Restart); 78 return Arch_invokeIRQControl(irq, destSlot, srcSlot, trigger); 79 } else { 80 current_syscall_error.type = seL4_IllegalOperation; 81 return EXCEPTION_SYSCALL_ERROR; 82 } 83} 84