/* * Copyright 2014, General Dynamics C4 Systems * * This software may be distributed and modified according to the terms of * the GNU General Public License version 2. Note that NO WARRANTY is provided. * See "LICENSE_GPLv2.txt" for details. * * @TAG(GD_GPL) */ #include #include #include static exception_t Arch_invokeIRQControl(irq_t irq, cte_t *handlerSlot, cte_t *controlSlot, bool_t trigger) { #ifdef HAVE_SET_TRIGGER setIRQTrigger(irq, trigger); #endif return invokeIRQControl(irq, handlerSlot, controlSlot); } exception_t Arch_decodeIRQControlInvocation(word_t invLabel, word_t length, cte_t *srcSlot, extra_caps_t excaps, word_t *buffer) { if (invLabel == ARMIRQIssueIRQHandlerTrigger) { if (length < 4 || excaps.excaprefs[0] == NULL) { current_syscall_error.type = seL4_TruncatedMessage; return EXCEPTION_SYSCALL_ERROR; } if (!config_set(HAVE_SET_TRIGGER)) { userError("This platform does not support setting the IRQ trigger"); current_syscall_error.type = seL4_IllegalOperation; return EXCEPTION_SYSCALL_ERROR; } word_t irq_w = getSyscallArg(0, buffer); irq_t irq = (irq_t) irq_w; bool_t trigger = !!getSyscallArg(1, buffer); word_t index = getSyscallArg(2, buffer); word_t depth = getSyscallArg(3, buffer); cap_t cnodeCap = excaps.excaprefs[0]->cap; exception_t status = Arch_checkIRQ(irq_w); if (status != EXCEPTION_NONE) { return status; } if (isIRQActive(irq)) { current_syscall_error.type = seL4_RevokeFirst; userError("Rejecting request for IRQ %u. Already active.", (int)irq); return EXCEPTION_SYSCALL_ERROR; } lookupSlot_ret_t lu_ret = lookupTargetSlot(cnodeCap, index, depth); if (lu_ret.status != EXCEPTION_NONE) { userError("Target slot for new IRQ Handler cap invalid: cap %lu, IRQ %u.", getExtraCPtr(buffer, 0), (int)irq); return lu_ret.status; } cte_t *destSlot = lu_ret.slot; status = ensureEmptySlot(destSlot); if (status != EXCEPTION_NONE) { userError("Target slot for new IRQ Handler cap not empty: cap %lu, IRQ %u.", getExtraCPtr(buffer, 0), (int)irq); return status; } setThreadState(NODE_STATE(ksCurThread), ThreadState_Restart); return Arch_invokeIRQControl(irq, destSlot, srcSlot, trigger); } else { current_syscall_error.type = seL4_IllegalOperation; return EXCEPTION_SYSCALL_ERROR; } }