diff --git a/Makefile b/Makefile index 5672f005f..18b7c8ae0 100644 --- a/Makefile +++ b/Makefile @@ -136,7 +136,7 @@ INCLUDES += -Ilib/include/ \ -Iinclude/${ARCH}/ \ -Iinclude/ \ -Iarch/system/gic \ - -Iservices/psci \ + -Iservices/std_svc/psci \ -Iinclude/stdlib \ -Iinclude/stdlib/sys \ -Iplat/${PLAT} \ diff --git a/bl31/bl31.mk b/bl31/bl31.mk index 5bc58c597..8f6998c62 100644 --- a/bl31/bl31.mk +++ b/bl31/bl31.mk @@ -33,13 +33,15 @@ vpath %.c common \ arch/system/gic \ plat/${PLAT} \ arch/${ARCH} \ - services/psci \ + services/std_svc \ + services/std_svc/psci \ lib/sync/locks/bakery \ plat/${PLAT}/${ARCH} \ ${PLAT_BL31_C_VPATH} vpath %.S lib/arch/${ARCH} \ - services/psci \ + services/std_svc \ + services/std_svc/psci \ include \ plat/${PLAT}/${ARCH} \ lib/sync/locks/exclusive \ @@ -51,6 +53,7 @@ BL31_SOURCES += bl31_arch_setup.c \ bl31_entrypoint.S \ runtime_exceptions.S \ bl31_main.c \ + std_svc_setup.c \ psci_entry.S \ psci_setup.c \ psci_common.c \ diff --git a/docs/rt-svc-writers-guide.md b/docs/rt-svc-writers-guide.md index 07394b056..2d13f745e 100644 --- a/docs/rt-svc-writers-guide.md +++ b/docs/rt-svc-writers-guide.md @@ -93,9 +93,10 @@ handler will be responsible for all SMC Functions within a given service type. 3. Getting started ------------------- -ARM Trusted Firmware has a [`services`] directory in the source tree under -which each owning entity can place the implementation of its runtime service. -The [PSCI] implementation is located here in the [`services/psci`] directory. +ARM Trusted Firmware has a [`services`] directory in the source tree under which +each owning entity can place the implementation of its runtime service. The +[PSCI] implementation is located here in the [`services/std_svc/psci`] +directory. Runtime service sources will need to include the [`runtime_svc.h`] header file. @@ -141,16 +142,16 @@ to ensure that the following conditions are met: 3. The `_type` is one of `SMC_TYPE_FAST` or `SMC_TYPE_STD` 4. `_setup` and `_smch` routines have been specified -[`psci_steup.c`] provides an example of registering a runtime service: +[`std_svc_setup.c`] provides an example of registering a runtime service: - /* Register PSCI as a run time service */ + /* Register Standard Service Calls as runtime service */ DECLARE_RT_SVC( - psci, + std_svc, OEN_STD_START, OEN_STD_END, SMC_TYPE_FAST, - psci_setup, - psci_smc_handler + std_svc_setup, + std_svc_smc_handler ); @@ -300,9 +301,9 @@ _Copyright (c) 2014, ARM Limited and Contributors. All rights reserved._ [Firmware Design]: ./firmware-design.md -[`services`]: ../services -[`services/psci`]: ../services/psci -[`psci_steup.c`]: ../services/psci/psci_setup.c -[`runtime_svc.h`]: ../include/runtime_svc.h -[PSCI]: http://infocenter.arm.com/help/topic/com.arm.doc.den0022b/index.html "Power State Coordination Interface PDD (ARM DEN 0022B.b)" -[SMCCC]: http://infocenter.arm.com/help/topic/com.arm.doc.den0028a/index.html "SMC Calling Convention PDD (ARM DEN 0028A)" +[`services`]: ../services +[`services/std_svc/psci`]: ../services/std_svc/psci +[`std_svc_setup.c`]: ../services/std_svc/std_svc_setup.c +[`runtime_svc.h`]: ../include/runtime_svc.h +[PSCI]: http://infocenter.arm.com/help/topic/com.arm.doc.den0022b/index.html "Power State Coordination Interface PDD (ARM DEN 0022B.b)" +[SMCCC]: http://infocenter.arm.com/help/topic/com.arm.doc.den0028a/index.html "SMC Calling Convention PDD (ARM DEN 0028A)" diff --git a/include/psci.h b/include/psci.h index 922f95f39..6fe1d8af3 100644 --- a/include/psci.h +++ b/include/psci.h @@ -47,9 +47,15 @@ #define PSCI_MIG_INFO_TYPE 0x84000006 #define PSCI_MIG_INFO_UP_CPU_AARCH32 0x84000007 #define PSCI_MIG_INFO_UP_CPU_AARCH64 0xc4000007 -#define PSCI_SYSTEM_OFF 0x84000008 +#define PSCI_SYSTEM_OFF 0x84000008 #define PSCI_SYSTEM_RESET 0x84000009 +/* + * Number of PSCI calls (above) implemented. System off and reset aren't + * implemented as yet + */ +#define PSCI_NUM_CALLS 13 + /******************************************************************************* * PSCI Migrate and friends ******************************************************************************/ diff --git a/include/runtime_svc.h b/include/runtime_svc.h index ad202a943..148c0bc80 100644 --- a/include/runtime_svc.h +++ b/include/runtime_svc.h @@ -232,6 +232,28 @@ CASSERT(RT_SVC_DESC_HANDLE == __builtin_offsetof(rt_svc_desc, handle), \ ((call_type & FUNCID_TYPE_MASK) \ << FUNCID_OEN_WIDTH)) + +/* + * Macro to define UUID for services. Apart from defining and initializing a + * uuid_t structure, this macro verifies that the first word of the defined UUID + * does not equal SMC_UNK. This is to ensure that the caller won't mistake the + * returned UUID in x0 for an invalid SMC error return + */ +#define DEFINE_SVC_UUID(_name, _tl, _tm, _th, _cl, _ch, \ + _n0, _n1, _n2, _n3, _n4, _n5) \ + CASSERT(_tl != SMC_UNK, invalid_svc_uuid);\ + static const uuid_t _name = { \ + _tl, _tm, _th, _cl, _ch, \ + { _n0, _n1, _n2, _n3, _n4, _n5 } \ + } + +/* Return a UUID in the SMC return registers */ +#define SMC_UUID_RET(_h, _uuid) \ + SMC_RET4(handle, ((const uint32_t *) &(_uuid))[0], \ + ((const uint32_t *) &(_uuid))[1], \ + ((const uint32_t *) &(_uuid))[2], \ + ((const uint32_t *) &(_uuid))[3]) + /******************************************************************************* * Function & variable prototypes ******************************************************************************/ diff --git a/include/std_svc.h b/include/std_svc.h new file mode 100644 index 000000000..cbd5b6208 --- /dev/null +++ b/include/std_svc.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __STD_SVC_H__ +#define __STD_SVC_H__ + +/* SMC function IDs for Standard Service queries */ + +#define ARM_STD_SVC_CALL_COUNT 0x8400ff00 +#define ARM_STD_SVC_UID 0x8400ff01 +/* 0x8400ff02 is reserved */ +#define ARM_STD_SVC_VERSION 0x8400ff03 + +/* ARM Standard Service Calls version numbers */ +#define STD_SVC_VERSION_MAJOR 0x0 +#define STD_SVC_VERSION_MINOR 0x1 + +/* The macros below are used to identify PSCI calls from the SMC function ID */ +#define PSCI_FID_MASK 0xffe0u +#define PSCI_FID_VALUE 0u +#define is_psci_fid(_fid) \ + (((_fid) & PSCI_FID_MASK) == PSCI_FID_VALUE) + +#endif /* __STD_SVC_H__ */ diff --git a/services/psci/psci_afflvl_off.c b/services/std_svc/psci/psci_afflvl_off.c similarity index 100% rename from services/psci/psci_afflvl_off.c rename to services/std_svc/psci/psci_afflvl_off.c diff --git a/services/psci/psci_afflvl_on.c b/services/std_svc/psci/psci_afflvl_on.c similarity index 100% rename from services/psci/psci_afflvl_on.c rename to services/std_svc/psci/psci_afflvl_on.c diff --git a/services/psci/psci_afflvl_suspend.c b/services/std_svc/psci/psci_afflvl_suspend.c similarity index 100% rename from services/psci/psci_afflvl_suspend.c rename to services/std_svc/psci/psci_afflvl_suspend.c diff --git a/services/psci/psci_common.c b/services/std_svc/psci/psci_common.c similarity index 100% rename from services/psci/psci_common.c rename to services/std_svc/psci/psci_common.c diff --git a/services/psci/psci_entry.S b/services/std_svc/psci/psci_entry.S similarity index 100% rename from services/psci/psci_entry.S rename to services/std_svc/psci/psci_entry.S diff --git a/services/psci/psci_main.c b/services/std_svc/psci/psci_main.c similarity index 95% rename from services/psci/psci_main.c rename to services/std_svc/psci/psci_main.c index ca3a5a067..6bf058304 100644 --- a/services/psci/psci_main.c +++ b/services/std_svc/psci/psci_main.c @@ -190,18 +190,6 @@ unsigned long psci_migrate_info_up_cpu(void) return PSCI_E_SUCCESS; } -/* Unimplemented */ -void psci_system_off(void) -{ - assert(0); -} - -/* Unimplemented */ -void psci_system_reset(void) -{ - assert(0); -} - /******************************************************************************* * PSCI top level handler for servicing SMCs. ******************************************************************************/ @@ -254,17 +242,9 @@ uint64_t psci_smc_handler(uint32_t smc_fid, rc = psci_migrate_info_up_cpu(); break; - case PSCI_SYSTEM_OFF: - psci_system_off(); - assert(0); - - case PSCI_SYSTEM_RESET: - psci_system_reset(); - assert(0); - default: rc = SMC_UNK; - WARN("Unimplemented psci call -> 0x%x \n", smc_fid); + WARN("Unimplemented PSCI Call: 0x%x \n", smc_fid); } SMC_RET1(handle, rc); diff --git a/services/psci/psci_private.h b/services/std_svc/psci/psci_private.h similarity index 99% rename from services/psci/psci_private.h rename to services/std_svc/psci/psci_private.h index 4f47ca5dd..2d9d12ba8 100644 --- a/services/psci/psci_private.h +++ b/services/std_svc/psci/psci_private.h @@ -166,6 +166,10 @@ extern uint64_t psci_smc_handler(uint32_t smc_fid, void *cookie, void *handle, uint64_t flags); + +/* PSCI setup function */ +extern int32_t psci_setup(void); + #endif /*__ASSEMBLY__*/ #endif /* __PSCI_PRIVATE_H__ */ diff --git a/services/psci/psci_setup.c b/services/std_svc/psci/psci_setup.c similarity index 98% rename from services/psci/psci_setup.c rename to services/std_svc/psci/psci_setup.c index 8d7903c19..e3a5d5d08 100644 --- a/services/psci/psci_setup.c +++ b/services/std_svc/psci/psci_setup.c @@ -342,14 +342,3 @@ int32_t psci_setup(void) return 0; } - -/* Register PSCI as a run time service */ -DECLARE_RT_SVC( - psci, - - OEN_STD_START, - OEN_STD_END, - SMC_TYPE_FAST, - psci_setup, - psci_smc_handler -); diff --git a/services/std_svc/std_svc_setup.c b/services/std_svc/std_svc_setup.c new file mode 100644 index 000000000..080836ab9 --- /dev/null +++ b/services/std_svc/std_svc_setup.c @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/* Standard Service UUID */ +DEFINE_SVC_UUID(arm_svc_uid, + 0x108d905b, 0xf863, 0x47e8, 0xae, 0x2d, + 0xc0, 0xfb, 0x56, 0x41, 0xf6, 0xe2); + +/* Setup Standard Services */ +static int32_t std_svc_setup(void) +{ + /* + * PSCI is the only specification implemented as a Standard Service. + * Invoke PSCI setup from here + */ + return psci_setup(); +} + +/* + * Top-level Standard Service SMC handler. This handler will in turn dispatch + * calls to PSCI SMC handler + */ +uint64_t std_svc_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) +{ + /* + * Dispatch PSCI calls to PSCI SMC handler and return its return + * value + */ + if (is_psci_fid(smc_fid)) { + return psci_smc_handler(smc_fid, x1, x2, x3, x4, cookie, + handle, flags); + } + + switch (smc_fid) { + case ARM_STD_SVC_CALL_COUNT: + /* + * Return the number of Standard Service Calls. PSCI is the only + * standard service implemented; so return number of PSCI calls + */ + SMC_RET1(handle, PSCI_NUM_CALLS); + + case ARM_STD_SVC_UID: + /* Return UID to the caller */ + SMC_UUID_RET(handle, arm_svc_uid); + + case ARM_STD_SVC_VERSION: + /* Return the version of current implementation */ + SMC_RET2(handle, STD_SVC_VERSION_MAJOR, STD_SVC_VERSION_MINOR); + + default: + WARN("Unimplemented Standard Service Call: 0x%x \n", smc_fid); + SMC_RET1(handle, SMC_UNK); + } +} + +/* Register Standard Service Calls as runtime service */ +DECLARE_RT_SVC( + std_svc, + + OEN_STD_START, + OEN_STD_END, + SMC_TYPE_FAST, + std_svc_setup, + std_svc_smc_handler +);