armv7-a/r: check gic init wait done when using sgi

In SMP mode, qemu/goldfish platform, cpu0 use up_cpu_start()
to start others cpus.

But in previous patch(mathion ahead), arm_gic_initialize() will
wait others cpus start, so deadlocked!

Resolve:
Move the wait logic when use using sgi

Signed-off-by: ligd <liguiding1@xiaomi.com>
This commit is contained in:
ligd 2023-12-26 15:24:21 +08:00 committed by Xiang Xiao
parent 4f5b3f3d82
commit cd88cb1e48
2 changed files with 45 additions and 39 deletions

View File

@ -48,7 +48,7 @@
****************************************************************************/
#if defined(CONFIG_SMP) && CONFIG_SMP_NCPUS > 1
static volatile bool g_gic_init_done[CONFIG_SMP_NCPUS];
static volatile cpu_set_t g_gic_init_done;
#endif
/****************************************************************************
@ -68,20 +68,22 @@ static volatile bool g_gic_init_done[CONFIG_SMP_NCPUS];
#if defined(CONFIG_SMP) && CONFIG_SMP_NCPUS > 1
static void arm_gic_init_done(void)
{
int cpu = up_cpu_index();
int i;
CPU_SET(up_cpu_index(), &g_gic_init_done);
}
g_gic_init_done[cpu] = true;
if (cpu == 0)
static void arm_gic_wait_done(cpu_set_t cpuset)
{
cpu_set_t tmpset;
do
{
for (i = 1; i < CONFIG_SMP_NCPUS; i++)
{
while (!g_gic_init_done[i]);
}
CPU_AND(&tmpset, &g_gic_init_done, &cpuset);
}
while (!CPU_EQUAL(&tmpset, &cpuset));
}
#else
#define arm_gic_init_done()
#define arm_gic_wait_done(cpuset)
#endif
/****************************************************************************
@ -709,6 +711,39 @@ int arm_gic_irq_trigger(int irq, bool edge)
return -EINVAL;
}
void arm_cpu_sgi(int sgi, unsigned int cpuset)
{
uint32_t regval;
arm_gic_wait_done(cpuset);
#ifdef CONFIG_SMP
regval = GIC_ICDSGIR_INTID(sgi) | GIC_ICDSGIR_CPUTARGET(cpuset) |
GIC_ICDSGIR_TGTFILTER_LIST;
#else
regval = GIC_ICDSGIR_INTID(sgi) | GIC_ICDSGIR_CPUTARGET(0) |
GIC_ICDSGIR_TGTFILTER_THIS;
#endif
#if defined(CONFIG_ARCH_TRUSTZONE_SECURE)
if (sgi >= GIC_IRQ_SGI0 && sgi <= GIC_IRQ_SGI7)
#endif
{
/* Set NSATT be 1: forward the SGI specified in the SGIINTID field to a
* specified CPU interfaces only if the SGI is configured as Group 1 on
* that interface.
* For non-secure context, the configuration of GIC_ICDSGIR_NSATT_GRP1
* is not mandatory in the GICv2 specification, but for SMP scenarios,
* this value needs to be configured, otherwise issues may occur in the
* SMP scenario.
*/
regval |= GIC_ICDSGIR_NSATT_GRP1;
}
putreg32(regval, GIC_ICDSGIR);
}
#ifdef CONFIG_SMP
/****************************************************************************
* Name: up_send_smp_call

View File

@ -678,36 +678,7 @@ static inline unsigned int arm_gic_nlines(void)
*
****************************************************************************/
static inline void arm_cpu_sgi(int sgi, unsigned int cpuset)
{
uint32_t regval;
#ifdef CONFIG_SMP
regval = GIC_ICDSGIR_INTID(sgi) | GIC_ICDSGIR_CPUTARGET(cpuset) |
GIC_ICDSGIR_TGTFILTER_LIST;
#else
regval = GIC_ICDSGIR_INTID(sgi) | GIC_ICDSGIR_CPUTARGET(0) |
GIC_ICDSGIR_TGTFILTER_THIS;
#endif
#if defined(CONFIG_ARCH_TRUSTZONE_SECURE)
if (sgi >= GIC_IRQ_SGI0 && sgi <= GIC_IRQ_SGI7)
#endif
{
/* Set NSATT be 1: forward the SGI specified in the SGIINTID field to a
* specified CPU interfaces only if the SGI is configured as Group 1 on
* that interface.
* For non-secure context, the configuration of GIC_ICDSGIR_NSATT_GRP1
* is not mandatory in the GICv2 specification, but for SMP scenarios,
* this value needs to be configured, otherwise issues may occur in the
* SMP scenario.
*/
regval |= GIC_ICDSGIR_NSATT_GRP1;
}
putreg32(regval, GIC_ICDSGIR);
}
void arm_cpu_sgi(int sgi, unsigned int cpuset);
/****************************************************************************
* Public Function Prototypes