xref: /haiku/src/system/kernel/arch/x86/64/thread.cpp (revision 5ac9b506412b11afb993bb52d161efe7666958a5)
1 /*
2  * Copyright 2018, Jérôme Duval, jerome.duval@gmail.com.
3  * Copyright 2012, Alex Smith, alex@alex-smith.me.uk.
4  * Copyright 2002-2008, Axel Dörfler, axeld@pinc-software.de.
5  * Distributed under the terms of the MIT License.
6  *
7  * Copyright 2001, Travis Geiselbrecht. All rights reserved.
8  * Distributed under the terms of the NewOS License.
9  */
10 
11 
12 #include <arch/thread.h>
13 
14 #include <string.h>
15 
16 #include <commpage.h>
17 #include <cpu.h>
18 #include <debug.h>
19 #include <kernel.h>
20 #include <ksignal.h>
21 #include <int.h>
22 #include <team.h>
23 #include <thread.h>
24 #include <tls.h>
25 #include <tracing.h>
26 #include <util/Random.h>
27 #include <vm/vm_types.h>
28 #include <vm/VMAddressSpace.h>
29 
30 #include "paging/X86PagingStructures.h"
31 #include "paging/X86VMTranslationMap.h"
32 
33 
34 //#define TRACE_ARCH_THREAD
35 #ifdef TRACE_ARCH_THREAD
36 #	define TRACE(x...) dprintf(x)
37 #else
38 #	define TRACE(x...) ;
39 #endif
40 
41 
42 #ifdef SYSCALL_TRACING
43 
44 namespace SyscallTracing {
45 
46 class RestartSyscall : public AbstractTraceEntry {
47 	public:
48 		RestartSyscall()
49 		{
50 			Initialized();
51 		}
52 
53 		virtual void AddDump(TraceOutput& out)
54 		{
55 			out.Print("syscall restart");
56 		}
57 };
58 
59 }
60 
61 #	define TSYSCALL(x)	new(std::nothrow) SyscallTracing::x
62 
63 #else
64 #	define TSYSCALL(x)
65 #endif	// SYSCALL_TRACING
66 
67 
68 extern "C" void x86_64_thread_entry();
69 
70 // Initial thread saved state.
71 static arch_thread sInitialState;
72 
73 
74 void
75 x86_restart_syscall(iframe* frame)
76 {
77 	Thread* thread = thread_get_current_thread();
78 
79 	atomic_and(&thread->flags, ~THREAD_FLAGS_RESTART_SYSCALL);
80 	atomic_or(&thread->flags, THREAD_FLAGS_SYSCALL_RESTARTED);
81 
82 	// Get back the original system call number and modify the frame to
83 	// re-execute the syscall instruction.
84 	frame->ax = frame->orig_rax;
85 	frame->ip -= 2;
86 
87 	TSYSCALL(RestartSyscall());
88 }
89 
90 
91 void
92 x86_set_tls_context(Thread* thread)
93 {
94 	// Set FS segment base address to the TLS segment.
95 	x86_write_msr(IA32_MSR_FS_BASE, thread->user_local_storage);
96 }
97 
98 
99 static addr_t
100 arch_randomize_stack_pointer(addr_t value)
101 {
102 	static_assert(MAX_RANDOM_VALUE >= B_PAGE_SIZE - 1,
103 		"randomization range is too big");
104 	value -= random_value() & (B_PAGE_SIZE - 1);
105 	return (value & ~addr_t(0xf)) - 8;
106 		// This means, result % 16 == 8, which is what rsp should adhere to
107 		// when a function is entered for the stack to be considered aligned to
108 		// 16 byte.
109 }
110 
111 
112 static uint8*
113 get_signal_stack(Thread* thread, iframe* frame, struct sigaction* action,
114 	size_t spaceNeeded)
115 {
116 	// Use the alternate signal stack if we should and can.
117 	if (thread->signal_stack_enabled
118 			&& (action->sa_flags & SA_ONSTACK) != 0
119 			&& (frame->user_sp < thread->signal_stack_base
120 				|| frame->user_sp >= thread->signal_stack_base
121 					+ thread->signal_stack_size)) {
122 		addr_t stackTop = thread->signal_stack_base + thread->signal_stack_size;
123 		return (uint8*)arch_randomize_stack_pointer(stackTop - spaceNeeded);
124 	}
125 
126 	// We are going to use the stack that we are already on. We must not touch
127 	// the red zone (128 byte area below the stack pointer, reserved for use
128 	// by functions to store temporary data and guaranteed not to be modified
129 	// by signal handlers).
130 	return (uint8*)((frame->user_sp - 128 - spaceNeeded) & ~addr_t(0xf)) - 8;
131 		// align stack pointer (cf. arch_randomize_stack_pointer())
132 }
133 
134 
135 //	#pragma mark -
136 
137 
138 status_t
139 arch_thread_init(kernel_args* args)
140 {
141 	// Save one global valid FPU state; it will be copied in the arch dependent
142 	// part of each new thread.
143 	asm volatile (
144 		"clts;"		\
145 		"fninit;"	\
146 		"fnclex;"	\
147 		"fxsave %0;"
148 		: "=m" (sInitialState.fpu_state));
149 	return B_OK;
150 }
151 
152 
153 status_t
154 arch_thread_init_thread_struct(Thread* thread)
155 {
156 	// Copy the initial saved FPU state to the new thread.
157 	memcpy(&thread->arch_info, &sInitialState, sizeof(arch_thread));
158 
159 	// Initialise the current thread pointer.
160 	thread->arch_info.thread = thread;
161 
162 	return B_OK;
163 }
164 
165 
166 /*!	Prepares the given thread's kernel stack for executing its entry function.
167 
168 	\param thread The thread.
169 	\param stack The usable bottom of the thread's kernel stack.
170 	\param stackTop The usable top of the thread's kernel stack.
171 	\param function The entry function the thread shall execute.
172 	\param data Pointer to be passed to the entry function.
173 */
174 void
175 arch_thread_init_kthread_stack(Thread* thread, void* _stack, void* _stackTop,
176 	void (*function)(void*), const void* data)
177 {
178 	uintptr_t* stackTop = static_cast<uintptr_t*>(_stackTop);
179 
180 	TRACE("arch_thread_init_kthread_stack: stack top %p, function %p, data: "
181 		"%p\n", _stackTop, function, data);
182 
183 	// Save the stack top for system call entry.
184 	thread->arch_info.syscall_rsp = (uint64*)thread->kernel_stack_top;
185 
186 	thread->arch_info.instruction_pointer
187 		= reinterpret_cast<uintptr_t>(x86_64_thread_entry);
188 
189 	*--stackTop = uintptr_t(data);
190 	*--stackTop = uintptr_t(function);
191 
192 	// Save the stack position.
193 	thread->arch_info.current_stack = stackTop;
194 }
195 
196 
197 void
198 arch_thread_dump_info(void* info)
199 {
200 	arch_thread* thread = (arch_thread*)info;
201 
202 	kprintf("\trsp: %p\n", thread->current_stack);
203 	kprintf("\tsyscall_rsp: %p\n", thread->syscall_rsp);
204 	kprintf("\tuser_rsp: %p\n", thread->user_rsp);
205 	kprintf("\tfpu_state at %p\n", thread->fpu_state);
206 }
207 
208 
209 /*!	Sets up initial thread context and enters user space
210 */
211 status_t
212 arch_thread_enter_userspace(Thread* thread, addr_t entry, void* args1,
213 	void* args2)
214 {
215 	addr_t stackTop = thread->user_stack_base + thread->user_stack_size;
216 	addr_t codeAddr;
217 
218 	TRACE("arch_thread_enter_userspace: entry %#lx, args %p %p, "
219 		"stackTop %#lx\n", entry, args1, args2, stackTop);
220 
221 	stackTop = arch_randomize_stack_pointer(stackTop - sizeof(codeAddr));
222 
223 	// Copy the address of the stub that calls exit_thread() when the thread
224 	// entry function returns to the top of the stack to act as the return
225 	// address. The stub is inside commpage.
226 	addr_t commPageAddress = (addr_t)thread->team->commpage_address;
227 	set_ac();
228 	codeAddr = ((addr_t*)commPageAddress)[COMMPAGE_ENTRY_X86_THREAD_EXIT]
229 		+ commPageAddress;
230 	clear_ac();
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_SELECTOR;
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_SELECTOR;
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 	if (frame->fpu != nullptr) {
311 		memcpy((void*)&signalFrameData->context.uc_mcontext.fpu, frame->fpu,
312 			sizeof(signalFrameData->context.uc_mcontext.fpu));
313 	} else {
314 		memcpy((void*)&signalFrameData->context.uc_mcontext.fpu,
315 			sInitialState.fpu_state,
316 			sizeof(signalFrameData->context.uc_mcontext.fpu));
317 	}
318 
319 	// Fill in signalFrameData->context.uc_stack.
320 	signal_get_user_stack(frame->user_sp, &signalFrameData->context.uc_stack);
321 
322 	// Store syscall_restart_return_value.
323 	signalFrameData->syscall_restart_return_value = frame->orig_rax;
324 
325 	// Get the stack to use and copy the frame data to it.
326 	uint8* userStack = get_signal_stack(thread, frame, action,
327 		sizeof(*signalFrameData) + sizeof(frame->ip));
328 
329 	signal_frame_data* userSignalFrameData
330 		= (signal_frame_data*)(userStack + sizeof(frame->ip));
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 	if (user_memcpy(userStack, &frame->ip, sizeof(frame->ip)) != B_OK)
339 		return B_BAD_ADDRESS;
340 
341 	// Update Thread::user_signal_context, now that everything seems to have
342 	// gone fine.
343 	thread->user_signal_context = &userSignalFrameData->context;
344 
345 	// Set up the iframe to execute the signal handler wrapper on our prepared
346 	// stack. First argument points to the frame data.
347 	addr_t* commPageAddress = (addr_t*)thread->team->commpage_address;
348 	frame->user_sp = (addr_t)userStack;
349 	set_ac();
350 	frame->ip = commPageAddress[COMMPAGE_ENTRY_X86_SIGNAL_HANDLER]
351 		+ (addr_t)commPageAddress;
352 	clear_ac();
353 	frame->di = (addr_t)userSignalFrameData;
354 
355 	return B_OK;
356 }
357 
358 
359 int64
360 arch_restore_signal_frame(struct signal_frame_data* signalFrameData)
361 {
362 	iframe* frame = x86_get_current_iframe();
363 
364 	frame->orig_rax = signalFrameData->syscall_restart_return_value;
365 	frame->ax = signalFrameData->context.uc_mcontext.rax;
366 	frame->bx = signalFrameData->context.uc_mcontext.rbx;
367 	frame->cx = signalFrameData->context.uc_mcontext.rcx;
368 	frame->dx = signalFrameData->context.uc_mcontext.rdx;
369 	frame->di = signalFrameData->context.uc_mcontext.rdi;
370 	frame->si = signalFrameData->context.uc_mcontext.rsi;
371 	frame->bp = signalFrameData->context.uc_mcontext.rbp;
372 	frame->r8 = signalFrameData->context.uc_mcontext.r8;
373 	frame->r9 = signalFrameData->context.uc_mcontext.r9;
374 	frame->r10 = signalFrameData->context.uc_mcontext.r10;
375 	frame->r11 = signalFrameData->context.uc_mcontext.r11;
376 	frame->r12 = signalFrameData->context.uc_mcontext.r12;
377 	frame->r13 = signalFrameData->context.uc_mcontext.r13;
378 	frame->r14 = signalFrameData->context.uc_mcontext.r14;
379 	frame->r15 = signalFrameData->context.uc_mcontext.r15;
380 	frame->user_sp = signalFrameData->context.uc_mcontext.rsp;
381 	frame->ip = signalFrameData->context.uc_mcontext.rip;
382 	frame->flags = (frame->flags & ~(uint64)X86_EFLAGS_USER_FLAGS)
383 		| (signalFrameData->context.uc_mcontext.rflags & X86_EFLAGS_USER_FLAGS);
384 
385 	Thread* thread = thread_get_current_thread();
386 
387 	memcpy(thread->arch_info.fpu_state,
388 		(void*)&signalFrameData->context.uc_mcontext.fpu,
389 		sizeof(thread->arch_info.fpu_state));
390 	frame->fpu = &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