quark_se: make EOI operations atomic

Some issues have been noted with nested interrupts on quark SE.
In particular, the wrong vector # being sent to the IOAPIC EOI
register. Now when doing EOI, we lock interrupts so that the act
of reading the current vector being serviced, and sending EOI
to both controllers happens atomically.

Change-Id: Id9ad992740e197bb9d4638764952b04a27c4af61
Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
This commit is contained in:
Andrew Boie 2016-07-12 10:34:28 -07:00 committed by Inaky Perez-Gonzalez
commit af085b8edf
3 changed files with 14 additions and 4 deletions

View file

@ -288,7 +288,7 @@ SECTION_FUNC(TEXT, _IntExitWithEoi)
#endif
#if CONFIG_EOI_FORWARDING_BUG
call _lakemont_eoi
#endif
#else
xorl %eax, %eax /* zeroes eax */
/* TODO not great to have hard-coded LOAPIC stuff here. When
* we get around to introducing the interrupt controller abstraction
@ -298,6 +298,7 @@ SECTION_FUNC(TEXT, _IntExitWithEoi)
*/
loapic_eoi_reg = (CONFIG_LOAPIC_BASE_ADDRESS + LOAPIC_EOI)
movl %eax, loapic_eoi_reg /* tell LOAPIC the IRQ is handled */
#endif
/* fall through to _IntExit */
/**

View file

@ -32,13 +32,21 @@
void _lakemont_eoi(void)
{
int vector = _loapic_isr_vector_get();
int key;
key = irq_lock();
/* It is difficult to know whether the IRQ being serviced is
* a level interrupt handled by the IOAPIC; the only information
* we have is the vector # in the IDT. So unconditionally
* write to IOAPIC_EOI for every interrupt
*/
sys_write32(vector, CONFIG_IOAPIC_BASE_ADDRESS + IOAPIC_EOI);
sys_write32(_loapic_isr_vector_get(), CONFIG_IOAPIC_BASE_ADDRESS +
IOAPIC_EOI);
/* Send EOI to the LOAPIC as well */
sys_write32(0, CONFIG_LOAPIC_BASE_ADDRESS + LOAPIC_EOI);
irq_unlock(key);
}

View file

@ -80,8 +80,9 @@ static inline void _loapic_eoi(void)
{
#if CONFIG_EOI_FORWARDING_BUG
_lakemont_eoi();
#endif
#else
*(volatile int *)(CONFIG_LOAPIC_BASE_ADDRESS + LOAPIC_EOI) = 0;
#endif
}
#endif /* _ASMLANGUAGE */