/** * Copyright (c) 2011 Trusted Logic S.A. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * version 2 as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA */ .text #define SMICODEPUB_IRQ_END 0xFE #define SMICODEPUB_FIQ_END 0xFD #define SMICODEPUB_RPC_END 0xFC #define PUB2SEC_NOCST 0xFF #define SMICODEPUB_NEWTASK 0x00 /* * RPC status: * - 0: the secure world yielded due to an interrupt * - 1: the secure world yielded on an RPC (no public thread is handling it) * - 2: the secure world yielded on an RPC and the response is ready */ #define RPC_ADVANCEMENT_NONE 0 #define RPC_ADVANCEMENT_PENDING 1 #define RPC_ADVANCEMENT_FINISHED 2 #ifdef CONFIG_ARM_ERRATA_430973 #define INVALIDATE_BTB MCR p15, 0, R0, c7, c5, 6 #else #define INVALIDATE_BTB #endif schedule_secure_world: .global schedule_secure_world /* Save registers */ push {r4-r12, lr} /* Copy the Secure Service ID in r12 */ mov r12, r0 cmp r0, #SMICODEPUB_IRQ_END beq return_from_irq cmp r0, #SMICODEPUB_RPC_END beq return_from_rpc mov r6, #PUB2SEC_NOCST mov r12, #SMICODEPUB_NEWTASK b label_smc return_from_rpc: ldr r9, =g_RPC_parameters ldm r9, {r0-r3} /* fall through */ return_from_irq: ldr r10, =g_secure_task_id ldr r6, [r10] b label_smc label_smc: INVALIDATE_BTB dsb dmb #ifdef CONFIG_BENCH_SECURE_CYCLE /* Come from Non Secure: activate counter 1 (write to 0 are ignored) */ mov r4, #0x00000002 /* Read Count Enable Set Register */ mcr p15, 0x0, r4, c9, c12, 1 /* Come from Non Secure: stop counter 0 (write to 0 are ignored) */ mov r4, #0x00000001 /* Write Count Enable Clear Register */ mcr p15, 0x0, r4, c9, c12, 2 #endif smc #0 b service_end nop #ifdef CONFIG_BENCH_SECURE_CYCLE /* Come from Secure: activate counter 0 (write to 0 are ignored) */ mov r4, #0x00000001 /* Write Count Enable Set Register */ mcr p15, 0x0, r4, c9, c12, 1 /* Come from Secure: stop counter 1 (write to 0 are ignored) */ mov r4, #0x00000002 /* Write Count Enable Clear Register */ mcr p15, 0x0, r4, c9, c12, 2 #endif INVALIDATE_BTB ldr r8, =g_secure_task_id str r6, [r8] mov r0, #0x00 ldr r8, =g_service_end str r0, [r8] b schedule_secure_world_exit service_end: schedule_secure_world_exit: #ifdef CONFIG_BENCH_SECURE_CYCLE /* Come from Secure: activate counter 0 (write to 0 are ignored) */ mov r4, #0x00000001 /* Write Count Enable Set Register */ mcr p15, 0x0, r4, c9, c12, 1 /* Come from Secure: stop counter 1 (write to 0 are ignored) */ mov r4, #0x00000002 /* Write Count Enable Clear Register */ mcr p15, 0x0, r4, c9, c12, 2 #endif INVALIDATE_BTB /* Restore registers */ pop {r4-r12, pc} rpc_handler: .global rpc_handler #ifdef CONFIG_BENCH_SECURE_CYCLE /* Come from Secure: activate counter 0 (write to 0 are ignored) */ mov r4, #0x00000001 /* Write Count Enable Set Register */ mcr p15, 0x0, r4, c9, c12, 1 /* Come from Secure: stop counter 1 (write to 0 are ignored) */ mov r4, #0x00000002 /* Write Count Enable Clear Register */ mcr p15, 0x0, r4, c9, c12, 2 #endif INVALIDATE_BTB /* g_RPC_advancement = RPC_ADVANCEMENT_PENDING */ ldr r8, =g_RPC_advancement mov r9, #RPC_ADVANCEMENT_PENDING str r9, [r8] ldr r8, =g_RPC_parameters stm r8, {r0-r3} ldr r8, =g_secure_task_id str r6, [r8] mov r0, #0x00 ldr r8, =g_service_end str r0, [r8] /* Restore registers */ pop {r4-r12, pc} #ifdef CONFIG_BENCH_SECURE_CYCLE setup_counters: .global setup_counters push {r14} mrc p15, 0, r2, c9, c12, 0 orr r2, r2, #0x3 mcr p15, 0, r2, c9, c12, 0 mrc p15, 0, r2, c9, c12, 1 orr r2, r2, #0x80000000 mcr p15, 0, r2, c9, c12, 1 pop {pc} run_code_speed: .global run_code_speed push {r14} /* Reset cycle counter */ mov r2, #0 mcr p15, 0, r2, c9, c13, 0 run_code_speed_loop: sub r0, r0, #1 cmp r0, #0 bne run_code_speed_loop /* Read cycle counter */ mrc p15, 0, r0, c9, c13, 0 pop {pc} run_data_speed: .global run_data_speed push {r14} /* Reset cycle counter */ mov r2, #0 mcr p15, 0, r2, c9, c13, 0 run_data_speed_loop: sub r0, r0, #1 ldr r2, [r1] cmp r0, #0 bne run_data_speed_loop /* read cycle counter */ mrc p15, 0, r0, c9, c13, 0 pop {pc} #endif read_mpidr: .global read_mpidr mrc p15, 0, r0, c0, c0, 5 bx lr