arm64/smp: changing the startup of arm64 SMP from serial to parallel

Signed-off-by: hujun5 <hujun5@xiaomi.com>
This commit is contained in:
hujun5 2024-08-01 21:31:55 +08:00 committed by Xiang Xiao
parent 5ff98fb4e1
commit 6dd26a3e68
3 changed files with 51 additions and 111 deletions

View File

@ -133,13 +133,6 @@
#define MODE_EL1 (0x1) #define MODE_EL1 (0x1)
#define MODE_EL0 (0x0) #define MODE_EL0 (0x0)
/* struct arm64_boot_params member offset for assembly code
* struct is defined at arm64_cpustart.c
*/
#define BOOT_PARAM_MPID 0
#define BOOT_PARAM_SP 8
#ifndef __ASSEMBLY__ #ifndef __ASSEMBLY__
/**************************************************************************** /****************************************************************************

View File

@ -54,34 +54,45 @@
* Public data * Public data
****************************************************************************/ ****************************************************************************/
typedef void (*arm64_cpustart_t)(void *data); uint64_t *const g_cpu_int_stacktop[CONFIG_SMP_NCPUS] =
struct arm64_boot_params
{
uint64_t cpuid;
char *boot_sp;
arm64_cpustart_t func;
void *arg;
int cpu_num;
volatile long cpu_ready_flag;
};
volatile struct arm64_boot_params aligned_data(L1_CACHE_BYTES)
cpu_boot_params =
{
.cpuid = -1,
.boot_sp = (char *)g_cpu_idlestackalloc[0],
};
volatile uint64_t *g_cpu_int_stacktop[CONFIG_SMP_NCPUS] =
{ {
(uint64_t *)(g_interrupt_stacks[0] + INTSTACK_SIZE), (uint64_t *)(g_interrupt_stacks[0] + INTSTACK_SIZE),
#if CONFIG_SMP_NCPUS > 1
(uint64_t *)(g_interrupt_stacks[1] + INTSTACK_SIZE),
#if CONFIG_SMP_NCPUS > 2
(uint64_t *)(g_interrupt_stacks[2] + INTSTACK_SIZE),
#if CONFIG_SMP_NCPUS > 3
(uint64_t *)(g_interrupt_stacks[3] + INTSTACK_SIZE),
#if CONFIG_SMP_NCPUS > 4
(uint64_t *)(g_interrupt_stacks[4] + INTSTACK_SIZE),
#if CONFIG_SMP_NCPUS > 5
# error This logic needs to extended for CONFIG_SMP_NCPUS > 5
#endif /* CONFIG_SMP_NCPUS > 5 */
#endif /* CONFIG_SMP_NCPUS > 4 */
#endif /* CONFIG_SMP_NCPUS > 3 */
#endif /* CONFIG_SMP_NCPUS > 2 */
#endif /* CONFIG_SMP_NCPUS > 1 */
}; };
#ifdef CONFIG_ARM64_DECODEFIQ #ifdef CONFIG_ARM64_DECODEFIQ
volatile uint64_t *g_cpu_int_fiq_stacktop[CONFIG_SMP_NCPUS] = uint64_t *const g_cpu_int_fiq_stacktop[CONFIG_SMP_NCPUS] =
{ {
(uint64_t *)(g_interrupt_fiq_stacks[0] + INTSTACK_SIZE), (uint64_t *)(g_interrupt_fiq_stacks[0] + INTSTACK_SIZE),
#if CONFIG_SMP_NCPUS > 1
(uint64_t *)(g_interrupt_fiq_stacks[1] + INTSTACK_SIZE),
#if CONFIG_SMP_NCPUS > 2
(uint64_t *)(g_interrupt_fiq_stacks[2] + INTSTACK_SIZE),
#if CONFIG_SMP_NCPUS > 3
(uint64_t *)(g_interrupt_fiq_stacks[3] + INTSTACK_SIZE),
#if CONFIG_SMP_NCPUS > 4
(uint64_t *)(g_interrupt_fiq_stacks[4] + INTSTACK_SIZE),
#if CONFIG_SMP_NCPUS > 5
# error This logic needs to extended for CONFIG_SMP_NCPUS > 5
#endif /* CONFIG_SMP_NCPUS > 5 */
#endif /* CONFIG_SMP_NCPUS > 4 */
#endif /* CONFIG_SMP_NCPUS > 3 */
#endif /* CONFIG_SMP_NCPUS > 2 */
#endif /* CONFIG_SMP_NCPUS > 1 */
}; };
#endif #endif
@ -100,20 +111,7 @@ static inline void local_delay(void)
} }
} }
#if defined (CONFIG_ARCH_HAVE_MMU) || defined (CONFIG_ARCH_HAVE_MPU) static void arm64_smp_init_top(void)
static void flush_boot_params(void)
{
uintptr_t flush_start;
uintptr_t flush_end;
flush_start = (uintptr_t)&cpu_boot_params;
flush_end = flush_start + sizeof(cpu_boot_params);
up_flush_dcache(flush_start, flush_end);
}
#endif
static void arm64_smp_init_top(void *arg)
{ {
struct tcb_s *tcb = this_task(); struct tcb_s *tcb = this_task();
@ -139,16 +137,14 @@ static void arm64_smp_init_top(void *arg)
write_sysreg(0, tpidrro_el0); write_sysreg(0, tpidrro_el0);
UNUSED(tcb); UNUSED(tcb);
cpu_boot_params.cpu_ready_flag = 1;
SP_SEV();
nx_idle_trampoline(); nx_idle_trampoline();
} }
static void arm64_start_cpu(int cpu_num, char *stack, int stack_sz, static void arm64_start_cpu(int cpu_num)
arm64_cpustart_t fn)
{ {
#ifdef CONFIG_ARM64_PSCI
uint64_t cpu_mpid = arm64_get_mpid(cpu_num); uint64_t cpu_mpid = arm64_get_mpid(cpu_num);
#endif
#ifdef CONFIG_SCHED_INSTRUMENTATION #ifdef CONFIG_SCHED_INSTRUMENTATION
@ -157,26 +153,6 @@ static void arm64_start_cpu(int cpu_num, char *stack, int stack_sz,
sched_note_cpu_start(this_task(), cpu_num); sched_note_cpu_start(this_task(), cpu_num);
#endif #endif
cpu_boot_params.boot_sp = stack;
cpu_boot_params.func = fn;
cpu_boot_params.arg = 0;
cpu_boot_params.cpu_num = cpu_num;
g_cpu_int_stacktop[cpu_num] =
(uint64_t *)(g_interrupt_stacks[cpu_num] + INTSTACK_SIZE);
#ifdef CONFIG_ARM64_DECODEFIQ
g_cpu_int_fiq_stacktop[cpu_num] =
(uint64_t *)(g_interrupt_fiq_stacks[cpu_num] + INTSTACK_SIZE);
#endif
ARM64_DSB();
/* store mpid last as this is our synchronization point */
cpu_boot_params.cpuid = arm64_get_cpuid(cpu_mpid);
flush_boot_params();
#ifdef CONFIG_ARM64_PSCI #ifdef CONFIG_ARM64_PSCI
if (psci_cpu_on(cpu_mpid, (uint64_t)__start)) if (psci_cpu_on(cpu_mpid, (uint64_t)__start))
{ {
@ -231,17 +207,7 @@ int up_cpu_start(int cpu)
sched_note_cpu_start(this_task(), cpu); sched_note_cpu_start(this_task(), cpu);
#endif #endif
cpu_boot_params.cpu_ready_flag = 0; arm64_start_cpu(cpu);
arm64_start_cpu(cpu, (char *)g_cpu_idlestackalloc[cpu], SMP_STACK_SIZE,
arm64_smp_init_top);
/* Waiting for this CPU to be boot complete */
while (!cpu_boot_params.cpu_ready_flag)
{
SP_WFE();
flush_boot_params();
}
return 0; return 0;
} }
@ -250,9 +216,6 @@ int up_cpu_start(int cpu)
void arm64_boot_secondary_c_routine(void) void arm64_boot_secondary_c_routine(void)
{ {
arm64_cpustart_t func;
void *arg;
#ifdef CONFIG_ARCH_HAVE_MPU #ifdef CONFIG_ARCH_HAVE_MPU
arm64_mpu_init(false); arm64_mpu_init(false);
#endif #endif
@ -267,20 +230,6 @@ void arm64_boot_secondary_c_routine(void)
up_perf_init(NULL); up_perf_init(NULL);
func = cpu_boot_params.func; arm64_smp_init_top();
arg = cpu_boot_params.arg;
ARM64_DSB();
/* Secondary core clears .func to announce its presence.
* Primary core is polling for this. We no longer own
* arm64_cpu_boot_params afterwards.
*/
cpu_boot_params.func = NULL;
ARM64_DSB();
SP_SEV();
func(arg);
} }

View File

@ -122,8 +122,6 @@ real_start:
msr DAIFSet, 0xf msr DAIFSet, 0xf
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
ldr x0, =cpu_boot_params
get_cpu_id x1 get_cpu_id x1
/* The global variable cpu_boot_params is not safety to /* The global variable cpu_boot_params is not safety to
@ -146,17 +144,20 @@ real_start:
cmp x1, #0 cmp x1, #0
beq primary_core beq primary_core
/* loop until our turn comes */
1: dmb ld
wfe
ldr x2, [x0, #BOOT_PARAM_MPID]
cmp x1, x2
bne 1b
/* we can now load our stack pointer value and move on */ /* we can now load our stack pointer value and move on */
ldr x24, [x0, #BOOT_PARAM_SP] ldr x24, =g_cpu_idlestackalloc
/* g_cpu_idlestackalloc represents a continuous
* stack space allocated for CPUs from 0 to n.
* the stack top address for each CPU based on
* its index,x24 is the top of the stack for CPUs 0 to n.
*/
1:
sub x1, x1, #1
add x24, x24, #(SMP_STACK_SIZE)
cmp x1, #0
bne 1b
# ifdef CONFIG_STACK_COLORATION # ifdef CONFIG_STACK_COLORATION
/* Write a known value to the IDLE thread stack to support stack /* Write a known value to the IDLE thread stack to support stack
@ -184,11 +185,8 @@ real_start:
b cpu_boot b cpu_boot
primary_core: primary_core:
/* set primary core id */ ldr x24, =g_cpu_idlestackalloc
str x1, [x0, #BOOT_PARAM_MPID]
ldr x24, [x0, #BOOT_PARAM_SP]
add x24, x24, #(CONFIG_IDLETHREAD_STACKSIZE) add x24, x24, #(CONFIG_IDLETHREAD_STACKSIZE)
#else #else
/* In some case, we need to boot one core in a SMP system, /* In some case, we need to boot one core in a SMP system,