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