Skip to content
Snippets Groups Projects
Commit 4ce8f0a9 authored by Kent McLeod's avatar Kent McLeod
Browse files

Add RISC-V IRQ invocations

We add support for seL4_IRQControlGet and seL4_IRQControlGetTrigger. If
a platform doesn't support setting the trigger, then
seL4_IRQControlGetTrigger will return an error. If the platform doesn't
have a PLIC driver, then it won't have any IRQs that can be requested.

Also authored by: Siwei Zhuang <siwei.zhuang@data61.csiro.au>
parent 9a552d84
No related branches found
No related tags found
No related merge requests found
......@@ -77,6 +77,7 @@ void initTimer(void);
void initL2Cache(void);
void initIRQController(void);
void setIRQTrigger(irq_t irq, bool_t trigger);
void handleSpuriousIRQ(void);
......
......@@ -194,4 +194,24 @@
</param>
</method>
</interface>
<interface name="seL4_IRQControl" manual_name="IRQ Control" cap_description="An IRQControl capability. This gives you the authority to make this call.">
<method id="RISCVIRQIssueIRQHandlerTrigger" name="GetTrigger" manual_name="GetTrigger"
manual_label="irq_controlgettrigger">
<brief>
Create an IRQ handler capability and specify the trigger method (edge or level).
</brief>
<description>
<docref>See <autoref label="sec:interrupts"/>.</docref>
</description>
<param dir="in" name="irq" type="seL4_Word" description="The IRQ that you want this capability to handle."/>
<param dir="in" name="trigger" type="seL4_Word" description="Indicates whether this IRQ is edge (1) or level (0) triggered."/>
<param dir="in" name="root" type="seL4_CNode" description="CPTR to the CNode that forms the root of the destination CSpace. Must be at a depth equivalent to the wordsize."/>
<param dir="in" name="index" type="seL4_Word" description="CPTR to the destination slot. Resolved from the root of the destination CSpace."/>
<param dir="in" name="depth" type="seL4_Uint8" description="Number of bits of dest_index to resolve to find the destination slot."/>
</method>
</interface>
</api>
......@@ -23,13 +23,79 @@
exception_t Arch_checkIRQ(word_t irq)
{
return EXCEPTION_SYSCALL_ERROR;
if (irq > PLIC_MAX_IRQ && irq != irqInvalid) {
current_syscall_error.type = seL4_RangeError;
current_syscall_error.rangeErrorMin = 1;
current_syscall_error.rangeErrorMax = maxIRQ;
userError("Rejecting request for IRQ %u. IRQ is greater than maxIRQ.", (int)irq);
return EXCEPTION_SYSCALL_ERROR;
}
return EXCEPTION_NONE;
}
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)
{
current_syscall_error.type = seL4_IllegalOperation;
return EXCEPTION_SYSCALL_ERROR;
if (invLabel == RISCVIRQIssueIRQHandlerTrigger) {
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;
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment