Added IRQ routing to specific core for ARM
Add a new syscall, `seL4_IRQControl_GetTriggerCore`, to get a IRQHandler with specific target core(s) and trigger method. Only available in SMP mode.
This commit is contained in:
parent
a0ae9f76a1
commit
84e6d4cdb1
5 changed files with 86 additions and 0 deletions
|
|
@ -29,6 +29,9 @@ void initL2Cache(void);
|
|||
void initIRQController(void);
|
||||
void cpu_initLocalIRQController(void);
|
||||
void setIRQTrigger(irq_t irq, bool_t trigger);
|
||||
#ifdef ENABLE_SMP_SUPPORT
|
||||
void setIRQTarget(irq_t irq, seL4_Word target);
|
||||
#endif
|
||||
|
||||
static inline void plat_cleanL2Range(paddr_t start, paddr_t end);
|
||||
static inline void plat_invalidateL2Range(paddr_t start, paddr_t end);
|
||||
|
|
|
|||
|
|
@ -30,6 +30,13 @@ enum irqNumbers {
|
|||
irqInvalid = (irq_t) - 1
|
||||
};
|
||||
|
||||
/* CPU specific IRQ's */
|
||||
#define SGI_START 0u
|
||||
#define PPI_START 16u
|
||||
|
||||
/* Shared Peripheral Interrupts */
|
||||
#define SPI_START 32u
|
||||
|
||||
/* Special IRQ's */
|
||||
#define SPECIAL_IRQ_START 1020u
|
||||
#define IRQ_NONE 1023u
|
||||
|
|
@ -237,6 +244,7 @@ void initIRQController(void);
|
|||
#ifdef ENABLE_SMP_SUPPORT
|
||||
void ipiBroadcast(irq_t irq, bool_t includeSelfCPU);
|
||||
void ipi_send_target(irq_t irq, word_t cpuTargetList);
|
||||
void setIRQTarget(irq_t irq, seL4_Word target);
|
||||
#endif /* ENABLE_SMP_SUPPORT */
|
||||
|
||||
#ifdef CONFIG_ARM_HYPERVISOR_SUPPORT
|
||||
|
|
|
|||
|
|
@ -291,5 +291,22 @@
|
|||
<param dir="in" name="depth" type="seL4_Uint8" description="Number of bits of dest_index to resolve to find the destination slot."/>
|
||||
</method>
|
||||
|
||||
<method id="ARMIRQIssueIRQHandlerTriggerCore" name="GetTriggerCore" manual_name="GetTriggerCore"
|
||||
manual_label="irq_controlgettriggercore" condition="CONFIG_MAX_NUM_NODES > 1">
|
||||
<brief>
|
||||
Create an IRQ handler capability and specify the trigger method (edge or level) and the target core.
|
||||
</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."/>
|
||||
<param dir="in" name="target" type="seL4_Word" description="Indicates the target core ID to which this irq will be sent."/>
|
||||
</method>
|
||||
|
||||
</interface>
|
||||
</api>
|
||||
|
|
|
|||
|
|
@ -211,6 +211,22 @@ void ipi_send_target(irq_t irq, word_t cpuTargetList)
|
|||
}
|
||||
gic_dist->sgi_control = (cpuTargetList << (GICD_SGIR_CPUTARGETLIST_SHIFT)) | (irq << GICD_SGIR_SGIINTID_SHIFT);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set CPU target for the interrupt if it's not a PPI
|
||||
*/
|
||||
void setIRQTarget(irq_t irq, seL4_Word target)
|
||||
{
|
||||
uint8_t targetList = 1 << target;
|
||||
uint8_t *targets = (void *)(gic_dist->targets);
|
||||
|
||||
/* Return early if PPI */
|
||||
if (irq < SPI_START) {
|
||||
fail("PPI can't have designated target core\n");
|
||||
return;
|
||||
}
|
||||
targets[irq] = targetList;
|
||||
}
|
||||
#endif /* ENABLE_SMP_SUPPORT */
|
||||
|
||||
#ifdef CONFIG_ARM_HYPERVISOR_SUPPORT
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@
|
|||
|
||||
#include <types.h>
|
||||
#include <api/failures.h>
|
||||
#include <config.h>
|
||||
|
||||
#include <arch/object/interrupt.h>
|
||||
|
||||
|
|
@ -74,6 +75,47 @@ exception_t Arch_decodeIRQControlInvocation(word_t invLabel, word_t length,
|
|||
|
||||
setThreadState(NODE_STATE(ksCurThread), ThreadState_Restart);
|
||||
return Arch_invokeIRQControl(irq, destSlot, srcSlot, trigger);
|
||||
#ifdef ENABLE_SMP_SUPPORT
|
||||
} else if (invLabel == ARMIRQIssueIRQHandlerTriggerCore) {
|
||||
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) & 0xfful;
|
||||
seL4_Word target = getSyscallArg(4, 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);
|
||||
setIRQTarget(irq, target);
|
||||
return Arch_invokeIRQControl(irq, destSlot, srcSlot, trigger);
|
||||
#endif /* ENABLE_SMP_SUPPORT */
|
||||
} else {
|
||||
current_syscall_error.type = seL4_IllegalOperation;
|
||||
return EXCEPTION_SYSCALL_ERROR;
|
||||
|
|
|
|||
Loading…
Reference in a new issue