diff --git a/include/drivers/interrupt_controller/loapic.h b/include/drivers/interrupt_controller/loapic.h index 698ffc30b58..23671fa011f 100644 --- a/include/drivers/interrupt_controller/loapic.h +++ b/include/drivers/interrupt_controller/loapic.h @@ -39,6 +39,7 @@ #define LOAPIC_TIMER_ICR 0x380 /* Timer Initial Count Reg */ #define LOAPIC_TIMER_CCR 0x390 /* Timer Current Count Reg */ #define LOAPIC_TIMER_CONFIG 0x3e0 /* Timer Divide Config Reg */ +#define LOAPIC_SELF_IPI 0x3f0 /* Self IPI Reg, only support in X2APIC mode */ #define LOAPIC_ICR_BUSY 0x00001000 /* delivery status: 1 = busy */ diff --git a/subsys/testsuite/include/interrupt_util.h b/subsys/testsuite/include/interrupt_util.h index 09fad0cbf1f..76944c087e8 100644 --- a/subsys/testsuite/include/interrupt_util.h +++ b/subsys/testsuite/include/interrupt_util.h @@ -101,30 +101,49 @@ static inline void trigger_irq(int irq) } #elif defined(CONFIG_X86) + +#ifdef CONFIG_X2APIC #include +#define VECTOR_MASK 0xFF +#else #include +#define LOAPIC_ICR_IPI_TEST 0x00004000U +#endif #define TRIGGER_IRQ_INT(vector) __asm__ volatile("int %0" : : "i" (vector) : "memory") /* - * Write Local APIC's ICR to trigger IPI for testing + * We can emulate the interrupt by sending the IPI to + * core itself by the LOAPIC for x86 platform. + * + * In APIC mode, Write LOAPIC's ICR to trigger IPI, + * the LOAPIC_ICR_IPI_TEST 0x00004000U means: * Delivery Mode: Fixed * Destination Mode: Physical * Level: Assert * Trigger Mode: Edge * Destination Shorthand: No Shorthand * Destination: depends on cpu_id + * + * In X2APIC mode, this no longer works. We emulate the + * interrupt by writing the IA32_X2APIC_SELF_IPI MSR + * to send IPI to the core itself via LOAPIC also. + * According to SDM vol.3 chapter 10.12.11, the bit[7:0] + * for setting the vector is only needed. */ -#define LOAPIC_ICR_IPI_TEST 0x00004000U - static inline void trigger_irq(int vector) { +#ifdef CONFIG_X2APIC + x86_write_x2apic(LOAPIC_SELF_IPI, ((VECTOR_MASK & vector))); +#else + #ifdef CONFIG_SMP int cpu_id = arch_curr_cpu()->id; #else int cpu_id = 0; #endif z_loapic_ipi(cpu_id, LOAPIC_ICR_IPI_TEST, vector); +#endif /* CONFIG_X2APIC */ } #elif defined(CONFIG_ARCH_POSIX)