xref: /haiku/src/system/kernel/arch/x86/64/signals.cpp (revision 6f80a9801fedbe7355c4360bd204ba746ec3ec2d)
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 
21 extern "C" void __attribute__((noreturn))
22 x86_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 
50 static void
51 register_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 
74 void
75 x86_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