xref: /haiku/src/system/kernel/arch/riscv64/arch_commpage.cpp (revision 13581b3d2a71545960b98fefebc5225b5bf29072)
1 /*
2  * Copyright 2007, Travis Geiselbrecht. All rights reserved.
3  * Distributed under the terms of the MIT License.
4  */
5 
6 #include <commpage.h>
7 
8 #include <string.h>
9 
10 #include <KernelExport.h>
11 
12 #include <cpu.h>
13 #include <elf.h>
14 #include <smp.h>
15 
16 #include "syscall_numbers.h"
17 
18 
19 extern "C" void arch_user_thread_exit();
20 
21 
22 extern "C" void __attribute__((noreturn))
23 arch_user_signal_handler(signal_frame_data* data)
24 {
25 	if (data->siginfo_handler) {
26 		auto handler = (void (*)(int, siginfo_t*, void*, void*))data->handler;
27 		handler(data->info.si_signo, &data->info, &data->context, data->user_data);
28 	} else {
29 		auto handler = (void (*)(int, void*, vregs*))data->handler;
30 		handler(data->info.si_signo, data->user_data, &data->context.uc_mcontext);
31 	}
32 
33 	#define TO_STRING_LITERAL_HELPER(number)	#number
34 	#define TO_STRING_LITERAL(number)	TO_STRING_LITERAL_HELPER(number)
35 
36 	// _kern_restore_signal_frame(data)
37 	asm volatile(
38 		"mv a0, %0;"
39 		"li t0, " TO_STRING_LITERAL(SYSCALL_RESTORE_SIGNAL_FRAME) ";"
40 		"ecall;"
41 		:: "r"(data)
42 	);
43 
44 	#undef TO_STRING_LITERAL_HELPER
45 	#undef TO_STRING_LITERAL
46 
47 	__builtin_unreachable();
48 }
49 
50 
51 static void
52 register_commpage_function(const char* functionName, int32 commpageIndex,
53 	const char* commpageSymbolName, addr_t expectedAddress)
54 {
55 	// get address and size of function
56 	elf_symbol_info symbolInfo;
57 	if (elf_lookup_kernel_symbol(functionName, &symbolInfo)	!= B_OK) {
58 		panic("register_commpage_function(): Failed to find "
59 			"signal frame function \"%s\"!", functionName);
60 	}
61 
62 	ASSERT(expectedAddress == symbolInfo.address);
63 
64 	// fill in the commpage table entry
65 	addr_t position = fill_commpage_entry(commpageIndex,
66 		(void*)symbolInfo.address, symbolInfo.size);
67 
68 	// add symbol to the commpage image
69 	image_id image = get_commpage_image();
70 	elf_add_memory_image_symbol(image, commpageSymbolName, position,
71 		symbolInfo.size, B_SYMBOL_TYPE_TEXT);
72 }
73 
74 
75 status_t
76 arch_commpage_init(void)
77 {
78 	return B_OK;
79 }
80 
81 
82 status_t
83 arch_commpage_init_post_cpus(void)
84 {
85 	register_commpage_function("arch_user_signal_handler",
86 		COMMPAGE_ENTRY_RISCV64_SIGNAL_HANDLER, "commpage_signal_handler",
87 		(addr_t)&arch_user_signal_handler);
88 
89 	register_commpage_function("arch_user_thread_exit",
90 		COMMPAGE_ENTRY_RISCV64_THREAD_EXIT, "commpage_thread_exit",
91 		(addr_t)&arch_user_thread_exit);
92 
93 	return B_OK;
94 }
95