bsps/leon3: Size the interrupt map per chip

The BSP assumed 64 bus lines for every chip with an interrupt map.  The
GR740 has 32 bus lines in eight map registers.  The BSP read the
undefined offsets 0x320 to 0x33C, and vector 32 passed as valid, so
ts-validation-intr failed on the GR740.  The GR765 has 64 bus lines.

A map field is eight bits wide.  A field value above 31 indexed past
the dispatch table of 32 entries and made the bit shifts undefined.

Replace the option LEON3_IRQAMP_IRQMAP by LEON3_IRQMAP_BUS_LINE_COUNT,
which is 32 for the GR740 and 64 for the GR765.  With an interrupt map,
an interrupt vector is a bus line.  The vector count is then the bus
line count, and the dispatch table keeps one entry for each controller
line.  Bound each map entry by the dispatch table, so that a hardware
fault cannot index past it.

The description of LEON3_IRQAMP_EXTENDED_INTERRUPT named an interrupt
line and did not say which kind.  Call it a controller line, the term
which the other options use.

The extended interrupt raise test took a vector for its controller
line.  It raised 1U << vector for vectors up to the count, which is
undefined from 32 on.  Its specification item did not exist.
Regenerate the test from the new item.  It raises the mapped controller
line of each vector which maps to an extended controller line.  It
checks that it exercised each extended controller line.

Close #5786.

Assisted-by: Claude:claude-opus-5-5 claude-code
Signed-off-by: Sebastian Huber <sebastian.huber@embedded-brains.de>
This commit is contained in:
Sebastian Huber
2026-09-30 09:53:11 -05:00
committed by Kinsey Moore
parent 3840a7bc54
commit c9206587ac
9 changed files with 249 additions and 136 deletions
+13 -5
View File
@@ -42,10 +42,19 @@
#define BSP_INTERRUPT_VECTOR_MAX_STD 15 /* Standard IRQ controller */
#define BSP_INTERRUPT_VECTOR_MAX_EXT 31 /* Extended IRQ controller */
#define BSP_INTERRUPT_VECTOR_MAX_MAP \
63 /* Extended IRQ controller with mapping registers */
#if LEON3_IRQMAP_BUS_LINE_COUNT != 0
/*
* A bus line is an interrupt line of the system interrupt bus. A controller
* line is an interrupt line of the IRQ(A)MP. With an interrupt map, an
* interrupt vector is a bus line. The dispatch table has one entry for each
* controller line.
*/
#define BSP_INTERRUPT_VECTOR_COUNT LEON3_IRQMAP_BUS_LINE_COUNT
#define BSP_INTERRUPT_DISPATCH_TABLE_SIZE ( BSP_INTERRUPT_VECTOR_MAX_EXT + 1 )
#else
#define BSP_INTERRUPT_VECTOR_COUNT ( BSP_INTERRUPT_VECTOR_MAX_EXT + 1 )
#endif
/* The check is different depending on IRQ controller, runtime detected */
#define BSP_INTERRUPT_CUSTOM_VALID_VECTOR
@@ -97,9 +106,8 @@ rtems_status_code leon3_irqmap_get(
rtems_vector_number *controller_line
);
#ifdef LEON3_IRQAMP_IRQMAP
extern rtems_vector_number
LEON3_IrqCtrl_Mapping[ BSP_INTERRUPT_VECTOR_MAX_MAP + 1 ];
#if LEON3_IRQMAP_BUS_LINE_COUNT != 0
extern uint8_t LEON3_IrqCtrl_Mapping[ BSP_INTERRUPT_VECTOR_COUNT ];
#define bsp_interrupt_vector_modify( v ) LEON3_IrqCtrl_Mapping[ ( v ) ]
#endif
+1 -1
View File
@@ -159,7 +159,7 @@ static inline rtems_vector_number leon3_irqmap_get_unchecked(
rtems_vector_number bus_line
)
{
#ifdef LEON3_IRQAMP_IRQMAP
#if LEON3_IRQMAP_BUS_LINE_COUNT != 0
return LEON3_IrqCtrl_Mapping[ bus_line ];
#else
return bus_line;
+1 -1
View File
@@ -114,7 +114,7 @@ void _CPU_SMP_Send_interrupt( uint32_t target_processor_index )
/* send interrupt to destination CPU */
grlib_store_32(
&LEON3_IrqCtrl_Regs->piforce[ target_processor_index ],
#ifdef LEON3_IRQAMP_IRQMAP
#if LEON3_IRQMAP_BUS_LINE_COUNT != 0
1U << leon3_irqmap_get_unchecked( LEON3_mp_irq )
#else
1U << LEON3_mp_irq
+37 -29
View File
@@ -49,9 +49,20 @@
uint32_t LEON3_IrqCtrl_EIrq;
#endif
#ifdef LEON3_IRQAMP_IRQMAP
#if LEON3_IRQMAP_BUS_LINE_COUNT != 0
/* Mapping from bus interrupt lines to IRQ(A)MP interrupt lines */
rtems_vector_number LEON3_IrqCtrl_Mapping[ BSP_INTERRUPT_VECTOR_MAX_MAP + 1 ];
uint8_t LEON3_IrqCtrl_Mapping[ BSP_INTERRUPT_VECTOR_COUNT ];
/*
* A map field is eight bits wide. A field value outside the dispatch table is
* a hardware fault. The mask keeps the controller line inside the dispatch
* table also in this case.
*/
static uint8_t leon3_irqmap_controller_line( uint32_t field )
{
return (uint8_t) ( field & ( BSP_INTERRUPT_DISPATCH_TABLE_SIZE - 1 ) );
}
#endif
rtems_status_code leon3_irqmap_get(
@@ -63,11 +74,7 @@ rtems_status_code leon3_irqmap_get(
return RTEMS_INVALID_ADDRESS;
}
#ifdef LEON3_IRQAMP_IRQMAP
if ( bus_line > BSP_INTERRUPT_VECTOR_MAX_MAP ) {
#else
if ( bus_line >= BSP_INTERRUPT_VECTOR_COUNT ) {
#endif
*controller_line = UINT32_MAX;
return RTEMS_INVALID_NUMBER;
}
@@ -91,25 +98,25 @@ void leon3_ext_irq_init( irqamp *regs )
grlib_load_32( &regs->mpstat )
);
#endif
#ifdef LEON3_IRQAMP_IRQMAP
#if LEON3_IRQMAP_BUS_LINE_COUNT != 0
for (
rtems_vector_number bus_line = 0; bus_line <= BSP_INTERRUPT_VECTOR_MAX_MAP;
rtems_vector_number bus_line = 0; bus_line < BSP_INTERRUPT_VECTOR_COUNT;
bus_line += 4
) {
uint32_t n = bus_line / 4;
uint32_t irqmap_n = grlib_load_32( &LEON3_IrqCtrl_Regs->irqmap[ n ] );
LEON3_IrqCtrl_Mapping[ bus_line + 0 ] = IRQAMP_IRQMAP_IRQMAP_4_N_0_GET(
irqmap_n
LEON3_IrqCtrl_Mapping[ bus_line + 0 ] = leon3_irqmap_controller_line(
IRQAMP_IRQMAP_IRQMAP_4_N_0_GET( irqmap_n )
);
LEON3_IrqCtrl_Mapping[ bus_line + 1 ] = IRQAMP_IRQMAP_IRQMAP_4_N_1_GET(
irqmap_n
LEON3_IrqCtrl_Mapping[ bus_line + 1 ] = leon3_irqmap_controller_line(
IRQAMP_IRQMAP_IRQMAP_4_N_1_GET( irqmap_n )
);
LEON3_IrqCtrl_Mapping[ bus_line + 2 ] = IRQAMP_IRQMAP_IRQMAP_4_N_2_GET(
irqmap_n
LEON3_IrqCtrl_Mapping[ bus_line + 2 ] = leon3_irqmap_controller_line(
IRQAMP_IRQMAP_IRQMAP_4_N_2_GET( irqmap_n )
);
LEON3_IrqCtrl_Mapping[ bus_line + 3 ] = IRQAMP_IRQMAP_IRQMAP_4_N_3_GET(
irqmap_n
LEON3_IrqCtrl_Mapping[ bus_line + 3 ] = leon3_irqmap_controller_line(
IRQAMP_IRQMAP_IRQMAP_4_N_3_GET( irqmap_n )
);
}
#endif
@@ -121,8 +128,9 @@ bool bsp_interrupt_is_valid_vector( rtems_vector_number vector )
return false;
}
#if defined( LEON3_IRQAMP_IRQMAP )
return vector <= BSP_INTERRUPT_VECTOR_MAX_MAP;
#if LEON3_IRQMAP_BUS_LINE_COUNT != 0
return vector < BSP_INTERRUPT_VECTOR_COUNT &&
leon3_irqmap_get_unchecked( vector ) != 0;
#elif defined( LEON3_IRQAMP_EXTENDED_INTERRUPT )
return vector <= BSP_INTERRUPT_VECTOR_MAX_EXT;
#else
@@ -184,7 +192,7 @@ rtems_status_code bsp_interrupt_get_attributes(
bool is_standard_interrupt;
bool is_maskable;
#ifdef LEON3_IRQAMP_IRQMAP
#if LEON3_IRQMAP_BUS_LINE_COUNT != 0
vector = leon3_irqmap_get_unchecked( vector );
#endif
@@ -216,7 +224,7 @@ rtems_status_code bsp_interrupt_is_pending(
bsp_interrupt_assert( bsp_interrupt_is_valid_vector( vector ) );
bsp_interrupt_assert( pending != NULL );
#ifdef LEON3_IRQAMP_IRQMAP
#if LEON3_IRQMAP_BUS_LINE_COUNT != 0
vector = leon3_irqmap_get_unchecked( vector );
#endif
@@ -242,7 +250,7 @@ rtems_status_code bsp_interrupt_raise( rtems_vector_number vector )
bsp_interrupt_assert( bsp_interrupt_is_valid_vector( vector ) );
#ifdef LEON3_IRQAMP_IRQMAP
#if LEON3_IRQMAP_BUS_LINE_COUNT != 0
vector = leon3_irqmap_get_unchecked( vector );
#endif
@@ -272,7 +280,7 @@ rtems_status_code bsp_interrupt_raise_on(
bsp_interrupt_assert( bsp_interrupt_is_valid_vector( vector ) );
bsp_interrupt_assert( cpu_index < rtems_scheduler_get_processor_maximum() );
#ifdef LEON3_IRQAMP_IRQMAP
#if LEON3_IRQMAP_BUS_LINE_COUNT != 0
vector = leon3_irqmap_get_unchecked( vector );
#endif
@@ -293,7 +301,7 @@ rtems_status_code bsp_interrupt_clear( rtems_vector_number vector )
bsp_interrupt_assert( bsp_interrupt_is_valid_vector( vector ) );
#ifdef LEON3_IRQAMP_IRQMAP
#if LEON3_IRQMAP_BUS_LINE_COUNT != 0
vector = leon3_irqmap_get_unchecked( vector );
#endif
@@ -323,7 +331,7 @@ rtems_status_code bsp_interrupt_vector_is_enabled(
bsp_interrupt_assert( bsp_interrupt_is_valid_vector( vector ) );
#ifdef LEON3_IRQAMP_IRQMAP
#if LEON3_IRQMAP_BUS_LINE_COUNT != 0
vector = leon3_irqmap_get_unchecked( vector );
#endif
@@ -345,7 +353,7 @@ static void leon3_interrupt_vector_enable( rtems_vector_number vector )
uint32_t brdcst;
irqamp *regs;
#ifdef LEON3_IRQAMP_IRQMAP
#if LEON3_IRQMAP_BUS_LINE_COUNT != 0
vector = leon3_irqmap_get_unchecked( vector );
#endif
@@ -399,7 +407,7 @@ rtems_status_code bsp_interrupt_vector_enable( rtems_vector_number vector )
bsp_interrupt_assert( bsp_interrupt_is_valid_vector( vector ) );
#ifdef LEON3_IRQAMP_IRQMAP
#if LEON3_IRQMAP_BUS_LINE_COUNT != 0
vector = leon3_irqmap_get_unchecked( vector );
#endif
@@ -435,7 +443,7 @@ rtems_status_code bsp_interrupt_vector_disable( rtems_vector_number vector )
bsp_interrupt_assert( bsp_interrupt_is_valid_vector( vector ) );
#ifdef LEON3_IRQAMP_IRQMAP
#if LEON3_IRQMAP_BUS_LINE_COUNT != 0
vector = leon3_irqmap_get_unchecked( vector );
#endif
@@ -508,7 +516,7 @@ rtems_status_code bsp_interrupt_set_affinity(
uint32_t bit;
irqamp *regs;
#ifdef LEON3_IRQAMP_IRQMAP
#if LEON3_IRQMAP_BUS_LINE_COUNT != 0
rtems_vector_number irq_vector;
if ( leon3_irqmap_get( vector, &irq_vector ) != RTEMS_SUCCESSFUL ) {
@@ -549,7 +557,7 @@ rtems_status_code bsp_interrupt_get_affinity(
Processor_mask *affinity
)
{
#ifdef LEON3_IRQAMP_IRQMAP
#if LEON3_IRQMAP_BUS_LINE_COUNT != 0
rtems_vector_number irq_vector;
if ( leon3_irqmap_get( vector, &irq_vector ) != RTEMS_SUCCESSFUL ) {
+1 -1
View File
@@ -47,7 +47,7 @@ links:
- role: build-dependency
uid: optirqampextirq
- role: build-dependency
uid: optirqampirqmap
uid: optirqmapbuslinecount
- role: build-dependency
uid: optirqampts
- role: build-dependency
@@ -17,5 +17,6 @@ format: '{}'
links: []
name: LEON3_IRQAMP_EXTENDED_INTERRUPT
description: |
This option specifies the interrupt line of the IRQ(A)MP extended interrupt.
This option specifies the controller line of the IRQ(A)MP extended
interrupt.
type: build
@@ -1,20 +0,0 @@
SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause
copyrights:
- Copyright (C) 2026 Frontgrade Gaisler
actions:
- get-boolean: null
- define-condition: null
build-type: option
default:
- enabled-by:
- sparc/gr740
- sparc/gr765
value: true
- enabled-by: true
value: false
enabled-by: true
links: []
name: LEON3_IRQAMP_IRQMAP
description: |
This option specifies if the IRQ(A)MP interrupt (re-)map registers are available.
type: build
@@ -0,0 +1,28 @@
SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause
actions:
- get-integer: null
- assert-in-set:
- 0
- 32
- 64
- format-and-define: null
build-type: option
copyrights:
- Copyright (C) 2026 Frontgrade Gaisler
- Copyright (C) 2026 embedded brains GmbH & Co. KG
default:
- enabled-by: sparc/gr740
value: 32
- enabled-by: sparc/gr765
value: 64
- enabled-by: true
value: 0
description: |
This option defines the count of bus lines of the IRQ(A)MP interrupt map.
The GR740 has 32 bus lines, and the GR765 has 64. A value of zero specifies
that the BSP uses no interrupt map.
enabled-by: true
format: '{}'
links: []
name: LEON3_IRQMAP_BUS_LINE_COUNT
type: build
File diff suppressed because it is too large Load Diff