Skip to content

Commit bb143f8

Browse files
committed
ARCv2: SMP: Emulate IPI to self using software triggered interrupt
ARConnect/MCIP Inter-Core-Interrupt module can't send interrupt to local core. So use core intc capability to trigger software interrupt to self, using an unsued IRQ #21. This showed up as csd deadlock with LTP trace_sched on a dual core system. This test acts as scheduler fuzzer, triggering all sorts of schedulting activity. Trouble starts with IPI to self, which doesn't get delivered (effectively lost due to H/w capability), but the msg intended to be sent remain enqueued in per-cpu @ipi_data. All subsequent IPIs to this core from other cores get elided due to the IPI coalescing optimization in ipi_send_msg_one() where a pending msg implies an IPI already sent and assumes other core is yet to ack it. After the elided IPI, other core simply goes into csd_lock_wait() but never comes out as this core never sees the interrupt. Fixes STAR 9001008624 Cc: Peter Zijlstra <[email protected]> Cc: <[email protected]> [4.2] Signed-off-by: Vineet Gupta <[email protected]>
1 parent 3e5177c commit bb143f8

File tree

3 files changed

+32
-5
lines changed

3 files changed

+32
-5
lines changed

arch/arc/include/asm/irqflags-arcv2.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#define AUX_IRQ_CTRL 0x00E
2323
#define AUX_IRQ_ACT 0x043 /* Active Intr across all levels */
2424
#define AUX_IRQ_LVL_PEND 0x200 /* Pending Intr across all levels */
25+
#define AUX_IRQ_HINT 0x201 /* For generating Soft Interrupts */
2526
#define AUX_IRQ_PRIORITY 0x206
2627
#define ICAUSE 0x40a
2728
#define AUX_IRQ_SELECT 0x40b
@@ -115,6 +116,16 @@ static inline int arch_irqs_disabled(void)
115116
return arch_irqs_disabled_flags(arch_local_save_flags());
116117
}
117118

119+
static inline void arc_softirq_trigger(int irq)
120+
{
121+
write_aux_reg(AUX_IRQ_HINT, irq);
122+
}
123+
124+
static inline void arc_softirq_clear(int irq)
125+
{
126+
write_aux_reg(AUX_IRQ_HINT, 0);
127+
}
128+
118129
#else
119130

120131
.macro IRQ_DISABLE scratch

arch/arc/kernel/entry-arcv2.S

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -45,11 +45,12 @@ VECTOR reserved ; Reserved slots
4545
VECTOR handle_interrupt ; (16) Timer0
4646
VECTOR handle_interrupt ; unused (Timer1)
4747
VECTOR handle_interrupt ; unused (WDT)
48-
VECTOR handle_interrupt ; (19) ICI (inter core interrupt)
49-
VECTOR handle_interrupt
50-
VECTOR handle_interrupt
51-
VECTOR handle_interrupt
52-
VECTOR handle_interrupt ; (23) End of fixed IRQs
48+
VECTOR handle_interrupt ; (19) Inter core Interrupt (IPI)
49+
VECTOR handle_interrupt ; (20) perf Interrupt
50+
VECTOR handle_interrupt ; (21) Software Triggered Intr (Self IPI)
51+
VECTOR handle_interrupt ; unused
52+
VECTOR handle_interrupt ; (23) unused
53+
# End of fixed IRQs
5354

5455
.rept CONFIG_ARC_NUMBER_OF_INTERRUPTS - 8
5556
VECTOR handle_interrupt

arch/arc/kernel/mcip.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,12 @@
1111
#include <linux/smp.h>
1212
#include <linux/irq.h>
1313
#include <linux/spinlock.h>
14+
#include <asm/irqflags-arcv2.h>
1415
#include <asm/mcip.h>
1516
#include <asm/setup.h>
1617

18+
#define SOFTIRQ_IRQ 21
19+
1720
static char smp_cpuinfo_buf[128];
1821
static int idu_detected;
1922

@@ -22,13 +25,20 @@ static DEFINE_RAW_SPINLOCK(mcip_lock);
2225
static void mcip_setup_per_cpu(int cpu)
2326
{
2427
smp_ipi_irq_setup(cpu, IPI_IRQ);
28+
smp_ipi_irq_setup(cpu, SOFTIRQ_IRQ);
2529
}
2630

2731
static void mcip_ipi_send(int cpu)
2832
{
2933
unsigned long flags;
3034
int ipi_was_pending;
3135

36+
/* ARConnect can only send IPI to others */
37+
if (unlikely(cpu == raw_smp_processor_id())) {
38+
arc_softirq_trigger(SOFTIRQ_IRQ);
39+
return;
40+
}
41+
3242
/*
3343
* NOTE: We must spin here if the other cpu hasn't yet
3444
* serviced a previous message. This can burn lots
@@ -63,6 +73,11 @@ static void mcip_ipi_clear(int irq)
6373
unsigned long flags;
6474
unsigned int __maybe_unused copy;
6575

76+
if (unlikely(irq == SOFTIRQ_IRQ)) {
77+
arc_softirq_clear(irq);
78+
return;
79+
}
80+
6681
raw_spin_lock_irqsave(&mcip_lock, flags);
6782

6883
/* Who sent the IPI */

0 commit comments

Comments
 (0)