Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 340308
b: refs/heads/master
c: ddf23e8
h: refs/heads/master
v: v3
  • Loading branch information
Al Viro committed Oct 14, 2012
1 parent f60e450 commit 4f86bb4
Show file tree
Hide file tree
Showing 11 changed files with 109 additions and 48 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 8eae10e86c57b6be5e4842b34ea541efbca28bf8
refs/heads/master: ddf23e87a804cbf6fa3818076b33fe023cce09fd
2 changes: 0 additions & 2 deletions trunk/arch/m32r/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,6 @@ config M32R
select GENERIC_ATOMIC64
select ARCH_USES_GETTIMEOFFSET
select MODULES_USE_ELF_RELA
select GENERIC_KERNEL_THREAD
select GENERIC_KERNEL_EXECVE

config SBUS
bool
Expand Down
5 changes: 5 additions & 0 deletions trunk/arch/m32r/include/asm/processor.h
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,11 @@ struct mm_struct;
/* Free all resources held by a thread. */
extern void release_thread(struct task_struct *);

/*
* create a kernel thread without removing it from tasklists
*/
extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);

/* Copy and release all segment info associated with a VM */
extern void copy_segments(struct task_struct *p, struct mm_struct * mm);
extern void release_segments(struct mm_struct * mm);
Expand Down
2 changes: 0 additions & 2 deletions trunk/arch/m32r/include/asm/ptrace.h
Original file line number Diff line number Diff line change
Expand Up @@ -139,8 +139,6 @@ extern void withdraw_debug_trap(struct pt_regs *regs);

#define task_pt_regs(task) \
((struct pt_regs *)(task_stack_page(task) + THREAD_SIZE) - 1)
#define current_pt_regs() ((struct pt_regs *) \
((unsigned long)current_thread_info() + THREAD_SIZE) - 1)

#endif /* __KERNEL */

Expand Down
1 change: 0 additions & 1 deletion trunk/arch/m32r/include/asm/unistd.h
Original file line number Diff line number Diff line change
Expand Up @@ -352,7 +352,6 @@
#define __ARCH_WANT_SYS_OLDUMOUNT
#define __ARCH_WANT_SYS_RT_SIGACTION
#define __ARCH_WANT_SYS_RT_SIGSUSPEND
#define __ARCH_WANT_SYS_EXECVE

#define __IGNORE_lchown
#define __IGNORE_setuid
Expand Down
9 changes: 0 additions & 9 deletions trunk/arch/m32r/kernel/entry.S
Original file line number Diff line number Diff line change
Expand Up @@ -125,15 +125,6 @@
and \reg, sp
.endm

ENTRY(ret_from_kernel_thread)
pop r0
bl schedule_tail
GET_THREAD_INFO(r8)
ld r0, R0(r8)
ld r1, R1(r8)
jl r1
bra syscall_exit

ENTRY(ret_from_fork)
pop r0
bl schedule_tail
Expand Down
106 changes: 80 additions & 26 deletions trunk/arch/m32r/kernel/process.c
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,41 @@ void show_regs(struct pt_regs * regs)
#endif
}

/*
* Create a kernel thread
*/

/*
* This is the mechanism for creating a new kernel thread.
*
* NOTE! Only a kernel-only process(ie the swapper or direct descendants
* who haven't done an "execve()") should use this: it will work within
* a system call from a "real" process, but the process memory space will
* not be free'd until both the parent and the child have exited.
*/
static void kernel_thread_helper(void *nouse, int (*fn)(void *), void *arg)
{
fn(arg);
do_exit(-1);
}

int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
{
struct pt_regs regs;

memset(&regs, 0, sizeof (regs));
regs.r1 = (unsigned long)fn;
regs.r2 = (unsigned long)arg;

regs.bpc = (unsigned long)kernel_thread_helper;

regs.psw = M32R_PSW_BIE;

/* Ok, create the new process. */
return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, &regs, 0, NULL,
NULL);
}

/*
* Free current thread data structures etc..
*/
Expand Down Expand Up @@ -192,49 +227,44 @@ int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu)
}

int copy_thread(unsigned long clone_flags, unsigned long spu,
unsigned long arg, struct task_struct *tsk, struct pt_regs *regs)
unsigned long unused, struct task_struct *tsk, struct pt_regs *regs)
{
struct pt_regs *childregs = task_pt_regs(tsk);
extern void ret_from_fork(void);
extern void ret_from_kernel_thread(void);

if (unlikely(tsk->flags & PF_KTHREAD)) {
memset(childregs, 0, sizeof(struct pt_regs));
childregs->psw = M32R_PSW_BIE;
childregs->r1 = spu; /* fn */
childregs->r0 = arg;
tsk->thread.lr = (unsigned long)ret_from_kernel_thread;
} else {
/* Copy registers */
*childregs = *regs;
childregs->spu = spu;
childregs->r0 = 0; /* Child gets zero as return value */
tsk->thread.lr = (unsigned long)ret_from_fork;
}

/* Copy registers */
*childregs = *regs;

childregs->spu = spu;
childregs->r0 = 0; /* Child gets zero as return value */
regs->r0 = tsk->pid;
tsk->thread.sp = (unsigned long)childregs;
tsk->thread.lr = (unsigned long)ret_from_fork;

return 0;
}

asmlinkage int sys_fork(void)
asmlinkage int sys_fork(unsigned long r0, unsigned long r1, unsigned long r2,
unsigned long r3, unsigned long r4, unsigned long r5, unsigned long r6,
struct pt_regs regs)
{
#ifdef CONFIG_MMU
struct pt_regs *regs = current_pt_regs();
return do_fork(SIGCHLD, regs->spu, regs, 0, NULL, NULL);
return do_fork(SIGCHLD, regs.spu, &regs, 0, NULL, NULL);
#else
return -EINVAL;
#endif /* CONFIG_MMU */
}

asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp,
unsigned long parent_tidptr,
unsigned long child_tidptr)
unsigned long child_tidptr,
unsigned long r4, unsigned long r5, unsigned long r6,
struct pt_regs regs)
{
struct pt_regs *regs = current_pt_regs();
if (!newsp)
newsp = regs->spu;
newsp = regs.spu;

return do_fork(clone_flags, newsp, regs, 0,
return do_fork(clone_flags, newsp, &regs, 0,
(int __user *)parent_tidptr, (int __user *)child_tidptr);
}

Expand All @@ -248,13 +278,37 @@ asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp,
* do not have enough call-clobbered registers to hold all
* the information you need.
*/
asmlinkage int sys_vfork(void)
asmlinkage int sys_vfork(unsigned long r0, unsigned long r1, unsigned long r2,
unsigned long r3, unsigned long r4, unsigned long r5, unsigned long r6,
struct pt_regs regs)
{
struct pt_regs *regs = current_pt_regs();
return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->spu, regs, 0,
return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs.spu, &regs, 0,
NULL, NULL);
}

/*
* sys_execve() executes a new program.
*/
asmlinkage int sys_execve(const char __user *ufilename,
const char __user *const __user *uargv,
const char __user *const __user *uenvp,
unsigned long r3, unsigned long r4, unsigned long r5,
unsigned long r6, struct pt_regs regs)
{
int error;
struct filename *filename;

filename = getname(ufilename);
error = PTR_ERR(filename);
if (IS_ERR(filename))
goto out;

error = do_execve(filename->name, uargv, uenvp, &regs);
putname(filename);
out:
return error;
}

/*
* These bracket the sleeping functions..
*/
Expand Down
21 changes: 21 additions & 0 deletions trunk/arch/m32r/kernel/sys_m32r.c
Original file line number Diff line number Diff line change
Expand Up @@ -88,3 +88,24 @@ asmlinkage int sys_cachectl(char *addr, int nbytes, int op)
/* Not implemented yet. */
return -ENOSYS;
}

/*
* 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 __scno __asm__ ("r7") = __NR_execve;
register long __arg3 __asm__ ("r2") = (long)(envp);
register long __arg2 __asm__ ("r1") = (long)(argv);
register long __res __asm__ ("r0") = (long)(filename);
__asm__ __volatile__ (
"trap #" SYSCALL_VECTOR "|| nop"
: "=r" (__res)
: "r" (__scno), "0" (__res), "r" (__arg2),
"r" (__arg3)
: "memory");
return __res;
}
1 change: 1 addition & 0 deletions trunk/arch/mn10300/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ config MN10300
select HAVE_NMI_WATCHDOG if MN10300_WD_TIMER
select GENERIC_CLOCKEVENTS
select GENERIC_KERNEL_THREAD
select GENERIC_KERNEL_EXECVE
select MODULES_USE_ELF_RELA

config AM33_2
Expand Down
1 change: 0 additions & 1 deletion trunk/arch/mn10300/include/asm/unistd.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@
#define __ARCH_WANT_SYS_RT_SIGACTION
#define __ARCH_WANT_SYS_RT_SIGSUSPEND
#define __ARCH_WANT_SYS_EXECVE
#define __ARCH_WANT_KERNEL_EXECVE

/*
* "Conditional" syscalls
Expand Down
7 changes: 1 addition & 6 deletions trunk/arch/mn10300/kernel/entry.S
Original file line number Diff line number Diff line change
Expand Up @@ -60,13 +60,8 @@ ENTRY(ret_from_kernel_thread)
mov (REG_D0,fp),d0
mov (REG_A0,fp),a0
calls (a0)
jmp sys_exit

ENTRY(ret_from_kernel_execve)
add -12,d0 /* pt_regs -> frame */
mov d0,sp
GET_THREAD_INFO a2
clr d0
mov d0,(REG_D0,fp)
jmp syscall_exit

###############################################################################
Expand Down

0 comments on commit 4f86bb4

Please sign in to comment.