1b61d94a1SMarc Bonnici /*
248426cffSBoyan Karatotev * Copyright (c) 2017-2025, Arm Limited and Contributors. All rights reserved.
3b61d94a1SMarc Bonnici *
4b61d94a1SMarc Bonnici * SPDX-License-Identifier: BSD-3-Clause
5b61d94a1SMarc Bonnici */
6b61d94a1SMarc Bonnici
7b61d94a1SMarc Bonnici #include <arch_helpers.h>
8b61d94a1SMarc Bonnici #include <assert.h>
9b61d94a1SMarc Bonnici #include <errno.h>
10b61d94a1SMarc Bonnici
11b61d94a1SMarc Bonnici #include <bl31/bl31.h>
12b61d94a1SMarc Bonnici #include <bl31/ehf.h>
13b61d94a1SMarc Bonnici #include <common/debug.h>
14b61d94a1SMarc Bonnici #include <common/runtime_svc.h>
15b61d94a1SMarc Bonnici #include <lib/el3_runtime/context_mgmt.h>
16e6e34868SMadhukar Pappireddy #include <lib/el3_runtime/simd_ctx.h>
17b61d94a1SMarc Bonnici #include <lib/smccc.h>
18b61d94a1SMarc Bonnici #include <lib/spinlock.h>
19b61d94a1SMarc Bonnici #include <lib/utils.h>
20b61d94a1SMarc Bonnici #include <lib/xlat_tables/xlat_tables_v2.h>
21b61d94a1SMarc Bonnici #include <plat/common/platform.h>
22b61d94a1SMarc Bonnici #include <services/spm_mm_partition.h>
23b61d94a1SMarc Bonnici #include <services/spm_mm_svc.h>
2496546b5cSManish Pandey #include <services/ven_el3_svc.h>
25b61d94a1SMarc Bonnici #include <smccc_helpers.h>
26b61d94a1SMarc Bonnici
27b61d94a1SMarc Bonnici #include "spm_common.h"
28b61d94a1SMarc Bonnici #include "spm_mm_private.h"
29b61d94a1SMarc Bonnici
30b61d94a1SMarc Bonnici /*******************************************************************************
31b61d94a1SMarc Bonnici * Secure Partition context information.
32b61d94a1SMarc Bonnici ******************************************************************************/
33b61d94a1SMarc Bonnici static sp_context_t sp_ctx;
34b61d94a1SMarc Bonnici
3596546b5cSManish Pandey /********************************************************************************
3696546b5cSManish Pandey * TPM service UUID: 17b862a4-1806-4faf-86b3-089a58353861 as mentioned in
3796546b5cSManish Pandey * https://developer.arm.com/documentation/den0138/latest/
3896546b5cSManish Pandey *******************************************************************************/
3996546b5cSManish Pandey DEFINE_SVC_UUID2(tpm_service_uuid,
4096546b5cSManish Pandey 0x17b862a4, 0x1806, 0x4faf, 0x86, 0xb3,
4196546b5cSManish Pandey 0x08, 0x9a, 0x58, 0x35, 0x38, 0x61);
4296546b5cSManish Pandey
43b61d94a1SMarc Bonnici /*******************************************************************************
44b61d94a1SMarc Bonnici * Set state of a Secure Partition context.
45b61d94a1SMarc Bonnici ******************************************************************************/
sp_state_set(sp_context_t * sp_ptr,sp_state_t state)4648426cffSBoyan Karatotev static void sp_state_set(sp_context_t *sp_ptr, sp_state_t state)
47b61d94a1SMarc Bonnici {
48b61d94a1SMarc Bonnici sp_ptr->state = state;
49b61d94a1SMarc Bonnici spin_unlock(&(sp_ptr->state_lock));
50b61d94a1SMarc Bonnici }
51b61d94a1SMarc Bonnici
52b61d94a1SMarc Bonnici /*******************************************************************************
5348426cffSBoyan Karatotev * Change the state of a Secure Partition to the one specified.
54b61d94a1SMarc Bonnici ******************************************************************************/
sp_state_wait_switch(sp_context_t * sp_ptr,sp_state_t from,sp_state_t to)5548426cffSBoyan Karatotev static void sp_state_wait_switch(sp_context_t *sp_ptr, sp_state_t from, sp_state_t to)
56b61d94a1SMarc Bonnici {
57b61d94a1SMarc Bonnici spin_lock(&(sp_ptr->state_lock));
58b61d94a1SMarc Bonnici sp_ptr->state = to;
59b61d94a1SMarc Bonnici }
60b61d94a1SMarc Bonnici
61b61d94a1SMarc Bonnici /*******************************************************************************
62b61d94a1SMarc Bonnici * This function takes an SP context pointer and performs a synchronous entry
63b61d94a1SMarc Bonnici * into it.
64b61d94a1SMarc Bonnici ******************************************************************************/
spm_sp_synchronous_entry(sp_context_t * ctx)65b61d94a1SMarc Bonnici static uint64_t spm_sp_synchronous_entry(sp_context_t *ctx)
66b61d94a1SMarc Bonnici {
67b61d94a1SMarc Bonnici uint64_t rc;
68b61d94a1SMarc Bonnici
69b61d94a1SMarc Bonnici assert(ctx != NULL);
70b61d94a1SMarc Bonnici
71b61d94a1SMarc Bonnici /* Assign the context of the SP to this CPU */
72b61d94a1SMarc Bonnici cm_set_context(&(ctx->cpu_ctx), SECURE);
73b61d94a1SMarc Bonnici
74b61d94a1SMarc Bonnici /* Restore the context assigned above */
75b61d94a1SMarc Bonnici cm_el1_sysregs_context_restore(SECURE);
76b61d94a1SMarc Bonnici cm_set_next_eret_context(SECURE);
77b61d94a1SMarc Bonnici
78b61d94a1SMarc Bonnici /* Invalidate TLBs at EL1. */
79b61d94a1SMarc Bonnici tlbivmalle1();
80b61d94a1SMarc Bonnici dsbish();
81b61d94a1SMarc Bonnici
82b61d94a1SMarc Bonnici /* Enter Secure Partition */
83b61d94a1SMarc Bonnici rc = spm_secure_partition_enter(&ctx->c_rt_ctx);
84b61d94a1SMarc Bonnici
85b61d94a1SMarc Bonnici /* Save secure state */
86b61d94a1SMarc Bonnici cm_el1_sysregs_context_save(SECURE);
87b61d94a1SMarc Bonnici
88b61d94a1SMarc Bonnici return rc;
89b61d94a1SMarc Bonnici }
90b61d94a1SMarc Bonnici
91b61d94a1SMarc Bonnici /*******************************************************************************
92b61d94a1SMarc Bonnici * This function returns to the place where spm_sp_synchronous_entry() was
93b61d94a1SMarc Bonnici * called originally.
94b61d94a1SMarc Bonnici ******************************************************************************/
spm_sp_synchronous_exit(uint64_t rc)95b61d94a1SMarc Bonnici __dead2 static void spm_sp_synchronous_exit(uint64_t rc)
96b61d94a1SMarc Bonnici {
97b61d94a1SMarc Bonnici sp_context_t *ctx = &sp_ctx;
98b61d94a1SMarc Bonnici
99b61d94a1SMarc Bonnici /*
100b61d94a1SMarc Bonnici * The SPM must have initiated the original request through a
101b61d94a1SMarc Bonnici * synchronous entry into the secure partition. Jump back to the
102b61d94a1SMarc Bonnici * original C runtime context with the value of rc in x0;
103b61d94a1SMarc Bonnici */
104b61d94a1SMarc Bonnici spm_secure_partition_exit(ctx->c_rt_ctx, rc);
105b61d94a1SMarc Bonnici
106b61d94a1SMarc Bonnici panic();
107b61d94a1SMarc Bonnici }
108b61d94a1SMarc Bonnici
109b61d94a1SMarc Bonnici /*******************************************************************************
110b61d94a1SMarc Bonnici * Jump to each Secure Partition for the first time.
111b61d94a1SMarc Bonnici ******************************************************************************/
spm_init(void)112b61d94a1SMarc Bonnici static int32_t spm_init(void)
113b61d94a1SMarc Bonnici {
114b61d94a1SMarc Bonnici uint64_t rc;
115b61d94a1SMarc Bonnici sp_context_t *ctx;
116b61d94a1SMarc Bonnici
117b61d94a1SMarc Bonnici INFO("Secure Partition init...\n");
118b61d94a1SMarc Bonnici
119b61d94a1SMarc Bonnici ctx = &sp_ctx;
120b61d94a1SMarc Bonnici
121b61d94a1SMarc Bonnici ctx->state = SP_STATE_RESET;
122b61d94a1SMarc Bonnici
123b61d94a1SMarc Bonnici rc = spm_sp_synchronous_entry(ctx);
124b61d94a1SMarc Bonnici assert(rc == 0);
125b61d94a1SMarc Bonnici
126b61d94a1SMarc Bonnici ctx->state = SP_STATE_IDLE;
127b61d94a1SMarc Bonnici
128b61d94a1SMarc Bonnici INFO("Secure Partition initialized.\n");
129b61d94a1SMarc Bonnici
130b61d94a1SMarc Bonnici return !rc;
131b61d94a1SMarc Bonnici }
132b61d94a1SMarc Bonnici
133b61d94a1SMarc Bonnici /*******************************************************************************
134b61d94a1SMarc Bonnici * Initialize contexts of all Secure Partitions.
135b61d94a1SMarc Bonnici ******************************************************************************/
spm_mm_setup(void)136b61d94a1SMarc Bonnici int32_t spm_mm_setup(void)
137b61d94a1SMarc Bonnici {
138b61d94a1SMarc Bonnici sp_context_t *ctx;
139b61d94a1SMarc Bonnici
140b61d94a1SMarc Bonnici /* Disable MMU at EL1 (initialized by BL2) */
141b61d94a1SMarc Bonnici disable_mmu_icache_el1();
142b61d94a1SMarc Bonnici
143b61d94a1SMarc Bonnici /* Initialize context of the SP */
144b61d94a1SMarc Bonnici INFO("Secure Partition context setup start...\n");
145b61d94a1SMarc Bonnici
146b61d94a1SMarc Bonnici ctx = &sp_ctx;
147b61d94a1SMarc Bonnici
148b61d94a1SMarc Bonnici /* Assign translation tables context. */
149b61d94a1SMarc Bonnici ctx->xlat_ctx_handle = spm_get_sp_xlat_context();
150b61d94a1SMarc Bonnici
151b61d94a1SMarc Bonnici spm_sp_setup(ctx);
152b61d94a1SMarc Bonnici
153b61d94a1SMarc Bonnici /* Register init function for deferred init. */
154b61d94a1SMarc Bonnici bl31_register_bl32_init(&spm_init);
155b61d94a1SMarc Bonnici
156b61d94a1SMarc Bonnici INFO("Secure Partition setup done.\n");
157b61d94a1SMarc Bonnici
158b61d94a1SMarc Bonnici return 0;
159b61d94a1SMarc Bonnici }
160b61d94a1SMarc Bonnici
161b61d94a1SMarc Bonnici /*******************************************************************************
162b61d94a1SMarc Bonnici * Function to perform a call to a Secure Partition.
163b61d94a1SMarc Bonnici ******************************************************************************/
spm_mm_sp_call(uint32_t smc_fid,uint64_t x1,uint64_t x2,uint64_t x3)164b61d94a1SMarc Bonnici uint64_t spm_mm_sp_call(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3)
165b61d94a1SMarc Bonnici {
166b61d94a1SMarc Bonnici uint64_t rc;
167b61d94a1SMarc Bonnici sp_context_t *sp_ptr = &sp_ctx;
168b61d94a1SMarc Bonnici
169e6e34868SMadhukar Pappireddy #if CTX_INCLUDE_FPREGS || CTX_INCLUDE_SVE_REGS
17015dd6f19SNishant Sharma /*
171e6e34868SMadhukar Pappireddy * SP runs to completion, no need to restore FP/SVE registers of secure context.
172e6e34868SMadhukar Pappireddy * Save FP/SVE registers only for non secure context.
17315dd6f19SNishant Sharma */
174e6e34868SMadhukar Pappireddy simd_ctx_save(NON_SECURE, false);
175e6e34868SMadhukar Pappireddy #endif /* CTX_INCLUDE_FPREGS || CTX_INCLUDE_SVE_REGS */
17615dd6f19SNishant Sharma
177b61d94a1SMarc Bonnici /* Wait until the Secure Partition is idle and set it to busy. */
178b61d94a1SMarc Bonnici sp_state_wait_switch(sp_ptr, SP_STATE_IDLE, SP_STATE_BUSY);
179b61d94a1SMarc Bonnici
180b61d94a1SMarc Bonnici /* Set values for registers on SP entry */
181b61d94a1SMarc Bonnici cpu_context_t *cpu_ctx = &(sp_ptr->cpu_ctx);
182b61d94a1SMarc Bonnici
183b61d94a1SMarc Bonnici write_ctx_reg(get_gpregs_ctx(cpu_ctx), CTX_GPREG_X0, smc_fid);
184b61d94a1SMarc Bonnici write_ctx_reg(get_gpregs_ctx(cpu_ctx), CTX_GPREG_X1, x1);
185b61d94a1SMarc Bonnici write_ctx_reg(get_gpregs_ctx(cpu_ctx), CTX_GPREG_X2, x2);
186b61d94a1SMarc Bonnici write_ctx_reg(get_gpregs_ctx(cpu_ctx), CTX_GPREG_X3, x3);
187b61d94a1SMarc Bonnici
188b61d94a1SMarc Bonnici /* Jump to the Secure Partition. */
189b61d94a1SMarc Bonnici rc = spm_sp_synchronous_entry(sp_ptr);
190b61d94a1SMarc Bonnici
191b61d94a1SMarc Bonnici /* Flag Secure Partition as idle. */
192b61d94a1SMarc Bonnici assert(sp_ptr->state == SP_STATE_BUSY);
193b61d94a1SMarc Bonnici sp_state_set(sp_ptr, SP_STATE_IDLE);
194b61d94a1SMarc Bonnici
195e6e34868SMadhukar Pappireddy #if CTX_INCLUDE_FPREGS || CTX_INCLUDE_SVE_REGS
19615dd6f19SNishant Sharma /*
197e6e34868SMadhukar Pappireddy * SP runs to completion, no need to save FP/SVE registers of secure context.
198e6e34868SMadhukar Pappireddy * Restore only non secure world FP/SVE registers.
19915dd6f19SNishant Sharma */
200e6e34868SMadhukar Pappireddy simd_ctx_restore(NON_SECURE);
201e6e34868SMadhukar Pappireddy #endif /* CTX_INCLUDE_FPREGS || CTX_INCLUDE_SVE_REGS */
20215dd6f19SNishant Sharma
203b61d94a1SMarc Bonnici return rc;
204b61d94a1SMarc Bonnici }
205b61d94a1SMarc Bonnici
206b61d94a1SMarc Bonnici /*******************************************************************************
207b61d94a1SMarc Bonnici * MM_COMMUNICATE handler
208b61d94a1SMarc Bonnici ******************************************************************************/
mm_communicate(uint32_t smc_fid,uint64_t mm_cookie,uint64_t comm_buffer_address,uint64_t comm_size_address,void * handle)209b61d94a1SMarc Bonnici static uint64_t mm_communicate(uint32_t smc_fid, uint64_t mm_cookie,
210b61d94a1SMarc Bonnici uint64_t comm_buffer_address,
211b61d94a1SMarc Bonnici uint64_t comm_size_address, void *handle)
212b61d94a1SMarc Bonnici {
213b61d94a1SMarc Bonnici uint64_t rc;
214b61d94a1SMarc Bonnici
215b61d94a1SMarc Bonnici /* Cookie. Reserved for future use. It must be zero. */
216b61d94a1SMarc Bonnici if (mm_cookie != 0U) {
217b61d94a1SMarc Bonnici ERROR("MM_COMMUNICATE: cookie is not zero\n");
218b61d94a1SMarc Bonnici SMC_RET1(handle, SPM_MM_INVALID_PARAMETER);
219b61d94a1SMarc Bonnici }
220b61d94a1SMarc Bonnici
221b61d94a1SMarc Bonnici if (comm_buffer_address == 0U) {
222b61d94a1SMarc Bonnici ERROR("MM_COMMUNICATE: comm_buffer_address is zero\n");
223b61d94a1SMarc Bonnici SMC_RET1(handle, SPM_MM_INVALID_PARAMETER);
224b61d94a1SMarc Bonnici }
225b61d94a1SMarc Bonnici
226b61d94a1SMarc Bonnici if (comm_size_address != 0U) {
227b61d94a1SMarc Bonnici VERBOSE("MM_COMMUNICATE: comm_size_address is not 0 as recommended.\n");
228b61d94a1SMarc Bonnici }
229b61d94a1SMarc Bonnici
230b61d94a1SMarc Bonnici /*
231b61d94a1SMarc Bonnici * The current secure partition design mandates
232b61d94a1SMarc Bonnici * - at any point, only a single core can be
2331b491eeaSElyes Haouas * executing in the secure partition.
234b61d94a1SMarc Bonnici * - a core cannot be preempted by an interrupt
235b61d94a1SMarc Bonnici * while executing in secure partition.
236b61d94a1SMarc Bonnici * Raise the running priority of the core to the
237b61d94a1SMarc Bonnici * interrupt level configured for secure partition
238b61d94a1SMarc Bonnici * so as to block any interrupt from preempting this
239b61d94a1SMarc Bonnici * core.
240b61d94a1SMarc Bonnici */
241b61d94a1SMarc Bonnici ehf_activate_priority(PLAT_SP_PRI);
242b61d94a1SMarc Bonnici
243b61d94a1SMarc Bonnici /* Save the Normal world context */
244b61d94a1SMarc Bonnici cm_el1_sysregs_context_save(NON_SECURE);
245b61d94a1SMarc Bonnici
246b61d94a1SMarc Bonnici rc = spm_mm_sp_call(smc_fid, comm_buffer_address, comm_size_address,
247b61d94a1SMarc Bonnici plat_my_core_pos());
248b61d94a1SMarc Bonnici
249b61d94a1SMarc Bonnici /* Restore non-secure state */
250b61d94a1SMarc Bonnici cm_el1_sysregs_context_restore(NON_SECURE);
251b61d94a1SMarc Bonnici cm_set_next_eret_context(NON_SECURE);
252b61d94a1SMarc Bonnici
253b61d94a1SMarc Bonnici /*
254b61d94a1SMarc Bonnici * Exited from secure partition. This core can take
255b61d94a1SMarc Bonnici * interrupts now.
256b61d94a1SMarc Bonnici */
257b61d94a1SMarc Bonnici ehf_deactivate_priority(PLAT_SP_PRI);
258b61d94a1SMarc Bonnici
259b61d94a1SMarc Bonnici SMC_RET1(handle, rc);
260b61d94a1SMarc Bonnici }
261b61d94a1SMarc Bonnici
262b61d94a1SMarc Bonnici /*******************************************************************************
26396546b5cSManish Pandey * SPM_MM TPM start handler as mentioned in section 3.3.1 of TCG ACPI
26496546b5cSManish Pandey * specification version 1.4
26596546b5cSManish Pandey ******************************************************************************/
spm_mm_tpm_start_handler(uint32_t smc_fid,uint64_t x1,uint64_t x2,uint64_t x3,uint64_t x4,void * cookie,void * handle,uint64_t flags)26696546b5cSManish Pandey uint64_t spm_mm_tpm_start_handler(uint32_t smc_fid,
26796546b5cSManish Pandey uint64_t x1,
26896546b5cSManish Pandey uint64_t x2,
26996546b5cSManish Pandey uint64_t x3,
27096546b5cSManish Pandey uint64_t x4,
27196546b5cSManish Pandey void *cookie,
27296546b5cSManish Pandey void *handle,
27396546b5cSManish Pandey uint64_t flags)
27496546b5cSManish Pandey {
27596546b5cSManish Pandey mm_communicate_header_t *mm_comm_header = (void *)PLAT_SPM_BUF_BASE;
27696546b5cSManish Pandey uint32_t spm_mm_smc_fid;
27796546b5cSManish Pandey
27896546b5cSManish Pandey if (!is_caller_non_secure(flags)) {
27996546b5cSManish Pandey ERROR("spm_mm TPM START must be requested from normal world only.\n");
28096546b5cSManish Pandey SMC_RET1(handle, SMC_UNK);
28196546b5cSManish Pandey }
28296546b5cSManish Pandey
28396546b5cSManish Pandey switch (smc_fid) {
28496546b5cSManish Pandey case TPM_START_SMC_32:
28596546b5cSManish Pandey spm_mm_smc_fid = MM_COMMUNICATE_AARCH32;
28696546b5cSManish Pandey break;
28796546b5cSManish Pandey case TPM_START_SMC_64:
28896546b5cSManish Pandey spm_mm_smc_fid = MM_COMMUNICATE_AARCH64;
28996546b5cSManish Pandey break;
29096546b5cSManish Pandey default:
29196546b5cSManish Pandey ERROR("Unexpected SMC FID\n");
29296546b5cSManish Pandey SMC_RET1(handle, SMC_UNK);
29396546b5cSManish Pandey break;
29496546b5cSManish Pandey }
29596546b5cSManish Pandey
29696546b5cSManish Pandey memset(mm_comm_header, 0U, sizeof(mm_communicate_header_t));
29796546b5cSManish Pandey memcpy(&mm_comm_header->header_guid, &tpm_service_uuid, sizeof(struct efi_guid));
29896546b5cSManish Pandey
29996546b5cSManish Pandey return mm_communicate(spm_mm_smc_fid, x1, (uint64_t)mm_comm_header, x3, handle);
30096546b5cSManish Pandey }
30196546b5cSManish Pandey
30296546b5cSManish Pandey /*******************************************************************************
303b61d94a1SMarc Bonnici * Secure Partition Manager SMC handler.
304b61d94a1SMarc Bonnici ******************************************************************************/
spm_mm_smc_handler(uint32_t smc_fid,uint64_t x1,uint64_t x2,uint64_t x3,uint64_t x4,void * cookie,void * handle,uint64_t flags)305b61d94a1SMarc Bonnici uint64_t spm_mm_smc_handler(uint32_t smc_fid,
306b61d94a1SMarc Bonnici uint64_t x1,
307b61d94a1SMarc Bonnici uint64_t x2,
308b61d94a1SMarc Bonnici uint64_t x3,
309b61d94a1SMarc Bonnici uint64_t x4,
310b61d94a1SMarc Bonnici void *cookie,
311b61d94a1SMarc Bonnici void *handle,
312b61d94a1SMarc Bonnici uint64_t flags)
313b61d94a1SMarc Bonnici {
314b61d94a1SMarc Bonnici unsigned int ns;
315*127bd5b1SLevi Yun int32_t ret;
316*127bd5b1SLevi Yun uint32_t attr;
317*127bd5b1SLevi Yun uint32_t page_count;
318b61d94a1SMarc Bonnici
319b61d94a1SMarc Bonnici /* Determine which security state this SMC originated from */
320b61d94a1SMarc Bonnici ns = is_caller_non_secure(flags);
321b61d94a1SMarc Bonnici
322b61d94a1SMarc Bonnici if (ns == SMC_FROM_SECURE) {
323b61d94a1SMarc Bonnici
324b61d94a1SMarc Bonnici /* Handle SMCs from Secure world. */
325b61d94a1SMarc Bonnici
326b61d94a1SMarc Bonnici assert(handle == cm_get_context(SECURE));
327b61d94a1SMarc Bonnici
328b61d94a1SMarc Bonnici /* Make next ERET jump to S-EL0 instead of S-EL1. */
329b61d94a1SMarc Bonnici cm_set_elr_spsr_el3(SECURE, read_elr_el1(), read_spsr_el1());
330b61d94a1SMarc Bonnici
331b61d94a1SMarc Bonnici switch (smc_fid) {
332b61d94a1SMarc Bonnici
333b61d94a1SMarc Bonnici case SPM_MM_VERSION_AARCH32:
334b61d94a1SMarc Bonnici SMC_RET1(handle, SPM_MM_VERSION_COMPILED);
335b61d94a1SMarc Bonnici
336b61d94a1SMarc Bonnici case MM_SP_EVENT_COMPLETE_AARCH64:
337b61d94a1SMarc Bonnici spm_sp_synchronous_exit(x1);
338b61d94a1SMarc Bonnici
339b61d94a1SMarc Bonnici case MM_SP_MEMORY_ATTRIBUTES_GET_AARCH64:
340b61d94a1SMarc Bonnici INFO("Received MM_SP_MEMORY_ATTRIBUTES_GET_AARCH64 SMC\n");
341b61d94a1SMarc Bonnici
342b61d94a1SMarc Bonnici if (sp_ctx.state != SP_STATE_RESET) {
343b61d94a1SMarc Bonnici WARN("MM_SP_MEMORY_ATTRIBUTES_GET_AARCH64 is available at boot time only\n");
344b61d94a1SMarc Bonnici SMC_RET1(handle, SPM_MM_NOT_SUPPORTED);
345b61d94a1SMarc Bonnici }
346*127bd5b1SLevi Yun
347*127bd5b1SLevi Yun /* x2 = page_count - 1 */
348*127bd5b1SLevi Yun page_count = x2 + 1;
349*127bd5b1SLevi Yun
350*127bd5b1SLevi Yun ret = spm_memory_attributes_get_smc_handler(
351*127bd5b1SLevi Yun &sp_ctx, x1, &page_count, &attr);
352*127bd5b1SLevi Yun if (ret != SPM_MM_SUCCESS) {
353*127bd5b1SLevi Yun SMC_RET1(handle, ret);
354*127bd5b1SLevi Yun } else {
355*127bd5b1SLevi Yun SMC_RET2(handle, attr, --page_count);
356*127bd5b1SLevi Yun }
357b61d94a1SMarc Bonnici
358b61d94a1SMarc Bonnici case MM_SP_MEMORY_ATTRIBUTES_SET_AARCH64:
359b61d94a1SMarc Bonnici INFO("Received MM_SP_MEMORY_ATTRIBUTES_SET_AARCH64 SMC\n");
360b61d94a1SMarc Bonnici
361b61d94a1SMarc Bonnici if (sp_ctx.state != SP_STATE_RESET) {
362b61d94a1SMarc Bonnici WARN("MM_SP_MEMORY_ATTRIBUTES_SET_AARCH64 is available at boot time only\n");
363b61d94a1SMarc Bonnici SMC_RET1(handle, SPM_MM_NOT_SUPPORTED);
364b61d94a1SMarc Bonnici }
365b61d94a1SMarc Bonnici SMC_RET1(handle,
366b61d94a1SMarc Bonnici spm_memory_attributes_set_smc_handler(
367b61d94a1SMarc Bonnici &sp_ctx, x1, x2, x3));
368b61d94a1SMarc Bonnici default:
369b61d94a1SMarc Bonnici break;
370b61d94a1SMarc Bonnici }
371b61d94a1SMarc Bonnici } else {
372b61d94a1SMarc Bonnici
373b61d94a1SMarc Bonnici /* Handle SMCs from Non-secure world. */
374b61d94a1SMarc Bonnici
375b61d94a1SMarc Bonnici assert(handle == cm_get_context(NON_SECURE));
376b61d94a1SMarc Bonnici
377b61d94a1SMarc Bonnici switch (smc_fid) {
378b61d94a1SMarc Bonnici
379b61d94a1SMarc Bonnici case MM_VERSION_AARCH32:
380b61d94a1SMarc Bonnici SMC_RET1(handle, MM_VERSION_COMPILED);
381b61d94a1SMarc Bonnici
382b61d94a1SMarc Bonnici case MM_COMMUNICATE_AARCH32:
383b61d94a1SMarc Bonnici case MM_COMMUNICATE_AARCH64:
384b61d94a1SMarc Bonnici return mm_communicate(smc_fid, x1, x2, x3, handle);
385b61d94a1SMarc Bonnici
386b61d94a1SMarc Bonnici case MM_SP_MEMORY_ATTRIBUTES_GET_AARCH64:
387b61d94a1SMarc Bonnici case MM_SP_MEMORY_ATTRIBUTES_SET_AARCH64:
388b61d94a1SMarc Bonnici /* SMC interfaces reserved for secure callers. */
389b61d94a1SMarc Bonnici SMC_RET1(handle, SPM_MM_NOT_SUPPORTED);
390b61d94a1SMarc Bonnici
391b61d94a1SMarc Bonnici default:
392b61d94a1SMarc Bonnici break;
393b61d94a1SMarc Bonnici }
394b61d94a1SMarc Bonnici }
395b61d94a1SMarc Bonnici
396b61d94a1SMarc Bonnici SMC_RET1(handle, SMC_UNK);
397b61d94a1SMarc Bonnici }
398