m68k: switch to generic sys_execve()/kernel_execve()
The tricky part here is that task_pt_regs() on m68k works *only* for process inside do_signal(). However, we need something much simpler - pt_regs of a process inside do_signal() may be at different offsets from the stack bottom, depending on the way we'd entered the kernel, but for a task inside sys_execve() it *is* at constant offset. Moreover, for a kernel thread about to become a userland process the same location is also fine - setting sp to that will leave the kernel stack pointer at the very bottom of the kernel stack when we finally switch to userland. Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
parent
533e6903be
commit
d878d6dace
|
@ -85,6 +85,8 @@ struct switch_stack {
|
||||||
#define user_mode(regs) (!((regs)->sr & PS_S))
|
#define user_mode(regs) (!((regs)->sr & PS_S))
|
||||||
#define instruction_pointer(regs) ((regs)->pc)
|
#define instruction_pointer(regs) ((regs)->pc)
|
||||||
#define profile_pc(regs) instruction_pointer(regs)
|
#define profile_pc(regs) instruction_pointer(regs)
|
||||||
|
#define current_pt_regs() \
|
||||||
|
(struct pt_regs *)((char *)current_thread_info() + THREAD_SIZE) - 1
|
||||||
|
|
||||||
#define arch_has_single_step() (1)
|
#define arch_has_single_step() (1)
|
||||||
|
|
||||||
|
|
|
@ -382,6 +382,8 @@
|
||||||
#define __ARCH_WANT_SYS_SIGPROCMASK
|
#define __ARCH_WANT_SYS_SIGPROCMASK
|
||||||
#define __ARCH_WANT_SYS_RT_SIGACTION
|
#define __ARCH_WANT_SYS_RT_SIGACTION
|
||||||
#define __ARCH_WANT_SYS_RT_SIGSUSPEND
|
#define __ARCH_WANT_SYS_RT_SIGSUSPEND
|
||||||
|
#define __ARCH_WANT_SYS_EXECVE
|
||||||
|
#define __ARCH_WANT_KERNEL_EXECVE
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* "Conditional" syscalls
|
* "Conditional" syscalls
|
||||||
|
|
|
@ -122,6 +122,11 @@ ENTRY(ret_from_kernel_thread)
|
||||||
movel %d0,(%sp)
|
movel %d0,(%sp)
|
||||||
jra sys_exit
|
jra sys_exit
|
||||||
|
|
||||||
|
ENTRY(ret_from_kernel_execve)
|
||||||
|
movel 4(%sp), %sp
|
||||||
|
GET_CURRENT(%d0)
|
||||||
|
jra ret_from_exception
|
||||||
|
|
||||||
#if defined(CONFIG_COLDFIRE) || !defined(CONFIG_MMU)
|
#if defined(CONFIG_COLDFIRE) || !defined(CONFIG_MMU)
|
||||||
|
|
||||||
#ifdef TRAP_DBG_INTERRUPT
|
#ifdef TRAP_DBG_INTERRUPT
|
||||||
|
|
|
@ -298,26 +298,6 @@ int dump_fpu (struct pt_regs *regs, struct user_m68kfp_struct *fpu)
|
||||||
EXPORT_SYMBOL(dump_fpu);
|
EXPORT_SYMBOL(dump_fpu);
|
||||||
#endif /* CONFIG_FPU */
|
#endif /* CONFIG_FPU */
|
||||||
|
|
||||||
/*
|
|
||||||
* sys_execve() executes a new program.
|
|
||||||
*/
|
|
||||||
asmlinkage int sys_execve(const char __user *name,
|
|
||||||
const char __user *const __user *argv,
|
|
||||||
const char __user *const __user *envp)
|
|
||||||
{
|
|
||||||
int error;
|
|
||||||
char * filename;
|
|
||||||
struct pt_regs *regs = (struct pt_regs *) &name;
|
|
||||||
|
|
||||||
filename = getname(name);
|
|
||||||
error = PTR_ERR(filename);
|
|
||||||
if (IS_ERR(filename))
|
|
||||||
return error;
|
|
||||||
error = do_execve(filename, argv, envp, regs);
|
|
||||||
putname(filename);
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned long get_wchan(struct task_struct *p)
|
unsigned long get_wchan(struct task_struct *p)
|
||||||
{
|
{
|
||||||
unsigned long fp, pc;
|
unsigned long fp, pc;
|
||||||
|
|
|
@ -549,23 +549,6 @@ asmlinkage int sys_getpagesize(void)
|
||||||
return PAGE_SIZE;
|
return PAGE_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* 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,
|
|
||||||
const char *const argv[],
|
|
||||||
const char *const envp[])
|
|
||||||
{
|
|
||||||
register long __res asm ("%d0") = __NR_execve;
|
|
||||||
register long __a asm ("%d1") = (long)(filename);
|
|
||||||
register long __b asm ("%d2") = (long)(argv);
|
|
||||||
register long __c asm ("%d3") = (long)(envp);
|
|
||||||
asm volatile ("trap #0" : "+d" (__res)
|
|
||||||
: "d" (__a), "d" (__b), "d" (__c));
|
|
||||||
return __res;
|
|
||||||
}
|
|
||||||
|
|
||||||
asmlinkage unsigned long sys_get_thread_area(void)
|
asmlinkage unsigned long sys_get_thread_area(void)
|
||||||
{
|
{
|
||||||
return current_thread_info()->tp_value;
|
return current_thread_info()->tp_value;
|
||||||
|
|
Loading…
Reference in New Issue