Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / native_client / src / trusted / service_runtime / arch / x86_32 / sel_rt_32.h
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 /*
8  * NaCl Secure Runtime
9  */
10
11 #ifndef __NATIVE_CLIENT_SERVICE_RUNTIME_ARCH_X86_32_SEL_RT_32_H__
12 #define __NATIVE_CLIENT_SERVICE_RUNTIME_ARCH_X86_32_SEL_RT_32_H__ 1
13
14 /* This file can be #included from assembly to get the #defines. */
15 #if !defined(__ASSEMBLER__)
16
17 #include <stddef.h>
18
19 #include "native_client/src/include/nacl_base.h"
20 #include "native_client/src/include/nacl_compiler_annotations.h"
21 #include "native_client/src/include/nacl_macros.h"
22 #include "native_client/src/include/portability.h"
23 #include "native_client/src/shared/platform/nacl_check.h"
24
25 EXTERN_C_BEGIN
26
27 uint16_t NaClGetGlobalCs(void);
28
29 uint16_t NaClGetGlobalDs(void);
30
31 uint16_t NaClGetCs(void);
32 /* setting CS is done using an lcall */
33
34 uint16_t NaClGetDs(void);
35
36 void    NaClSetDs(uint16_t v);
37
38 uint16_t NaClGetEs(void);
39
40 void    NaClSetEs(uint16_t v);
41
42 uint16_t NaClGetFs(void);
43
44 void    NaClSetFs(uint16_t v);
45
46 uint16_t NaClGetGs(void);
47
48 void    NaClSetGs(uint16_t v);
49
50 uint16_t NaClGetSs(void);
51
52 void    NaClSyscallSegSSE(void);
53 void    NaClSyscallSegNoSSE(void);
54 void    NaClSyscallSegRegsSavedSSE(void);
55 void    NaClSyscallSegRegsSavedNoSSE(void);
56
57 /*
58  * On a context switch through the syscall interface, not all
59  * registers are saved.  We assume that C calling convention is used,
60  * so %ecx and %edx are caller-saved and the NaCl service runtime does
61  * not have to bother saving them; %eax (or %edx:%eax pair) should
62  * have the return value, so its old value is also not saved.  (We
63  * should, however, ensure that there is not an accidental covert
64  * channel leaking information via these registers on syscall return.)
65  * The eflags register is also caller saved.
66  *
67  * We assume that the following is packed.  This is true for gcc and
68  * msvc for x86, but we will include a check that sizeof(struct
69  * NaClThreadContext) == 64 bytes. (32-bit and 64-bit mode)
70  */
71
72 typedef uint32_t  nacl_reg_t;  /* general purpose register type */
73
74 #define NACL_PRIdNACL_REG NACL_PRId32
75 #define NACL_PRIiNACL_REG NACL_PRIi32
76 #define NACL_PRIoNACL_REG NACL_PRIo32
77 #define NACL_PRIuNACL_REG NACL_PRIu32
78 #define NACL_PRIxNACL_REG NACL_PRIx32
79 #define NACL_PRIXNACL_REG NACL_PRIX32
80
81 /* The %gs segment points to this struct when running untrusted code. */
82 struct NaClGsSegment {
83   uint32_t tls_value1;  /* Used by user code */
84   uint32_t tls_value2;  /* Used by the integrated runtime (IRT) library */
85
86   /*
87    * These are register values to restore when returning to untrusted
88    * code using NaClSwitchRemainingRegs().
89    */
90   uint32_t new_prog_ctr;
91   uint32_t new_ecx;
92 };
93
94 /*
95  * The layout of NaClThreadContext must be kept in sync with the
96  * #defines below.
97  */
98 #if NACL_WINDOWS
99 /* Align gs_segment for better performance on Intel Atom */
100 __declspec(align(64))
101 #endif
102 struct NaClThreadContext {
103   /*
104    * We align gs_segment to a multiple of 64 bytes because otherwise
105    * memory accesses through the %gs segment are slow on Intel Atom
106    * CPUs.
107    *
108    * While GCC allows __attribute__((aligned(X))) on a field in a
109    * struct, MSVC does not, so we use a struct-level attribute (plus a
110    * padding field) on all platforms for consistency.  Note that we do
111    * not put __attribute__((aligned(X))) on struct NaClGsSegment
112    * because that would increase sizeof(struct NaClGsSegment) to 64.
113    *
114    * By putting this field first in the struct, we avoid the need
115    * for alignment padding before it.
116    */
117   struct NaClGsSegment gs_segment;
118
119   /*
120    * We need some padding somewhere to make the whole struct a multiple
121    * of its 64-byte alignment size.  Putting it here rather than at the
122    * end leaves space to extend struct NaClGsSegment without affecting
123    * all the other offsets.
124    *
125    * As well as requiring the tedious updating of NACL_THREAD_CONTEXT_OFFSET_*
126    * macros below, changing offsets when not also touching every .S file that
127    * uses those macros runs afoul of a Gyp bug wherein incremental builds fail
128    * to rebuild .S files whose included files have changed.
129    * See http://code.google.com/p/nativeclient/issues/detail?id=2969
130    */
131   uint8_t     future_padding[0x24];
132
133   /* ecx, edx, eax, eflags not saved */
134   nacl_reg_t  ebx;
135   nacl_reg_t  esi;
136   nacl_reg_t  edi;
137   nacl_reg_t  prog_ctr;  /* return addr */
138   nacl_reg_t  frame_ptr;
139   nacl_reg_t  stack_ptr;
140   uint16_t    ss; /* stack_ptr and ss must be adjacent */
141   uint16_t    fcw;
142   uint16_t    sys_fcw;
143   uint16_t    align_padding1;
144   uint32_t    mxcsr;
145   uint32_t    sys_mxcsr;
146   /*
147    * gs is our TLS base in the app; on the host side it's either fs or gs.
148    */
149   uint16_t    ds;
150   uint16_t    es;
151   uint16_t    fs;
152   uint16_t    gs;
153   /*
154    * spring_addr, sys_ret and new_prog_ctr are not a part of the
155    * thread's register set, but are needed by NaClSwitch.  By
156    * including them here, the two use the same interface.
157    */
158   nacl_reg_t  new_prog_ctr;
159   nacl_reg_t  sysret;
160   nacl_reg_t  spring_addr;
161   uint16_t    cs; /* spring_addr and cs must be adjacent */
162   uint16_t    align_padding2;
163
164   /* These two are adjacent because they are restored using 'lss'. */
165   uint32_t    trusted_stack_ptr;
166   uint16_t    trusted_ss;
167
168   uint16_t    trusted_es;
169   uint16_t    trusted_fs;
170   uint16_t    trusted_gs;
171 }
172 #if defined(__GNUC__)
173     /* Align gs_segment for better performance on Intel Atom */
174     __attribute__((aligned(64)))
175 #endif
176     ;
177
178 static INLINE uintptr_t NaClGetThreadCtxSp(struct NaClThreadContext *th_ctx) {
179   return th_ctx->stack_ptr;
180 }
181
182 #endif /* !defined(__ASSEMBLER__) */
183
184 #define NACL_THREAD_CONTEXT_OFFSET_GS_SEGMENT         0x00
185 #define NACL_THREAD_CONTEXT_OFFSET_FUTURE_PADDING     0x10
186 #define NACL_THREAD_CONTEXT_OFFSET_EBX                0x34
187 #define NACL_THREAD_CONTEXT_OFFSET_ESI                0x38
188 #define NACL_THREAD_CONTEXT_OFFSET_EDI                0x3c
189 #define NACL_THREAD_CONTEXT_OFFSET_PROG_CTR           0x40
190 #define NACL_THREAD_CONTEXT_OFFSET_FRAME_PTR          0x44
191 #define NACL_THREAD_CONTEXT_OFFSET_STACK_PTR          0x48
192 #define NACL_THREAD_CONTEXT_OFFSET_SS                 0x4c
193 #define NACL_THREAD_CONTEXT_OFFSET_FCW                0x4e
194 #define NACL_THREAD_CONTEXT_OFFSET_SYS_FCW            0x50
195 #define NACL_THREAD_CONTEXT_OFFSET_ALIGN_PADDING1     0x52
196 #define NACL_THREAD_CONTEXT_OFFSET_MXCSR              0x54
197 #define NACL_THREAD_CONTEXT_OFFSET_SYS_MXCSR          0x58
198 #define NACL_THREAD_CONTEXT_OFFSET_DS                 0x5c
199 #define NACL_THREAD_CONTEXT_OFFSET_ES                 0x5e
200 #define NACL_THREAD_CONTEXT_OFFSET_FS                 0x60
201 #define NACL_THREAD_CONTEXT_OFFSET_GS                 0x62
202 #define NACL_THREAD_CONTEXT_OFFSET_NEW_PROG_CTR       0x64
203 #define NACL_THREAD_CONTEXT_OFFSET_SYSRET             0x68
204 #define NACL_THREAD_CONTEXT_OFFSET_SPRING_ADDR        0x6c
205 #define NACL_THREAD_CONTEXT_OFFSET_CS                 0x70
206 #define NACL_THREAD_CONTEXT_OFFSET_ALIGN_PADDING2     0x72
207 #define NACL_THREAD_CONTEXT_OFFSET_TRUSTED_STACK_PTR  0x74
208 #define NACL_THREAD_CONTEXT_OFFSET_TRUSTED_SS         0x78
209 #define NACL_THREAD_CONTEXT_OFFSET_TRUSTED_ES         0x7a
210 #define NACL_THREAD_CONTEXT_OFFSET_TRUSTED_FS         0x7c
211 #define NACL_THREAD_CONTEXT_OFFSET_TRUSTED_GS         0x7e
212
213 #if !defined(__ASSEMBLER__)
214
215 static INLINE void NaClThreadContextOffsetCheck(void) {
216   /*
217    * We use 'offset' to check that every field of NaClThreadContext is
218    * verified below.  The fields must be listed below in order.
219    */
220   int offset = 0;
221
222 #define NACL_CHECK_FIELD(offset_name, field) \
223     NACL_COMPILE_TIME_ASSERT(offset_name == \
224                              offsetof(struct NaClThreadContext, field)); \
225     CHECK(offset == offset_name); \
226     offset += sizeof(((struct NaClThreadContext *) NULL)->field);
227
228   NACL_CHECK_FIELD(NACL_THREAD_CONTEXT_OFFSET_GS_SEGMENT, gs_segment);
229   NACL_CHECK_FIELD(NACL_THREAD_CONTEXT_OFFSET_FUTURE_PADDING, future_padding);
230   NACL_CHECK_FIELD(NACL_THREAD_CONTEXT_OFFSET_EBX, ebx);
231   NACL_CHECK_FIELD(NACL_THREAD_CONTEXT_OFFSET_ESI, esi);
232   NACL_CHECK_FIELD(NACL_THREAD_CONTEXT_OFFSET_EDI, edi);
233   NACL_CHECK_FIELD(NACL_THREAD_CONTEXT_OFFSET_PROG_CTR, prog_ctr);
234   NACL_CHECK_FIELD(NACL_THREAD_CONTEXT_OFFSET_FRAME_PTR, frame_ptr);
235   NACL_CHECK_FIELD(NACL_THREAD_CONTEXT_OFFSET_STACK_PTR, stack_ptr);
236   NACL_CHECK_FIELD(NACL_THREAD_CONTEXT_OFFSET_SS, ss);
237   NACL_CHECK_FIELD(NACL_THREAD_CONTEXT_OFFSET_FCW, fcw);
238   NACL_CHECK_FIELD(NACL_THREAD_CONTEXT_OFFSET_SYS_FCW, sys_fcw);
239   NACL_CHECK_FIELD(NACL_THREAD_CONTEXT_OFFSET_ALIGN_PADDING1, align_padding1);
240   NACL_CHECK_FIELD(NACL_THREAD_CONTEXT_OFFSET_MXCSR, mxcsr);
241   NACL_CHECK_FIELD(NACL_THREAD_CONTEXT_OFFSET_SYS_MXCSR, sys_mxcsr);
242   NACL_CHECK_FIELD(NACL_THREAD_CONTEXT_OFFSET_DS, ds);
243   NACL_CHECK_FIELD(NACL_THREAD_CONTEXT_OFFSET_ES, es);
244   NACL_CHECK_FIELD(NACL_THREAD_CONTEXT_OFFSET_FS, fs);
245   NACL_CHECK_FIELD(NACL_THREAD_CONTEXT_OFFSET_GS, gs);
246   NACL_CHECK_FIELD(NACL_THREAD_CONTEXT_OFFSET_NEW_PROG_CTR, new_prog_ctr);
247   NACL_CHECK_FIELD(NACL_THREAD_CONTEXT_OFFSET_SYSRET, sysret);
248   NACL_CHECK_FIELD(NACL_THREAD_CONTEXT_OFFSET_SPRING_ADDR, spring_addr);
249   NACL_CHECK_FIELD(NACL_THREAD_CONTEXT_OFFSET_CS, cs);
250   NACL_CHECK_FIELD(NACL_THREAD_CONTEXT_OFFSET_ALIGN_PADDING2, align_padding2);
251   NACL_CHECK_FIELD(NACL_THREAD_CONTEXT_OFFSET_TRUSTED_STACK_PTR,
252                    trusted_stack_ptr);
253   NACL_CHECK_FIELD(NACL_THREAD_CONTEXT_OFFSET_TRUSTED_SS, trusted_ss);
254   NACL_CHECK_FIELD(NACL_THREAD_CONTEXT_OFFSET_TRUSTED_ES, trusted_es);
255   NACL_CHECK_FIELD(NACL_THREAD_CONTEXT_OFFSET_TRUSTED_FS, trusted_fs);
256   NACL_CHECK_FIELD(NACL_THREAD_CONTEXT_OFFSET_TRUSTED_GS, trusted_gs);
257   CHECK(offset == sizeof(struct NaClThreadContext));
258
259 #undef NACL_CHECK_FIELD
260 }
261
262 EXTERN_C_END
263
264 #endif
265
266 #if defined(__ASSEMBLER__)
267 /*
268  * The MacOS assembler has a macro facility that is pretty close
269  * to GNU as macros, but not quite the same.
270  */
271 #if NACL_OSX || defined(__clang__)
272 # define MACRO(name)    .macro name
273 # define ENDMACRO       .endmacro
274 # define MACROENTRY     DEFINE_GLOBAL_HIDDEN_LOCATION($0):
275 # define MACROARG1      $0
276 # define MACROARG2      $1
277 # define MACROARG3      $2
278 # define MACROARG4      $3
279 # define MACROIMMED(x)  $$##x
280 #else
281 # define MACRO(name)    .macro name arg1, arg2=0, arg3=, arg4=
282 # define ENDMACRO       .endm
283 # define MACROENTRY     DEFINE_GLOBAL_HIDDEN_LOCATION(\arg1):
284 # define MACROARG1      \arg1
285 # define MACROARG2      \arg2
286 # define MACROARG3      \arg3
287 # define MACROARG4      \arg4
288 # define MACROIMMED(x)  $##x
289 #endif
290
291 #endif
292
293 #endif /* __NATIVE_CLIENT_SERVICE_RUNTIME_ARCH_X86_32_SEL_RT_32_H__ */