summaryrefslogtreecommitdiffstats
path: root/c/src/lib/libbsp/i386/shared
diff options
context:
space:
mode:
Diffstat (limited to 'c/src/lib/libbsp/i386/shared')
-rw-r--r--c/src/lib/libbsp/i386/shared/irq/idt.c34
-rw-r--r--c/src/lib/libbsp/i386/shared/irq/irq.c32
-rw-r--r--c/src/lib/libbsp/i386/shared/irq/irq_init.c7
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