spm_mm_setup.c 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. /*
  2. * Copyright (c) 2017-2024, Arm Limited and Contributors. All rights reserved.
  3. * Copyright (c) 2021, NVIDIA Corporation. All rights reserved.
  4. *
  5. * SPDX-License-Identifier: BSD-3-Clause
  6. */
  7. #include <assert.h>
  8. #include <string.h>
  9. #include <arch.h>
  10. #include <arch_helpers.h>
  11. #include <context.h>
  12. #include <common/debug.h>
  13. #include <lib/el3_runtime/context_mgmt.h>
  14. #include <lib/xlat_tables/xlat_tables_v2.h>
  15. #include <platform_def.h>
  16. #include <plat/common/common_def.h>
  17. #include <plat/common/platform.h>
  18. #include <services/spm_mm_partition.h>
  19. #include "spm_common.h"
  20. #include "spm_mm_private.h"
  21. #include "spm_shim_private.h"
  22. /* Setup context of the Secure Partition */
  23. void spm_sp_setup(sp_context_t *sp_ctx)
  24. {
  25. cpu_context_t *ctx = &(sp_ctx->cpu_ctx);
  26. u_register_t sctlr_el1_val;
  27. /* Pointer to the MP information from the platform port. */
  28. const spm_mm_boot_info_t *sp_boot_info =
  29. plat_get_secure_partition_boot_info(NULL);
  30. /*
  31. * Initialize CPU context
  32. * ----------------------
  33. */
  34. entry_point_info_t ep_info = {0};
  35. SET_PARAM_HEAD(&ep_info, PARAM_EP, VERSION_1, SECURE | EP_ST_ENABLE);
  36. /* Setup entrypoint and SPSR */
  37. ep_info.pc = sp_boot_info->sp_image_base;
  38. ep_info.spsr = SPSR_64(MODE_EL0, MODE_SP_EL0, DISABLE_ALL_EXCEPTIONS);
  39. /*
  40. * X0: Virtual address of a buffer shared between EL3 and Secure EL0.
  41. * The buffer will be mapped in the Secure EL1 translation regime
  42. * with Normal IS WBWA attributes and RO data and Execute Never
  43. * instruction access permissions.
  44. *
  45. * X1: Size of the buffer in bytes
  46. *
  47. * X2: cookie value (Implementation Defined)
  48. *
  49. * X3: cookie value (Implementation Defined)
  50. *
  51. * X4 to X7 = 0
  52. */
  53. ep_info.args.arg0 = sp_boot_info->sp_shared_buf_base;
  54. ep_info.args.arg1 = sp_boot_info->sp_shared_buf_size;
  55. ep_info.args.arg2 = PLAT_SPM_COOKIE_0;
  56. ep_info.args.arg3 = PLAT_SPM_COOKIE_1;
  57. cm_setup_context(ctx, &ep_info);
  58. /*
  59. * SP_EL0: A non-zero value will indicate to the SP that the SPM has
  60. * initialized the stack pointer for the current CPU through
  61. * implementation defined means. The value will be 0 otherwise.
  62. */
  63. write_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_SP_EL0,
  64. sp_boot_info->sp_stack_base + sp_boot_info->sp_pcpu_stack_size);
  65. /*
  66. * Setup translation tables
  67. * ------------------------
  68. */
  69. #if ENABLE_ASSERTIONS
  70. /* Get max granularity supported by the platform. */
  71. unsigned int max_granule = xlat_arch_get_max_supported_granule_size();
  72. VERBOSE("Max translation granule size supported: %u KiB\n",
  73. max_granule / 1024U);
  74. unsigned int max_granule_mask = max_granule - 1U;
  75. /* Base must be aligned to the max granularity */
  76. assert((sp_boot_info->sp_ns_comm_buf_base & max_granule_mask) == 0);
  77. /* Size must be a multiple of the max granularity */
  78. assert((sp_boot_info->sp_ns_comm_buf_size & max_granule_mask) == 0);
  79. #endif /* ENABLE_ASSERTIONS */
  80. /* This region contains the exception vectors used at S-EL1. */
  81. const mmap_region_t sel1_exception_vectors =
  82. MAP_REGION_FLAT(SPM_SHIM_EXCEPTIONS_START,
  83. SPM_SHIM_EXCEPTIONS_SIZE,
  84. MT_CODE | MT_SECURE | MT_PRIVILEGED);
  85. mmap_add_region_ctx(sp_ctx->xlat_ctx_handle,
  86. &sel1_exception_vectors);
  87. mmap_add_ctx(sp_ctx->xlat_ctx_handle,
  88. plat_get_secure_partition_mmap(NULL));
  89. init_xlat_tables_ctx(sp_ctx->xlat_ctx_handle);
  90. /*
  91. * MMU-related registers
  92. * ---------------------
  93. */
  94. xlat_ctx_t *xlat_ctx = sp_ctx->xlat_ctx_handle;
  95. uint64_t mmu_cfg_params[MMU_CFG_PARAM_MAX];
  96. setup_mmu_cfg((uint64_t *)&mmu_cfg_params, 0, xlat_ctx->base_table,
  97. xlat_ctx->pa_max_address, xlat_ctx->va_max_address,
  98. EL1_EL0_REGIME);
  99. write_el1_ctx_common(get_el1_sysregs_ctx(ctx), mair_el1,
  100. mmu_cfg_params[MMU_CFG_MAIR]);
  101. write_ctx_tcr_el1_reg_errata(ctx, mmu_cfg_params[MMU_CFG_TCR]);
  102. write_el1_ctx_common(get_el1_sysregs_ctx(ctx), ttbr0_el1,
  103. mmu_cfg_params[MMU_CFG_TTBR0]);
  104. /* Setup SCTLR_EL1 */
  105. sctlr_el1_val = read_ctx_sctlr_el1_reg_errata(ctx);
  106. sctlr_el1_val |=
  107. /*SCTLR_EL1_RES1 |*/
  108. /* Don't trap DC CVAU, DC CIVAC, DC CVAC, DC CVAP, or IC IVAU */
  109. SCTLR_UCI_BIT |
  110. /* RW regions at xlat regime EL1&0 are forced to be XN. */
  111. SCTLR_WXN_BIT |
  112. /* Don't trap to EL1 execution of WFI or WFE at EL0. */
  113. SCTLR_NTWI_BIT | SCTLR_NTWE_BIT |
  114. /* Don't trap to EL1 accesses to CTR_EL0 from EL0. */
  115. SCTLR_UCT_BIT |
  116. /* Don't trap to EL1 execution of DZ ZVA at EL0. */
  117. SCTLR_DZE_BIT |
  118. /* Enable SP Alignment check for EL0 */
  119. SCTLR_SA0_BIT |
  120. /* Don't change PSTATE.PAN on taking an exception to EL1 */
  121. SCTLR_SPAN_BIT |
  122. /* Allow cacheable data and instr. accesses to normal memory. */
  123. SCTLR_C_BIT | SCTLR_I_BIT |
  124. /* Enable MMU. */
  125. SCTLR_M_BIT
  126. ;
  127. sctlr_el1_val &= ~(
  128. /* Explicit data accesses at EL0 are little-endian. */
  129. SCTLR_E0E_BIT |
  130. /*
  131. * Alignment fault checking disabled when at EL1 and EL0 as
  132. * the UEFI spec permits unaligned accesses.
  133. */
  134. SCTLR_A_BIT |
  135. /* Accesses to DAIF from EL0 are trapped to EL1. */
  136. SCTLR_UMA_BIT
  137. );
  138. /* Store the initialised SCTLR_EL1 value in the cpu_context */
  139. write_ctx_sctlr_el1_reg_errata(ctx, sctlr_el1_val);
  140. /*
  141. * Setup other system registers
  142. * ----------------------------
  143. */
  144. /* Shim Exception Vector Base Address */
  145. write_el1_ctx_common(get_el1_sysregs_ctx(ctx), vbar_el1,
  146. SPM_SHIM_EXCEPTIONS_PTR);
  147. write_el1_ctx_arch_timer(get_el1_sysregs_ctx(ctx), cntkctl_el1,
  148. EL0PTEN_BIT | EL0VTEN_BIT | EL0PCTEN_BIT | EL0VCTEN_BIT);
  149. /*
  150. * FPEN: Allow the Secure Partition to access FP/SIMD registers.
  151. * Note that SPM will not do any saving/restoring of these registers on
  152. * behalf of the SP. This falls under the SP's responsibility.
  153. * TTA: Enable access to trace registers.
  154. * ZEN (v8.2): Trap SVE instructions and access to SVE registers.
  155. */
  156. write_el1_ctx_common(get_el1_sysregs_ctx(ctx), cpacr_el1,
  157. CPACR_EL1_FPEN(CPACR_EL1_FP_TRAP_NONE));
  158. /*
  159. * Prepare information in buffer shared between EL3 and S-EL0
  160. * ----------------------------------------------------------
  161. */
  162. void *shared_buf_ptr = (void *) sp_boot_info->sp_shared_buf_base;
  163. /* Copy the boot information into the shared buffer with the SP. */
  164. assert((uintptr_t)shared_buf_ptr + sizeof(spm_mm_boot_info_t)
  165. <= (sp_boot_info->sp_shared_buf_base + sp_boot_info->sp_shared_buf_size));
  166. assert(sp_boot_info->sp_shared_buf_base <=
  167. (UINTPTR_MAX - sp_boot_info->sp_shared_buf_size + 1));
  168. assert(sp_boot_info != NULL);
  169. memcpy((void *) shared_buf_ptr, (const void *) sp_boot_info,
  170. sizeof(spm_mm_boot_info_t));
  171. /* Pointer to the MP information from the platform port. */
  172. spm_mm_mp_info_t *sp_mp_info =
  173. ((spm_mm_boot_info_t *) shared_buf_ptr)->mp_info;
  174. assert(sp_mp_info != NULL);
  175. /*
  176. * Point the shared buffer MP information pointer to where the info will
  177. * be populated, just after the boot info.
  178. */
  179. ((spm_mm_boot_info_t *) shared_buf_ptr)->mp_info =
  180. (spm_mm_mp_info_t *) ((uintptr_t)shared_buf_ptr
  181. + sizeof(spm_mm_boot_info_t));
  182. /*
  183. * Update the shared buffer pointer to where the MP information for the
  184. * payload will be populated
  185. */
  186. shared_buf_ptr = ((spm_mm_boot_info_t *) shared_buf_ptr)->mp_info;
  187. /*
  188. * Copy the cpu information into the shared buffer area after the boot
  189. * information.
  190. */
  191. assert(sp_boot_info->num_cpus <= PLATFORM_CORE_COUNT);
  192. assert((uintptr_t)shared_buf_ptr
  193. <= (sp_boot_info->sp_shared_buf_base + sp_boot_info->sp_shared_buf_size -
  194. (sp_boot_info->num_cpus * sizeof(*sp_mp_info))));
  195. memcpy(shared_buf_ptr, (const void *) sp_mp_info,
  196. sp_boot_info->num_cpus * sizeof(*sp_mp_info));
  197. /*
  198. * Calculate the linear indices of cores in boot information for the
  199. * secure partition and flag the primary CPU
  200. */
  201. sp_mp_info = (spm_mm_mp_info_t *) shared_buf_ptr;
  202. for (unsigned int index = 0; index < sp_boot_info->num_cpus; index++) {
  203. u_register_t mpidr = sp_mp_info[index].mpidr;
  204. sp_mp_info[index].linear_id = plat_core_pos_by_mpidr(mpidr);
  205. if (plat_my_core_pos() == sp_mp_info[index].linear_id)
  206. sp_mp_info[index].flags |= MP_INFO_FLAG_PRIMARY_CPU;
  207. }
  208. }