arch/at91sam3x8e: finalize entry routine
This commit is contained in:
parent
8252f14b6b
commit
63ccd87112
7 changed files with 66 additions and 25 deletions
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
|
||||
/*
|
||||
|
|
|
@ -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
|
||||
|
||||
/*
|
||||
|
|
|
@ -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));
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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),
|
||||
};
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
Loading…
Reference in a new issue