1PSCI Library Integration guide for Armv8-A AArch32 systems 2========================================================== 3 4This document describes the PSCI library interface with a focus on how to 5integrate with a suitable Trusted OS for an Armv8-A AArch32 system. The PSCI 6Library implements the PSCI Standard as described in `PSCI`_ and is meant 7to be integrated with EL3 Runtime Software which invokes the PSCI Library 8interface appropriately. **EL3 Runtime Software** refers to software executing 9at the highest secure privileged mode, which is EL3 in AArch64 or Secure SVC/ 10Monitor mode in AArch32, and provides runtime services to the non-secure world. 11The runtime service request is made via SMC (Secure Monitor Call) and the call 12must adhere to `SMCCC`_. In AArch32, EL3 Runtime Software may additionally 13include Trusted OS functionality. A minimal AArch32 Secure Payload, SP-MIN, is 14provided in Trusted Firmware-A (TF-A) to illustrate the usage and integration 15of the PSCI library. The description of PSCI library interface and its 16integration with EL3 Runtime Software in this document is targeted towards 17AArch32 systems. 18 19Generic call sequence for PSCI Library interface (AArch32) 20---------------------------------------------------------- 21 22The generic call sequence of PSCI Library interfaces (see 23`PSCI Library Interface`_) during cold boot in AArch32 24system is described below: 25 26#. After cold reset, the EL3 Runtime Software performs its cold boot 27 initialization including the PSCI library pre-requisites mentioned in 28 `PSCI Library Interface`_, and also the necessary platform 29 setup. 30 31#. Call ``psci_setup()`` in Monitor mode. 32 33#. Optionally call ``psci_register_spd_pm_hook()`` to register callbacks to 34 do bookkeeping for the EL3 Runtime Software during power management. 35 36#. Call ``psci_prepare_next_non_secure_ctx()`` to initialize the non-secure CPU 37 context. 38 39#. Get the non-secure ``cpu_context_t`` for the current CPU by calling 40 ``cm_get_context()`` , then programming the registers in the non-secure 41 context and exiting to non-secure world. If the EL3 Runtime Software needs 42 additional configuration to be set for non-secure context, like routing 43 FIQs to the secure world, the values of the registers can be modified prior 44 to programming. See `PSCI CPU context management`_ for more 45 details on CPU context management. 46 47The generic call sequence of PSCI library interfaces during warm boot in 48AArch32 systems is described below: 49 50#. After warm reset, the EL3 Runtime Software performs the necessary warm 51 boot initialization including the PSCI library pre-requisites mentioned in 52 `PSCI Library Interface`_ (Note that the Data cache 53 **must not** be enabled). 54 55#. Call ``psci_warmboot_entrypoint()`` in Monitor mode. This interface 56 initializes/restores the non-secure CPU context as well. 57 58#. Do step 5 of the cold boot call sequence described above. 59 60The generic call sequence of PSCI library interfaces on receipt of a PSCI SMC 61on an AArch32 system is described below: 62 63#. On receipt of an SMC, save the register context as per `SMCCC`_. 64 65#. If the SMC function identifier corresponds to a SMC32 PSCI API, construct 66 the appropriate arguments and call the ``psci_smc_handler()`` interface. 67 The invocation may or may not return back to the caller depending on 68 whether the PSCI API resulted in power down of the CPU. 69 70#. If ``psci_smc_handler()`` returns, populate the return value in R0 (AArch32)/ 71 X0 (AArch64) and restore other registers as per `SMCCC`_. 72 73PSCI CPU context management 74--------------------------- 75 76PSCI library is in charge of initializing/restoring the non-secure CPU system 77registers according to `PSCI`_ during cold/warm boot. 78This is referred to as ``PSCI CPU Context Management``. Registers that need to 79be preserved across CPU power down/power up cycles are maintained in 80``cpu_context_t`` data structure. The initialization of other non-secure CPU 81system registers which do not require coordination with the EL3 Runtime 82Software is done directly by the PSCI library (see ``cm_prepare_el3_exit()``). 83 84The EL3 Runtime Software is responsible for managing register context 85during switch between Normal and Secure worlds. The register context to be 86saved and restored depends on the mechanism used to trigger the world switch. 87For example, if the world switch was triggered by an SMC call, then the 88registers need to be saved and restored according to `SMCCC`_. In AArch64, 89due to the tight integration with BL31, both BL31 and PSCI library 90use the same ``cpu_context_t`` data structure for PSCI CPU context management 91and register context management during world switch. This cannot be assumed 92for AArch32 EL3 Runtime Software since most AArch32 Trusted OSes already implement 93a mechanism for register context management during world switch. Hence, when 94the PSCI library is integrated with a AArch32 EL3 Runtime Software, the 95``cpu_context_t`` is stripped down for just PSCI CPU context management. 96 97During cold/warm boot, after invoking appropriate PSCI library interfaces, it 98is expected that the EL3 Runtime Software will query the ``cpu_context_t`` and 99write appropriate values to the corresponding system registers. This mechanism 100resolves 2 additional problems for AArch32 EL3 Runtime Software: 101 102#. Values for certain system registers like SCR and SCTLR cannot be 103 unilaterally determined by PSCI library and need inputs from the EL3 104 Runtime Software. Using ``cpu_context_t`` as an intermediary data store 105 allows EL3 Runtime Software to modify the register values appropriately 106 before programming them. 107 108#. The PSCI library provides appropriate LR and SPSR values (entrypoint 109 information) for exit into non-secure world. Using ``cpu_context_t`` as an 110 intermediary data store allows the EL3 Runtime Software to store these 111 values safely until it is ready for exit to non-secure world. 112 113Currently the ``cpu_context_t`` data structure for AArch32 stores the following 114registers: R0 - R3, LR (R14), SCR, SPSR, SCTLR. 115 116The EL3 Runtime Software must implement accessors to get/set pointers 117to CPU context ``cpu_context_t`` data and these are described in 118`CPU Context management API`_. 119 120PSCI Library Interface 121---------------------- 122 123The PSCI library implements the `PSCI`_. The interfaces to this library are 124declared in ``psci_lib.h`` and are as listed below: 125 126.. code:: c 127 128 u_register_t psci_smc_handler(uint32_t smc_fid, u_register_t x1, 129 u_register_t x2, u_register_t x3, 130 u_register_t x4, void *cookie, 131 void *handle, u_register_t flags); 132 int psci_setup(const psci_lib_args_t *lib_args); 133 void psci_warmboot_entrypoint(void); 134 void psci_register_spd_pm_hook(const spd_pm_ops_t *pm); 135 void psci_prepare_next_non_secure_ctx(entry_point_info_t *next_image_info); 136 137The CPU context data 'cpu_context_t' is programmed to the registers differently 138when PSCI is integrated with an AArch32 EL3 Runtime Software compared to 139when the PSCI is integrated with an AArch64 EL3 Runtime Software (BL31). For 140example, in the case of AArch64, there is no need to retrieve ``cpu_context_t`` 141data and program the registers as it will done implicitly as part of 142``el3_exit``. The description below of the PSCI interfaces is targeted at 143integration with an AArch32 EL3 Runtime Software. 144 145The PSCI library is responsible for initializing/restoring the non-secure world 146to an appropriate state after boot and may choose to directly program the 147non-secure system registers. The PSCI generic code takes care not to directly 148modify any of the system registers affecting the secure world and instead 149returns the values to be programmed to these registers via ``cpu_context_t``. 150The EL3 Runtime Software is responsible for programming those registers and 151can use the proposed values provided in the ``cpu_context_t``, modifying the 152values if required. 153 154PSCI library needs the flexibility to access both secure and non-secure 155copies of banked registers. Hence it needs to be invoked in Monitor mode 156for AArch32 and in EL3 for AArch64. The NS bit in SCR (in AArch32) or SCR_EL3 157(in AArch64) must be set to 0. Additional requirements for the PSCI library 158interfaces are: 159 160- Instruction cache must be enabled 161- Both IRQ and FIQ must be masked for the current CPU 162- The page tables must be setup and the MMU enabled 163- The C runtime environment must be setup and stack initialized 164- The Data cache must be enabled prior to invoking any of the PSCI library 165 interfaces except for ``psci_warmboot_entrypoint()``. For 166 ``psci_warmboot_entrypoint()``, if the build option ``HW_ASSISTED_COHERENCY`` 167 is enabled however, data caches are expected to be enabled. 168 169Further requirements for each interface can be found in the interface 170description. 171 172Interface : psci_setup() 173~~~~~~~~~~~~~~~~~~~~~~~~ 174 175:: 176 177 Argument : const psci_lib_args_t *lib_args 178 Return : void 179 180This function is to be called by the primary CPU during cold boot before 181any other interface to the PSCI library. It takes ``lib_args``, a const pointer 182to ``psci_lib_args_t``, as the argument. The ``psci_lib_args_t`` is a versioned 183structure and is declared in ``psci_lib.h`` header as follows: 184 185.. code:: c 186 187 typedef struct psci_lib_args { 188 /* The version information of PSCI Library Interface */ 189 param_header_t h; 190 /* The warm boot entrypoint function */ 191 mailbox_entrypoint_t mailbox_ep; 192 } psci_lib_args_t; 193 194The first field ``h``, of ``param_header_t`` type, provides the version 195information. The second field ``mailbox_ep`` is the warm boot entrypoint address 196and is used to configure the platform mailbox. Helper macros are provided in 197``psci_lib.h`` to construct the ``lib_args`` argument statically or during 198runtime. Prior to calling the ``psci_setup()`` interface, the platform setup for 199cold boot must have completed. Major actions performed by this interface are: 200 201- Initializes architecture. 202- Initializes PSCI power domain and state coordination data structures. 203- Calls ``plat_setup_psci_ops()`` with warm boot entrypoint ``mailbox_ep`` as 204 argument. 205- Calls ``cm_set_context_by_index()`` (see 206 `CPU Context management API`_) for all the CPUs in the 207 platform 208 209Interface : psci_prepare_next_non_secure_ctx() 210~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 211 212:: 213 214 Argument : entry_point_info_t *next_image_info 215 Return : void 216 217After ``psci_setup()`` and prior to exit to the non-secure world, this function 218must be called by the EL3 Runtime Software to initialize the non-secure world 219context. The non-secure world entrypoint information ``next_image_info`` (first 220argument) will be used to determine the non-secure context. After this function 221returns, the EL3 Runtime Software must retrieve the ``cpu_context_t`` (using 222cm_get_context()) for the current CPU and program the registers prior to exit 223to the non-secure world. 224 225Interface : psci_register_spd_pm_hook() 226~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 227 228:: 229 230 Argument : const spd_pm_ops_t * 231 Return : void 232 233As explained in `Secure payload power management callback`_, 234the EL3 Runtime Software may want to perform some bookkeeping during power 235management operations. This function is used to register the ``spd_pm_ops_t`` 236(first argument) callbacks with the PSCI library which will be called 237appropriately during power management. Calling this function is optional and 238need to be called by the primary CPU during the cold boot sequence after 239``psci_setup()`` has completed. 240 241Interface : psci_smc_handler() 242~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 243 244:: 245 246 Argument : uint32_t smc_fid, u_register_t x1, 247 u_register_t x2, u_register_t x3, 248 u_register_t x4, void *cookie, 249 void *handle, u_register_t flags 250 Return : u_register_t 251 252This function is the top level handler for SMCs which fall within the 253PSCI service range specified in `SMCCC`_. The function ID ``smc_fid`` (first 254argument) determines the PSCI API to be called. The ``x1`` to ``x4`` (2nd to 5th 255arguments), are the values of the registers r1 - r4 (in AArch32) or x1 - x4 256(in AArch64) when the SMC is received. These are the arguments to PSCI API as 257described in `PSCI`_. The 'flags' (8th argument) is a bit field parameter 258and is detailed in 'smccc.h' header. It includes whether the call is from the 259secure or non-secure world. The ``cookie`` (6th argument) and the ``handle`` 260(7th argument) are not used and are reserved for future use. 261 262The return value from this interface is the return value from the underlying 263PSCI API corresponding to ``smc_fid``. This function may not return back to the 264caller if PSCI API causes power down of the CPU. In this case, when the CPU 265wakes up, it will start execution from the warm reset address. 266 267Interface : psci_warmboot_entrypoint() 268~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 269 270:: 271 272 Argument : void 273 Return : void 274 275This function performs the warm boot initialization/restoration as mandated by 276`PSCI`_. For AArch32, on wakeup from power down the CPU resets to secure SVC 277mode and the EL3 Runtime Software must perform the prerequisite initializations 278mentioned at top of this section. This function must be called with Data cache 279disabled (unless build option ``HW_ASSISTED_COHERENCY`` is enabled) but with MMU 280initialized and enabled. The major actions performed by this function are: 281 282- Invalidates the stack and enables the data cache. 283- Initializes architecture and PSCI state coordination. 284- Restores/Initializes the peripheral drivers to the required state via 285 appropriate ``plat_psci_ops_t`` hooks 286- Restores the EL3 Runtime Software context via appropriate ``spd_pm_ops_t`` 287 callbacks. 288- Restores/Initializes the non-secure context and populates the 289 ``cpu_context_t`` for the current CPU. 290 291Upon the return of this function, the EL3 Runtime Software must retrieve the 292non-secure ``cpu_context_t`` using ``cm_get_context()`` and program the registers 293prior to exit to the non-secure world. 294 295EL3 Runtime Software dependencies 296--------------------------------- 297 298The PSCI Library includes supporting frameworks like context management, 299cpu operations (cpu_ops) and per-cpu data framework. Other helper library 300functions like bakery locks and spin locks are also included in the library. 301The dependencies which must be fulfilled by the EL3 Runtime Software 302for integration with PSCI library are described below. 303 304General dependencies 305~~~~~~~~~~~~~~~~~~~~ 306 307The PSCI library being a Multiprocessor (MP) implementation, EL3 Runtime 308Software must provide an SMC handling framework capable of MP adhering to 309`SMCCC`_ specification. 310 311The EL3 Runtime Software must also export cache maintenance primitives 312and some helper utilities for assert, print and memory operations as listed 313below. The TF-A source tree provides implementations for all 314these functions but the EL3 Runtime Software may use its own implementation. 315 316**Functions : assert(), memcpy(), memset(), printf()** 317 318These must be implemented as described in ISO C Standard. 319 320**Function : flush_dcache_range()** 321 322:: 323 324 Argument : uintptr_t addr, size_t size 325 Return : void 326 327This function cleans and invalidates (flushes) the data cache for memory 328at address ``addr`` (first argument) address and of size ``size`` (second argument). 329 330**Function : inv_dcache_range()** 331 332:: 333 334 Argument : uintptr_t addr, size_t size 335 Return : void 336 337This function invalidates (flushes) the data cache for memory at address 338``addr`` (first argument) address and of size ``size`` (second argument). 339 340CPU Context management API 341~~~~~~~~~~~~~~~~~~~~~~~~~~ 342 343The CPU context management data memory is statically allocated by PSCI library 344in BSS section. The PSCI library requires the EL3 Runtime Software to implement 345APIs to store and retrieve pointers to this CPU context data. SP-MIN 346demonstrates how these APIs can be implemented but the EL3 Runtime Software can 347choose a more optimal implementation (like dedicating the secure TPIDRPRW 348system register (in AArch32) for storing these pointers). 349 350**Function : cm_set_context_by_index()** 351 352:: 353 354 Argument : unsigned int cpu_idx, void *context, unsigned int security_state 355 Return : void 356 357This function is called during cold boot when the ``psci_setup()`` PSCI library 358interface is called. 359 360This function must store the pointer to the CPU context data, ``context`` (2nd 361argument), for the specified ``security_state`` (3rd argument) and CPU identified 362by ``cpu_idx`` (first argument). The ``security_state`` will always be non-secure 363when called by PSCI library and this argument is retained for compatibility 364with BL31. The ``cpu_idx`` will correspond to the index returned by the 365``plat_core_pos_by_mpidr()`` for ``mpidr`` of the CPU. 366 367The actual method of storing the ``context`` pointers is implementation specific. 368For example, SP-MIN stores the pointers in the array ``sp_min_cpu_ctx_ptr`` 369declared in ``sp_min_main.c``. 370 371**Function : cm_get_context()** 372 373:: 374 375 Argument : uint32_t security_state 376 Return : void * 377 378This function must return the pointer to the ``cpu_context_t`` structure for 379the specified ``security_state`` (first argument) for the current CPU. The caller 380must ensure that ``cm_set_context_by_index`` is called first and the appropriate 381context pointers are stored prior to invoking this API. The ``security_state`` 382will always be non-secure when called by PSCI library and this argument 383is retained for compatibility with BL31. 384 385**Function : cm_get_context_by_index()** 386 387:: 388 389 Argument : unsigned int cpu_idx, unsigned int security_state 390 Return : void * 391 392This function must return the pointer to the ``cpu_context_t`` structure for 393the specified ``security_state`` (second argument) for the CPU identified by 394``cpu_idx`` (first argument). The caller must ensure that 395``cm_set_context_by_index`` is called first and the appropriate context 396pointers are stored prior to invoking this API. The ``security_state`` will 397always be non-secure when called by PSCI library and this argument is 398retained for compatibility with BL31. The ``cpu_idx`` will correspond to the 399index returned by the ``plat_core_pos_by_mpidr()`` for ``mpidr`` of the CPU. 400 401Platform API 402~~~~~~~~~~~~ 403 404The platform layer abstracts the platform-specific details from the generic 405PSCI library. The following platform APIs/macros must be defined by the EL3 406Runtime Software for integration with the PSCI library. 407 408The mandatory platform APIs are: 409 410- plat_my_core_pos 411- plat_core_pos_by_mpidr 412- plat_get_syscnt_freq2 413- plat_get_power_domain_tree_desc 414- plat_setup_psci_ops 415- plat_reset_handler 416- plat_panic_handler 417- plat_get_my_stack 418 419The mandatory platform macros are: 420 421- PLATFORM_CORE_COUNT 422- PLAT_MAX_PWR_LVL 423- PLAT_NUM_PWR_DOMAINS 424- CACHE_WRITEBACK_GRANULE 425- PLAT_MAX_OFF_STATE 426- PLAT_MAX_RET_STATE 427- PLAT_MAX_PWR_LVL_STATES (optional) 428- PLAT_PCPU_DATA_SIZE (optional) 429 430The details of these APIs/macros can be found in the :ref:`Porting Guide`. 431 432All platform specific operations for power management are done via 433``plat_psci_ops_t`` callbacks registered by the platform when 434``plat_setup_psci_ops()`` API is called. The description of each of 435the callbacks in ``plat_psci_ops_t`` can be found in PSCI section of the 436:ref:`Porting Guide`. If any these callbacks are not registered, then the 437PSCI API associated with that callback will not be supported by PSCI 438library. 439 440Secure payload power management callback 441~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 442 443During PSCI power management operations, the EL3 Runtime Software may 444need to perform some bookkeeping, and PSCI library provides 445``spd_pm_ops_t`` callbacks for this purpose. These hooks must be 446populated and registered by using ``psci_register_spd_pm_hook()`` PSCI 447library interface. 448 449Typical bookkeeping during PSCI power management calls include save/restore 450of the EL3 Runtime Software context. Also if the EL3 Runtime Software makes 451use of secure interrupts, then these interrupts must also be managed 452appropriately during CPU power down/power up. Any secure interrupt targeted 453to the current CPU must be disabled or re-targeted to other running CPU prior 454to power down of the current CPU. During power up, these interrupt can be 455enabled/re-targeted back to the current CPU. 456 457.. code:: c 458 459 typedef struct spd_pm_ops { 460 void (*svc_on)(u_register_t target_cpu); 461 int32_t (*svc_off)(u_register_t __unused); 462 void (*svc_suspend)(u_register_t max_off_pwrlvl); 463 void (*svc_on_finish)(u_register_t __unused); 464 void (*svc_suspend_finish)(u_register_t max_off_pwrlvl); 465 int32_t (*svc_migrate)(u_register_t from_cpu, u_register_t to_cpu); 466 int32_t (*svc_migrate_info)(u_register_t *resident_cpu); 467 void (*svc_system_off)(void); 468 void (*svc_system_reset)(void); 469 } spd_pm_ops_t; 470 471A brief description of each callback is given below: 472 473- svc_on, svc_off, svc_on_finish 474 475 The ``svc_on``, ``svc_off`` callbacks are called during PSCI_CPU_ON, 476 PSCI_CPU_OFF APIs respectively. The ``svc_on_finish`` is called when the 477 target CPU of PSCI_CPU_ON API powers up and executes the 478 ``psci_warmboot_entrypoint()`` PSCI library interface. 479 480- svc_suspend, svc_suspend_finish 481 482 The ``svc_suspend`` callback is called during power down bu either 483 PSCI_SUSPEND or PSCI_SYSTEM_SUSPEND APIs. The ``svc_suspend_finish`` is 484 called when the CPU wakes up from suspend and executes the 485 ``psci_warmboot_entrypoint()`` PSCI library interface. The ``max_off_pwrlvl`` 486 (first parameter) denotes the highest power domain level being powered down 487 to or woken up from suspend. 488 489- svc_system_off, svc_system_reset 490 491 These callbacks are called during PSCI_SYSTEM_OFF and PSCI_SYSTEM_RESET 492 PSCI APIs respectively. 493 494- svc_migrate_info 495 496 This callback is called in response to PSCI_MIGRATE_INFO_TYPE or 497 PSCI_MIGRATE_INFO_UP_CPU APIs. The return value of this callback must 498 correspond to the return value of PSCI_MIGRATE_INFO_TYPE API as described 499 in `PSCI`_. If the secure payload is a Uniprocessor (UP) 500 implementation, then it must update the mpidr of the CPU it is resident in 501 via ``resident_cpu`` (first argument). The updates to ``resident_cpu`` is 502 ignored if the secure payload is a multiprocessor (MP) implementation. 503 504- svc_migrate 505 506 This callback is only relevant if the secure payload in EL3 Runtime 507 Software is a Uniprocessor (UP) implementation and supports migration from 508 the current CPU ``from_cpu`` (first argument) to another CPU ``to_cpu`` 509 (second argument). This callback is called in response to PSCI_MIGRATE 510 API. This callback is never called if the secure payload is a 511 Multiprocessor (MP) implementation. 512 513CPU operations 514~~~~~~~~~~~~~~ 515 516The CPU operations (cpu_ops) framework implement power down sequence specific 517to the CPU and the details of which can be found at 518:ref:`firmware_design_cpu_ops_fwk`. The TF-A tree implements the ``cpu_ops`` 519for various supported CPUs and the EL3 Runtime Software needs to include the 520required ``cpu_ops`` in its build. The start and end of the ``cpu_ops`` 521descriptors must be exported by the EL3 Runtime Software via the 522``__CPU_OPS_START__`` and ``__CPU_OPS_END__`` linker symbols. 523 524The ``cpu_ops`` descriptors also include reset sequences and may include errata 525workarounds for the CPU. The EL3 Runtime Software can choose to call this 526during cold/warm reset if it does not implement its own reset sequence/errata 527workarounds. 528 529-------------- 530 531*Copyright (c) 2016-2023, Arm Limited and Contributors. All rights reserved.* 532 533.. _PSCI: https://developer.arm.com/documentation/den0022/latest/ 534.. _SMCCC: https://developer.arm.com/docs/den0028/latest 535