mirror of
https://github.com/ARM-software/arm-trusted-firmware.git
synced 2025-04-24 13:55:56 +00:00
Merge pull request #919 from davidcunado-arm/dc/smc_yielding_generic
Update terminology: standard SMC to yielding SMC
This commit is contained in:
commit
4b427bd487
11 changed files with 101 additions and 95 deletions
|
@ -180,7 +180,7 @@ endfunc tsp_entrypoint
|
||||||
* -------------------------------------------
|
* -------------------------------------------
|
||||||
*/
|
*/
|
||||||
func tsp_vector_table
|
func tsp_vector_table
|
||||||
b tsp_std_smc_entry
|
b tsp_yield_smc_entry
|
||||||
b tsp_fast_smc_entry
|
b tsp_fast_smc_entry
|
||||||
b tsp_cpu_on_entry
|
b tsp_cpu_on_entry
|
||||||
b tsp_cpu_off_entry
|
b tsp_cpu_off_entry
|
||||||
|
@ -189,7 +189,7 @@ func tsp_vector_table
|
||||||
b tsp_sel1_intr_entry
|
b tsp_sel1_intr_entry
|
||||||
b tsp_system_off_entry
|
b tsp_system_off_entry
|
||||||
b tsp_system_reset_entry
|
b tsp_system_reset_entry
|
||||||
b tsp_abort_std_smc_entry
|
b tsp_abort_yield_smc_entry
|
||||||
endfunc tsp_vector_table
|
endfunc tsp_vector_table
|
||||||
|
|
||||||
/*---------------------------------------------
|
/*---------------------------------------------
|
||||||
|
@ -437,12 +437,12 @@ endfunc tsp_fast_smc_entry
|
||||||
|
|
||||||
/*---------------------------------------------
|
/*---------------------------------------------
|
||||||
* This entrypoint is used by the TSPD to ask
|
* This entrypoint is used by the TSPD to ask
|
||||||
* the TSP to service a std smc request.
|
* the TSP to service a Yielding SMC request.
|
||||||
* We will enable preemption during execution
|
* We will enable preemption during execution
|
||||||
* of tsp_smc_handler.
|
* of tsp_smc_handler.
|
||||||
* ---------------------------------------------
|
* ---------------------------------------------
|
||||||
*/
|
*/
|
||||||
func tsp_std_smc_entry
|
func tsp_yield_smc_entry
|
||||||
msr daifclr, #DAIF_FIQ_BIT | DAIF_IRQ_BIT
|
msr daifclr, #DAIF_FIQ_BIT | DAIF_IRQ_BIT
|
||||||
bl tsp_smc_handler
|
bl tsp_smc_handler
|
||||||
msr daifset, #DAIF_FIQ_BIT | DAIF_IRQ_BIT
|
msr daifset, #DAIF_FIQ_BIT | DAIF_IRQ_BIT
|
||||||
|
@ -450,15 +450,15 @@ func tsp_std_smc_entry
|
||||||
|
|
||||||
/* Should never reach here */
|
/* Should never reach here */
|
||||||
no_ret plat_panic_handler
|
no_ret plat_panic_handler
|
||||||
endfunc tsp_std_smc_entry
|
endfunc tsp_yield_smc_entry
|
||||||
|
|
||||||
/*---------------------------------------------------------------------
|
/*---------------------------------------------------------------------
|
||||||
* This entrypoint is used by the TSPD to abort a pre-empted Standard
|
* This entrypoint is used by the TSPD to abort a pre-empted Yielding
|
||||||
* SMC. It could be on behalf of non-secure world or because a CPU
|
* SMC. It could be on behalf of non-secure world or because a CPU
|
||||||
* suspend/CPU off request needs to abort the preempted SMC.
|
* suspend/CPU off request needs to abort the preempted SMC.
|
||||||
* --------------------------------------------------------------------
|
* --------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
func tsp_abort_std_smc_entry
|
func tsp_abort_yield_smc_entry
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Exceptions masking is already done by the TSPD when entering this
|
* Exceptions masking is already done by the TSPD when entering this
|
||||||
|
@ -477,4 +477,4 @@ func tsp_abort_std_smc_entry
|
||||||
|
|
||||||
/* Should never reach here */
|
/* Should never reach here */
|
||||||
bl plat_panic_handler
|
bl plat_panic_handler
|
||||||
endfunc tsp_abort_std_smc_entry
|
endfunc tsp_abort_yield_smc_entry
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved.
|
* Copyright (c) 2013-2017, ARM Limited and Contributors. All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions are met:
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
@ -372,7 +372,7 @@ tsp_args_t *tsp_smc_handler(uint64_t func,
|
||||||
tsp_stats[linear_id].eret_count++;
|
tsp_stats[linear_id].eret_count++;
|
||||||
|
|
||||||
INFO("TSP: cpu 0x%lx received %s smc 0x%lx\n", read_mpidr(),
|
INFO("TSP: cpu 0x%lx received %s smc 0x%lx\n", read_mpidr(),
|
||||||
((func >> 31) & 1) == 1 ? "fast" : "standard",
|
((func >> 31) & 1) == 1 ? "fast" : "yielding",
|
||||||
func);
|
func);
|
||||||
INFO("TSP: cpu 0x%lx: %d smcs, %d erets\n", read_mpidr(),
|
INFO("TSP: cpu 0x%lx: %d smcs, %d erets\n", read_mpidr(),
|
||||||
tsp_stats[linear_id].smc_count,
|
tsp_stats[linear_id].smc_count,
|
||||||
|
@ -418,7 +418,7 @@ tsp_args_t *tsp_smc_handler(uint64_t func,
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* TSP smc abort handler. This function is called when aborting a preemtped
|
* TSP smc abort handler. This function is called when aborting a preemtped
|
||||||
* standard SMC request. It should cleanup all resources owned by the SMC
|
* yielding SMC request. It should cleanup all resources owned by the SMC
|
||||||
* handler such as locks or dynamically allocated memory so following SMC
|
* handler such as locks or dynamically allocated memory so following SMC
|
||||||
* request are executed in a clean environment.
|
* request are executed in a clean environment.
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved.
|
* Copyright (c) 2013-2017, ARM Limited and Contributors. All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions are met:
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
@ -93,7 +93,8 @@ static int32_t validate_rt_svc_desc(const rt_svc_desc_t *desc)
|
||||||
if (desc->end_oen >= OEN_LIMIT)
|
if (desc->end_oen >= OEN_LIMIT)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
if (desc->call_type != SMC_TYPE_FAST && desc->call_type != SMC_TYPE_STD)
|
if (desc->call_type != SMC_TYPE_FAST &&
|
||||||
|
desc->call_type != SMC_TYPE_YIELD)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
/* A runtime service having no init or handle function doesn't make sense */
|
/* A runtime service having no init or handle function doesn't make sense */
|
||||||
|
@ -143,7 +144,7 @@ void runtime_svc_init(void)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The runtime service may have separate rt_svc_desc_t
|
* The runtime service may have separate rt_svc_desc_t
|
||||||
* for its fast smc and standard smc. Since the service itself
|
* for its fast smc and yielding smc. Since the service itself
|
||||||
* need to be initialized only once, only one of them will have
|
* need to be initialized only once, only one of them will have
|
||||||
* an initialisation routine defined. Call the initialisation
|
* an initialisation routine defined. Call the initialisation
|
||||||
* routine for this runtime service, if it is defined.
|
* routine for this runtime service, if it is defined.
|
||||||
|
|
|
@ -686,7 +686,7 @@ Software (BL31).
|
||||||
|
|
||||||
The design of the runtime services depends heavily on the concepts and
|
The design of the runtime services depends heavily on the concepts and
|
||||||
definitions described in the [SMCCC], in particular SMC Function IDs, Owning
|
definitions described in the [SMCCC], in particular SMC Function IDs, Owning
|
||||||
Entity Numbers (OEN), Fast and Standard calls, and the SMC32 and SMC64 calling
|
Entity Numbers (OEN), Fast and Yielding calls, and the SMC32 and SMC64 calling
|
||||||
conventions. Please refer to that document for more detailed explanation of
|
conventions. Please refer to that document for more detailed explanation of
|
||||||
these terms.
|
these terms.
|
||||||
|
|
||||||
|
@ -812,7 +812,7 @@ SMC Function which indicates the SMC64 calling convention: such calls are
|
||||||
ignored and return the Unknown SMC Function Identifier result code `0xFFFFFFFF`
|
ignored and return the Unknown SMC Function Identifier result code `0xFFFFFFFF`
|
||||||
in R0/X0.
|
in R0/X0.
|
||||||
|
|
||||||
Bit[31] (fast/standard call) and bits[29:24] (owning entity number) of the SMC
|
Bit[31] (fast/yielding call) and bits[29:24] (owning entity number) of the SMC
|
||||||
Function ID are combined to index into the `rt_svc_descs_indices[]` array. The
|
Function ID are combined to index into the `rt_svc_descs_indices[]` array. The
|
||||||
resulting value might indicate a service that has no handler, in this case the
|
resulting value might indicate a service that has no handler, in this case the
|
||||||
framework will also report an Unknown SMC Function ID. Otherwise, the value is
|
framework will also report an Unknown SMC Function ID. Otherwise, the value is
|
||||||
|
|
|
@ -761,7 +761,7 @@ invoked.
|
||||||
3. It sets the `ELR_EL3` system register to `tsp_sel1_intr_entry` and sets the
|
3. It sets the `ELR_EL3` system register to `tsp_sel1_intr_entry` and sets the
|
||||||
`SPSR_EL3.DAIF` bits in the secure CPU context. It sets `x0` to
|
`SPSR_EL3.DAIF` bits in the secure CPU context. It sets `x0` to
|
||||||
`TSP_HANDLE_SEL1_INTR_AND_RETURN`. If the TSP was preempted earlier by a non
|
`TSP_HANDLE_SEL1_INTR_AND_RETURN`. If the TSP was preempted earlier by a non
|
||||||
secure interrupt during `standard` SMC processing, save the registers that
|
secure interrupt during `yielding` SMC processing, save the registers that
|
||||||
will be trashed, which is the `ELR_EL3` and `SPSR_EL3`, in order to be able
|
will be trashed, which is the `ELR_EL3` and `SPSR_EL3`, in order to be able
|
||||||
to re-enter TSP for Secure-EL1 interrupt processing. It does not need to
|
to re-enter TSP for Secure-EL1 interrupt processing. It does not need to
|
||||||
save any other secure context since the TSP is expected to preserve it
|
save any other secure context since the TSP is expected to preserve it
|
||||||
|
@ -809,17 +809,17 @@ upon receiving an SMC with `TSP_HANDLED_S_EL1_INTR` as the function identifier:
|
||||||
|
|
||||||
##### 2.3.2.4 Test secure payload dispatcher non-secure interrupt handling
|
##### 2.3.2.4 Test secure payload dispatcher non-secure interrupt handling
|
||||||
The TSP in Secure-EL1 can be preempted by a non-secure interrupt during
|
The TSP in Secure-EL1 can be preempted by a non-secure interrupt during
|
||||||
`standard` SMC processing or by a higher priority EL3 interrupt during
|
`yielding` SMC processing or by a higher priority EL3 interrupt during
|
||||||
Secure-EL1 interrupt processing. Currently only non-secure interrupts can
|
Secure-EL1 interrupt processing. Currently only non-secure interrupts can
|
||||||
cause preemption of TSP since there are no EL3 interrupts in the
|
cause preemption of TSP since there are no EL3 interrupts in the
|
||||||
system.
|
system.
|
||||||
|
|
||||||
It should be noted that while TSP is preempted, the TSPD only allows entry into
|
It should be noted that while TSP is preempted, the TSPD only allows entry into
|
||||||
the TSP either for Secure-EL1 interrupt handling or for resuming the preempted
|
the TSP either for Secure-EL1 interrupt handling or for resuming the preempted
|
||||||
`standard` SMC in response to the `TSP_FID_RESUME` SMC from the normal world.
|
`yielding` SMC in response to the `TSP_FID_RESUME` SMC from the normal world.
|
||||||
(See Section 3).
|
(See Section 3).
|
||||||
|
|
||||||
The non-secure interrupt triggered in Secure-EL1 during `standard` SMC processing
|
The non-secure interrupt triggered in Secure-EL1 during `yielding` SMC processing
|
||||||
can be routed to either EL3 or Secure-EL1 and is controlled by build option
|
can be routed to either EL3 or Secure-EL1 and is controlled by build option
|
||||||
`TSP_NS_INTR_ASYNC_PREEMPT` (see Section 2.2.2.1). If the build option is set,
|
`TSP_NS_INTR_ASYNC_PREEMPT` (see Section 2.2.2.1). If the build option is set,
|
||||||
the TSPD will set the routing model for the non-secure interrupt to be routed to
|
the TSPD will set the routing model for the non-secure interrupt to be routed to
|
||||||
|
@ -835,7 +835,7 @@ further handling.
|
||||||
|
|
||||||
If the `TSP_NS_INTR_ASYNC_PREEMPT` build option is zero (default), the default
|
If the `TSP_NS_INTR_ASYNC_PREEMPT` build option is zero (default), the default
|
||||||
routing model for non-secure interrupt in secure state is in effect
|
routing model for non-secure interrupt in secure state is in effect
|
||||||
i.e. __TEL3=0, CSS=0__. During `standard` SMC processing, the IRQ
|
i.e. __TEL3=0, CSS=0__. During `yielding` SMC processing, the IRQ
|
||||||
exceptions are unmasked i.e. `PSTATE.I=0`, and a non-secure interrupt will
|
exceptions are unmasked i.e. `PSTATE.I=0`, and a non-secure interrupt will
|
||||||
trigger at Secure-EL1 IRQ exception vector. The TSP saves the general purpose
|
trigger at Secure-EL1 IRQ exception vector. The TSP saves the general purpose
|
||||||
register context and issues an SMC with `TSP_PREEMPTED` as the function
|
register context and issues an SMC with `TSP_PREEMPTED` as the function
|
||||||
|
@ -860,7 +860,7 @@ invoked:
|
||||||
4. `SMC_PREEMPTED` is set in x0 and return to non secure state after
|
4. `SMC_PREEMPTED` is set in x0 and return to non secure state after
|
||||||
restoring non secure context.
|
restoring non secure context.
|
||||||
|
|
||||||
The Normal World is expected to resume the TSP after the `standard` SMC preemption
|
The Normal World is expected to resume the TSP after the `yielding` SMC preemption
|
||||||
by issuing an SMC with `TSP_FID_RESUME` as the function identifier (see section 3).
|
by issuing an SMC with `TSP_FID_RESUME` as the function identifier (see section 3).
|
||||||
The TSPD service takes the following actions in `tspd_smc_handler()` function
|
The TSPD service takes the following actions in `tspd_smc_handler()` function
|
||||||
upon receiving this SMC:
|
upon receiving this SMC:
|
||||||
|
@ -951,9 +951,9 @@ The TSP handles interrupts under the asynchronous model as follows.
|
||||||
-----------------------
|
-----------------------
|
||||||
|
|
||||||
### 3.1 Implication of preempted SMC on Non-Secure Software
|
### 3.1 Implication of preempted SMC on Non-Secure Software
|
||||||
A `standard` SMC call to Secure payload can be preempted by a non-secure
|
A `yielding` SMC call to Secure payload can be preempted by a non-secure
|
||||||
interrupt and the execution can return to the non-secure world for handling
|
interrupt and the execution can return to the non-secure world for handling
|
||||||
the interrupt (For details on `standard` SMC refer [SMC calling convention]).
|
the interrupt (For details on `yielding` SMC refer [SMC calling convention]).
|
||||||
In this case, the SMC call has not completed its execution and the execution
|
In this case, the SMC call has not completed its execution and the execution
|
||||||
must return back to the secure payload to resume the preempted SMC call.
|
must return back to the secure payload to resume the preempted SMC call.
|
||||||
This can be achieved by issuing an SMC call which instructs to resume the
|
This can be achieved by issuing an SMC call which instructs to resume the
|
||||||
|
@ -964,26 +964,26 @@ a fast SMC call.
|
||||||
|
|
||||||
In the Test Secure Payload implementation, `TSP_FID_RESUME` is designated
|
In the Test Secure Payload implementation, `TSP_FID_RESUME` is designated
|
||||||
as the resume SMC FID. It is important to note that `TSP_FID_RESUME` is a
|
as the resume SMC FID. It is important to note that `TSP_FID_RESUME` is a
|
||||||
`standard` SMC which means it too can be be preempted. The typical non
|
`yielding` SMC which means it too can be be preempted. The typical non
|
||||||
secure software sequence for issuing a `standard` SMC would look like this,
|
secure software sequence for issuing a `yielding` SMC would look like this,
|
||||||
assuming `P.STATE.I=0` in the non secure state :
|
assuming `P.STATE.I=0` in the non secure state :
|
||||||
|
|
||||||
int rc;
|
int rc;
|
||||||
rc = smc(TSP_STD_SMC_FID, ...); /* Issue a Standard SMC call */
|
rc = smc(TSP_YIELD_SMC_FID, ...); /* Issue a Yielding SMC call */
|
||||||
/* The pending non-secure interrupt is handled by the interrupt handler
|
/* The pending non-secure interrupt is handled by the interrupt handler
|
||||||
and returns back here. */
|
and returns back here. */
|
||||||
while (rc == SMC_PREEMPTED) { /* Check if the SMC call is preempted */
|
while (rc == SMC_PREEMPTED) { /* Check if the SMC call is preempted */
|
||||||
rc = smc(TSP_FID_RESUME); /* Issue resume SMC call */
|
rc = smc(TSP_FID_RESUME); /* Issue resume SMC call */
|
||||||
}
|
}
|
||||||
|
|
||||||
The `TSP_STD_SMC_FID` is any `standard` SMC function identifier and the smc()
|
The `TSP_YIELD_SMC_FID` is any `yielding` SMC function identifier and the smc()
|
||||||
function invokes a SMC call with the required arguments. The pending non-secure
|
function invokes a SMC call with the required arguments. The pending non-secure
|
||||||
interrupt causes an IRQ exception and the IRQ handler registered at the
|
interrupt causes an IRQ exception and the IRQ handler registered at the
|
||||||
exception vector handles the non-secure interrupt and returns. The return value
|
exception vector handles the non-secure interrupt and returns. The return value
|
||||||
from the SMC call is tested for `SMC_PREEMPTED` to check whether it is
|
from the SMC call is tested for `SMC_PREEMPTED` to check whether it is
|
||||||
preempted. If it is, then the resume SMC call `TSP_FID_RESUME` is issued. The
|
preempted. If it is, then the resume SMC call `TSP_FID_RESUME` is issued. The
|
||||||
return value of the SMC call is tested again to check if it is preempted.
|
return value of the SMC call is tested again to check if it is preempted.
|
||||||
This is done in a loop till the SMC call succeeds or fails. If a `standard`
|
This is done in a loop till the SMC call succeeds or fails. If a `yielding`
|
||||||
SMC is preempted, until it is resumed using `TSP_FID_RESUME` SMC and
|
SMC is preempted, until it is resumed using `TSP_FID_RESUME` SMC and
|
||||||
completed, the current TSPD prevents any other SMC call from re-entering
|
completed, the current TSPD prevents any other SMC call from re-entering
|
||||||
TSP by returning `SMC_UNK` error.
|
TSP by returning `SMC_UNK` error.
|
||||||
|
|
|
@ -51,9 +51,9 @@ of these terms.
|
||||||
The SMC Function Identifier includes a OEN field. These values and their
|
The SMC Function Identifier includes a OEN field. These values and their
|
||||||
meaning are described in [SMCCC] and summarized in table 1 below. Some entities
|
meaning are described in [SMCCC] and summarized in table 1 below. Some entities
|
||||||
are allocated a range of of OENs. The OEN must be interpreted in conjunction
|
are allocated a range of of OENs. The OEN must be interpreted in conjunction
|
||||||
with the SMC call type, which is either _Fast_ or _Standard_. Fast calls are
|
with the SMC call type, which is either _Fast_ or _Yielding_. Fast calls are
|
||||||
uninterruptible whereas Standard calls can be pre-empted. The majority of
|
uninterruptible whereas Yielding calls can be pre-empted. The majority of
|
||||||
Owning Entities only have allocated ranges for Fast calls: Standard calls are
|
Owning Entities only have allocated ranges for Fast calls: Yielding calls are
|
||||||
reserved exclusively for Trusted OS providers or for interoperability with
|
reserved exclusively for Trusted OS providers or for interoperability with
|
||||||
legacy 32-bit software that predates the [SMCCC].
|
legacy 32-bit software that predates the [SMCCC].
|
||||||
|
|
||||||
|
@ -67,8 +67,8 @@ legacy 32-bit software that predates the [SMCCC].
|
||||||
Fast 48-49 Trusted Application calls
|
Fast 48-49 Trusted Application calls
|
||||||
Fast 50-63 Trusted OS calls
|
Fast 50-63 Trusted OS calls
|
||||||
|
|
||||||
Std 0- 1 Reserved for existing ARMv7 calls
|
Yielding 0- 1 Reserved for existing ARMv7 calls
|
||||||
Std 2-63 Trusted OS Standard Calls
|
Yielding 2-63 Trusted OS Standard Calls
|
||||||
|
|
||||||
_Table 1: Service types and their corresponding Owning Entity Numbers_
|
_Table 1: Service types and their corresponding Owning Entity Numbers_
|
||||||
|
|
||||||
|
@ -115,7 +115,7 @@ initialization and call handler functions.
|
||||||
* `_start` and `_end` values must be based on the `OEN_*` values defined in
|
* `_start` and `_end` values must be based on the `OEN_*` values defined in
|
||||||
[`smcc.h`]
|
[`smcc.h`]
|
||||||
|
|
||||||
* `_type` must be one of `SMC_TYPE_FAST` or `SMC_TYPE_STD`
|
* `_type` must be one of `SMC_TYPE_FAST` or `SMC_TYPE_YIELD`
|
||||||
|
|
||||||
* `_setup` is the initialization function with the `rt_svc_init` signature:
|
* `_setup` is the initialization function with the `rt_svc_init` signature:
|
||||||
|
|
||||||
|
@ -138,7 +138,7 @@ to ensure that the following conditions are met:
|
||||||
|
|
||||||
1. The `_start` OEN is not greater than the `_end` OEN
|
1. The `_start` OEN is not greater than the `_end` OEN
|
||||||
2. The `_end` OEN does not exceed the maximum OEN value (63)
|
2. The `_end` OEN does not exceed the maximum OEN value (63)
|
||||||
3. The `_type` is one of `SMC_TYPE_FAST` or `SMC_TYPE_STD`
|
3. The `_type` is one of `SMC_TYPE_FAST` or `SMC_TYPE_YIELD`
|
||||||
4. `_setup` and `_smch` routines have been specified
|
4. `_setup` and `_smch` routines have been specified
|
||||||
|
|
||||||
[`std_svc_setup.c`] provides an example of registering a runtime service:
|
[`std_svc_setup.c`] provides an example of registering a runtime service:
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved.
|
* Copyright (c) 2013-2017, ARM Limited and Contributors. All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions are met:
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
@ -46,7 +46,7 @@
|
||||||
#define TSP_SYSTEM_RESET_DONE 0xf2000009
|
#define TSP_SYSTEM_RESET_DONE 0xf2000009
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Function identifiers to handle S-El1 interrupt through the synchronous
|
* Function identifiers to handle S-EL1 interrupt through the synchronous
|
||||||
* handling model. If the TSP was previously interrupted then control has to
|
* handling model. If the TSP was previously interrupted then control has to
|
||||||
* be returned to the TSPD after handling the interrupt else execution can
|
* be returned to the TSPD after handling the interrupt else execution can
|
||||||
* remain in the TSP.
|
* remain in the TSP.
|
||||||
|
@ -58,7 +58,7 @@
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Identifiers for various TSP services. Corresponding function IDs (whether
|
* Identifiers for various TSP services. Corresponding function IDs (whether
|
||||||
* fast or standard) are generated by macros defined below
|
* fast or yielding) are generated by macros defined below
|
||||||
*/
|
*/
|
||||||
#define TSP_ADD 0x2000
|
#define TSP_ADD 0x2000
|
||||||
#define TSP_SUB 0x2001
|
#define TSP_SUB 0x2001
|
||||||
|
@ -74,15 +74,15 @@
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Generate function IDs for TSP services to be used in SMC calls, by
|
* Generate function IDs for TSP services to be used in SMC calls, by
|
||||||
* appropriately setting bit 31 to differentiate standard and fast SMC calls
|
* appropriately setting bit 31 to differentiate yielding and fast SMC calls
|
||||||
*/
|
*/
|
||||||
#define TSP_STD_FID(fid) ((TSP_BARE_FID(fid) | 0x72000000))
|
#define TSP_YIELD_FID(fid) ((TSP_BARE_FID(fid) | 0x72000000))
|
||||||
#define TSP_FAST_FID(fid) ((TSP_BARE_FID(fid) | 0x72000000) | (1u << 31))
|
#define TSP_FAST_FID(fid) ((TSP_BARE_FID(fid) | 0x72000000) | (1u << 31))
|
||||||
|
|
||||||
/* SMC function ID to request a previously preempted std smc */
|
/* SMC function ID to request a previously preempted yielding smc */
|
||||||
#define TSP_FID_RESUME TSP_STD_FID(0x3000)
|
#define TSP_FID_RESUME TSP_YIELD_FID(0x3000)
|
||||||
/*
|
/*
|
||||||
* SMC function ID to request abortion of a previously preempted std smc. A
|
* SMC function ID to request abortion of a previously preempted yielding SMC. A
|
||||||
* fast SMC is used so that the TSP abort handler does not have to be
|
* fast SMC is used so that the TSP abort handler does not have to be
|
||||||
* reentrant.
|
* reentrant.
|
||||||
*/
|
*/
|
||||||
|
@ -116,7 +116,7 @@
|
||||||
typedef uint32_t tsp_vector_isn_t;
|
typedef uint32_t tsp_vector_isn_t;
|
||||||
|
|
||||||
typedef struct tsp_vectors {
|
typedef struct tsp_vectors {
|
||||||
tsp_vector_isn_t std_smc_entry;
|
tsp_vector_isn_t yield_smc_entry;
|
||||||
tsp_vector_isn_t fast_smc_entry;
|
tsp_vector_isn_t fast_smc_entry;
|
||||||
tsp_vector_isn_t cpu_on_entry;
|
tsp_vector_isn_t cpu_on_entry;
|
||||||
tsp_vector_isn_t cpu_off_entry;
|
tsp_vector_isn_t cpu_off_entry;
|
||||||
|
@ -125,7 +125,7 @@ typedef struct tsp_vectors {
|
||||||
tsp_vector_isn_t sel1_intr_entry;
|
tsp_vector_isn_t sel1_intr_entry;
|
||||||
tsp_vector_isn_t system_off_entry;
|
tsp_vector_isn_t system_off_entry;
|
||||||
tsp_vector_isn_t system_reset_entry;
|
tsp_vector_isn_t system_reset_entry;
|
||||||
tsp_vector_isn_t abort_std_smc_entry;
|
tsp_vector_isn_t abort_yield_smc_entry;
|
||||||
} tsp_vectors_t;
|
} tsp_vectors_t;
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -61,7 +61,10 @@
|
||||||
#define SMC_OK 0
|
#define SMC_OK 0
|
||||||
#define SMC_UNK 0xffffffff
|
#define SMC_UNK 0xffffffff
|
||||||
#define SMC_TYPE_FAST ULL(1)
|
#define SMC_TYPE_FAST ULL(1)
|
||||||
|
#if !ERROR_DEPRECATED
|
||||||
#define SMC_TYPE_STD 0
|
#define SMC_TYPE_STD 0
|
||||||
|
#endif
|
||||||
|
#define SMC_TYPE_YIELD 0
|
||||||
#define SMC_PREEMPTED 0xfffffffe
|
#define SMC_PREEMPTED 0xfffffffe
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* Owning entity number definitions inside the function id as per the SMC
|
* Owning entity number definitions inside the function id as per the SMC
|
||||||
|
@ -75,7 +78,7 @@
|
||||||
#define OEN_SIP_END 2
|
#define OEN_SIP_END 2
|
||||||
#define OEN_OEM_START 3
|
#define OEN_OEM_START 3
|
||||||
#define OEN_OEM_END 3
|
#define OEN_OEM_END 3
|
||||||
#define OEN_STD_START 4 /* Standard Calls */
|
#define OEN_STD_START 4 /* Standard Service Calls */
|
||||||
#define OEN_STD_END 4
|
#define OEN_STD_END 4
|
||||||
#define OEN_TAP_START 48 /* Trusted Applications */
|
#define OEN_TAP_START 48 /* Trusted Applications */
|
||||||
#define OEN_TAP_END 49
|
#define OEN_TAP_END 49
|
||||||
|
|
|
@ -65,7 +65,7 @@ void tspd_init_tsp_ep_state(struct entry_point_info *tsp_entry_point,
|
||||||
tsp_ctx->mpidr = read_mpidr_el1();
|
tsp_ctx->mpidr = read_mpidr_el1();
|
||||||
tsp_ctx->state = 0;
|
tsp_ctx->state = 0;
|
||||||
set_tsp_pstate(tsp_ctx->state, TSP_PSTATE_OFF);
|
set_tsp_pstate(tsp_ctx->state, TSP_PSTATE_OFF);
|
||||||
clr_std_smc_active_flag(tsp_ctx->state);
|
clr_yield_smc_active_flag(tsp_ctx->state);
|
||||||
|
|
||||||
cm_set_context(&tsp_ctx->cpu_ctx, SECURE);
|
cm_set_context(&tsp_ctx->cpu_ctx, SECURE);
|
||||||
|
|
||||||
|
@ -140,18 +140,18 @@ void tspd_synchronous_sp_exit(tsp_context_t *tsp_ctx, uint64_t ret)
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
int tspd_abort_preempted_smc(tsp_context_t *tsp_ctx)
|
int tspd_abort_preempted_smc(tsp_context_t *tsp_ctx)
|
||||||
{
|
{
|
||||||
if (!get_std_smc_active_flag(tsp_ctx->state))
|
if (!get_yield_smc_active_flag(tsp_ctx->state))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Abort any preempted SMC request */
|
/* Abort any preempted SMC request */
|
||||||
clr_std_smc_active_flag(tsp_ctx->state);
|
clr_yield_smc_active_flag(tsp_ctx->state);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Arrange for an entry into the test secure payload. It will
|
* Arrange for an entry into the test secure payload. It will
|
||||||
* be returned via TSP_ABORT_DONE case in tspd_smc_handler.
|
* be returned via TSP_ABORT_DONE case in tspd_smc_handler.
|
||||||
*/
|
*/
|
||||||
cm_set_elr_el3(SECURE,
|
cm_set_elr_el3(SECURE,
|
||||||
(uint64_t) &tsp_vectors->abort_std_smc_entry);
|
(uint64_t) &tsp_vectors->abort_yield_smc_entry);
|
||||||
uint64_t rc = tspd_synchronous_sp_entry(tsp_ctx);
|
uint64_t rc = tspd_synchronous_sp_entry(tsp_ctx);
|
||||||
|
|
||||||
if (rc != 0)
|
if (rc != 0)
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved.
|
* Copyright (c) 2013-2017, ARM Limited and Contributors. All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions are met:
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
@ -102,7 +102,7 @@ uint64_t tspd_handle_sp_preemption(void *handle)
|
||||||
cm_set_next_eret_context(NON_SECURE);
|
cm_set_next_eret_context(NON_SECURE);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The TSP was preempted during STD SMC execution.
|
* The TSP was preempted during execution of a Yielding SMC Call.
|
||||||
* Return back to the normal world with SMC_PREEMPTED as error
|
* Return back to the normal world with SMC_PREEMPTED as error
|
||||||
* code in x0.
|
* code in x0.
|
||||||
*/
|
*/
|
||||||
|
@ -146,7 +146,7 @@ static uint64_t tspd_sel1_interrupt_handler(uint32_t id,
|
||||||
* context since the TSP is supposed to preserve it during S-EL1
|
* context since the TSP is supposed to preserve it during S-EL1
|
||||||
* interrupt handling.
|
* interrupt handling.
|
||||||
*/
|
*/
|
||||||
if (get_std_smc_active_flag(tsp_ctx->state)) {
|
if (get_yield_smc_active_flag(tsp_ctx->state)) {
|
||||||
tsp_ctx->saved_spsr_el3 = SMC_GET_EL3(&tsp_ctx->cpu_ctx,
|
tsp_ctx->saved_spsr_el3 = SMC_GET_EL3(&tsp_ctx->cpu_ctx,
|
||||||
CTX_SPSR_EL3);
|
CTX_SPSR_EL3);
|
||||||
tsp_ctx->saved_elr_el3 = SMC_GET_EL3(&tsp_ctx->cpu_ctx,
|
tsp_ctx->saved_elr_el3 = SMC_GET_EL3(&tsp_ctx->cpu_ctx,
|
||||||
|
@ -345,7 +345,7 @@ uint64_t tspd_smc_handler(uint32_t smc_fid,
|
||||||
* Restore the relevant EL3 state which saved to service
|
* Restore the relevant EL3 state which saved to service
|
||||||
* this SMC.
|
* this SMC.
|
||||||
*/
|
*/
|
||||||
if (get_std_smc_active_flag(tsp_ctx->state)) {
|
if (get_yield_smc_active_flag(tsp_ctx->state)) {
|
||||||
SMC_SET_EL3(&tsp_ctx->cpu_ctx,
|
SMC_SET_EL3(&tsp_ctx->cpu_ctx,
|
||||||
CTX_SPSR_EL3,
|
CTX_SPSR_EL3,
|
||||||
tsp_ctx->saved_spsr_el3);
|
tsp_ctx->saved_spsr_el3);
|
||||||
|
@ -461,7 +461,7 @@ uint64_t tspd_smc_handler(uint32_t smc_fid,
|
||||||
#endif
|
#endif
|
||||||
/*
|
/*
|
||||||
* This function ID is used only by the SP to indicate it has finished
|
* This function ID is used only by the SP to indicate it has finished
|
||||||
* aborting a preempted Standard SMC request.
|
* aborting a preempted Yielding SMC Call.
|
||||||
*/
|
*/
|
||||||
case TSP_ABORT_DONE:
|
case TSP_ABORT_DONE:
|
||||||
|
|
||||||
|
@ -509,10 +509,10 @@ uint64_t tspd_smc_handler(uint32_t smc_fid,
|
||||||
case TSP_FAST_FID(TSP_MUL):
|
case TSP_FAST_FID(TSP_MUL):
|
||||||
case TSP_FAST_FID(TSP_DIV):
|
case TSP_FAST_FID(TSP_DIV):
|
||||||
|
|
||||||
case TSP_STD_FID(TSP_ADD):
|
case TSP_YIELD_FID(TSP_ADD):
|
||||||
case TSP_STD_FID(TSP_SUB):
|
case TSP_YIELD_FID(TSP_SUB):
|
||||||
case TSP_STD_FID(TSP_MUL):
|
case TSP_YIELD_FID(TSP_MUL):
|
||||||
case TSP_STD_FID(TSP_DIV):
|
case TSP_YIELD_FID(TSP_DIV):
|
||||||
if (ns) {
|
if (ns) {
|
||||||
/*
|
/*
|
||||||
* This is a fresh request from the non-secure client.
|
* This is a fresh request from the non-secure client.
|
||||||
|
@ -523,7 +523,7 @@ uint64_t tspd_smc_handler(uint32_t smc_fid,
|
||||||
assert(handle == cm_get_context(NON_SECURE));
|
assert(handle == cm_get_context(NON_SECURE));
|
||||||
|
|
||||||
/* Check if we are already preempted */
|
/* Check if we are already preempted */
|
||||||
if (get_std_smc_active_flag(tsp_ctx->state))
|
if (get_yield_smc_active_flag(tsp_ctx->state))
|
||||||
SMC_RET1(handle, SMC_UNK);
|
SMC_RET1(handle, SMC_UNK);
|
||||||
|
|
||||||
cm_el1_sysregs_context_save(NON_SECURE);
|
cm_el1_sysregs_context_save(NON_SECURE);
|
||||||
|
@ -553,13 +553,14 @@ uint64_t tspd_smc_handler(uint32_t smc_fid,
|
||||||
cm_set_elr_el3(SECURE, (uint64_t)
|
cm_set_elr_el3(SECURE, (uint64_t)
|
||||||
&tsp_vectors->fast_smc_entry);
|
&tsp_vectors->fast_smc_entry);
|
||||||
} else {
|
} else {
|
||||||
set_std_smc_active_flag(tsp_ctx->state);
|
set_yield_smc_active_flag(tsp_ctx->state);
|
||||||
cm_set_elr_el3(SECURE, (uint64_t)
|
cm_set_elr_el3(SECURE, (uint64_t)
|
||||||
&tsp_vectors->std_smc_entry);
|
&tsp_vectors->yield_smc_entry);
|
||||||
#if TSP_NS_INTR_ASYNC_PREEMPT
|
#if TSP_NS_INTR_ASYNC_PREEMPT
|
||||||
/*
|
/*
|
||||||
* Enable the routing of NS interrupts to EL3
|
* Enable the routing of NS interrupts to EL3
|
||||||
* during STD SMC processing on this core.
|
* during processing of a Yielding SMC Call on
|
||||||
|
* this core.
|
||||||
*/
|
*/
|
||||||
enable_intr_rm_local(INTR_TYPE_NS, SECURE);
|
enable_intr_rm_local(INTR_TYPE_NS, SECURE);
|
||||||
#endif
|
#endif
|
||||||
|
@ -585,13 +586,13 @@ uint64_t tspd_smc_handler(uint32_t smc_fid,
|
||||||
/* Restore non-secure state */
|
/* Restore non-secure state */
|
||||||
cm_el1_sysregs_context_restore(NON_SECURE);
|
cm_el1_sysregs_context_restore(NON_SECURE);
|
||||||
cm_set_next_eret_context(NON_SECURE);
|
cm_set_next_eret_context(NON_SECURE);
|
||||||
if (GET_SMC_TYPE(smc_fid) == SMC_TYPE_STD) {
|
if (GET_SMC_TYPE(smc_fid) == SMC_TYPE_YIELD) {
|
||||||
clr_std_smc_active_flag(tsp_ctx->state);
|
clr_yield_smc_active_flag(tsp_ctx->state);
|
||||||
#if TSP_NS_INTR_ASYNC_PREEMPT
|
#if TSP_NS_INTR_ASYNC_PREEMPT
|
||||||
/*
|
/*
|
||||||
* Disable the routing of NS interrupts to EL3
|
* Disable the routing of NS interrupts to EL3
|
||||||
* after STD SMC processing is finished on this
|
* after processing of a Yielding SMC Call on
|
||||||
* core.
|
* this core is finished.
|
||||||
*/
|
*/
|
||||||
disable_intr_rm_local(INTR_TYPE_NS, SECURE);
|
disable_intr_rm_local(INTR_TYPE_NS, SECURE);
|
||||||
#endif
|
#endif
|
||||||
|
@ -602,8 +603,8 @@ uint64_t tspd_smc_handler(uint32_t smc_fid,
|
||||||
|
|
||||||
break;
|
break;
|
||||||
/*
|
/*
|
||||||
* Request from the non-secure world to abort a preempted Standard SMC
|
* Request from the non-secure world to abort a preempted Yielding SMC
|
||||||
* call.
|
* Call.
|
||||||
*/
|
*/
|
||||||
case TSP_FID_ABORT:
|
case TSP_FID_ABORT:
|
||||||
/* ABORT should only be invoked by normal world */
|
/* ABORT should only be invoked by normal world */
|
||||||
|
@ -635,7 +636,7 @@ uint64_t tspd_smc_handler(uint32_t smc_fid,
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Request from non secure world to resume the preempted
|
* Request from non secure world to resume the preempted
|
||||||
* Standard SMC call.
|
* Yielding SMC Call.
|
||||||
*/
|
*/
|
||||||
case TSP_FID_RESUME:
|
case TSP_FID_RESUME:
|
||||||
/* RESUME should be invoked only by normal world */
|
/* RESUME should be invoked only by normal world */
|
||||||
|
@ -652,7 +653,7 @@ uint64_t tspd_smc_handler(uint32_t smc_fid,
|
||||||
assert(handle == cm_get_context(NON_SECURE));
|
assert(handle == cm_get_context(NON_SECURE));
|
||||||
|
|
||||||
/* Check if we are already preempted before resume */
|
/* Check if we are already preempted before resume */
|
||||||
if (!get_std_smc_active_flag(tsp_ctx->state))
|
if (!get_yield_smc_active_flag(tsp_ctx->state))
|
||||||
SMC_RET1(handle, SMC_UNK);
|
SMC_RET1(handle, SMC_UNK);
|
||||||
|
|
||||||
cm_el1_sysregs_context_save(NON_SECURE);
|
cm_el1_sysregs_context_save(NON_SECURE);
|
||||||
|
@ -664,7 +665,7 @@ uint64_t tspd_smc_handler(uint32_t smc_fid,
|
||||||
#if TSP_NS_INTR_ASYNC_PREEMPT
|
#if TSP_NS_INTR_ASYNC_PREEMPT
|
||||||
/*
|
/*
|
||||||
* Enable the routing of NS interrupts to EL3 during resumption
|
* Enable the routing of NS interrupts to EL3 during resumption
|
||||||
* of STD SMC call on this core.
|
* of a Yielding SMC Call on this core.
|
||||||
*/
|
*/
|
||||||
enable_intr_rm_local(INTR_TYPE_NS, SECURE);
|
enable_intr_rm_local(INTR_TYPE_NS, SECURE);
|
||||||
#endif
|
#endif
|
||||||
|
@ -724,13 +725,13 @@ DECLARE_RT_SVC(
|
||||||
tspd_smc_handler
|
tspd_smc_handler
|
||||||
);
|
);
|
||||||
|
|
||||||
/* Define a SPD runtime service descriptor for standard SMC calls */
|
/* Define a SPD runtime service descriptor for Yielding SMC Calls */
|
||||||
DECLARE_RT_SVC(
|
DECLARE_RT_SVC(
|
||||||
tspd_std,
|
tspd_std,
|
||||||
|
|
||||||
OEN_TOS_START,
|
OEN_TOS_START,
|
||||||
OEN_TOS_END,
|
OEN_TOS_END,
|
||||||
SMC_TYPE_STD,
|
SMC_TYPE_YIELD,
|
||||||
NULL,
|
NULL,
|
||||||
tspd_smc_handler
|
tspd_smc_handler
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved.
|
* Copyright (c) 2013-2017, ARM Limited and Contributors. All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions are met:
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
@ -57,7 +57,7 @@
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This flag is used by the TSPD to determine if the TSP is servicing a standard
|
* This flag is used by the TSPD to determine if the TSP is servicing a yielding
|
||||||
* SMC request prior to programming the next entry into the TSP e.g. if TSP
|
* SMC request prior to programming the next entry into the TSP e.g. if TSP
|
||||||
* execution is preempted by a non-secure interrupt and handed control to the
|
* execution is preempted by a non-secure interrupt and handed control to the
|
||||||
* normal world. If another request which is distinct from what the TSP was
|
* normal world. If another request which is distinct from what the TSP was
|
||||||
|
@ -65,15 +65,16 @@
|
||||||
* reject the new request or service it while ensuring that the previous context
|
* reject the new request or service it while ensuring that the previous context
|
||||||
* is not corrupted.
|
* is not corrupted.
|
||||||
*/
|
*/
|
||||||
#define STD_SMC_ACTIVE_FLAG_SHIFT 2
|
#define YIELD_SMC_ACTIVE_FLAG_SHIFT 2
|
||||||
#define STD_SMC_ACTIVE_FLAG_MASK 1
|
#define YIELD_SMC_ACTIVE_FLAG_MASK 1
|
||||||
#define get_std_smc_active_flag(state) ((state >> STD_SMC_ACTIVE_FLAG_SHIFT) \
|
#define get_yield_smc_active_flag(state) \
|
||||||
& STD_SMC_ACTIVE_FLAG_MASK)
|
((state >> YIELD_SMC_ACTIVE_FLAG_SHIFT) \
|
||||||
#define set_std_smc_active_flag(state) (state |= \
|
& YIELD_SMC_ACTIVE_FLAG_MASK)
|
||||||
1 << STD_SMC_ACTIVE_FLAG_SHIFT)
|
#define set_yield_smc_active_flag(state) (state |= \
|
||||||
#define clr_std_smc_active_flag(state) (state &= \
|
1 << YIELD_SMC_ACTIVE_FLAG_SHIFT)
|
||||||
~(STD_SMC_ACTIVE_FLAG_MASK \
|
#define clr_yield_smc_active_flag(state) (state &= \
|
||||||
<< STD_SMC_ACTIVE_FLAG_SHIFT))
|
~(YIELD_SMC_ACTIVE_FLAG_MASK \
|
||||||
|
<< YIELD_SMC_ACTIVE_FLAG_SHIFT))
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* Secure Payload execution state information i.e. aarch32 or aarch64
|
* Secure Payload execution state information i.e. aarch32 or aarch64
|
||||||
|
|
Loading…
Add table
Reference in a new issue