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:
* Handle a system call.
*/
_GLOBAL(DoSyscall)
std r3,ORIG_GPR3(r1)
li r12,0
std r12,RESULT(r1)
ld r11,_CCR(r1) /* Clear SO bit in CR */
lis r10,0x1000
andc r11,r11,r10
......
......@@ -789,7 +789,6 @@ SystemCall_common:
beq+ HardwareInterrupt_entry
1:
#endif
std r3,ORIG_GPR3(r1)
#ifdef DO_SOFT_DISABLE
ld r20,SOFTE(r1)
#else
......@@ -1119,12 +1118,6 @@ _GLOBAL(save_remaining_regs)
SAVE_4GPRS(16, 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
*/
......@@ -1141,9 +1134,9 @@ _GLOBAL(save_remaining_regs)
* If from user state, update THREAD.regs
*/
beq 2f /* Modify THREAD.regs if from user */
addi r24,r1,STACK_FRAME_OVERHEAD
addi r23,r1,STACK_FRAME_OVERHEAD
ld r22, PACACURRENT(r13)
std r24,THREAD+PT_REGS(r22)
std r23,THREAD+PT_REGS(r22)
2:
SET_REG_TO_CONST(r22, MSR_KERNEL)
......
......@@ -443,26 +443,61 @@ _GLOBAL(cvt_df)
* kernel_thread(fn, arg, flags)
*/
_GLOBAL(kernel_thread)
/* XXX fix this when we optimise syscall entry to not save volatiles */
mr r6,r3 /* function */
mr r7,r4 /* arg */
std r29,-24(r1)
std r30,-16(r1)
stdu r1,-STACK_FRAME_OVERHEAD(r1)
mr r29,r3
mr r30,r4
ori r3,r5,CLONE_VM /* flags */
oris r3,r3,(CLONE_UNTRACED>>16)
li r4,0 /* new sp (unused) */
li r0,__NR_clone
sc
cmpi 0,r3,0 /* parent or child? */
bnelr /* return if parent */
bne 1f /* return if parent */
li r0,0
stdu r0,-STACK_FRAME_OVERHEAD(r1)
ld r2,8(r6)
ld r6,0(r6)
mtlr r6 /* fn addr in lr */
mr r3,r7 /* load arg and call fn */
ld r2,8(r29)
ld r29,0(r29)
mtlr r29 /* fn addr in lr */
mr r3,r30 /* load arg and call fn */
blrl
li r0,__NR_exit /* exit after child exits */
li r3,0
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
/* Why isn't this a) automatic, b) written in 'C'? */
......
......@@ -242,6 +242,7 @@
#define __NR_io_getevents 229
#define __NR_io_submit 230
#define __NR_io_cancel 231
/* 223 + 224 currently unused */
#define __NR_exit_group 234
#define __NR_lookup_dcookie 235
#define __NR_sys_epoll_create 236
......@@ -249,178 +250,6 @@
#define __NR_sys_epoll_wait 238
#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__
/*
......@@ -434,17 +263,15 @@ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) \
/*
* System call prototypes.
*/
#define __NR__exit __NR_exit
static inline _syscall0(pid_t,setsid)
static inline _syscall3(int,write,int,fd,const char *,buf,off_t,count)
static inline _syscall3(int,read,int,fd,char *,buf,off_t,count)
static inline _syscall3(off_t,lseek,int,fd,off_t,offset,int,count)
static inline _syscall1(int,dup,int,fd)
static inline _syscall3(int,execve,const char *,file,char **,argv,char **,envp)
static inline _syscall3(int,open,const char *,file,int,flag,int,mode)
static inline _syscall1(int,close,int,fd)
static inline _syscall1(int,_exit,int,exitcode)
static inline _syscall3(pid_t,waitpid,pid_t,pid,int *,wait_stat,int,options)
extern pid_t setsid(void);
extern int write(int fd, const char *buf, off_t count);
extern int read(int fd, char *buf, off_t count);
extern off_t lseek(int fd, off_t offset, int count);
extern int dup(int fd);
extern int execve(const char *file, char **argv, char **envp);
extern int open(const char *file, int flag, int mode);
extern int close(int fd);
extern pid_t waitpid(pid_t pid, int *wait_stat, int options);
#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