diff options
Diffstat (limited to 'services/spd')
-rw-r--r-- | services/spd/tlkd/tlkd_common.c | 8 | ||||
-rw-r--r-- | services/spd/tlkd/tlkd_main.c | 94 | ||||
-rw-r--r-- | services/spd/tlkd/tlkd_pm.c | 26 | ||||
-rw-r--r-- | services/spd/trusty/generic-arm64-smcall.c | 23 | ||||
-rw-r--r-- | services/spd/trusty/generic-arm64-smcall.h | 1 | ||||
-rw-r--r-- | services/spd/trusty/smcall.h | 8 | ||||
-rw-r--r-- | services/spd/trusty/trusty.c | 35 | ||||
-rw-r--r-- | services/spd/tspd/tspd_main.c | 4 |
8 files changed, 158 insertions, 41 deletions
diff --git a/services/spd/tlkd/tlkd_common.c b/services/spd/tlkd/tlkd_common.c index dbe6c2e34..820bd8a72 100644 --- a/services/spd/tlkd/tlkd_common.c +++ b/services/spd/tlkd/tlkd_common.c @@ -38,16 +38,16 @@ uint64_t tlkd_va_translate(uintptr_t va, int type) int at = type & AT_MASK; switch (at) { case 0: - ats12e1r(va); + AT(ats12e1r, va); break; case 1: - ats12e1w(va); + AT(ats12e1w, va); break; case 2: - ats12e0r(va); + AT(ats12e0r, va); break; case 3: - ats12e0w(va); + AT(ats12e0w, va); break; default: assert(0); /* Unreachable */ diff --git a/services/spd/tlkd/tlkd_main.c b/services/spd/tlkd/tlkd_main.c index 3cfc52db4..ecac43522 100644 --- a/services/spd/tlkd/tlkd_main.c +++ b/services/spd/tlkd/tlkd_main.c @@ -1,5 +1,6 @@ /* - * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2020, NVIDIA Corporation. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -14,6 +15,7 @@ * responsible for initialising and maintaining communication with the SP. ******************************************************************************/ #include <assert.h> +#include <bl31/interrupt_mgmt.h> #include <errno.h> #include <stddef.h> @@ -49,6 +51,50 @@ DEFINE_SVC_UUID2(tlk_uuid, static int32_t tlkd_init(void); /******************************************************************************* + * Secure Payload Dispatcher's timer interrupt handler + ******************************************************************************/ +static uint64_t tlkd_interrupt_handler(uint32_t id, + uint32_t flags, + void *handle, + void *cookie) +{ + cpu_context_t *s_cpu_context; + int irq = plat_ic_get_pending_interrupt_id(); + + /* acknowledge the interrupt and mark it complete */ + (void)plat_ic_acknowledge_interrupt(); + plat_ic_end_of_interrupt(irq); + + /* + * Disable the routing of NS interrupts from secure world to + * EL3 while interrupted on this core. + */ + disable_intr_rm_local(INTR_TYPE_S_EL1, SECURE); + + /* Check the security state when the exception was generated */ + assert(get_interrupt_src_ss(flags) == NON_SECURE); + assert(handle == cm_get_context(NON_SECURE)); + + /* Save non-secure state */ + cm_el1_sysregs_context_save(NON_SECURE); + + /* Get a reference to the secure context */ + s_cpu_context = cm_get_context(SECURE); + assert(s_cpu_context); + + /* + * Restore non-secure state. There is no need to save the + * secure system register context since the SP was supposed + * to preserve it during S-EL1 interrupt handling. + */ + cm_el1_sysregs_context_restore(SECURE); + cm_set_next_eret_context(SECURE); + + /* Provide the IRQ number to the SPD */ + SMC_RET4(s_cpu_context, (uint32_t)TLK_IRQ_FIRED, 0, (uint32_t)irq, 0); +} + +/******************************************************************************* * Secure Payload Dispatcher setup. The SPD finds out the SP entrypoint and type * (aarch32/aarch64) if not already known and initialises the context for entry * into the SP for its initialisation. @@ -56,6 +102,8 @@ static int32_t tlkd_init(void); static int32_t tlkd_setup(void) { entry_point_info_t *tlk_ep_info; + uint32_t flags; + int32_t ret; /* * Get information about the Secure Payload (BL32) image. Its @@ -86,6 +134,18 @@ static int32_t tlkd_setup(void) tlk_ep_info->pc, &tlk_ctx); + /* get a list of all S-EL1 IRQs from the platform */ + + /* register interrupt handler */ + flags = 0; + set_interrupt_rm_flag(flags, NON_SECURE); + ret = register_interrupt_type_handler(INTR_TYPE_S_EL1, + tlkd_interrupt_handler, + flags); + if (ret != 0) { + ERROR("failed to register tlkd interrupt handler (%d)\n", ret); + } + /* * All TLK SPD initialization done. Now register our init function * with BL31 for deferred invocation @@ -212,6 +272,9 @@ static uintptr_t tlkd_smc_handler(uint32_t smc_fid, case TLK_TA_LAUNCH_OP: case TLK_TA_SEND_EVENT: case TLK_RESUME_FID: + case TLK_SET_BL_VERSION: + case TLK_LOCK_BL_INTERFACE: + case TLK_BL_RPMB_SERVICE: if (!ns) SMC_RET1(handle, SMC_UNK); @@ -370,7 +433,6 @@ static uintptr_t tlkd_smc_handler(uint32_t smc_fid, */ case TLK_SUSPEND_DONE: case TLK_RESUME_DONE: - case TLK_SYSTEM_OFF_DONE: if (ns) SMC_RET1(handle, SMC_UNK); @@ -385,6 +447,34 @@ static uintptr_t tlkd_smc_handler(uint32_t smc_fid, break; /* + * This function ID is used by SP to indicate that it has completed + * handling the secure interrupt. + */ + case TLK_IRQ_DONE: + + if (ns) + SMC_RET1(handle, SMC_UNK); + + assert(handle == cm_get_context(SECURE)); + + /* save secure world context */ + cm_el1_sysregs_context_save(SECURE); + + /* Get a reference to the non-secure context */ + ns_cpu_context = cm_get_context(NON_SECURE); + assert(ns_cpu_context); + + /* + * Restore non-secure state. There is no need to save the + * secure system register context since the SP was supposed + * to preserve it during S-EL1 interrupt handling. + */ + cm_el1_sysregs_context_restore(NON_SECURE); + cm_set_next_eret_context(NON_SECURE); + + SMC_RET0(ns_cpu_context); + + /* * Return the number of service function IDs implemented to * provide service to non-secure */ diff --git a/services/spd/tlkd/tlkd_pm.c b/services/spd/tlkd/tlkd_pm.c index 7d1959bce..ed5bf7761 100644 --- a/services/spd/tlkd/tlkd_pm.c +++ b/services/spd/tlkd/tlkd_pm.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2020, NVIDIA Corporation. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -98,29 +99,6 @@ static void cpu_resume_handler(u_register_t suspend_level) } /******************************************************************************* - * System is about to be reset. Inform the SP to allow any book-keeping - ******************************************************************************/ -static void system_off_handler(void) -{ - int cpu = read_mpidr() & MPIDR_CPU_MASK; - gp_regs_t *gp_regs; - - /* TLK runs only on CPU0 */ - if (cpu != 0) - return; - - /* pass system off/reset events to TLK */ - gp_regs = get_gpregs_ctx(&tlk_ctx.cpu_ctx); - write_ctx_reg(gp_regs, CTX_GPREG_X0, TLK_SYSTEM_OFF); - - /* - * Enter the SP. We do not care about the return value because we - * must continue with the shutdown anyway. - */ - (void)tlkd_synchronous_sp_entry(&tlk_ctx); -} - -/******************************************************************************* * Structure populated by the Dispatcher to be given a chance to perform any * bookkeeping before PSCI executes a power mgmt. operation. ******************************************************************************/ @@ -128,6 +106,4 @@ const spd_pm_ops_t tlkd_pm_ops = { .svc_migrate_info = cpu_migrate_info, .svc_suspend = cpu_suspend_handler, .svc_suspend_finish = cpu_resume_handler, - .svc_system_off = system_off_handler, - .svc_system_reset = system_off_handler }; diff --git a/services/spd/trusty/generic-arm64-smcall.c b/services/spd/trusty/generic-arm64-smcall.c index dfc3e71b7..5c3a62849 100644 --- a/services/spd/trusty/generic-arm64-smcall.c +++ b/services/spd/trusty/generic-arm64-smcall.c @@ -12,6 +12,22 @@ #include "generic-arm64-smcall.h" +#ifndef PLAT_ARM_GICD_BASE +#ifdef GICD_BASE +#define PLAT_ARM_GICD_BASE GICD_BASE +#define PLAT_ARM_GICC_BASE GICC_BASE +#ifdef GICR_BASE +#define PLAT_ARM_GICR_BASE GICR_BASE +#endif +#else +#error PLAT_ARM_GICD_BASE or GICD_BASE must be defined +#endif +#endif + +#ifndef PLAT_ARM_GICR_BASE +#define PLAT_ARM_GICR_BASE SMC_UNK +#endif + int trusty_disable_serial_debug; struct dputc_state { @@ -48,12 +64,15 @@ static void trusty_dputc(char ch, int secure) static uint64_t trusty_get_reg_base(uint32_t reg) { switch (reg) { - case 0: + case SMC_GET_GIC_BASE_GICD: return PLAT_ARM_GICD_BASE; - case 1: + case SMC_GET_GIC_BASE_GICC: return PLAT_ARM_GICC_BASE; + case SMC_GET_GIC_BASE_GICR: + return PLAT_ARM_GICR_BASE; + default: NOTICE("%s(0x%x) unknown reg\n", __func__, reg); return SMC_UNK; diff --git a/services/spd/trusty/generic-arm64-smcall.h b/services/spd/trusty/generic-arm64-smcall.h index 06efc722f..ac0346924 100644 --- a/services/spd/trusty/generic-arm64-smcall.h +++ b/services/spd/trusty/generic-arm64-smcall.h @@ -23,5 +23,6 @@ */ #define SMC_GET_GIC_BASE_GICD 0 #define SMC_GET_GIC_BASE_GICC 1 +#define SMC_GET_GIC_BASE_GICR 2 #define SMC_FC_GET_REG_BASE SMC_FASTCALL_NR(SMC_ENTITY_PLATFORM_MONITOR, 0x1) #define SMC_FC64_GET_REG_BASE SMC_FASTCALL64_NR(SMC_ENTITY_PLATFORM_MONITOR, 0x1) diff --git a/services/spd/trusty/smcall.h b/services/spd/trusty/smcall.h index 9c1c38c74..c66f7db86 100644 --- a/services/spd/trusty/smcall.h +++ b/services/spd/trusty/smcall.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2020, NVIDIA Corporation. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -71,4 +72,11 @@ #define SMC_YC_VDEV_KICK_VQ SMC_YIELDCALL_NR(SMC_ENTITY_TRUSTED_OS, 24U) #define SMC_YC_SET_ROT_PARAMS SMC_YIELDCALL_NR(SMC_ENTITY_TRUSTED_OS, 65535U) +/* + * Standard Trusted OS Function IDs that fall under Trusted OS call range + * according to SMC calling convention + */ +#define SMC_FC64_GET_UUID SMC_FASTCALL64_NR(63U, 0xFF01U) /* Implementation UID */ +#define SMC_FC_GET_UUID SMC_FASTCALL_NR(63U, 0xFF01U) /* Implementation.UID */ + #endif /* SMCALL_H */ diff --git a/services/spd/trusty/trusty.c b/services/spd/trusty/trusty.c index d6c092cb7..e102b8228 100644 --- a/services/spd/trusty/trusty.c +++ b/services/spd/trusty/trusty.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2020, NVIDIA Corporation. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -16,11 +17,18 @@ #include <common/debug.h> #include <common/runtime_svc.h> #include <lib/el3_runtime/context_mgmt.h> +#include <lib/smccc.h> #include <plat/common/platform.h> +#include <tools_share/uuid.h> #include "sm_err.h" #include "smcall.h" +/* Trusty UID: RFC-4122 compliant UUID version 4 */ +DEFINE_SVC_UUID2(trusty_uuid, + 0x40ee25f0, 0xa2bc, 0x304c, 0x8c, 0x4c, + 0xa1, 0x73, 0xc5, 0x7d, 0x8a, 0xf1); + /* macro to check if Hypervisor is enabled in the HCR_EL2 register */ #define HYP_ENABLE_FLAG 0x286001U @@ -150,9 +158,9 @@ static uint64_t trusty_fiq_handler(uint32_t id, (void)memcpy(&ctx->fiq_gpregs, get_gpregs_ctx(handle), sizeof(ctx->fiq_gpregs)); ctx->fiq_pc = SMC_GET_EL3(handle, CTX_ELR_EL3); ctx->fiq_cpsr = SMC_GET_EL3(handle, CTX_SPSR_EL3); - ctx->fiq_sp_el1 = read_ctx_reg(get_sysregs_ctx(handle), CTX_SP_EL1); + ctx->fiq_sp_el1 = read_ctx_reg(get_el1_sysregs_ctx(handle), CTX_SP_EL1); - write_ctx_reg(get_sysregs_ctx(handle), CTX_SP_EL1, ctx->fiq_handler_sp); + write_ctx_reg(get_el1_sysregs_ctx(handle), CTX_SP_EL1, ctx->fiq_handler_sp); cm_set_elr_spsr_el3(NON_SECURE, ctx->fiq_handler_pc, (uint32_t)ctx->fiq_handler_cpsr); SMC_RET0(handle); @@ -211,7 +219,7 @@ static uint64_t trusty_fiq_exit(void *handle, uint64_t x1, uint64_t x2, uint64_t */ (void)memcpy(get_gpregs_ctx(handle), &ctx->fiq_gpregs, sizeof(ctx->fiq_gpregs)); ctx->fiq_handler_active = 0; - write_ctx_reg(get_sysregs_ctx(handle), CTX_SP_EL1, ctx->fiq_sp_el1); + write_ctx_reg(get_el1_sysregs_ctx(handle), CTX_SP_EL1, ctx->fiq_sp_el1); cm_set_elr_spsr_el3(NON_SECURE, ctx->fiq_pc, (uint32_t)ctx->fiq_cpsr); SMC_RET0(handle); @@ -256,6 +264,11 @@ static uintptr_t trusty_smc_handler(uint32_t smc_fid, SMC_RET1(handle, SMC_UNK); } else { switch (smc_fid) { + case SMC_FC64_GET_UUID: + case SMC_FC_GET_UUID: + /* provide the UUID for the service to the client */ + SMC_UUID_RET(handle, trusty_uuid); + break; case SMC_FC64_SET_FIQ_HANDLER: return trusty_set_fiq_handler(handle, x1, x2, x3); case SMC_FC64_GET_FIQ_REGS: @@ -263,6 +276,12 @@ static uintptr_t trusty_smc_handler(uint32_t smc_fid, case SMC_FC_FIQ_EXIT: return trusty_fiq_exit(handle, x1, x2, x3); default: + /* Not all OENs greater than SMC_ENTITY_SECURE_MONITOR are supported */ + if (SMC_ENTITY(smc_fid) > SMC_ENTITY_SECURE_MONITOR) { + VERBOSE("%s: unsupported SMC FID (0x%x)\n", __func__, smc_fid); + SMC_RET1(handle, SMC_UNK); + } + if (is_hypervisor_mode()) vmid = SMC_GET_GP(handle, CTX_GPREG_X7); @@ -390,6 +409,10 @@ static const spd_pm_ops_t trusty_pm = { void plat_trusty_set_boot_args(aapcs64_params_t *args); +#if !defined(TSP_SEC_MEM_SIZE) && defined(BL32_MEM_SIZE) +#define TSP_SEC_MEM_SIZE BL32_MEM_SIZE +#endif + #ifdef TSP_SEC_MEM_SIZE #pragma weak plat_trusty_set_boot_args void plat_trusty_set_boot_args(aapcs64_params_t *args) @@ -409,7 +432,7 @@ static int32_t trusty_setup(void) /* Get trusty's entry point info */ ep_info = bl31_plat_get_next_image_ep_info(SECURE); if (ep_info == NULL) { - INFO("Trusty image missing.\n"); + VERBOSE("Trusty image missing.\n"); return -1; } @@ -462,7 +485,7 @@ static int32_t trusty_setup(void) trusty_fiq_handler, flags); if (ret != 0) { - ERROR("trusty: failed to register fiq handler, ret = %d\n", ret); + VERBOSE("trusty: failed to register fiq handler, ret = %d\n", ret); } if (aarch32) { @@ -498,7 +521,7 @@ DECLARE_RT_SVC( trusty_fast, OEN_TOS_START, - SMC_ENTITY_SECURE_MONITOR, + OEN_TOS_END, SMC_TYPE_FAST, trusty_setup, trusty_smc_handler diff --git a/services/spd/tspd/tspd_main.c b/services/spd/tspd/tspd_main.c index f2067244e..b0cbf625d 100644 --- a/services/spd/tspd/tspd_main.c +++ b/services/spd/tspd/tspd_main.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -126,7 +126,7 @@ static uint64_t tspd_sel1_interrupt_handler(uint32_t id, * interrupt handling. */ if (get_yield_smc_active_flag(tsp_ctx->state)) { - tsp_ctx->saved_spsr_el3 = SMC_GET_EL3(&tsp_ctx->cpu_ctx, + tsp_ctx->saved_spsr_el3 = (uint32_t)SMC_GET_EL3(&tsp_ctx->cpu_ctx, CTX_SPSR_EL3); tsp_ctx->saved_elr_el3 = SMC_GET_EL3(&tsp_ctx->cpu_ctx, CTX_ELR_EL3); |