Patrick Georgi (pgeorgi(a)google.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/9542
-gerrit
commit f26ce871695d023a0e1ce4f2903cbc89123510c1
Author: Joseph Lo <josephl(a)nvidia.com>
Date: Fri Nov 21 08:54:15 2014 +0800
tegra132: psci: add cpu_on/off support
The CPU on/off functions are the method for the Kernel to support CPU
hot-plug function in PSCI. To support this, we still need flow controller
support to capture the WFI from the CPU and inform PMC to power gate the
CPU core. On the other path, we turn on the CPU by toggling the PMC and
use flow controller to let go when the power is steady.
BUG=chrome-os-partner:32136
BRANCH=None
TEST=built the kernel with PSCI enabled,
check both of the CPUs are coming up,
test the CPU hot-plug is working on Ryu
Change-Id: If2c529b6719c5747d5aea95fb5049b2d7353ff17
Signed-off-by: Patrick Georgi <pgeorgi(a)chromium.org>
Original-Commit-Id: 0f078e89daad1c4d8b342a395f36b3e922af66f5
Original-Change-Id: Ie49940adb2966dcc9967d2fcc9b1e0dcd6d98743
Original-Signed-off-by: Joseph Lo <josephl(a)nvidia.com>
Original-Reviewed-on: https://chromium-review.googlesource.com/231267
Original-Reviewed-by: Aaron Durbin <adurbin(a)chromium.org>
---
src/soc/nvidia/tegra132/Makefile.inc | 2 +
src/soc/nvidia/tegra132/flow_ctrl.c | 96 +++++++++++++++++++++++++
src/soc/nvidia/tegra132/include/soc/flow_ctrl.h | 26 +++++++
src/soc/nvidia/tegra132/psci.c | 75 ++++++++++++++++++-
4 files changed, 197 insertions(+), 2 deletions(-)
diff --git a/src/soc/nvidia/tegra132/Makefile.inc b/src/soc/nvidia/tegra132/Makefile.inc
index a46a2e5..fc22b2a 100644
--- a/src/soc/nvidia/tegra132/Makefile.inc
+++ b/src/soc/nvidia/tegra132/Makefile.inc
@@ -97,6 +97,8 @@ ramstage-$(CONFIG_ARCH_USE_SECURE_MONITOR) += secmon.c
secmon-$(CONFIG_ARCH_USE_SECURE_MONITOR) += 32bit_reset.S
secmon-$(CONFIG_ARCH_USE_SECURE_MONITOR) += cpu.c
secmon-$(CONFIG_ARCH_USE_SECURE_MONITOR) += cpu_lib.S
+secmon-$(CONFIG_ARCH_USE_SECURE_MONITOR) += flow_ctrl.c
+secmon-$(CONFIG_ARCH_USE_SECURE_MONITOR) += power.c
secmon-$(CONFIG_ARCH_USE_SECURE_MONITOR) += psci.c
secmon-$(CONFIG_ARCH_USE_SECURE_MONITOR) += uart.c
diff --git a/src/soc/nvidia/tegra132/flow_ctrl.c b/src/soc/nvidia/tegra132/flow_ctrl.c
new file mode 100644
index 0000000..4da54b1
--- /dev/null
+++ b/src/soc/nvidia/tegra132/flow_ctrl.c
@@ -0,0 +1,96 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <arch/io.h>
+#include <soc/addressmap.h>
+#include <soc/flow_ctrl.h>
+
+#define FLOW_CTRL_HALT_CPU0_EVENTS 0x0
+#define FLOW_CTRL_WAITEVENT (2 << 29)
+#define FLOW_CTRL_WAIT_FOR_INTERRUPT (4 << 29)
+#define FLOW_CTRL_HALT_LIC_IRQ (1 << 11)
+#define FLOW_CTRL_HALT_LIC_FIQ (1 << 10)
+#define FLOW_CTRL_CPU0_CSR 0x8
+#define FLOW_CTRL_CSR_INTR_FLAG (1 << 15)
+#define FLOW_CTRL_CSR_EVENT_FLAG (1 << 14)
+#define FLOW_CTRL_CSR_WFI_CPU0 (1 << 8)
+#define FLOW_CTRL_CSR_WFI_BITMAP (0xF << 8)
+#define FLOW_CTRL_CSR_WFE_BITMAP (0xF << 4)
+#define FLOW_CTRL_CSR_ENABLE (1 << 0)
+#define FLOW_CTRL_HALT_CPU1_EVENTS 0x14
+#define FLOW_CTRL_CPU1_CSR 0x18
+
+#define HALT_REG_CORE0 (\
+ FLOW_CTRL_WAIT_FOR_INTERRUPT | \
+ FLOW_CTRL_HALT_LIC_IRQ | \
+ FLOW_CTRL_HALT_LIC_FIQ)
+
+#define HALT_REG_CORE1 FLOW_CTRL_WAITEVENT
+
+static void *tegra_flowctrl_base = (void*)TEGRA_FLOW_BASE;
+
+static const uint8_t flowctrl_offset_halt_cpu[] = {
+ FLOW_CTRL_HALT_CPU0_EVENTS,
+ FLOW_CTRL_HALT_CPU1_EVENTS
+};
+
+static const uint8_t flowctrl_offset_cpu_csr[] = {
+ FLOW_CTRL_CPU0_CSR,
+ FLOW_CTRL_CPU1_CSR
+};
+
+static uint32_t flowctrl_read_cpu_csr(int cpu)
+{
+ return read32(tegra_flowctrl_base + flowctrl_offset_cpu_csr[cpu]);
+}
+
+static void flowctrl_write_cpu_csr(int cpu, uint32_t val)
+{
+ write32(val, tegra_flowctrl_base + flowctrl_offset_cpu_csr[cpu]);
+ val = readl(tegra_flowctrl_base + flowctrl_offset_cpu_csr[cpu]);
+}
+
+void flowctrl_write_cpu_halt(int cpu, uint32_t val)
+{
+ writel(val, tegra_flowctrl_base + flowctrl_offset_halt_cpu[cpu]);
+ val = readl(tegra_flowctrl_base + flowctrl_offset_halt_cpu[cpu]);
+}
+
+static void flowctrl_prepare_cpu_off(int cpu)
+{
+ uint32_t reg;
+
+ reg = flowctrl_read_cpu_csr(cpu);
+ reg &= ~FLOW_CTRL_CSR_WFE_BITMAP; /* clear wfe bitmap */
+ reg &= ~FLOW_CTRL_CSR_WFI_BITMAP; /* clear wfi bitmap */
+ reg |= FLOW_CTRL_CSR_INTR_FLAG; /* clear intr flag */
+ reg |= FLOW_CTRL_CSR_EVENT_FLAG; /* clear event flag */
+ reg |= FLOW_CTRL_CSR_WFI_CPU0 << cpu; /* power gating on wfi */
+ reg |= FLOW_CTRL_CSR_ENABLE; /* enable power gating */
+ flowctrl_write_cpu_csr(cpu, reg);
+}
+
+void flowctrl_cpu_off(int cpu)
+{
+ uint32_t reg;
+
+ reg = cpu ? HALT_REG_CORE1 : HALT_REG_CORE0;
+ flowctrl_prepare_cpu_off(cpu);
+ flowctrl_write_cpu_halt(cpu, reg);
+}
diff --git a/src/soc/nvidia/tegra132/include/soc/flow_ctrl.h b/src/soc/nvidia/tegra132/include/soc/flow_ctrl.h
new file mode 100644
index 0000000..28fe846
--- /dev/null
+++ b/src/soc/nvidia/tegra132/include/soc/flow_ctrl.h
@@ -0,0 +1,26 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef _TEGRA132_FLOW_CTRL_H_
+#define _TEGRA132_FLOW_CTRL_H_
+
+void flowctrl_cpu_off(int cpu);
+void flowctrl_write_cpu_halt(int cpu, uint32_t val);
+
+#endif
diff --git a/src/soc/nvidia/tegra132/psci.c b/src/soc/nvidia/tegra132/psci.c
index b075ffc..4525f98 100644
--- a/src/soc/nvidia/tegra132/psci.c
+++ b/src/soc/nvidia/tegra132/psci.c
@@ -17,8 +17,16 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA
*/
+#include <arch/cpu.h>
+#include <arch/io.h>
#include <arch/psci.h>
+#include <soc/addressmap.h>
+#include <soc/clk_rst.h>
#include <soc/cpu.h>
+#include <soc/flow_ctrl.h>
+#include <soc/power.h>
+
+#include <console/console.h>
static void *cpu_on_entry_point;
@@ -57,14 +65,77 @@ static size_t children_at_level(int parent_level, uint64_t mpidr)
}
}
+#define TEGRA132_PM_CORE_C7 0x3
+
+static inline void tegra132_enter_sleep(unsigned long pmstate)
+{
+ asm volatile(
+ " isb\n"
+ " msr actlr_el1, %0\n"
+ " wfi\n"
+ :
+ : "r" (pmstate));
+}
+
+static void prepare_cpu_on(int cpu)
+{
+ uint32_t partid;
+
+ partid = cpu ? POWER_PARTID_CE1 : POWER_PARTID_CE0;
+
+ power_ungate_partition(partid);
+ flowctrl_write_cpu_halt(cpu, 0);
+}
+
static int cmd_prepare(struct psci_cmd *cmd)
{
- return PSCI_RET_NOT_SUPPORTED;
+ int ret;
+
+ switch (cmd->type) {
+ case PSCI_CMD_ON:
+ prepare_cpu_on(cmd->target->cpu_state.ci->id);
+ ret = PSCI_RET_SUCCESS;
+ break;
+ case PSCI_CMD_OFF:
+ if (cmd->state_id != -1) {
+ ret = PSCI_RET_INVALID_PARAMETERS;
+ break;
+ }
+ cmd->state_id = TEGRA132_PM_CORE_C7;
+ ret = PSCI_RET_SUCCESS;
+ break;
+ default:
+ ret = PSCI_RET_NOT_SUPPORTED;
+ break;
+ }
+ return ret;
}
static int cmd_commit(struct psci_cmd *cmd)
{
- return PSCI_RET_NOT_SUPPORTED;
+ int ret;
+ struct cpu_info *ci;
+
+ ci = cmd->target->cpu_state.ci;
+
+ switch (cmd->type) {
+ case PSCI_CMD_ON:
+ /* Take CPU out of reset */
+ start_cpu_silent(ci->id, cpu_on_entry_point);
+ ret = PSCI_RET_SUCCESS;
+ break;
+ case PSCI_CMD_OFF:
+ flowctrl_cpu_off(ci->id);
+ tegra132_enter_sleep(cmd->state_id);
+ /* Never reach here */
+ ret = PSCI_RET_NOT_SUPPORTED;
+ printk(BIOS_ERR, "t132 CPU%d PSCI_CMD_OFF fail\n", ci->id);
+ break;
+ default:
+ ret = PSCI_RET_NOT_SUPPORTED;
+ break;
+ }
+ return ret;
}
struct psci_soc_ops soc_psci_ops = {
Patrick Georgi (pgeorgi(a)google.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/9541
-gerrit
commit 2d4e6ab4370b68d19eba50fa3283ce711bb3d5bb
Author: Furquan Shaikh <furquan(a)google.com>
Date: Fri Nov 21 15:54:39 2014 -0800
arm64: No need of invalidating cache line for secondary CPU stack
With support for initializing registers based on values saved by primary CPU, we
no longer need to invalidate secondary CPU stack cache lines. Before jumping to
C environment, we enable caching and update the required registers.
BUG=chrome-os-partner:33962
BRANCH=None
TEST=Compiles and boots both CPU0 and CPU1 on ryu.
Change-Id: Ifee36302b5de25b909b4570a30ada8ecd742ab82
Signed-off-by: Patrick Georgi <pgeorgi(a)chromium.org>
Original-Commit-Id: 0a0403d06b89dae30b7520747501b0521d16a6db
Original-Signed-off-by: Furquan Shaikh <furquan(a)google.com>
Original-Change-Id: I738250f948e912725264cba3e389602af7510e3e
Original-Reviewed-on: https://chromium-review.googlesource.com/231563
Original-Reviewed-by: Aaron Durbin <adurbin(a)chromium.org>
Original-Tested-by: Furquan Shaikh <furquan(a)chromium.org>
Original-Commit-Queue: Furquan Shaikh <furquan(a)chromium.org>
---
src/arch/arm64/cpu_ramstage.c | 10 ----------
1 file changed, 10 deletions(-)
diff --git a/src/arch/arm64/cpu_ramstage.c b/src/arch/arm64/cpu_ramstage.c
index e6d0e8c..466ca01 100644
--- a/src/arch/arm64/cpu_ramstage.c
+++ b/src/arch/arm64/cpu_ramstage.c
@@ -151,13 +151,6 @@ static void init_cpu_info(struct bus *bus)
}
}
-static void invalidate_cpu_stack_top(unsigned int id)
-{
- const size_t size = 128;
- char *stack = cpu_get_stack(id);
- dcache_invalidate_by_mva(stack - size, size);
-}
-
void arch_initialize_cpus(device_t cluster, struct cpu_control_ops *cntrl_ops)
{
size_t max_cpus;
@@ -221,9 +214,6 @@ void arch_initialize_cpus(device_t cluster, struct cpu_control_ops *cntrl_ops)
/* Start the CPU. */
printk(BIOS_DEBUG, "Starting CPU%x\n", ci->id);
- /* Ensure CPU's top of stack is not in the cache. */
- invalidate_cpu_stack_top(ci->id);
-
if (cntrl_ops->start_cpu(ci->id, entry)) {
printk(BIOS_ERR,
"Failed to start CPU%x\n", ci->id);
Patrick Georgi (pgeorgi(a)google.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/9540
-gerrit
commit 6c93417c9a097da54e67f08b5469e38383018c5b
Author: Furquan Shaikh <furquan(a)google.com>
Date: Fri Nov 21 15:42:40 2014 -0800
arm64: Add support for save/restore registers for CPU startup.
startup.c provides function to enable CPU in any stage to save register data
that can be used by secondary CPU (for normal boot) or any CPU (for resume
boot). stage_entry.S defines space for saving arm64_startup_data. This can be
filled by:
1) Primary CPU before bringing up secondary CPUs so that the secondary can use
register values to initialize MMU-related and other required registers to
appropriate values.
2) CPU suspend path to ensure that on resume the values which were saved are
restored appropriately.
stage_entry.S provides a common path for both normal and resume boot to
initialize saved registers. For resume path, it is important to set the
secondary entry point for startup since x26 needs to be 1 for enabling MMU and
cache.
This also ensures that we do not fall into false memory cache errors which
caused CPU to fail during normal / resume boot. Thus, we can get rid of the
stack cache invalidate for secondary CPUs.
BUG=chrome-os-partner:33962
BRANCH=None
TEST=Compiles and boots both CPU0 and CPU1 on ryu without mmu_enable and stack
cache invalidate for CPU1.
Change-Id: Ia4ca0e7d35c0738dbbaa926cce4268143c6f9de3
Signed-off-by: Patrick Georgi <pgeorgi(a)chromium.org>
Original-Commit-Id: 9f5e78469313ddd144ad7cf5abc3e07cb712183a
Original-Signed-off-by: Furquan Shaikh <furquan(a)google.com>
Original-Change-Id: I527a95779cf3fed37392b6605b096f54f8286d64
Original-Reviewed-on: https://chromium-review.googlesource.com/231561
Original-Reviewed-by: Aaron Durbin <adurbin(a)chromium.org>
Original-Tested-by: Furquan Shaikh <furquan(a)chromium.org>
Original-Commit-Queue: Furquan Shaikh <furquan(a)chromium.org>
---
src/arch/arm64/Makefile.inc | 2 +
src/arch/arm64/armv8/secmon/secmon_init.c | 40 ++--------------
src/arch/arm64/c_entry.c | 17 ++-----
src/arch/arm64/cpu_ramstage.c | 14 ++++--
src/arch/arm64/include/arch/startup.h | 46 ++++++++++++++++++
src/arch/arm64/include/armv8/arch/cpu.h | 11 +++++
src/arch/arm64/stage_entry.S | 78 ++++++++++++++++++++++++++++---
src/arch/arm64/startup.c | 54 +++++++++++++++++++++
8 files changed, 201 insertions(+), 61 deletions(-)
diff --git a/src/arch/arm64/Makefile.inc b/src/arch/arm64/Makefile.inc
index bb3cab5..f81e76a 100644
--- a/src/arch/arm64/Makefile.inc
+++ b/src/arch/arm64/Makefile.inc
@@ -138,6 +138,7 @@ ifeq ($(CONFIG_ARCH_RAMSTAGE_ARM64),y)
ramstage-y += c_entry.c
ramstage-y += stages.c
+ramstage-y += startup.c
ramstage-y += div0.c
ramstage-y += cpu.c
ramstage-y += cpu_ramstage.c
@@ -157,6 +158,7 @@ rmodules_arm64-y += ../../lib/memmove.c
rmodules_arm64-y += eabi_compat.c
secmon-$(CONFIG_ARCH_USE_SECURE_MONITOR) += stage_entry.S
+secmon-$(CONFIG_ARCH_USE_SECURE_MONITOR) += startup.c
secmon-$(CONFIG_ARCH_USE_SECURE_MONITOR) += ../../lib/malloc.c
secmon-$(CONFIG_ARCH_USE_SECURE_MONITOR) += ../../lib/memset.c
secmon-$(CONFIG_ARCH_USE_SECURE_MONITOR) += ../../lib/memcmp.c
diff --git a/src/arch/arm64/armv8/secmon/secmon_init.c b/src/arch/arm64/armv8/secmon/secmon_init.c
index 63bd490..7d7f8bb 100644
--- a/src/arch/arm64/armv8/secmon/secmon_init.c
+++ b/src/arch/arm64/armv8/secmon/secmon_init.c
@@ -27,20 +27,11 @@
#include <arch/psci.h>
#include <arch/secmon.h>
#include <arch/smc.h>
+#include <arch/startup.h>
#include <console/console.h>
#include <stddef.h>
#include "secmon.h"
-/* Common CPU state for all CPUs running in secmon. */
-struct cpu_resume_data {
- uint64_t mair;
- uint64_t tcr;
- uint64_t ttbr0;
- uint64_t scr;
-};
-
-static struct cpu_resume_data resume_data;
-
static void secmon_init(struct secmon_params *params, int bsp);
static void secmon_init_bsp(void *arg)
@@ -61,27 +52,6 @@ void (*c_entry[2])(void *) = { &secmon_init_bsp, &secmon_init_nonbsp };
static void cpu_resume(void *unused)
{
- uint32_t sctlr;
-
- /* Re-enable exception vector. */
- exception_hwinit();
-
- tlbiall_el3();
- raw_write_mair_el3(resume_data.mair);
- raw_write_tcr_el3(resume_data.tcr);
- raw_write_ttbr0_el3(resume_data.ttbr0);
- dsb();
- isb();
-
- /* Enable MMU */
- sctlr = raw_read_sctlr_el3();
- sctlr |= SCTLR_C | SCTLR_M | SCTLR_I;
- raw_write_sctlr_el3(sctlr);
- isb();
-
- raw_write_scr_el3(resume_data.scr);
- isb();
-
psci_cpu_entry();
}
@@ -92,11 +62,7 @@ static void cpu_resume_init(void)
dcache_clean_by_mva(&c_entry, sizeof(c_entry));
/* Back up state. */
- resume_data.mair = raw_read_mair_el3();
- resume_data.tcr = raw_read_tcr_el3();
- resume_data.ttbr0 = raw_read_ttbr0_el3();
- resume_data.scr = raw_read_scr_el3();
- dcache_clean_by_mva(&resume_data, sizeof(resume_data));
+ startup_save_cpu_data();
}
static void start_up_cpu(void *arg)
@@ -150,7 +116,7 @@ static void secmon_init(struct secmon_params *params, int bsp)
wait_for_all_cpus(params->online_cpus);
smc_init();
- psci_init((uintptr_t)arm64_cpu_startup);
+ psci_init((uintptr_t)arm64_cpu_startup_resume);
/* Initialize the resume path. */
cpu_resume_init();
diff --git a/src/arch/arm64/c_entry.c b/src/arch/arm64/c_entry.c
index de8ebcd..bf7a335 100644
--- a/src/arch/arm64/c_entry.c
+++ b/src/arch/arm64/c_entry.c
@@ -19,9 +19,9 @@
#include <arch/cache.h>
#include <arch/cpu.h>
-#include <arch/exception.h>
#include <arch/mmu.h>
#include <arch/stages.h>
+#include <arch/startup.h>
#include "cpu-internal.h"
void __attribute__((weak)) arm64_soc_init(void)
@@ -55,22 +55,15 @@ static void arm64_init(void)
main();
}
-static void secondary_cpu_start(void)
-{
- mmu_enable();
- exception_hwinit();
-
- /* This will never return. */
- arch_secondary_cpu_init();
-}
-
/*
* This variable holds entry point for CPUs starting up. The first
* element is the BSP path, and the second is the non-BSP path.
*/
-void (*c_entry[2])(void) = { &arm64_init, &secondary_cpu_start };
+void (*c_entry[2])(void) = { &arm64_init, &arch_secondary_cpu_init };
void *prepare_secondary_cpu_startup(void)
{
- return secondary_entry_point(&arm64_cpu_startup);
+ startup_save_cpu_data();
+
+ return secondary_entry_point(&arm64_cpu_startup_resume);
}
diff --git a/src/arch/arm64/cpu_ramstage.c b/src/arch/arm64/cpu_ramstage.c
index ec1ac0f..e6d0e8c 100644
--- a/src/arch/arm64/cpu_ramstage.c
+++ b/src/arch/arm64/cpu_ramstage.c
@@ -109,8 +109,6 @@ static void init_this_cpu(void *arg)
printk(BIOS_DEBUG, "CPU%x: MPIDR: %llx\n", ci->id, ci->mpidr);
- el3_init();
-
/* Initialize the GIC. */
gic_init();
@@ -151,9 +149,6 @@ static void init_cpu_info(struct bus *bus)
ci->cpu = cur;
ci->id = cur->path.cpu.id;
}
-
- /* Mark current cpu online. */
- cpu_mark_online(cpu_info());
}
static void invalidate_cpu_stack_top(unsigned int id)
@@ -184,6 +179,15 @@ void arch_initialize_cpus(device_t cluster, struct cpu_control_ops *cntrl_ops)
if (bus == NULL)
return;
+ /*
+ * el3_init must be performed prior to prepare_secondary_cpu_startup.
+ * This is important since el3_init initializes SCR values on BSP CPU
+ * and then prepare_secondary_cpu_startup reads the initialized SCR
+ * value and saves it for use by non-BSP CPUs.
+ */
+ el3_init();
+ /* Mark current cpu online. */
+ cpu_mark_online(cpu_info());
entry = prepare_secondary_cpu_startup();
/* Initialize the cpu_info structures. */
diff --git a/src/arch/arm64/include/arch/startup.h b/src/arch/arm64/include/arch/startup.h
new file mode 100644
index 0000000..bb3a863
--- /dev/null
+++ b/src/arch/arm64/include/arch/startup.h
@@ -0,0 +1,46 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2014 Google 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ */
+
+#ifndef __ARCH_ARM64_INCLUDE_ARCH_STARTUP_H__
+#define __ARCH_ARM64_INCLUDE_ARCH_STARTUP_H__
+
+/* Every element occupies 8 bytes (64-bit entries) */
+#define PER_ELEMENT_SIZE_BYTES 8
+#define MAIR_INDEX 0
+#define TCR_INDEX 1
+#define TTBR0_INDEX 2
+#define SCR_INDEX 3
+#define VBAR_INDEX 4
+/* IMPORTANT!!! If any new element is added please update NUM_ELEMENTS */
+#define NUM_ELEMENTS 5
+
+#ifndef __ASSEMBLY__
+
+/*
+ * startup_save_cpu_data is used to save register values that need to be setup
+ * when a CPU starts booting. This is used by secondary CPUs as well as resume
+ * path to directly setup MMU and other related registers.
+ */
+void startup_save_cpu_data(void);
+
+#endif
+
+#endif /* __ARCH_ARM64_INCLUDE_ARCH_STARTUP_H__ */
diff --git a/src/arch/arm64/include/armv8/arch/cpu.h b/src/arch/arm64/include/armv8/arch/cpu.h
index d968a06..34220d9 100644
--- a/src/arch/arm64/include/armv8/arch/cpu.h
+++ b/src/arch/arm64/include/armv8/arch/cpu.h
@@ -170,4 +170,15 @@ static inline void *secondary_entry_point(void *e)
*/
void arm64_cpu_startup(void);
+/*
+ * The arm64_cpu_startup_resume() initializes a CPU's exception stack and
+ * regular stack as well initializing the C environment for the processor. It
+ * calls into the array of function pointers at symbol c_entry depending
+ * on BSP state. Note that arm64_cpu_startup contains secondary entry
+ * point which can be obtained by secondary_entry_point().
+ * Additionally, it also restores saved register data and enables MMU, caches
+ * and exceptions before jumping to C environment for both BSP and non-BSP CPUs.
+ */
+void arm64_cpu_startup_resume(void);
+
#endif /* __ARCH_CPU_H__ */
diff --git a/src/arch/arm64/stage_entry.S b/src/arch/arm64/stage_entry.S
index 5a5ddab..fa2064e 100644
--- a/src/arch/arm64/stage_entry.S
+++ b/src/arch/arm64/stage_entry.S
@@ -29,6 +29,7 @@
#include <arch/asm.h>
#define __ASSEMBLY__
#include <arch/lib_helpers.h>
+#include <arch/startup.h>
#define STACK_SZ CONFIG_STACK_SIZE
#define EXCEPTION_STACK_SZ CONFIG_STACK_SIZE
@@ -38,6 +39,12 @@
* according to MAX_CPUS. Additionally provide exception stacks for each CPU.
*/
.section .bss, "aw", @nobits
+
+.global _arm64_startup_data
+.balign 8
+_arm64_startup_data:
+.space NUM_ELEMENTS*PER_ELEMENT_SIZE_BYTES
+
.global _stack
.global _estack
.balign STACK_SZ
@@ -136,23 +143,80 @@ ENTRY(__rmodule_entry)
b arm64_c_environment
ENDPROC(__rmodule_entry)
-ENTRY(_arm64_cpu_startup)
+/*
+ * Setup SCTLR so that:
+ * Little endian mode is setup, XN is not enforced, MMU and caches are disabled.
+ * Alignment and stack alignment checks are disabled.
+ */
+.macro setup_sctlr
read_current x0, sctlr
bic x0, x0, #(1 << 25) /* Little Endian */
bic x0, x0, #(1 << 19) /* XN not enforced */
bic x0, x0, #(1 << 12) /* Disable Instruction Cache */
- bic x0, x0, #0xf /* Clear SA, C, A, and M */
+ bic x0, x0, #0xf /* Clear SA, C, A and M */
+ write_current sctlr, x0, x1
+.endm
+
+/*
+ * This macro assumes x2 has base address and returns value read in x0
+ * x1 is used as temporary register.
+ */
+.macro get_element_addr index
+ add x1, x2, #(\index * PER_ELEMENT_SIZE_BYTES)
+ ldr x0, [x1]
+.endm
+
+/*
+ * Uses following registers:
+ * x0 = reading stored value
+ * x1 = temp reg
+ * x2 = base address of saved data region
+ */
+.macro startup_restore
+ adr x2, _arm64_startup_data
+
+ get_element_addr MAIR_INDEX
+ write_current mair, x0, x1
+
+ get_element_addr TCR_INDEX
+ write_current tcr, x0, x1
+
+ get_element_addr TTBR0_INDEX
+ write_current ttbr0, x0, x1
+
+ get_element_addr SCR_INDEX
+ write_el3 scr, x0, x1
+
+ get_element_addr VBAR_INDEX
+ write_current vbar, x0, x1
+
+ dsb sy
+ isb
+
+ tlbiall_current x1
+ read_current x0, sctlr
+ orr x0, x0, #(1 << 12) /* Enable Instruction Cache */
+ orr x0, x0, #(1 << 2) /* Enable Data/Unified Cache */
+ orr x0, x0, #(1 << 0) /* Enable MMU */
write_current sctlr, x0, x1
+
+ dsb sy
isb
- b arm64_c_environment
-ENDPROC(_arm64_cpu_startup)
+.endm
CPU_RESET_ENTRY(arm64_cpu_startup)
split_bsp_path
- b _arm64_cpu_startup
+ setup_sctlr
+ b arm64_c_environment
ENDPROC(arm64_cpu_startup)
-ENTRY(stage_entry)
+CPU_RESET_ENTRY(arm64_cpu_startup_resume)
split_bsp_path
- b _arm64_cpu_startup
+ setup_sctlr
+ startup_restore
+ b arm64_c_environment
+ENDPROC(arm64_cpu_startup_resume)
+
+ENTRY(stage_entry)
+ b arm64_cpu_startup
ENDPROC(stage_entry)
diff --git a/src/arch/arm64/startup.c b/src/arch/arm64/startup.c
new file mode 100644
index 0000000..d2b7691
--- /dev/null
+++ b/src/arch/arm64/startup.c
@@ -0,0 +1,54 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2014 Google 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ */
+
+#include <arch/cache.h>
+#include <arch/lib_helpers.h>
+#include <arch/startup.h>
+#include <console/console.h>
+
+/* This space is defined in stage_entry.S. */
+extern u8 _arm64_startup_data[];
+
+static inline void save_element(size_t index, uint64_t val)
+{
+ uint64_t *ptr = (uint64_t *)_arm64_startup_data;
+
+ ptr[index] = val;
+}
+
+/*
+ * startup_save_cpu_data is used to save register values that need to be setup
+ * when a CPU starts booting. This is used by secondary CPUs as well as resume
+ * path to directly setup MMU and other related registers.
+ */
+void startup_save_cpu_data(void)
+{
+ save_element(MAIR_INDEX, raw_read_mair_current());
+ save_element(TCR_INDEX, raw_read_tcr_current());
+ save_element(TTBR0_INDEX, raw_read_ttbr0_current());
+ save_element(VBAR_INDEX, raw_read_vbar_current());
+
+ if (get_current_el() == EL3)
+ save_element(SCR_INDEX, raw_read_scr_el3());
+
+ dcache_clean_by_mva(_arm64_startup_data,
+ NUM_ELEMENTS * PER_ELEMENT_SIZE_BYTES);
+}
Patrick Georgi (pgeorgi(a)google.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/9538
-gerrit
commit 48e75775453d4552770c06061153bb9467afb99d
Author: Furquan Shaikh <furquan(a)google.com>
Date: Fri Nov 21 15:35:17 2014 -0800
arm64: Add conditional read/write from/to EL3 assembly macros.
Some registers are available only at EL3. Add conditional read/write functions
that perform operations only if currently we are in EL3.
BUG=chrome-os-partner:33962
BRANCH=None
TEST=Compiles and boots to kernel prompt.
Change-Id: Ic95838d10e18f58867b6b77aee937bdacae50597
Signed-off-by: Patrick Georgi <pgeorgi(a)chromium.org>
Original-Commit-Id: 62a0e324a00248dba92cb3e2ac2f4072d0e4e2a7
Original-Signed-off-by: Furquan Shaikh <furquan(a)google.com>
Original-Change-Id: Ia170d94adb9ecc141ff86e4a3041ddbf9045bc89
Original-Reviewed-on: https://chromium-review.googlesource.com/231549
Original-Reviewed-by: Aaron Durbin <adurbin(a)chromium.org>
Original-Tested-by: Furquan Shaikh <furquan(a)chromium.org>
Original-Commit-Queue: Furquan Shaikh <furquan(a)chromium.org>
---
src/arch/arm64/include/armv8/arch/lib_helpers.h | 25 +++++++++++++++++++++++++
1 file changed, 25 insertions(+)
diff --git a/src/arch/arm64/include/armv8/arch/lib_helpers.h b/src/arch/arm64/include/armv8/arch/lib_helpers.h
index a804747..422b81a 100644
--- a/src/arch/arm64/include/armv8/arch/lib_helpers.h
+++ b/src/arch/arm64/include/armv8/arch/lib_helpers.h
@@ -214,6 +214,31 @@
104:
.endm
+/* Macro to read from a register at EL3 only if we are currently at that
+ level. This is required to ensure that we do not attempt to read registers
+ from a level lower than el3. e.g. SCR is available for read only at EL3.
+ IMPORTANT: if EL != EL3, macro silently doesn't perform the read.
+*/
+.macro read_el3 xreg sysreg
+ switch_el \xreg, 402f, 402f, 401f
+401:
+ mrs \xreg, \sysreg\()_el3
+402:
+.endm
+
+/* Macro to write to a register at EL3 only if we are currently at that
+ level. This is required to ensure that we do not attempt to write to
+ registers from a level lower than el3. e.g. SCR is available to write only at
+ EL3.
+ IMPORTANT: if EL != EL3, macro silently doesn't perform the write.
+*/
+.macro write_el3 sysreg xreg temp
+ switch_el \temp, 402f, 402f, 401f
+401:
+ msr \sysreg\()_el3, \xreg
+402:
+.endm
+
#else
#include <stdint.h>
Patrick Georgi (pgeorgi(a)google.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/9536
-gerrit
commit 187144bb555f71c85f06e2405604798d1fbfcc65
Author: Furquan Shaikh <furquan(a)google.com>
Date: Fri Nov 21 17:07:16 2014 -0800
tegra132: Make non-vboot2 memlayout more useful
Update non-vboot2 memlayout:
1) Add timestamp region
2) Increase ramstage size
3) Change name from memlayout_vboot.ld to memlayout.ld so that any non-vboot
upstream board can also use this layout.
BUG=None
BRANCH=None
TEST=Compiles and boots to kernel prompt on ryu with vboot selected instead of
vboot2.
Change-Id: Idced98f9df7cdbab5f62cd1e382c6046ade1d867
Signed-off-by: Patrick Georgi <pgeorgi(a)chromium.org>
Original-Commit-Id: 20fffa282b20fb32ce2ff687f4479be630f90fcf
Original-Signed-off-by: Furquan Shaikh <furquan(a)google.com>
Original-Change-Id: I91accd54efc53ab563a2063b9c6e9390f5dd527f
Original-Reviewed-on: https://chromium-review.googlesource.com/231547
Original-Reviewed-by: Aaron Durbin <adurbin(a)chromium.org>
Original-Tested-by: Furquan Shaikh <furquan(a)chromium.org>
Original-Commit-Queue: Furquan Shaikh <furquan(a)chromium.org>
---
src/mainboard/google/rush/memlayout.ld | 2 +-
src/mainboard/google/rush_ryu/memlayout.ld | 2 +-
src/soc/nvidia/tegra132/include/soc/memlayout.ld | 44 ++++++++++++++++++++++
.../nvidia/tegra132/include/soc/memlayout_vboot.ld | 43 ---------------------
4 files changed, 46 insertions(+), 45 deletions(-)
diff --git a/src/mainboard/google/rush/memlayout.ld b/src/mainboard/google/rush/memlayout.ld
index 5bd72e5..d8fdb9a 100644
--- a/src/mainboard/google/rush/memlayout.ld
+++ b/src/mainboard/google/rush/memlayout.ld
@@ -1,5 +1,5 @@
#if IS_ENABLED(CONFIG_VBOOT2_VERIFY_FIRMWARE)
#include <soc/memlayout_vboot2.ld>
#else
-#include <soc/memlayout_vboot.ld>
+#include <soc/memlayout.ld>
#endif
diff --git a/src/mainboard/google/rush_ryu/memlayout.ld b/src/mainboard/google/rush_ryu/memlayout.ld
index 5bd72e5..d8fdb9a 100644
--- a/src/mainboard/google/rush_ryu/memlayout.ld
+++ b/src/mainboard/google/rush_ryu/memlayout.ld
@@ -1,5 +1,5 @@
#if IS_ENABLED(CONFIG_VBOOT2_VERIFY_FIRMWARE)
#include <soc/memlayout_vboot2.ld>
#else
-#include <soc/memlayout_vboot.ld>
+#include <soc/memlayout.ld>
#endif
diff --git a/src/soc/nvidia/tegra132/include/soc/memlayout.ld b/src/soc/nvidia/tegra132/include/soc/memlayout.ld
new file mode 100644
index 0000000..a7e3635
--- /dev/null
+++ b/src/soc/nvidia/tegra132/include/soc/memlayout.ld
@@ -0,0 +1,44 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright 2014 Google 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <memlayout.h>
+
+#include <arch/header.ld>
+
+/*
+ * Note: The BootROM uses the address range [0x4000_0000:0x4000_E000) itself,
+ * so the bootblock loading address must be placed after that. After the
+ * handoff that area may be reclaimed for other uses, e.g. CBFS cache.
+ * TODO: Did this change on Tegra132? What's the new valid range?
+ */
+
+SECTIONS
+{
+ SRAM_START(0x40000000)
+ PRERAM_CBMEM_CONSOLE(0x40000000, 8K)
+ PRERAM_CBFS_CACHE(0x40002000, 84K)
+ STACK(0x40017000, 16K)
+ BOOTBLOCK(0x4001B800, 22K)
+ ROMSTAGE(0x40021000, 124K)
+ SRAM_END(0x40040000)
+
+ DRAM_START(0x80000000)
+ POSTRAM_CBFS_CACHE(0x80100000, 1M)
+ RAMSTAGE(0x80200000, 256K)
+}
diff --git a/src/soc/nvidia/tegra132/include/soc/memlayout_vboot.ld b/src/soc/nvidia/tegra132/include/soc/memlayout_vboot.ld
deleted file mode 100644
index c097c3c..0000000
--- a/src/soc/nvidia/tegra132/include/soc/memlayout_vboot.ld
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * This file is part of the coreboot project.
- *
- * Copyright 2014 Google 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include <memlayout.h>
-
-#include <arch/header.ld>
-
-/*
- * Note: The BootROM uses the address range [0x4000_0000:0x4000_E000) itself,
- * so the bootblock loading address must be placed after that. After the
- * handoff that area may be reclaimed for other uses, e.g. CBFS cache.
- * TODO: Did this change on Tegra132? What's the new valid range?
- */
-
-SECTIONS
-{
- SRAM_START(0x40000000)
- PRERAM_CBMEM_CONSOLE(0x40000000, 8K)
- CBFS_CACHE(0x40002000, 88K)
- STACK(0x40018000, 16K)
- BOOTBLOCK(0x4001C000, 20K)
- ROMSTAGE(0x40021000, 124K)
- SRAM_END(0x40040000)
-
- DRAM_START(0x80000000)
- RAMSTAGE(0x80200000, 192K)
-}