From a9bec67dfda087ac739a29cbc4eb4ccb38da3e45 Mon Sep 17 00:00:00 2001
From: Sandrine Bailleux <sandrine.bailleux@arm.com>
Date: Fri, 30 Oct 2015 15:05:17 +0000
Subject: [PATCH] Introduce COLD_BOOT_SINGLE_CPU build option

This patch introduces a new build option named COLD_BOOT_SINGLE_CPU,
which allows platforms that only release a single CPU out of reset to
slightly optimise their cold boot code, both in terms of code size
and performance.

COLD_BOOT_SINGLE_CPU defaults to 0, which assumes that the platform
may release several CPUs out of reset. In this case, the cold reset
code needs to coordinate all CPUs via the usual primary/secondary
CPU distinction.

If a platform guarantees that only a single CPU will ever be released
out of reset, there is no need to arbitrate execution ; the notion of
primary and secondary CPUs itself no longer exists. Such platforms
may set COLD_BOOT_SINGLE_CPU to 1 in order to compile out the
primary/secondary CPU identification in the cold reset code.

All ARM standard platforms can release several CPUs out of reset
so they use COLD_BOOT_SINGLE_CPU=0. However, on CSS platforms like
Juno, bringing up more than one CPU at reset should only be attempted
when booting an EL3 payload, as it is not fully supported in the
normal boot flow.

For platforms using COLD_BOOT_SINGLE_CPU=1, the following 2 platform
APIs become optional:
  - plat_secondary_cold_boot_setup();
  - plat_is_my_cpu_primary().
The Porting Guide has been updated to reflect that.

User Guide updated as well.

Change-Id: Ic5b474e61b7aec1377d1e0b6925d17dfc376c46b
---
 Makefile                       |  5 +++++
 bl1/aarch64/bl1_entrypoint.S   |  2 +-
 bl31/aarch64/bl31_entrypoint.S |  2 +-
 docs/porting-guide.md          | 13 +++++++++++--
 docs/user-guide.md             |  9 +++++++++
 5 files changed, 27 insertions(+), 4 deletions(-)

diff --git a/Makefile b/Makefile
index 80e05fa63..0c3303f86 100644
--- a/Makefile
+++ b/Makefile
@@ -89,6 +89,9 @@ TRUSTED_BOARD_BOOT		:= 0
 PROGRAMMABLE_RESET_ADDRESS	:= 0
 # Build flag to treat usage of deprecated platform and framework APIs as error.
 ERROR_DEPRECATED		:= 0
+# By default, consider that the platform may release several CPUs out of reset.
+# The platform Makefile is free to override this value.
+COLD_BOOT_SINGLE_CPU		:= 0
 # Flag to introduce an infinite loop in BL1 just before it exits into the next
 # image. This is meant to help debugging the post-BL2 phase.
 SPIN_ON_BL1_EXIT		:= 0
@@ -357,6 +360,7 @@ $(eval $(call assert_boolean,CREATE_KEYS))
 $(eval $(call assert_boolean,SAVE_KEYS))
 $(eval $(call assert_boolean,TRUSTED_BOARD_BOOT))
 $(eval $(call assert_boolean,PROGRAMMABLE_RESET_ADDRESS))
+$(eval $(call assert_boolean,COLD_BOOT_SINGLE_CPU))
 $(eval $(call assert_boolean,PSCI_EXTENDED_STATE_ID))
 $(eval $(call assert_boolean,ERROR_DEPRECATED))
 $(eval $(call assert_boolean,ENABLE_PLAT_COMPAT))
@@ -380,6 +384,7 @@ $(eval $(call add_define,LOG_LEVEL))
 $(eval $(call add_define,USE_COHERENT_MEM))
 $(eval $(call add_define,TRUSTED_BOARD_BOOT))
 $(eval $(call add_define,PROGRAMMABLE_RESET_ADDRESS))
+$(eval $(call add_define,COLD_BOOT_SINGLE_CPU))
 $(eval $(call add_define,PSCI_EXTENDED_STATE_ID))
 $(eval $(call add_define,ERROR_DEPRECATED))
 $(eval $(call add_define,ENABLE_PLAT_COMPAT))
diff --git a/bl1/aarch64/bl1_entrypoint.S b/bl1/aarch64/bl1_entrypoint.S
index 4fc52918a..83594f218 100644
--- a/bl1/aarch64/bl1_entrypoint.S
+++ b/bl1/aarch64/bl1_entrypoint.S
@@ -51,7 +51,7 @@ func bl1_entrypoint
 	el3_entrypoint_common					\
 		_set_endian=1					\
 		_warm_boot_mailbox=!PROGRAMMABLE_RESET_ADDRESS	\
-		_secondary_cold_boot=1				\
+		_secondary_cold_boot=!COLD_BOOT_SINGLE_CPU	\
 		_init_memory=1					\
 		_init_c_runtime=1				\
 		_exception_vectors=bl1_exceptions
diff --git a/bl31/aarch64/bl31_entrypoint.S b/bl31/aarch64/bl31_entrypoint.S
index 636b1d287..45aa85dc4 100644
--- a/bl31/aarch64/bl31_entrypoint.S
+++ b/bl31/aarch64/bl31_entrypoint.S
@@ -85,7 +85,7 @@ func bl31_entrypoint
 	el3_entrypoint_common					\
 		_set_endian=1					\
 		_warm_boot_mailbox=!PROGRAMMABLE_RESET_ADDRESS	\
-		_secondary_cold_boot=1				\
+		_secondary_cold_boot=!COLD_BOOT_SINGLE_CPU	\
 		_init_memory=1					\
 		_init_c_runtime=1				\
 		_exception_vectors=runtime_exceptions
diff --git a/docs/porting-guide.md b/docs/porting-guide.md
index 82bed6b04..6c6122adf 100644
--- a/docs/porting-guide.md
+++ b/docs/porting-guide.md
@@ -459,7 +459,7 @@ type of reset nor to query the warm reset entrypoint. Therefore, implementing
 this function is not required on such platforms.
 
 
-### Function : plat_secondary_cold_boot_setup() [mandatory]
+### Function : plat_secondary_cold_boot_setup() [mandatory when COLD_BOOT_SINGLE_CPU == 0]
 
     Argument : void
 
@@ -476,8 +476,12 @@ populated.
 
 This function fulfills requirement 2 above.
 
+Note that for platforms that can't release secondary CPUs out of reset, only the
+primary CPU will execute the cold boot code. Therefore, implementing this
+function is not required on such platforms.
 
-### Function : plat_is_my_cpu_primary() [mandatory]
+
+### Function : plat_is_my_cpu_primary() [mandatory when COLD_BOOT_SINGLE_CPU == 0]
 
     Argument : void
     Return   : unsigned int
@@ -487,6 +491,11 @@ secondary CPU. A return value of zero indicates that the CPU is not the
 primary CPU, while a non-zero return value indicates that the CPU is the
 primary CPU.
 
+Note that for platforms that can't release secondary CPUs out of reset, only the
+primary CPU will execute the cold boot code. Therefore, there is no need to
+distinguish between primary and secondary CPUs and implementing this function is
+not required.
+
 
 ### Function : platform_mem_init() [mandatory]
 
diff --git a/docs/user-guide.md b/docs/user-guide.md
index 53745f0eb..f7e4f4c79 100644
--- a/docs/user-guide.md
+++ b/docs/user-guide.md
@@ -359,6 +359,15 @@ performed.
     implication for `plat_get_my_entrypoint()` platform porting interface.
     (see the [Porting Guide] for details)
 
+*   `COLD_BOOT_SINGLE_CPU`: This option indicates whether the platform may
+    release several CPUs out of reset. It can take either 0 (several CPUs may be
+    brought up) or 1 (only one CPU will ever be brought up during cold reset).
+    Default is 0. If the platform always brings up a single CPU, there is no
+    need to distinguish between primary and secondary CPUs and the boot path can
+    be optimised. The `plat_is_my_cpu_primary()` and
+    `plat_secondary_cold_boot_setup()` platform porting interfaces do not need
+    to be implemented in this case.
+
 *   `PSCI_EXTENDED_STATE_ID`: As per PSCI1.0 Specification, there are 2 formats
     possible for the PSCI power-state parameter viz original and extended
     State-ID formats. This flag if set to 1, configures the generic PSCI layer
-- 
GitLab