[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:
Sylvain Gauthier
2019-07-19 14:14:24 +10:00
parent a6157d5d8e
commit 121943c3c7
18 changed files with 78 additions and 18 deletions

View File

@@ -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}")

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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