2014-02-18 18:09:12 +00:00
|
|
|
/*
|
2019-01-11 18:26:51 +00:00
|
|
|
* Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved.
|
2014-02-18 18:09:12 +00:00
|
|
|
*
|
2017-05-03 09:38:09 +01:00
|
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
2014-02-18 18:09:12 +00:00
|
|
|
*/
|
|
|
|
|
2019-09-13 14:11:59 +01:00
|
|
|
#include <assert.h>
|
2018-12-14 00:18:21 +00:00
|
|
|
|
2019-09-13 14:11:59 +01:00
|
|
|
#include <arch_features.h>
|
2018-12-14 00:18:21 +00:00
|
|
|
#include <arch_helpers.h>
|
|
|
|
#include <bl32/tsp/tsp.h>
|
|
|
|
#include <common/bl_common.h>
|
|
|
|
#include <common/debug.h>
|
|
|
|
#include <lib/spinlock.h>
|
|
|
|
#include <plat/common/platform.h>
|
2019-09-13 14:11:59 +01:00
|
|
|
#include <platform_def.h>
|
2014-08-04 11:41:20 +01:00
|
|
|
#include <platform_tsp.h>
|
2018-12-14 00:18:21 +00:00
|
|
|
|
2014-08-01 17:58:27 +01:00
|
|
|
#include "tsp_private.h"
|
2014-02-18 18:09:12 +00:00
|
|
|
|
2014-05-16 18:48:12 +01:00
|
|
|
|
2014-02-18 18:09:12 +00:00
|
|
|
/*******************************************************************************
|
|
|
|
* Lock to control access to the console
|
|
|
|
******************************************************************************/
|
|
|
|
spinlock_t console_lock;
|
|
|
|
|
|
|
|
/*******************************************************************************
|
|
|
|
* Per cpu data structure to populate parameters for an SMC in C code and use
|
|
|
|
* a pointer to this structure in assembler code to populate x0-x7
|
|
|
|
******************************************************************************/
|
2014-04-10 15:37:22 +01:00
|
|
|
static tsp_args_t tsp_smc_args[PLATFORM_CORE_COUNT];
|
2014-02-18 18:09:12 +00:00
|
|
|
|
|
|
|
/*******************************************************************************
|
|
|
|
* Per cpu data structure to keep track of TSP activity
|
|
|
|
******************************************************************************/
|
2014-05-09 11:42:56 +01:00
|
|
|
work_statistics_t tsp_stats[PLATFORM_CORE_COUNT];
|
2014-02-18 18:09:12 +00:00
|
|
|
|
2014-05-16 18:48:12 +01:00
|
|
|
/*******************************************************************************
|
2016-06-16 14:24:26 +01:00
|
|
|
* The TSP memory footprint starts at address BL32_BASE and ends with the
|
|
|
|
* linker symbol __BL32_END__. Use these addresses to compute the TSP image
|
|
|
|
* size.
|
2014-05-16 18:48:12 +01:00
|
|
|
******************************************************************************/
|
2019-01-25 13:28:38 +00:00
|
|
|
#define BL32_TOTAL_LIMIT BL32_END
|
2016-06-16 14:24:26 +01:00
|
|
|
#define BL32_TOTAL_SIZE (BL32_TOTAL_LIMIT - (unsigned long) BL32_BASE)
|
2014-05-16 18:48:12 +01:00
|
|
|
|
2014-04-10 15:37:22 +01:00
|
|
|
static tsp_args_t *set_smc_args(uint64_t arg0,
|
2014-02-18 18:09:12 +00:00
|
|
|
uint64_t arg1,
|
|
|
|
uint64_t arg2,
|
|
|
|
uint64_t arg3,
|
|
|
|
uint64_t arg4,
|
|
|
|
uint64_t arg5,
|
|
|
|
uint64_t arg6,
|
|
|
|
uint64_t arg7)
|
|
|
|
{
|
|
|
|
uint32_t linear_id;
|
2014-04-10 15:37:22 +01:00
|
|
|
tsp_args_t *pcpu_smc_args;
|
2014-02-18 18:09:12 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Return to Secure Monitor by raising an SMC. The results of the
|
|
|
|
* service are passed as an arguments to the SMC
|
|
|
|
*/
|
2015-07-08 21:45:46 +01:00
|
|
|
linear_id = plat_my_core_pos();
|
2014-02-18 18:09:12 +00:00
|
|
|
pcpu_smc_args = &tsp_smc_args[linear_id];
|
|
|
|
write_sp_arg(pcpu_smc_args, TSP_ARG0, arg0);
|
|
|
|
write_sp_arg(pcpu_smc_args, TSP_ARG1, arg1);
|
|
|
|
write_sp_arg(pcpu_smc_args, TSP_ARG2, arg2);
|
|
|
|
write_sp_arg(pcpu_smc_args, TSP_ARG3, arg3);
|
|
|
|
write_sp_arg(pcpu_smc_args, TSP_ARG4, arg4);
|
|
|
|
write_sp_arg(pcpu_smc_args, TSP_ARG5, arg5);
|
|
|
|
write_sp_arg(pcpu_smc_args, TSP_ARG6, arg6);
|
|
|
|
write_sp_arg(pcpu_smc_args, TSP_ARG7, arg7);
|
|
|
|
|
|
|
|
return pcpu_smc_args;
|
|
|
|
}
|
|
|
|
|
2019-02-26 11:41:03 +00:00
|
|
|
/*******************************************************************************
|
|
|
|
* Setup function for TSP.
|
|
|
|
******************************************************************************/
|
|
|
|
void tsp_setup(void)
|
|
|
|
{
|
|
|
|
/* Perform early platform-specific setup */
|
|
|
|
tsp_early_platform_setup();
|
|
|
|
|
|
|
|
/* Perform late platform-specific setup */
|
|
|
|
tsp_plat_arch_setup();
|
2019-09-13 14:11:59 +01:00
|
|
|
|
|
|
|
#if ENABLE_PAUTH
|
|
|
|
/*
|
|
|
|
* Assert that the ARMv8.3-PAuth registers are present or an access
|
|
|
|
* fault will be triggered when they are being saved or restored.
|
|
|
|
*/
|
|
|
|
assert(is_armv8_3_pauth_present());
|
|
|
|
#endif /* ENABLE_PAUTH */
|
2019-02-26 11:41:03 +00:00
|
|
|
}
|
|
|
|
|
2014-02-18 18:09:12 +00:00
|
|
|
/*******************************************************************************
|
|
|
|
* TSP main entry point where it gets the opportunity to initialize its secure
|
|
|
|
* state/applications. Once the state is initialized, it must return to the
|
2014-05-20 21:43:27 +01:00
|
|
|
* SPD with a pointer to the 'tsp_vector_table' jump table.
|
2014-02-18 18:09:12 +00:00
|
|
|
******************************************************************************/
|
|
|
|
uint64_t tsp_main(void)
|
|
|
|
{
|
2014-07-29 17:14:00 +01:00
|
|
|
NOTICE("TSP: %s\n", version_string);
|
|
|
|
NOTICE("TSP: %s\n", build_message);
|
2016-06-16 14:24:26 +01:00
|
|
|
INFO("TSP: Total memory base : 0x%lx\n", (unsigned long) BL32_BASE);
|
|
|
|
INFO("TSP: Total memory size : 0x%lx bytes\n", BL32_TOTAL_SIZE);
|
2014-07-29 17:14:00 +01:00
|
|
|
|
2015-07-08 21:45:46 +01:00
|
|
|
uint32_t linear_id = plat_my_core_pos();
|
2014-02-18 18:09:12 +00:00
|
|
|
|
|
|
|
/* Initialize the platform */
|
2014-08-04 11:41:20 +01:00
|
|
|
tsp_platform_setup();
|
2014-02-18 18:09:12 +00:00
|
|
|
|
|
|
|
/* Initialize secure/applications state here */
|
2014-05-09 13:33:42 +01:00
|
|
|
tsp_generic_timer_start();
|
2014-02-18 18:09:12 +00:00
|
|
|
|
|
|
|
/* Update this cpu's statistics */
|
|
|
|
tsp_stats[linear_id].smc_count++;
|
|
|
|
tsp_stats[linear_id].eret_count++;
|
|
|
|
tsp_stats[linear_id].cpu_on_count++;
|
|
|
|
|
2014-07-29 17:14:00 +01:00
|
|
|
#if LOG_LEVEL >= LOG_LEVEL_INFO
|
2014-02-18 18:09:12 +00:00
|
|
|
spin_lock(&console_lock);
|
2015-07-08 21:45:46 +01:00
|
|
|
INFO("TSP: cpu 0x%lx: %d smcs, %d erets %d cpu on requests\n",
|
|
|
|
read_mpidr(),
|
2014-02-18 18:09:12 +00:00
|
|
|
tsp_stats[linear_id].smc_count,
|
|
|
|
tsp_stats[linear_id].eret_count,
|
|
|
|
tsp_stats[linear_id].cpu_on_count);
|
|
|
|
spin_unlock(&console_lock);
|
2014-07-29 17:14:00 +01:00
|
|
|
#endif
|
2014-05-20 21:43:27 +01:00
|
|
|
return (uint64_t) &tsp_vector_table;
|
2014-02-18 18:09:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*******************************************************************************
|
|
|
|
* This function performs any remaining book keeping in the test secure payload
|
|
|
|
* after this cpu's architectural state has been setup in response to an earlier
|
|
|
|
* psci cpu_on request.
|
|
|
|
******************************************************************************/
|
2014-04-10 15:37:22 +01:00
|
|
|
tsp_args_t *tsp_cpu_on_main(void)
|
2014-02-18 18:09:12 +00:00
|
|
|
{
|
2015-07-08 21:45:46 +01:00
|
|
|
uint32_t linear_id = plat_my_core_pos();
|
2014-02-18 18:09:12 +00:00
|
|
|
|
2014-05-09 13:33:42 +01:00
|
|
|
/* Initialize secure/applications state here */
|
|
|
|
tsp_generic_timer_start();
|
|
|
|
|
2014-02-18 18:09:12 +00:00
|
|
|
/* Update this cpu's statistics */
|
|
|
|
tsp_stats[linear_id].smc_count++;
|
|
|
|
tsp_stats[linear_id].eret_count++;
|
|
|
|
tsp_stats[linear_id].cpu_on_count++;
|
|
|
|
|
2014-07-29 17:14:00 +01:00
|
|
|
#if LOG_LEVEL >= LOG_LEVEL_INFO
|
2014-02-18 18:09:12 +00:00
|
|
|
spin_lock(&console_lock);
|
2015-07-08 21:45:46 +01:00
|
|
|
INFO("TSP: cpu 0x%lx turned on\n", read_mpidr());
|
|
|
|
INFO("TSP: cpu 0x%lx: %d smcs, %d erets %d cpu on requests\n",
|
|
|
|
read_mpidr(),
|
2014-07-29 17:14:00 +01:00
|
|
|
tsp_stats[linear_id].smc_count,
|
|
|
|
tsp_stats[linear_id].eret_count,
|
|
|
|
tsp_stats[linear_id].cpu_on_count);
|
2014-02-18 18:09:12 +00:00
|
|
|
spin_unlock(&console_lock);
|
2014-07-29 17:14:00 +01:00
|
|
|
#endif
|
2014-02-18 18:09:12 +00:00
|
|
|
/* Indicate to the SPD that we have completed turned ourselves on */
|
|
|
|
return set_smc_args(TSP_ON_DONE, 0, 0, 0, 0, 0, 0, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*******************************************************************************
|
|
|
|
* This function performs any remaining book keeping in the test secure payload
|
|
|
|
* before this cpu is turned off in response to a psci cpu_off request.
|
|
|
|
******************************************************************************/
|
2014-04-10 15:37:22 +01:00
|
|
|
tsp_args_t *tsp_cpu_off_main(uint64_t arg0,
|
2014-02-18 18:09:12 +00:00
|
|
|
uint64_t arg1,
|
|
|
|
uint64_t arg2,
|
|
|
|
uint64_t arg3,
|
|
|
|
uint64_t arg4,
|
|
|
|
uint64_t arg5,
|
|
|
|
uint64_t arg6,
|
|
|
|
uint64_t arg7)
|
|
|
|
{
|
2015-07-08 21:45:46 +01:00
|
|
|
uint32_t linear_id = plat_my_core_pos();
|
2014-02-18 18:09:12 +00:00
|
|
|
|
2014-05-09 13:33:42 +01:00
|
|
|
/*
|
|
|
|
* This cpu is being turned off, so disable the timer to prevent the
|
|
|
|
* secure timer interrupt from interfering with power down. A pending
|
|
|
|
* interrupt will be lost but we do not care as we are turning off.
|
|
|
|
*/
|
|
|
|
tsp_generic_timer_stop();
|
|
|
|
|
2014-02-18 18:09:12 +00:00
|
|
|
/* Update this cpu's statistics */
|
|
|
|
tsp_stats[linear_id].smc_count++;
|
|
|
|
tsp_stats[linear_id].eret_count++;
|
|
|
|
tsp_stats[linear_id].cpu_off_count++;
|
|
|
|
|
2014-07-29 17:14:00 +01:00
|
|
|
#if LOG_LEVEL >= LOG_LEVEL_INFO
|
2014-02-18 18:09:12 +00:00
|
|
|
spin_lock(&console_lock);
|
2015-07-08 21:45:46 +01:00
|
|
|
INFO("TSP: cpu 0x%lx off request\n", read_mpidr());
|
|
|
|
INFO("TSP: cpu 0x%lx: %d smcs, %d erets %d cpu off requests\n",
|
|
|
|
read_mpidr(),
|
2014-07-29 17:14:00 +01:00
|
|
|
tsp_stats[linear_id].smc_count,
|
|
|
|
tsp_stats[linear_id].eret_count,
|
|
|
|
tsp_stats[linear_id].cpu_off_count);
|
2014-02-18 18:09:12 +00:00
|
|
|
spin_unlock(&console_lock);
|
2014-07-29 17:14:00 +01:00
|
|
|
#endif
|
2014-02-18 18:09:12 +00:00
|
|
|
|
2014-02-09 18:24:19 +00:00
|
|
|
/* Indicate to the SPD that we have completed this request */
|
2014-02-18 18:09:12 +00:00
|
|
|
return set_smc_args(TSP_OFF_DONE, 0, 0, 0, 0, 0, 0, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*******************************************************************************
|
|
|
|
* This function performs any book keeping in the test secure payload before
|
|
|
|
* this cpu's architectural state is saved in response to an earlier psci
|
|
|
|
* cpu_suspend request.
|
|
|
|
******************************************************************************/
|
2014-09-30 11:19:51 +01:00
|
|
|
tsp_args_t *tsp_cpu_suspend_main(uint64_t arg0,
|
2014-02-18 18:09:12 +00:00
|
|
|
uint64_t arg1,
|
|
|
|
uint64_t arg2,
|
|
|
|
uint64_t arg3,
|
|
|
|
uint64_t arg4,
|
|
|
|
uint64_t arg5,
|
|
|
|
uint64_t arg6,
|
|
|
|
uint64_t arg7)
|
|
|
|
{
|
2015-07-08 21:45:46 +01:00
|
|
|
uint32_t linear_id = plat_my_core_pos();
|
2014-02-18 18:09:12 +00:00
|
|
|
|
2014-05-09 13:33:42 +01:00
|
|
|
/*
|
|
|
|
* Save the time context and disable it to prevent the secure timer
|
|
|
|
* interrupt from interfering with wakeup from the suspend state.
|
|
|
|
*/
|
|
|
|
tsp_generic_timer_save();
|
|
|
|
tsp_generic_timer_stop();
|
|
|
|
|
2014-02-18 18:09:12 +00:00
|
|
|
/* Update this cpu's statistics */
|
|
|
|
tsp_stats[linear_id].smc_count++;
|
|
|
|
tsp_stats[linear_id].eret_count++;
|
|
|
|
tsp_stats[linear_id].cpu_suspend_count++;
|
|
|
|
|
2014-07-29 17:14:00 +01:00
|
|
|
#if LOG_LEVEL >= LOG_LEVEL_INFO
|
2014-02-18 18:09:12 +00:00
|
|
|
spin_lock(&console_lock);
|
2015-02-05 15:42:31 +00:00
|
|
|
INFO("TSP: cpu 0x%lx: %d smcs, %d erets %d cpu suspend requests\n",
|
2015-07-08 21:45:46 +01:00
|
|
|
read_mpidr(),
|
2014-07-29 17:14:00 +01:00
|
|
|
tsp_stats[linear_id].smc_count,
|
|
|
|
tsp_stats[linear_id].eret_count,
|
|
|
|
tsp_stats[linear_id].cpu_suspend_count);
|
2014-02-18 18:09:12 +00:00
|
|
|
spin_unlock(&console_lock);
|
2014-07-29 17:14:00 +01:00
|
|
|
#endif
|
2014-02-18 18:09:12 +00:00
|
|
|
|
2014-02-09 18:24:19 +00:00
|
|
|
/* Indicate to the SPD that we have completed this request */
|
2014-02-18 18:09:12 +00:00
|
|
|
return set_smc_args(TSP_SUSPEND_DONE, 0, 0, 0, 0, 0, 0, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*******************************************************************************
|
|
|
|
* This function performs any book keeping in the test secure payload after this
|
|
|
|
* cpu's architectural state has been restored after wakeup from an earlier psci
|
|
|
|
* cpu_suspend request.
|
|
|
|
******************************************************************************/
|
2015-09-07 20:43:27 +01:00
|
|
|
tsp_args_t *tsp_cpu_resume_main(uint64_t max_off_pwrlvl,
|
2014-02-18 18:09:12 +00:00
|
|
|
uint64_t arg1,
|
|
|
|
uint64_t arg2,
|
|
|
|
uint64_t arg3,
|
|
|
|
uint64_t arg4,
|
|
|
|
uint64_t arg5,
|
|
|
|
uint64_t arg6,
|
|
|
|
uint64_t arg7)
|
|
|
|
{
|
2015-07-08 21:45:46 +01:00
|
|
|
uint32_t linear_id = plat_my_core_pos();
|
2014-02-18 18:09:12 +00:00
|
|
|
|
2014-05-09 13:33:42 +01:00
|
|
|
/* Restore the generic timer context */
|
|
|
|
tsp_generic_timer_restore();
|
|
|
|
|
2014-02-18 18:09:12 +00:00
|
|
|
/* Update this cpu's statistics */
|
|
|
|
tsp_stats[linear_id].smc_count++;
|
|
|
|
tsp_stats[linear_id].eret_count++;
|
|
|
|
tsp_stats[linear_id].cpu_resume_count++;
|
|
|
|
|
2014-07-29 17:14:00 +01:00
|
|
|
#if LOG_LEVEL >= LOG_LEVEL_INFO
|
2014-02-18 18:09:12 +00:00
|
|
|
spin_lock(&console_lock);
|
types: use int-ll64 for both aarch32 and aarch64
Since commit 031dbb122472 ("AArch32: Add essential Arch helpers"),
it is difficult to use consistent format strings for printf() family
between aarch32 and aarch64.
For example, uint64_t is defined as 'unsigned long long' for aarch32
and as 'unsigned long' for aarch64. Likewise, uintptr_t is defined
as 'unsigned int' for aarch32, and as 'unsigned long' for aarch64.
A problem typically arises when you use printf() in common code.
One solution could be, to cast the arguments to a type long enough
for both architectures. For example, if 'val' is uint64_t type,
like this:
printf("val = %llx\n", (unsigned long long)val);
Or, somebody may suggest to use a macro provided by <inttypes.h>,
like this:
printf("val = %" PRIx64 "\n", val);
But, both would make the code ugly.
The solution adopted in Linux kernel is to use the same typedefs for
all architectures. The fixed integer types in the kernel-space have
been unified into int-ll64, like follows:
typedef signed char int8_t;
typedef unsigned char uint8_t;
typedef signed short int16_t;
typedef unsigned short uint16_t;
typedef signed int int32_t;
typedef unsigned int uint32_t;
typedef signed long long int64_t;
typedef unsigned long long uint64_t;
[ Linux commit: 0c79a8e29b5fcbcbfd611daf9d500cfad8370fcf ]
This gets along with the codebase shared between 32 bit and 64 bit,
with the data model called ILP32, LP64, respectively.
The width for primitive types is defined as follows:
ILP32 LP64
int 32 32
long 32 64
long long 64 64
pointer 32 64
'long long' is 64 bit for both, so it is used for defining uint64_t.
'long' has the same width as pointer, so for uintptr_t.
We still need an ifdef conditional for (s)size_t.
All 64 bit architectures use "unsigned long" size_t, and most 32 bit
architectures use "unsigned int" size_t. H8/300, S/390 are known as
exceptions; they use "unsigned long" size_t despite their architecture
is 32 bit.
One idea for simplification might be to define size_t as 'unsigned long'
across architectures, then forbid the use of "%z" string format.
However, this would cause a distortion between size_t and sizeof()
operator. We have unknowledge about the native type of sizeof(), so
we need a guess of it anyway. I want the following formula to always
return 1:
__builtin_types_compatible_p(size_t, typeof(sizeof(int)))
Fortunately, ARM is probably a majority case. As far as I know, all
32 bit ARM compilers use "unsigned int" size_t.
Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
2018-02-02 06:09:36 +00:00
|
|
|
INFO("TSP: cpu 0x%lx resumed. maximum off power level %lld\n",
|
2015-09-07 20:43:27 +01:00
|
|
|
read_mpidr(), max_off_pwrlvl);
|
2015-02-05 15:42:31 +00:00
|
|
|
INFO("TSP: cpu 0x%lx: %d smcs, %d erets %d cpu suspend requests\n",
|
2015-07-08 21:45:46 +01:00
|
|
|
read_mpidr(),
|
2014-07-29 17:14:00 +01:00
|
|
|
tsp_stats[linear_id].smc_count,
|
|
|
|
tsp_stats[linear_id].eret_count,
|
|
|
|
tsp_stats[linear_id].cpu_suspend_count);
|
2014-02-18 18:09:12 +00:00
|
|
|
spin_unlock(&console_lock);
|
2014-07-29 17:14:00 +01:00
|
|
|
#endif
|
2014-02-09 18:24:19 +00:00
|
|
|
/* Indicate to the SPD that we have completed this request */
|
2014-02-18 18:09:12 +00:00
|
|
|
return set_smc_args(TSP_RESUME_DONE, 0, 0, 0, 0, 0, 0, 0);
|
|
|
|
}
|
|
|
|
|
2014-08-12 11:17:06 +01:00
|
|
|
/*******************************************************************************
|
|
|
|
* This function performs any remaining bookkeeping in the test secure payload
|
|
|
|
* before the system is switched off (in response to a psci SYSTEM_OFF request)
|
|
|
|
******************************************************************************/
|
|
|
|
tsp_args_t *tsp_system_off_main(uint64_t arg0,
|
|
|
|
uint64_t arg1,
|
|
|
|
uint64_t arg2,
|
|
|
|
uint64_t arg3,
|
|
|
|
uint64_t arg4,
|
|
|
|
uint64_t arg5,
|
|
|
|
uint64_t arg6,
|
|
|
|
uint64_t arg7)
|
|
|
|
{
|
2015-07-08 21:45:46 +01:00
|
|
|
uint32_t linear_id = plat_my_core_pos();
|
2014-08-12 11:17:06 +01:00
|
|
|
|
|
|
|
/* Update this cpu's statistics */
|
|
|
|
tsp_stats[linear_id].smc_count++;
|
|
|
|
tsp_stats[linear_id].eret_count++;
|
|
|
|
|
|
|
|
#if LOG_LEVEL >= LOG_LEVEL_INFO
|
|
|
|
spin_lock(&console_lock);
|
2015-07-08 21:45:46 +01:00
|
|
|
INFO("TSP: cpu 0x%lx SYSTEM_OFF request\n", read_mpidr());
|
|
|
|
INFO("TSP: cpu 0x%lx: %d smcs, %d erets requests\n", read_mpidr(),
|
2014-08-12 11:17:06 +01:00
|
|
|
tsp_stats[linear_id].smc_count,
|
|
|
|
tsp_stats[linear_id].eret_count);
|
|
|
|
spin_unlock(&console_lock);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* Indicate to the SPD that we have completed this request */
|
|
|
|
return set_smc_args(TSP_SYSTEM_OFF_DONE, 0, 0, 0, 0, 0, 0, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*******************************************************************************
|
|
|
|
* This function performs any remaining bookkeeping in the test secure payload
|
|
|
|
* before the system is reset (in response to a psci SYSTEM_RESET request)
|
|
|
|
******************************************************************************/
|
|
|
|
tsp_args_t *tsp_system_reset_main(uint64_t arg0,
|
|
|
|
uint64_t arg1,
|
|
|
|
uint64_t arg2,
|
|
|
|
uint64_t arg3,
|
|
|
|
uint64_t arg4,
|
|
|
|
uint64_t arg5,
|
|
|
|
uint64_t arg6,
|
|
|
|
uint64_t arg7)
|
|
|
|
{
|
2015-07-08 21:45:46 +01:00
|
|
|
uint32_t linear_id = plat_my_core_pos();
|
2014-08-12 11:17:06 +01:00
|
|
|
|
|
|
|
/* Update this cpu's statistics */
|
|
|
|
tsp_stats[linear_id].smc_count++;
|
|
|
|
tsp_stats[linear_id].eret_count++;
|
|
|
|
|
|
|
|
#if LOG_LEVEL >= LOG_LEVEL_INFO
|
|
|
|
spin_lock(&console_lock);
|
2015-07-08 21:45:46 +01:00
|
|
|
INFO("TSP: cpu 0x%lx SYSTEM_RESET request\n", read_mpidr());
|
|
|
|
INFO("TSP: cpu 0x%lx: %d smcs, %d erets requests\n", read_mpidr(),
|
2014-08-12 11:17:06 +01:00
|
|
|
tsp_stats[linear_id].smc_count,
|
|
|
|
tsp_stats[linear_id].eret_count);
|
|
|
|
spin_unlock(&console_lock);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* Indicate to the SPD that we have completed this request */
|
|
|
|
return set_smc_args(TSP_SYSTEM_RESET_DONE, 0, 0, 0, 0, 0, 0, 0);
|
|
|
|
}
|
|
|
|
|
2014-02-18 18:09:12 +00:00
|
|
|
/*******************************************************************************
|
|
|
|
* TSP fast smc handler. The secure monitor jumps to this function by
|
|
|
|
* doing the ERET after populating X0-X7 registers. The arguments are received
|
|
|
|
* in the function arguments in order. Once the service is rendered, this
|
2014-05-09 20:49:17 +01:00
|
|
|
* function returns to Secure Monitor by raising SMC.
|
2014-02-18 18:09:12 +00:00
|
|
|
******************************************************************************/
|
2014-05-09 20:49:17 +01:00
|
|
|
tsp_args_t *tsp_smc_handler(uint64_t func,
|
2014-02-18 18:09:12 +00:00
|
|
|
uint64_t arg1,
|
|
|
|
uint64_t arg2,
|
|
|
|
uint64_t arg3,
|
|
|
|
uint64_t arg4,
|
|
|
|
uint64_t arg5,
|
|
|
|
uint64_t arg6,
|
|
|
|
uint64_t arg7)
|
|
|
|
{
|
2014-02-09 23:11:46 +00:00
|
|
|
uint64_t results[2];
|
|
|
|
uint64_t service_args[2];
|
2015-07-08 21:45:46 +01:00
|
|
|
uint32_t linear_id = plat_my_core_pos();
|
2014-02-18 18:09:12 +00:00
|
|
|
|
2014-02-09 23:11:46 +00:00
|
|
|
/* Update this cpu's statistics */
|
|
|
|
tsp_stats[linear_id].smc_count++;
|
|
|
|
tsp_stats[linear_id].eret_count++;
|
|
|
|
|
types: use int-ll64 for both aarch32 and aarch64
Since commit 031dbb122472 ("AArch32: Add essential Arch helpers"),
it is difficult to use consistent format strings for printf() family
between aarch32 and aarch64.
For example, uint64_t is defined as 'unsigned long long' for aarch32
and as 'unsigned long' for aarch64. Likewise, uintptr_t is defined
as 'unsigned int' for aarch32, and as 'unsigned long' for aarch64.
A problem typically arises when you use printf() in common code.
One solution could be, to cast the arguments to a type long enough
for both architectures. For example, if 'val' is uint64_t type,
like this:
printf("val = %llx\n", (unsigned long long)val);
Or, somebody may suggest to use a macro provided by <inttypes.h>,
like this:
printf("val = %" PRIx64 "\n", val);
But, both would make the code ugly.
The solution adopted in Linux kernel is to use the same typedefs for
all architectures. The fixed integer types in the kernel-space have
been unified into int-ll64, like follows:
typedef signed char int8_t;
typedef unsigned char uint8_t;
typedef signed short int16_t;
typedef unsigned short uint16_t;
typedef signed int int32_t;
typedef unsigned int uint32_t;
typedef signed long long int64_t;
typedef unsigned long long uint64_t;
[ Linux commit: 0c79a8e29b5fcbcbfd611daf9d500cfad8370fcf ]
This gets along with the codebase shared between 32 bit and 64 bit,
with the data model called ILP32, LP64, respectively.
The width for primitive types is defined as follows:
ILP32 LP64
int 32 32
long 32 64
long long 64 64
pointer 32 64
'long long' is 64 bit for both, so it is used for defining uint64_t.
'long' has the same width as pointer, so for uintptr_t.
We still need an ifdef conditional for (s)size_t.
All 64 bit architectures use "unsigned long" size_t, and most 32 bit
architectures use "unsigned int" size_t. H8/300, S/390 are known as
exceptions; they use "unsigned long" size_t despite their architecture
is 32 bit.
One idea for simplification might be to define size_t as 'unsigned long'
across architectures, then forbid the use of "%z" string format.
However, this would cause a distortion between size_t and sizeof()
operator. We have unknowledge about the native type of sizeof(), so
we need a guess of it anyway. I want the following formula to always
return 1:
__builtin_types_compatible_p(size_t, typeof(sizeof(int)))
Fortunately, ARM is probably a majority case. As far as I know, all
32 bit ARM compilers use "unsigned int" size_t.
Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
2018-02-02 06:09:36 +00:00
|
|
|
INFO("TSP: cpu 0x%lx received %s smc 0x%llx\n", read_mpidr(),
|
2017-04-05 11:34:03 +01:00
|
|
|
((func >> 31) & 1) == 1 ? "fast" : "yielding",
|
2014-07-29 17:14:00 +01:00
|
|
|
func);
|
2015-07-08 21:45:46 +01:00
|
|
|
INFO("TSP: cpu 0x%lx: %d smcs, %d erets\n", read_mpidr(),
|
2014-07-29 17:14:00 +01:00
|
|
|
tsp_stats[linear_id].smc_count,
|
|
|
|
tsp_stats[linear_id].eret_count);
|
2014-02-18 18:09:12 +00:00
|
|
|
|
2014-02-09 23:11:46 +00:00
|
|
|
/* Render secure services and obtain results here */
|
2014-02-18 18:09:12 +00:00
|
|
|
results[0] = arg1;
|
|
|
|
results[1] = arg2;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Request a service back from dispatcher/secure monitor. This call
|
2019-01-11 18:26:51 +00:00
|
|
|
* return and thereafter resume execution
|
2014-02-18 18:09:12 +00:00
|
|
|
*/
|
|
|
|
tsp_get_magic(service_args);
|
|
|
|
|
2019-07-18 14:25:33 +01:00
|
|
|
#if CTX_INCLUDE_MTE_REGS
|
|
|
|
/*
|
|
|
|
* Write a dummy value to an MTE register, to simulate usage in the
|
|
|
|
* secure world
|
|
|
|
*/
|
|
|
|
write_gcr_el1(0x99);
|
|
|
|
#endif
|
|
|
|
|
2014-02-18 18:09:12 +00:00
|
|
|
/* Determine the function to perform based on the function ID */
|
2014-05-09 20:49:17 +01:00
|
|
|
switch (TSP_BARE_FID(func)) {
|
|
|
|
case TSP_ADD:
|
2014-02-18 18:09:12 +00:00
|
|
|
results[0] += service_args[0];
|
|
|
|
results[1] += service_args[1];
|
|
|
|
break;
|
2014-05-09 20:49:17 +01:00
|
|
|
case TSP_SUB:
|
2014-02-18 18:09:12 +00:00
|
|
|
results[0] -= service_args[0];
|
|
|
|
results[1] -= service_args[1];
|
|
|
|
break;
|
2014-05-09 20:49:17 +01:00
|
|
|
case TSP_MUL:
|
2014-02-18 18:09:12 +00:00
|
|
|
results[0] *= service_args[0];
|
|
|
|
results[1] *= service_args[1];
|
|
|
|
break;
|
2014-05-09 20:49:17 +01:00
|
|
|
case TSP_DIV:
|
2014-02-18 18:09:12 +00:00
|
|
|
results[0] /= service_args[0] ? service_args[0] : 1;
|
|
|
|
results[1] /= service_args[1] ? service_args[1] : 1;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2014-05-09 20:49:17 +01:00
|
|
|
return set_smc_args(func, 0,
|
2014-02-18 18:09:12 +00:00
|
|
|
results[0],
|
|
|
|
results[1],
|
2014-05-09 20:49:17 +01:00
|
|
|
0, 0, 0, 0);
|
2014-02-18 18:09:12 +00:00
|
|
|
}
|
|
|
|
|
2016-11-24 15:43:19 +00:00
|
|
|
/*******************************************************************************
|
2019-01-11 18:26:51 +00:00
|
|
|
* TSP smc abort handler. This function is called when aborting a preempted
|
2017-04-05 11:34:03 +01:00
|
|
|
* yielding SMC request. It should cleanup all resources owned by the SMC
|
2016-11-24 15:43:19 +00:00
|
|
|
* handler such as locks or dynamically allocated memory so following SMC
|
|
|
|
* request are executed in a clean environment.
|
|
|
|
******************************************************************************/
|
|
|
|
tsp_args_t *tsp_abort_smc_handler(uint64_t func,
|
|
|
|
uint64_t arg1,
|
|
|
|
uint64_t arg2,
|
|
|
|
uint64_t arg3,
|
|
|
|
uint64_t arg4,
|
|
|
|
uint64_t arg5,
|
|
|
|
uint64_t arg6,
|
|
|
|
uint64_t arg7)
|
|
|
|
{
|
|
|
|
return set_smc_args(TSP_ABORT_DONE, 0, 0, 0, 0, 0, 0, 0);
|
|
|
|
}
|