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
19extern "C" void arch_user_thread_exit();
20
21
22extern "C" void __attribute__((noreturn))
23arch_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
51static void
52register_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
75status_t
76arch_commpage_init(void)
77{
78	return B_OK;
79}
80
81
82status_t
83arch_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