Tegra: assembly version of the 'plat_core_pos_by_mpidr' handler
The 'plat_core_pos_by_mpidr' handler gets called very early during boot
and the compiler generated code overwrites the caller's registers.
This patch converts the 'plat_core_pos_by_mpidr' handler into an assembly
function and uses registers x0-x3, to fix this anomaly.
Change-Id: I8d974e007a0bad039defaf77b11a180d899ead3c
Signed-off-by: Varun Wadekar <vwadekar@nvidia.com>
diff --git a/plat/nvidia/tegra/common/aarch64/tegra_helpers.S b/plat/nvidia/tegra/common/aarch64/tegra_helpers.S
index b6622c7..5f01416 100644
--- a/plat/nvidia/tegra/common/aarch64/tegra_helpers.S
+++ b/plat/nvidia/tegra/common/aarch64/tegra_helpers.S
@@ -39,6 +39,7 @@
.globl plat_crash_console_init
.globl plat_crash_console_putc
.globl plat_crash_console_flush
+ .weak plat_core_pos_by_mpidr
.globl tegra_secure_entrypoint
.globl plat_reset_handler
@@ -270,6 +271,42 @@
ret
endfunc plat_reset_handler
+ /* ------------------------------------------------------
+ * int32_t plat_core_pos_by_mpidr(u_register_t mpidr)
+ *
+ * This function implements a part of the critical
+ * interface between the psci generic layer and the
+ * platform that allows the former to query the platform
+ * to convert an MPIDR to a unique linear index. An error
+ * code (-1) is returned in case the MPIDR is invalid.
+ *
+ * Clobbers: x0-x3
+ * ------------------------------------------------------
+ */
+func plat_core_pos_by_mpidr
+ lsr x1, x0, #MPIDR_AFF0_SHIFT
+ and x1, x1, #MPIDR_AFFLVL_MASK /* core id */
+ lsr x2, x0, #MPIDR_AFF1_SHIFT
+ and x2, x2, #MPIDR_AFFLVL_MASK /* cluster id */
+
+ /* core_id >= PLATFORM_MAX_CPUS_PER_CLUSTER */
+ mov x0, #-1
+ cmp x1, #(PLATFORM_MAX_CPUS_PER_CLUSTER - 1)
+ b.gt 1f
+
+ /* cluster_id >= PLATFORM_CLUSTER_COUNT */
+ cmp x2, #(PLATFORM_CLUSTER_COUNT - 1)
+ b.gt 1f
+
+ /* CorePos = CoreId + (ClusterId * cpus per cluster) */
+ mov x3, #PLATFORM_MAX_CPUS_PER_CLUSTER
+ mul x3, x3, x2
+ add x0, x1, x3
+
+1:
+ ret
+endfunc plat_core_pos_by_mpidr
+
/* ----------------------------------------
* Secure entrypoint function for CPU boot
* ----------------------------------------
diff --git a/plat/nvidia/tegra/common/tegra_common.mk b/plat/nvidia/tegra/common/tegra_common.mk
index 50c9592..66d037f 100644
--- a/plat/nvidia/tegra/common/tegra_common.mk
+++ b/plat/nvidia/tegra/common/tegra_common.mk
@@ -32,5 +32,4 @@
${COMMON_DIR}/tegra_io_storage.c \
${COMMON_DIR}/tegra_platform.c \
${COMMON_DIR}/tegra_pm.c \
- ${COMMON_DIR}/tegra_sip_calls.c \
- ${COMMON_DIR}/tegra_topology.c
+ ${COMMON_DIR}/tegra_sip_calls.c
diff --git a/plat/nvidia/tegra/common/tegra_topology.c b/plat/nvidia/tegra/common/tegra_topology.c
deleted file mode 100644
index 205b051..0000000
--- a/plat/nvidia/tegra/common/tegra_topology.c
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#include <platform_def.h>
-
-#include <arch.h>
-#include <lib/psci/psci.h>
-#include <plat/common/platform.h>
-
-#pragma weak plat_core_pos_by_mpidr
-
-/*******************************************************************************
- * This function implements a part of the critical interface between the psci
- * generic layer and the platform that allows the former to query the platform
- * to convert an MPIDR to a unique linear index. An error code (-1) is returned
- * in case the MPIDR is invalid.
- ******************************************************************************/
-int32_t plat_core_pos_by_mpidr(u_register_t mpidr)
-{
- u_register_t cluster_id, cpu_id;
- int32_t result;
-
- cluster_id = (mpidr >> (u_register_t)MPIDR_AFF1_SHIFT) &
- (u_register_t)MPIDR_AFFLVL_MASK;
- cpu_id = (mpidr >> (u_register_t)MPIDR_AFF0_SHIFT) &
- (u_register_t)MPIDR_AFFLVL_MASK;
-
- /* CorePos = CoreId + (ClusterId * cpus per cluster) */
- result = (int32_t)cpu_id + ((int32_t)cluster_id *
- PLATFORM_MAX_CPUS_PER_CLUSTER);
-
- if (cluster_id >= (u_register_t)PLATFORM_CLUSTER_COUNT) {
- result = PSCI_E_NOT_PRESENT;
- }
-
- /*
- * Validate cpu_id by checking whether it represents a CPU in
- * one of the two clusters present on the platform.
- */
- if (cpu_id >= (u_register_t)PLATFORM_MAX_CPUS_PER_CLUSTER) {
- result = PSCI_E_NOT_PRESENT;
- }
-
- return result;
-}