[PATCH] bsps/arm: Update GICv3 to use newer affinity interface

Kinsey Moore kinsey.moore at oarcorp.com
Fri Jan 24 18:05:40 UTC 2020


This patch looks good to me.

Kinsey Moore

> -----Original Message-----
> From: Jeff Kubascik <jeff.kubascik at dornerworks.com>
> Sent: Thursday, January 23, 2020 08:49
> To: devel at rtems.org
> Cc: Kinsey Moore <kinsey.moore at oarcorp.com>; Joel Sherrill
> <joel.sherrill at oarcorp.com>
> Subject: [PATCH] bsps/arm: Update GICv3 to use newer affinity interface
> 
> The GICv3 implementation uses the GICD_ITARGETSR register to configure
> interrupt affinity. The GIC uses this register only when affinity routing is disabled,
> which is called legacy operation mode. However, affinity routing is being
> enabled, by setting the ARE_NS bit in the GICD_CTLR register; therefore
> GICD_ITARGETSR will be ignored.
> 
> While affinity routing could be disabled, this legacy operation mode is optional
> for a GIC implementation - it should be avoided.
> 
> This change uses the newer affinity register GICD_IROUTER. The register is 64
> bits wide, so any access would need to be performed with two store operations
> on a 32 bit RTEMS build. This had to be done with assembly code, as the
> compiler optimizer will try to use the 64 bit floating point store operation VSTM
> to write to the register. This does not work with virtual GICD registers on the
> Xen hypervisor, as the VSTM instruction data abort does not provide syndrome
> information.
> 
> Affinity routing allows for hierarchical routing of interrupts. To take advantage
> of this feature, it would require an understanding of the processor/core
> hierarchy. RTEMS specifies the desired processor affinity with a mask, which
> does not provide this information. For now, assume a simple single level routing
> hierarchy.
> 
> Signed-off-by: Jeff Kubascik <jeff.kubascik at dornerworks.com>
> ---
>  bsps/arm/include/bsp/arm-gic-regs.h | 15 +++++++++++++++
>  bsps/arm/shared/irq/irq-gicv3.c     | 26 +++++++++++++++++++++++---
>  2 files changed, 38 insertions(+), 3 deletions(-)
> 
> diff --git a/bsps/arm/include/bsp/arm-gic-regs.h b/bsps/arm/include/bsp/arm-
> gic-regs.h
> index 8a65294b6f..13b715a3b1 100644
> --- a/bsps/arm/include/bsp/arm-gic-regs.h
> +++ b/bsps/arm/include/bsp/arm-gic-regs.h
> @@ -151,6 +151,21 @@ typedef struct {
>  #define GIC_DIST_ICDSGIR_SGIINTID(val) BSP_FLD32(val, 0, 3)  #define
> GIC_DIST_ICDSGIR_SGIINTID_GET(reg) BSP_FLD32GET(reg, 0, 3)  #define
> GIC_DIST_ICDSGIR_SGIINTID_SET(reg, val) BSP_FLD32SET(reg, val, 0, 3)
> +  uint32_t reserved_f04[5247];
> +  uint64_t icdirr[988];
> +#define GIC_DIST_ICDIRR_AFF3(val) BSP_FLD64(val, 32, 39) #define
> +GIC_DIST_ICDIRR_AFF3_GET(reg) BSP_FLD64GET(val, 32, 39) #define
> +GIC_DIST_ICDIRR_AFF3_SET(reg, val) BSP_FLD64SET(reg, val, 32, 39)
> +#define GIC_DIST_ICDIRR_INTERRUPT_ROUTING_MODE BSP_BIT64(31)
> #define
> +GIC_DIST_ICDIRR_AFF2(val) BSP_FLD64(val, 16, 23) #define
> +GIC_DIST_ICDIRR_AFF2_GET(reg) BSP_FLD64GET(val, 16, 23) #define
> +GIC_DIST_ICDIRR_AFF2_SET(reg, val) BSP_FLD64SET(reg, val, 16, 23)
> +#define GIC_DIST_ICDIRR_AFF1(val) BSP_FLD64(val, 8, 15) #define
> +GIC_DIST_ICDIRR_AFF1_GET(reg) BSP_FLD64GET(val, 8, 15) #define
> +GIC_DIST_ICDIRR_AFF1_SET(reg, val) BSP_FLD64SET(reg, val, 8, 15)
> +#define GIC_DIST_ICDIRR_AFF0(val) BSP_FLD64(val, 0, 7) #define
> +GIC_DIST_ICDIRR_AFF0_GET(reg) BSP_FLD64GET(val, 0, 7) #define
> +GIC_DIST_ICDIRR_AFF0_SET(reg, val) BSP_FLD64SET(reg, val, 0, 7)
>  } gic_dist;
> 
>  /* GICv3 only */
> diff --git a/bsps/arm/shared/irq/irq-gicv3.c b/bsps/arm/shared/irq/irq-gicv3.c
> index 138b565b9b..1b127fb4a1 100644
> --- a/bsps/arm/shared/irq/irq-gicv3.c
> +++ b/bsps/arm/shared/irq/irq-gicv3.c
> @@ -107,6 +107,12 @@
>  #define WRITE64_SR(SR_NAME, VALUE) \
>      __asm__ volatile("mcrr    " SR_NAME "  \n" : : "r" (VALUE) );
> 
> +#define WRITE64_REG(ADDR, VALUE) \
> +({ \
> +  __asm__ volatile("str %0, [%1, #0]"::"r"(VALUE), "r"(ADDR)); \
> +  __asm__ volatile("str %0, [%1, #4]"::"r"(VALUE >> 32), "r"(ADDR)); \
> +})
> +
>  #define ARM_GIC_REDIST ((volatile gic_redist *) BSP_ARM_GIC_REDIST_BASE)
> #define ARM_GIC_SGI_PPI (((volatile gic_sgi_ppi *)
> ((char*)BSP_ARM_GIC_REDIST_BASE + (1 << 16))))
> 
> @@ -166,6 +172,16 @@ static inline uint32_t get_id_count(volatile gic_dist
> *dist)
>    return id_count;
>  }
> 
> +static uint64_t cpu_to_affinity(uint32_t cpu) {
> +  /* CPU logical mapping is not present - keep it simple with a single level
> +     routing hierarchy */
> +  return (GIC_DIST_ICDIRR_AFF3(0) |
> +          GIC_DIST_ICDIRR_AFF2(0) |
> +          GIC_DIST_ICDIRR_AFF1(0) |
> +          GIC_DIST_ICDIRR_AFF0(cpu));
> +}
> +
>  static void init_cpu_interface(void)
>  {
>    uint32_t sre_value = 0x7;
> @@ -222,7 +238,7 @@ rtems_status_code bsp_interrupt_facility_initialize(void)
>    }
> 
>    for (id = 32; id < id_count; ++id) {
> -    gic_id_set_targets(dist, id, 0x01);
> +    WRITE64_REG(&dist->icdirr[id-32], cpu_to_affinity(0));
>    }
> 
>    init_cpu_interface();
> @@ -293,9 +309,13 @@ void bsp_interrupt_set_affinity(
>  )
>  {
>    volatile gic_dist *dist = ARM_GIC_DIST;
> -  uint8_t targets = (uint8_t) _Processor_mask_To_uint32_t(affinity, 0);
> +  uint32_t cpu = _Processor_mask_Find_last_set(affinity);
> 
> -  gic_id_set_targets(dist, vector, targets);
> +  if (vector < 32) {
> +    /* Affinity doesn't apply to SGIs/PPIs */  } else {
> +    WRITE64_REG(&dist->icdirr[vector-32], cpu_to_affinity(cpu));  }
>  }
> 
>  void bsp_interrupt_get_affinity(
> --
> 2.17.1



More information about the devel mailing list