arch: arm64: fix the wrong way to send ipi interrupt

On GICv3, when we send an IPI interrupt, aff3, aff2 and aff1 should
be assigned a value corespond to a PE for which interrupt will be
generated. target_list only corresponds to aff0.

On real hardware, aff3, aff2, aff1 and aff0 should be treated as a
whole to determine a PE.

Signed-off-by: Huifeng Zhang <Huifeng.Zhang@arm.com>
This commit is contained in:
Huifeng Zhang 2022-07-05 14:13:23 +08:00 committed by Fabio Baltieri
commit 3d81d7f23f
3 changed files with 20 additions and 14 deletions

View file

@ -47,7 +47,6 @@ volatile struct boot_params __aligned(L1_CACHE_BYTES) arm64_cpu_boot_params = {
static const uint64_t cpu_node_list[] = { static const uint64_t cpu_node_list[] = {
DT_FOREACH_CHILD_STATUS_OKAY_SEP(DT_PATH(cpus), DT_REG_ADDR, (,)) DT_FOREACH_CHILD_STATUS_OKAY_SEP(DT_PATH(cpus), DT_REG_ADDR, (,))
}; };
static uint16_t target_list_mask;
extern void z_arm64_mm_init(bool is_primary_core); extern void z_arm64_mm_init(bool is_primary_core);
@ -106,8 +105,6 @@ void arch_start_cpu(int cpu_num, k_thread_stack_t *stack, int sz,
while (arm64_cpu_boot_params.fn) { while (arm64_cpu_boot_params.fn) {
wfe(); wfe();
} }
/* Set secondary cores bit mask */
target_list_mask |= 1 << MPIDR_TO_CORE(cpu_mpid);
printk("Secondary CPU core %d (MPID:%#llx) is up\n", cpu_num, cpu_mpid); printk("Secondary CPU core %d (MPID:%#llx) is up\n", cpu_num, cpu_mpid);
} }
@ -157,14 +154,21 @@ void z_arm64_secondary_start(void)
static void broadcast_ipi(unsigned int ipi) static void broadcast_ipi(unsigned int ipi)
{ {
const uint64_t mpidr = GET_MPIDR(); uint64_t mpidr = MPIDR_TO_CORE(GET_MPIDR());
/* /*
* Send SGI to all cores except itself * Send SGI to all cores except itself
* Note: Assume only one Cluster now.
*/ */
gic_raise_sgi(ipi, mpidr, target_list_mask & for (int i = 0; i < CONFIG_MP_NUM_CPUS; i++) {
~(1 << MPIDR_TO_CORE(mpidr))); uint64_t target_mpidr = cpu_node_list[i];
uint8_t aff0 = MPIDR_AFFLVL(target_mpidr, 0);
if (mpidr == target_mpidr) {
continue;
}
gic_raise_sgi(ipi, target_mpidr, 1 << aff0);
}
} }
void sched_ipi_handler(const void *unused) void sched_ipi_handler(const void *unused)
@ -211,8 +215,9 @@ void flush_fpu_ipi_handler(const void *unused)
void z_arm64_flush_fpu_ipi(unsigned int cpu) void z_arm64_flush_fpu_ipi(unsigned int cpu)
{ {
const uint64_t mpidr = cpu_node_list[cpu]; const uint64_t mpidr = cpu_node_list[cpu];
uint8_t aff0 = MPIDR_AFFLVL(mpidr, 0);
gic_raise_sgi(SGI_FPU_IPI, mpidr, 1 << MPIDR_TO_CORE(mpidr)); gic_raise_sgi(SGI_FPU_IPI, mpidr, 1 << aff0);
} }
#endif #endif
@ -220,9 +225,6 @@ static int arm64_smp_init(const struct device *dev)
{ {
ARG_UNUSED(dev); ARG_UNUSED(dev);
/* Seting the primary core bit mask */
target_list_mask |= 1 << MPIDR_TO_CORE(GET_MPIDR());
/* /*
* SGI0 is use for sched ipi, this might be changed to use Kconfig * SGI0 is use for sched ipi, this might be changed to use Kconfig
* option * option

View file

@ -73,12 +73,13 @@
#define MPIDR_AFF2_SHIFT (16) #define MPIDR_AFF2_SHIFT (16)
#define MPIDR_AFF3_SHIFT (32) #define MPIDR_AFF3_SHIFT (32)
#define MPIDR_AFF_MASK (GENMASK(23, 0) | GENMASK(39, 32))
#define MPIDR_AFFLVL(mpidr, aff_level) \ #define MPIDR_AFFLVL(mpidr, aff_level) \
(((mpidr) >> MPIDR_AFF##aff_level##_SHIFT) & MPIDR_AFFLVL_MASK) (((mpidr) >> MPIDR_AFF##aff_level##_SHIFT) & MPIDR_AFFLVL_MASK)
#define GET_MPIDR() read_sysreg(mpidr_el1) #define GET_MPIDR() read_sysreg(mpidr_el1)
#define MPIDR_TO_CORE(mpidr) MPIDR_AFFLVL(mpidr, 0) #define MPIDR_TO_CORE(mpidr) (mpidr & MPIDR_AFF_MASK)
#define IS_PRIMARY_CORE() (!MPIDR_TO_CORE(GET_MPIDR()))
#define MODE_EL_SHIFT (0x2) #define MODE_EL_SHIFT (0x2)
#define MODE_EL_MASK (0x3) #define MODE_EL_MASK (0x3)

View file

@ -89,7 +89,10 @@ static inline void trigger_irq(int irq)
sys_write32(GICD_SGIR_TGTFILT_REQONLY | GICD_SGIR_SGIINTID(irq), sys_write32(GICD_SGIR_TGTFILT_REQONLY | GICD_SGIR_SGIINTID(irq),
GICD_SGIR); GICD_SGIR);
#else #else
gic_raise_sgi(irq, GET_MPIDR(), BIT(MPIDR_TO_CORE(GET_MPIDR()))); uint64_t mpidr = GET_MPIDR();
uint8_t aff0 = MPIDR_AFFLVL(mpidr, 0);
gic_raise_sgi(irq, mpidr, BIT(aff0));
#endif #endif
} }