forked from Imagelibrary/seL4
ARM: No special handling for edge-triggered IRQs
Clearing the pending state only has an effect if the IRQ state is active-and-pending, which happens for edge-triggered interrupts if another edge happens on the IRQ line for the currently active interrupt. This window is small enough to ignore, at worst user space will get another notification, which is harmless. If unnecessary notifications are unwanted, the pending state should be cleared during seL4_IRQHandler_Ack(), as that covers a much bigger window. However, edge-triggered interrupts are not expected to happen often. Making all interrupt handling slightly faster and the code simpler is the better trade-off. Reading the GIC config word is very slow for GICv2, see pull #1107. Signed-off-by: Indan Zupancic <indan@nul.nu>
This commit is contained in:
@@ -126,21 +126,6 @@ extern volatile struct gic_dist_map *const gic_dist;
|
||||
extern volatile struct gic_cpu_iface_map *const gic_cpuiface;
|
||||
|
||||
/* Helpers */
|
||||
static inline int is_irq_edge_triggered(word_t irq)
|
||||
{
|
||||
int word = irq >> 4;
|
||||
int bit = ((irq & 0xf) * 2);
|
||||
return !!(gic_dist->config[word] & BIT(bit + 1));
|
||||
}
|
||||
|
||||
static inline void dist_pending_clr(word_t irq)
|
||||
{
|
||||
int word = IRQ_REG(irq);
|
||||
int bit = IRQ_BIT(irq);
|
||||
/* Using |= here is detrimental to your health */
|
||||
gic_dist->pending_clr[word] = BIT(bit);
|
||||
}
|
||||
|
||||
static inline void dist_enable_clr(word_t irq)
|
||||
{
|
||||
int word = IRQ_REG(irq);
|
||||
@@ -198,9 +183,6 @@ static inline void ackInterrupt(irq_t irq)
|
||||
{
|
||||
assert(IS_IRQ_VALID(active_irq[CURRENT_CPU_INDEX()])
|
||||
&& (active_irq[CURRENT_CPU_INDEX()] & IRQ_MASK) == IRQT_TO_IRQ(irq));
|
||||
if (is_irq_edge_triggered(IRQT_TO_IRQ(irq))) {
|
||||
dist_pending_clr(IRQT_TO_IRQ(irq));
|
||||
}
|
||||
gic_cpuiface->eoi = active_irq[CURRENT_CPU_INDEX()];
|
||||
active_irq[CURRENT_CPU_INDEX()] = IRQ_NONE;
|
||||
|
||||
|
||||
@@ -234,37 +234,6 @@ extern volatile struct gic_rdist_map *gic_rdist_map[CONFIG_MAX_NUM_NODES];
|
||||
extern volatile struct gic_rdist_sgi_ppi_map *gic_rdist_sgi_ppi_map[CONFIG_MAX_NUM_NODES];
|
||||
|
||||
/* Helpers */
|
||||
static inline int is_irq_edge_triggered(word_t irq)
|
||||
{
|
||||
uint32_t icfgr = 0;
|
||||
int word = irq >> 4;
|
||||
int bit = ((irq & 0xf) * 2);
|
||||
|
||||
if (HW_IRQ_IS_SGI(irq)) {
|
||||
return 0;
|
||||
}
|
||||
if (HW_IRQ_IS_PPI(irq)) {
|
||||
icfgr = gic_rdist_sgi_ppi_map[CURRENT_CPU_INDEX()]->icfgr1;
|
||||
} else {
|
||||
icfgr = gic_dist->icfgrn[word];
|
||||
}
|
||||
|
||||
return !!(icfgr & BIT(bit + 1));
|
||||
}
|
||||
|
||||
static inline void gic_pending_clr(word_t irq)
|
||||
{
|
||||
int word = IRQ_REG(irq);
|
||||
int bit = IRQ_BIT(irq);
|
||||
/* Using |= here is detrimental to your health */
|
||||
/* Applicable for SPI and PPIs */
|
||||
if (irq < SPI_START) {
|
||||
gic_rdist_sgi_ppi_map[CURRENT_CPU_INDEX()]->icpendr0 = BIT(bit);
|
||||
} else {
|
||||
gic_dist->icpendrn[word] = BIT(bit);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void gic_enable_clr(word_t irq)
|
||||
{
|
||||
int word = IRQ_REG(irq);
|
||||
@@ -340,12 +309,8 @@ static inline void maskInterrupt(bool_t disable, irq_t irq)
|
||||
|
||||
static inline void ackInterrupt(irq_t irq)
|
||||
{
|
||||
word_t hw_irq = IRQT_TO_IRQ(irq);
|
||||
assert(IS_IRQ_VALID(active_irq[CURRENT_CPU_INDEX()]) && (active_irq[CURRENT_CPU_INDEX()] & IRQ_MASK) == hw_irq);
|
||||
|
||||
if (is_irq_edge_triggered(hw_irq)) {
|
||||
gic_pending_clr(hw_irq);
|
||||
}
|
||||
assert(IS_IRQ_VALID(active_irq[CURRENT_CPU_INDEX()])
|
||||
&& (active_irq[CURRENT_CPU_INDEX()] & IRQ_MASK) == IRQT_TO_IRQ(irq));
|
||||
|
||||
/* Set End of Interrupt for active IRQ: ICC_EOIR1_EL1 */
|
||||
SYSTEM_WRITE_WORD(ICC_EOIR1_EL1, active_irq[CURRENT_CPU_INDEX()]);
|
||||
|
||||
Reference in New Issue
Block a user