Skip to content

Commit

Permalink
tests: testsuite: add emulating send IPI in X2APIC mode
Browse files Browse the repository at this point in the history
We emulate the interrupt by sending the IPI to core itself by
the local APIC for x86 platfrom.

But in X2APIC mode, this no longer works. So we emulate the
interrupt the 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.

Fixes zephyrproject-rtos#42108

Signed-off-by: Enjia Mai <[email protected]>
  • Loading branch information
enjiamai authored and nashif committed Mar 9, 2022
1 parent ad2799e commit 2b1bccd
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 3 deletions.
1 change: 1 addition & 0 deletions include/drivers/interrupt_controller/loapic.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */

Expand Down
25 changes: 22 additions & 3 deletions subsys/testsuite/include/interrupt_util.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,30 +101,49 @@ static inline void trigger_irq(int irq)
}

#elif defined(CONFIG_X86)

#ifdef CONFIG_X2APIC
#include <drivers/interrupt_controller/loapic.h>
#define VECTOR_MASK 0xFF
#else
#include <sys/arch_interface.h>
#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)
Expand Down

0 comments on commit 2b1bccd

Please sign in to comment.