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

View file

@ -15,12 +15,10 @@ void arch_enter(void *sp)
{
struct reg_snapshot *regs = sp;
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;
if (sc_num == SYSCALL_WRITE)
*(uint32_t *)0x400E1030U = 1 << 27;
if (sc_num > NSYSCALLS) {
arch_syscall_set_rval(regs, -EINVAL);
return;
@ -33,8 +31,8 @@ void arch_enter(void *sp)
}
/* TODO: not every syscall uses the max amount of parameters (duh) */
sc_ret = handler(arch_syscall_arg1(regs), arch_syscall_arg2(regs),
arch_syscall_arg3(regs), arch_syscall_arg4(regs));
sc_ret = handler(arch_syscall_arg1(regs), arch_syscall_arg2(regs), arch_syscall_arg3(regs),
arch_syscall_arg4(regs), arch_syscall_arg5(regs), arch_syscall_arg6(regs));
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:
*
* number: r7
* rval: r0
* arg1: r0
* arg2: r1
* arg3: r2
* arg4: r3
* rval: r0
*
* The syscall number is passed as part of the SVC instruction and read
* from the program counter in arch_syscall().
* arg5: r4
* arg6: r5
*/
/*

View file

@ -10,10 +10,50 @@
.thumb_func
.global syscall
.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:
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
.size syscall, .-syscall
/*

View file

@ -54,11 +54,13 @@ struct reg_snapshot {
struct reg_hw_snapshot hw;
};
#define arch_syscall_num(reg_snap) ((reg_snap)->hw.r0)
#define arch_syscall_arg1(reg_snap) ((reg_snap)->hw.r1)
#define arch_syscall_arg2(reg_snap) ((reg_snap)->hw.r2)
#define arch_syscall_arg3(reg_snap) ((reg_snap)->hw.r3)
#define arch_syscall_arg4(reg_snap) ((reg_snap)->hw.r12)
#define arch_syscall_num(reg_snap) ((reg_snap)->sw.r7)
#define arch_syscall_arg1(reg_snap) ((reg_snap)->hw.r0)
#define arch_syscall_arg2(reg_snap) ((reg_snap)->hw.r1)
#define arch_syscall_arg3(reg_snap) ((reg_snap)->hw.r2)
#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));

View file

@ -17,11 +17,12 @@ enum syscall {
};
/** 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. */
extern const int (*sys_table[NSYSCALLS])(sysarg_t arg1, sysarg_t arg2,
sysarg_t arg3, sysarg_t arg4);
extern const int (*sys_table[NSYSCALLS])(sysarg_t arg1, sysarg_t arg2, sysarg_t arg3,
sysarg_t arg4, sysarg_t arg5, sysarg_t arg6);
/* catchall handler that returns -ENOSYS */
int sys_stub(void);

View file

@ -6,10 +6,11 @@
#include <toolchain.h>
#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
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_WRITE, &sys_write),
};

View file

@ -11,13 +11,12 @@
__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,
(sysarg_t)offset);
(sysarg_t)offset, 0, 0);
}
__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,
(sysarg_t)0);
return syscall(SYSCALL_WRITE, (sysarg_t)fildes, (sysarg_t)buf, (sysarg_t)nbyte, 0, 0, 0);
}
/*