Commit d8cc89ec authored by Anton Blanchard's avatar Anton Blanchard

ppc64: Preparation work for minimal register save/restore exception paths

parent ae802127
...@@ -57,6 +57,9 @@ show_syscalls_task: ...@@ -57,6 +57,9 @@ show_syscalls_task:
* Handle a system call. * Handle a system call.
*/ */
_GLOBAL(DoSyscall) _GLOBAL(DoSyscall)
std r3,ORIG_GPR3(r1)
li r12,0
std r12,RESULT(r1)
ld r11,_CCR(r1) /* Clear SO bit in CR */ ld r11,_CCR(r1) /* Clear SO bit in CR */
lis r10,0x1000 lis r10,0x1000
andc r11,r11,r10 andc r11,r11,r10
......
...@@ -789,7 +789,6 @@ SystemCall_common: ...@@ -789,7 +789,6 @@ SystemCall_common:
beq+ HardwareInterrupt_entry beq+ HardwareInterrupt_entry
1: 1:
#endif #endif
std r3,ORIG_GPR3(r1)
#ifdef DO_SOFT_DISABLE #ifdef DO_SOFT_DISABLE
ld r20,SOFTE(r1) ld r20,SOFTE(r1)
#else #else
...@@ -1119,12 +1118,6 @@ _GLOBAL(save_remaining_regs) ...@@ -1119,12 +1118,6 @@ _GLOBAL(save_remaining_regs)
SAVE_4GPRS(16, r1) SAVE_4GPRS(16, r1)
SAVE_8GPRS(24, r1) SAVE_8GPRS(24, r1)
/*
* Clear the RESULT field
*/
li r22,0
std r22,RESULT(r1)
/* /*
* Test if from user state; result will be tested later * Test if from user state; result will be tested later
*/ */
...@@ -1141,9 +1134,9 @@ _GLOBAL(save_remaining_regs) ...@@ -1141,9 +1134,9 @@ _GLOBAL(save_remaining_regs)
* If from user state, update THREAD.regs * If from user state, update THREAD.regs
*/ */
beq 2f /* Modify THREAD.regs if from user */ beq 2f /* Modify THREAD.regs if from user */
addi r24,r1,STACK_FRAME_OVERHEAD addi r23,r1,STACK_FRAME_OVERHEAD
ld r22, PACACURRENT(r13) ld r22, PACACURRENT(r13)
std r24,THREAD+PT_REGS(r22) std r23,THREAD+PT_REGS(r22)
2: 2:
SET_REG_TO_CONST(r22, MSR_KERNEL) SET_REG_TO_CONST(r22, MSR_KERNEL)
......
...@@ -443,26 +443,61 @@ _GLOBAL(cvt_df) ...@@ -443,26 +443,61 @@ _GLOBAL(cvt_df)
* kernel_thread(fn, arg, flags) * kernel_thread(fn, arg, flags)
*/ */
_GLOBAL(kernel_thread) _GLOBAL(kernel_thread)
/* XXX fix this when we optimise syscall entry to not save volatiles */ std r29,-24(r1)
mr r6,r3 /* function */ std r30,-16(r1)
mr r7,r4 /* arg */ stdu r1,-STACK_FRAME_OVERHEAD(r1)
mr r29,r3
mr r30,r4
ori r3,r5,CLONE_VM /* flags */ ori r3,r5,CLONE_VM /* flags */
oris r3,r3,(CLONE_UNTRACED>>16) oris r3,r3,(CLONE_UNTRACED>>16)
li r4,0 /* new sp (unused) */ li r4,0 /* new sp (unused) */
li r0,__NR_clone li r0,__NR_clone
sc sc
cmpi 0,r3,0 /* parent or child? */ cmpi 0,r3,0 /* parent or child? */
bnelr /* return if parent */ bne 1f /* return if parent */
li r0,0 li r0,0
stdu r0,-STACK_FRAME_OVERHEAD(r1) stdu r0,-STACK_FRAME_OVERHEAD(r1)
ld r2,8(r6) ld r2,8(r29)
ld r6,0(r6) ld r29,0(r29)
mtlr r6 /* fn addr in lr */ mtlr r29 /* fn addr in lr */
mr r3,r7 /* load arg and call fn */ mr r3,r30 /* load arg and call fn */
blrl blrl
li r0,__NR_exit /* exit after child exits */ li r0,__NR_exit /* exit after child exits */
li r3,0 li r3,0
sc sc
1: addi r1,r1,STACK_FRAME_OVERHEAD
ld r29,-24(r1)
ld r30,-16(r1)
blr
.section ".toc","aw"
.SYSCALL_ERRNO:
.tc errno[TC],errno
.section ".text"
.align 3
#define SYSCALL(name) \
_GLOBAL(name) \
li r0,__NR_##name; \
sc; \
bnslr; \
ld r4,.SYSCALL_ERRNO@toc(2); \
std r3,0(r4); \
li r3,-1; \
blr
#define __NR__exit __NR_exit
SYSCALL(setsid)
SYSCALL(open)
SYSCALL(read)
SYSCALL(write)
SYSCALL(lseek)
SYSCALL(close)
SYSCALL(dup)
SYSCALL(execve)
SYSCALL(waitpid)
#ifdef CONFIG_BINFMT_ELF32 #ifdef CONFIG_BINFMT_ELF32
/* Why isn't this a) automatic, b) written in 'C'? */ /* Why isn't this a) automatic, b) written in 'C'? */
......
...@@ -242,6 +242,7 @@ ...@@ -242,6 +242,7 @@
#define __NR_io_getevents 229 #define __NR_io_getevents 229
#define __NR_io_submit 230 #define __NR_io_submit 230
#define __NR_io_cancel 231 #define __NR_io_cancel 231
/* 223 + 224 currently unused */
#define __NR_exit_group 234 #define __NR_exit_group 234
#define __NR_lookup_dcookie 235 #define __NR_lookup_dcookie 235
#define __NR_sys_epoll_create 236 #define __NR_sys_epoll_create 236
...@@ -249,178 +250,6 @@ ...@@ -249,178 +250,6 @@
#define __NR_sys_epoll_wait 238 #define __NR_sys_epoll_wait 238
#define __NR_remap_file_pages 239 #define __NR_remap_file_pages 239
#define __NR(n) #n
#define __syscall_return(type) \
return (__sc_err & 0x10000000 ? errno = __sc_ret, __sc_ret = -1 : 0), \
(type) __sc_ret
#define __syscall_clobbers \
"r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12"
#define _syscall0(type,name) \
type name(void) \
{ \
unsigned long __sc_ret, __sc_err; \
{ \
register unsigned long __sc_0 __asm__ ("r0"); \
register unsigned long __sc_3 __asm__ ("r3"); \
\
__sc_0 = __NR_##name; \
__asm__ __volatile__ \
("sc \n\t" \
"mfcr %1 " \
: "=&r" (__sc_3), "=&r" (__sc_0) \
: "0" (__sc_3), "1" (__sc_0) \
: __syscall_clobbers); \
__sc_ret = __sc_3; \
__sc_err = __sc_0; \
} \
__syscall_return (type); \
}
#define _syscall1(type,name,type1,arg1) \
type name(type1 arg1) \
{ \
unsigned long __sc_ret, __sc_err; \
{ \
register unsigned long __sc_0 __asm__ ("r0"); \
register unsigned long __sc_3 __asm__ ("r3"); \
\
__sc_3 = (unsigned long) (arg1); \
__sc_0 = __NR_##name; \
__asm__ __volatile__ \
("sc \n\t" \
"mfcr %1 " \
: "=&r" (__sc_3), "=&r" (__sc_0) \
: "0" (__sc_3), "1" (__sc_0) \
: __syscall_clobbers); \
__sc_ret = __sc_3; \
__sc_err = __sc_0; \
} \
__syscall_return (type); \
}
#define _syscall2(type,name,type1,arg1,type2,arg2) \
type name(type1 arg1, type2 arg2) \
{ \
unsigned long __sc_ret, __sc_err; \
{ \
register unsigned long __sc_0 __asm__ ("r0"); \
register unsigned long __sc_3 __asm__ ("r3"); \
register unsigned long __sc_4 __asm__ ("r4"); \
\
__sc_3 = (unsigned long) (arg1); \
__sc_4 = (unsigned long) (arg2); \
__sc_0 = __NR_##name; \
__asm__ __volatile__ \
("sc \n\t" \
"mfcr %1 " \
: "=&r" (__sc_3), "=&r" (__sc_0) \
: "0" (__sc_3), "1" (__sc_0), \
"r" (__sc_4) \
: __syscall_clobbers); \
__sc_ret = __sc_3; \
__sc_err = __sc_0; \
} \
__syscall_return (type); \
}
#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \
type name(type1 arg1, type2 arg2, type3 arg3) \
{ \
unsigned long __sc_ret, __sc_err; \
{ \
register unsigned long __sc_0 __asm__ ("r0"); \
register unsigned long __sc_3 __asm__ ("r3"); \
register unsigned long __sc_4 __asm__ ("r4"); \
register unsigned long __sc_5 __asm__ ("r5"); \
\
__sc_3 = (unsigned long) (arg1); \
__sc_4 = (unsigned long) (arg2); \
__sc_5 = (unsigned long) (arg3); \
__sc_0 = __NR_##name; \
__asm__ __volatile__ \
("sc \n\t" \
"mfcr %1 " \
: "=&r" (__sc_3), "=&r" (__sc_0) \
: "0" (__sc_3), "1" (__sc_0), \
"r" (__sc_4), \
"r" (__sc_5) \
: __syscall_clobbers); \
__sc_ret = __sc_3; \
__sc_err = __sc_0; \
} \
__syscall_return (type); \
}
#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \
type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4) \
{ \
unsigned long __sc_ret, __sc_err; \
{ \
register unsigned long __sc_0 __asm__ ("r0"); \
register unsigned long __sc_3 __asm__ ("r3"); \
register unsigned long __sc_4 __asm__ ("r4"); \
register unsigned long __sc_5 __asm__ ("r5"); \
register unsigned long __sc_6 __asm__ ("r6"); \
\
__sc_3 = (unsigned long) (arg1); \
__sc_4 = (unsigned long) (arg2); \
__sc_5 = (unsigned long) (arg3); \
__sc_6 = (unsigned long) (arg4); \
__sc_0 = __NR_##name; \
__asm__ __volatile__ \
("sc \n\t" \
"mfcr %1 " \
: "=&r" (__sc_3), "=&r" (__sc_0) \
: "0" (__sc_3), "1" (__sc_0), \
"r" (__sc_4), \
"r" (__sc_5), \
"r" (__sc_6) \
: __syscall_clobbers); \
__sc_ret = __sc_3; \
__sc_err = __sc_0; \
} \
__syscall_return (type); \
}
#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5) \
type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) \
{ \
unsigned long __sc_ret, __sc_err; \
{ \
register unsigned long __sc_0 __asm__ ("r0"); \
register unsigned long __sc_3 __asm__ ("r3"); \
register unsigned long __sc_4 __asm__ ("r4"); \
register unsigned long __sc_5 __asm__ ("r5"); \
register unsigned long __sc_6 __asm__ ("r6"); \
register unsigned long __sc_7 __asm__ ("r7"); \
\
__sc_3 = (unsigned long) (arg1); \
__sc_4 = (unsigned long) (arg2); \
__sc_5 = (unsigned long) (arg3); \
__sc_6 = (unsigned long) (arg4); \
__sc_7 = (unsigned long) (arg5); \
__sc_0 = __NR_##name; \
__asm__ __volatile__ \
("sc \n\t" \
"mfcr %1 " \
: "=&r" (__sc_3), "=&r" (__sc_0) \
: "0" (__sc_3), "1" (__sc_0), \
"r" (__sc_4), \
"r" (__sc_5), \
"r" (__sc_6), \
"r" (__sc_7) \
: __syscall_clobbers); \
__sc_ret = __sc_3; \
__sc_err = __sc_0; \
} \
__syscall_return (type); \
}
#ifdef __KERNEL_SYSCALLS__ #ifdef __KERNEL_SYSCALLS__
/* /*
...@@ -434,17 +263,15 @@ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) \ ...@@ -434,17 +263,15 @@ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) \
/* /*
* System call prototypes. * System call prototypes.
*/ */
#define __NR__exit __NR_exit extern pid_t setsid(void);
static inline _syscall0(pid_t,setsid) extern int write(int fd, const char *buf, off_t count);
static inline _syscall3(int,write,int,fd,const char *,buf,off_t,count) extern int read(int fd, char *buf, off_t count);
static inline _syscall3(int,read,int,fd,char *,buf,off_t,count) extern off_t lseek(int fd, off_t offset, int count);
static inline _syscall3(off_t,lseek,int,fd,off_t,offset,int,count) extern int dup(int fd);
static inline _syscall1(int,dup,int,fd) extern int execve(const char *file, char **argv, char **envp);
static inline _syscall3(int,execve,const char *,file,char **,argv,char **,envp) extern int open(const char *file, int flag, int mode);
static inline _syscall3(int,open,const char *,file,int,flag,int,mode) extern int close(int fd);
static inline _syscall1(int,close,int,fd) extern pid_t waitpid(pid_t pid, int *wait_stat, int options);
static inline _syscall1(int,_exit,int,exitcode)
static inline _syscall3(pid_t,waitpid,pid_t,pid,int *,wait_stat,int,options)
#endif /* __KERNEL_SYSCALLS__ */ #endif /* __KERNEL_SYSCALLS__ */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment