Add EL3 runtime services and SPD documentation

1. Add design information on EL3 runtime services and
Secure-EL1 Payload Dispatchers (SPD) to
firmware-design.md.

2. Create new EL3 runtime service writer's guide
(rt-svc-writers-guide.md) to ease creation of new
runtime services.

Change-Id: I670aeb5fc246e25c6e599a15139aac886a0074fd
This commit is contained in:
Dan Handley 2014-02-25 19:09:48 +00:00
parent 247f60bcbc
commit 5e1e920075
3 changed files with 634 additions and 49 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

View File

@ -4,11 +4,14 @@ ARM Trusted Firmware Design
Contents :
1. Introduction
2. Cold Boot
3. Memory layout on FVP platforms
4. Firmware Image Package (FIP)
5. Code Structure
6. References
2. Cold boot
3. EL3 runtime services framework
4. Power State Coordination Interface
5. Secure-EL1 Payloads and Dispatchers
6. Memory layout on FVP platforms
7. Firmware Image Package (FIP)
8. Code Structure
9. References
1. Introduction
@ -29,7 +32,7 @@ instruction. The SMC instruction must be used as mandated by the [SMC Calling
Convention PDD][SMCCC] [3].
2. Cold Boot
2. Cold boot
-------------
The cold boot path starts when the platform is physically turned on. One of
@ -334,59 +337,330 @@ memory address populated by BL2.
* Runtime services initialization:
The only runtime service implemented by BL3-1 is PSCI. The complete PSCI API
is not yet implemented. The following functions are currently implemented:
The runtime service framework and its initialization is described in the
"EL3 runtime services framework" section below.
- `PSCI_VERSION`
- `CPU_OFF`
- `CPU_ON`
- `CPU_SUSPEND`
- `AFFINITY_INFO`
Details about the PSCI service are provided in the "Power State Coordination
Interface" section below.
The `CPU_ON`, `CPU_OFF` and `CPU_SUSPEND` functions implement the warm boot
path in ARM Trusted Firmware. `CPU_ON` and `CPU_OFF` have undergone testing
on all the supported FVPs. `CPU_SUSPEND` & `AFFINITY_INFO` have undergone
testing only on the AEM v8 Base FVP. Support for `AFFINITY_INFO` is still
experimental. Support for `CPU_SUSPEND` is stable for entry into power down
states. Standby states are currently not supported. `PSCI_VERSION` is
present but completely untested in this version of the software.
* BL3-2 (Secure-EL1 Payload) image initialization
Unsupported PSCI functions can be divided into ones that can return
execution to the caller and ones that cannot. The following functions
return with a error code as documented in the [Power State Coordination
Interface PDD] [PSCI].
If a BL3-2 image is present then there must be a matching Secure-EL1 Payload
Dispatcher (SPD) service (see later for details). During initialization
that service must register a function to carry out initialization of BL3-2
once the runtime services are fully initialized. BL3-1 invokes such a
registered function to initialize BL3-2 before running BL3-3.
- `MIGRATE` : -1 (NOT_SUPPORTED)
- `MIGRATE_INFO_TYPE` : 2 (Trusted OS is either not present or does not
require migration)
- `MIGRATE_INFO_UP_CPU` : 0 (Return value is UNDEFINED)
Details on BL3-2 initialization and the SPD's role are described in the
"Secure-EL1 Payloads and Dispatchers" section below.
The following unsupported functions do not return and signal an assertion
failure if invoked.
* BL3-3 (Non-trusted Firmware) execution
- `SYSTEM_OFF`
- `SYSTEM_RESET`
BL3-1 returns the error code `-1` if an SMC is raised for any other runtime
service. This behavior is mandated by the [SMC calling convention PDD]
[SMCCC].
BL3-1 initializes the EL2 or EL1 processor context for normal-world cold
boot, ensuring that no secure state information finds its way into the
non-secure execution state. BL3-1 uses the entrypoint information provided
by BL2 to jump to the Non-trusted firmware image (BL3-3) at the highest
available Exception Level (EL2 if available, otherwise EL1).
### BL3-2 (Secure Payload) image initialization
3. EL3 runtime services framework
----------------------------------
BL2 is responsible for loading a BL3-2 image in memory specified by the platform.
BL3-1 provides an api that uses the entrypoint and memory layout information for
the BL3-2 image provided by BL2 to initialise BL3-2 in S-EL1.
Software executing in the non-secure state and in the secure state at exception
levels lower than EL3 will request runtime services using the Secure Monitor
Call (SMC) instruction. These requests will follow the convention described in
the SMC Calling Convention PDD ([SMCCC]). The [SMCCC] assigns function
identifiers to each SMC request and describes how arguments are passed and
returned.
The EL3 runtime services framework enables the development of services by
different providers that can be easily integrated into final product firmware.
The following sections describe the framework which facilitates the
registration, initialization and use of runtime services in EL3 Runtime
Firmware (BL3-1).
The design of the runtime services depends heavily on the concepts and
definitions described in the [SMCCC], in particular SMC Function IDs, Owning
Entity Numbers (OEN), Fast and Standard calls, and the SMC32 and SMC64 calling
conventions. Please refer to that document for more detailed explanation of
these terms.
The following runtime services are expected to be implemented first. They have
not all been instantiated in the current implementation.
1. Standard service calls
This service is for management of the entire system. The Power State
Coordination Interface ([PSCI]) is the first set of standard service calls
defined by ARM (see PSCI section later).
NOTE: Currently this service is called PSCI since there are no other
defined standard service calls.
2. Secure-EL1 Payload Dispatcher service
If a system runs a Trusted OS or other Secure-EL1 Payload (SP) then
it also requires a _Secure Monitor_ at EL3 to switch the EL1 processor
context between the normal world (EL1/EL2) and trusted world (Secure-EL1).
The Secure Monitor will make these world switches in response to SMCs. The
[SMCCC] provides for such SMCs with the Trusted OS Call and Trusted
Application Call OEN ranges.
The interface between the EL3 Runtime Firmware and the Secure-EL1 Payload is
not defined by the [SMCCC] or any other standard. As a result, each
Secure-EL1 Payload requires a specific Secure Monitor that runs as a runtime
service - within ARM Trusted Firmware this service is referred to as the
Secure-EL1 Payload Dispatcher (SPD).
ARM Trusted Firmware provides a Test Secure-EL1 Payload (TSP) and its
associated Dispatcher (TSPD). Details of SPD design and TSP/TSPD operation
are described in the "Secure-EL1 Payloads and Dispatchers" section below.
3. CPU implementation service
This service will provide an interface to CPU implementation specific
services for a given platform e.g. access to processor errata workarounds.
This service is currently unimplemented.
Additional services for ARM Architecture, SiP and OEM calls can be implemented.
Each implemented service handles a range of SMC function identifiers as
described in the [SMCCC].
### Normal world software execution
### Registration
BL3-1 uses the entrypoint information provided by BL2 to jump to the normal
world software image (BL3-3) at the highest available Exception Level (EL2 if
available, otherwise EL1).
A runtime service is registered using the `DECLARE_RT_SVC()` macro, specifying
the name of the service, the range of OENs covered, the type of service and
initialization and call handler functions. This macro instantiates a `const
struct rt_svc_desc` for the service with these details (see `runtime_svc.h`).
This structure is allocated in a special ELF section `rt_svc_descs`, enabling
the framework to find all service descriptors included into BL3-1.
The specific service for a SMC Function is selected based on the OEN and call
type of the Function ID, and the framework uses that information in the service
descriptor to identify the handler for the SMC Call.
The service descriptors do not include information to identify the precise set
of SMC function identifiers supported by this service implementation, the
security state from which such calls are valid nor the capability to support
64-bit and/or 32-bit callers (using SMC32 or SMC64). Responding appropriately
to these aspects of a SMC call is the responsibility of the service
implementation, the framework is focused on integration of services from
different providers and minimizing the time taken by the framework before the
service handler is invoked.
Details of the parameters, requirements and behavior of the initialization and
call handling functions are provided in the following sections.
3. Memory layout on FVP platforms
### Initialization
`runtime_svc_init()` in `runtime_svc.c` initializes the runtime services
framework running on the primary CPU during cold boot as part of the BL3-1
initialization. This happens prior to initializing a Trusted OS and running
Normal world boot firmware that might in turn use these services.
Initialization involves validating each of the declared runtime service
descriptors, calling the service initialization function and populating the
index used for runtime lookup of the service.
The BL3-1 linker script collects all of the declared service descriptors into a
single array and defines symbols that allow the framework to locate and traverse
the array, and determine its size.
The framework does basic validation of each descriptor to halt firmware
initialization if service declaration errors are detected. The framework does
not check descriptors for the following error conditions, and may behave in an
unpredictable manner under such scenarios:
1. Overlapping OEN ranges
2. Multiple descriptors for the same range of OENs and `call_type`
3. Incorrect range of owning entity numbers for a given `call_type`
Once validated, the service `init()` callback is invoked. This function carries
out any essential EL3 initialization before servicing requests. The `init()`
function is only invoked on the primary CPU during cold boot. If the service
uses per-CPU data this must either be initialized for all CPUs during this call,
or be done lazily when a CPU first issues an SMC call to that service. If
`init()` returns anything other than `0`, this is treated as an initialization
error and the service is ignored: this does not cause the firmware to halt.
The OEN and call type fields present in the SMC Function ID cover a total of
128 distinct services, but in practice a single descriptor can cover a range of
OENs, e.g. SMCs to call a Trusted OS function. To optimize the lookup of a
service handler, the framework uses an array of 128 indices that map every
distinct OEN/call-type combination either to one of the declared services or to
indicate the service is not handled. This `rt_svc_descs_indices[]` array is
populated for all of the OENs covered by a service after the service `init()`
function has reported success. So a service that fails to initialize will never
have it's `handle()` function invoked.
The following figure shows how the `rt_svc_descs_indices[]` index maps the SMC
Function ID call type and OEN onto a specific service handler in the
`rt_svc_descs[]` array.
![Image 1](diagrams/rt-svc-descs-layout.png?raw=true)
### Handling an SMC
When the EL3 runtime services framework receives a Secure Monitor Call, the SMC
Function ID is passed in W0 from the lower exception level (as per the
[SMCCC]). If the calling register width is AArch32, it is invalid to invoke an
SMC Function which indicates the SMC64 calling convention: such calls are
ignored and return the Unknown SMC Function Identifier result code `0xFFFFFFFF`
in R0/X0.
Bit[31] (fast/standard 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
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
used as a further index into the `rt_svc_descs[]` array to locate the required
service and handler.
The service's `handle()` callback is provided with five of the SMC parameters
directly, the others are saved into memory for retrieval (if needed) by the
handler. The handler is also provided with an opaque `handle` for use with the
supporting library for parameter retrieval, setting return values and context
manipulation; and with `flags` indicating the security state of the caller. The
framework finally sets up the execution stack for the handler, and invokes the
services `handle()` function.
On return from the handler the result registers are populated in X0-X3 before
restoring the stack and CPU state and returning from the original SMC.
4. Power State Coordination Interface
--------------------------------------
TODO: Provide design walkthrough of PSCI implementation.
The complete PSCI API is not yet implemented. The following functions are
currently implemented:
- `PSCI_VERSION`
- `CPU_OFF`
- `CPU_ON`
- `CPU_SUSPEND`
- `AFFINITY_INFO`
The `CPU_ON`, `CPU_OFF` and `CPU_SUSPEND` functions implement the warm boot
path in ARM Trusted Firmware. `CPU_ON` and `CPU_OFF` have undergone testing
on all the supported FVPs. `CPU_SUSPEND` & `AFFINITY_INFO` have undergone
testing only on the AEM v8 Base FVP. Support for `AFFINITY_INFO` is still
experimental. Support for `CPU_SUSPEND` is stable for entry into power down
states. Standby states are currently not supported. `PSCI_VERSION` is
present but completely untested in this version of the software.
Unsupported PSCI functions can be divided into ones that can return
execution to the caller and ones that cannot. The following functions
return with a error code as documented in the [Power State Coordination
Interface PDD] [PSCI].
- `MIGRATE` : -1 (NOT_SUPPORTED)
- `MIGRATE_INFO_TYPE` : 2 (Trusted OS is either not present or does not
require migration)
- `MIGRATE_INFO_UP_CPU` : 0 (Return value is UNDEFINED)
The following unsupported functions do not return and signal an assertion
failure if invoked.
- `SYSTEM_OFF`
- `SYSTEM_RESET`
5. Secure-EL1 Payloads and Dispatchers
---------------------------------------
On a production system that includes a Trusted OS running in Secure-EL1/EL0,
the Trusted OS is coupled with a companion runtime service in the BL3-1
firmware. This service is responsible for the initialisation of the Trusted
OS and all communications with it. The Trusted OS is the BL3-2 stage of the
boot flow in ARM Trusted Firmware. The firmware will attempt to locate, load
and execute a BL3-2 image.
ARM Trusted Firmware uses a more general term for the BL3-2 software that runs
at Secure-EL1 - the _Secure-EL1 Payload_ - as it is not always a Trusted OS.
The ARM Trusted Firmware provides a Test Secure-EL1 Payload (TSP) and a Test
Secure-EL1 Payload Dispatcher (TSPD) service as an example of how a Trusted OS
is supported on a production system using the Runtime Services Framework. On
such a system, the Test BL3-2 image and service are replaced by the Trusted OS
and its dispatcher service.
The TSP runs in Secure-EL1. It is designed to demonstrate synchronous
communication with the normal-world software running in EL1/EL2. Communication
is initiated by the normal-world software
* either directly through a Fast SMC (as defined in the [SMCCC])
* or indirectly through a [PSCI] SMC. The [PSCI] implementation in turn
informs the TSPD about the requested power management operation. This allows
the TSP to prepare for or respond to the power state change
The TSPD service is responsible for.
* Initializing the TSP
* Routing requests and responses between the secure and the non-secure
states during the two types of communications just described
### Initializing a BL3-2 Image
The Secure-EL1 Payload Dispatcher (SPD) service is responsible for initializing
the BL3-2 image. It needs access to the information passed by BL2 to BL3-1 to do
so. Hence BL3-1 implements:
1. `bl31_plat_get_bl32_mem_layout()` to return the extents of memory
available for BL3-2's use as communicated by BL2.
2. `bl31_get_next_image_info(uint32_t security_state)` to return a reference
to the `el_change_info` structure corresponding to the next image which will
be run in the specified security state. The SPD uses this api with the
secure security state as the parameter to get entry related information about
BL3-2.
In the absence of a BL3-2 image, BL3-1 passes control to the normal world
bootloader image (BL3-3). When the BL3-2 image is present, it is typical
that the SPD wants control to be passed to BL3-2 first and then later to BL3-3.
To do this the SPD has to register a BL3-2 initialization function during
initialization of the SPD service. The BL3-2 initialization function has this
prototype:
int32_t init(meminfo *bl32_meminfo);
and is registered using the `bl31_register_bl32_init()` function.
Trusted Firmware supports two approaches for the SPD to pass control to BL3-2
before returning through EL3 and running the non-trusted firmware (BL3-3):
1. In the BL3-2 initialization function, set up a secure context (see below
for more details of CPU context support) for this CPU and use
`bl31_set_next_image_type()` to request that the exit from `bl31_main()` is
to the BL3-2 entrypoint in Secure-EL1.
When the BL3-2 has completed initialization at Secure-EL1, it returns to
BL3-1 by issuing an SMC, using a Function ID allocated to the SPD. On
receipt of this SMC, the SPD service handler should switch the CPU context
from trusted to normal world and use the `bl31_set_next_image_type()` and
`bl31_prepare_next_image_entry()` functions to set up the initial return to
the normal world firmware BL3-3. On return from the handler the framework
will exit to EL2 and run BL3-3.
2. In the BL3-2 initialization function, use an SPD-defined mechanism to
invoke a 'world-switch synchronous call' to Secure-EL1 to run the BL3-2
entrypoint.
NOTE: The Test SPD service included with the Trusted Firmware provides one
implementation of such a mechanism.
On completion BL3-2 returns control to BL3-1 via a SMC, and on receipt the
SPD service handler invokes the synchronous call return mechanism to return
to the BL3-2 initialization function. On return from this function,
`bl31_main()` will set up the return to the normal world firmware BL3-3 and
continue the boot process in the normal world.
6. Memory layout on FVP platforms
----------------------------------
On FVP platforms, we use the Trusted ROM and Trusted SRAM to store the trusted
@ -659,7 +933,7 @@ following view:
------------ 0x04000000
4. Firmware Image Package (FIP)
7. Firmware Image Package (FIP)
--------------------------------
Using a Firmware Image Package (FIP) allows for packing bootloader images (and
@ -739,7 +1013,7 @@ Currently the FVPs policy only allows for loading of known images. The platform
policy can be modified to add additional images.
5. Code Structure
8. Code Structure
------------------
Trusted Firmware code is logically divided between the three boot loader
@ -754,11 +1028,13 @@ following categories (present as directories in the source code):
other code.
* **Stage specific.** Code specific to a boot stage.
* **Drivers.**
* **Services.** EL3 runtime services, e.g. PSCI or SPD. Specific SPD services
reside in the `services/spd` directory (e.g. `services/spd/tspd`).
Each boot loader stage uses code from one or more of the above mentioned
categories. Based upon the above, the code layout looks like this:
Directory Used by BL1? Used by BL2? Used by BL3?
Directory Used by BL1? Used by BL2? Used by BL3-1?
bl1 Yes No No
bl2 No Yes No
bl31 No No Yes
@ -767,6 +1043,7 @@ categories. Based upon the above, the code layout looks like this:
drivers Yes No Yes
common Yes Yes Yes
lib Yes Yes Yes
services No No Yes
All assembler files have the `.S` extension. The linker source files for each
boot stage have the extension `.ld.S`. These are processed by GCC to create the
@ -776,7 +1053,7 @@ FDTs provide a description of the hardware platform and are used by the Linux
kernel at boot time. These can be found in the `fdts` directory.
6. References
9. References
--------------
1. Trusted Board Boot Requirements CLIENT PDD (ARM DEN 0006B-5). Available

View File

@ -0,0 +1,308 @@
EL3 Runtime Service Writers Guide for ARM Trusted Firmware
==========================================================
Contents
--------
1. Introduction
2. Owning Entities, Call Types and Function IDs
3. Getting started
4. Registering a runtime service
5. Initializing a runtime service
6. Handling runtime service requests
7. Services that contain multiple sub-services
8. Secure-EL1 Payload Dispatcher service (SPD)
- - - - - - - - - - - - - - - - - -
1. Introduction
----------------
This document describes how to add a runtime service to the EL3 Runtime
Firmware component of ARM Trusted Firmware (BL3-1).
Software executing in the normal world and in the trusted world at exception
levels lower than EL3 will request runtime services using the Secure Monitor
Call (SMC) instruction. These requests will follow the convention described in
the SMC Calling Convention PDD ([SMCCC]). The [SMCCC] assigns function
identifiers to each SMC request and describes how arguments are passed and
results are returned.
SMC Functions are grouped together based on the implementor of the service, for
example a subset of the Function IDs are designated as "OEM Calls" (see [SMCCC]
for full details). The EL3 runtime services framework in BL3-1 enables the
independent implementation of services for each group, which are then compiled
into the BL3-1 image. This simplifies the integration of common software from
ARM to support [PSCI], Secure Monitor for a Trusted OS and SoC specific
software. The common runtime services framework ensures that SMC Functions are
dispatched to their respective service implementation - the [Firmware Design]
provides details of how this is achieved.
The interface and operation of the runtime services depends heavily on the
concepts and definitions described in the [SMCCC], in particular SMC Function
IDs, Owning Entity Numbers (OEN), Fast and Standard calls, and the SMC32 and
SMC64 calling conventions. Please refer to that document for a full explanation
of these terms.
2. Owning Entities, Call Types and Function IDs
------------------------------------------------
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
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
uninterruptible whereas Standard calls can be pre-empted. The majority of
Owning Entities only have allocated ranges for Fast calls: Standard calls are
reserved exclusively for Trusted OS providers or for interoperability with
legacy 32-bit software that predates the [SMCCC].
Type OEN Service
Fast 0 ARM Architecture calls
Fast 1 CPU Service calls
Fast 2 SiP Service calls
Fast 3 OEM Service calls
Fast 4 Standard Service calls
Fast 5-47 Reserved for future use
Fast 48-49 Trusted Application calls
Fast 50-63 Trusted OS calls
Std 0- 1 Reserved for existing ARMv7 calls
Std 2-63 Trusted OS Standard Calls
_Table 1: Service types and their corresponding Owning Entity Numbers_
Each individual entity can allocate the valid identifiers within the entity
range as they need - it is not necessary to coordinate with other entities of
the same type. For example, two SoC providers can use the same Function ID
within the SiP Service calls OEN range to mean different things - as these
calls should be specific to the SoC. The Standard Runtime Calls OEN is used for
services defined by ARM standards, such as [PSCI].
The SMC Function ID also indicates whether the call has followed the SMC32
calling convention, where all parameters are 32-bit, or the SMC64 calling
convention, where the parameters are 64-bit. The framework identifies and
rejects invalid calls that use the SMC64 calling convention but that originate
from an AArch32 caller.
The EL3 runtime services framework uses the call type and OEN to identify a
specific handler for each SMC call, but it is expected that an individual
handler will be responsible for all SMC Functions within a given service type.
3. Getting started
-------------------
ARM Trusted Firmware has a [`services`] directory in the source tree under
which each owning entity can place the implementation of its runtime service.
The [PSCI] implementation is located here in the [`services/psci`] directory.
Runtime service sources will need to include the [`runtime_svc.h`] header file.
4. Registering a runtime service
---------------------------------
A runtime service is registered using the `DECLARE_RT_SVC()` macro, specifying
the name of the service, the range of OENs covered, the type of service and
initialization and call handler functions.
#define DECLARE_RT_SVC(_name, _start, _end, _type, _setup, _smch)
* `_name` is used to identify the data structure declared by this macro, and
is also used for diagnostic purposes
* `_start` and `_end` values must be based on the `OEN_*` values defined in
[`runtime_svc.h`]
* `_type` must be one of `SMC_TYPE_FAST` or `SMC_TYPE_STD`
* `_setup` is the initialization function with the `rt_svc_init` signature:
typedef int32_t (*rt_svc_init)(void);
* `_smch` is the SMC handler function with the `rt_svc_handle` signature:
typedef uint64_t (*rt_svc_handle)(uint32_t smc_fid,
uint64_t x1, uint64_t x2,
uint64_t x3, uint64_t x4,
void *reserved,
void *handle,
uint64_t flags);
Details of the requirements and behavior of the two callbacks is provided in
the following sections.
During initialization the services framework validates each declared service
to ensure that the following conditions are met:
1. The `_start` OEN is not greater than the `_end` OEN
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`
4. `_setup` and `_smch` routines have been specified
[`psci_steup.c`] provides an example of registering a runtime service:
/* Register PSCI as a run time service */
DECLARE_RT_SVC(
psci,
OEN_STD_START,
OEN_STD_END,
SMC_TYPE_FAST,
psci_setup,
psci_smc_handler
);
5. Initializing a runtime service
---------------------------------
Runtime services are initialized once, during cold boot, by the primary CPU
after platform and architectural initialization is complete. The framework
performs basic validation of the declared service before calling
the service initialization function (`_setup` in the declaration). This
function must carry out any essential EL3 initialization prior to receiving a
SMC Function call via the handler function.
On success, the initialization function must return `0`. Any other return value
will cause the framework to issue a diagnostic:
Error initializing runtime service <name of the service>
and then ignore the service - the system will continue to boot but SMC calls
will not be passed to the service handler and instead return the _Unknown SMC
Function ID_ result `0xFFFFFFFF`.
If the system must not be allowed to proceed without the service, the
initialization function must itself cause the firmware boot to be halted.
If the service uses per-CPU data this must either be initialized for all CPUs
during this call, or be done lazily when a CPU first issues an SMC call to that
service.
6. Handling runtime service requests
-------------------------------------
SMC calls for a service are forwarded by the framework to the service's SMC
handler function (`_smch` in the service declaration). This function must have
the following signature:
typedef uint64_t (*rt_svc_handle)(uint32_t smc_fid,
uint64_t x1, uint64_t x2,
uint64_t x3, uint64_t x4,
void *reserved,
void *handle,
uint64_t flags);
The handler is responsible for:
1. Determining that `smc_fid` is a valid and supported SMC Function ID,
otherwise completing the request with the _Unknown SMC Function ID_:
SMC_RET1(handle, SMC_UNK);
2. Determining if the requested function is valid for the calling security
state. SMC Calls can be made from both the normal and trusted worlds and
the framework will forward all calls to the service handler.
The `flags` parameter to this function indicates the caller security state
in bit[0], where a value of `1` indicates a non-secure caller. The
`is_caller_secure(flags)` and `is_caller_non_secure(flags)` can be used to
test this condition.
If invalid, the request should be completed with:
SMC_RET1(handle, SMC_UNK);
3. Truncating parameters for calls made using the SMC32 calling convention.
Such calls can be determined by checking the CC field in bit[30] of the
`smc_fid` parameter, for example by using:
if (GET_SMC_CC(smc_fid) == SMC_32) ...
For such calls, the upper bits of the parameters x1-x4 and the saved
parameters X5-X7 are UNDEFINED and must be explicitly ignored by the
handler. This can be done by truncating the values to a suitable 32-bit
integer type before use, for example by ensuring that functions defined
to handle individual SMC Functions use appropriate 32-bit parameters.
4. Providing the service requested by the SMC Function, utilizing the
immediate parameters x1-x4 and/or the additional saved parameters X5-X7.
The latter can be retrieved using the `SMC_GET_GP(handle, ref)` function,
supplying the appropriate `CTX_GPREG_Xn` reference, e.g.
uint64_t x6 = SMC_GET_GP(handle, CTX_GPREG_X6);
5. Implementing the standard SMC32 Functions that provide information about
the implementation of the service. These are the Call Count, Implementor
UID and Revision Details for each service documented in section 6 of the
[SMCCC].
The ARM Trusted Firmware expects owning entities to follow this
recommendation.
5. Returning the result to the caller. The [SMCCC] allows for up to 256 bits
of return value in SMC64 using X0-X3 and 128 bits in SMC32 using W0-W3. The
framework provides a family of macros to set the multi-register return
value and complete the handler:
SMC_RET1(handle, x0);
SMC_RET2(handle, x0, x1);
SMC_RET3(handle, x0, x1, x2);
SMC_RET4(handle, x0, x1, x2, x3);
The `reserved` parameter to the handler is reserved for future use and can be
ignored. The value returned by a SMC handler is also reserved for future use -
completion of the handler function must always be via one of the `SMC_RETn()`
macros.
NOTE: The PSCI and Test Secure-EL1 Payload Dispatcher services do not follow
all of the above requirements yet.
7. Services that contain multiple sub-services
-----------------------------------------------
It is possible that a single owning entity implements multiple sub-services. For
example, the Standard calls service handles `0x84000000`-`0x8400FFFF` and
`0xC4000000`-`0xC400FFFF` functions. Within that range, the [PSCI] service
handles the `0x84000000`-`0x8400001F` and `0xC4000000`-`0xC400001F` functions.
In that respect, [PSCI] is a 'sub-service' of the Standard calls service. In
future, there could be additional such sub-services in the Standard calls
service which perform independent functions.
In this situation it may be valuable to introduce a second level framework to
enable independent implementation of sub-services. Such a framework might look
very similar to the current runtime services framework, but using a different
part of the SMC Function ID to identify the sub-service. Trusted Firmware does
not provide such a framework at present.
8. Secure-EL1 Payload Dispatcher service (SPD)
-----------------------------------------------
Services that handle SMC Functions targeting a Trusted OS, Trusted Application,
or other Secure-EL1 Payload are special. These services need to manage the
Secure-EL1 context, provide the _Secure Monitor_ functionality of switching
between the normal and secure worlds, deliver SMC Calls through to Secure-EL1
and generally manage the Secure-EL1 Payload through CPU power-state transitions.
TODO: Provide details of the additional work required to implement a SPD and
the BL3-1 support for these services. Or a reference to the document that will
provide this information....
- - - - - - - - - - - - - - - - - - - - - - - - - -
_Copyright (c) 2014, ARM Limited and Contributors. All rights reserved._
[Firmware Design]: ./firmware-design.md
[`services`]: ../services
[`services/psci`]: ../services/psci
[`psci_steup.c`]: ../services/psci/psci_setup.c
[`runtime_svc.h`]: ../include/runtime_svc.h
[PSCI]: http://infocenter.arm.com/help/topic/com.arm.doc.den0022b/index.html "Power State Coordination Interface PDD (ARM DEN 0022B.b)"
[SMCCC]: http://infocenter.arm.com/help/topic/com.arm.doc.den0028a/index.html "SMC Calling Convention PDD (ARM DEN 0028A)"