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.
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
14 /* This file can be #included from assembly to get the #defines. */
15 #if !defined(__ASSEMBLER__)
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"
27 uint16_t NaClGetGlobalCs(void);
29 uint16_t NaClGetGlobalDs(void);
31 uint16_t NaClGetCs(void);
32 /* setting CS is done using an lcall */
34 uint16_t NaClGetDs(void);
36 void NaClSetDs(uint16_t v);
38 uint16_t NaClGetEs(void);
40 void NaClSetEs(uint16_t v);
42 uint16_t NaClGetFs(void);
44 void NaClSetFs(uint16_t v);
46 uint16_t NaClGetGs(void);
48 void NaClSetGs(uint16_t v);
50 uint16_t NaClGetSs(void);
52 void NaClSyscallSegSSE(void);
53 void NaClSyscallSegNoSSE(void);
54 void NaClSyscallSegRegsSavedSSE(void);
55 void NaClSyscallSegRegsSavedNoSSE(void);
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.
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)
72 typedef uint32_t nacl_reg_t; /* general purpose register type */
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
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 */
87 * These are register values to restore when returning to untrusted
88 * code using NaClSwitchRemainingRegs().
90 uint32_t new_prog_ctr;
95 * The layout of NaClThreadContext must be kept in sync with the
99 /* Align gs_segment for better performance on Intel Atom */
100 __declspec(align(64))
102 struct NaClThreadContext {
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
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.
114 * By putting this field first in the struct, we avoid the need
115 * for alignment padding before it.
117 struct NaClGsSegment gs_segment;
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.
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
131 uint8_t future_padding[0x24];
133 /* ecx, edx, eax, eflags not saved */
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 */
143 uint16_t align_padding1;
147 * gs is our TLS base in the app; on the host side it's either fs or gs.
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.
158 nacl_reg_t new_prog_ctr;
160 nacl_reg_t spring_addr;
161 uint16_t cs; /* spring_addr and cs must be adjacent */
162 uint16_t align_padding2;
164 /* These two are adjacent because they are restored using 'lss'. */
165 uint32_t trusted_stack_ptr;
172 #if defined(__GNUC__)
173 /* Align gs_segment for better performance on Intel Atom */
174 __attribute__((aligned(64)))
178 static INLINE uintptr_t NaClGetThreadCtxSp(struct NaClThreadContext *th_ctx) {
179 return th_ctx->stack_ptr;
182 #endif /* !defined(__ASSEMBLER__) */
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
213 #if !defined(__ASSEMBLER__)
215 static INLINE void NaClThreadContextOffsetCheck(void) {
217 * We use 'offset' to check that every field of NaClThreadContext is
218 * verified below. The fields must be listed below in order.
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);
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,
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));
259 #undef NACL_CHECK_FIELD
266 #if defined(__ASSEMBLER__)
268 * The MacOS assembler has a macro facility that is pretty close
269 * to GNU as macros, but not quite the same.
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
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
293 #endif /* __NATIVE_CLIENT_SERVICE_RUNTIME_ARCH_X86_32_SEL_RT_32_H__ */