1c681d02cSMarcin Juszkiewicz /* 2c681d02cSMarcin Juszkiewicz * Copyright (c) 2023, Linaro Limited and Contributors. All rights reserved. 3c681d02cSMarcin Juszkiewicz * 4c681d02cSMarcin Juszkiewicz * SPDX-License-Identifier: BSD-3-Clause 5c681d02cSMarcin Juszkiewicz */ 6c681d02cSMarcin Juszkiewicz 7c681d02cSMarcin Juszkiewicz #include <assert.h> 8c681d02cSMarcin Juszkiewicz 9c681d02cSMarcin Juszkiewicz #include <common/runtime_svc.h> 10c681d02cSMarcin Juszkiewicz #include <smccc_helpers.h> 11c681d02cSMarcin Juszkiewicz 12b386c6e6SMathieu Poirier #include <sbsa_platform.h> 13b386c6e6SMathieu Poirier 14c681d02cSMarcin Juszkiewicz #define SMC_FASTCALL 0x80000000 15c681d02cSMarcin Juszkiewicz #define SMC64_FUNCTION (SMC_FASTCALL | 0x40000000) 16c681d02cSMarcin Juszkiewicz #define SIP_FUNCTION (SMC64_FUNCTION | 0x02000000) 17c681d02cSMarcin Juszkiewicz #define SIP_FUNCTION_ID(n) (SIP_FUNCTION | (n)) 18c681d02cSMarcin Juszkiewicz 19c681d02cSMarcin Juszkiewicz /* 20c681d02cSMarcin Juszkiewicz * We do not use SMCCC_ARCH_SOC_ID here because qemu_sbsa is virtual platform 21c681d02cSMarcin Juszkiewicz * which uses SoC present in QEMU. And they can change on their own while we 22c681d02cSMarcin Juszkiewicz * need version of whole 'virtual hardware platform'. 23c681d02cSMarcin Juszkiewicz */ 24c681d02cSMarcin Juszkiewicz #define SIP_SVC_VERSION SIP_FUNCTION_ID(1) 251e67b1b1SMarcin Juszkiewicz #define SIP_SVC_GET_GIC SIP_FUNCTION_ID(100) 264171e981SMarcin Juszkiewicz #define SIP_SVC_GET_GIC_ITS SIP_FUNCTION_ID(101) 2742925c15SMarcin Juszkiewicz #define SIP_SVC_GET_CPU_COUNT SIP_FUNCTION_ID(200) 2842925c15SMarcin Juszkiewicz #define SIP_SVC_GET_CPU_NODE SIP_FUNCTION_ID(201) 29c891b4d8SXiong Yining #define SIP_SVC_GET_CPU_TOPOLOGY SIP_FUNCTION_ID(202) 308b7dd839SXiong Yining #define SIP_SVC_GET_MEMORY_NODE_COUNT SIP_FUNCTION_ID(300) 318b7dd839SXiong Yining #define SIP_SVC_GET_MEMORY_NODE SIP_FUNCTION_ID(301) 324171e981SMarcin Juszkiewicz 331e67b1b1SMarcin Juszkiewicz uintptr_t sbsa_get_gicd(void); 341e67b1b1SMarcin Juszkiewicz uintptr_t sbsa_get_gicr(void); 351e67b1b1SMarcin Juszkiewicz 369b076436SMarcin Juszkiewicz /* 37c681d02cSMarcin Juszkiewicz * This function is responsible for handling all SiP calls from the NS world 38c681d02cSMarcin Juszkiewicz */ 39c681d02cSMarcin Juszkiewicz uintptr_t sbsa_sip_smc_handler(uint32_t smc_fid, 40c681d02cSMarcin Juszkiewicz u_register_t x1, 41c681d02cSMarcin Juszkiewicz u_register_t x2, 42c681d02cSMarcin Juszkiewicz u_register_t x3, 43c681d02cSMarcin Juszkiewicz u_register_t x4, 44c681d02cSMarcin Juszkiewicz void *cookie, 45c681d02cSMarcin Juszkiewicz void *handle, 46c681d02cSMarcin Juszkiewicz u_register_t flags) 47c681d02cSMarcin Juszkiewicz { 48c681d02cSMarcin Juszkiewicz uint32_t ns; 4942925c15SMarcin Juszkiewicz uint64_t index; 50c681d02cSMarcin Juszkiewicz 51c681d02cSMarcin Juszkiewicz /* Determine which security state this SMC originated from */ 52c681d02cSMarcin Juszkiewicz ns = is_caller_non_secure(flags); 53c681d02cSMarcin Juszkiewicz if (!ns) { 54c681d02cSMarcin Juszkiewicz ERROR("%s: wrong world SMC (0x%x)\n", __func__, smc_fid); 55c681d02cSMarcin Juszkiewicz SMC_RET1(handle, SMC_UNK); 56c681d02cSMarcin Juszkiewicz } 57c681d02cSMarcin Juszkiewicz 58c681d02cSMarcin Juszkiewicz switch (smc_fid) { 59c681d02cSMarcin Juszkiewicz case SIP_SVC_VERSION: 60c681d02cSMarcin Juszkiewicz INFO("Platform version requested\n"); 61*d564e084SMathieu Poirier SMC_RET3(handle, NULL, sbsa_platform_version_major(), 62*d564e084SMathieu Poirier sbsa_platform_version_minor()); 63c681d02cSMarcin Juszkiewicz 641e67b1b1SMarcin Juszkiewicz case SIP_SVC_GET_GIC: 651e67b1b1SMarcin Juszkiewicz SMC_RET3(handle, NULL, sbsa_get_gicd(), sbsa_get_gicr()); 661e67b1b1SMarcin Juszkiewicz 674171e981SMarcin Juszkiewicz case SIP_SVC_GET_GIC_ITS: 68*d564e084SMathieu Poirier SMC_RET2(handle, NULL, sbsa_platform_gic_its_addr()); 694171e981SMarcin Juszkiewicz 7042925c15SMarcin Juszkiewicz case SIP_SVC_GET_CPU_COUNT: 71*d564e084SMathieu Poirier SMC_RET2(handle, NULL, sbsa_platform_num_cpus()); 7242925c15SMarcin Juszkiewicz 7342925c15SMarcin Juszkiewicz case SIP_SVC_GET_CPU_NODE: 7442925c15SMarcin Juszkiewicz index = x1; 7542925c15SMarcin Juszkiewicz if (index < PLATFORM_CORE_COUNT) { 76*d564e084SMathieu Poirier struct platform_cpu_data data; 77*d564e084SMathieu Poirier 78*d564e084SMathieu Poirier data = sbsa_platform_cpu_node(index); 79*d564e084SMathieu Poirier 80*d564e084SMathieu Poirier SMC_RET3(handle, NULL, data.nodeid, data.mpidr); 8142925c15SMarcin Juszkiewicz } else { 8242925c15SMarcin Juszkiewicz SMC_RET1(handle, SMC_ARCH_CALL_INVAL_PARAM); 8342925c15SMarcin Juszkiewicz } 8442925c15SMarcin Juszkiewicz 85c891b4d8SXiong Yining case SIP_SVC_GET_CPU_TOPOLOGY: 86*d564e084SMathieu Poirier struct platform_cpu_topology topology; 87*d564e084SMathieu Poirier 88*d564e084SMathieu Poirier topology = sbsa_platform_cpu_topology(); 89*d564e084SMathieu Poirier 90*d564e084SMathieu Poirier if (topology.cores > 0) { 91*d564e084SMathieu Poirier SMC_RET5(handle, NULL, topology.sockets, 92*d564e084SMathieu Poirier topology.clusters, topology.cores, 93*d564e084SMathieu Poirier topology.threads); 94c891b4d8SXiong Yining } else { 95c891b4d8SXiong Yining /* we do not know topology so we report SMC as unknown */ 96c891b4d8SXiong Yining SMC_RET1(handle, SMC_UNK); 97c891b4d8SXiong Yining } 98c891b4d8SXiong Yining 998b7dd839SXiong Yining case SIP_SVC_GET_MEMORY_NODE_COUNT: 100*d564e084SMathieu Poirier SMC_RET2(handle, NULL, sbsa_platform_num_memnodes()); 1018b7dd839SXiong Yining 1028b7dd839SXiong Yining case SIP_SVC_GET_MEMORY_NODE: 1038b7dd839SXiong Yining index = x1; 1048b7dd839SXiong Yining if (index < PLAT_MAX_MEM_NODES) { 105*d564e084SMathieu Poirier struct platform_memory_data data; 106*d564e084SMathieu Poirier 107*d564e084SMathieu Poirier data = sbsa_platform_memory_node(index); 108*d564e084SMathieu Poirier 109*d564e084SMathieu Poirier SMC_RET4(handle, NULL, data.nodeid, 110*d564e084SMathieu Poirier data.addr_base, data.addr_size); 1118b7dd839SXiong Yining } else { 1128b7dd839SXiong Yining SMC_RET1(handle, SMC_ARCH_CALL_INVAL_PARAM); 1138b7dd839SXiong Yining } 1148b7dd839SXiong Yining 115c681d02cSMarcin Juszkiewicz default: 116c681d02cSMarcin Juszkiewicz ERROR("%s: unhandled SMC (0x%x) (function id: %d)\n", __func__, smc_fid, 117c681d02cSMarcin Juszkiewicz smc_fid - SIP_FUNCTION); 118c681d02cSMarcin Juszkiewicz SMC_RET1(handle, SMC_UNK); 119c681d02cSMarcin Juszkiewicz } 120c681d02cSMarcin Juszkiewicz } 121c681d02cSMarcin Juszkiewicz 122c681d02cSMarcin Juszkiewicz int sbsa_sip_smc_setup(void) 123c681d02cSMarcin Juszkiewicz { 124c681d02cSMarcin Juszkiewicz return 0; 125c681d02cSMarcin Juszkiewicz } 126c681d02cSMarcin Juszkiewicz 127c681d02cSMarcin Juszkiewicz /* Define a runtime service descriptor for fast SMC calls */ 128c681d02cSMarcin Juszkiewicz DECLARE_RT_SVC( 129c681d02cSMarcin Juszkiewicz sbsa_sip_svc, 130c681d02cSMarcin Juszkiewicz OEN_SIP_START, 131c681d02cSMarcin Juszkiewicz OEN_SIP_END, 132c681d02cSMarcin Juszkiewicz SMC_TYPE_FAST, 133c681d02cSMarcin Juszkiewicz sbsa_sip_smc_setup, 134c681d02cSMarcin Juszkiewicz sbsa_sip_smc_handler 135c681d02cSMarcin Juszkiewicz ); 136