kernel: do not use assembly code for commpage signal handler
Unify with x86 and riscv64 implementation. Change-Id: I2f44575768628eb3a2d4eaaa86f020de582ecd0b Reviewed-on: https://review.haiku-os.org/c/haiku/+/5203 Tested-by: Commit checker robot <no-reply+buildbot@haiku-os.org> Reviewed-by: Jérôme Duval <jerome.duval@gmail.com> Reviewed-by: Fredrik Holmqvist <fredrik.holmqvist@gmail.com>
This commit is contained in:
parent
6886114066
commit
24eb3d5aba
@ -15,25 +15,66 @@
|
||||
#include <elf.h>
|
||||
#include <smp.h>
|
||||
|
||||
#include "syscall_numbers.h"
|
||||
|
||||
extern "C" void x86_64_user_signal_handler(void);
|
||||
extern int x86_64_user_signal_handler_end;
|
||||
|
||||
extern "C" void __attribute__((noreturn))
|
||||
x86_64_user_signal_handler(signal_frame_data* data)
|
||||
{
|
||||
if (data->siginfo_handler) {
|
||||
auto handler = (void (*)(int, siginfo_t*, void*, void*))data->handler;
|
||||
handler(data->info.si_signo, &data->info, &data->context, data->user_data);
|
||||
} else {
|
||||
auto handler = (void (*)(int, void*, vregs*))data->handler;
|
||||
handler(data->info.si_signo, data->user_data, &data->context.uc_mcontext);
|
||||
}
|
||||
|
||||
#define TO_STRING_LITERAL_HELPER(number) #number
|
||||
#define TO_STRING_LITERAL(number) TO_STRING_LITERAL_HELPER(number)
|
||||
|
||||
// _kern_restore_signal_frame(data)
|
||||
asm volatile(
|
||||
"movq %0, %%rdi;"
|
||||
"movq $" TO_STRING_LITERAL(SYSCALL_RESTORE_SIGNAL_FRAME) ", %%rax;"
|
||||
"syscall;"
|
||||
:: "r"(data)
|
||||
);
|
||||
|
||||
#undef TO_STRING_LITERAL_HELPER
|
||||
#undef TO_STRING_LITERAL
|
||||
|
||||
__builtin_unreachable();
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
register_commpage_function(const char* functionName, int32 commpageIndex,
|
||||
const char* commpageSymbolName, addr_t expectedAddress)
|
||||
{
|
||||
// get address and size of function
|
||||
elf_symbol_info symbolInfo;
|
||||
if (elf_lookup_kernel_symbol(functionName, &symbolInfo) != B_OK) {
|
||||
panic("register_commpage_function(): Failed to find "
|
||||
"signal frame function \"%s\"!", functionName);
|
||||
}
|
||||
|
||||
ASSERT(expectedAddress == symbolInfo.address);
|
||||
|
||||
// fill in the commpage table entry
|
||||
addr_t position = fill_commpage_entry(commpageIndex,
|
||||
(void*)symbolInfo.address, symbolInfo.size);
|
||||
|
||||
// add symbol to the commpage image
|
||||
image_id image = get_commpage_image();
|
||||
elf_add_memory_image_symbol(image, commpageSymbolName, position,
|
||||
symbolInfo.size, B_SYMBOL_TYPE_TEXT);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
x86_initialize_commpage_signal_handler()
|
||||
{
|
||||
void* handlerCode = (void*)&x86_64_user_signal_handler;
|
||||
void* handlerCodeEnd = &x86_64_user_signal_handler_end;
|
||||
|
||||
// Copy the signal handler code to the commpage.
|
||||
size_t len = (size_t)((addr_t)handlerCodeEnd - (addr_t)handlerCode);
|
||||
addr_t position = fill_commpage_entry(COMMPAGE_ENTRY_X86_SIGNAL_HANDLER,
|
||||
handlerCode, len);
|
||||
|
||||
// Add symbol to the commpage image.
|
||||
image_id image = get_commpage_image();
|
||||
elf_add_memory_image_symbol(image, "commpage_signal_handler", position,
|
||||
len, B_SYMBOL_TYPE_TEXT);
|
||||
register_commpage_function("x86_64_user_signal_handler",
|
||||
COMMPAGE_ENTRY_X86_SIGNAL_HANDLER, "commpage_signal_handler",
|
||||
(addr_t)&x86_64_user_signal_handler);
|
||||
}
|
||||
|
||||
|
@ -1,56 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012, Alex Smith, alex@alex-smith.me.uk.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include <asm_defs.h>
|
||||
|
||||
#include "asm_offsets.h"
|
||||
#include "syscall_numbers.h"
|
||||
|
||||
|
||||
.text
|
||||
|
||||
|
||||
// Userspace signal handler wrapper, copied to the commpage.
|
||||
FUNCTION(x86_64_user_signal_handler):
|
||||
push %rbp
|
||||
movq %rsp, %rbp
|
||||
|
||||
// RDI points to the signal_frame_data structure, however we'll overwrite
|
||||
// that with the function arguments, so move it somewhere else. We can use
|
||||
// callee-save registers here without preserving them because the old value
|
||||
// will be restored when the frame is restored.
|
||||
movq %rdi, %r12
|
||||
|
||||
// Check the handler type.
|
||||
cmpb $0, SIGNAL_FRAME_DATA_siginfo_handler(%r12)
|
||||
jne .Lsiginfo_handler
|
||||
|
||||
.Lsimple_handler:
|
||||
// Fetch other arguments (user data, vregs).
|
||||
movq SIGNAL_FRAME_DATA_user_data(%r12), %rsi
|
||||
leaq SIGNAL_FRAME_DATA_context + UCONTEXT_T_uc_mcontext(%r12), %rdx
|
||||
|
||||
.Lcall_handler:
|
||||
// Get the handler address and the signal number first argument.
|
||||
movq SIGNAL_FRAME_DATA_handler(%r12), %rax
|
||||
movl SIGNAL_FRAME_DATA_info + SIGINFO_T_si_signo(%r12), %edi
|
||||
|
||||
// Call the handler.
|
||||
callq *%rax
|
||||
|
||||
// Perform the restore_signal_frame() syscall, should not return.
|
||||
movq $SYSCALL_RESTORE_SIGNAL_FRAME, %rax
|
||||
movq %r12, %rdi
|
||||
syscall
|
||||
|
||||
.Lsiginfo_handler:
|
||||
// Fetch other arguments (info pointer, context, user data).
|
||||
leaq SIGNAL_FRAME_DATA_info(%r12), %rsi
|
||||
leaq SIGNAL_FRAME_DATA_context(%r12), %rdx
|
||||
movq SIGNAL_FRAME_DATA_user_data(%r12), %rcx
|
||||
jmp .Lcall_handler
|
||||
FUNCTION_END(x86_64_user_signal_handler)
|
||||
SYMBOL(x86_64_user_signal_handler_end):
|
@ -28,7 +28,6 @@ if $(TARGET_ARCH) = x86_64 {
|
||||
errata.cpp
|
||||
interrupts.S
|
||||
signals.cpp
|
||||
signals_asm.S
|
||||
syscalls.cpp
|
||||
thread.cpp
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user