Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 340299
b: refs/heads/master
c: ee1e17c
h: refs/heads/master
i:
  340297: 3358e3b
  340295: 177e923
v: v3
  • Loading branch information
Al Viro committed Oct 15, 2012
1 parent 501f8d4 commit 0685dda
Show file tree
Hide file tree
Showing 15 changed files with 140 additions and 140 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: 5fd0b580a9fda554eae27fff4953e6622bd792d7
refs/heads/master: ee1e17c69eb3c843d283eb3fbed1616ed9a122eb
2 changes: 0 additions & 2 deletions trunk/arch/avr32/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@ config AVR32
select GENERIC_CLOCKEVENTS
select HAVE_MOD_ARCH_SPECIFIC
select MODULES_USE_ELF_RELA
select GENERIC_KERNEL_THREAD
select GENERIC_KERNEL_EXECVE
help
AVR32 is a high-performance 32-bit RISC microprocessor core,
designed for cost-sensitive embedded applications, with particular
Expand Down
3 changes: 3 additions & 0 deletions trunk/arch/avr32/include/asm/processor.h
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,9 @@ struct task_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);

/* Return saved PC of a blocked thread */
#define thread_saved_pc(tsk) ((tsk)->thread.cpu_context.pc)

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

/*
* "Conditional" syscalls
Expand Down
2 changes: 1 addition & 1 deletion trunk/arch/avr32/kernel/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ extra-y := head.o vmlinux.lds
obj-$(CONFIG_SUBARCH_AVR32B) += entry-avr32b.o
obj-y += syscall_table.o syscall-stubs.o irq.o
obj-y += setup.o traps.o ocd.o ptrace.o
obj-y += signal.o process.o time.o
obj-y += signal.o sys_avr32.o process.o time.o
obj-y += switch_to.o cpu.o
obj-$(CONFIG_MODULES) += module.o avr32_ksyms.o
obj-$(CONFIG_KPROBES) += kprobes.o
Expand Down
14 changes: 6 additions & 8 deletions trunk/arch/avr32/kernel/entry-avr32b.S
Original file line number Diff line number Diff line change
Expand Up @@ -251,15 +251,13 @@ syscall_badsys:
.global ret_from_fork
ret_from_fork:
call schedule_tail
mov r12, 0
rjmp syscall_return

.global ret_from_kernel_thread
ret_from_kernel_thread:
call schedule_tail
mov r12, r0
mov lr, r2 /* syscall_return */
mov pc, r1
/* check for syscall tracing */
get_thread_info r0
ld.w r1, r0[TI_flags]
andl r1, _TIF_ALLWORK_MASK, COH
brne syscall_exit_work
rjmp syscall_exit_cont

syscall_trace_enter:
pushm r8-r12
Expand Down
88 changes: 71 additions & 17 deletions trunk/arch/avr32/kernel/process.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,44 @@ void machine_restart(char *cmd)
while (1) ;
}

/*
* PC is actually discarded when returning from a system call -- the
* return address must be stored in LR. This function will make sure
* LR points to do_exit before starting the thread.
*
* Also, when returning from fork(), r12 is 0, so we must copy the
* argument as well.
*
* r0 : The argument to the main thread function
* r1 : The address of do_exit
* r2 : The address of the main thread function
*/
asmlinkage extern void kernel_thread_helper(void);
__asm__(" .type kernel_thread_helper, @function\n"
"kernel_thread_helper:\n"
" mov r12, r0\n"
" mov lr, r2\n"
" mov pc, r1\n"
" .size kernel_thread_helper, . - kernel_thread_helper");

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

memset(&regs, 0, sizeof(regs));

regs.r0 = (unsigned long)arg;
regs.r1 = (unsigned long)fn;
regs.r2 = (unsigned long)do_exit;
regs.lr = (unsigned long)kernel_thread_helper;
regs.pc = (unsigned long)kernel_thread_helper;
regs.sr = MODE_SUPERVISOR;

return do_fork(flags | CLONE_VM | CLONE_UNTRACED,
0, &regs, 0, NULL, NULL);
}
EXPORT_SYMBOL(kernel_thread);

/*
* Free current thread data structures etc
*/
Expand Down Expand Up @@ -294,31 +332,26 @@ int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu)
}

asmlinkage void ret_from_fork(void);
asmlinkage void ret_from_kernel_thread(void);
asmlinkage void syscall_return(void);

int copy_thread(unsigned long clone_flags, unsigned long usp,
unsigned long arg,
unsigned long unused,
struct task_struct *p, struct pt_regs *regs)
{
struct pt_regs *childregs = task_pt_regs(p);

if (unlikely(!regs)) {
memset(childregs, 0, sizeof(struct pt_regs));
p->thread.cpu_context.r0 = arg;
p->thread.cpu_context.r1 = usp; /* fn */
p->thread.cpu_context.r2 = syscall_return;
p->thread.cpu_context.pc = (unsigned long)ret_from_kernel_thread;
childregs->sr = MODE_SUPERVISOR;
} else {
*childregs = *regs;
struct pt_regs *childregs;

childregs = ((struct pt_regs *)(THREAD_SIZE + (unsigned long)task_stack_page(p))) - 1;
*childregs = *regs;

if (user_mode(regs))
childregs->sp = usp;
childregs->r12 = 0; /* Set return value for child */
p->thread.cpu_context.pc = (unsigned long)ret_from_fork;
}
else
childregs->sp = (unsigned long)task_stack_page(p) + THREAD_SIZE;

childregs->r12 = 0; /* Set return value for child */

p->thread.cpu_context.sr = MODE_SUPERVISOR | SR_GM;
p->thread.cpu_context.ksp = (unsigned long)childregs;
p->thread.cpu_context.pc = (unsigned long)ret_from_fork;

clear_tsk_thread_flag(p, TIF_DEBUG);
if ((clone_flags & CLONE_PTRACE) && test_thread_flag(TIF_DEBUG))
Expand Down Expand Up @@ -349,6 +382,27 @@ asmlinkage int sys_vfork(struct pt_regs *regs)
0, NULL, NULL);
}

asmlinkage int sys_execve(const char __user *ufilename,
const char __user *const __user *uargv,
const char __user *const __user *uenvp,
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;
}


/*
* This function is supposed to answer the question "who called
* schedule()?"
Expand Down
24 changes: 24 additions & 0 deletions trunk/arch/avr32/kernel/sys_avr32.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*
* Copyright (C) 2004-2006 Atmel Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/unistd.h>

int kernel_execve(const char *file,
const char *const *argv,
const char *const *envp)
{
register long scno asm("r8") = __NR_execve;
register long sc1 asm("r12") = (long)file;
register long sc2 asm("r11") = (long)argv;
register long sc3 asm("r10") = (long)envp;

asm volatile("scall"
: "=r"(sc1)
: "r"(scno), "0"(sc1), "r"(sc2), "r"(sc3)
: "cc", "memory");
return sc1;
}
6 changes: 6 additions & 0 deletions trunk/arch/avr32/kernel/syscall-stubs.S
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,12 @@ __sys_vfork:
mov r12, sp
rjmp sys_vfork

.global __sys_execve
.type __sys_execve,@function
__sys_execve:
mov r9, sp
rjmp sys_execve

.global __sys_mmap2
.type __sys_mmap2,@function
__sys_mmap2:
Expand Down
2 changes: 1 addition & 1 deletion trunk/arch/avr32/kernel/syscall_table.S
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ sys_call_table:
.long sys_creat
.long sys_link
.long sys_unlink /* 10 */
.long sys_execve
.long __sys_execve
.long sys_chdir
.long sys_time
.long sys_mknod
Expand Down
2 changes: 2 additions & 0 deletions trunk/arch/blackfin/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ config BLACKFIN
select ARCH_USES_GETTIMEOFFSET if !GENERIC_CLOCKEVENTS
select HAVE_MOD_ARCH_SPECIFIC
select MODULES_USE_ELF_RELA
select GENERIC_KERNEL_THREAD
select GENERIC_KERNEL_EXECVE

config GENERIC_CSUM
def_bool y
Expand Down
2 changes: 0 additions & 2 deletions trunk/arch/blackfin/include/asm/processor.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,6 @@ static inline void release_thread(struct task_struct *dead_task)
{
}

extern int kernel_thread(int (*fn) (void *), void *arg, unsigned long flags);

/*
* Free current thread data structures etc..
*/
Expand Down
22 changes: 8 additions & 14 deletions trunk/arch/blackfin/kernel/entry.S
Original file line number Diff line number Diff line change
Expand Up @@ -46,22 +46,16 @@ ENTRY(_ret_from_fork)
SP += -12;
pseudo_long_call _schedule_tail, p5;
SP += 12;
r0 = [sp + PT_IPEND];
cc = bittst(r0,1);
if cc jump .Lin_kernel;
p1 = [sp++];
r0 = [sp++];
cc = p1 == 0;
if cc jump .Lfork;
sp += -12;
call (p1);
sp += 12;
.Lfork:
RESTORE_CONTEXT
rti;
.Lin_kernel:
bitclr(r0,1);
[sp + PT_IPEND] = r0;
/* do a 'fake' RTI by jumping to [RETI]
* to avoid clearing supervisor mode in child
*/
r0 = [sp + PT_PC];
[sp + PT_P0] = r0;

RESTORE_ALL_SYS
jump (p0);
ENDPROC(_ret_from_fork)

ENTRY(_sys_vfork)
Expand Down
55 changes: 17 additions & 38 deletions trunk/arch/blackfin/kernel/process.c
Original file line number Diff line number Diff line change
Expand Up @@ -101,40 +101,6 @@ void cpu_idle(void)
}
}

/*
* This gets run with P1 containing the
* function to call, and R1 containing
* the "args". Note P0 is clobbered on the way here.
*/
void kernel_thread_helper(void);
__asm__(".section .text\n"
".align 4\n"
"_kernel_thread_helper:\n\t"
"\tsp += -12;\n\t"
"\tr0 = r1;\n\t" "\tcall (p1);\n\t" "\tcall _do_exit;\n" ".previous");

/*
* Create a kernel thread.
*/
pid_t kernel_thread(int (*fn) (void *), void *arg, unsigned long flags)
{
struct pt_regs regs;

memset(&regs, 0, sizeof(regs));

regs.r1 = (unsigned long)arg;
regs.p1 = (unsigned long)fn;
regs.pc = (unsigned long)kernel_thread_helper;
regs.orig_p0 = -1;
/* Set bit 2 to tell ret_from_fork we should be returning to kernel
mode. */
regs.ipend = 0x8002;
__asm__ __volatile__("%0 = syscfg;":"=da"(regs.syscfg):);
return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, &regs, 0, NULL,
NULL);
}
EXPORT_SYMBOL(kernel_thread);

/*
* Do necessary setup to start up a newly executed thread.
*
Expand Down Expand Up @@ -193,13 +159,26 @@ copy_thread(unsigned long clone_flags,
struct task_struct *p, struct pt_regs *regs)
{
struct pt_regs *childregs;
unsigned long *v;

childregs = (struct pt_regs *) (task_stack_page(p) + THREAD_SIZE) - 1;
*childregs = *regs;
childregs->r0 = 0;
v = ((unsigned long *)childregs) - 2;
if (unlikely(!regs)) {
memset(childregs, 0, sizeof(struct pt_regs));
v[0] = usp;
v[1] = topstk;
childregs->orig_p0 = -1;
childregs->ipend = 0x8000;
__asm__ __volatile__("%0 = syscfg;":"=da"(childregs->syscfg):);
p->thread.usp = 0;
} else {
*childregs = *regs;
childregs->r0 = 0;
p->thread.usp = usp;
v[0] = v[1] = 0;
}

p->thread.usp = usp;
p->thread.ksp = (unsigned long)childregs;
p->thread.ksp = (unsigned long)v;
p->thread.pc = (unsigned long)ret_from_fork;

return 0;
Expand Down
Loading

0 comments on commit 0685dda

Please sign in to comment.