2 * Copyright 2012, Alex Smith, alex@alex-smith.me.uk.
3 * Copyright 2002-2008, Axel Dörfler, axeld@pinc-software.de.
4 * Distributed under the terms of the MIT License.
6 * Copyright 2001, Travis Geiselbrecht. All rights reserved.
7 * Distributed under the terms of the NewOS License.
11 #include <arch/thread.h>
25 #include <util/Random.h>
26 #include <vm/vm_types.h>
27 #include <vm/VMAddressSpace.h>
29 #include "paging/X86PagingStructures.h"
30 #include "paging/X86VMTranslationMap.h"
33 //#define TRACE_ARCH_THREAD
34 #ifdef TRACE_ARCH_THREAD
35 # define TRACE(x...) dprintf(x)
37 # define TRACE(x...) ;
41 #ifdef SYSCALL_TRACING
43 namespace SyscallTracing
{
45 class RestartSyscall
: public AbstractTraceEntry
{
52 virtual void AddDump(TraceOutput
& out
)
54 out
.Print("syscall restart");
60 # define TSYSCALL(x) new(std::nothrow) SyscallTracing::x
64 #endif // SYSCALL_TRACING
67 extern "C" void x86_64_thread_entry();
69 // Initial thread saved state.
70 static arch_thread sInitialState
;
74 x86_restart_syscall(iframe
* frame
)
76 Thread
* thread
= thread_get_current_thread();
78 atomic_and(&thread
->flags
, ~THREAD_FLAGS_RESTART_SYSCALL
);
79 atomic_or(&thread
->flags
, THREAD_FLAGS_SYSCALL_RESTARTED
);
81 // Get back the original system call number and modify the frame to
82 // re-execute the syscall instruction.
83 frame
->ax
= frame
->orig_rax
;
86 TSYSCALL(RestartSyscall());
91 x86_set_tls_context(Thread
* thread
)
93 // Set FS segment base address to the TLS segment.
94 x86_write_msr(IA32_MSR_FS_BASE
, thread
->user_local_storage
);
99 arch_randomize_stack_pointer(addr_t value
)
101 static_assert(MAX_RANDOM_VALUE
>= B_PAGE_SIZE
- 1,
102 "randomization range is too big");
103 value
-= random_value() & (B_PAGE_SIZE
- 1);
104 return value
& ~addr_t(0xf);
109 get_signal_stack(Thread
* thread
, iframe
* frame
, struct sigaction
* action
)
111 // Use the alternate signal stack if we should and can.
112 if (thread
->signal_stack_enabled
113 && (action
->sa_flags
& SA_ONSTACK
) != 0
114 && (frame
->user_sp
< thread
->signal_stack_base
115 || frame
->user_sp
>= thread
->signal_stack_base
116 + thread
->signal_stack_size
)) {
117 addr_t stackTop
= thread
->signal_stack_base
+ thread
->signal_stack_size
;
118 return (uint8
*)arch_randomize_stack_pointer(stackTop
);
121 // We are going to use the stack that we are already on. We must not touch
122 // the red zone (128 byte area below the stack pointer, reserved for use
123 // by functions to store temporary data and guaranteed not to be modified
124 // by signal handlers).
125 return (uint8
*)(frame
->user_sp
- 128);
133 arch_thread_init(kernel_args
* args
)
135 // Save one global valid FPU state; it will be copied in the arch dependent
136 // part of each new thread.
142 : "=m" (sInitialState
.fpu_state
));
148 arch_thread_init_thread_struct(Thread
* thread
)
150 // Copy the initial saved FPU state to the new thread.
151 memcpy(&thread
->arch_info
, &sInitialState
, sizeof(arch_thread
));
153 // Initialise the current thread pointer.
154 thread
->arch_info
.thread
= thread
;
160 /*! Prepares the given thread's kernel stack for executing its entry function.
162 \param thread The thread.
163 \param stack The usable bottom of the thread's kernel stack.
164 \param stackTop The usable top of the thread's kernel stack.
165 \param function The entry function the thread shall execute.
166 \param data Pointer to be passed to the entry function.
169 arch_thread_init_kthread_stack(Thread
* thread
, void* _stack
, void* _stackTop
,
170 void (*function
)(void*), const void* data
)
172 uintptr_t* stackTop
= static_cast<uintptr_t*>(_stackTop
);
174 TRACE("arch_thread_init_kthread_stack: stack top %p, function %p, data: "
175 "%p\n", _stackTop
, function
, data
);
177 // Save the stack top for system call entry.
178 thread
->arch_info
.syscall_rsp
= (uint64
*)thread
->kernel_stack_top
;
180 thread
->arch_info
.instruction_pointer
181 = reinterpret_cast<uintptr_t>(x86_64_thread_entry
);
183 *--stackTop
= uintptr_t(data
);
184 *--stackTop
= uintptr_t(function
);
186 // Save the stack position.
187 thread
->arch_info
.current_stack
= stackTop
;
192 arch_thread_dump_info(void* info
)
194 arch_thread
* thread
= (arch_thread
*)info
;
196 kprintf("\trsp: %p\n", thread
->current_stack
);
197 kprintf("\tsyscall_rsp: %p\n", thread
->syscall_rsp
);
198 kprintf("\tuser_rsp: %p\n", thread
->user_rsp
);
199 kprintf("\tfpu_state at %p\n", thread
->fpu_state
);
203 /*! Sets up initial thread context and enters user space
206 arch_thread_enter_userspace(Thread
* thread
, addr_t entry
, void* args1
,
209 addr_t stackTop
= thread
->user_stack_base
+ thread
->user_stack_size
;
211 TRACE("arch_thread_enter_userspace: entry %#lx, args %p %p, "
212 "stackTop %#lx\n", entry
, args1
, args2
, stackTop
);
214 stackTop
= arch_randomize_stack_pointer(stackTop
);
216 // Copy the address of the stub that calls exit_thread() when the thread
217 // entry function returns to the top of the stack to act as the return
218 // address. The stub is inside commpage.
219 addr_t commPageAddress
= (addr_t
)thread
->team
->commpage_address
;
220 addr_t codeAddr
= ((addr_t
*)commPageAddress
)[COMMPAGE_ENTRY_X86_THREAD_EXIT
]
222 stackTop
-= sizeof(codeAddr
);
223 if (user_memcpy((void*)stackTop
, (const void*)&codeAddr
, sizeof(codeAddr
))
225 return B_BAD_ADDRESS
;
227 // Prepare the user iframe.
229 frame
.type
= IFRAME_TYPE_SYSCALL
;
230 frame
.si
= (uint64
)args2
;
231 frame
.di
= (uint64
)args1
;
233 frame
.cs
= USER_CODE_SELECTOR
;
234 frame
.flags
= X86_EFLAGS_RESERVED1
| X86_EFLAGS_INTERRUPT
235 | (3 << X86_EFLAGS_IO_PRIVILEG_LEVEL_SHIFT
);
237 frame
.ss
= USER_DATA_SELECTOR
;
239 // Return to userland. Never returns.
240 x86_initial_return_to_userland(thread
, &frame
);
246 /*! Sets up the user iframe for invoking a signal handler.
248 The function fills in the remaining fields of the given \a signalFrameData,
249 copies it to the thread's userland stack (the one on which the signal shall
250 be handled), and sets up the user iframe so that when returning to userland
251 a wrapper function is executed that calls the user-defined signal handler.
252 When the signal handler returns, the wrapper function shall call the
253 "restore signal frame" syscall with the (possibly modified) signal frame
256 The following fields of the \a signalFrameData structure still need to be
258 - \c context.uc_stack: The stack currently used by the thread.
259 - \c context.uc_mcontext: The current userland state of the registers.
260 - \c syscall_restart_return_value: Architecture specific use. On x86_64 the
261 value of rax which is overwritten by the syscall return value.
263 Furthermore the function needs to set \c thread->user_signal_context to the
264 userland pointer to the \c ucontext_t on the user stack.
266 \param thread The current thread.
267 \param action The signal action specified for the signal to be handled.
268 \param signalFrameData A partially initialized structure of all the data
269 that need to be copied to userland.
270 \return \c B_OK on success, another error code, if something goes wrong.
273 arch_setup_signal_frame(Thread
* thread
, struct sigaction
* action
,
274 struct signal_frame_data
* signalFrameData
)
276 iframe
* frame
= x86_get_current_iframe();
277 if (!IFRAME_IS_USER(frame
)) {
278 panic("arch_setup_signal_frame(): No user iframe!");
282 // Store the register state.
283 signalFrameData
->context
.uc_mcontext
.rax
= frame
->ax
;
284 signalFrameData
->context
.uc_mcontext
.rbx
= frame
->bx
;
285 signalFrameData
->context
.uc_mcontext
.rcx
= frame
->cx
;
286 signalFrameData
->context
.uc_mcontext
.rdx
= frame
->dx
;
287 signalFrameData
->context
.uc_mcontext
.rdi
= frame
->di
;
288 signalFrameData
->context
.uc_mcontext
.rsi
= frame
->si
;
289 signalFrameData
->context
.uc_mcontext
.rbp
= frame
->bp
;
290 signalFrameData
->context
.uc_mcontext
.r8
= frame
->r8
;
291 signalFrameData
->context
.uc_mcontext
.r9
= frame
->r9
;
292 signalFrameData
->context
.uc_mcontext
.r10
= frame
->r10
;
293 signalFrameData
->context
.uc_mcontext
.r11
= frame
->r11
;
294 signalFrameData
->context
.uc_mcontext
.r12
= frame
->r12
;
295 signalFrameData
->context
.uc_mcontext
.r13
= frame
->r13
;
296 signalFrameData
->context
.uc_mcontext
.r14
= frame
->r14
;
297 signalFrameData
->context
.uc_mcontext
.r15
= frame
->r15
;
298 signalFrameData
->context
.uc_mcontext
.rsp
= frame
->user_sp
;
299 signalFrameData
->context
.uc_mcontext
.rip
= frame
->ip
;
300 signalFrameData
->context
.uc_mcontext
.rflags
= frame
->flags
;
302 if (frame
->fpu
!= nullptr) {
303 memcpy((void*)&signalFrameData
->context
.uc_mcontext
.fpu
, frame
->fpu
,
304 sizeof(signalFrameData
->context
.uc_mcontext
.fpu
));
306 memcpy((void*)&signalFrameData
->context
.uc_mcontext
.fpu
,
307 sInitialState
.fpu_state
,
308 sizeof(signalFrameData
->context
.uc_mcontext
.fpu
));
311 // Fill in signalFrameData->context.uc_stack.
312 signal_get_user_stack(frame
->user_sp
, &signalFrameData
->context
.uc_stack
);
314 // Store syscall_restart_return_value.
315 signalFrameData
->syscall_restart_return_value
= frame
->orig_rax
;
317 // Get the stack to use and copy the frame data to it.
318 uint8
* userStack
= get_signal_stack(thread
, frame
, action
);
320 userStack
-= sizeof(*signalFrameData
);
321 signal_frame_data
* userSignalFrameData
= (signal_frame_data
*)userStack
;
323 if (user_memcpy(userSignalFrameData
, signalFrameData
,
324 sizeof(*signalFrameData
)) != B_OK
) {
325 return B_BAD_ADDRESS
;
328 // Copy a return address to the stack so that backtraces will be correct.
329 userStack
-= sizeof(frame
->ip
);
330 if (user_memcpy(userStack
, &frame
->ip
, sizeof(frame
->ip
)) != B_OK
)
331 return B_BAD_ADDRESS
;
333 // Update Thread::user_signal_context, now that everything seems to have
335 thread
->user_signal_context
= &userSignalFrameData
->context
;
337 // Set up the iframe to execute the signal handler wrapper on our prepared
338 // stack. First argument points to the frame data.
339 addr_t
* commPageAddress
= (addr_t
*)thread
->team
->commpage_address
;
340 frame
->user_sp
= (addr_t
)userStack
;
341 frame
->ip
= commPageAddress
[COMMPAGE_ENTRY_X86_SIGNAL_HANDLER
]
342 + (addr_t
)commPageAddress
;
343 frame
->di
= (addr_t
)userSignalFrameData
;
350 arch_restore_signal_frame(struct signal_frame_data
* signalFrameData
)
352 iframe
* frame
= x86_get_current_iframe();
354 frame
->orig_rax
= signalFrameData
->syscall_restart_return_value
;
355 frame
->ax
= signalFrameData
->context
.uc_mcontext
.rax
;
356 frame
->bx
= signalFrameData
->context
.uc_mcontext
.rbx
;
357 frame
->cx
= signalFrameData
->context
.uc_mcontext
.rcx
;
358 frame
->dx
= signalFrameData
->context
.uc_mcontext
.rdx
;
359 frame
->di
= signalFrameData
->context
.uc_mcontext
.rdi
;
360 frame
->si
= signalFrameData
->context
.uc_mcontext
.rsi
;
361 frame
->bp
= signalFrameData
->context
.uc_mcontext
.rbp
;
362 frame
->r8
= signalFrameData
->context
.uc_mcontext
.r8
;
363 frame
->r9
= signalFrameData
->context
.uc_mcontext
.r9
;
364 frame
->r10
= signalFrameData
->context
.uc_mcontext
.r10
;
365 frame
->r11
= signalFrameData
->context
.uc_mcontext
.r11
;
366 frame
->r12
= signalFrameData
->context
.uc_mcontext
.r12
;
367 frame
->r13
= signalFrameData
->context
.uc_mcontext
.r13
;
368 frame
->r14
= signalFrameData
->context
.uc_mcontext
.r14
;
369 frame
->r15
= signalFrameData
->context
.uc_mcontext
.r15
;
370 frame
->user_sp
= signalFrameData
->context
.uc_mcontext
.rsp
;
371 frame
->ip
= signalFrameData
->context
.uc_mcontext
.rip
;
372 frame
->flags
= (frame
->flags
& ~(uint64
)X86_EFLAGS_USER_FLAGS
)
373 | (signalFrameData
->context
.uc_mcontext
.rflags
& X86_EFLAGS_USER_FLAGS
);
375 Thread
* thread
= thread_get_current_thread();
377 memcpy(thread
->arch_info
.fpu_state
,
378 (void*)&signalFrameData
->context
.uc_mcontext
.fpu
,
379 sizeof(thread
->arch_info
.fpu_state
));
380 frame
->fpu
= &thread
->arch_info
.fpu_state
;
382 // The syscall return code overwrites frame->ax with the return value of
383 // the syscall, need to return it here to ensure the correct value is