x86: Lock interrupts when connecting interrupts

When dyanmicaly connecting an interrupt via irq_connect(), interrupts must be
locked both when allocating a dynamic interrupt stub and when updating the
interrupt descriptor table (IDT) to prevent race conditions.

Change-Id: I9c68c1f73dda478880f1a32793a84cb6eb87735e
Signed-off-by: Peter Mitsis <peter.mitsis@windriver.com>
This commit is contained in:
Peter Mitsis 2015-09-30 12:26:57 -04:00 committed by Anas Nashif
commit 616ca21599

View file

@ -168,14 +168,22 @@ static NANO_INT_STUB dynamic_stubs[ALL_DYNAMIC_STUBS] = {
static int _int_stub_alloc(void)
{
int i;
int rv = -1;
unsigned int key;
key = irq_lock();
for (i = 0; i < ALL_DYNAMIC_STUBS &&
dynamic_stubs[i][0] != _STUB_AVAIL; i++) {
}
if (i == ALL_DYNAMIC_STUBS) {
return -1;
} else {
return i;
/* Mark the stub as allocated by using the CALL opcode */
if (i != ALL_DYNAMIC_STUBS) {
dynamic_stubs[i][0] = IA32_CALL_OPCODE;
rv = i;
}
irq_unlock(key);
return rv;
}
#endif /* ALL_DYNAMIC_STUBS > 0 */
@ -209,21 +217,27 @@ void _IntVecSet(
)
{
unsigned long long *pIdtEntry;
unsigned int key;
/*
* The <vector> parameter must be less than the value of the
* CONFIG_IDT_NUM_VECTORS configuration parameter, however,
* explicit
* validation will not be performed in this primitive.
* explicit validation will not be performed in this primitive.
*/
pIdtEntry = (unsigned long long *)(_idt_base_address + (vector << 3));
/*
* Lock interrupts to protect the IDT entry to which _IdtEntryCreate() will
* write. They must be locked here because the _IdtEntryCreate() code is
* shared with the 'gen_idt' host tool.
*/
key = irq_lock();
_IdtEntCreate(pIdtEntry, routine, dpl);
irq_unlock(key);
/* not required to synchronize the instruction and data caches */
/* not required to synchronize the instruction and data caches */
}
/*
@ -349,9 +363,11 @@ int irq_connect(
* values of <boiRtn>, <eoiRtn>, <boiRtnParm>, <eoiRtnParm>,
* <boiParamRequired>, and <eoiParamRequired>. The invocation of
* _IntEnt() and _IntExit() will always be required.
*
* NOTE: The 'call' opcode for the call to _IntEnt() has already been
* written by _int_stub_alloc() to mark the stub as allocated.
*/
STUB_PTR[0] = IA32_CALL_OPCODE;
UNALIGNED_WRITE((unsigned int *)&STUB_PTR[1],
(unsigned int)&_IntEnt - (unsigned int)&STUB_PTR[5]);