forked from Imagelibrary/seL4
[SMP] Added PPI support for gic_v2
Correctly defined the macros to translate between virtual and hardware IRQs such that PPIs can be properly handled on gic_v2. It is now possible to create a per-core handler for PPIs on platforms using this GIC.
This commit is contained in:
20
config.cmake
20
config.cmake
@@ -50,15 +50,25 @@ if(DEFINED CONFIGURE_MAX_IRQ)
|
||||
# calculate the irq cnode size based on MAX_IRQ
|
||||
if("${KernelArch}" STREQUAL "riscv")
|
||||
set(MAX_IRQ "${CONFIGURE_PLIC_MAX_NUM_INT}")
|
||||
math(EXPR MAX_IRQ "${MAX_IRQ} + 2")
|
||||
math(EXPR MAX_NUM_IRQ "${MAX_IRQ} + 2")
|
||||
else()
|
||||
set(MAX_IRQ "${CONFIGURE_MAX_IRQ}")
|
||||
if(
|
||||
DEFINED KernelMaxNumNodes
|
||||
AND CONFIGURE_NUM_PPI GREATER "0"
|
||||
AND "${KernelArch}" STREQUAL "arm"
|
||||
)
|
||||
math(
|
||||
EXPR MAX_NUM_IRQ
|
||||
"(${KernelMaxNumNodes}-1)*${CONFIGURE_NUM_PPI} + ${CONFIGURE_MAX_IRQ}"
|
||||
)
|
||||
else()
|
||||
set(MAX_NUM_IRQ "${CONFIGURE_MAX_IRQ}")
|
||||
endif()
|
||||
endif()
|
||||
set(BITS "0")
|
||||
set(MAX "${MAX_IRQ}")
|
||||
while(MAX GREATER "0")
|
||||
while(MAX_NUM_IRQ GREATER "0")
|
||||
math(EXPR BITS "${BITS} + 1")
|
||||
math(EXPR MAX "${MAX} >> 1")
|
||||
math(EXPR MAX_NUM_IRQ "${MAX_NUM_IRQ} >> 1")
|
||||
endwhile()
|
||||
math(EXPR SLOTS "1 << ${BITS}")
|
||||
if("${SLOTS}" LESS "${MAX_IRQ}")
|
||||
|
||||
@@ -98,6 +98,7 @@ endmacro()
|
||||
unset(CONFIGURE_PLIC_MAX_NUM_INT CACHE)
|
||||
unset(CONFIGURE_TIMER_FREQUENCY CACHE)
|
||||
unset(CONFIGURE_MAX_IRQ CACHE)
|
||||
unset(CONFIGURE_NUM_PPI CACHE)
|
||||
unset(CONFIGURE_INTERRUPT_CONTROLLER CACHE)
|
||||
unset(CONFIGURE_TIMER CACHE)
|
||||
unset(CONFIGURE_SMMU CACHE)
|
||||
@@ -107,11 +108,12 @@ function(declare_default_headers)
|
||||
0
|
||||
CONFIGURE
|
||||
""
|
||||
"TIMER_FREQUENCY;MAX_IRQ;PLIC_MAX_NUM_INT;INTERRUPT_CONTROLLER;TIMER;SMMU"
|
||||
"TIMER_FREQUENCY;MAX_IRQ;NUM_PPI;PLIC_MAX_NUM_INT;INTERRUPT_CONTROLLER;TIMER;SMMU"
|
||||
""
|
||||
)
|
||||
set(CONFIGURE_TIMER_FREQUENCY "${CONFIGURE_TIMER_FREQUENCY}" CACHE INTERNAL "")
|
||||
set(CONFIGURE_MAX_IRQ "${CONFIGURE_MAX_IRQ}" CACHE INTERNAL "")
|
||||
set(CONFIGURE_NUM_PPI "${CONFIGURE_NUM_PPI}" CACHE INTERNAL "")
|
||||
set(CONFIGURE_PLIC_MAX_NUM_INT "${CONFIGURE_PLIC_MAX_NUM_INT}" CACHE INTERNAL "")
|
||||
set(CONFIGURE_INTERRUPT_CONTROLLER "${CONFIGURE_INTERRUPT_CONTROLLER}" CACHE INTERNAL "")
|
||||
set(CONFIGURE_TIMER "${CONFIGURE_TIMER}" CACHE INTERNAL "")
|
||||
|
||||
@@ -42,6 +42,30 @@
|
||||
#define IRQ_MASK MASK(10u)
|
||||
#define IS_IRQ_VALID(X) (((X) & IRQ_MASK) < SPECIAL_IRQ_START)
|
||||
|
||||
#define NUM_PPI 32
|
||||
#define HW_IRQ_IS_PPI(irq) ((irq) < NUM_PPI)
|
||||
#define IRQ_IS_PPI(irq) ((irq) < NUM_PPI*CONFIG_MAX_NUM_NODES)
|
||||
|
||||
#if defined ENABLE_SMP_SUPPORT
|
||||
/* Takes a target core and an irq number and converts it to the intState index */
|
||||
#define CORE_IRQ_TO_IDX(tgt, irq) (HW_IRQ_IS_PPI(irq) ? \
|
||||
(tgt)*NUM_PPI + (irq) : \
|
||||
(CONFIG_MAX_NUM_NODES-1)*NUM_PPI + (irq))
|
||||
|
||||
/* Takes an intSate index and extracts the hardware irq number */
|
||||
#define IDX_TO_IRQ(idx) (IRQ_IS_PPI(idx) ? \
|
||||
(idx) - ((idx)/NUM_PPI)*NUM_PPI : \
|
||||
(idx) - (CONFIG_MAX_NUM_NODES-1)*NUM_PPI)
|
||||
|
||||
/* Takes an intState index and extracts the target CPU number */
|
||||
#define IDX_TO_CORE(idx) (IRQ_IS_PPI(idx) ? \
|
||||
(idx) / NUM_PPI : 0)
|
||||
#else
|
||||
#define CORE_IRQ_TO_IDX(tgt, irq) ((irq_t) (irq))
|
||||
#define IDX_TO_IRQ(idx) (idx)
|
||||
#define IDX_TO_CORE(idx) 0
|
||||
#endif
|
||||
|
||||
/* Helpers for VGIC */
|
||||
#define VGIC_HCR_EOI_INVALID_COUNT(hcr) (((hcr) >> 27) & 0x1f)
|
||||
#define VGIC_HCR_VGRP1DIE (1U << 7)
|
||||
@@ -188,7 +212,7 @@ static inline interrupt_t getActiveIRQ(void)
|
||||
irq = irqInvalid;
|
||||
}
|
||||
|
||||
return irq;
|
||||
return CORE_IRQ_TO_IDX(SMP_TERNARY(getCurrentCPUIndex(), 0), irq);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -203,19 +227,22 @@ static inline bool_t isIRQPending(void)
|
||||
|
||||
static inline void maskInterrupt(bool_t disable, interrupt_t irq)
|
||||
{
|
||||
#if defined ENABLE_SMP_SUPPORT && defined CONFIG_ARCH_ARM
|
||||
assert(!(IRQ_IS_PPI(irq)) || (IDX_TO_CORE(irq) == getCurrentCPUIndex()));
|
||||
#endif
|
||||
if (disable) {
|
||||
dist_enable_clr(irq);
|
||||
dist_enable_clr(IDX_TO_IRQ(irq));
|
||||
} else {
|
||||
dist_enable_set(irq);
|
||||
dist_enable_set(IDX_TO_IRQ(irq));
|
||||
}
|
||||
}
|
||||
|
||||
static inline void ackInterrupt(irq_t irq)
|
||||
{
|
||||
assert(IS_IRQ_VALID(active_irq[SMP_TERNARY(getCurrentCPUIndex(), 0)])
|
||||
&& (active_irq[SMP_TERNARY(getCurrentCPUIndex(), 0)] & IRQ_MASK) == irq);
|
||||
if (is_irq_edge_triggered(irq)) {
|
||||
dist_pending_clr(irq);
|
||||
&& (active_irq[SMP_TERNARY(getCurrentCPUIndex(), 0)] & IRQ_MASK) == IDX_TO_IRQ(irq));
|
||||
if (is_irq_edge_triggered(IDX_TO_IRQ(irq))) {
|
||||
dist_pending_clr(IDX_TO_IRQ(irq));
|
||||
}
|
||||
gic_cpuiface->eoi = active_irq[SMP_TERNARY(getCurrentCPUIndex(), 0)];
|
||||
active_irq[SMP_TERNARY(getCurrentCPUIndex(), 0)] = IRQ_NONE;
|
||||
|
||||
@@ -88,8 +88,12 @@ block irq_control_cap {
|
||||
}
|
||||
|
||||
block irq_handler_cap {
|
||||
padding 24
|
||||
field capIRQ 8
|
||||
#ifdef ENABLE_SMP_SUPPORT
|
||||
field capIRQ 32
|
||||
#else
|
||||
padding 24
|
||||
field capIRQ 8
|
||||
#endif
|
||||
|
||||
padding 24
|
||||
field capType 8
|
||||
|
||||
@@ -130,8 +130,12 @@ block irq_control_cap {
|
||||
}
|
||||
|
||||
block irq_handler_cap {
|
||||
#ifdef ENABLE_SMP_SUPPORT
|
||||
field capIRQ 64
|
||||
#else
|
||||
padding 52
|
||||
field capIRQ 12
|
||||
#endif
|
||||
|
||||
field capType 5
|
||||
padding 59
|
||||
|
||||
@@ -156,8 +156,8 @@ void setIRQTrigger(irq_t irq, bool_t trigger)
|
||||
/* in the gic_config, there is a 2 bit field for each irq,
|
||||
* setting the most significant bit of this field makes the irq edge-triggered,
|
||||
* while 0 indicates that it is level-triggered */
|
||||
word_t index = irq / 16u;
|
||||
word_t offset = (irq % 16u) * 2;
|
||||
word_t index = IDX_TO_IRQ(irq) / 16u;
|
||||
word_t offset = (IDX_TO_IRQ(irq) % 16u) * 2;
|
||||
if (trigger) {
|
||||
/* set the bit */
|
||||
gic_dist->config[index] |= BIT(offset + 1);
|
||||
@@ -214,13 +214,14 @@ void setIRQTarget(irq_t irq, seL4_Word target)
|
||||
{
|
||||
uint8_t targetList = 1 << target;
|
||||
uint8_t *targets = (void *)(gic_dist->targets);
|
||||
word_t hwIRQ = IDX_TO_IRQ(irq);
|
||||
|
||||
/* Return early if PPI */
|
||||
if (irq < SPI_START) {
|
||||
if (IRQ_IS_PPI(irq)) {
|
||||
fail("PPI can't have designated target core\n");
|
||||
return;
|
||||
}
|
||||
targets[irq] = targetList;
|
||||
targets[hwIRQ] = targetList;
|
||||
}
|
||||
#endif /* ENABLE_SMP_SUPPORT */
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@ if(KernelPlatformAllwinnerA20)
|
||||
declare_default_headers(
|
||||
TIMER_FREQUENCY 24000000llu
|
||||
MAX_IRQ 122
|
||||
NUM_PPI 32
|
||||
TIMER drivers/timer/allwinner.h
|
||||
INTERRUPT_CONTROLLER arch/machine/gic_v2.h
|
||||
)
|
||||
|
||||
@@ -26,6 +26,7 @@ if(KernelPlatformAPQ8064)
|
||||
declare_default_headers(
|
||||
TIMER_FREQUENCY 7000000llu
|
||||
MAX_IRQ 283
|
||||
NUM_PPI 32
|
||||
TIMER drivers/timer/arm_generic.h
|
||||
INTERRUPT_CONTROLLER arch/machine/gic_v2.h
|
||||
)
|
||||
|
||||
@@ -25,6 +25,7 @@ if(KernelPlatformExynos4)
|
||||
declare_default_headers(
|
||||
TIMER_FREQUENCY 24000000llu
|
||||
MAX_IRQ 159
|
||||
NUM_PPI 32
|
||||
TIMER drivers/timer/exynos4412-mct.h
|
||||
INTERRUPT_CONTROLLER arch/machine/gic_v2.h
|
||||
)
|
||||
|
||||
@@ -70,6 +70,7 @@ if(KernelPlatExynos5)
|
||||
declare_default_headers(
|
||||
TIMER_FREQUENCY 24000000llu
|
||||
MAX_IRQ 232
|
||||
NUM_PPI 32
|
||||
TIMER drivers/timer/arm_generic.h
|
||||
INTERRUPT_CONTROLLER arch/machine/gic_v2.h
|
||||
)
|
||||
|
||||
@@ -44,6 +44,7 @@ if(KernelPlatImx6)
|
||||
TIMER_FREQUENCY 400000000llu
|
||||
MAX_IRQ 159
|
||||
INTERRUPT_CONTROLLER arch/machine/gic_v2.h
|
||||
NUM_PPI 32
|
||||
TIMER drivers/timer/arm_priv.h
|
||||
)
|
||||
endif()
|
||||
|
||||
@@ -25,6 +25,7 @@ if(KernelPlatImx7)
|
||||
declare_default_headers(
|
||||
TIMER_FREQUENCY 8000000llu
|
||||
MAX_IRQ 159
|
||||
NUM_PPI 32
|
||||
TIMER drivers/timer/arm_generic.h
|
||||
INTERRUPT_CONTROLLER arch/machine/gic_v2.h
|
||||
)
|
||||
|
||||
@@ -24,6 +24,7 @@ if(KernelPlatformOdroidc2)
|
||||
declare_default_headers(
|
||||
TIMER_FREQUENCY 24000000llu
|
||||
MAX_IRQ 250
|
||||
NUM_PPI 32
|
||||
TIMER drivers/timer/arm_generic.h
|
||||
INTERRUPT_CONTROLLER arch/machine/gic_v2.h
|
||||
)
|
||||
|
||||
@@ -35,6 +35,7 @@ if(KernelPlatformTK1)
|
||||
TIMER_FREQUENCY 12000000llu
|
||||
MAX_IRQ 191
|
||||
INTERRUPT_CONTROLLER arch/machine/gic_v2.h
|
||||
NUM_PPI 32
|
||||
TIMER drivers/timer/arm_generic.h SMMU plat/machine/smmu.h
|
||||
)
|
||||
endif()
|
||||
|
||||
@@ -27,6 +27,7 @@ if(KernelPlatformTx1)
|
||||
TIMER_FREQUENCY 19200000llu
|
||||
MAX_IRQ 224
|
||||
INTERRUPT_CONTROLLER arch/machine/gic_v2.h
|
||||
NUM_PPI 32
|
||||
TIMER drivers/timer/arm_generic.h
|
||||
)
|
||||
endif()
|
||||
|
||||
@@ -30,6 +30,7 @@ if(KernelPlatformTx2)
|
||||
TIMER_FREQUENCY 31250000llu
|
||||
MAX_IRQ 383
|
||||
INTERRUPT_CONTROLLER arch/machine/gic_v2.h
|
||||
NUM_PPI 32
|
||||
TIMER drivers/timer/arm_generic.h
|
||||
)
|
||||
endif()
|
||||
|
||||
@@ -24,6 +24,7 @@ if(KernelPlatformZynq7000)
|
||||
declare_default_headers(
|
||||
TIMER_FREQUENCY 400000000llu
|
||||
MAX_IRQ 92
|
||||
NUM_PPI 32
|
||||
TIMER drivers/timer/arm_priv.h
|
||||
INTERRUPT_CONTROLLER arch/machine/gic_v2.h
|
||||
)
|
||||
|
||||
@@ -45,6 +45,7 @@ if(KernelPlatformZynqmp)
|
||||
declare_default_headers(
|
||||
TIMER_FREQUENCY 100000000llu
|
||||
MAX_IRQ 187
|
||||
NUM_PPI 32
|
||||
TIMER drivers/timer/arm_generic.h
|
||||
INTERRUPT_CONTROLLER arch/machine/gic_v2.h
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user