Commit 8213a2f3 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/signal

Pull pile 2 of execve and kernel_thread unification work from Al Viro:
 "Stuff in there: kernel_thread/kernel_execve/sys_execve conversions for
  several more architectures plus assorted signal fixes and cleanups.

  There'll be more (in particular, real fixes for the alpha
  do_notify_resume() irq mess)..."

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/signal: (43 commits)
  alpha: don't open-code trace_report_syscall_{enter,exit}
  Uninclude linux/freezer.h
  m32r: trim masks
  avr32: trim masks
  tile: don't bother with SIGTRAP in setup_frame
  microblaze: don't bother with SIGTRAP in setup_rt_frame()
  mn10300: don't bother with SIGTRAP in setup_frame()
  frv: no need to raise SIGTRAP in setup_frame()
  x86: get rid of duplicate code in case of CONFIG_VM86
  unicore32: remove pointless test
  h8300: trim _TIF_WORK_MASK
  parisc: decide whether to go to slow path (tracesys) based on thread flags
  parisc: don't bother looping in do_signal()
  parisc: fix double restarts
  bury the rest of TIF_IRET
  sanitize tsk_is_polling()
  bury _TIF_RESTORE_SIGMASK
  unicore32: unobfuscate _TIF_WORK_MASK
  mips: NOTIFY_RESUME is not needed in TIF masks
  mips: merge the identical "return from syscall" per-ABI code
  ...

Conflicts:
	arch/arm/include/asm/thread_info.h
parents 40924754 12f79be9
......@@ -84,7 +84,6 @@ register struct thread_info *__current_thread_info __asm__("$8");
#define _TIF_SIGPENDING (1<<TIF_SIGPENDING)
#define _TIF_NEED_RESCHED (1<<TIF_NEED_RESCHED)
#define _TIF_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG)
#define _TIF_RESTORE_SIGMASK (1<<TIF_RESTORE_SIGMASK)
#define _TIF_NOTIFY_RESUME (1<<TIF_NOTIFY_RESUME)
/* Work to do on interrupt/exception return. */
......@@ -117,5 +116,7 @@ register struct thread_info *__current_thread_info __asm__("$8");
(int __user *)(value)); \
})
#define tsk_is_polling(t) test_tsk_thread_flag(t, TIF_POLLING_NRFLAG)
#endif /* __KERNEL__ */
#endif /* _ALPHA_THREAD_INFO_H */
......@@ -418,11 +418,10 @@ $work_notifysig:
strace:
/* set up signal stack, call syscall_trace */
bsr $1, do_switch_stack
jsr $26, syscall_trace
jsr $26, syscall_trace_enter /* returns the syscall number */
bsr $1, undo_switch_stack
/* get the system call number and the arguments back.. */
ldq $0, 0($sp)
/* get the arguments back.. */
ldq $16, SP_OFF+24($sp)
ldq $17, SP_OFF+32($sp)
ldq $18, SP_OFF+40($sp)
......@@ -449,7 +448,7 @@ $strace_success:
stq $0, 0($sp) /* save return value */
bsr $1, do_switch_stack
jsr $26, syscall_trace
jsr $26, syscall_trace_leave
bsr $1, undo_switch_stack
br $31, ret_from_sys_call
......@@ -467,7 +466,7 @@ $strace_error:
bsr $1, do_switch_stack
mov $19, $9 /* save old syscall number */
mov $20, $10 /* save old a3 */
jsr $26, syscall_trace
jsr $26, syscall_trace_leave
mov $9, $19
mov $10, $20
bsr $1, undo_switch_stack
......@@ -698,7 +697,7 @@ sys_sigreturn:
lda $sp, -SWITCH_STACK_SIZE($sp)
jsr $26, do_sigreturn
bne $9, 1f
jsr $26, syscall_trace
jsr $26, syscall_trace_leave
1: br $1, undo_switch_stack
br ret_from_sys_call
.end sys_sigreturn
......@@ -715,7 +714,7 @@ sys_rt_sigreturn:
lda $sp, -SWITCH_STACK_SIZE($sp)
jsr $26, do_rt_sigreturn
bne $9, 1f
jsr $26, syscall_trace
jsr $26, syscall_trace_leave
1: br $1, undo_switch_stack
br ret_from_sys_call
.end sys_rt_sigreturn
......
......@@ -13,6 +13,7 @@
#include <linux/user.h>
#include <linux/security.h>
#include <linux/signal.h>
#include <linux/tracehook.h>
#include <asm/uaccess.h>
#include <asm/pgtable.h>
......@@ -312,25 +313,18 @@ long arch_ptrace(struct task_struct *child, long request,
return ret;
}
asmlinkage unsigned long syscall_trace_enter(void)
{
unsigned long ret = 0;
if (test_thread_flag(TIF_SYSCALL_TRACE) &&
tracehook_report_syscall_entry(current_pt_regs()))
ret = -1UL;
return ret ?: current_pt_regs()->r0;
}
asmlinkage void
syscall_trace(void)
syscall_trace_leave(void)
{
if (!test_thread_flag(TIF_SYSCALL_TRACE))
return;
if (!(current->ptrace & PT_PTRACED))
return;
/* The 0x80 provides a way for the tracing parent to distinguish
between a syscall stop and SIGTRAP delivery */
ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
? 0x80 : 0));
/*
* This isn't the same as continuing with a signal, but it will do
* for normal use. strace only continues with a signal if the
* stopping signal is not SIGTRAP. -brl
*/
if (current->exit_code) {
send_sig(current->exit_code, current, 1);
current->exit_code = 0;
}
if (test_thread_flag(TIF_SYSCALL_TRACE))
tracehook_report_syscall_exit(current_pt_regs(), 0);
}
......@@ -151,7 +151,6 @@ extern int vfp_restore_user_hwstate(struct user_vfp __user *,
#define TIF_SYSCALL_TRACE 8
#define TIF_SYSCALL_AUDIT 9
#define TIF_SYSCALL_TRACEPOINT 10
#define TIF_POLLING_NRFLAG 16
#define TIF_USING_IWMMXT 17
#define TIF_MEMDIE 18 /* is terminating due to OOM killer */
#define TIF_RESTORE_SIGMASK 20
......@@ -164,7 +163,6 @@ extern int vfp_restore_user_hwstate(struct user_vfp __user *,
#define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE)
#define _TIF_SYSCALL_AUDIT (1 << TIF_SYSCALL_AUDIT)
#define _TIF_SYSCALL_TRACEPOINT (1 << TIF_SYSCALL_TRACEPOINT)
#define _TIF_POLLING_NRFLAG (1 << TIF_POLLING_NRFLAG)
#define _TIF_USING_IWMMXT (1 << TIF_USING_IWMMXT)
#define _TIF_SECCOMP (1 << TIF_SECCOMP)
......
......@@ -10,7 +10,6 @@
#include <linux/errno.h>
#include <linux/signal.h>
#include <linux/personality.h>
#include <linux/freezer.h>
#include <linux/uaccess.h>
#include <linux/tracehook.h>
......
......@@ -77,8 +77,6 @@ static inline struct thread_info *current_thread_info(void)
#define TIF_SYSCALL_TRACE 0 /* syscall trace active */
#define TIF_SIGPENDING 1 /* signal pending */
#define TIF_NEED_RESCHED 2 /* rescheduling necessary */
#define TIF_POLLING_NRFLAG 3 /* true if poll_idle() is polling
TIF_NEED_RESCHED */
#define TIF_BREAKPOINT 4 /* enter monitor mode on return */
#define TIF_SINGLE_STEP 5 /* single step in progress */
#define TIF_MEMDIE 6 /* is terminating due to OOM killer */
......@@ -91,10 +89,9 @@ static inline struct thread_info *current_thread_info(void)
#define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE)
#define _TIF_SIGPENDING (1 << TIF_SIGPENDING)
#define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED)
#define _TIF_POLLING_NRFLAG (1 << TIF_POLLING_NRFLAG)
#define _TIF_BREAKPOINT (1 << TIF_BREAKPOINT)
#define _TIF_SINGLE_STEP (1 << TIF_SINGLE_STEP)
#define _TIF_MEMDIE (1 << TIF_MEMDIE)
#define _TIF_RESTORE_SIGMASK (1 << TIF_RESTORE_SIGMASK)
#define _TIF_CPU_GOING_TO_SLEEP (1 << TIF_CPU_GOING_TO_SLEEP)
#define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME)
......@@ -102,17 +99,14 @@ static inline struct thread_info *current_thread_info(void)
/* work to do on interrupt/exception return */
#define _TIF_WORK_MASK \
((1 << TIF_SIGPENDING) \
(_TIF_SIGPENDING \
| _TIF_NOTIFY_RESUME \
| (1 << TIF_NEED_RESCHED) \
| (1 << TIF_POLLING_NRFLAG) \
| (1 << TIF_BREAKPOINT) \
| (1 << TIF_RESTORE_SIGMASK))
| _TIF_NEED_RESCHED \
| _TIF_BREAKPOINT)
/* work to do on any return to userspace */
#define _TIF_ALLWORK_MASK (_TIF_WORK_MASK | (1 << TIF_SYSCALL_TRACE) | \
_TIF_NOTIFY_RESUME)
#define _TIF_ALLWORK_MASK (_TIF_WORK_MASK | _TIF_SYSCALL_TRACE)
/* work to do on return from debug mode */
#define _TIF_DBGWORK_MASK (_TIF_WORK_MASK & ~(1 << TIF_BREAKPOINT))
#define _TIF_DBGWORK_MASK (_TIF_WORK_MASK & ~_TIF_BREAKPOINT)
#endif /* __ASM_AVR32_THREAD_INFO_H */
......@@ -15,7 +15,6 @@
#include <linux/errno.h>
#include <linux/ptrace.h>
#include <linux/unistd.h>
#include <linux/freezer.h>
#include <linux/tracehook.h>
#include <asm/uaccess.h>
......
......@@ -96,8 +96,6 @@ static inline struct thread_info *current_thread_info(void)
#define TIF_SYSCALL_TRACE 0 /* syscall trace active */
#define TIF_SIGPENDING 1 /* signal pending */
#define TIF_NEED_RESCHED 2 /* rescheduling necessary */
#define TIF_POLLING_NRFLAG 3 /* true if poll_idle() is polling
TIF_NEED_RESCHED */
#define TIF_MEMDIE 4 /* is terminating due to OOM killer */
#define TIF_RESTORE_SIGMASK 5 /* restore signal mask in do_signal() */
#define TIF_IRQ_SYNC 7 /* sync pipeline stage */
......@@ -108,8 +106,6 @@ static inline struct thread_info *current_thread_info(void)
#define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE)
#define _TIF_SIGPENDING (1<<TIF_SIGPENDING)
#define _TIF_NEED_RESCHED (1<<TIF_NEED_RESCHED)
#define _TIF_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG)
#define _TIF_RESTORE_SIGMASK (1<<TIF_RESTORE_SIGMASK)
#define _TIF_IRQ_SYNC (1<<TIF_IRQ_SYNC)
#define _TIF_NOTIFY_RESUME (1<<TIF_NOTIFY_RESUME)
#define _TIF_SINGLESTEP (1<<TIF_SINGLESTEP)
......
......@@ -10,7 +10,6 @@
#include <linux/tty.h>
#include <linux/personality.h>
#include <linux/binfmts.h>
#include <linux/freezer.h>
#include <linux/uaccess.h>
#include <linux/tracehook.h>
......
......@@ -17,6 +17,7 @@ config C6X
select OF
select OF_EARLY_FLATTREE
select GENERIC_CLOCKEVENTS
select GENERIC_KERNEL_THREAD
config MMU
def_bool n
......
......@@ -92,8 +92,6 @@ static inline void release_thread(struct task_struct *dead_task)
{
}
extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
#define copy_segments(tsk, mm) do { } while (0)
#define release_segments(mm) do { } while (0)
......
......@@ -44,11 +44,6 @@ extern int sys_cache_sync(unsigned long s, unsigned long e);
struct pt_regs;
extern asmlinkage long sys_c6x_clone(struct pt_regs *regs);
extern asmlinkage long sys_c6x_execve(const char __user *name,
const char __user *const __user *argv,
const char __user *const __user *envp,
struct pt_regs *regs);
#include <asm-generic/syscalls.h>
......
......@@ -97,7 +97,6 @@ struct thread_info *current_thread_info(void)
#define TIF_NEED_RESCHED 3 /* rescheduling necessary */
#define TIF_RESTORE_SIGMASK 4 /* restore signal mask in do_signal() */
#define TIF_POLLING_NRFLAG 16 /* true if polling TIF_NEED_RESCHED */
#define TIF_MEMDIE 17 /* OOM killer killed process */
#define TIF_WORK_MASK 0x00007FFE /* work on irq/exception return */
......
......@@ -14,6 +14,9 @@
* more details.
*/
#define __ARCH_WANT_KERNEL_EXECVE
#define __ARCH_WANT_SYS_EXECVE
/* Use the standard ABI for syscalls. */
#include <asm-generic/unistd.h>
......
......@@ -116,7 +116,6 @@ void foo(void)
DEFINE(_TIF_NOTIFY_RESUME, (1<<TIF_NOTIFY_RESUME));
DEFINE(_TIF_SIGPENDING, (1<<TIF_SIGPENDING));
DEFINE(_TIF_NEED_RESCHED, (1<<TIF_NEED_RESCHED));
DEFINE(_TIF_POLLING_NRFLAG, (1<<TIF_POLLING_NRFLAG));
DEFINE(_TIF_ALLWORK_MASK, TIF_ALLWORK_MASK);
DEFINE(_TIF_WORK_MASK, TIF_WORK_MASK);
......
......@@ -400,6 +400,32 @@ ret_from_fork_2:
STW .D2T2 B0,*+SP(REGS_A4+8)
ENDPROC(ret_from_fork)
ENTRY(ret_from_kernel_thread)
#ifdef CONFIG_C6X_BIG_KERNEL
MVKL .S1 schedule_tail,A0
MVKH .S1 schedule_tail,A0
B .S2X A0
#else
B .S2 schedule_tail
#endif
LDW .D2T2 *+SP(REGS_A0+8),B10 /* get fn */
ADDKPC .S2 0f,B3,3
0:
B .S2 B10 /* call fn */
LDW .D2T1 *+SP(REGS_A1+8),A4 /* get arg */
MVKL .S2 sys_exit,B11
MVKH .S2 sys_exit,B11
ADDKPC .S2 0f,B3,1
0:
BNOP .S2 B11,5 /* jump to sys_exit */
ENDPROC(ret_from_kernel_thread)
ENTRY(ret_from_kernel_execve)
GET_THREAD_INFO A12
BNOP .S2 syscall_exit,4
ADD .D2X A4,-8,SP
ENDPROC(ret_from_kernel_execve)
;;
;; These are the interrupt handlers, responsible for calling __do_IRQ()
;; int6 is used for syscalls (see _system_call entry)
......@@ -593,13 +619,6 @@ ENTRY(sys_sigaltstack)
NOP 4
ENDPROC(sys_sigaltstack)
;; kernel_execve
ENTRY(kernel_execve)
MVK .S2 __NR_execve,B0
SWE
BNOP .S2 B3,5
ENDPROC(kernel_execve)
;;
;; Special system calls
;; return address is in B3
......@@ -628,29 +647,6 @@ ENTRY(sys_rt_sigreturn)
#endif
ENDPROC(sys_rt_sigreturn)
ENTRY(sys_execve)
ADDAW .D2 SP,2,B6 ; put regs addr in 4th parameter
; & adjust regs stack addr
LDW .D2T2 *+SP(REGS_B4+8),B4
;; c6x_execve(char *name, char **argv,
;; char **envp, struct pt_regs *regs)
#ifdef CONFIG_C6X_BIG_KERNEL
|| MVKL .S1 sys_c6x_execve,A0
MVKH .S1 sys_c6x_execve,A0
B .S2X A0
#else
|| B .S2 sys_c6x_execve
#endif
STW .D2T2 B3,*SP--[2]
ADDKPC .S2 ret_from_c6x_execve,B3,3
ret_from_c6x_execve:
LDW .D2T2 *++SP[2],B3
NOP 4
BNOP .S2 B3,5
ENDPROC(sys_execve)
ENTRY(sys_pread_c6x)
MV .D2X A8,B7
#ifdef CONFIG_C6X_BIG_KERNEL
......
......@@ -25,6 +25,7 @@ void (*c6x_restart)(void);
void (*c6x_halt)(void);
extern asmlinkage void ret_from_fork(void);
extern asmlinkage void ret_from_kernel_thread(void);
/*
* power off function, if any
......@@ -103,37 +104,6 @@ void machine_power_off(void)
halt_loop();
}
static void kernel_thread_helper(int dummy, void *arg, int (*fn)(void *))
{
do_exit(fn(arg));
}
/*
* Create a kernel thread
*/
int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
{
struct pt_regs regs;
/*
* copy_thread sets a4 to zero (child return from fork)
* so we can't just set things up to directly return to
* fn.
*/
memset(&regs, 0, sizeof(regs));
regs.b4 = (unsigned long) arg;
regs.a6 = (unsigned long) fn;
regs.pc = (unsigned long) kernel_thread_helper;
local_save_flags(regs.csr);
regs.csr |= 1;
regs.tsr = 5; /* Set GEE and GIE in TSR */
/* Ok, create the new process.. */
return do_fork(flags | CLONE_VM | CLONE_UNTRACED, -1, &regs,
0, NULL, NULL);
}
EXPORT_SYMBOL(kernel_thread);
void flush_thread(void)
{
}
......@@ -191,22 +161,24 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
childregs = task_pt_regs(p);
*childregs = *regs;
childregs->a4 = 0;
if (usp == -1)
if (!regs) {
/* case of __kernel_thread: we return to supervisor space */
memset(childregs, 0, sizeof(struct pt_regs));
childregs->sp = (unsigned long)(childregs + 1);
else
p->thread.pc = (unsigned long) ret_from_kernel_thread;
childregs->a0 = usp; /* function */
childregs->a1 = ustk_size; /* argument */
} else {
/* Otherwise use the given stack */
*childregs = *regs;
childregs->sp = usp;
p->thread.pc = (unsigned long) ret_from_fork;
}
/* Set usp/ksp */
p->thread.usp = childregs->sp;
/* switch_to uses stack to save/restore 14 callee-saved regs */
thread_saved_ksp(p) = (unsigned long)childregs - 8;
p->thread.pc = (unsigned int) ret_from_fork;
p->thread.wchan = (unsigned long) ret_from_fork;
p->thread.wchan = p->thread.pc;
#ifdef __DSBT__
{
unsigned long dp;
......@@ -221,28 +193,6 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
return 0;
}
/*
* c6x_execve() executes a new program.
*/
SYSCALL_DEFINE4(c6x_execve, const char __user *, name,
const char __user *const __user *, argv,
const char __user *const __user *, envp,
struct pt_regs *, regs)
{
int error;
char *filename;
filename = getname(name);
error = PTR_ERR(filename);
if (IS_ERR(filename))
goto out;
error = do_execve(filename, argv, envp, regs);
putname(filename);
out:
return error;
}
unsigned long get_wchan(struct task_struct *p)
{
return p->thread.wchan;
......
......@@ -78,15 +78,12 @@ struct thread_info {
#define TIF_SIGPENDING 2 /* signal pending */
#define TIF_NEED_RESCHED 3 /* rescheduling necessary */
#define TIF_RESTORE_SIGMASK 9 /* restore signal mask in do_signal() */
#define TIF_POLLING_NRFLAG 16 /* true if poll_idle() is polling TIF_NEED_RESCHED */
#define TIF_MEMDIE 17 /* is terminating due to OOM killer */
#define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE)
#define _TIF_NOTIFY_RESUME (1<<TIF_NOTIFY_RESUME)
#define _TIF_SIGPENDING (1<<TIF_SIGPENDING)
#define _TIF_NEED_RESCHED (1<<TIF_NEED_RESCHED)
#define _TIF_RESTORE_SIGMASK (1<<TIF_RESTORE_SIGMASK)
#define _TIF_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG)
#define _TIF_WORK_MASK 0x0000FFFE /* work to do on interrupt/exception return */
#define _TIF_ALLWORK_MASK 0x0000FFFF /* work to do on any return to u-space */
......
......@@ -12,6 +12,7 @@ config FRV
select ARCH_HAVE_NMI_SAFE_CMPXCHG
select GENERIC_CPU_DEVICES
select ARCH_WANT_IPC_PARSE_VERSION
select GENERIC_KERNEL_THREAD
config ZONE_DMA
bool
......
......@@ -92,14 +92,12 @@ extern struct task_struct *__kernel_current_task;
/*
* do necessary setup to start up a newly executed thread.
* - need to discard the frame stacked by init() invoking the execve syscall
*/
#define start_thread(_regs, _pc, _usp) \
do { \
__frame = __kernel_frame0_ptr; \
__frame->pc = (_pc); \
__frame->psr &= ~PSR_S; \
__frame->sp = (_usp); \
_regs->pc = (_pc); \
_regs->psr &= ~PSR_S; \
_regs->sp = (_usp); \
} while(0)
/* Free all resources held by a thread. */
......@@ -107,7 +105,6 @@ static inline void release_thread(struct task_struct *dead_task)
{
}
extern asmlinkage int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
extern asmlinkage void save_user_regs(struct user_context *target);
extern asmlinkage void *restore_user_regs(const struct user_context *target, ...);
......
......@@ -76,6 +76,7 @@ register struct pt_regs *__frame asm("gr28");
#define user_mode(regs) (!((regs)->psr & PSR_S))
#define instruction_pointer(regs) ((regs)->pc)
#define user_stack_pointer(regs) ((regs)->sp)
#define current_pt_regs() (__frame)
extern unsigned long user_stack(const struct pt_regs *);
#define profile_pc(regs) ((regs)->pc)
......
......@@ -94,7 +94,6 @@ register struct thread_info *__current_thread_info asm("gr15");
#define TIF_NEED_RESCHED 3 /* rescheduling necessary */
#define TIF_SINGLESTEP 4 /* restore singlestep on return to user mode */
#define TIF_RESTORE_SIGMASK 5 /* restore signal mask in do_signal() */
#define TIF_POLLING_NRFLAG 6 /* true if poll_idle() is polling TIF_NEED_RESCHED */
#define TIF_MEMDIE 7 /* is terminating due to OOM killer */
#define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE)
......@@ -102,8 +101,6 @@ register struct thread_info *__current_thread_info asm("gr15");
#define _TIF_SIGPENDING (1 << TIF_SIGPENDING)
#define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED)
#define _TIF_SINGLESTEP (1 << TIF_SINGLESTEP)
#define _TIF_RESTORE_SIGMASK (1 << TIF_RESTORE_SIGMASK)
#define _TIF_POLLING_NRFLAG (1 << TIF_POLLING_NRFLAG)
/* work to do on interrupt/exception return */
#define _TIF_WORK_MASK \
......
......@@ -372,6 +372,8 @@
#define __ARCH_WANT_SYS_SIGPROCMASK
#define __ARCH_WANT_SYS_RT_SIGACTION
#define __ARCH_WANT_SYS_RT_SIGSUSPEND
#define __ARCH_WANT_SYS_EXECVE
#define __ARCH_WANT_KERNEL_EXECVE
/*
* "Conditional" syscalls
......
......@@ -7,8 +7,8 @@ heads-$(CONFIG_MMU) := head-mmu-fr451.o
extra-y:= head.o vmlinux.lds
obj-y := $(heads-y) entry.o entry-table.o break.o switch_to.o kernel_thread.o \
kernel_execve.o process.o traps.o ptrace.o signal.o dma.o \
obj-y := $(heads-y) entry.o entry-table.o break.o switch_to.o \
process.o traps.o ptrace.o signal.o dma.o \
sys_frv.o time.o setup.o frv_ksyms.o \
debug-stub.o irq.o sleep.o uaccess.o
......
......@@ -863,6 +863,19 @@ ret_from_fork:
setlos.p #0,gr8
bra __syscall_exit
.globl ret_from_kernel_thread
ret_from_kernel_thread:
lddi.p @(gr28,#REG_GR(8)),gr20
call schedule_tail
or.p gr20,gr20,gr8
calll @(gr21,gr0)
bra sys_exit
.globl ret_from_kernel_execve
ret_from_kernel_execve:
ori gr28,0,sp
bra __syscall_exit
###################################################################################################
#
# Return to user mode is not as complex as all this looks,
......
......@@ -30,7 +30,6 @@ EXPORT_SYMBOL(ip_fast_csum);
EXPORT_SYMBOL(local_irq_count);
EXPORT_SYMBOL(local_bh_count);
#endif
EXPORT_SYMBOL(kernel_thread);
EXPORT_SYMBOL(__res_bus_clock_speed_HZ);
EXPORT_SYMBOL(__page_offset);
......
/* in-kernel program execution
*
* Copyright (C) 2006 Red Hat, Inc. All Rights Reserved.
* Written by David Howells (dhowells@redhat.com)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
#include <linux/linkage.h>
#include <asm/unistd.h>
###############################################################################
#
# Do a system call from kernel instead of calling sys_execve so we end up with
# proper pt_regs.
#
# int kernel_execve(const char *filename, char *const argv[], char *const envp[])
#
# On entry: GR8/GR9/GR10: arguments to function
# On return: GR8: syscall return.
#
###############################################################################
.globl kernel_execve
.type kernel_execve,@function
kernel_execve:
setlos __NR_execve,gr7
tira gr0,#0
bralr
.size kernel_execve,.-kernel_execve
/* kernel_thread.S: kernel thread creation
*
* Copyright (C) 2003 Red Hat, Inc. All Rights Reserved.
* Written by David Howells (dhowells@redhat.com)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
#include <linux/linkage.h>
#include <linux/kern_levels.h>
#include <asm/unistd.h>
#define CLONE_VM 0x00000100 /* set if VM shared between processes */
.section .rodata
kernel_thread_emsg:
.asciz KERN_ERR "failed to create kernel thread: error=%d\n"
.text
.balign 4
###############################################################################
#
# Create a kernel thread
#
# int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
#
###############################################################################
.globl kernel_thread
.type kernel_thread,@function
kernel_thread:
or.p gr8,gr0,gr4
or gr9,gr0,gr5
# start by forking the current process, but with shared VM
setlos.p #__NR_clone,gr7 ; syscall number
ori gr10,#CLONE_VM,gr8 ; first syscall arg [clone_flags]
sethi.p #0xe4e4,gr9 ; second syscall arg [newsp]
setlo #0xe4e4,gr9
setlos.p #0,gr10 ; third syscall arg [parent_tidptr]
setlos #0,gr11 ; fourth syscall arg [child_tidptr]
tira gr0,#0
setlos.p #4095,gr7
andcc gr8,gr8,gr0,icc0
addcc.p gr8,gr7,gr0,icc1
bnelr icc0,#2
bc icc1,#0,kernel_thread_error
# now invoke the work function
or gr5,gr0,gr8
calll @(gr4,gr0)
# and finally exit the thread
setlos #__NR_exit,gr7 ; syscall number
tira gr0,#0
kernel_thread_error:
subi sp,#8,sp
movsg lr,gr4
sti gr8,@(sp,#0)
sti.p gr4,@(sp,#4)
or gr8,gr0,gr9
sethi.p %hi(kernel_thread_emsg),gr8
setlo %lo(kernel_thread_emsg),gr8