From fe6ce5ac9c501f94b62f402f92c5d230d05fc6a8 Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Mon, 28 Jun 2021 14:53:06 +0200 Subject: bsps/irq: Implement new directives for GICv2/3 Update #3269. --- bsps/aarch64/a53/include/bsp/irq.h | 2 +- bsps/include/dev/irq/arm-gic-irq.h | 3 + bsps/shared/dev/irq/arm-gicv2.c | 87 +++++++++++++++++++++---- bsps/shared/dev/irq/arm-gicv3.c | 129 ++++++++++++++++++++++++++++++++----- 4 files changed, 189 insertions(+), 32 deletions(-) diff --git a/bsps/aarch64/a53/include/bsp/irq.h b/bsps/aarch64/a53/include/bsp/irq.h index b797408ca5..e0cc6a6026 100644 --- a/bsps/aarch64/a53/include/bsp/irq.h +++ b/bsps/aarch64/a53/include/bsp/irq.h @@ -48,7 +48,7 @@ extern "C" { #endif /* __cplusplus */ -#define BSP_INTERRUPT_VECTOR_COUNT 1024 +#define BSP_INTERRUPT_VECTOR_COUNT 256 /* Interrupts vectors */ #define BSP_TIMER_VIRT_PPI 27 diff --git a/bsps/include/dev/irq/arm-gic-irq.h b/bsps/include/dev/irq/arm-gic-irq.h index 68e0247fd8..398fd8bceb 100644 --- a/bsps/include/dev/irq/arm-gic-irq.h +++ b/bsps/include/dev/irq/arm-gic-irq.h @@ -46,6 +46,9 @@ extern "C" { #define ARM_GIC_IRQ_SGI_13 13 #define ARM_GIC_IRQ_SGI_14 14 #define ARM_GIC_IRQ_SGI_15 15 +#define ARM_GIC_IRQ_SGI_LAST 15 + +#define ARM_GIC_IRQ_PPI_LAST 31 #define ARM_GIC_DIST ((volatile gic_dist *) BSP_ARM_GIC_DIST_BASE) diff --git a/bsps/shared/dev/irq/arm-gicv2.c b/bsps/shared/dev/irq/arm-gicv2.c index 8372d0f191..eaae6124e8 100644 --- a/bsps/shared/dev/irq/arm-gicv2.c +++ b/bsps/shared/dev/irq/arm-gicv2.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2019 embedded brains GmbH. All rights reserved. + * Copyright (c) 2013, 2021 embedded brains GmbH. All rights reserved. * * embedded brains GmbH * Dornierstr. 4 @@ -69,6 +69,32 @@ rtems_status_code bsp_interrupt_get_attributes( rtems_interrupt_attributes *attributes ) { + attributes->is_maskable = true; + attributes->maybe_enable = true; + attributes->maybe_disable = true; + attributes->can_raise = true; + + if ( vector <= ARM_GIC_IRQ_SGI_LAST ) { + /* + * It is implementation-defined whether implemented SGIs are permanently + * enabled, or can be enabled and disabled by writes to GICD_ISENABLER0 and + * GICD_ICENABLER0. + */ + attributes->can_raise_on = true; + attributes->cleared_by_acknowledge = true; + attributes->trigger_signal = RTEMS_INTERRUPT_NO_SIGNAL; + } else { + attributes->can_disable = true; + attributes->can_clear = true; + attributes->trigger_signal = RTEMS_INTERRUPT_UNSPECIFIED_SIGNAL; + + if ( vector > ARM_GIC_IRQ_PPI_LAST ) { + /* SPI */ + attributes->can_get_affinity = true; + attributes->can_set_affinity = true; + } + } + return RTEMS_SUCCESSFUL; } @@ -77,16 +103,25 @@ rtems_status_code bsp_interrupt_is_pending( bool *pending ) { - bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); - bsp_interrupt_assert(pending != NULL); - *pending = false; - return RTEMS_UNSATISFIED; + volatile gic_dist *dist = ARM_GIC_DIST; + + *pending = gic_id_is_pending(dist, vector); + return RTEMS_SUCCESSFUL; } rtems_status_code bsp_interrupt_raise(rtems_vector_number vector) { bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); - return RTEMS_UNSATISFIED; + + if (vector <= ARM_GIC_IRQ_SGI_LAST) { + arm_gic_trigger_sgi(vector, 1U << _SMP_Get_current_processor()); + } else { + volatile gic_dist *dist = ARM_GIC_DIST; + + gic_id_set_pending(dist, vector); + } + + return RTEMS_SUCCESSFUL; } #if defined(RTEMS_SMP) @@ -95,15 +130,27 @@ rtems_status_code bsp_interrupt_raise_on( uint32_t cpu_index ) { - bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); - return RTEMS_UNSATISFIED; + if (vector >= 16) { + return RTEMS_UNSATISFIED; + } + + arm_gic_trigger_sgi(vector, 1U << cpu_index); + return RTEMS_SUCCESSFUL; } #endif rtems_status_code bsp_interrupt_clear(rtems_vector_number vector) { + volatile gic_dist *dist = ARM_GIC_DIST; + bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); - return RTEMS_UNSATISFIED; + + if (vector <= ARM_GIC_IRQ_SGI_LAST) { + return RTEMS_UNSATISFIED; + } + + gic_id_clear_pending(dist, vector); + return RTEMS_SUCCESSFUL; } rtems_status_code bsp_interrupt_vector_is_enabled( @@ -111,10 +158,13 @@ rtems_status_code bsp_interrupt_vector_is_enabled( bool *enabled ) { + volatile gic_dist *dist = ARM_GIC_DIST; + bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); bsp_interrupt_assert(enabled != NULL); - *enabled = false; - return RTEMS_UNSATISFIED; + + *enabled = gic_id_is_enabled(dist, vector); + return RTEMS_SUCCESSFUL; } rtems_status_code bsp_interrupt_vector_enable(rtems_vector_number vector) @@ -207,8 +257,8 @@ BSP_START_TEXT_SECTION void arm_gic_irq_initialize_secondary_cpu(void) dist->icdigr[0] = 0xffffffff; #endif - /* Initialize Peripheral Private Interrupts (PPIs) */ - for (id = 0; id < 32; ++id) { + /* Initialize priority of SGIs and PPIs */ + for (id = 0; id <= ARM_GIC_IRQ_PPI_LAST; ++id) { gic_id_set_priority(dist, id, PRIORITY_DEFAULT); } @@ -300,6 +350,10 @@ rtems_status_code bsp_interrupt_set_affinity( volatile gic_dist *dist = ARM_GIC_DIST; uint8_t targets = (uint8_t) _Processor_mask_To_uint32_t(affinity, 0); + if ( vector <= ARM_GIC_IRQ_PPI_LAST ) { + return RTEMS_UNSATISFIED; + } + gic_id_set_targets(dist, vector, targets); return RTEMS_SUCCESSFUL; } @@ -310,8 +364,13 @@ rtems_status_code bsp_interrupt_get_affinity( ) { volatile gic_dist *dist = ARM_GIC_DIST; - uint8_t targets = gic_id_get_targets(dist, vector); + uint8_t targets; + + if ( vector <= ARM_GIC_IRQ_PPI_LAST ) { + return RTEMS_UNSATISFIED; + } + targets = gic_id_get_targets(dist, vector); _Processor_mask_From_uint32_t(affinity, targets, 0); return RTEMS_SUCCESSFUL; } diff --git a/bsps/shared/dev/irq/arm-gicv3.c b/bsps/shared/dev/irq/arm-gicv3.c index 3c1e2f8731..ca282a378d 100644 --- a/bsps/shared/dev/irq/arm-gicv3.c +++ b/bsps/shared/dev/irq/arm-gicv3.c @@ -169,6 +169,32 @@ rtems_status_code bsp_interrupt_get_attributes( rtems_interrupt_attributes *attributes ) { + attributes->is_maskable = true; + attributes->maybe_enable = true; + attributes->maybe_disable = true; + attributes->can_raise = true; + + if ( vector <= ARM_GIC_IRQ_SGI_LAST ) { + /* + * It is implementation-defined whether implemented SGIs are permanently + * enabled, or can be enabled and disabled by writes to GICD_ISENABLER0 and + * GICD_ICENABLER0. + */ + attributes->can_raise_on = true; + attributes->cleared_by_acknowledge = true; + attributes->trigger_signal = RTEMS_INTERRUPT_NO_SIGNAL; + } else { + attributes->can_disable = true; + attributes->can_clear = true; + attributes->trigger_signal = RTEMS_INTERRUPT_UNSPECIFIED_SIGNAL; + + if ( vector > ARM_GIC_IRQ_PPI_LAST ) { + /* SPI */ + attributes->can_get_affinity = true; + attributes->can_set_affinity = true; + } + } + return RTEMS_SUCCESSFUL; } @@ -179,14 +205,39 @@ rtems_status_code bsp_interrupt_is_pending( { bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); bsp_interrupt_assert(pending != NULL); - *pending = false; - return RTEMS_UNSATISFIED; + + if (vector <= ARM_GIC_IRQ_PPI_LAST) { + volatile gic_sgi_ppi *sgi_ppi = + gicv3_get_sgi_ppi(_SMP_Get_current_processor()); + + *pending = (sgi_ppi->icspispendr[0] & (1U << vector)) != 0; + } else { + volatile gic_dist *dist = ARM_GIC_DIST; + + *pending = gic_id_is_pending(dist, vector); + } + + return RTEMS_SUCCESSFUL; } rtems_status_code bsp_interrupt_raise(rtems_vector_number vector) { bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); - return RTEMS_UNSATISFIED; + + if (vector <= ARM_GIC_IRQ_SGI_LAST) { + arm_gic_trigger_sgi(vector, 1U << _SMP_Get_current_processor()); + } else if (vector <= ARM_GIC_IRQ_PPI_LAST) { + volatile gic_sgi_ppi *sgi_ppi = + gicv3_get_sgi_ppi(_SMP_Get_current_processor()); + + sgi_ppi->icspispendr[0] = 1U << vector; + } else { + volatile gic_dist *dist = ARM_GIC_DIST; + + gic_id_set_pending(dist, vector); + } + + return RTEMS_SUCCESSFUL; } #if defined(RTEMS_SMP) @@ -195,15 +246,35 @@ rtems_status_code bsp_interrupt_raise_on( uint32_t cpu_index ) { - bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); - return RTEMS_UNSATISFIED; + if (vector >= 16) { + return RTEMS_UNSATISFIED; + } + + arm_gic_trigger_sgi(vector, 1U << cpu_index); + return RTEMS_SUCCESSFUL; } #endif rtems_status_code bsp_interrupt_clear(rtems_vector_number vector) { bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); - return RTEMS_UNSATISFIED; + + if (vector <= ARM_GIC_IRQ_SGI_LAST) { + return RTEMS_UNSATISFIED; + } + + if ( vector <= ARM_GIC_IRQ_PPI_LAST ) { + volatile gic_sgi_ppi *sgi_ppi = + gicv3_get_sgi_ppi(_SMP_Get_current_processor()); + + sgi_ppi->icspicpendr[0] = 1U << vector; + } else { + volatile gic_dist *dist = ARM_GIC_DIST; + + gic_id_clear_pending(dist, vector); + } + + return RTEMS_SUCCESSFUL; } rtems_status_code bsp_interrupt_vector_is_enabled( @@ -213,8 +284,19 @@ rtems_status_code bsp_interrupt_vector_is_enabled( { bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); bsp_interrupt_assert(enabled != NULL); - *enabled = false; - return RTEMS_UNSATISFIED; + + if ( vector <= ARM_GIC_IRQ_PPI_LAST ) { + volatile gic_sgi_ppi *sgi_ppi = + gicv3_get_sgi_ppi(_SMP_Get_current_processor()); + + *enabled = (sgi_ppi->icspiser[0] & (1U << vector)) != 0; + } else { + volatile gic_dist *dist = ARM_GIC_DIST; + + *enabled = gic_id_is_enabled(dist, vector); + } + + return RTEMS_SUCCESSFUL; } rtems_status_code bsp_interrupt_vector_enable(rtems_vector_number vector) @@ -222,22 +304,24 @@ rtems_status_code bsp_interrupt_vector_enable(rtems_vector_number vector) bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); - if (vector >= 32) { + if (vector > ARM_GIC_IRQ_PPI_LAST) { volatile gic_dist *dist = ARM_GIC_DIST; + gic_id_enable(dist, vector); } else { volatile gic_sgi_ppi *sgi_ppi = gicv3_get_sgi_ppi(_SMP_Get_current_processor()); + /* Set interrupt group to 1 in the current security mode */ #if defined(ARM_MULTILIB_ARCH_V4) || defined(AARCH64_IS_NONSECURE) - sgi_ppi->icspigrpr[0] |= 1 << (vector % 32); - sgi_ppi->icspigrpmodr[0] &= ~(1 << (vector % 32)); + sgi_ppi->icspigrpr[0] |= 1U << vector; + sgi_ppi->icspigrpmodr[0] &= ~(1U << vector); #else - sgi_ppi->icspigrpr[0] &= ~(1 << (vector % 32)); - sgi_ppi->icspigrpmodr[0] |= 1 << (vector % 32); + sgi_ppi->icspigrpr[0] &= ~(1U << vector); + sgi_ppi->icspigrpmodr[0] |= 1U << vector; #endif /* Set enable */ - sgi_ppi->icspiser[0] = 1 << (vector % 32); + sgi_ppi->icspiser[0] = 1U << vector; } return RTEMS_SUCCESSFUL; @@ -247,13 +331,15 @@ rtems_status_code bsp_interrupt_vector_disable(rtems_vector_number vector) { bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); - if (vector >= 32) { + if (vector > ARM_GIC_IRQ_PPI_LAST) { volatile gic_dist *dist = ARM_GIC_DIST; + gic_id_disable(dist, vector); } else { volatile gic_sgi_ppi *sgi_ppi = gicv3_get_sgi_ppi(_SMP_Get_current_processor()); - sgi_ppi->icspicer[0] = 1 << (vector % 32); + + sgi_ppi->icspicer[0] = 1U << vector; } return RTEMS_SUCCESSFUL; @@ -407,6 +493,10 @@ rtems_status_code bsp_interrupt_set_affinity( volatile gic_dist *dist = ARM_GIC_DIST; uint8_t targets = (uint8_t) _Processor_mask_To_uint32_t(affinity, 0); + if ( vector <= ARM_GIC_IRQ_PPI_LAST ) { + return RTEMS_UNSATISFIED; + } + gic_id_set_targets(dist, vector, targets); return RTEMS_SUCCESSFUL; } @@ -417,8 +507,13 @@ rtems_status_code bsp_interrupt_get_affinity( ) { volatile gic_dist *dist = ARM_GIC_DIST; - uint8_t targets = gic_id_get_targets(dist, vector); + uint8_t targets; + + if ( vector <= ARM_GIC_IRQ_PPI_LAST ) { + return RTEMS_UNSATISFIED; + } + targets = gic_id_get_targets(dist, vector); _Processor_mask_From_uint32_t(affinity, targets, 0); return RTEMS_SUCCESSFUL; } -- cgit v1.2.3