diff options
author | Pavel Pisa <pisa@cmp.felk.cvut.cz> | 2016-10-12 09:40:41 +0200 |
---|---|---|
committer | Pavel Pisa <pisa@cmp.felk.cvut.cz> | 2016-10-17 09:41:58 +0200 |
commit | 6b54dcbbef6a003ae4c5fb9ae77f2f261f82dbf9 (patch) | |
tree | 944e6955408a0b4cfe093beabab1fb67a2d91efe /c/src/lib/libbsp/i386/shared/irq | |
parent | bsp/atsamv: Fix typo (diff) | |
download | rtems-6b54dcbbef6a003ae4c5fb9ae77f2f261f82dbf9.tar.bz2 |
bsps/i386: replace global interrupt disable by SMP build supporting locking.
Diffstat (limited to 'c/src/lib/libbsp/i386/shared/irq')
-rw-r--r-- | c/src/lib/libbsp/i386/shared/irq/idt.c | 34 | ||||
-rw-r--r-- | c/src/lib/libbsp/i386/shared/irq/irq.c | 32 | ||||
-rw-r--r-- | c/src/lib/libbsp/i386/shared/irq/irq_init.c | 7 |
3 files changed, 51 insertions, 22 deletions
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 <rtems/score/cpu.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 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 |