1/*
2 * Copyright 2012, Alex Smith, alex@alex-smith.me.uk.
3 * Distributed under the terms of the MIT License.
4 */
5
6
7#include "x86_signals.h"
8
9#include <string.h>
10
11#include <KernelExport.h>
12
13#include <commpage.h>
14#include <cpu.h>
15#include <elf.h>
16#include <smp.h>
17
18#include "syscall_numbers.h"
19
20
21extern "C" void __attribute__((noreturn))
22x86_64_user_signal_handler(signal_frame_data* data)
23{
24	if (data->siginfo_handler) {
25		auto handler = (void (*)(int, siginfo_t*, void*, void*))data->handler;
26		handler(data->info.si_signo, &data->info, &data->context, data->user_data);
27	} else {
28		auto handler = (void (*)(int, void*, vregs*))data->handler;
29		handler(data->info.si_signo, data->user_data, &data->context.uc_mcontext);
30	}
31
32	#define TO_STRING_LITERAL_HELPER(number)	#number
33	#define TO_STRING_LITERAL(number)	TO_STRING_LITERAL_HELPER(number)
34
35	// _kern_restore_signal_frame(data)
36	asm volatile(
37		"movq %0, %%rdi;"
38		"movq $" TO_STRING_LITERAL(SYSCALL_RESTORE_SIGNAL_FRAME) ", %%rax;"
39		"syscall;"
40		:: "r"(data)
41	);
42
43	#undef TO_STRING_LITERAL_HELPER
44	#undef TO_STRING_LITERAL
45
46	__builtin_unreachable();
47}
48
49
50static void
51register_commpage_function(const char* functionName, int32 commpageIndex,
52	const char* commpageSymbolName, addr_t expectedAddress)
53{
54	// get address and size of function
55	elf_symbol_info symbolInfo;
56	if (elf_lookup_kernel_symbol(functionName, &symbolInfo)	!= B_OK) {
57		panic("register_commpage_function(): Failed to find "
58			"signal frame function \"%s\"!", functionName);
59	}
60
61	ASSERT(expectedAddress == symbolInfo.address);
62
63	// fill in the commpage table entry
64	addr_t position = fill_commpage_entry(commpageIndex,
65		(void*)symbolInfo.address, symbolInfo.size);
66
67	// add symbol to the commpage image
68	image_id image = get_commpage_image();
69	elf_add_memory_image_symbol(image, commpageSymbolName, position,
70		symbolInfo.size, B_SYMBOL_TYPE_TEXT);
71}
72
73
74void
75x86_initialize_commpage_signal_handler()
76{
77	register_commpage_function("x86_64_user_signal_handler",
78		COMMPAGE_ENTRY_X86_SIGNAL_HANDLER, "commpage_signal_handler",
79		(addr_t)&x86_64_user_signal_handler);
80}
81