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;
|
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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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().
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -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));
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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),
|
||||||
};
|
};
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
Loading…
Reference in a new issue