arch/arm64: send sgi with correct aff and target list

armv8r and armv8a have different process affinity,
and sgi affinity needs to be able to adapt all of them.

Signed-off-by: zhangyuan21 <zhangyuan21@xiaomi.com>
This commit is contained in:
zhangyuan21 2023-04-24 05:27:18 +08:00 committed by Alan Carvalho de Assis
parent ea98e5a92e
commit f8b5fd2a9a
7 changed files with 62 additions and 9 deletions

View File

@ -69,6 +69,8 @@
#define CONFIG_LOAD_BASE 0x00000000
#define MPID_TO_CLUSTER_ID(mpid) ((mpid) & ~0xff)
#endif
#endif /* __ARCH_ARM64_INCLUDE_FVP_V8R_CHIP_H */

View File

@ -59,6 +59,8 @@
#define CONFIG_LOAD_BASE 0x40280000
#define MPID_TO_CLUSTER_ID(mpid) ((mpid) & ~0xff)
#endif
#endif /* __ARCH_ARM64_INCLUDE_QEMU_CHIP_H */

View File

@ -150,6 +150,7 @@
/* MPIDR_EL1, Multiprocessor Affinity Register */
#define MPIDR_AFFLVL_MASK (0xff)
#define MPIDR_ID_MASK (0xff00ffffff)
#define MPIDR_AFF0_SHIFT (0)
#define MPIDR_AFF1_SHIFT (8)
@ -180,7 +181,13 @@
(((mpid) >> MPIDR_AFF ## aff_level ## _SHIFT) & MPIDR_AFFLVL_MASK)
#define CORE_TO_MPID(core, aff_level) \
(((core) << MPIDR_AFF ## aff_level ## _SHIFT))
({ \
uint64_t __mpidr = GET_MPIDR(); \
__mpidr &= ~(MPIDR_AFFLVL_MASK << MPIDR_AFF ## aff_level ## _SHIFT); \
__mpidr |= (cpu << MPIDR_AFF ## aff_level ## _SHIFT); \
__mpidr &= MPIDR_ID_MASK; \
__mpidr; \
})
/* System register interface to GICv3 */
@ -561,6 +568,8 @@ void arm64_cpu_enable(void);
#ifdef CONFIG_SMP
uint64_t arm64_get_mpid(int cpu);
#else
# define arm64_get_mpid(cpu) GET_MPIDR()
#endif /* CONFIG_SMP */
#endif /* __ASSEMBLY__ */

View File

@ -30,8 +30,16 @@
#include "arm64_internal.h"
#include "arm64_arch.h"
/****************************************************************************
* Public Data
****************************************************************************/
extern void *_vector_table[];
/****************************************************************************
* Private Data
****************************************************************************/
/****************************************************************************
* Public Functions
****************************************************************************/

View File

@ -247,7 +247,6 @@ int arm64_pause_handler(int irq, void *context, void *arg)
int up_cpu_pause(int cpu)
{
int ret;
uint64_t mpidr = GET_MPIDR();
DEBUGASSERT(cpu >= 0 && cpu < CONFIG_SMP_NCPUS && cpu != this_cpu());
@ -273,7 +272,7 @@ int up_cpu_pause(int cpu)
/* Execute SGI2 */
ret = arm64_gic_raise_sgi(SGI_CPU_PAUSE, mpidr, (1 << cpu));
ret = arm64_gic_raise_sgi(SGI_CPU_PAUSE, (1 << cpu));
if (ret < 0)
{
/* What happened? Unlock the g_cpu_wait spinlock */

View File

@ -307,8 +307,7 @@ int arm64_gic_irq_trigger(unsigned int intid, uint32_t flags);
uint64_t * arm64_decodeirq(uint64_t *regs);
int arm64_gic_raise_sgi(unsigned int sgi_id, uint64_t target_aff,
uint16_t target_list);
int arm64_gic_raise_sgi(unsigned int sgi_id, uint16_t target_list);
#ifdef CONFIG_SMP

View File

@ -303,7 +303,7 @@ void arm64_gic_eoi(unsigned int intid)
write_sysreg(intid, ICC_EOIR1_EL1);
}
int arm64_gic_raise_sgi(unsigned int sgi_id, uint64_t target_aff,
static int arm64_gic_send_sgi(unsigned int sgi_id, uint64_t target_aff,
uint16_t target_list)
{
uint32_t aff3;
@ -329,6 +329,41 @@ int arm64_gic_raise_sgi(unsigned int sgi_id, uint64_t target_aff,
return 0;
}
int arm64_gic_raise_sgi(unsigned int sgi_id, uint16_t target_list)
{
uint64_t pre_cluster_id = UINT64_MAX;
uint64_t curr_cluster_id;
uint64_t curr_mpidr;
uint16_t tlist = 0;
uint16_t cpu = 0;
uint16_t i;
while ((i = ffs(target_list)))
{
cpu += (i - 1);
target_list >>= i;
curr_mpidr = arm64_get_mpid(cpu);
curr_cluster_id = MPID_TO_CLUSTER_ID(curr_mpidr);
if (pre_cluster_id != UINT64_MAX &&
pre_cluster_id != curr_cluster_id)
{
arm64_gic_send_sgi(sgi_id, pre_cluster_id, tlist);
}
tlist |= 1 << (curr_mpidr & MPIDR_AFFLVL_MASK);
cpu += i;
pre_cluster_id = curr_cluster_id;
}
arm64_gic_send_sgi(sgi_id, pre_cluster_id, tlist);
return 0;
}
/* Wake up GIC redistributor.
* clear ProcessorSleep and wait till ChildAsleep is cleared.
* ProcessSleep to be cleared only when ChildAsleep is set
@ -597,13 +632,12 @@ void up_affinity_irq(int irq, cpu_set_t cpuset)
void up_trigger_irq(int irq, cpu_set_t cpuset)
{
uint64_t mpidr = GET_MPIDR();
uint32_t mask = BIT(irq & (GIC_NUM_INTR_PER_REG - 1));
uint32_t idx = irq / GIC_NUM_INTR_PER_REG;
if (GIC_IS_SGI(irq))
{
arm64_gic_raise_sgi(irq, mpidr, cpuset);
arm64_gic_raise_sgi(irq, cpuset);
}
else if (irq >= 0 && irq < NR_IRQS)
{