bsps/i386: replace global interrupt disable by SMP build supporting locking.

This commit is contained in:
Pavel Pisa
2016-10-12 09:40:41 +02:00
parent f45ddeea12
commit 6b54dcbbef
9 changed files with 148 additions and 72 deletions

View File

@@ -84,15 +84,18 @@ static uint32_t pc386_get_timecount_i8254(struct timecounter *tc)
{ {
uint32_t irqs; uint32_t irqs;
uint8_t lsb, msb; uint8_t lsb, msb;
rtems_interrupt_level level; rtems_interrupt_lock_context lock_context;
/* /*
* Fetch all the data in an interrupt critical section. * Fetch all the data in an interrupt critical section.
*/ */
rtems_interrupt_disable(level);
rtems_interrupt_lock_acquire(&rtems_i386_i8254_access_lock, &lock_context);
READ_8254(lsb, msb); READ_8254(lsb, msb);
irqs = Clock_driver_ticks; irqs = Clock_driver_ticks;
rtems_interrupt_enable(level);
rtems_interrupt_lock_release(&rtems_i386_i8254_access_lock, &lock_context);
return (irqs + 1) * pc386_microseconds_per_isr - ((msb << 8) | lsb); return (irqs + 1) * pc386_microseconds_per_isr - ((msb << 8) | lsb);
} }
@@ -141,6 +144,7 @@ static void calibrate_tsc(void)
static void clockOn(void) static void clockOn(void)
{ {
rtems_interrupt_lock_context lock_context;
pc386_isrs_per_tick = 1; pc386_isrs_per_tick = 1;
pc386_microseconds_per_isr = rtems_configuration_get_microseconds_per_tick(); pc386_microseconds_per_isr = rtems_configuration_get_microseconds_per_tick();
@@ -150,8 +154,6 @@ static void clockOn(void)
} }
pc386_clock_click_count = US_TO_TICK(pc386_microseconds_per_isr); pc386_clock_click_count = US_TO_TICK(pc386_microseconds_per_isr);
bsp_interrupt_vector_enable( BSP_PERIODIC_TIMER - BSP_IRQ_VECTOR_BASE );
#if 0 #if 0
printk( "configured usecs per tick=%d \n", printk( "configured usecs per tick=%d \n",
rtems_configuration_get_microseconds_per_tick() ); rtems_configuration_get_microseconds_per_tick() );
@@ -160,9 +162,13 @@ static void clockOn(void)
printk( "final timer counts=%d\n", pc386_clock_click_count ); printk( "final timer counts=%d\n", pc386_clock_click_count );
#endif #endif
rtems_interrupt_lock_acquire(&rtems_i386_i8254_access_lock, &lock_context);
outport_byte(TIMER_MODE, TIMER_SEL0|TIMER_16BIT|TIMER_RATEGEN); outport_byte(TIMER_MODE, TIMER_SEL0|TIMER_16BIT|TIMER_RATEGEN);
outport_byte(TIMER_CNTR0, pc386_clock_click_count >> 0 & 0xff); outport_byte(TIMER_CNTR0, pc386_clock_click_count >> 0 & 0xff);
outport_byte(TIMER_CNTR0, pc386_clock_click_count >> 8 & 0xff); outport_byte(TIMER_CNTR0, pc386_clock_click_count >> 8 & 0xff);
rtems_interrupt_lock_release(&rtems_i386_i8254_access_lock, &lock_context);
bsp_interrupt_vector_enable( BSP_PERIODIC_TIMER - BSP_IRQ_VECTOR_BASE );
/* /*
* Now calibrate cycles per tick. Do this every time we * Now calibrate cycles per tick. Do this every time we
@@ -174,10 +180,13 @@ static void clockOn(void)
static void clockOff(void) static void clockOff(void)
{ {
rtems_interrupt_lock_context lock_context;
rtems_interrupt_lock_acquire(&rtems_i386_i8254_access_lock, &lock_context);
/* reset timer mode to standard (BIOS) value */ /* reset timer mode to standard (BIOS) value */
outport_byte(TIMER_MODE, TIMER_SEL0 | TIMER_16BIT | TIMER_RATEGEN); outport_byte(TIMER_MODE, TIMER_SEL0 | TIMER_16BIT | TIMER_RATEGEN);
outport_byte(TIMER_CNTR0, 0); outport_byte(TIMER_CNTR0, 0);
outport_byte(TIMER_CNTR0, 0); outport_byte(TIMER_CNTR0, 0);
rtems_interrupt_lock_release(&rtems_i386_i8254_access_lock, &lock_context);
} /* Clock_exit */ } /* Clock_exit */
bool Clock_isr_enabled = false; bool Clock_isr_enabled = false;

View File

@@ -260,13 +260,17 @@ int BSP_wait_polled_input(void)
int rtems_kbpoll( void ) int rtems_kbpoll( void )
{ {
int rc; int rc;
rtems_interrupt_level level;
rtems_interrupt_disable(level); /*
* The locking or disable of interrupts does not help
* there because if interrupts are enabled after leave of this
* function the state can change without notice anyway.
*/
RTEMS_COMPILER_MEMORY_BARRIER();
rc = ( kbd_first != kbd_last ) ? TRUE : FALSE; rc = ( kbd_first != kbd_last ) ? TRUE : FALSE;
rtems_interrupt_enable(level); RTEMS_COMPILER_MEMORY_BARRIER();
return rc; return rc;
} }

View File

@@ -9,6 +9,7 @@
#include <rtems/kd.h> #include <rtems/kd.h>
#include <bsp.h> #include <bsp.h>
#include <bsp/bootcard.h> #include <bsp/bootcard.h>
#include <stdatomic.h>
#define SIZE(x) (sizeof(x)/sizeof((x)[0])) #define SIZE(x) (sizeof(x)/sizeof((x)[0]))
@@ -28,59 +29,53 @@
#define KBD_DEFLOCK 0 #define KBD_DEFLOCK 0
#endif #endif
static int set_bit(int nr, unsigned long * addr) static int kbd_test_and_set_bit(int nr, atomic_uint_least32_t * addr)
{ {
int mask; uint_least32_t mask;
int retval; int retval;
rtems_interrupt_level level;
addr += nr >> 5; addr += nr >> 5;
mask = 1 << (nr & 0x1f); mask = 1UL << (nr & 0x1f);
rtems_interrupt_disable(level);
retval = (mask & *addr) != 0; retval = (atomic_fetch_or(addr, mask) & mask) != 0;
*addr |= mask;
rtems_interrupt_enable(level);
return retval; return retval;
} }
static int clear_bit(int nr, unsigned long * addr) static int kbd_test_and_clear_bit(int nr, atomic_uint_least32_t * addr)
{ {
int mask; uint_least32_t mask;
int retval; int retval;
rtems_interrupt_level level;
addr += nr >> 5; addr += nr >> 5;
mask = 1 << (nr & 0x1f); mask = 1UL << (nr & 0x1f);
rtems_interrupt_disable(level);
retval = (mask & *addr) != 0; retval = (atomic_fetch_and(addr, ~mask) & mask) != 0;
*addr &= ~mask;
rtems_interrupt_enable(level);
return retval; return retval;
} }
static int test_bit(int nr, unsigned long * addr) static int kbd_test_bit(int nr, atomic_uint_least32_t * addr)
{ {
int mask; unsigned long mask;
addr += nr >> 5; addr += nr >> 5;
mask = 1 << (nr & 0x1f); mask = 1 << (nr & 0x1f);
return ((mask & *addr) != 0); return ((mask & atomic_load(addr)) != 0);
} }
#define test_and_set_bit(x,y) set_bit(x,y)
#define test_and_clear_bit(x,y) clear_bit(x,y)
/* /*
* global state includes the following, and various static variables * global state includes the following, and various static variables
* in this module: prev_scancode, shift_state, diacr, npadch, dead_key_next. * in this module: prev_scancode, shift_state, diacr, npadch, dead_key_next.
* (last_console is now a global variable) * (last_console is now a global variable)
*/ */
#define BITS_PER_LONG (sizeof(long)*CHAR_BIT) #define KBD_BITS_PER_ELEMENT (sizeof(atomic_uint_least32_t)*CHAR_BIT)
/* shift state counters.. */ /* shift state counters.. */
static unsigned char k_down[NR_SHIFT] = {0, }; static unsigned char k_down[NR_SHIFT] = {0, };
/* keyboard key bitmap */ /* keyboard key bitmap */
static unsigned long key_down[256/BITS_PER_LONG] = { 0, }; static atomic_uint_least32_t
key_down[(256 + KBD_BITS_PER_ELEMENT - 1) / KBD_BITS_PER_ELEMENT] = { 0, };
static int dead_key_next = 0; static int dead_key_next = 0;
/* /*
@@ -243,10 +238,10 @@ void handle_scancode(unsigned char scancode, int down)
if (up_flag) { if (up_flag) {
rep = 0; rep = 0;
if(!test_and_clear_bit(keycode, key_down)) if(!kbd_test_and_clear_bit(keycode, key_down))
up_flag = kbd_unexpected_up(keycode); up_flag = kbd_unexpected_up(keycode);
} else } else
rep = test_and_set_bit(keycode, key_down); rep = kbd_test_and_set_bit(keycode, key_down);
#ifdef CONFIG_MAGIC_SYSRQ /* Handle the SysRq Hack */ #ifdef CONFIG_MAGIC_SYSRQ /* Handle the SysRq Hack */
if (keycode == SYSRQ_KEY) { if (keycode == SYSRQ_KEY) {
@@ -695,10 +690,10 @@ void compute_shiftstate(void)
k_down[i] = 0; k_down[i] = 0;
for(i=0; i < SIZE(key_down); i++) for(i=0; i < SIZE(key_down); i++)
if(key_down[i]) { /* skip this word if not a single bit on */ if(atomic_load(key_down + i)) { /* skip this word if not a single bit on */
k = i*BITS_PER_LONG; k = i*KBD_BITS_PER_ELEMENT;
for(j=0; j<BITS_PER_LONG; j++,k++) for(j=0; j<KBD_BITS_PER_ELEMENT; j++,k++)
if(test_bit(k, key_down)) { if(kbd_test_bit(k, key_down)) {
sym = U(plain_map[k]); sym = U(plain_map[k]);
if(KTYP(sym) == KT_SHIFT) { if(KTYP(sym) == KT_SHIFT) {
val = KVAL(sym); val = KVAL(sym);

View File

@@ -18,6 +18,7 @@
#include <sys/types.h> #include <sys/types.h>
#include <errno.h> #include <errno.h>
#include <bsp.h>
#include <i386_io.h> #include <i386_io.h>
#include <rtems.h> #include <rtems.h>
#include <rtems/kd.h> #include <rtems/kd.h>
@@ -69,21 +70,21 @@ static void
_kd_mksound(unsigned int hz, unsigned int ticks) _kd_mksound(unsigned int hz, unsigned int ticks)
{ {
unsigned int count = 0; unsigned int count = 0;
rtems_interrupt_level level; rtems_interrupt_lock_context lock_context;
if (hz > 20 && hz < 32767) if (hz > 20 && hz < 32767)
count = 1193180 / hz; count = 1193180 / hz;
rtems_interrupt_disable(level); rtems_interrupt_lock_acquire(&rtems_i386_i8254_access_lock, &lock_context);
/* del_timer(&sound_timer); */ /* del_timer(&sound_timer); */
if (count) { if (count) {
/* enable counter 2 */ /* enable counter 2 */
outb_p(inb_p(0x61)|3, 0x61); outb_p(inb_p(0x61)|3, 0x61);
/* set command for counter 2, 2 byte write */ /* set command for counter 2, 2 byte write */
outb_p(0xB6, 0x43); outb_p(0xB6, TIMER_MODE);
/* select desired HZ */ /* select desired HZ */
outb_p(count & 0xff, 0x42); outb_p(count & 0xff, TIMER_CNTR2);
outb((count >> 8) & 0xff, 0x42); outb((count >> 8) & 0xff, TIMER_CNTR2);
/* /*
if (ticks) { if (ticks) {
@@ -94,7 +95,7 @@ _kd_mksound(unsigned int hz, unsigned int ticks)
} else } else
kd_nosound(0); kd_nosound(0);
rtems_interrupt_enable(level); rtems_interrupt_lock_release(&rtems_i386_i8254_access_lock, &lock_context);
return; return;
} }

View File

@@ -146,6 +146,11 @@ extern int rtems_3c509_driver_attach(struct rtems_bsdnet_ifconfig *config);
#define TIMER_TICK 1193182 /* The internal tick rate in ticks per second */ #define TIMER_TICK 1193182 /* The internal tick rate in ticks per second */
#if defined( RTEMS_SMP )
extern ISR_lock_Control rtems_i386_i8254_access_lock;
#endif
/*-------------------------------------------------------------------------+ /*-------------------------------------------------------------------------+
| Console Defines | Console Defines
| WARNING: These Values MUST match the order in | WARNING: These Values MUST match the order in

View File

@@ -44,6 +44,9 @@
#define CMD_READ_BACK_STATUS 0xE2 /* command read back status */ #define CMD_READ_BACK_STATUS 0xE2 /* command read back status */
RTEMS_INTERRUPT_LOCK_DEFINE( /* visible global variable */ ,
rtems_i386_i8254_access_lock, "rtems_i386_i8254_access_lock" );
/* /*
* Global Variables * Global Variables
*/ */
@@ -115,23 +118,35 @@ static uint32_t tsc_read_timer(void)
*/ */
static void timerOff(const rtems_raw_irq_connect_data* used) static void timerOff(const rtems_raw_irq_connect_data* used)
{ {
rtems_interrupt_lock_context lock_context;
/* /*
* disable interrrupt at i8259 level * disable interrrupt at i8259 level
*/ */
bsp_interrupt_vector_disable(used->idtIndex - BSP_IRQ_VECTOR_BASE); bsp_interrupt_vector_disable(used->idtIndex - BSP_IRQ_VECTOR_BASE);
rtems_interrupt_lock_acquire(&rtems_i386_i8254_access_lock, &lock_context);
/* reset timer mode to standard (DOS) value */ /* reset timer mode to standard (DOS) value */
outport_byte(TIMER_MODE, TIMER_SEL0|TIMER_16BIT|TIMER_RATEGEN); outport_byte(TIMER_MODE, TIMER_SEL0|TIMER_16BIT|TIMER_RATEGEN);
outport_byte(TIMER_CNTR0, 0); outport_byte(TIMER_CNTR0, 0);
outport_byte(TIMER_CNTR0, 0); outport_byte(TIMER_CNTR0, 0);
rtems_interrupt_lock_release(&rtems_i386_i8254_access_lock, &lock_context);
} }
static void timerOn(const rtems_raw_irq_connect_data* used) static void timerOn(const rtems_raw_irq_connect_data* used)
{ {
rtems_interrupt_lock_context lock_context;
rtems_interrupt_lock_acquire(&rtems_i386_i8254_access_lock, &lock_context);
/* load timer for US_PER_ISR microsecond period */ /* load timer for US_PER_ISR microsecond period */
outport_byte(TIMER_MODE, TIMER_SEL0|TIMER_16BIT|TIMER_RATEGEN); outport_byte(TIMER_MODE, TIMER_SEL0|TIMER_16BIT|TIMER_RATEGEN);
outport_byte(TIMER_CNTR0, US_TO_TICK(US_PER_ISR) >> 0 & 0xff); outport_byte(TIMER_CNTR0, US_TO_TICK(US_PER_ISR) >> 0 & 0xff);
outport_byte(TIMER_CNTR0, US_TO_TICK(US_PER_ISR) >> 8 & 0xff); outport_byte(TIMER_CNTR0, US_TO_TICK(US_PER_ISR) >> 8 & 0xff);
rtems_interrupt_lock_release(&rtems_i386_i8254_access_lock, &lock_context);
/* /*
* enable interrrupt at i8259 level * enable interrrupt at i8259 level
*/ */
@@ -199,10 +214,14 @@ static uint32_t i386_read_timer(void)
{ {
register uint32_t total, clicks; register uint32_t total, clicks;
register uint8_t lsb, msb; register uint8_t lsb, msb;
rtems_interrupt_lock_context lock_context;
rtems_interrupt_lock_acquire(&rtems_i386_i8254_access_lock, &lock_context);
outport_byte(TIMER_MODE, TIMER_SEL0|TIMER_LATCH); outport_byte(TIMER_MODE, TIMER_SEL0|TIMER_LATCH);
inport_byte(TIMER_CNTR0, lsb); inport_byte(TIMER_CNTR0, lsb);
inport_byte(TIMER_CNTR0, msb); inport_byte(TIMER_CNTR0, msb);
rtems_interrupt_lock_release(&rtems_i386_i8254_access_lock, &lock_context);
clicks = (msb << 8) | lsb; clicks = (msb << 8) | lsb;
total = (Ttimer_val * US_PER_ISR) + (US_PER_ISR - TICK_TO_US(clicks)); total = (Ttimer_val * US_PER_ISR) + (US_PER_ISR - TICK_TO_US(clicks));
@@ -273,10 +292,13 @@ static unsigned short lastLoadedValue;
*/ */
static void loadTimerValue( unsigned short loadedValue ) static void loadTimerValue( unsigned short loadedValue )
{ {
rtems_interrupt_lock_context lock_context;
rtems_interrupt_lock_acquire(&rtems_i386_i8254_access_lock, &lock_context);
lastLoadedValue = loadedValue; lastLoadedValue = loadedValue;
outport_byte(TIMER_MODE, TIMER_SEL0|TIMER_16BIT|TIMER_SQWAVE); outport_byte(TIMER_MODE, TIMER_SEL0|TIMER_16BIT|TIMER_SQWAVE);
outport_byte(TIMER_CNTR0, loadedValue & 0xff); outport_byte(TIMER_CNTR0, loadedValue & 0xff);
outport_byte(TIMER_CNTR0, (loadedValue >> 8) & 0xff); outport_byte(TIMER_CNTR0, (loadedValue >> 8) & 0xff);
rtems_interrupt_lock_release(&rtems_i386_i8254_access_lock, &lock_context);
} }
/* /*
@@ -290,6 +312,8 @@ static unsigned int readTimer0(void)
unsigned short lsb, msb; unsigned short lsb, msb;
unsigned char status; unsigned char status;
unsigned int count; unsigned int count;
rtems_interrupt_lock_context lock_context;
rtems_interrupt_lock_acquire(&rtems_i386_i8254_access_lock, &lock_context);
outport_byte( outport_byte(
TIMER_MODE, TIMER_MODE,
@@ -298,6 +322,9 @@ static unsigned int readTimer0(void)
inport_byte(TIMER_CNTR0, status); inport_byte(TIMER_CNTR0, status);
inport_byte(TIMER_CNTR0, lsb); inport_byte(TIMER_CNTR0, lsb);
inport_byte(TIMER_CNTR0, msb); inport_byte(TIMER_CNTR0, msb);
rtems_interrupt_lock_release(&rtems_i386_i8254_access_lock, &lock_context);
count = ( msb << 8 ) | lsb ; count = ( msb << 8 ) | lsb ;
if (status & RB_OUTPUT ) if (status & RB_OUTPUT )
count += lastLoadedValue; count += lastLoadedValue;
@@ -337,7 +364,13 @@ Calibrate_loop_1ms(void)
rtems_interrupt_level level; rtems_interrupt_level level;
int retries = 0; int retries = 0;
rtems_interrupt_disable(level); /*
* This code is designed to run before interrupt management
* is enabled and running it on multiple CPUs and or after
* secondary CPUs are bring up seems really broken.
* Disabling of local interrupts is enough.
*/
rtems_interrupt_local_disable(level);
retry: retry:
if ( ++retries >= 5 ) { if ( ++retries >= 5 ) {
@@ -506,7 +539,7 @@ retry:
#ifdef DEBUG_CALIBRATE #ifdef DEBUG_CALIBRATE
printk("slowLoop1ms = %u, fastLoop1ms = %u\n", slowLoop1ms, fastLoop1ms); printk("slowLoop1ms = %u, fastLoop1ms = %u\n", slowLoop1ms, fastLoop1ms);
#endif #endif
rtems_interrupt_enable(level); rtems_interrupt_local_enable(level);
} }

View File

@@ -19,6 +19,16 @@
#include <rtems/score/cpu.h> #include <rtems/score/cpu.h>
#include <bsp/irq.h> #include <bsp/irq.h>
/*
* This locking is not enough if IDT is changed at runtime
* and entry can be changed for vector which is enabled
* at change time. But such use is broken anyway.
* Protect code only against concurrent changes.
* Even that is probably unnecessary if different
* entries are changed concurrently.
*/
RTEMS_INTERRUPT_LOCK_DEFINE( static, rtems_idt_access_lock, "rtems_idt_access_lock" );
static rtems_raw_irq_connect_data* raw_irq_table; static rtems_raw_irq_connect_data* raw_irq_table;
static rtems_raw_irq_connect_data default_raw_irq_entry; static rtems_raw_irq_connect_data default_raw_irq_entry;
static interrupt_gate_descriptor default_idt_entry; static interrupt_gate_descriptor default_idt_entry;
@@ -60,7 +70,7 @@ int i386_set_idt_entry (const rtems_raw_irq_connect_data* irq)
{ {
interrupt_gate_descriptor* idt_entry_tbl; interrupt_gate_descriptor* idt_entry_tbl;
unsigned limit; unsigned limit;
rtems_interrupt_level level; rtems_interrupt_lock_context lock_context;
i386_get_info_from_IDTR (&idt_entry_tbl, &limit); i386_get_info_from_IDTR (&idt_entry_tbl, &limit);
@@ -81,14 +91,14 @@ int i386_set_idt_entry (const rtems_raw_irq_connect_data* irq)
return 0; return 0;
} }
rtems_interrupt_disable(level); rtems_interrupt_lock_acquire(&rtems_idt_access_lock, &lock_context);
raw_irq_table [irq->idtIndex] = *irq; raw_irq_table [irq->idtIndex] = *irq;
create_interrupt_gate_descriptor (&idt_entry_tbl[irq->idtIndex], irq->hdl); create_interrupt_gate_descriptor (&idt_entry_tbl[irq->idtIndex], irq->hdl);
if (irq->on) if (irq->on)
irq->on(irq); irq->on(irq);
rtems_interrupt_enable(level); rtems_interrupt_lock_release(&rtems_idt_access_lock, &lock_context);
return 1; return 1;
} }
@@ -99,7 +109,7 @@ void _CPU_ISR_install_vector (uint32_t vector,
interrupt_gate_descriptor* idt_entry_tbl; interrupt_gate_descriptor* idt_entry_tbl;
unsigned limit; unsigned limit;
interrupt_gate_descriptor new; interrupt_gate_descriptor new;
rtems_interrupt_level level; rtems_interrupt_lock_context lock_context;
i386_get_info_from_IDTR (&idt_entry_tbl, &limit); i386_get_info_from_IDTR (&idt_entry_tbl, &limit);
@@ -109,14 +119,14 @@ void _CPU_ISR_install_vector (uint32_t vector,
if (vector >= limit) { if (vector >= limit) {
return; return;
} }
rtems_interrupt_disable(level); rtems_interrupt_lock_acquire(&rtems_idt_access_lock, &lock_context);
* ((unsigned int *) oldHdl) = idt_entry_tbl[vector].low_offsets_bits | * ((unsigned int *) oldHdl) = idt_entry_tbl[vector].low_offsets_bits |
(idt_entry_tbl[vector].high_offsets_bits << 16); (idt_entry_tbl[vector].high_offsets_bits << 16);
create_interrupt_gate_descriptor(&new, hdl); create_interrupt_gate_descriptor(&new, hdl);
idt_entry_tbl[vector] = new; idt_entry_tbl[vector] = new;
rtems_interrupt_enable(level); rtems_interrupt_lock_release(&rtems_idt_access_lock, &lock_context);
} }
int i386_get_current_idt_entry (rtems_raw_irq_connect_data* irq) int i386_get_current_idt_entry (rtems_raw_irq_connect_data* irq)
@@ -143,7 +153,7 @@ int i386_delete_idt_entry (const rtems_raw_irq_connect_data* irq)
{ {
interrupt_gate_descriptor* idt_entry_tbl; interrupt_gate_descriptor* idt_entry_tbl;
unsigned limit; unsigned limit;
rtems_interrupt_level level; rtems_interrupt_lock_context lock_context;
i386_get_info_from_IDTR (&idt_entry_tbl, &limit); i386_get_info_from_IDTR (&idt_entry_tbl, &limit);
@@ -163,7 +173,7 @@ int i386_delete_idt_entry (const rtems_raw_irq_connect_data* irq)
if (get_hdl_from_vector(irq->idtIndex) != irq->hdl){ if (get_hdl_from_vector(irq->idtIndex) != irq->hdl){
return 0; return 0;
} }
rtems_interrupt_disable(level); rtems_interrupt_lock_acquire(&rtems_idt_access_lock, &lock_context);
idt_entry_tbl[irq->idtIndex] = default_idt_entry; idt_entry_tbl[irq->idtIndex] = default_idt_entry;
@@ -173,7 +183,7 @@ int i386_delete_idt_entry (const rtems_raw_irq_connect_data* irq)
raw_irq_table[irq->idtIndex] = default_raw_irq_entry; raw_irq_table[irq->idtIndex] = default_raw_irq_entry;
raw_irq_table[irq->idtIndex].idtIndex = irq->idtIndex; raw_irq_table[irq->idtIndex].idtIndex = irq->idtIndex;
rtems_interrupt_enable(level); rtems_interrupt_lock_release(&rtems_idt_access_lock, &lock_context);
return 1; return 1;
} }
@@ -185,7 +195,7 @@ int i386_init_idt (rtems_raw_irq_global_settings* config)
{ {
unsigned limit; unsigned limit;
unsigned i; unsigned i;
rtems_interrupt_level level; rtems_interrupt_lock_context lock_context;
interrupt_gate_descriptor* idt_entry_tbl; interrupt_gate_descriptor* idt_entry_tbl;
i386_get_info_from_IDTR (&idt_entry_tbl, &limit); i386_get_info_from_IDTR (&idt_entry_tbl, &limit);
@@ -203,7 +213,7 @@ int i386_init_idt (rtems_raw_irq_global_settings* config)
local_settings = config; local_settings = config;
default_raw_irq_entry = config->defaultRawEntry; default_raw_irq_entry = config->defaultRawEntry;
rtems_interrupt_disable(level); rtems_interrupt_lock_acquire(&rtems_idt_access_lock, &lock_context);
create_interrupt_gate_descriptor (&default_idt_entry, default_raw_irq_entry.hdl); create_interrupt_gate_descriptor (&default_idt_entry, default_raw_irq_entry.hdl);
@@ -218,7 +228,7 @@ int i386_init_idt (rtems_raw_irq_global_settings* config)
raw_irq_table[i].off(&raw_irq_table[i]); raw_irq_table[i].off(&raw_irq_table[i]);
} }
} }
rtems_interrupt_enable(level); rtems_interrupt_lock_release(&rtems_idt_access_lock, &lock_context);
return 1; return 1;
} }

View File

@@ -23,6 +23,8 @@
#include "elcr.h" #include "elcr.h"
RTEMS_INTERRUPT_LOCK_DEFINE( static, rtems_i8259_access_lock, "rtems_i8259_access_lock" );
/* /*
* pointer to the mask representing the additionnal irq vectors * pointer to the mask representing the additionnal irq vectors
* that must be disabled when a particular entry is activated. * that must be disabled when a particular entry is activated.
@@ -130,9 +132,9 @@ static inline uint8_t BSP_i8259a_irq_in_service_reg(uint32_t ioport)
static int BSP_irq_disable_at_i8259a(const rtems_irq_number irqLine) static int BSP_irq_disable_at_i8259a(const rtems_irq_number irqLine)
{ {
unsigned short mask; unsigned short mask;
rtems_interrupt_level level; rtems_interrupt_lock_context lock_context;
rtems_interrupt_disable(level); rtems_interrupt_lock_acquire(&rtems_i8259_access_lock, &lock_context);
mask = 1 << irqLine; mask = 1 << irqLine;
i8259a_imr_cache |= mask; i8259a_imr_cache |= mask;
@@ -146,7 +148,7 @@ static int BSP_irq_disable_at_i8259a(const rtems_irq_number irqLine)
BSP_i8259a_irq_update_slave_imr(); BSP_i8259a_irq_update_slave_imr();
} }
rtems_interrupt_enable(level); rtems_interrupt_lock_release(&rtems_i8259_access_lock, &lock_context);
return 0; return 0;
} }
@@ -161,11 +163,11 @@ static int BSP_irq_disable_at_i8259a(const rtems_irq_number irqLine)
static int BSP_irq_enable_at_i8259a(const rtems_irq_number irqLine) static int BSP_irq_enable_at_i8259a(const rtems_irq_number irqLine)
{ {
unsigned short mask; unsigned short mask;
rtems_interrupt_level level; rtems_interrupt_lock_context lock_context;
uint8_t isr; uint8_t isr;
uint8_t irr; uint8_t irr;
rtems_interrupt_disable(level); rtems_interrupt_lock_acquire(&rtems_i8259_access_lock, &lock_context);
mask = 1 << irqLine; mask = 1 << irqLine;
i8259a_imr_cache &= ~mask; i8259a_imr_cache &= ~mask;
@@ -186,7 +188,7 @@ static int BSP_irq_enable_at_i8259a(const rtems_irq_number irqLine)
if (((isr ^ irr) & mask) != 0) if (((isr ^ irr) & mask) != 0)
printk("i386: isr=%x irr=%x\n", isr, irr); printk("i386: isr=%x irr=%x\n", isr, irr);
rtems_interrupt_enable(level); rtems_interrupt_lock_release(&rtems_i8259_access_lock, &lock_context);
return 0; return 0;
} /* mask_irq */ } /* mask_irq */
@@ -239,11 +241,11 @@ static rtems_irq_prio irqPrioTable[BSP_IRQ_LINES_NUMBER]={
static void compute_i8259_masks_from_prio (void) static void compute_i8259_masks_from_prio (void)
{ {
rtems_interrupt_level level; rtems_interrupt_lock_context lock_context;
unsigned int i; unsigned int i;
unsigned int j; unsigned int j;
rtems_interrupt_disable(level); rtems_interrupt_lock_acquire(&rtems_i8259_access_lock, &lock_context);
/* /*
* Always mask at least current interrupt to prevent re-entrance * Always mask at least current interrupt to prevent re-entrance
@@ -260,7 +262,7 @@ static void compute_i8259_masks_from_prio (void)
} }
} }
rtems_interrupt_enable(level); rtems_interrupt_lock_release(&rtems_i8259_access_lock, &lock_context);
} }
static inline bool bsp_interrupt_vector_is_valid(rtems_vector_number vector) static inline bool bsp_interrupt_vector_is_valid(rtems_vector_number vector)
@@ -314,6 +316,7 @@ void BSP_dispatch_isr(int vector);
void BSP_dispatch_isr(int vector) void BSP_dispatch_isr(int vector)
{ {
rtems_interrupt_lock_context lock_context;
rtems_i8259_masks in_progress_save = 0; rtems_i8259_masks in_progress_save = 0;
if (vector < BSP_IRQ_VECTOR_NUMBER) { if (vector < BSP_IRQ_VECTOR_NUMBER) {
@@ -321,6 +324,9 @@ void BSP_dispatch_isr(int vector)
* Hardware? * Hardware?
*/ */
if (vector <= BSP_IRQ_MAX_ON_i8259A) { if (vector <= BSP_IRQ_MAX_ON_i8259A) {
rtems_interrupt_lock_acquire_isr(&rtems_i8259_access_lock, &lock_context);
/* /*
* See if this is a spurious interrupt. * See if this is a spurious interrupt.
*/ */
@@ -335,6 +341,7 @@ void BSP_dispatch_isr(int vector)
uint8_t isr = BSP_i8259a_irq_in_service_reg(PIC_MASTER_COMMAND_IO_PORT); uint8_t isr = BSP_i8259a_irq_in_service_reg(PIC_MASTER_COMMAND_IO_PORT);
if ((isr & (1 << 7)) == 0) { if ((isr & (1 << 7)) == 0) {
++spurious_count; ++spurious_count;
rtems_interrupt_lock_release_isr(&rtems_i8259_access_lock, &lock_context);
return; return;
} }
} }
@@ -355,6 +362,8 @@ void BSP_dispatch_isr(int vector)
* Do not use auto-EOI as some slave PIC do not work correctly. * Do not use auto-EOI as some slave PIC do not work correctly.
*/ */
BSP_irq_ack_at_i8259a(vector); BSP_irq_ack_at_i8259a(vector);
rtems_interrupt_lock_release_isr(&rtems_i8259_access_lock, &lock_context);
} }
/* /*
@@ -378,6 +387,9 @@ void BSP_dispatch_isr(int vector)
RTEMS_COMPILER_MEMORY_BARRIER(); RTEMS_COMPILER_MEMORY_BARRIER();
if (vector <= BSP_IRQ_MAX_ON_i8259A) { if (vector <= BSP_IRQ_MAX_ON_i8259A) {
rtems_interrupt_lock_acquire_isr(&rtems_i8259_access_lock, &lock_context);
/* /*
* Put the mask back but keep this vector masked if the trigger type is * Put the mask back but keep this vector masked if the trigger type is
* level. The driver or a thread level interrupt server needs to enable it * level. The driver or a thread level interrupt server needs to enable it
@@ -388,6 +400,8 @@ void BSP_dispatch_isr(int vector)
BSP_i8259a_irq_update_master_imr(); BSP_i8259a_irq_update_master_imr();
BSP_i8259a_irq_update_slave_imr(); BSP_i8259a_irq_update_slave_imr();
} }
rtems_interrupt_lock_release_isr(&rtems_i8259_access_lock, &lock_context);
} }
} }
} }

View File

@@ -124,7 +124,12 @@ void rtems_irq_mngt_init(void)
while(1); while(1);
} }
rtems_interrupt_disable(level); /*
* The interrupt management can be initialized only once
* during system bootup and that should happen on boot
* CPU so there is no need to synchronize with others CPUs.
*/
rtems_interrupt_local_disable(level);
/* /*
* Init the complete IDT vector table with defaultRawIrq value * Init the complete IDT vector table with defaultRawIrq value