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