diff --git a/arch/arm64/src/bcm2711/CMakeLists.txt b/arch/arm64/src/bcm2711/CMakeLists.txt index 00c021def9e..0dc93d00e3b 100644 --- a/arch/arm64/src/bcm2711/CMakeLists.txt +++ b/arch/arm64/src/bcm2711/CMakeLists.txt @@ -22,6 +22,10 @@ set(SRCS bcm2711_boot.c bcm2711_mailbox.c bcm2711_serial.c bcm2711_gpio.c) +if(CONFIG_SMP) + list(APPEND SRCS bcm2711_cpustart.c) +endif() + # Early boot logging if(CONFIG_ARCH_EARLY_PRINT) diff --git a/arch/arm64/src/bcm2711/Make.defs b/arch/arm64/src/bcm2711/Make.defs index b1e8e2608d7..a82aa277441 100644 --- a/arch/arm64/src/bcm2711/Make.defs +++ b/arch/arm64/src/bcm2711/Make.defs @@ -27,6 +27,10 @@ CHIP_CSRCS += bcm2711_mailbox.c CHIP_CSRCS += bcm2711_serial.c CHIP_CSRCS += bcm2711_gpio.c +ifeq ($(CONFIG_SMP),y) +CHIP_CSRCS += bcm2711_cpustart.c +endif + # Early boot logging ifeq ($(CONFIG_ARCH_EARLY_PRINT),y) diff --git a/arch/arm64/src/bcm2711/bcm2711_boot.c b/arch/arm64/src/bcm2711/bcm2711_boot.c index 4a424607a44..7c0d92ecf0b 100644 --- a/arch/arm64/src/bcm2711/bcm2711_boot.c +++ b/arch/arm64/src/bcm2711/bcm2711_boot.c @@ -26,19 +26,21 @@ #include #include +#include + +#include #include "arm64_arch.h" #include "arm64_internal.h" #include "arm64_mmu.h" #include "bcm2711_boot.h" #include "bcm2711_serial.h" -#include +#include "bcm2711_mailbox.h" #ifdef CONFIG_SMP -#include "arm64_smp.h" +#include "bcm2711_cpustart.h" #endif -#include #ifdef CONFIG_LEGACY_PAGING #include #endif @@ -72,6 +74,10 @@ const struct arm_mmu_config g_mmu_config = .mmu_regions = g_mmu_regions, }; +/**************************************************************************** + * Public Data + ****************************************************************************/ + /**************************************************************************** * Public Functions ****************************************************************************/ @@ -124,7 +130,12 @@ int arm64_get_cpuid(uint64_t mpid) void arm64_el_init(void) { - /* TODO: what goes here? */ +#ifdef CONFIG_SMP + + /* This needs to be run at high EL or it does not work for some reason. */ + + bcm2711_cpustart(); +#endif } /**************************************************************************** diff --git a/arch/arm64/src/bcm2711/bcm2711_cpustart.c b/arch/arm64/src/bcm2711/bcm2711_cpustart.c new file mode 100644 index 00000000000..9de3dfd23ff --- /dev/null +++ b/arch/arm64/src/bcm2711/bcm2711_cpustart.c @@ -0,0 +1,86 @@ +/**************************************************************************** + * arch/arm64/src/bcm2711/bcm2711_cpustart.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include "arm64_smp.h" +#include "arm64_internal.h" + +#include "hardware/bcm2711_memmap.h" +#include "bcm2711_cpustart.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: bcm2711_cpustart + * + * Description: + * Populate CPU core spin tables with the correct start addresses and + * notify cores. + * + ****************************************************************************/ + +void bcm2711_cpustart(void) +{ + /* According to the bcm2711.dtsi file in the Linux source tree [1], the + * CPUs on the BCM2711 use a spin-table enable method and poll the + * following addresses: + * + * CPU0: 0x000000d8 (BCM_MBOX_CLR06) + * CPU1: 0x000000e0 (BCM_MBOX_CLR08) + * CPU2: 0x000000e8 (BCM_MBOX_CLR10) + * CPU3: 0x000000f0 (BCM_MBOX_CLR12) + * + * Some kernel docs about booting [2] have a handy explanation of how this + * works: + * + * "polling their cpu-release-addr location, which must be contained in the + * reserved region ... when a read of the location pointed to by the + * cpu-release-addr returns a non-zero value, the CPU must jump to this + * value" [2] + * + * In our case, we want these CPUs to load the NuttX kernel defined by + * `_start`. We don't need to worry about CPU0, that one always starts. + * These are 64-bit words (hence skipping every second register). + * + * [1] https://github.com/raspberrypi/linux/blob/rpi-6.12.y/ + * arch/arm/boot/dts/broadcom/bcm2711.dtsi + * + * [2] https://www.kernel.org/doc/Documentation/arm64/booting.txt + */ + + for (uint8_t cpu = 0; cpu < CONFIG_SMP_NCPUS; cpu++) + { + putreg64((uint64_t)__start, BCM_SPINTBL_CPU(cpu)); + sinfo("Starting CPU %u at %p\n", cpu, __start); + } + + UP_DSB(); + UP_SEV(); +} diff --git a/arch/arm64/src/bcm2711/bcm2711_cpustart.h b/arch/arm64/src/bcm2711/bcm2711_cpustart.h new file mode 100644 index 00000000000..ef4cefa89bb --- /dev/null +++ b/arch/arm64/src/bcm2711/bcm2711_cpustart.h @@ -0,0 +1,54 @@ +/**************************************************************************** + * arch/arm64/src/bcm2711/bcm2711_cpustart.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM64_SRC_BCM2711_BCM2711_CPUSTART_H +#define __ARCH_ARM64_SRC_BCM2711_BCM2711_CPUSTART_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +void bcm2711_cpustart(void); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif // __ASSEMBLY__ + +#endif /* __ARCH_ARM64_SRC_BCM2711_BCM2711_CPUSTART_H */ diff --git a/arch/arm64/src/bcm2711/hardware/bcm2711_memmap.h b/arch/arm64/src/bcm2711/hardware/bcm2711_memmap.h index b569fe40fd6..1ee99ff35bb 100644 --- a/arch/arm64/src/bcm2711/hardware/bcm2711_memmap.h +++ b/arch/arm64/src/bcm2711/hardware/bcm2711_memmap.h @@ -125,4 +125,10 @@ #define BCM_VC_MBOX_BASEADDR (BCM_PERIPHERAL_BASEADDR + 0xb880) +/* Spin table addresses + * https://huangweiliang.github.io/2026/02/03/QNX-Startup/ + */ + +#define BCM_SPINTBL_CPU(cpu) (0xd8L + (cpu) * 8) + #endif /* __ARCH_ARM64_SRC_BCM2711_MM_H */ diff --git a/boards/arm64/bcm2711/raspberrypi-4b/configs/smp/defconfig b/boards/arm64/bcm2711/raspberrypi-4b/configs/smp/defconfig new file mode 100644 index 00000000000..da99e7f6703 --- /dev/null +++ b/boards/arm64/bcm2711/raspberrypi-4b/configs/smp/defconfig @@ -0,0 +1,55 @@ +# +# This file is autogenerated: PLEASE DO NOT EDIT IT. +# +# You can use "make menuconfig" to make any modifications to the installed .config file. +# You can then do "make savedefconfig" to generate a new defconfig file that includes your +# modifications. +# +# CONFIG_NDEBUG is not set +CONFIG_ARCH="arm64" +CONFIG_ARCH_ARM64=y +CONFIG_ARCH_BOARD="raspberrypi-4b" +CONFIG_ARCH_BOARD_RASPBERRYPI_4B=y +CONFIG_ARCH_CHIP="bcm2711" +CONFIG_ARCH_CHIP_BCM2711=y +CONFIG_ARCH_INTERRUPTSTACK=4096 +CONFIG_ARCH_IRQPRIO=y +CONFIG_BOARD_LOOPSPERMSEC=132954 +CONFIG_BUILTIN=y +CONFIG_DEBUG_FULLOPT=y +CONFIG_DEBUG_SYMBOLS=y +CONFIG_DEFAULT_TASK_STACKSIZE=8192 +CONFIG_EXAMPLES_HELLO=y +CONFIG_EXPERIMENTAL=y +CONFIG_FS_PROCFS=y +CONFIG_FS_ROMFS=y +CONFIG_HAVE_CXX=y +CONFIG_HAVE_CXXINITIALIZE=y +CONFIG_IDLETHREAD_STACKSIZE=8192 +CONFIG_INIT_ENTRYPOINT="nsh_main" +CONFIG_INTELHEX_BINARY=y +CONFIG_NSH_BUILTIN_APPS=y +CONFIG_NSH_FILEIOSIZE=512 +CONFIG_NSH_READLINE=y +CONFIG_PREALLOC_TIMERS=4 +CONFIG_PTHREAD_STACK_MIN=8192 +CONFIG_RAMLOG=y +CONFIG_RAM_SIZE=4227858432 +CONFIG_RAM_START=0x00000000 +CONFIG_RAW_BINARY=y +CONFIG_READLINE_CMD_HISTORY=y +CONFIG_RR_INTERVAL=200 +CONFIG_SCHED_HPWORK=y +CONFIG_SCHED_HPWORKPRIORITY=192 +CONFIG_SMP=y +CONFIG_STACK_COLORATION=y +CONFIG_START_MONTH=11 +CONFIG_START_YEAR=2022 +CONFIG_SYMTAB_ORDEREDBYNAME=y +CONFIG_SYSTEM_NSH=y +CONFIG_SYSTEM_SYSTEM=y +CONFIG_TESTING_GETPRIME=y +CONFIG_TESTING_OSTEST=y +CONFIG_TESTING_SMP=y +CONFIG_USEC_PER_TICK=1000 +CONFIG_USERLED=y