1/*
2 * Copyright 2022-2023, Haiku Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
4 *
5 * Copyright 2009, Johannes Wischert, johanneswi@gmail.com.
6 * Distributed under the terms of the MIT License.
7 */
8
9
10#include <commpage.h>
11
12#include <string.h>
13
14#include <KernelExport.h>
15
16#include <cpu.h>
17#include <elf.h>
18#include <smp.h>
19
20#include "syscall_numbers.h"
21
22
23extern "C" void arch_user_thread_exit();
24
25
26extern "C" void __attribute__((noreturn))
27arch_user_signal_handler(signal_frame_data* data)
28{
29	if (data->siginfo_handler) {
30		auto handler = (void (*)(int, siginfo_t*, void*, void*))data->handler;
31		handler(data->info.si_signo, &data->info, &data->context, data->user_data);
32	} else {
33		auto handler = (void (*)(int, void*, vregs*))data->handler;
34		handler(data->info.si_signo, data->user_data, &data->context.uc_mcontext);
35	}
36
37	// _kern_restore_signal_frame(data)
38	asm volatile(
39		"mov r0, %[data];"
40		"svc %[syscall_num]"
41		:: [data] "r"(data), [syscall_num] "i" (SYSCALL_RESTORE_SIGNAL_FRAME)
42	);
43
44	__builtin_unreachable();
45}
46
47
48static void
49register_commpage_function(const char* functionName, int32 commpageIndex,
50	const char* commpageSymbolName, addr_t expectedAddress)
51{
52	// get address and size of function
53	elf_symbol_info symbolInfo;
54	if (elf_lookup_kernel_symbol(functionName, &symbolInfo) != B_OK) {
55		panic("register_commpage_function(): Failed to find "
56			"function \"%s\"!", functionName);
57	}
58
59	ASSERT(expectedAddress == symbolInfo.address);
60
61	// fill in the commpage table entry
62	addr_t position = fill_commpage_entry(commpageIndex,
63		(void*)symbolInfo.address, symbolInfo.size);
64
65	// add symbol to the commpage image
66	image_id image = get_commpage_image();
67	elf_add_memory_image_symbol(image, commpageSymbolName, position,
68		symbolInfo.size, B_SYMBOL_TYPE_TEXT);
69}
70
71
72status_t
73arch_commpage_init(void)
74{
75	return B_OK;
76}
77
78
79status_t
80arch_commpage_init_post_cpus(void)
81{
82	register_commpage_function("arch_user_signal_handler",
83		COMMPAGE_ENTRY_ARM_SIGNAL_HANDLER, "commpage_signal_handler",
84		(addr_t)&arch_user_signal_handler);
85
86	register_commpage_function("arch_user_thread_exit",
87		COMMPAGE_ENTRY_ARM_THREAD_EXIT, "commpage_thread_exit",
88		(addr_t)&arch_user_thread_exit);
89
90	return B_OK;
91}
92