From 0924ac3b7dee1e12b6583c79cc869ec92ddc0c72 Mon Sep 17 00:00:00 2001 From: Luis Gerhorst <privat@luisgerhorst.de> Date: Wed, 16 Dec 2020 15:20:46 +0100 Subject: [PATCH] Compile with CONFIG_SMP --- arch/arm/core/aarch64/CMakeLists.txt | 1 + arch/arm/core/aarch64/cpu_smp.c | 38 +++++++++++++++++++ arch/arm/core/aarch64/macro_priv.inc | 22 ++++++++--- arch/arm/core/offsets/offsets_aarch64.c | 4 ++ boards/arm/qemu_raspi3/qemu_raspi3.dts | 21 +++++++--- boards/arm/qemu_raspi3/qemu_raspi3_defconfig | 4 ++ drivers/timer/Kconfig | 3 +- drivers/timer/arm_arch_timer.c | 7 ++++ drivers/timer/bcm2835_arm_timer.c | 2 + .../brcm,bcm2835-armctrl-ic.yaml | 10 ++--- .../brcm,bcm2835-l1-intc.yaml | 21 ++++++++++ include/arch/arm/aarch64/asm_inline_gcc.h | 17 +++++++++ 12 files changed, 129 insertions(+), 21 deletions(-) create mode 100644 arch/arm/core/aarch64/cpu_smp.c create mode 100644 dts/bindings/interrupt-controller/brcm,bcm2835-l1-intc.yaml diff --git a/arch/arm/core/aarch64/CMakeLists.txt b/arch/arm/core/aarch64/CMakeLists.txt index 57ad9a8593d..b336145dfa1 100644 --- a/arch/arm/core/aarch64/CMakeLists.txt +++ b/arch/arm/core/aarch64/CMakeLists.txt @@ -31,3 +31,4 @@ zephyr_library_sources_ifdef(CONFIG_GEN_SW_ISR_TABLE isr_wrapper.S) zephyr_library_sources_ifdef(CONFIG_IRQ_OFFLOAD irq_offload.c) zephyr_library_sources_ifdef(CONFIG_ARM_MMU arm_mmu.c) zephyr_library_sources_ifdef(CONFIG_THREAD_LOCAL_STORAGE ../common/tls.c) +zephyr_library_sources_ifdef(CONFIG_SMP cpu_smp.c) diff --git a/arch/arm/core/aarch64/cpu_smp.c b/arch/arm/core/aarch64/cpu_smp.c new file mode 100644 index 00000000000..a8b2ec2a254 --- /dev/null +++ b/arch/arm/core/aarch64/cpu_smp.c @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2019 Intel Corporation + * SPDX-License-Identifier: Apache-2.0 + */ + +#include <kernel.h> +#include <kernel_arch_data.h> +#include <kernel_arch_func.h> +#include <kernel_structs.h> +#include <kernel_internal.h> + +static ALWAYS_INLINE void __SEV(void) +{ + __asm__ volatile ("sev" : : : "memory"); +} + +/* References: + * - https://github.com/torvalds/linux/commit/08e875c16a16c950e1e6d85755df5f3440844675 + * - stubs/src.armv7/kernel/boot/startup.S + * + * */ +void arch_start_cpu(int cpu_num, k_thread_stack_t *stack, int sz, + arch_cpustart_t fn, void *arg) +{ + printk("%s\n", __func__); + /* e.g. + #define ARM7_MBOX_OFF_C1_MB3 0x9C + #define ARM7_MBOX_OFF_C2_MB3 0xAC + #define ARM7_MBOX_OFF_C3_MB3 0xBC */ + /* intptr_t cpu_mbox_addr = ARM7_MBOX_BASE + 0x8C + (intptr_t) cpu_num * 0x10; */ + + /* = (arch_cpustart_t *) cpu_mbox_addr; */ + /* *cpu_mbox = fn; */ + + // synchronise and wake up other cores + /* __DSB(); */ + /* __SEV(); */ +} diff --git a/arch/arm/core/aarch64/macro_priv.inc b/arch/arm/core/aarch64/macro_priv.inc index f941eced636..1a8b001002d 100644 --- a/arch/arm/core/aarch64/macro_priv.inc +++ b/arch/arm/core/aarch64/macro_priv.inc @@ -101,6 +101,15 @@ eret .endm +.macro arch_curr_cpu xreg0, xreg1 + mrs \xreg1, mpidr_el1 + and \xreg1, \xreg1, #0xFF + mov \xreg0, #__cpu_t_SIZEOF + mul \xreg1, \xreg1, \xreg0 + ldr \xreg0, =_kernel + add \xreg0, \xreg0, \xreg1 +.endm + /** * @brief Increment nested counter * @@ -108,10 +117,10 @@ */ .macro inc_nest_counter xreg0, xreg1 - ldr \xreg0, =_kernel - ldr \xreg1, [\xreg0, #_kernel_offset_to_nested] + arch_curr_cpu \xreg0, \xreg1 + ldr \xreg1, [\xreg0, #___cpu_t_nested_OFFSET] add \xreg1, \xreg1, #1 - str \xreg1, [\xreg0, #_kernel_offset_to_nested] + str \xreg1, [\xreg0, #___cpu_t_nested_OFFSET] .endm /** @@ -121,10 +130,11 @@ */ .macro dec_nest_counter xreg0, xreg1 - ldr \xreg0, =_kernel - ldr \xreg1, [\xreg0, #_kernel_offset_to_nested] +mrs \xreg1, mpidr_el1 + arch_curr_cpu \xreg0, \xreg1 + ldr \xreg1, [\xreg0, #___cpu_t_nested_OFFSET] sub \xreg1, \xreg1, #1 - str \xreg1, [\xreg0, #_kernel_offset_to_nested] + str \xreg1, [\xreg0, #___cpu_t_nested_OFFSET] .endm #endif /* _ASMLANGUAGE */ diff --git a/arch/arm/core/offsets/offsets_aarch64.c b/arch/arm/core/offsets/offsets_aarch64.c index 4e75c78038b..f06582a8216 100644 --- a/arch/arm/core/offsets/offsets_aarch64.c +++ b/arch/arm/core/offsets/offsets_aarch64.c @@ -29,4 +29,8 @@ #include <kernel_arch_data.h> #include <kernel_offsets.h> +#ifdef CONFIG_SMP +GEN_ABSOLUTE_SYM(__cpu_t_SIZEOF, sizeof(_cpu_t)); +#endif + #endif /* _ARM_OFFSETS_INC_ */ diff --git a/boards/arm/qemu_raspi3/qemu_raspi3.dts b/boards/arm/qemu_raspi3/qemu_raspi3.dts index 475ba056d50..acba1c26b18 100644 --- a/boards/arm/qemu_raspi3/qemu_raspi3.dts +++ b/boards/arm/qemu_raspi3/qemu_raspi3.dts @@ -48,23 +48,30 @@ compatible = "brcm,bcm2835-armctrl-ic"; reg = <0x3f00b200 0x200>; interrupt-controller; - #interrupt-cells = <2>; + #interrupt-cells = <3>; label = "intc"; }; local_intc: local_intc@40000000 { - compatible = "brcm,bcm2836-l1-intc"; + compatible = "brcm,bcm2835-l1-intc"; reg = <0x40000000 0x100>; interrupt-controller; - #interrupt-cells = <2>; - interrupt-parent = <&local_intc>; + #interrupt-cells = <3>; + label = "l1-intc"; }; + timer { + compatible = "arm,arm-timer"; + interrupt-parent = <&local_intc>; + interrupts = <0 0 0>, <1 0 0>, <2 0 0>, <3 0 0>; /* CNTPSIRQ, CNTPNSIRQ, CNTHPIRQ, CNTVIRQ */ + label = "arch_timer"; + }; + /* https://github.com/s-matyukevich/raspberry-pi-os/blob/master/docs/lesson03/rpi-os.md#timer-initialization */ timer@3f003000 { compatible = "brcm,bcm2835-system-timer"; reg = <0x3f003000 0x20>; - interrupts = <1 0>, <1 1>, <1 2>, <1 3>; + interrupts = <0 0 0>, <1 0 0>, <2 0 0>, <3 0 0>; /* This could be a reference to BCM2835_CLOCK_TIMER, * but we don't have the driver using the common clock * support yet. @@ -72,10 +79,12 @@ clock-frequency = <1000000>; /* 1MHz */ }; + /* Page 196 in the "BCM2837 ARM Peripherals manual" https://github.com/raspberrypi/documentation/files/1888662/BCM2837-ARM-Peripherals.-.Revised.-.V2-1.pdf */ + /* TODO: This is likely not required. We just need timer@3f003000 for the system clock and armv7-timer for the timer ticks. */ timer@3f00b000 { compatible = "brcm,bcm2835-arm-timer"; reg = <0x3f00b000 0x1000>; - interrupts = <1 64>; + interrupts = <64 0 0>; clock-frequency = <1000000>; /* 1MHz */ }; diff --git a/boards/arm/qemu_raspi3/qemu_raspi3_defconfig b/boards/arm/qemu_raspi3/qemu_raspi3_defconfig index 4701bd1ce25..5f787cd68f1 100644 --- a/boards/arm/qemu_raspi3/qemu_raspi3_defconfig +++ b/boards/arm/qemu_raspi3/qemu_raspi3_defconfig @@ -26,3 +26,7 @@ CONFIG_UART_RASPI3_MINI=y CONFIG_QEMU_ICOUNT=n # CONFIG_BOOTLOADER_SRAM_SIZE=512 CONFIG_LOG=y + +CONFIG_SMP=y +CONFIG_MP_NUM_CPUS=4 +CONFIG_ARM_ARCH_TIMER=y \ No newline at end of file diff --git a/drivers/timer/Kconfig b/drivers/timer/Kconfig index a6fd5af5f0f..10815723e91 100644 --- a/drivers/timer/Kconfig +++ b/drivers/timer/Kconfig @@ -113,7 +113,6 @@ config ARCV2_TIMER_IRQ_PRIORITY config ARM_ARCH_TIMER bool "ARM architected timer" - depends on GIC select TICKLESS_CAPABLE help This module implements a kernel device driver for the ARM architected @@ -307,7 +306,7 @@ config BCM2835_SYSTEM_TIMER config BCM2835_ARM_TIMER bool "BCM2835 and BCM2837 ARM Timer" - default y + default n depends on !TICKLESS_IDLE depends on SOC_QEMU_RASPI3 help diff --git a/drivers/timer/arm_arch_timer.c b/drivers/timer/arm_arch_timer.c index bbf95b30c06..5b186c5ad08 100644 --- a/drivers/timer/arm_arch_timer.c +++ b/drivers/timer/arm_arch_timer.c @@ -106,3 +106,10 @@ uint32_t z_timer_cycle_get_32(void) { return (uint32_t)arm_arch_timer_count(); } + +#if defined(CONFIG_SMP) && CONFIG_MP_NUM_CPUS > 1 +void smp_timer_init(void) +{ + /* Nothing to be executed on each individual cpu. */ +} +#endif diff --git a/drivers/timer/bcm2835_arm_timer.c b/drivers/timer/bcm2835_arm_timer.c index 841b7390e9b..ccc34fe7d3d 100644 --- a/drivers/timer/bcm2835_arm_timer.c +++ b/drivers/timer/bcm2835_arm_timer.c @@ -11,6 +11,7 @@ #include <device.h> #include <irq.h> #include <spinlock.h> +#include <drivers/timer/system_timer.h> #define ARM_TIMER_BASE DT_INST_REG_ADDR(0) @@ -70,4 +71,5 @@ int z_clock_driver_init(const struct device *device) // system timer. put32(ARM_TIMER_LOAD, k_ticks_to_cyc_floor32(1)); put32(ARM_TIMER_CTRL, CTRL_ENABLE | CTRL_INT_ENABLE | CTRL_23BIT); + return 0; } diff --git a/dts/bindings/interrupt-controller/brcm,bcm2835-armctrl-ic.yaml b/dts/bindings/interrupt-controller/brcm,bcm2835-armctrl-ic.yaml index 4c385ae66fe..93386a80ec1 100644 --- a/dts/bindings/interrupt-controller/brcm,bcm2835-armctrl-ic.yaml +++ b/dts/bindings/interrupt-controller/brcm,bcm2835-armctrl-ic.yaml @@ -14,12 +14,8 @@ properties: label: required: true -# The 1st cell is the interrupt bank; 0 for interrupts in the "IRQ basic -# pending" register, or 1/2 respectively for interrupts in the "IRQ pending -# 1/2" register. -# -# The 2nd cell contains the interrupt number within the bank. Valid values -# are 0..7 for bank 0, and 0..31 for bank 1. +# GIC-compatible to allow reuse of arm,arm-timer. flags and priority are always 0. interrupt-cells: - irq - - number + - flags + - priority diff --git a/dts/bindings/interrupt-controller/brcm,bcm2835-l1-intc.yaml b/dts/bindings/interrupt-controller/brcm,bcm2835-l1-intc.yaml new file mode 100644 index 00000000000..917b9814136 --- /dev/null +++ b/dts/bindings/interrupt-controller/brcm,bcm2835-l1-intc.yaml @@ -0,0 +1,21 @@ +# Copyright (c) 2018 Marvell +# SPDX-License-Identifier: Apache-2.0 + +description: Interrupt Controller + +compatible: "brcm,bcm2835-l1-intc" + +include: base.yaml + +properties: + reg: + required: true + + label: + required: true + +# GIC-compatible to allow reuse of arm,arm-timer. flags and priority are always 0. +interrupt-cells: + - irq + - flags + - priority diff --git a/include/arch/arm/aarch64/asm_inline_gcc.h b/include/arch/arm/aarch64/asm_inline_gcc.h index f8614880c3e..d17f1979d67 100644 --- a/include/arch/arm/aarch64/asm_inline_gcc.h +++ b/include/arch/arm/aarch64/asm_inline_gcc.h @@ -18,6 +18,7 @@ #include <arch/arm/aarch64/cpu.h> #include <zephyr/types.h> +#include <kernel_structs.h> #ifdef __cplusplus extern "C" { @@ -71,6 +72,22 @@ static ALWAYS_INLINE bool arch_irq_unlocked(unsigned int key) return (key & DAIF_IRQ) == 0; } +static ALWAYS_INLINE struct _cpu *arch_curr_cpu(void) +{ +#ifdef CONFIG_SMP + unsigned int k = arch_irq_lock(); + + unsigned long mpid = read_sysreg(mpidr_el1); + struct _cpu *ret = &_kernel.cpus[mpid & 0xff]; + + arch_irq_unlock(k); + + return ret; +#else + return &_kernel.cpus[0]; +#endif +} + #ifdef __cplusplus } #endif -- GitLab