Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / native_client / src / trusted / service_runtime / arch / arm / nacl_switch.S
1 /*
2  * Copyright (c) 2012 The Native Client Authors. All rights reserved.
3  * Use of this source code is governed by a BSD-style license that can be
4  * found in the LICENSE file.
5  */
6
7 #include "native_client/src/trusted/service_runtime/nacl_config.h"
8 #include "native_client/src/trusted/service_runtime/arch/arm/sel_rt.h"
9
10 .text
11 .fpu neon
12
13 /*
14  * This trusted code is linked into the service_runtime and
15  * executed when switching from the service runtime to a nacl
16  * module. This happens when a main nacl thread is created and starting to
17  * execute the nacle code, or when nacl module is returning from a system
18  * call. This piece of code lives in a service runtime part of address space.
19  * the one and only argument is in register r0
20  *
21  * r0 -- address of thread context (struct NaClThreadContext)
22  */
23
24 /*
25  * Here we are starting a new untrusted thread.  The callee-saved VFP/NEON
26  * registers have ambient values from trusted code, which must not leak
27  * into untrusted code.  So clear them.
28  */
29 DEFINE_GLOBAL_HIDDEN_FUNCTION(NaClStartSwitch):
30   veor q4, q4, q4
31   veor q5, q5, q5
32   veor q6, q6, q6
33   veor q7, q7, q7
34
35 /*
36  * Execution falls through to here.  This is also the entry point for
37  * returning from a syscall, which does not need to repeat the work of
38  * clearing the callee-saved registers because the C frames for the call
39  * to NaClSyscallCSegHook and its callees will save and restore their
40  * incoming (i.e. the untrusted) values of those registers.
41  */
42 DEFINE_GLOBAL_HIDDEN_FUNCTION(NaClSwitch):
43
44 /*
45  * Load the untrusted code's value of the fpscr into a scratch register.
46  */
47   ldr ip, [r0, #NACL_THREAD_CONTEXT_OFFSET_FPSCR]
48
49 /*
50  * We clear registers r2, r3, lr, flag and status fields in
51  * CPSR (status register) to avoid information leaks.  The remaining
52  * registers are overwritten by the code that follows after.
53  */
54
55   mov r2, #0
56   mov r3, #0
57   mov lr, #0
58   msr cpsr_fs, #0
59
60 /*
61  * Clear out the VFP/NEON state that otherwise might leak information.
62  * Registers d8-d15 (aka q4-q7) are callee-saves, so the untrusted state
63  * of those will have been saved and restored by whatever trusted code
64  * paths might have touched them.  The other VFP/NEON registers are
65  * call-clobbered, so trusted code might have left interesting bits
66  * there and we must hide that information.
67  */
68   veor q0, q0, q0
69   veor q1, q1, q1
70   veor q2, q2, q2
71   veor q3, q3, q3
72   veor q8, q8, q8
73   veor q9, q9, q9
74   veor q10, q10, q10
75   veor q11, q11, q11
76   veor q12, q12, q12
77   veor q13, q13, q13
78   veor q14, q14, q14
79   veor q15, q15, q15
80
81 /*
82  * Restore the untrusted code's fpscr state.
83  */
84   fmxr fpscr, ip
85
86 /*
87  * TODO(mcgrathr): Perhaps drop callee-saved registers (r4-r8,r10-r11)
88  * from this restore and instead just clear them in NaClStartSwitch.
89  */
90   ldmia r0!, NACL_CALLEE_SAVE_LIST
91   add r0, #4  /* skip prog_ctr in struct NaClThreadContext */
92   /* Read sysret and new_prog_ctr from struct NaClThreadContext */
93   ldmia r0, {r0, r1}
94   /* Transfer control to untrusted code */
95   bx r1