diff --git a/soc/intel/intel_adsp/ace/CMakeLists.txt b/soc/intel/intel_adsp/ace/CMakeLists.txt index 519275d90476..9aebd85c43cf 100644 --- a/soc/intel/intel_adsp/ace/CMakeLists.txt +++ b/soc/intel/intel_adsp/ace/CMakeLists.txt @@ -18,6 +18,10 @@ zephyr_include_directories(include) zephyr_include_directories(include/${CONFIG_SOC}) zephyr_library_sources_ifdef(CONFIG_SOC_INTEL_COMM_WIDGET comm_widget.c) zephyr_library_sources_ifdef(CONFIG_SOC_INTEL_COMM_WIDGET comm_widget_messages.c) +zephyr_library_sources_ifdef( + CONFIG_SOC_SERIES_INTEL_ADSP_ACE_CUSTOM_MORE_SPIN_RELAX_NOPS + spin_relax.c +) if (CONFIG_XTENSA_MMU) zephyr_library_sources_ifdef(CONFIG_SOC_INTEL_ACE30 mmu_ace30.c) diff --git a/soc/intel/intel_adsp/ace/Kconfig b/soc/intel/intel_adsp/ace/Kconfig index e38ebdeb9c55..f4c7903e7a04 100644 --- a/soc/intel/intel_adsp/ace/Kconfig +++ b/soc/intel/intel_adsp/ace/Kconfig @@ -31,3 +31,24 @@ config SRAM_RETENTION_MODE When this option is enabled, the SRAM retention mode will be activated during the firmware boot-up process. If disabled, the retention mode will not be activated. + +config SOC_SERIES_INTEL_ADSP_ACE_CUSTOM_MORE_SPIN_RELAX_NOPS + bool "Use Intel Audio DSP specific arch_spin_relax() with more NOPs" + depends on !XTENSA_MORE_SPIN_RELAX_NOPS + default y if SMP && MP_MAX_NUM_CPUS > 1 + help + Add some NOPs after failure to lock a spinlock. This gives + the bus extra time to synchronize the RCW transaction + among CPUs. + +config SOC_SERIES_INTEL_ADSP_ACE_NUM_SPIN_RELAX_NOPS + int "Number of NOPs to be used in Intel Audio DSP specific arch_spin_relax()" + depends on SOC_SERIES_INTEL_ADSP_ACE_CUSTOM_MORE_SPIN_RELAX_NOPS + default 32 if MP_MAX_NUM_CPUS = 1 + default 64 if MP_MAX_NUM_CPUS = 2 + default 96 if MP_MAX_NUM_CPUS = 3 + default 128 if MP_MAX_NUM_CPUS = 4 + default 160 if MP_MAX_NUM_CPUS = 5 + help + Specify the number of NOPs in Intel Audio DSP specific + arch_spin_relax(). diff --git a/soc/intel/intel_adsp/ace/Kconfig.defconfig.series b/soc/intel/intel_adsp/ace/Kconfig.defconfig.series index 0d606715e09a..36b512d27cb3 100644 --- a/soc/intel/intel_adsp/ace/Kconfig.defconfig.series +++ b/soc/intel/intel_adsp/ace/Kconfig.defconfig.series @@ -57,20 +57,6 @@ config LOG_BACKEND_ADSP endif # LOG -config XTENSA_MORE_SPIN_RELAX_NOPS - default y if SMP && MP_MAX_NUM_CPUS > 1 - -if XTENSA_MORE_SPIN_RELAX_NOPS - -config XTENSA_NUM_SPIN_RELAX_NOPS - default 32 if MP_MAX_NUM_CPUS = 1 - default 64 if MP_MAX_NUM_CPUS = 2 - default 96 if MP_MAX_NUM_CPUS = 3 - default 128 if MP_MAX_NUM_CPUS = 4 - default 160 if MP_MAX_NUM_CPUS = 5 - -endif # XTENSA_MORE_SPIN_RELAX_NOPS - if KERNEL_VM_SUPPORT config KERNEL_VM_SIZE diff --git a/soc/intel/intel_adsp/ace/ace-link.ld b/soc/intel/intel_adsp/ace/ace-link.ld index 3e6d9428c590..aa92a212ea0a 100644 --- a/soc/intel/intel_adsp/ace/ace-link.ld +++ b/soc/intel/intel_adsp/ace/ace-link.ld @@ -297,6 +297,8 @@ SECTIONS { *libarch__xtensa__core.a:userspace.S.obj(.literal.xtensa_do_syscall) *libarch__xtensa__core.a:userspace.S.obj(.text.xtensa_do_syscall) + *libarch__xtensa__core.a:ptables.c.obj(.literal.xtensa_swap_update_page_tables) + *libarch__xtensa__core.a:ptables.c.obj(.text.xtensa_swap_update_page_tables) #ifdef CONFIG_XTENSA_SYSCALL_USE_HELPER *libarch__xtensa__core.a:syscall_helper.c.obj(.text.xtensa_syscall_helper*) @@ -503,6 +505,24 @@ SECTIONS { .bss SEGSTART_UNCACHED (NOLOAD) : { _bss_start = .; + +#if defined(CONFIG_ZTEST) && defined(CONFIG_SIMULATOR_XTENSA) + /* For some weird unknown reasons, the simulator really do not + * like these cpuhold_* variables to be tightly packed together. + * This results in cpuhold_spawned not being updated, and we + * will be stuck in the while loop for it to be set. + * Workaround by explicitly aligning these variables. + */ + . = ALIGN(16); + *:ztest.c.obj(.bss.cpuhold_sem) + . = ALIGN(16); + *:ztest.c.obj(.bss.cpuhold_active) + . = ALIGN(16); + *:ztest.c.obj(.bss.cpuhold_spawned) + . = ALIGN(16); + *:ztest.c.obj(.bss.cpuhold_pool_items) +#endif /* CONFIG_ZTEST && CONFIG_SIMULATOR_XTENSA */ + *(.dynsbss) *(.sbss) *(.sbss.*) diff --git a/soc/intel/intel_adsp/ace/spin_relax.c b/soc/intel/intel_adsp/ace/spin_relax.c new file mode 100644 index 000000000000..073deb5a6d07 --- /dev/null +++ b/soc/intel/intel_adsp/ace/spin_relax.c @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2025 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#include +#include + +#ifdef CONFIG_SOC_SERIES_INTEL_ADSP_ACE_NUM_SPIN_RELAX_NOPS +void arch_spin_relax(void) +{ + register uint32_t remaining = CONFIG_SOC_SERIES_INTEL_ADSP_ACE_NUM_SPIN_RELAX_NOPS; + + while (remaining > 0) { +#if (CONFIG_SOC_SERIES_INTEL_ADSP_ACE_NUM_SPIN_RELAX_NOPS % 4) == 0 + remaining -= 4; + + /* + * Note the xcc/xt-clang likes to "truncate" + * continuous NOPs to max 4 NOPs. So this is + * the most we can do in one loop. + */ + __asm__("nop.n; nop.n; nop.n; nop.n;"); +#else + remaining--; + __asm__("nop.n"); +#endif + } +} +#endif /* CONFIG_SOC_SERIES_INTEL_ADSP_ACE_NUM_SPIN_RELAX_NOPS */