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:
Sylvain Gauthier 2019-05-13 13:03:53 +10:00
parent a0ae9f76a1
commit 84e6d4cdb1
5 changed files with 86 additions and 0 deletions

View file

@ -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);

View file

@ -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

View file

@ -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>

View file

@ -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

View file

@ -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;