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
44namespace SyscallTracing {
45
46class 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
68extern "C" void x86_64_thread_entry();
69
70// Initial thread saved state.
71static arch_thread sInitialState;
72
73
74void
75x86_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
91void
92x86_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
99static addr_t
100arch_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
112static uint8*
113get_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
138status_t
139arch_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
153status_t
154arch_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*/
174void
175arch_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
197void
198arch_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*/
211status_t
212arch_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*/
280status_t
281arch_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
359int64
360arch_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