xref: /haiku/src/system/kernel/arch/x86/64/thread.cpp (revision 04a0e9c7b68cbe3a43d38e2bca8e860fd80936fb)
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 	addr_t* stackTop = (addr_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 	// x86_64 uses registers for argument passing, first argument in RDI,
177 	// however we don't save RDI on every context switch (there is no need
178 	// for us to: it is not callee-save, and only contains the first argument
179 	// to x86_context_switch). However, this presents a problem since we
180 	// cannot store the argument for the entry function here. Therefore, we
181 	// save the function address in R14 and the argument in R15 (which are
182 	// restored), and then set up the stack to initially call a wrapper
183 	// function which passes the argument correctly.
184 
185 	*--stackTop = 0;							// Dummy return address.
186 	*--stackTop = (addr_t)x86_64_thread_entry;	// Wrapper function.
187 	*--stackTop = (addr_t)data;					// R15: argument.
188 	*--stackTop = (addr_t)function;				// R14: entry function.
189 	*--stackTop = 0;							// R13.
190 	*--stackTop = 0;							// R12.
191 	*--stackTop = 0;							// RBP.
192 	*--stackTop = 0;							// RBX.
193 
194 	// Save the stack position.
195 	thread->arch_info.current_stack = stackTop;
196 }
197 
198 
199 void
200 arch_thread_dump_info(void* info)
201 {
202 	arch_thread* thread = (arch_thread*)info;
203 
204 	kprintf("\trsp: %p\n", thread->current_stack);
205 	kprintf("\tsyscall_rsp: %p\n", thread->syscall_rsp);
206 	kprintf("\tuser_rsp: %p\n", thread->user_rsp);
207 	kprintf("\tfpu_state at %p\n", thread->fpu_state);
208 }
209 
210 
211 /*!	Sets up initial thread context and enters user space
212 */
213 status_t
214 arch_thread_enter_userspace(Thread* thread, addr_t entry, void* args1,
215 	void* args2)
216 {
217 	addr_t stackTop = thread->user_stack_base + thread->user_stack_size;
218 
219 	TRACE("arch_thread_enter_userspace: entry %#lx, args %p %p, "
220 		"stackTop %#lx\n", entry, args1, args2, stackTop);
221 
222 	stackTop = arch_randomize_stack_pointer(stackTop);
223 
224 	// Copy the address of the stub that calls exit_thread() when the thread
225 	// entry function returns to the top of the stack to act as the return
226 	// address. The stub is inside commpage.
227 	addr_t commPageAddress = (addr_t)thread->team->commpage_address;
228 	addr_t codeAddr = ((addr_t*)commPageAddress)[COMMPAGE_ENTRY_X86_THREAD_EXIT]
229 		+ commPageAddress;
230 	stackTop -= sizeof(codeAddr);
231 	if (user_memcpy((void*)stackTop, (const void*)&codeAddr, sizeof(codeAddr))
232 			!= B_OK)
233 		return B_BAD_ADDRESS;
234 
235 	// Prepare the user iframe.
236 	iframe frame = {};
237 	frame.type = IFRAME_TYPE_SYSCALL;
238 	frame.si = (uint64)args2;
239 	frame.di = (uint64)args1;
240 	frame.ip = entry;
241 	frame.cs = USER_CODE_SEG;
242 	frame.flags = X86_EFLAGS_RESERVED1 | X86_EFLAGS_INTERRUPT
243 		| (3 << X86_EFLAGS_IO_PRIVILEG_LEVEL_SHIFT);
244 	frame.sp = stackTop;
245 	frame.ss = USER_DATA_SEG;
246 
247 	// Return to userland. Never returns.
248 	x86_initial_return_to_userland(thread, &frame);
249 
250 	return B_OK;
251 }
252 
253 
254 /*!	Sets up the user iframe for invoking a signal handler.
255 
256 	The function fills in the remaining fields of the given \a signalFrameData,
257 	copies it to the thread's userland stack (the one on which the signal shall
258 	be handled), and sets up the user iframe so that when returning to userland
259 	a wrapper function is executed that calls the user-defined signal handler.
260 	When the signal handler returns, the wrapper function shall call the
261 	"restore signal frame" syscall with the (possibly modified) signal frame
262 	data.
263 
264 	The following fields of the \a signalFrameData structure still need to be
265 	filled in:
266 	- \c context.uc_stack: The stack currently used by the thread.
267 	- \c context.uc_mcontext: The current userland state of the registers.
268 	- \c syscall_restart_return_value: Architecture specific use. On x86_64 the
269 		value of rax which is overwritten by the syscall return value.
270 
271 	Furthermore the function needs to set \c thread->user_signal_context to the
272 	userland pointer to the \c ucontext_t on the user stack.
273 
274 	\param thread The current thread.
275 	\param action The signal action specified for the signal to be handled.
276 	\param signalFrameData A partially initialized structure of all the data
277 		that need to be copied to userland.
278 	\return \c B_OK on success, another error code, if something goes wrong.
279 */
280 status_t
281 arch_setup_signal_frame(Thread* thread, struct sigaction* action,
282 	struct signal_frame_data* signalFrameData)
283 {
284 	iframe* frame = x86_get_current_iframe();
285 	if (!IFRAME_IS_USER(frame)) {
286 		panic("arch_setup_signal_frame(): No user iframe!");
287 		return B_BAD_VALUE;
288 	}
289 
290 	// Store the register state.
291 	signalFrameData->context.uc_mcontext.rax = frame->ax;
292 	signalFrameData->context.uc_mcontext.rbx = frame->bx;
293 	signalFrameData->context.uc_mcontext.rcx = frame->cx;
294 	signalFrameData->context.uc_mcontext.rdx = frame->dx;
295 	signalFrameData->context.uc_mcontext.rdi = frame->di;
296 	signalFrameData->context.uc_mcontext.rsi = frame->si;
297 	signalFrameData->context.uc_mcontext.rbp = frame->bp;
298 	signalFrameData->context.uc_mcontext.r8 = frame->r8;
299 	signalFrameData->context.uc_mcontext.r9 = frame->r9;
300 	signalFrameData->context.uc_mcontext.r10 = frame->r10;
301 	signalFrameData->context.uc_mcontext.r11 = frame->r11;
302 	signalFrameData->context.uc_mcontext.r12 = frame->r12;
303 	signalFrameData->context.uc_mcontext.r13 = frame->r13;
304 	signalFrameData->context.uc_mcontext.r14 = frame->r14;
305 	signalFrameData->context.uc_mcontext.r15 = frame->r15;
306 	signalFrameData->context.uc_mcontext.rsp = frame->user_sp;
307 	signalFrameData->context.uc_mcontext.rip = frame->ip;
308 	signalFrameData->context.uc_mcontext.rflags = frame->flags;
309 
310 	// Store the FPU state. There appears to be a bug in GCC where the aligned
311 	// attribute on a structure is being ignored when the structure is allocated
312 	// on the stack, so even if the fpu_state struct has aligned(16) it may not
313 	// get aligned correctly. Instead, use the current thread's FPU save area
314 	// and then memcpy() to the frame structure.
315 	x86_fxsave(thread->arch_info.fpu_state);
316 	memcpy((void*)&signalFrameData->context.uc_mcontext.fpu,
317 		thread->arch_info.fpu_state,
318 		sizeof(signalFrameData->context.uc_mcontext.fpu));
319 
320 	// Fill in signalFrameData->context.uc_stack.
321 	signal_get_user_stack(frame->user_sp, &signalFrameData->context.uc_stack);
322 
323 	// Store syscall_restart_return_value.
324 	signalFrameData->syscall_restart_return_value = frame->orig_rax;
325 
326 	// Get the stack to use and copy the frame data to it.
327 	uint8* userStack = get_signal_stack(thread, frame, action);
328 
329 	userStack -= sizeof(*signalFrameData);
330 	signal_frame_data* userSignalFrameData = (signal_frame_data*)userStack;
331 
332 	if (user_memcpy(userSignalFrameData, signalFrameData,
333 			sizeof(*signalFrameData)) != B_OK) {
334 		return B_BAD_ADDRESS;
335 	}
336 
337 	// Copy a return address to the stack so that backtraces will be correct.
338 	userStack -= sizeof(frame->ip);
339 	if (user_memcpy(userStack, &frame->ip, sizeof(frame->ip)) != B_OK)
340 		return B_BAD_ADDRESS;
341 
342 	// Update Thread::user_signal_context, now that everything seems to have
343 	// gone fine.
344 	thread->user_signal_context = &userSignalFrameData->context;
345 
346 	// Set up the iframe to execute the signal handler wrapper on our prepared
347 	// stack. First argument points to the frame data.
348 	addr_t* commPageAddress = (addr_t*)thread->team->commpage_address;
349 	frame->user_sp = (addr_t)userStack;
350 	frame->ip = commPageAddress[COMMPAGE_ENTRY_X86_SIGNAL_HANDLER]
351 		+ (addr_t)commPageAddress;
352 	frame->di = (addr_t)userSignalFrameData;
353 
354 	return B_OK;
355 }
356 
357 
358 int64
359 arch_restore_signal_frame(struct signal_frame_data* signalFrameData)
360 {
361 	iframe* frame = x86_get_current_iframe();
362 
363 	frame->orig_rax = signalFrameData->syscall_restart_return_value;
364 	frame->ax = signalFrameData->context.uc_mcontext.rax;
365 	frame->bx = signalFrameData->context.uc_mcontext.rbx;
366 	frame->cx = signalFrameData->context.uc_mcontext.rcx;
367 	frame->dx = signalFrameData->context.uc_mcontext.rdx;
368 	frame->di = signalFrameData->context.uc_mcontext.rdi;
369 	frame->si = signalFrameData->context.uc_mcontext.rsi;
370 	frame->bp = signalFrameData->context.uc_mcontext.rbp;
371 	frame->r8 = signalFrameData->context.uc_mcontext.r8;
372 	frame->r9 = signalFrameData->context.uc_mcontext.r9;
373 	frame->r10 = signalFrameData->context.uc_mcontext.r10;
374 	frame->r11 = signalFrameData->context.uc_mcontext.r11;
375 	frame->r12 = signalFrameData->context.uc_mcontext.r12;
376 	frame->r13 = signalFrameData->context.uc_mcontext.r13;
377 	frame->r14 = signalFrameData->context.uc_mcontext.r14;
378 	frame->r15 = signalFrameData->context.uc_mcontext.r15;
379 	frame->user_sp = signalFrameData->context.uc_mcontext.rsp;
380 	frame->ip = signalFrameData->context.uc_mcontext.rip;
381 	frame->flags = (frame->flags & ~(uint64)X86_EFLAGS_USER_FLAGS)
382 		| (signalFrameData->context.uc_mcontext.rflags & X86_EFLAGS_USER_FLAGS);
383 
384 	// Same as above, alignment may not be correct. Copy to thread and restore
385 	// from there.
386 	Thread* thread = thread_get_current_thread();
387 	memcpy(thread->arch_info.fpu_state,
388 		(void*)&signalFrameData->context.uc_mcontext.fpu,
389 		sizeof(thread->arch_info.fpu_state));
390 	x86_fxrstor(thread->arch_info.fpu_state);
391 
392 	// The syscall return code overwrites frame->ax with the return value of
393 	// the syscall, need to return it here to ensure the correct value is
394 	// restored.
395 	return frame->ax;
396 }
397