1*c681d02cSMarcin Juszkiewicz /* 2*c681d02cSMarcin Juszkiewicz * Copyright (c) 2023, Linaro Limited and Contributors. All rights reserved. 3*c681d02cSMarcin Juszkiewicz * 4*c681d02cSMarcin Juszkiewicz * SPDX-License-Identifier: BSD-3-Clause 5*c681d02cSMarcin Juszkiewicz */ 6*c681d02cSMarcin Juszkiewicz 7*c681d02cSMarcin Juszkiewicz #include <assert.h> 8*c681d02cSMarcin Juszkiewicz 9*c681d02cSMarcin Juszkiewicz #include <common/runtime_svc.h> 10*c681d02cSMarcin Juszkiewicz #include <libfdt.h> 11*c681d02cSMarcin Juszkiewicz #include <smccc_helpers.h> 12*c681d02cSMarcin Juszkiewicz 13*c681d02cSMarcin Juszkiewicz /* default platform version is 0.0 */ 14*c681d02cSMarcin Juszkiewicz static int platform_version_major; 15*c681d02cSMarcin Juszkiewicz static int platform_version_minor; 16*c681d02cSMarcin Juszkiewicz 17*c681d02cSMarcin Juszkiewicz #define SMC_FASTCALL 0x80000000 18*c681d02cSMarcin Juszkiewicz #define SMC64_FUNCTION (SMC_FASTCALL | 0x40000000) 19*c681d02cSMarcin Juszkiewicz #define SIP_FUNCTION (SMC64_FUNCTION | 0x02000000) 20*c681d02cSMarcin Juszkiewicz #define SIP_FUNCTION_ID(n) (SIP_FUNCTION | (n)) 21*c681d02cSMarcin Juszkiewicz 22*c681d02cSMarcin Juszkiewicz /* 23*c681d02cSMarcin Juszkiewicz * We do not use SMCCC_ARCH_SOC_ID here because qemu_sbsa is virtual platform 24*c681d02cSMarcin Juszkiewicz * which uses SoC present in QEMU. And they can change on their own while we 25*c681d02cSMarcin Juszkiewicz * need version of whole 'virtual hardware platform'. 26*c681d02cSMarcin Juszkiewicz */ 27*c681d02cSMarcin Juszkiewicz #define SIP_SVC_VERSION SIP_FUNCTION_ID(1) 28*c681d02cSMarcin Juszkiewicz 29*c681d02cSMarcin Juszkiewicz void read_platform_version(void *dtb) 30*c681d02cSMarcin Juszkiewicz { 31*c681d02cSMarcin Juszkiewicz int node; 32*c681d02cSMarcin Juszkiewicz 33*c681d02cSMarcin Juszkiewicz node = fdt_path_offset(dtb, "/"); 34*c681d02cSMarcin Juszkiewicz if (node >= 0) { 35*c681d02cSMarcin Juszkiewicz platform_version_major = fdt32_ld(fdt_getprop(dtb, node, 36*c681d02cSMarcin Juszkiewicz "machine-version-major", NULL)); 37*c681d02cSMarcin Juszkiewicz platform_version_minor = fdt32_ld(fdt_getprop(dtb, node, 38*c681d02cSMarcin Juszkiewicz "machine-version-minor", NULL)); 39*c681d02cSMarcin Juszkiewicz } 40*c681d02cSMarcin Juszkiewicz } 41*c681d02cSMarcin Juszkiewicz 42*c681d02cSMarcin Juszkiewicz void sip_svc_init(void) 43*c681d02cSMarcin Juszkiewicz { 44*c681d02cSMarcin Juszkiewicz /* Read DeviceTree data before MMU is enabled */ 45*c681d02cSMarcin Juszkiewicz 46*c681d02cSMarcin Juszkiewicz void *dtb = (void *)(uintptr_t)ARM_PRELOADED_DTB_BASE; 47*c681d02cSMarcin Juszkiewicz int err; 48*c681d02cSMarcin Juszkiewicz 49*c681d02cSMarcin Juszkiewicz err = fdt_open_into(dtb, dtb, PLAT_QEMU_DT_MAX_SIZE); 50*c681d02cSMarcin Juszkiewicz if (err < 0) { 51*c681d02cSMarcin Juszkiewicz ERROR("Invalid Device Tree at %p: error %d\n", dtb, err); 52*c681d02cSMarcin Juszkiewicz return; 53*c681d02cSMarcin Juszkiewicz } 54*c681d02cSMarcin Juszkiewicz 55*c681d02cSMarcin Juszkiewicz err = fdt_check_header(dtb); 56*c681d02cSMarcin Juszkiewicz if (err < 0) { 57*c681d02cSMarcin Juszkiewicz ERROR("Invalid DTB file passed\n"); 58*c681d02cSMarcin Juszkiewicz return; 59*c681d02cSMarcin Juszkiewicz } 60*c681d02cSMarcin Juszkiewicz 61*c681d02cSMarcin Juszkiewicz read_platform_version(dtb); 62*c681d02cSMarcin Juszkiewicz INFO("Platform version: %d.%d\n", platform_version_major, platform_version_minor); 63*c681d02cSMarcin Juszkiewicz } 64*c681d02cSMarcin Juszkiewicz 65*c681d02cSMarcin Juszkiewicz /* 66*c681d02cSMarcin Juszkiewicz * This function is responsible for handling all SiP calls from the NS world 67*c681d02cSMarcin Juszkiewicz */ 68*c681d02cSMarcin Juszkiewicz uintptr_t sbsa_sip_smc_handler(uint32_t smc_fid, 69*c681d02cSMarcin Juszkiewicz u_register_t x1, 70*c681d02cSMarcin Juszkiewicz u_register_t x2, 71*c681d02cSMarcin Juszkiewicz u_register_t x3, 72*c681d02cSMarcin Juszkiewicz u_register_t x4, 73*c681d02cSMarcin Juszkiewicz void *cookie, 74*c681d02cSMarcin Juszkiewicz void *handle, 75*c681d02cSMarcin Juszkiewicz u_register_t flags) 76*c681d02cSMarcin Juszkiewicz { 77*c681d02cSMarcin Juszkiewicz uint32_t ns; 78*c681d02cSMarcin Juszkiewicz 79*c681d02cSMarcin Juszkiewicz /* Determine which security state this SMC originated from */ 80*c681d02cSMarcin Juszkiewicz ns = is_caller_non_secure(flags); 81*c681d02cSMarcin Juszkiewicz if (!ns) { 82*c681d02cSMarcin Juszkiewicz ERROR("%s: wrong world SMC (0x%x)\n", __func__, smc_fid); 83*c681d02cSMarcin Juszkiewicz SMC_RET1(handle, SMC_UNK); 84*c681d02cSMarcin Juszkiewicz } 85*c681d02cSMarcin Juszkiewicz 86*c681d02cSMarcin Juszkiewicz switch (smc_fid) { 87*c681d02cSMarcin Juszkiewicz case SIP_SVC_VERSION: 88*c681d02cSMarcin Juszkiewicz INFO("Platform version requested\n"); 89*c681d02cSMarcin Juszkiewicz SMC_RET3(handle, NULL, platform_version_major, platform_version_minor); 90*c681d02cSMarcin Juszkiewicz 91*c681d02cSMarcin Juszkiewicz default: 92*c681d02cSMarcin Juszkiewicz ERROR("%s: unhandled SMC (0x%x) (function id: %d)\n", __func__, smc_fid, 93*c681d02cSMarcin Juszkiewicz smc_fid - SIP_FUNCTION); 94*c681d02cSMarcin Juszkiewicz SMC_RET1(handle, SMC_UNK); 95*c681d02cSMarcin Juszkiewicz } 96*c681d02cSMarcin Juszkiewicz } 97*c681d02cSMarcin Juszkiewicz 98*c681d02cSMarcin Juszkiewicz int sbsa_sip_smc_setup(void) 99*c681d02cSMarcin Juszkiewicz { 100*c681d02cSMarcin Juszkiewicz return 0; 101*c681d02cSMarcin Juszkiewicz } 102*c681d02cSMarcin Juszkiewicz 103*c681d02cSMarcin Juszkiewicz /* Define a runtime service descriptor for fast SMC calls */ 104*c681d02cSMarcin Juszkiewicz DECLARE_RT_SVC( 105*c681d02cSMarcin Juszkiewicz sbsa_sip_svc, 106*c681d02cSMarcin Juszkiewicz OEN_SIP_START, 107*c681d02cSMarcin Juszkiewicz OEN_SIP_END, 108*c681d02cSMarcin Juszkiewicz SMC_TYPE_FAST, 109*c681d02cSMarcin Juszkiewicz sbsa_sip_smc_setup, 110*c681d02cSMarcin Juszkiewicz sbsa_sip_smc_handler 111*c681d02cSMarcin Juszkiewicz ); 112