diff options
Diffstat (limited to 'services/spd/tlkd')
-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 |
3 files changed, 97 insertions, 31 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 }; |