xref: /haiku/src/system/kernel/arch/x86/64/thread.cpp (revision ded5af13dcf0b71231fee57a5d9502d388c1f758)
1 /*
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.
5  *
6  * Copyright 2001, Travis Geiselbrecht. All rights reserved.
7  * Distributed under the terms of the NewOS License.
8  */
9 
10 
11 #include <arch/thread.h>
12 
13 #include <string.h>
14 
15 #include <commpage.h>
16 #include <cpu.h>
17 #include <debug.h>
18 #include <kernel.h>
19 #include <ksignal.h>
20 #include <int.h>
21 #include <team.h>
22 #include <thread.h>
23 #include <tls.h>
24 #include <tracing.h>
25 #include <util/Random.h>
26 #include <vm/vm_types.h>
27 #include <vm/VMAddressSpace.h>
28 
29 #include "paging/X86PagingStructures.h"
30 #include "paging/X86VMTranslationMap.h"
31 
32 
33 //#define TRACE_ARCH_THREAD
34 #ifdef TRACE_ARCH_THREAD
35 #	define TRACE(x...) dprintf(x)
36 #else
37 #	define TRACE(x...) ;
38 #endif
39 
40 
41 #ifdef SYSCALL_TRACING
42 
43 namespace SyscallTracing {
44 
45 class RestartSyscall : public AbstractTraceEntry {
46 	public:
47 		RestartSyscall()
48 		{
49 			Initialized();
50 		}
51 
52 		virtual void AddDump(TraceOutput& out)
53 		{
54 			out.Print("syscall restart");
55 		}
56 };
57 
58 }
59 
60 #	define TSYSCALL(x)	new(std::nothrow) SyscallTracing::x
61 
62 #else
63 #	define TSYSCALL(x)
64 #endif	// SYSCALL_TRACING
65 
66 
67 extern "C" void x86_64_thread_entry();
68 
69 // Initial thread saved state.
70 static arch_thread sInitialState;
71 
72 
73 void
74 x86_restart_syscall(iframe* frame)
75 {
76 	Thread* thread = thread_get_current_thread();
77 
78 	atomic_and(&thread->flags, ~THREAD_FLAGS_RESTART_SYSCALL);
79 	atomic_or(&thread->flags, THREAD_FLAGS_SYSCALL_RESTARTED);
80 
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;
84 	frame->ip -= 2;
85 
86 	TSYSCALL(RestartSyscall());
87 }
88 
89 
90 void
91 x86_set_tls_context(Thread* thread)
92 {
93 	// Set FS segment base address to the TLS segment.
94 	x86_write_msr(IA32_MSR_FS_BASE, thread->user_local_storage);
95 }
96 
97 
98 static addr_t
99 arch_randomize_stack_pointer(addr_t value)
100 {
101 	STATIC_ASSERT(MAX_RANDOM_VALUE >= B_PAGE_SIZE - 1);
102 	value -= random_value() & (B_PAGE_SIZE - 1);
103 	return value & ~addr_t(0xf);
104 }
105 
106 
107 static uint8*
108 get_signal_stack(Thread* thread, iframe* frame, struct sigaction* action)
109 {
110 	// Use the alternate signal stack if we should and can.
111 	if (thread->signal_stack_enabled
112 			&& (action->sa_flags & SA_ONSTACK) != 0
113 			&& (frame->user_sp < thread->signal_stack_base
114 				|| frame->user_sp >= thread->signal_stack_base
115 					+ thread->signal_stack_size)) {
116 		addr_t stackTop = thread->signal_stack_base + thread->signal_stack_size;
117 		return (uint8*)arch_randomize_stack_pointer(stackTop);
118 	}
119 
120 	// We are going to use the stack that we are already on. We must not touch
121 	// the red zone (128 byte area below the stack pointer, reserved for use
122 	// by functions to store temporary data and guaranteed not to be modified
123 	// by signal handlers).
124 	return (uint8*)(frame->user_sp - 128);
125 }
126 
127 
128 //	#pragma mark -
129 
130 
131 status_t
132 arch_thread_init(kernel_args* args)
133 {
134 	// Save one global valid FPU state; it will be copied in the arch dependent
135 	// part of each new thread.
136 	asm volatile ("clts; fninit; fnclex;");
137 	x86_fxsave(sInitialState.fpu_state);
138 
139 	return B_OK;
140 }
141 
142 
143 status_t
144 arch_thread_init_thread_struct(Thread* thread)
145 {
146 	// Copy the initial saved FPU state to the new thread.
147 	memcpy(&thread->arch_info, &sInitialState, sizeof(arch_thread));
148 
149 	// Initialise the current thread pointer.
150 	thread->arch_info.thread = thread;
151 
152 	return B_OK;
153 }
154 
155 
156 /*!	Prepares the given thread's kernel stack for executing its entry function.
157 
158 	\param thread The thread.
159 	\param stack The usable bottom of the thread's kernel stack.
160 	\param stackTop The usable top of the thread's kernel stack.
161 	\param function The entry function the thread shall execute.
162 	\param data Pointer to be passed to the entry function.
163 */
164 void
165 arch_thread_init_kthread_stack(Thread* thread, void* _stack, void* _stackTop,
166 	void (*function)(void*), const void* data)
167 {
168 	uintptr_t* stackTop = static_cast<uintptr_t*>(_stackTop);
169 
170 	TRACE("arch_thread_init_kthread_stack: stack top %p, function %p, data: "
171 		"%p\n", _stackTop, function, data);
172 
173 	// Save the stack top for system call entry.
174 	thread->arch_info.syscall_rsp = (uint64*)thread->kernel_stack_top;
175 
176 	thread->arch_info.instruction_pointer
177 		= reinterpret_cast<uintptr_t>(x86_64_thread_entry);
178 
179 	*--stackTop = uintptr_t(data);
180 	*--stackTop = uintptr_t(function);
181 
182 	// Save the stack position.
183 	thread->arch_info.current_stack = stackTop;
184 }
185 
186 
187 void
188 arch_thread_dump_info(void* info)
189 {
190 	arch_thread* thread = (arch_thread*)info;
191 
192 	kprintf("\trsp: %p\n", thread->current_stack);
193 	kprintf("\tsyscall_rsp: %p\n", thread->syscall_rsp);
194 	kprintf("\tuser_rsp: %p\n", thread->user_rsp);
195 	kprintf("\tfpu_state at %p\n", thread->fpu_state);
196 }
197 
198 
199 /*!	Sets up initial thread context and enters user space
200 */
201 status_t
202 arch_thread_enter_userspace(Thread* thread, addr_t entry, void* args1,
203 	void* args2)
204 {
205 	addr_t stackTop = thread->user_stack_base + thread->user_stack_size;
206 
207 	TRACE("arch_thread_enter_userspace: entry %#lx, args %p %p, "
208 		"stackTop %#lx\n", entry, args1, args2, stackTop);
209 
210 	stackTop = arch_randomize_stack_pointer(stackTop);
211 
212 	// Copy the address of the stub that calls exit_thread() when the thread
213 	// entry function returns to the top of the stack to act as the return
214 	// address. The stub is inside commpage.
215 	addr_t commPageAddress = (addr_t)thread->team->commpage_address;
216 	addr_t codeAddr = ((addr_t*)commPageAddress)[COMMPAGE_ENTRY_X86_THREAD_EXIT]
217 		+ commPageAddress;
218 	stackTop -= sizeof(codeAddr);
219 	if (user_memcpy((void*)stackTop, (const void*)&codeAddr, sizeof(codeAddr))
220 			!= B_OK)
221 		return B_BAD_ADDRESS;
222 
223 	// Prepare the user iframe.
224 	iframe frame = {};
225 	frame.type = IFRAME_TYPE_SYSCALL;
226 	frame.si = (uint64)args2;
227 	frame.di = (uint64)args1;
228 	frame.ip = entry;
229 	frame.cs = USER_CODE_SELECTOR;
230 	frame.flags = X86_EFLAGS_RESERVED1 | X86_EFLAGS_INTERRUPT
231 		| (3 << X86_EFLAGS_IO_PRIVILEG_LEVEL_SHIFT);
232 	frame.sp = stackTop;
233 	frame.ss = USER_DATA_SELECTOR;
234 
235 	// Return to userland. Never returns.
236 	x86_initial_return_to_userland(thread, &frame);
237 
238 	return B_OK;
239 }
240 
241 
242 /*!	Sets up the user iframe for invoking a signal handler.
243 
244 	The function fills in the remaining fields of the given \a signalFrameData,
245 	copies it to the thread's userland stack (the one on which the signal shall
246 	be handled), and sets up the user iframe so that when returning to userland
247 	a wrapper function is executed that calls the user-defined signal handler.
248 	When the signal handler returns, the wrapper function shall call the
249 	"restore signal frame" syscall with the (possibly modified) signal frame
250 	data.
251 
252 	The following fields of the \a signalFrameData structure still need to be
253 	filled in:
254 	- \c context.uc_stack: The stack currently used by the thread.
255 	- \c context.uc_mcontext: The current userland state of the registers.
256 	- \c syscall_restart_return_value: Architecture specific use. On x86_64 the
257 		value of rax which is overwritten by the syscall return value.
258 
259 	Furthermore the function needs to set \c thread->user_signal_context to the
260 	userland pointer to the \c ucontext_t on the user stack.
261 
262 	\param thread The current thread.
263 	\param action The signal action specified for the signal to be handled.
264 	\param signalFrameData A partially initialized structure of all the data
265 		that need to be copied to userland.
266 	\return \c B_OK on success, another error code, if something goes wrong.
267 */
268 status_t
269 arch_setup_signal_frame(Thread* thread, struct sigaction* action,
270 	struct signal_frame_data* signalFrameData)
271 {
272 	iframe* frame = x86_get_current_iframe();
273 	if (!IFRAME_IS_USER(frame)) {
274 		panic("arch_setup_signal_frame(): No user iframe!");
275 		return B_BAD_VALUE;
276 	}
277 
278 	// Store the register state.
279 	signalFrameData->context.uc_mcontext.rax = frame->ax;
280 	signalFrameData->context.uc_mcontext.rbx = frame->bx;
281 	signalFrameData->context.uc_mcontext.rcx = frame->cx;
282 	signalFrameData->context.uc_mcontext.rdx = frame->dx;
283 	signalFrameData->context.uc_mcontext.rdi = frame->di;
284 	signalFrameData->context.uc_mcontext.rsi = frame->si;
285 	signalFrameData->context.uc_mcontext.rbp = frame->bp;
286 	signalFrameData->context.uc_mcontext.r8 = frame->r8;
287 	signalFrameData->context.uc_mcontext.r9 = frame->r9;
288 	signalFrameData->context.uc_mcontext.r10 = frame->r10;
289 	signalFrameData->context.uc_mcontext.r11 = frame->r11;
290 	signalFrameData->context.uc_mcontext.r12 = frame->r12;
291 	signalFrameData->context.uc_mcontext.r13 = frame->r13;
292 	signalFrameData->context.uc_mcontext.r14 = frame->r14;
293 	signalFrameData->context.uc_mcontext.r15 = frame->r15;
294 	signalFrameData->context.uc_mcontext.rsp = frame->user_sp;
295 	signalFrameData->context.uc_mcontext.rip = frame->ip;
296 	signalFrameData->context.uc_mcontext.rflags = frame->flags;
297 
298 	// Store the FPU state. There appears to be a bug in GCC where the aligned
299 	// attribute on a structure is being ignored when the structure is allocated
300 	// on the stack, so even if the fpu_state struct has aligned(16) it may not
301 	// get aligned correctly. Instead, use the current thread's FPU save area
302 	// and then memcpy() to the frame structure.
303 	x86_fxsave(thread->arch_info.fpu_state);
304 	memcpy((void*)&signalFrameData->context.uc_mcontext.fpu,
305 		thread->arch_info.fpu_state,
306 		sizeof(signalFrameData->context.uc_mcontext.fpu));
307 
308 	// Fill in signalFrameData->context.uc_stack.
309 	signal_get_user_stack(frame->user_sp, &signalFrameData->context.uc_stack);
310 
311 	// Store syscall_restart_return_value.
312 	signalFrameData->syscall_restart_return_value = frame->orig_rax;
313 
314 	// Get the stack to use and copy the frame data to it.
315 	uint8* userStack = get_signal_stack(thread, frame, action);
316 
317 	userStack -= sizeof(*signalFrameData);
318 	signal_frame_data* userSignalFrameData = (signal_frame_data*)userStack;
319 
320 	if (user_memcpy(userSignalFrameData, signalFrameData,
321 			sizeof(*signalFrameData)) != B_OK) {
322 		return B_BAD_ADDRESS;
323 	}
324 
325 	// Copy a return address to the stack so that backtraces will be correct.
326 	userStack -= sizeof(frame->ip);
327 	if (user_memcpy(userStack, &frame->ip, sizeof(frame->ip)) != B_OK)
328 		return B_BAD_ADDRESS;
329 
330 	// Update Thread::user_signal_context, now that everything seems to have
331 	// gone fine.
332 	thread->user_signal_context = &userSignalFrameData->context;
333 
334 	// Set up the iframe to execute the signal handler wrapper on our prepared
335 	// stack. First argument points to the frame data.
336 	addr_t* commPageAddress = (addr_t*)thread->team->commpage_address;
337 	frame->user_sp = (addr_t)userStack;
338 	frame->ip = commPageAddress[COMMPAGE_ENTRY_X86_SIGNAL_HANDLER]
339 		+ (addr_t)commPageAddress;
340 	frame->di = (addr_t)userSignalFrameData;
341 
342 	return B_OK;
343 }
344 
345 
346 int64
347 arch_restore_signal_frame(struct signal_frame_data* signalFrameData)
348 {
349 	iframe* frame = x86_get_current_iframe();
350 
351 	frame->orig_rax = signalFrameData->syscall_restart_return_value;
352 	frame->ax = signalFrameData->context.uc_mcontext.rax;
353 	frame->bx = signalFrameData->context.uc_mcontext.rbx;
354 	frame->cx = signalFrameData->context.uc_mcontext.rcx;
355 	frame->dx = signalFrameData->context.uc_mcontext.rdx;
356 	frame->di = signalFrameData->context.uc_mcontext.rdi;
357 	frame->si = signalFrameData->context.uc_mcontext.rsi;
358 	frame->bp = signalFrameData->context.uc_mcontext.rbp;
359 	frame->r8 = signalFrameData->context.uc_mcontext.r8;
360 	frame->r9 = signalFrameData->context.uc_mcontext.r9;
361 	frame->r10 = signalFrameData->context.uc_mcontext.r10;
362 	frame->r11 = signalFrameData->context.uc_mcontext.r11;
363 	frame->r12 = signalFrameData->context.uc_mcontext.r12;
364 	frame->r13 = signalFrameData->context.uc_mcontext.r13;
365 	frame->r14 = signalFrameData->context.uc_mcontext.r14;
366 	frame->r15 = signalFrameData->context.uc_mcontext.r15;
367 	frame->user_sp = signalFrameData->context.uc_mcontext.rsp;
368 	frame->ip = signalFrameData->context.uc_mcontext.rip;
369 	frame->flags = (frame->flags & ~(uint64)X86_EFLAGS_USER_FLAGS)
370 		| (signalFrameData->context.uc_mcontext.rflags & X86_EFLAGS_USER_FLAGS);
371 
372 	// Same as above, alignment may not be correct. Copy to thread and restore
373 	// from there.
374 	Thread* thread = thread_get_current_thread();
375 	memcpy(thread->arch_info.fpu_state,
376 		(void*)&signalFrameData->context.uc_mcontext.fpu,
377 		sizeof(thread->arch_info.fpu_state));
378 	x86_fxrstor(thread->arch_info.fpu_state);
379 
380 	// The syscall return code overwrites frame->ax with the return value of
381 	// the syscall, need to return it here to ensure the correct value is
382 	// restored.
383 	return frame->ax;
384 }
385