arch/at91sam3x8e: finalize entry routine

This commit is contained in:
Felix Kopp 2021-01-05 17:31:26 +01:00
parent 8252f14b6b
commit 63ccd87112
No known key found for this signature in database
GPG key ID: C478BA0A85F75728
7 changed files with 66 additions and 25 deletions
arch/at91sam3x8e
include
arch/at91sam3x8e
ardix
kernel
lib

View file

@ -15,12 +15,10 @@ void arch_enter(void *sp)
{ {
struct reg_snapshot *regs = sp; struct reg_snapshot *regs = sp;
enum syscall sc_num = arch_syscall_num(regs); enum syscall sc_num = arch_syscall_num(regs);
int (*handler)(sysarg_t arg1, sysarg_t arg2, sysarg_t arg3, sysarg_t arg4); int (*handler)(sysarg_t arg1, sysarg_t arg2, sysarg_t arg3,
sysarg_t arg4, sysarg_t arg5, sysarg_t arg6);
int sc_ret; int sc_ret;
if (sc_num == SYSCALL_WRITE)
*(uint32_t *)0x400E1030U = 1 << 27;
if (sc_num > NSYSCALLS) { if (sc_num > NSYSCALLS) {
arch_syscall_set_rval(regs, -EINVAL); arch_syscall_set_rval(regs, -EINVAL);
return; return;
@ -33,8 +31,8 @@ void arch_enter(void *sp)
} }
/* TODO: not every syscall uses the max amount of parameters (duh) */ /* TODO: not every syscall uses the max amount of parameters (duh) */
sc_ret = handler(arch_syscall_arg1(regs), arch_syscall_arg2(regs), sc_ret = handler(arch_syscall_arg1(regs), arch_syscall_arg2(regs), arch_syscall_arg3(regs),
arch_syscall_arg3(regs), arch_syscall_arg4(regs)); arch_syscall_arg4(regs), arch_syscall_arg5(regs), arch_syscall_arg6(regs));
arch_syscall_set_rval(regs, sc_ret); arch_syscall_set_rval(regs, sc_ret);
} }

View file

@ -17,14 +17,14 @@ irq_svc:
/* /*
* Syscalls on Cortex-M use the following parameter calling convention: * Syscalls on Cortex-M use the following parameter calling convention:
* *
* number: r7
* rval: r0
* arg1: r0 * arg1: r0
* arg2: r1 * arg2: r1
* arg3: r2 * arg3: r2
* arg4: r3 * arg4: r3
* rval: r0 * arg5: r4
* * arg6: r5
* The syscall number is passed as part of the SVC instruction and read
* from the program counter in arch_syscall().
*/ */
/* /*

View file

@ -10,10 +10,50 @@
.thumb_func .thumb_func
.global syscall .global syscall
.type syscall, %function .type syscall, %function
/* int syscall(int number, int arg1, int arg2, int arg3, int arg4); */ /* int syscall(int number, int arg1, int arg2, int arg3, int arg4, int arg5, int arg6); */
syscall: syscall:
svc #1 push {r4-r5,r7}
/*
* I HAVE NO IDEA WHY THE F U C K GCC THINKS I CAN'T MOV TWO LOW REGS
* IN ONE INSTRUCTION WHEN THAT IS L I T E R A L L Y IN THE ASM OUTPUT
* OF GCC WHEN COMPILING SOME C CODE. BUT AT THIS POINT, I WON'T EVEN
* BOTHER WITH WHATEVER SHITTY COMPILE OPTION OR PREPROCESSOR DIRECTIVE
* I HAVE TO TURN ON IN ORDER FOR THIS PIECE OF SHIT THAT DARES CALLING
* ITSELF A COMPILER EAT MY SHIT CODE AND SHITS OUT THE SHITTY BINARY
* I WANT. FUCK YOU, SYSCALLS WILL JUST TAKE 10 INSTRUCTIONS MORE THEN.
*/
mov r3, r12
push {r3}
mov r12, r0 /* syscall number */
mov r7, r12
mov r12, r1 /* arg1 */
mov r0, r12
mov r12, r2 /* arg2 */
mov r1, r12
mov r12, r3 /* arg3 */
mov r2, r12
pop {r3}
mov r12, r3
/* stack params begin at 12 bytes offset because we already pushed three registers */
ldr r3, [sp, #12] /* arg4 */
ldr r4, [sp, #16] /* arg5 */
ldr r5, [sp, #20] /* arg6 */
svc #0
pop {r4-r5,r7}
/* r0 (return value) is set by the kernel */
bx lr bx lr
.size syscall, .-syscall .size syscall, .-syscall
/* /*

View file

@ -54,11 +54,13 @@ struct reg_snapshot {
struct reg_hw_snapshot hw; struct reg_hw_snapshot hw;
}; };
#define arch_syscall_num(reg_snap) ((reg_snap)->hw.r0) #define arch_syscall_num(reg_snap) ((reg_snap)->sw.r7)
#define arch_syscall_arg1(reg_snap) ((reg_snap)->hw.r1) #define arch_syscall_arg1(reg_snap) ((reg_snap)->hw.r0)
#define arch_syscall_arg2(reg_snap) ((reg_snap)->hw.r2) #define arch_syscall_arg2(reg_snap) ((reg_snap)->hw.r1)
#define arch_syscall_arg3(reg_snap) ((reg_snap)->hw.r3) #define arch_syscall_arg3(reg_snap) ((reg_snap)->hw.r2)
#define arch_syscall_arg4(reg_snap) ((reg_snap)->hw.r12) #define arch_syscall_arg4(reg_snap) ((reg_snap)->hw.r3)
#define arch_syscall_arg5(reg_snap) ((reg_snap)->sw.r4)
#define arch_syscall_arg6(reg_snap) ((reg_snap)->sw.r5)
#define arch_syscall_set_rval(reg_snap, val) ((reg_snap)->hw.r0 = (val)); #define arch_syscall_set_rval(reg_snap, val) ((reg_snap)->hw.r0 = (val));

View file

@ -17,11 +17,12 @@ enum syscall {
}; };
/** Perform an indirect system call. */ /** Perform an indirect system call. */
int syscall(enum syscall number, sysarg_t arg1, sysarg_t arg2, sysarg_t arg3, sysarg_t arg4); int syscall(enum syscall number, sysarg_t arg1, sysarg_t arg2, sysarg_t arg3,
sysarg_t arg4, sysarg_t arg5, sysarg_t arg6);
/** The table of system call handlers, indexed by syscall number. */ /** The table of system call handlers, indexed by syscall number. */
extern const int (*sys_table[NSYSCALLS])(sysarg_t arg1, sysarg_t arg2, extern const int (*sys_table[NSYSCALLS])(sysarg_t arg1, sysarg_t arg2, sysarg_t arg3,
sysarg_t arg3, sysarg_t arg4); sysarg_t arg4, sysarg_t arg5, sysarg_t arg6);
/* catchall handler that returns -ENOSYS */ /* catchall handler that returns -ENOSYS */
int sys_stub(void); int sys_stub(void);

View file

@ -6,10 +6,11 @@
#include <toolchain.h> #include <toolchain.h>
#define sys_table_entry(number, func) \ #define sys_table_entry(number, func) \
[number] (int (*)(sysarg_t, sysarg_t, sysarg_t, sysarg_t))(func) [number] (int (*)(sysarg_t, sysarg_t, sysarg_t, sysarg_t, sysarg_t, sysarg_t))(func)
__rodata __rodata
const int (*sys_table[NSYSCALLS])(sysarg_t arg1, sysarg_t arg2, sysarg_t arg3, sysarg_t arg4) = { const int (*sys_table[NSYSCALLS])(sysarg_t arg1, sysarg_t arg2, sysarg_t arg3,
sysarg_t arg4, sysarg_t arg5, sysarg_t arg6) = {
sys_table_entry(SYSCALL_READ, &sys_stub), sys_table_entry(SYSCALL_READ, &sys_stub),
sys_table_entry(SYSCALL_WRITE, &sys_write), sys_table_entry(SYSCALL_WRITE, &sys_write),
}; };

View file

@ -11,13 +11,12 @@
__shared ssize_t pwrite(int fildes, const void *buf, size_t nbyte, off_t offset) __shared ssize_t pwrite(int fildes, const void *buf, size_t nbyte, off_t offset)
{ {
return syscall(SYSCALL_WRITE, (sysarg_t)fildes, (sysarg_t)buf, (sysarg_t)nbyte, return syscall(SYSCALL_WRITE, (sysarg_t)fildes, (sysarg_t)buf, (sysarg_t)nbyte,
(sysarg_t)offset); (sysarg_t)offset, 0, 0);
} }
__shared ssize_t write(int fildes, const void *buf, size_t nbyte) __shared ssize_t write(int fildes, const void *buf, size_t nbyte)
{ {
return syscall(SYSCALL_WRITE, (sysarg_t)fildes, (sysarg_t)buf, (sysarg_t)nbyte, return syscall(SYSCALL_WRITE, (sysarg_t)fildes, (sysarg_t)buf, (sysarg_t)nbyte, 0, 0, 0);
(sysarg_t)0);
} }
/* /*