aboutsummaryrefslogtreecommitdiffstats
path: root/security/smc/bridge_pub2sec.S
diff options
context:
space:
mode:
Diffstat (limited to 'security/smc/bridge_pub2sec.S')
-rw-r--r--security/smc/bridge_pub2sec.S242
1 files changed, 242 insertions, 0 deletions
diff --git a/security/smc/bridge_pub2sec.S b/security/smc/bridge_pub2sec.S
new file mode 100644
index 0000000..15cd3b7
--- /dev/null
+++ b/security/smc/bridge_pub2sec.S
@@ -0,0 +1,242 @@
+/**
+ * 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