kernel/arm: implement syscall handler
Change-Id: I75f2fb7808f55a460835276ca66cce8a26e8403d Reviewed-on: https://review.haiku-os.org/c/haiku/+/4980 Tested-by: Commit checker robot <[email protected]> Reviewed-by: X512 <[email protected]> Reviewed-by: Fredrik Holmqvist <[email protected]>
This commit is contained in:
committed by
Fredrik Holmqvist
parent
a40b421ac7
commit
1b895c8371
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2012, Haiku Inc. All rights reserved.
|
* Copyright 2012-2022, Haiku Inc. All rights reserved.
|
||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
*
|
*
|
||||||
* Authors:
|
* Authors:
|
||||||
@@ -52,6 +52,30 @@
|
|||||||
ldmia sp, {sp, lr, pc}^ /* Restore lr and exit */
|
ldmia sp, {sp, lr, pc}^ /* Restore lr and exit */
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
|
/* The following two macros are adapted from the two macros above, taken from FreeBSD. */
|
||||||
|
|
||||||
|
.macro PUSHFRAMEINSWI
|
||||||
|
str lr, [sp, #-4]! /* Push the return address */
|
||||||
|
sub sp, sp, #(4*17) /* Adjust the stack pointer */
|
||||||
|
stmia sp, {r0-r12} /* Store the general purpose registers */
|
||||||
|
add r0, sp, #(4*13) /* Adjust the stack pointer */
|
||||||
|
stmia r0, {r13-r14}^ /* Store the user mode sp and lr registers */
|
||||||
|
mrs r0, spsr /* Store the SPSR */
|
||||||
|
str r0, [sp, #-4]!
|
||||||
|
mov r0, #0 /* Fill in svc mode sp and lr with zeroes */
|
||||||
|
str r0, [sp, #(4*16)]
|
||||||
|
str r0, [sp, #(4*17)]
|
||||||
|
.endm
|
||||||
|
|
||||||
|
.macro PULLFRAMEINSWIANDEXIT
|
||||||
|
ldr r0, [sp], #4 /* Get SPSR from stack */
|
||||||
|
msr spsr, r0
|
||||||
|
ldmia sp, {r0-r14}^ /* Restore user mode registers */
|
||||||
|
add sp, sp, #(4*17) /* Adjust the stack pointer */
|
||||||
|
ldr lr, [sp], #4 /* Pull the return address */
|
||||||
|
movs pc, lr /* Return to user mode */
|
||||||
|
.endm
|
||||||
|
|
||||||
.text
|
.text
|
||||||
|
|
||||||
.globl _vectors_start
|
.globl _vectors_start
|
||||||
@@ -137,12 +161,12 @@ FUNCTION_END(arm_undefined)
|
|||||||
|
|
||||||
|
|
||||||
FUNCTION(arm_syscall):
|
FUNCTION(arm_syscall):
|
||||||
PUSHFRAMEINSVC
|
PUSHFRAMEINSWI
|
||||||
|
|
||||||
mov r0, sp
|
mov r0, sp
|
||||||
bl arch_arm_syscall
|
bl arch_arm_syscall
|
||||||
|
|
||||||
PULLFRAMEFROMSVCANDEXIT
|
PULLFRAMEINSWIANDEXIT
|
||||||
FUNCTION_END(arm_syscall)
|
FUNCTION_END(arm_syscall)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,9 @@
|
|||||||
#include <device_manager.h>
|
#include <device_manager.h>
|
||||||
#include <kscheduler.h>
|
#include <kscheduler.h>
|
||||||
#include <interrupt_controller.h>
|
#include <interrupt_controller.h>
|
||||||
|
#include <ksyscalls.h>
|
||||||
#include <smp.h>
|
#include <smp.h>
|
||||||
|
#include <syscall_numbers.h>
|
||||||
#include <thread.h>
|
#include <thread.h>
|
||||||
#include <timer.h>
|
#include <timer.h>
|
||||||
#include <util/AutoLock.h>
|
#include <util/AutoLock.h>
|
||||||
@@ -30,6 +32,7 @@
|
|||||||
#include <vm/vm.h>
|
#include <vm/vm.h>
|
||||||
#include <vm/vm_priv.h>
|
#include <vm/vm_priv.h>
|
||||||
#include <vm/VMAddressSpace.h>
|
#include <vm/VMAddressSpace.h>
|
||||||
|
#include <algorithm>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include <drivers/bus/FDT.h>
|
#include <drivers/bus/FDT.h>
|
||||||
@@ -236,8 +239,39 @@ arch_arm_undefined(struct iframe *iframe)
|
|||||||
extern "C" void
|
extern "C" void
|
||||||
arch_arm_syscall(struct iframe *iframe)
|
arch_arm_syscall(struct iframe *iframe)
|
||||||
{
|
{
|
||||||
|
#ifdef TRACE_ARCH_INT
|
||||||
print_iframe("Software interrupt", iframe);
|
print_iframe("Software interrupt", iframe);
|
||||||
IFrameScope scope(iframe); // push/pop iframe
|
#endif
|
||||||
|
|
||||||
|
uint32_t syscall = *(uint32_t *)(iframe->pc-4) & 0x00ffffff;
|
||||||
|
TRACE(("syscall number: %d\n", syscall));
|
||||||
|
|
||||||
|
uint32_t args[20];
|
||||||
|
if (syscall < kSyscallCount) {
|
||||||
|
TRACE(("syscall(%s,%d)\n",
|
||||||
|
kExtendedSyscallInfos[syscall].name,
|
||||||
|
kExtendedSyscallInfos[syscall].parameter_count));
|
||||||
|
|
||||||
|
int argSize = kSyscallInfos[syscall].parameter_size;
|
||||||
|
memcpy(args, &iframe->r0, std::min<int>(argSize, 4 * sizeof(uint32)));
|
||||||
|
if (argSize > 4 * sizeof(uint32)) {
|
||||||
|
status_t res = user_memcpy(&args[4], (void *)iframe->usr_sp,
|
||||||
|
(argSize - 4 * sizeof(uint32)));
|
||||||
|
if (res < B_OK) {
|
||||||
|
dprintf("can't read syscall arguments on user stack\n");
|
||||||
|
iframe->r0 = res;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enable_interrupts();
|
||||||
|
|
||||||
|
uint64 returnValue = 0;
|
||||||
|
syscall_dispatcher(syscall, (void*)args, &returnValue);
|
||||||
|
|
||||||
|
TRACE(("returning %" B_PRId64 "\n", returnValue));
|
||||||
|
iframe->r0 = returnValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user