h8300: generic kernel_thread()
authorAl Viro <viro@zeniv.linux.org.uk>
Wed, 10 Oct 2012 17:17:31 +0000 (13:17 -0400)
committerAl Viro <viro@zeniv.linux.org.uk>
Sun, 14 Oct 2012 23:37:40 +0000 (19:37 -0400)
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
arch/h8300/Kconfig
arch/h8300/include/asm/processor.h
arch/h8300/include/asm/ptrace.h
arch/h8300/kernel/entry.S
arch/h8300/kernel/h8300_ksyms.c
arch/h8300/kernel/process.c

index 98fabd1..4cef8a9 100644 (file)
@@ -8,6 +8,7 @@ config H8300
        select GENERIC_IRQ_SHOW
        select GENERIC_CPU_DEVICES
        select MODULES_USE_ELF_RELA
+       select GENERIC_KERNEL_THREAD
 
 config SYMBOL_PREFIX
        string
index 4c9f6f8..4b0ca49 100644 (file)
@@ -107,8 +107,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..
  */
index d09c440..00502a6 100644 (file)
@@ -60,6 +60,8 @@ struct pt_regs {
 #define user_mode(regs) (!((regs)->ccr & PS_S))
 #define instruction_pointer(regs) ((regs)->pc)
 #define profile_pc(regs) instruction_pointer(regs)
+#define current_pt_regs() ((struct pt_regs *) \
+       (THREAD_SIZE + (unsigned long)current_thread_info()) - 1)
 #endif /* __KERNEL__ */
 #endif /* __ASSEMBLY__ */
 #endif /* _H8300_PTRACE_H */
index ca74316..2cdb49a 100644 (file)
@@ -158,6 +158,7 @@ INTERRUPTS = 128
 .globl SYMBOL_NAME(system_call)
 .globl SYMBOL_NAME(ret_from_exception)
 .globl SYMBOL_NAME(ret_from_fork)
+.globl SYMBOL_NAME(ret_from_kernel_thread)
 .globl SYMBOL_NAME(ret_from_interrupt)
 .globl SYMBOL_NAME(interrupt_redirect_table)
 .globl SYMBOL_NAME(sw_ksp),SYMBOL_NAME(sw_usp)
@@ -330,6 +331,15 @@ SYMBOL_NAME_LABEL(ret_from_fork)
        jsr     @SYMBOL_NAME(schedule_tail)
        jmp     @SYMBOL_NAME(ret_from_exception)
 
+SYMBOL_NAME_LABEL(ret_from_kernel_thread)
+       mov.l   er2,er0
+       jsr     @SYMBOL_NAME(schedule_tail)
+       mov.l   @(LER4:16,sp),er0
+       mov.l   @(LER5:16,sp),er1
+       jsr     @er1
+       sub.l   @er0,@er0
+       jsr     @SYMBOL_NAME(sys_exit)
+
 SYMBOL_NAME_LABEL(resume)
        /*
         * Beware - when entering resume, offset of tss is in d1,
index 6866bd9..53d7c0e 100644 (file)
@@ -33,7 +33,6 @@ EXPORT_SYMBOL(strncmp);
 
 EXPORT_SYMBOL(ip_fast_csum);
 
-EXPORT_SYMBOL(kernel_thread);
 EXPORT_SYMBOL(enable_irq);
 EXPORT_SYMBOL(disable_irq);
 
index e8dc139..e3dfea7 100644 (file)
@@ -47,6 +47,7 @@ void (*pm_power_off)(void) = NULL;
 EXPORT_SYMBOL(pm_power_off);
 
 asmlinkage void ret_from_fork(void);
+asmlinkage void ret_from_kernel_thread(void);
 
 /*
  * The idle loop on an H8/300..
@@ -122,39 +123,6 @@ void show_regs(struct pt_regs * regs)
                printk("\n");
 }
 
-/*
- * Create a kernel thread
- */
-int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
-{
-       long retval;
-       long clone_arg;
-       mm_segment_t fs;
-
-       fs = get_fs();
-       set_fs (KERNEL_DS);
-       clone_arg = flags | CLONE_VM;
-       __asm__("mov.l sp,er3\n\t"
-               "sub.l er2,er2\n\t"
-               "mov.l %2,er1\n\t"
-               "mov.l %1,er0\n\t"
-               "trapa #0\n\t"
-               "cmp.l sp,er3\n\t"
-               "beq 1f\n\t"
-               "mov.l %4,er0\n\t"
-               "mov.l %3,er1\n\t"
-               "jsr @er1\n\t"
-               "mov.l %5,er0\n\t"
-               "trapa #0\n"
-               "1:\n\t"
-               "mov.l er0,%0"
-               :"=r"(retval)
-               :"i"(__NR_clone),"g"(clone_arg),"g"(fn),"g"(arg),"i"(__NR_exit)
-               :"er0","er1","er2","er3");
-       set_fs (fs);
-       return retval;
-}
-
 void flush_thread(void)
 {
 }
@@ -198,6 +166,13 @@ int copy_thread(unsigned long clone_flags,
 
        childregs = (struct pt_regs *) (THREAD_SIZE + task_stack_page(p)) - 1;
 
+       if (unlikely(p->flags & PF_KTHREAD)) {
+               memset(childregs, 0, sizeof(struct pt_regs));
+               childregs->retpc = (unsigned long) ret_from_kernel_thread;
+               childregs->er4 = topstk; /* arg */
+               childregs->er5 = usp; /* fn */
+               p->thread.ksp = (unsigned long)childregs;
+       }
        *childregs = *regs;
        childregs->retpc = (unsigned long) ret_from_fork;
        childregs->er0 = 0;