[coreboot-gerrit] Change in coreboot[master]: soc/cavium: Add secondary CPU support
Patrick Rudolph (Code Review)
gerrit at coreboot.org
Fri Apr 20 14:52:32 CEST 2018
Patrick Rudolph has uploaded this change for review. ( https://review.coreboot.org/25752
Change subject: soc/cavium: Add secondary CPU support
......................................................................
soc/cavium: Add secondary CPU support
Change-Id: I07428161615bcd3d03a3eea0df2dd813e08c8f66
---
M src/mainboard/cavium/cn8100_sff_evb/Kconfig
M src/mainboard/cavium/cn8100_sff_evb/mainboard.c
M src/soc/cavium/cn81xx/Kconfig
M src/soc/cavium/cn81xx/Makefile.inc
M src/soc/cavium/cn81xx/cpu.c
A src/soc/cavium/cn81xx/cpu_secondary.S
M src/soc/cavium/cn81xx/include/soc/addressmap.h
M src/soc/cavium/cn81xx/include/soc/cpu.h
M src/soc/cavium/cn81xx/include/soc/memlayout.ld
M src/soc/cavium/cn81xx/soc.c
M src/soc/cavium/common/Makefile.inc
11 files changed, 286 insertions(+), 11 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/52/25752/1
diff --git a/src/mainboard/cavium/cn8100_sff_evb/Kconfig b/src/mainboard/cavium/cn8100_sff_evb/Kconfig
index 15dd814..3f13ad5 100644
--- a/src/mainboard/cavium/cn8100_sff_evb/Kconfig
+++ b/src/mainboard/cavium/cn8100_sff_evb/Kconfig
@@ -56,6 +56,9 @@
string
default "src/mainboard/$(CONFIG_MAINBOARD_DIR)/board.fmd"
+config MAX_CPUS
+ default 4
+
##########################################################
#### Update below when adding a new derivative board. ####
##########################################################
diff --git a/src/mainboard/cavium/cn8100_sff_evb/mainboard.c b/src/mainboard/cavium/cn8100_sff_evb/mainboard.c
index 31163d2..3dbfbfd 100644
--- a/src/mainboard/cavium/cn8100_sff_evb/mainboard.c
+++ b/src/mainboard/cavium/cn8100_sff_evb/mainboard.c
@@ -62,7 +62,7 @@
printk(BIOS_INFO, "MB: COREclk : %llu MHz\n",
thunderx_get_core_clock() / 1000000ULL);
- printk(BIOS_INFO, "MB: #CPU cores : %zu\n", cpu_get_num_cores());
+ printk(BIOS_INFO, "MB: #CPU cores : %zu\n", cpu_get_num_available_cores());
}
static void mainboard_init(device_t dev)
@@ -77,6 +77,10 @@
/* Init timer */
soc_timer_init();
+
+ /* Init CPUs */
+ for (i = 1; i < CONFIG_MAX_CPUS; i++)
+ start_cpu(i, NULL);
}
static void mainboard_enable(device_t dev)
diff --git a/src/soc/cavium/cn81xx/Kconfig b/src/soc/cavium/cn81xx/Kconfig
index cec0ada..d98378b 100644
--- a/src/soc/cavium/cn81xx/Kconfig
+++ b/src/soc/cavium/cn81xx/Kconfig
@@ -22,4 +22,7 @@
if SOC_CAVIUM_CN81XX
+config STACK_SIZE
+ default 0x2000
+
endif
diff --git a/src/soc/cavium/cn81xx/Makefile.inc b/src/soc/cavium/cn81xx/Makefile.inc
index f98e890..6fb664e 100644
--- a/src/soc/cavium/cn81xx/Makefile.inc
+++ b/src/soc/cavium/cn81xx/Makefile.inc
@@ -65,6 +65,7 @@
ramstage-y += cpu.c
ramstage-y += l2c.c
ramstage-y += ecam0.c
+ramstage-y += cpu_secondary.S
ramstage-y += bl31_plat_params.c
BL31_MAKEARGS += PLAT=t81 M0_CROSS_COMPILE="$(CROSS_COMPILE_arm)" ENABLE_SPE_FOR_LOWER_ELS=0
diff --git a/src/soc/cavium/cn81xx/cpu.c b/src/soc/cavium/cn81xx/cpu.c
index c054aa8..ee6feb4 100644
--- a/src/soc/cavium/cn81xx/cpu.c
+++ b/src/soc/cavium/cn81xx/cpu.c
@@ -14,13 +14,121 @@
*/
#include <types.h>
+#include <soc/addressmap.h>
#include <arch/io.h>
#include <soc/cpu.h>
#include <bdk-coreboot.h>
+#include <console/console.h>
+#include <timer.h>
+#include <delay.h>
-/* Return the number of cores available in the chip */
-size_t cpu_get_num_cores(void)
+uint64_t cpu_get_available_core_mask(void)
{
- uint64_t available = read64((void *)0x87e006001738ll);
- return bdk_dpop(available);
+ return read64((void *)RST_PP_AVAILABLE);
+}
+
+size_t cpu_get_num_available_cores(void)
+{
+ return bdk_dpop(cpu_get_available_core_mask());
+}
+
+static void (* secondary_c_entry)(size_t core_id) = NULL;
+static size_t secondary_booted;
+
+void secondary_cpu_init(size_t core_id)
+{
+ write64(&secondary_booted, 1);
+ dmb();
+
+ if (secondary_c_entry)
+ secondary_c_entry(core_id);
+ else
+ asm("wfi");
+}
+
+size_t cpu_self_get_core_id(void)
+{
+ u32 mpidr_el1;
+ asm("mrs %0, MPIDR_EL1\n\t" : "=r" (mpidr_el1) :: "memory");
+
+ /* Core is 4 bits from AFF0 and rest from AFF1 */
+ size_t core_num;
+ core_num = mpidr_el1 & 0xf;
+ core_num |= (mpidr_el1 & 0xff00) >> 4;
+
+ return core_num;
+}
+
+uint64_t cpu_self_get_core_mask(void)
+{
+ return 1ULL << cpu_self_get_core_id();
+}
+
+size_t start_cpu(size_t cpu, void (* entry_64)(size_t core_id))
+{
+ const uint64_t coremask = 1ULL << cpu;
+ struct stopwatch sw;
+ uint64_t pending;
+
+ printk(BIOS_DEBUG, "CPU: Starting CPU%zu @ %p.\n", cpu, entry_64);
+
+ /* Core not available */
+ if (!(coremask & cpu_get_available_core_mask()))
+ return 1;
+
+ /* Only secondary CPUs are supported */
+ if (cpu == cpu_self_get_core_id())
+ return 1;
+
+ /* Check stack here, instead of in cpu_secondary.S */
+ if ((CONFIG_STACK_SIZE * cpu) > _stack_sec_size)
+ return 1;
+
+ /* Write the address of the main entry point */
+ write64((void *)MIO_BOOT_AP_JUMP, (uintptr_t)secondary_init);
+
+ /* Get coremask of cores in reset */
+ const uint64_t reset = read64((void *)RST_PP_RESET);
+ printk(BIOS_INFO, "CPU: Cores currently in reset: 0x%llx\n", reset);
+
+ /* Setup entry for secondary core */
+ write64(&secondary_c_entry, (uintptr_t)entry_64);
+ write64(&secondary_booted, 0);
+ dmb();
+
+ printk(BIOS_DEBUG, "CPU: Taking core %zu out of reset.\n", cpu);
+
+ /* Release core from reset */
+ write64((void *)RST_PP_RESET, reset & ~coremask);
+
+ /* Wait for cores to finish coming out of reset */
+ udelay(1);
+
+ stopwatch_init_usecs_expire(&sw, 1000000);
+ do {
+ pending = read64((void *)RST_PP_PENDING);
+ } while (!stopwatch_expired(&sw) && (pending & coremask));
+
+ if (stopwatch_expired(&sw)) {
+ printk(BIOS_ERR, "ERROR: Timeout waiting for reset "
+ "pending to clear.");
+ return 1;
+ }
+
+ stopwatch_init_usecs_expire(&sw, 1000000);
+
+ printk(BIOS_DEBUG, "CPU: Wait up to 1s for the core to boot...\n");
+ while (!stopwatch_expired(&sw) && !read64(&secondary_booted));
+
+ /* Cleanup */
+ write64(&secondary_c_entry, 0);
+ dmb();
+
+ if (!read64(&secondary_booted)) {
+ printk(BIOS_ERR, "ERROR: Core %zu failed to start.\n", cpu);
+ return 1;
+ }
+
+ printk(BIOS_INFO, "CPU: Core %zu booted\n", cpu);
+ return 0;
}
diff --git a/src/soc/cavium/cn81xx/cpu_secondary.S b/src/soc/cavium/cn81xx/cpu_secondary.S
new file mode 100644
index 0000000..d4b4d3c
--- /dev/null
+++ b/src/soc/cavium/cn81xx/cpu_secondary.S
@@ -0,0 +1,91 @@
+/*
+ * Early initialization code for aarch64 (a.k.a. armv8)
+ *
+ * Copyright 2016 Cavium, Inc. <support at cavium.com>
+ * Copyright 2018-present Facebook, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; version 2 of
+ * the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <arch/asm.h>
+#include <soc/addressmap.h>
+
+// based on arm64_init_cpu
+ENTRY(secondary_init)
+ /* Initialize PSTATE (unmask all exceptions, select SP_EL0). */
+ msr SPSel, #0
+ msr DAIFClr, #0xf
+
+ /* TODO: This is where we'd put non-boot CPUs into WFI if needed. */
+
+ /* x22: SCTLR, return address: x23 (callee-saved by subroutine) */
+ mov x23, x30
+ /* TODO: Assert that we always start running at EL3 */
+ mrs x22, sctlr_el3
+
+ /* Activate ICache (12) already for speed during cache flush below. */
+ orr x22, x22, #(1 << 12)
+ msr sctlr_el3, x22
+ isb
+
+ /* Invalidate dcache */
+ bl dcache_invalidate_all
+
+ /* Deactivate MMU (0), Alignment Check (1) and DCache (2) */
+ and x22, x22, # ~(1 << 0) & ~(1 << 1) & ~(1 << 2)
+ /* Activate Stack Alignment (3) because why not */
+ orr x22, x22, #(1 << 3)
+ /* Set to little-endian (25) */
+ and x22, x22, # ~(1 << 25)
+ /* Deactivate write-xor-execute enforcement (19) */
+ and x22, x22, # ~(1 << 19)
+ msr sctlr_el3, x22
+
+ /* Invalidate icache and TLB for good measure */
+ ic iallu
+ tlbi alle3
+ dsb sy
+ isb
+
+ /* Load core ID to x0 */
+ mrs x0, MPIDR_EL1
+ and x1, x0, # 0xf
+ lsr x0, x0, 4
+ and x0, x0, # 0xff0
+ orr x0, x0, x1
+
+ /* Each core gets CONFIG_STACK_SIZE bytes of stack */
+ mov x2, # CONFIG_STACK_SIZE
+ mul x1, x0, x2
+ /* Backup core id */
+ mov x22, x0
+ ldr x0, =_stack_sec
+ add x0, x1, x0 // x0 = CONFIG_STACK_SIZE * coreid + _stack_sec
+ add x1, x0, # CONFIG_STACK_SIZE // x1 = x0 + CONFIG_STACK_SIZE
+
+ /* Initialize stack with sentinel value to later check overflow. */
+ ldr x2, =0xdeadbeefdeadbeef
+
+1:
+ stp x2, x2, [x0], #16
+ cmp x0, x1
+ bne 1b
+
+ /* Leave a line of beef dead for easier visibility in stack dumps. */
+ sub sp, x0, #16
+
+ /* Set arg0 to core id */
+ mov x0, x22
+
+ /* Call C entry */
+ bl secondary_cpu_init
+
+ENDPROC(secondary_init)
diff --git a/src/soc/cavium/cn81xx/include/soc/addressmap.h b/src/soc/cavium/cn81xx/include/soc/addressmap.h
index e235494..f902963 100644
--- a/src/soc/cavium/cn81xx/include/soc/addressmap.h
+++ b/src/soc/cavium/cn81xx/include/soc/addressmap.h
@@ -54,9 +54,14 @@
/* RST */
#define RST_PF_BAR0 (0x87E006000000ULL + 0x1600)
+#define RST_PP_AVAILABLE (RST_PF_BAR0 + 0x138ULL)
+#define RST_PP_RESET (RST_PF_BAR0 + 0x140ULL)
+#define RST_PP_PENDING (RST_PF_BAR0 + 0x148ULL)
+
#define FUSF_PF_BAR0 0x87E004000000ULL
#define MIO_FUS_PF_BAR0 0x87E003000000ULL
#define MIO_BOOT_PF_BAR0 0x87E000000000ULL
+#define MIO_BOOT_AP_JUMP (MIO_BOOT_PF_BAR0 + 0xD0ULL)
/* PTP */
#define MIO_PTP_PF_BAR0 0x807000000000ULL
diff --git a/src/soc/cavium/cn81xx/include/soc/cpu.h b/src/soc/cavium/cn81xx/include/soc/cpu.h
index e4ee99b..3720750 100644
--- a/src/soc/cavium/cn81xx/include/soc/cpu.h
+++ b/src/soc/cavium/cn81xx/include/soc/cpu.h
@@ -9,6 +9,59 @@
#ifndef __SOC_CAVIUM_CN81XX_CPU_H__
#define __SOC_CAVIUM_CN81XX_CPU_H__
-size_t cpu_get_num_cores(void);
+/**
+ * Number of the Core on which the program is currently running.
+ *
+ * @return Number of cores
+ */
+size_t cpu_self_get_core_id(void);
+
+/**
+ * Return a mask representing this core in a 64bit bitmask
+ *
+ * @return The mask of active core.
+ */
+uint64_t cpu_self_get_core_mask(void);
+
+/**
+ * Return the mask of available cores.
+ *
+ * @return Mask of available cores
+ */
+uint64_t cpu_get_available_core_mask(void);
+
+/**
+ * Return the number of cores available in the chip.
+ *
+ * @return The number of available cores.
+ */
+size_t cpu_get_num_available_cores(void);
+
+/**
+ * Init secondary cores and call the provided entry for given core.
+ * A stack of size 0x1000 is set up for each core in REGION stack_sec.
+ * The unique core id is passed to the entry point functions.
+ *
+ * @return zero on success
+ */
+size_t start_cpu(size_t cpu, void (* entry_64)(size_t core_id));
+
+/**
+ * Secondary ASM CPU entry point.
+ * For internal use only.
+ */
+void secondary_init(void);
+
+/**
+ * Secondary CPU C entry point.
+ * For internal use only.
+ */
+void secondary_cpu_init(size_t core_id);
+
+/* Symbols in memlayout.ld */
+
+extern u8 _stack_sec[];
+extern u8 _estack_sec[];
+#define _stack_sec_size (_estack_sec - _stack_sec)
#endif /* __SOC_CAVIUM_CN81XX_CPU_H__ */
diff --git a/src/soc/cavium/cn81xx/include/soc/memlayout.ld b/src/soc/cavium/cn81xx/include/soc/memlayout.ld
index e4a71eb..96acb3f 100644
--- a/src/soc/cavium/cn81xx/include/soc/memlayout.ld
+++ b/src/soc/cavium/cn81xx/include/soc/memlayout.ld
@@ -38,6 +38,9 @@
SRAM_END(BOOTROM_OFFSET + 0x80000)
TTB(BOOTROM_OFFSET + 0x80000, 128K)
RAMSTAGE(BOOTROM_OFFSET + 0xa0000, 512K)
+ /* Stack for secondary CPUs */
+ REGION(stack_sec, BOOTROM_OFFSET + 0x120000,
+ CONFIG_MAX_CPUS * CONFIG_STACK_SIZE, 0x1000)
/* Leave some space for the payload */
POSTRAM_CBFS_CACHE(0x2000000, 16M)
diff --git a/src/soc/cavium/cn81xx/soc.c b/src/soc/cavium/cn81xx/soc.c
index 3471ce2..1c79226 100644
--- a/src/soc/cavium/cn81xx/soc.c
+++ b/src/soc/cavium/cn81xx/soc.c
@@ -83,9 +83,12 @@
}
static struct device_operations soc_ops = {
- .read_resources = soc_read_resources,
- .init = soc_init,
- .final = soc_final,
+ .read_resources = soc_read_resources,
+ .set_resources = DEVICE_NOOP,
+ .enable_resources = DEVICE_NOOP,
+ .init = soc_init,
+ .final = soc_final,
+ .scan_bus = NULL,
};
static void enable_soc_dev(device_t dev)
@@ -93,7 +96,8 @@
if (dev->path.type == DEVICE_PATH_DOMAIN &&
dev->path.domain.domain == 0) {
dev->ops = &pci_domain_ops_ecam0;
- }
+ } else if (dev->path.type == DEVICE_PATH_CPU_CLUSTER)
+ dev->ops = &soc_ops;
}
struct chip_operations soc_cavium_cn81xx_ops = {
diff --git a/src/soc/cavium/common/Makefile.inc b/src/soc/cavium/common/Makefile.inc
index 1c959e3..5e49755 100644
--- a/src/soc/cavium/common/Makefile.inc
+++ b/src/soc/cavium/common/Makefile.inc
@@ -15,7 +15,7 @@
ifeq ($(CONFIG_SOC_CAVIUM_COMMON),y)
-CFLAGS_arm64 += -Wstack-usage=8192
+CFLAGS_arm64 += -Wstack-usage=$(CONFIG_STACK_SIZE)
bootblock-$(CONFIG_BOOTBLOCK_CUSTOM) += bootblock.c
--
To view, visit https://review.coreboot.org/25752
To unsubscribe, or for help writing mail filters, visit https://review.coreboot.org/settings
Gerrit-Project: coreboot
Gerrit-Branch: master
Gerrit-MessageType: newchange
Gerrit-Change-Id: I07428161615bcd3d03a3eea0df2dd813e08c8f66
Gerrit-Change-Number: 25752
Gerrit-PatchSet: 1
Gerrit-Owner: Patrick Rudolph <patrick.rudolph at 9elements.com>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.coreboot.org/pipermail/coreboot-gerrit/attachments/20180420/8609e487/attachment-0001.html>
More information about the coreboot-gerrit
mailing list