diff --git a/arch/xtensa/core/crt1.S b/arch/xtensa/core/crt1.S index 23ce498df9e..a147e9ed14d 100644 --- a/arch/xtensa/core/crt1.S +++ b/arch/xtensa/core/crt1.S @@ -148,13 +148,6 @@ _start: movi a0, 0 # endif -# if CONFIG_MP_NUM_CPUS > 1 - /* Only clear BSS when running on core 0 */ - rsr a3, PRID - extui a3, a3, 0, 8 /* extract core ID */ - bnez a3, .L3zte -# endif - /* * Clear the BSS (uninitialized data) segments. * This code supports multiple zeroed sections (*.bss). @@ -196,24 +189,6 @@ _start: #endif /* !XCHAL_HAVE_BOOTLOADER */ -#if CONFIG_MP_NUM_CPUS > 1 - /* - * z_cstart() is only for CPU #0. - * Other CPUs have different entry point. - */ - rsr a3, PRID - extui a3, a3, 0, 8 /* extract core ID */ - beqz a3, 2f - - /* Load our stack pointer set up for us by the SOC layer */ - movi a1, z_mp_stack_top - l32i a1, a1, 0 - - call4 z_mp_entry - -2: -#endif - /* Enter C domain, never returns from here */ CALL z_cstart diff --git a/soc/xtensa/intel_adsp/common/soc_mp.c b/soc/xtensa/intel_adsp/common/soc_mp.c index 6984a4fa775..6dac17b7d9d 100644 --- a/soc/xtensa/intel_adsp/common/soc_mp.c +++ b/soc/xtensa/intel_adsp/common/soc_mp.c @@ -55,8 +55,6 @@ LOG_MODULE_REGISTER(soc_mp, CONFIG_SOC_LOG_LEVEL); static const struct device *idc; #endif -extern void __start(void); - struct cpustart_rec { uint32_t cpu; @@ -90,6 +88,29 @@ static __aligned(XCHAL_DCACHE_LINESIZE) union { (*((volatile struct cpustart_rec *) \ z_soc_uncached_ptr(&cpustart_mem.cpustart))) +/* Tiny assembly stub for calling z_mp_entry() on the auxiliary CPUs. + * Mask interrupts, clear the register window state and set the stack + * pointer. This represents the minimum work required to run C code + * safely. + * + * Note that alignment is absolutely required: the IDC protocol passes + * only the upper 30 bits of the address to the second CPU. + */ +void z_soc_mp_asm_entry(void); +__asm__(".align 4 \n\t" + ".global z_soc_mp_asm_entry \n\t" + "z_soc_mp_asm_entry: \n\t" + " rsil a0, 5 \n\t" /* 5 == XCHAL_EXCM_LEVEL */ + " movi a0, 0 \n\t" + " wsr a0, WINDOWBASE \n\t" + " movi a0, 1 \n\t" + " wsr a0, WINDOWSTART \n\t" + " rsync \n\t" + " movi a1, z_mp_stack_top \n\t" + " l32i a1, a1, 0 \n\t" + " call4 z_mp_entry \n\t"); +BUILD_ASSERT(XCHAL_EXCM_LEVEL == 5); + void z_mp_entry(void) { volatile int ie; @@ -177,7 +198,9 @@ void arch_start_cpu(int cpu_num, k_thread_stack_t *stack, int sz, CAVS_ICTL_INT_CPU_OFFSET(cpu_num), 8); /* Send power up message to the other core */ - idc_write(IPC_IDCIETC(cpu_num), 0, IDC_MSG_POWER_UP_EXT(RAM_BASE)); + uint32_t ietc = IDC_MSG_POWER_UP_EXT((long) z_soc_mp_asm_entry); + + idc_write(IPC_IDCIETC(cpu_num), 0, ietc); idc_write(IPC_IDCITC(cpu_num), 0, IDC_MSG_POWER_UP | IPC_IDCITC_BUSY); /* Disable IDC interrupt on other core so IPI won't cause