diff --git a/arch/arm/core/aarch64/CMakeLists.txt b/arch/arm/core/aarch64/CMakeLists.txt index 57ad9a8593d220cc275a131d6390a6413d250d53..b336145dfa17dfeae4ff4628d3ec10a1e9804e4c 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 0000000000000000000000000000000000000000..a8b2ec2a254af69a59fbf3f4cbb228b9d1293807 --- /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 f941eced636e3951a067de0858b104a34ca87474..1a8b001002da334a777cea51b8c9d11d2f837952 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 4e75c78038b02fd39b0bc92892ea016869f467ee..f06582a8216f25eacc723ebbd233fc61cba1dca8 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 475ba056d50190dfd2757901aa8d6fc7910f1f45..acba1c26b182d4271093cba1f3fc46ccb8277ece 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 4701bd1ce255308fcf2911542683e84c62e34617..5f787cd68f113bf8890d5da84d05ff47ae877470 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 a6fd5af5f0f8a1ea7d889760c9c1e8d1a26b176a..10815723e91f67aeb139f17dc4fb2b7c35a792e0 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 bbf95b30c068a783d9e8ea930089e80668b7ec78..5b186c5ad08defc252774bcd597e46011367b73f 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 841b7390e9b607cdfb5e0c0c685e841bb9840692..ccc34fe7d3ddaa5405b42138ab3746ca53ff5383 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 4c385ae66fea953f3db317be4d1b39fc17e426b1..93386a80ec19df90323fc7331560862041686e9f 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 0000000000000000000000000000000000000000..917b981413662d8f274342a93db585749a91da9c --- /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 f8614880c3e76358c76afe9c8a20be4b401b1d45..d17f1979d671ff6f9d573e92789b2c44b84c5be8 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