[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