17a2130b4SMadhukar Pappireddy /* 2*6873088cSJ-Alves * Copyright (c) 2023-2024, Arm Limited. All rights reserved. 37a2130b4SMadhukar Pappireddy * 47a2130b4SMadhukar Pappireddy * SPDX-License-Identifier: BSD-3-Clause 57a2130b4SMadhukar Pappireddy */ 67a2130b4SMadhukar Pappireddy 77a2130b4SMadhukar Pappireddy #include <stdint.h> 8*6873088cSJ-Alves #include <errno.h> 97a2130b4SMadhukar Pappireddy 107a2130b4SMadhukar Pappireddy #include <common/debug.h> 117a2130b4SMadhukar Pappireddy #include <common/runtime_svc.h> 127a2130b4SMadhukar Pappireddy 137a2130b4SMadhukar Pappireddy #include <plat/arm/common/arm_sip_svc.h> 147a2130b4SMadhukar Pappireddy #include <plat/common/platform.h> 157a2130b4SMadhukar Pappireddy 16*6873088cSJ-Alves #if ENABLE_RME && SPMD_SPM_AT_SEL2 17*6873088cSJ-Alves #include <lib/gpt_rme/gpt_rme.h> 18*6873088cSJ-Alves #endif 19*6873088cSJ-Alves 207a2130b4SMadhukar Pappireddy #if ENABLE_SPMD_LP 217a2130b4SMadhukar Pappireddy #include <services/el3_spmd_logical_sp.h> 227a2130b4SMadhukar Pappireddy #endif 237a2130b4SMadhukar Pappireddy 24*6873088cSJ-Alves #if (ENABLE_RME == 1) && (defined(SPD_spmd) && SPMD_SPM_AT_SEL2 == 1) 25*6873088cSJ-Alves static uint64_t plat_protect_memory(bool protect, 26*6873088cSJ-Alves bool secure_origin, 27*6873088cSJ-Alves const uint64_t base, 28*6873088cSJ-Alves const size_t size, 29*6873088cSJ-Alves void *handle) 30*6873088cSJ-Alves { 31*6873088cSJ-Alves uint64_t ret = SMC_INVALID_PARAM; 32*6873088cSJ-Alves uint64_t last_updated = 0; 33*6873088cSJ-Alves 34*6873088cSJ-Alves if (!secure_origin) { 35*6873088cSJ-Alves SMC_RET1(handle, SMC_UNK); 36*6873088cSJ-Alves /* Shall not be reached. */ 37*6873088cSJ-Alves } 38*6873088cSJ-Alves 39*6873088cSJ-Alves if ((base % PAGE_SIZE_4KB) != 0U && 40*6873088cSJ-Alves (size % PAGE_SIZE_4KB) != 0U) { 41*6873088cSJ-Alves VERBOSE("Base address must be aligned to 4k.\n"); 42*6873088cSJ-Alves SMC_RET1(handle, SMC_INVALID_PARAM); 43*6873088cSJ-Alves /* Shall not be reached. */ 44*6873088cSJ-Alves } 45*6873088cSJ-Alves 46*6873088cSJ-Alves if ((ULONG_MAX - base) < size) { 47*6873088cSJ-Alves VERBOSE("Base + Size results in overflow.\n"); 48*6873088cSJ-Alves SMC_RET1(handle, SMC_INVALID_PARAM); 49*6873088cSJ-Alves /* Shall not be reached. */ 50*6873088cSJ-Alves } 51*6873088cSJ-Alves 52*6873088cSJ-Alves for (uint64_t it = base; it < (base + size); it += PAGE_SIZE_4KB) { 53*6873088cSJ-Alves /* 54*6873088cSJ-Alves * If protect is true, add memory to secure PAS. 55*6873088cSJ-Alves * Else unprotect it, making part of non-secure PAS. 56*6873088cSJ-Alves */ 57*6873088cSJ-Alves ret = protect 58*6873088cSJ-Alves ? gpt_delegate_pas(it, PAGE_SIZE_4KB, 59*6873088cSJ-Alves SMC_FROM_SECURE) 60*6873088cSJ-Alves : gpt_undelegate_pas(it, PAGE_SIZE_4KB, 61*6873088cSJ-Alves SMC_FROM_SECURE); 62*6873088cSJ-Alves 63*6873088cSJ-Alves switch (ret) { 64*6873088cSJ-Alves case 0: 65*6873088cSJ-Alves last_updated = it; 66*6873088cSJ-Alves break; 67*6873088cSJ-Alves case -EINVAL: 68*6873088cSJ-Alves SMC_RET2(handle, SMC_INVALID_PARAM, last_updated); 69*6873088cSJ-Alves break; /* Shall not be reached. */ 70*6873088cSJ-Alves case -EPERM: 71*6873088cSJ-Alves SMC_RET2(handle, SMC_DENIED, last_updated); 72*6873088cSJ-Alves break; /* Shall not be reached. */ 73*6873088cSJ-Alves default: 74*6873088cSJ-Alves ERROR("Unexpected return\n"); 75*6873088cSJ-Alves panic(); 76*6873088cSJ-Alves } 77*6873088cSJ-Alves } 78*6873088cSJ-Alves 79*6873088cSJ-Alves SMC_RET1(handle, SMC_OK); 80*6873088cSJ-Alves } 81*6873088cSJ-Alves #endif /* ENABLE_RME && SPMD_SPM_AT_SEL2 */ 82*6873088cSJ-Alves 837a2130b4SMadhukar Pappireddy uintptr_t plat_arm_sip_handler(uint32_t smc_fid, 847a2130b4SMadhukar Pappireddy u_register_t x1, 857a2130b4SMadhukar Pappireddy u_register_t x2, 867a2130b4SMadhukar Pappireddy u_register_t x3, 877a2130b4SMadhukar Pappireddy u_register_t x4, 887a2130b4SMadhukar Pappireddy void *cookie, 897a2130b4SMadhukar Pappireddy void *handle, 907a2130b4SMadhukar Pappireddy u_register_t flags) 917a2130b4SMadhukar Pappireddy { 9220324013SMadhukar Pappireddy bool secure_origin; 9320324013SMadhukar Pappireddy 9420324013SMadhukar Pappireddy /* Determine which security state this SMC originated from */ 9520324013SMadhukar Pappireddy secure_origin = is_caller_secure(flags); 96*6873088cSJ-Alves (void) secure_origin; 9720324013SMadhukar Pappireddy 9820324013SMadhukar Pappireddy switch (smc_fid) { 99*6873088cSJ-Alves #if PLAT_TEST_SPM 10020324013SMadhukar Pappireddy case ARM_SIP_SET_INTERRUPT_PENDING: 10120324013SMadhukar Pappireddy if (!secure_origin) { 10220324013SMadhukar Pappireddy SMC_RET1(handle, SMC_UNK); 10320324013SMadhukar Pappireddy } 10420324013SMadhukar Pappireddy 10520324013SMadhukar Pappireddy VERBOSE("SiP Call- Set interrupt pending %d\n", (uint32_t)x1); 10620324013SMadhukar Pappireddy plat_ic_set_interrupt_pending(x1); 10720324013SMadhukar Pappireddy 10820324013SMadhukar Pappireddy SMC_RET1(handle, SMC_OK); 10920324013SMadhukar Pappireddy break; /* Not reached */ 11020324013SMadhukar Pappireddy #endif 11120324013SMadhukar Pappireddy 112*6873088cSJ-Alves #if (ENABLE_RME == 1) && (defined(SPD_spmd) && SPMD_SPM_AT_SEL2 == 1) 113*6873088cSJ-Alves case PLAT_PROTECT_MEM_SMC64: 114*6873088cSJ-Alves INFO("Sip Call - Protect memory\n"); 115*6873088cSJ-Alves return plat_protect_memory(true, secure_origin, x1, x2, handle); 116*6873088cSJ-Alves break; 117*6873088cSJ-Alves case PLAT_UNPROTECT_MEM_SMC64: 118*6873088cSJ-Alves INFO("Sip Call - Unprotect memory\n"); 119*6873088cSJ-Alves return plat_protect_memory(false, secure_origin, x1, x2, handle); 120*6873088cSJ-Alves break; 121*6873088cSJ-Alves #endif 122*6873088cSJ-Alves } 123*6873088cSJ-Alves 1247a2130b4SMadhukar Pappireddy #if ENABLE_SPMD_LP 1257a2130b4SMadhukar Pappireddy return plat_spmd_logical_sp_smc_handler(smc_fid, x1, x2, x3, x4, 1267a2130b4SMadhukar Pappireddy cookie, handle, flags); 1277a2130b4SMadhukar Pappireddy #else 1287a2130b4SMadhukar Pappireddy WARN("Unimplemented ARM SiP Service Call: 0x%x\n", smc_fid); 1297a2130b4SMadhukar Pappireddy SMC_RET1(handle, SMC_UNK); 1307a2130b4SMadhukar Pappireddy #endif 1317a2130b4SMadhukar Pappireddy } 132