arch/x86: Make irq_offload SMP-safe on x86_64
The irq_offload mechanism was using the same entry of the IDT vector for all CPUs on SMP systems. This caused race conditions when two CPUs were doing irq_offload() calls. This patch addresses that by adding one indirection layer: the irq_offload() now sets a per CPU entry with the routine and parameter to be run. Then a software interrupt is generated, and a default handler will do the appropriate dispatching. Finally, test "kernel/smp_abort" is enabled for x86 as it should work now. Fixes #72172. Signed-off-by: Ederson de Souza <ederson.desouza@intel.com>
This commit is contained in:
parent
af63e488f0
commit
7f0b5edd8c
2 changed files with 29 additions and 4 deletions
|
@ -9,6 +9,7 @@
|
|||
*/
|
||||
|
||||
#include <zephyr/kernel.h>
|
||||
#include <zephyr/init.h>
|
||||
#include <zephyr/irq_offload.h>
|
||||
#include <kernel_arch_data.h>
|
||||
|
||||
|
@ -17,12 +18,37 @@
|
|||
extern void (*x86_irq_funcs[NR_IRQ_VECTORS])(const void *arg);
|
||||
extern const void *x86_irq_args[NR_IRQ_VECTORS];
|
||||
|
||||
static void (*irq_offload_funcs[CONFIG_MP_NUM_CPUS])(const void *arg);
|
||||
static const void *irq_offload_args[CONFIG_MP_NUM_CPUS];
|
||||
|
||||
static void dispatcher(const void *arg)
|
||||
{
|
||||
uint8_t cpu_id = _current_cpu->id;
|
||||
|
||||
if (irq_offload_funcs[cpu_id] != NULL) {
|
||||
irq_offload_funcs[cpu_id](irq_offload_args[cpu_id]);
|
||||
}
|
||||
}
|
||||
|
||||
void arch_irq_offload(irq_offload_routine_t routine, const void *parameter)
|
||||
{
|
||||
x86_irq_funcs[CONFIG_IRQ_OFFLOAD_VECTOR - IV_IRQS] = routine;
|
||||
x86_irq_args[CONFIG_IRQ_OFFLOAD_VECTOR - IV_IRQS] = parameter;
|
||||
int key = arch_irq_lock();
|
||||
uint8_t cpu_id = _current_cpu->id;
|
||||
|
||||
irq_offload_funcs[cpu_id] = routine;
|
||||
irq_offload_args[cpu_id] = parameter;
|
||||
|
||||
__asm__ volatile("int %0" : : "i" (CONFIG_IRQ_OFFLOAD_VECTOR)
|
||||
: "memory");
|
||||
x86_irq_funcs[CONFIG_IRQ_OFFLOAD_VECTOR - IV_IRQS] = NULL;
|
||||
|
||||
arch_irq_unlock(key);
|
||||
}
|
||||
|
||||
int irq_offload_init(void)
|
||||
{
|
||||
x86_irq_funcs[CONFIG_IRQ_OFFLOAD_VECTOR - IV_IRQS] = dispatcher;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
SYS_INIT(irq_offload_init, PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
tests:
|
||||
kernel.smp_abort:
|
||||
arch_exclude: x86 # Buggy irq_offload(), see #71172
|
||||
tags:
|
||||
- kernel
|
||||
- smp
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue