MIPS: loongson64: add IRQ work based on self-IPI

Since the commit 91840be8f7 ("irq_work: Fix use-after-free in
irq_work_single() on PREEMPT_RT"), we observed the performance of
execve() is significantly impacted on MIPS.

While we are unsure how that commit caused the impact or how to improve
it (or even if it can be improved at all), implementing IRQ work with
self-IPI seems able to mitigate the impaction.

Perhaps this can/should be implemented for other MIPS architecture
processors as well, but we don't have the enough knowledge of them, nor
access to the hardware.  So only implement it for loongson64 here.

Link: https://lore.kernel.org/6be1cdd5f91dd7418a32ff372a6f3ae259b19195.camel@xry111.site/
Signed-off-by: Xi Ruoyao <xry111@xry111.site>
Reviewed-by: Huacai Chen <chenhuacai@loongson.cn>
Reviewed-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
This commit is contained in:
Xi Ruoyao 2026-06-24 01:27:21 +08:00 committed by Thomas Bogendoerfer
parent 6d5fbecd02
commit dceafc1803
3 changed files with 21 additions and 0 deletions

View File

@ -0,0 +1,9 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _ASM_MIPS_IRQ_WORK_H
#define _ASM_MIPS_IRQ_WORK_H
static inline bool arch_irq_work_has_interrupt(void)
{
return IS_ENABLED(CONFIG_MACH_LOONGSON64) && IS_ENABLED(CONFIG_SMP);
}
#endif /* _ASM_MIPS_IRQ_WORK_H */

View File

@ -50,6 +50,8 @@ extern int __cpu_logical_map[NR_CPUS];
#define SMP_CALL_FUNCTION 0x2
/* Octeon - Tell another core to flush its icache */
#define SMP_ICACHE_FLUSH 0x4
/* Loongson64 - Self IPI for IRQ work */
#define SMP_IRQ_WORK 0x8
/* Mask of CPUs which are currently definitely operating coherently */
extern cpumask_t cpu_coherent_mask;

View File

@ -381,6 +381,13 @@ loongson3_send_ipi_mask(const struct cpumask *mask, unsigned int action)
ipi_write_action(cpu_logical_map(i), (u32)action);
}
#ifdef CONFIG_IRQ_WORK
void arch_irq_work_raise(void)
{
loongson3_send_ipi_single(smp_processor_id(), SMP_IRQ_WORK);
}
#endif
static irqreturn_t loongson3_ipi_interrupt(int irq, void *dev_id)
{
int cpu = smp_processor_id();
@ -397,6 +404,9 @@ static irqreturn_t loongson3_ipi_interrupt(int irq, void *dev_id)
irq_exit();
}
if (action & SMP_IRQ_WORK)
irq_work_run();
return IRQ_HANDLED;
}