From 6b54dcbbef6a003ae4c5fb9ae77f2f261f82dbf9 Mon Sep 17 00:00:00 2001 From: Pavel Pisa Date: Wed, 12 Oct 2016 09:40:41 +0200 Subject: bsps/i386: replace global interrupt disable by SMP build supporting locking. --- c/src/lib/libbsp/i386/pc386/clock/ckinit.c | 19 ++++++--- c/src/lib/libbsp/i386/pc386/console/inch.c | 10 +++-- c/src/lib/libbsp/i386/pc386/console/keyboard.c | 55 ++++++++++++-------------- c/src/lib/libbsp/i386/pc386/console/vt.c | 13 +++--- c/src/lib/libbsp/i386/pc386/include/bsp.h | 5 +++ c/src/lib/libbsp/i386/pc386/timer/timer.c | 45 ++++++++++++++++++--- c/src/lib/libbsp/i386/shared/irq/idt.c | 34 ++++++++++------ c/src/lib/libbsp/i386/shared/irq/irq.c | 32 ++++++++++----- c/src/lib/libbsp/i386/shared/irq/irq_init.c | 7 +++- 9 files changed, 148 insertions(+), 72 deletions(-) diff --git a/c/src/lib/libbsp/i386/pc386/clock/ckinit.c b/c/src/lib/libbsp/i386/pc386/clock/ckinit.c index 67f4bf728e..e7fe50ae4e 100644 --- a/c/src/lib/libbsp/i386/pc386/clock/ckinit.c +++ b/c/src/lib/libbsp/i386/pc386/clock/ckinit.c @@ -84,15 +84,18 @@ static uint32_t pc386_get_timecount_i8254(struct timecounter *tc) { uint32_t irqs; uint8_t lsb, msb; - rtems_interrupt_level level; + rtems_interrupt_lock_context lock_context; /* * 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); 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); } @@ -141,6 +144,7 @@ static void calibrate_tsc(void) static void clockOn(void) { + rtems_interrupt_lock_context lock_context; pc386_isrs_per_tick = 1; 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); - bsp_interrupt_vector_enable( BSP_PERIODIC_TIMER - BSP_IRQ_VECTOR_BASE ); - #if 0 printk( "configured usecs per tick=%d \n", rtems_configuration_get_microseconds_per_tick() ); @@ -160,9 +162,13 @@ static void clockOn(void) printk( "final timer counts=%d\n", pc386_clock_click_count ); #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_CNTR0, pc386_clock_click_count >> 0 & 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 @@ -174,10 +180,13 @@ static void clockOn(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 */ outport_byte(TIMER_MODE, TIMER_SEL0 | TIMER_16BIT | TIMER_RATEGEN); outport_byte(TIMER_CNTR0, 0); outport_byte(TIMER_CNTR0, 0); + rtems_interrupt_lock_release(&rtems_i386_i8254_access_lock, &lock_context); } /* Clock_exit */ bool Clock_isr_enabled = false; diff --git a/c/src/lib/libbsp/i386/pc386/console/inch.c b/c/src/lib/libbsp/i386/pc386/console/inch.c index 047269e4f0..f5d5079236 100644 --- a/c/src/lib/libbsp/i386/pc386/console/inch.c +++ b/c/src/lib/libbsp/i386/pc386/console/inch.c @@ -260,13 +260,17 @@ int BSP_wait_polled_input(void) int rtems_kbpoll( void ) { 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; - rtems_interrupt_enable(level); + RTEMS_COMPILER_MEMORY_BARRIER(); return rc; } diff --git a/c/src/lib/libbsp/i386/pc386/console/keyboard.c b/c/src/lib/libbsp/i386/pc386/console/keyboard.c index 3a33c54acc..0c8991b829 100644 --- a/c/src/lib/libbsp/i386/pc386/console/keyboard.c +++ b/c/src/lib/libbsp/i386/pc386/console/keyboard.c @@ -9,6 +9,7 @@ #include #include #include +#include #define SIZE(x) (sizeof(x)/sizeof((x)[0])) @@ -28,59 +29,53 @@ #define KBD_DEFLOCK 0 #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; - rtems_interrupt_level level; addr += nr >> 5; - mask = 1 << (nr & 0x1f); - rtems_interrupt_disable(level); - retval = (mask & *addr) != 0; - *addr |= mask; - rtems_interrupt_enable(level); + mask = 1UL << (nr & 0x1f); + + retval = (atomic_fetch_or(addr, mask) & mask) != 0; + 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; - rtems_interrupt_level level; addr += nr >> 5; - mask = 1 << (nr & 0x1f); - rtems_interrupt_disable(level); - retval = (mask & *addr) != 0; - *addr &= ~mask; - rtems_interrupt_enable(level); + mask = 1UL << (nr & 0x1f); + + retval = (atomic_fetch_and(addr, ~mask) & mask) != 0; + 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; 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 * in this module: prev_scancode, shift_state, diacr, npadch, dead_key_next. * (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.. */ static unsigned char k_down[NR_SHIFT] = {0, }; /* 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; /* @@ -243,10 +238,10 @@ void handle_scancode(unsigned char scancode, int down) if (up_flag) { 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); } 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 */ if (keycode == SYSRQ_KEY) { @@ -695,10 +690,10 @@ void compute_shiftstate(void) k_down[i] = 0; for(i=0; i < SIZE(key_down); i++) - if(key_down[i]) { /* skip this word if not a single bit on */ - k = i*BITS_PER_LONG; - for(j=0; j #include +#include #include #include #include @@ -69,21 +70,21 @@ static void _kd_mksound(unsigned int hz, unsigned int ticks) { unsigned int count = 0; - rtems_interrupt_level level; + rtems_interrupt_lock_context lock_context; if (hz > 20 && hz < 32767) count = 1193180 / hz; - rtems_interrupt_disable(level); + rtems_interrupt_lock_acquire(&rtems_i386_i8254_access_lock, &lock_context); /* del_timer(&sound_timer); */ if (count) { /* enable counter 2 */ outb_p(inb_p(0x61)|3, 0x61); /* set command for counter 2, 2 byte write */ - outb_p(0xB6, 0x43); + outb_p(0xB6, TIMER_MODE); /* select desired HZ */ - outb_p(count & 0xff, 0x42); - outb((count >> 8) & 0xff, 0x42); + outb_p(count & 0xff, TIMER_CNTR2); + outb((count >> 8) & 0xff, TIMER_CNTR2); /* if (ticks) { @@ -94,7 +95,7 @@ _kd_mksound(unsigned int hz, unsigned int ticks) } else kd_nosound(0); - rtems_interrupt_enable(level); + rtems_interrupt_lock_release(&rtems_i386_i8254_access_lock, &lock_context); return; } diff --git a/c/src/lib/libbsp/i386/pc386/include/bsp.h b/c/src/lib/libbsp/i386/pc386/include/bsp.h index cdfbce619e..4f42fc4c95 100644 --- a/c/src/lib/libbsp/i386/pc386/include/bsp.h +++ b/c/src/lib/libbsp/i386/pc386/include/bsp.h @@ -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 */ +#if defined( RTEMS_SMP ) + extern ISR_lock_Control rtems_i386_i8254_access_lock; +#endif + + /*-------------------------------------------------------------------------+ | Console Defines | WARNING: These Values MUST match the order in diff --git a/c/src/lib/libbsp/i386/pc386/timer/timer.c b/c/src/lib/libbsp/i386/pc386/timer/timer.c index 0e4d6a9c37..5bef139d38 100644 --- a/c/src/lib/libbsp/i386/pc386/timer/timer.c +++ b/c/src/lib/libbsp/i386/pc386/timer/timer.c @@ -44,6 +44,9 @@ #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 */ @@ -115,23 +118,35 @@ static uint32_t tsc_read_timer(void) */ static void timerOff(const rtems_raw_irq_connect_data* used) { + rtems_interrupt_lock_context lock_context; /* * 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 */ - outport_byte(TIMER_MODE, TIMER_SEL0|TIMER_16BIT|TIMER_RATEGEN); - outport_byte(TIMER_CNTR0, 0); - outport_byte(TIMER_CNTR0, 0); + outport_byte(TIMER_MODE, TIMER_SEL0|TIMER_16BIT|TIMER_RATEGEN); + 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) { + 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 */ 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) >> 8 & 0xff); + rtems_interrupt_lock_release(&rtems_i386_i8254_access_lock, &lock_context); + /* * enable interrrupt at i8259 level */ @@ -199,10 +214,14 @@ static uint32_t i386_read_timer(void) { register uint32_t total, clicks; 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); inport_byte(TIMER_CNTR0, lsb); inport_byte(TIMER_CNTR0, msb); + rtems_interrupt_lock_release(&rtems_i386_i8254_access_lock, &lock_context); + clicks = (msb << 8) | lsb; 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 ) { + rtems_interrupt_lock_context lock_context; + rtems_interrupt_lock_acquire(&rtems_i386_i8254_access_lock, &lock_context); lastLoadedValue = loadedValue; outport_byte(TIMER_MODE, TIMER_SEL0|TIMER_16BIT|TIMER_SQWAVE); outport_byte(TIMER_CNTR0, loadedValue & 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 char status; unsigned int count; + rtems_interrupt_lock_context lock_context; + rtems_interrupt_lock_acquire(&rtems_i386_i8254_access_lock, &lock_context); outport_byte( TIMER_MODE, @@ -298,6 +322,9 @@ static unsigned int readTimer0(void) inport_byte(TIMER_CNTR0, status); inport_byte(TIMER_CNTR0, lsb); inport_byte(TIMER_CNTR0, msb); + + rtems_interrupt_lock_release(&rtems_i386_i8254_access_lock, &lock_context); + count = ( msb << 8 ) | lsb ; if (status & RB_OUTPUT ) count += lastLoadedValue; @@ -337,7 +364,13 @@ Calibrate_loop_1ms(void) rtems_interrupt_level level; 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: if ( ++retries >= 5 ) { @@ -506,7 +539,7 @@ retry: #ifdef DEBUG_CALIBRATE printk("slowLoop1ms = %u, fastLoop1ms = %u\n", slowLoop1ms, fastLoop1ms); #endif - rtems_interrupt_enable(level); + rtems_interrupt_local_enable(level); } diff --git a/c/src/lib/libbsp/i386/shared/irq/idt.c b/c/src/lib/libbsp/i386/shared/irq/idt.c index ee6f8e02ab..ac79a97004 100644 --- a/c/src/lib/libbsp/i386/shared/irq/idt.c +++ b/c/src/lib/libbsp/i386/shared/irq/idt.c @@ -19,6 +19,16 @@ #include #include +/* + * 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 default_raw_irq_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; unsigned limit; - rtems_interrupt_level level; + rtems_interrupt_lock_context lock_context; 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; } - rtems_interrupt_disable(level); + rtems_interrupt_lock_acquire(&rtems_idt_access_lock, &lock_context); raw_irq_table [irq->idtIndex] = *irq; create_interrupt_gate_descriptor (&idt_entry_tbl[irq->idtIndex], irq->hdl); if (irq->on) irq->on(irq); - rtems_interrupt_enable(level); + rtems_interrupt_lock_release(&rtems_idt_access_lock, &lock_context); return 1; } @@ -99,7 +109,7 @@ void _CPU_ISR_install_vector (uint32_t vector, interrupt_gate_descriptor* idt_entry_tbl; unsigned limit; interrupt_gate_descriptor new; - rtems_interrupt_level level; + rtems_interrupt_lock_context lock_context; i386_get_info_from_IDTR (&idt_entry_tbl, &limit); @@ -109,14 +119,14 @@ void _CPU_ISR_install_vector (uint32_t vector, if (vector >= limit) { 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 | (idt_entry_tbl[vector].high_offsets_bits << 16); create_interrupt_gate_descriptor(&new, hdl); 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) @@ -143,7 +153,7 @@ int i386_delete_idt_entry (const rtems_raw_irq_connect_data* irq) { interrupt_gate_descriptor* idt_entry_tbl; unsigned limit; - rtems_interrupt_level level; + rtems_interrupt_lock_context lock_context; 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){ return 0; } - rtems_interrupt_disable(level); + rtems_interrupt_lock_acquire(&rtems_idt_access_lock, &lock_context); 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].idtIndex = irq->idtIndex; - rtems_interrupt_enable(level); + rtems_interrupt_lock_release(&rtems_idt_access_lock, &lock_context); return 1; } @@ -185,7 +195,7 @@ int i386_init_idt (rtems_raw_irq_global_settings* config) { unsigned limit; unsigned i; - rtems_interrupt_level level; + rtems_interrupt_lock_context lock_context; interrupt_gate_descriptor* idt_entry_tbl; 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; 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); @@ -218,7 +228,7 @@ int i386_init_idt (rtems_raw_irq_global_settings* config) 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; } diff --git a/c/src/lib/libbsp/i386/shared/irq/irq.c b/c/src/lib/libbsp/i386/shared/irq/irq.c index 887a1204df..f4ffd8c0e4 100644 --- a/c/src/lib/libbsp/i386/shared/irq/irq.c +++ b/c/src/lib/libbsp/i386/shared/irq/irq.c @@ -23,6 +23,8 @@ #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 * 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) { 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; 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(); } - rtems_interrupt_enable(level); + rtems_interrupt_lock_release(&rtems_i8259_access_lock, &lock_context); 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) { unsigned short mask; - rtems_interrupt_level level; + rtems_interrupt_lock_context lock_context; uint8_t isr; uint8_t irr; - rtems_interrupt_disable(level); + rtems_interrupt_lock_acquire(&rtems_i8259_access_lock, &lock_context); mask = 1 << irqLine; 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) 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; } /* mask_irq */ @@ -239,11 +241,11 @@ static rtems_irq_prio irqPrioTable[BSP_IRQ_LINES_NUMBER]={ static void compute_i8259_masks_from_prio (void) { - rtems_interrupt_level level; + rtems_interrupt_lock_context lock_context; unsigned int i; 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 @@ -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) @@ -314,6 +316,7 @@ 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; if (vector < BSP_IRQ_VECTOR_NUMBER) { @@ -321,6 +324,9 @@ void BSP_dispatch_isr(int vector) * Hardware? */ 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. */ @@ -335,6 +341,7 @@ void BSP_dispatch_isr(int vector) uint8_t isr = BSP_i8259a_irq_in_service_reg(PIC_MASTER_COMMAND_IO_PORT); if ((isr & (1 << 7)) == 0) { ++spurious_count; + rtems_interrupt_lock_release_isr(&rtems_i8259_access_lock, &lock_context); return; } } @@ -355,6 +362,8 @@ void BSP_dispatch_isr(int vector) * Do not use auto-EOI as some slave PIC do not work correctly. */ 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(); 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 * 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_slave_imr(); } + + rtems_interrupt_lock_release_isr(&rtems_i8259_access_lock, &lock_context); } } } diff --git a/c/src/lib/libbsp/i386/shared/irq/irq_init.c b/c/src/lib/libbsp/i386/shared/irq/irq_init.c index c401f29b71..fdf4801a5a 100644 --- a/c/src/lib/libbsp/i386/shared/irq/irq_init.c +++ b/c/src/lib/libbsp/i386/shared/irq/irq_init.c @@ -124,7 +124,12 @@ void rtems_irq_mngt_init(void) 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 -- cgit v1.2.3