Loading arch/frv/kernel/Makefile +1 −1 Original line number Diff line number Diff line Loading @@ -7,7 +7,7 @@ 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 \ obj-y := $(heads-y) entry.o entry-table.o break.o switch_to.o \ kernel_execve.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 Loading arch/frv/kernel/entry.S +8 −0 Original line number Diff line number Diff line Loading @@ -863,6 +863,14 @@ 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 ################################################################################################### # # Return to user mode is not as complex as all this looks, Loading arch/frv/kernel/frv_ksyms.c +0 −1 Original line number Diff line number Diff line Loading @@ -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); Loading arch/frv/kernel/kernel_thread.Sdeleted 100644 → 0 +0 −77 Original line number Diff line number Diff line /* 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 call printk ldi @(sp,#4),gr4 ldi @(sp,#0),gr8 subi sp,#8,sp jmpl @(gr4,gr0) .size kernel_thread,.-kernel_thread arch/frv/kernel/process.c +23 −21 Original line number Diff line number Diff line Loading @@ -37,6 +37,7 @@ #include "local.h" asmlinkage void ret_from_fork(void); asmlinkage void ret_from_kernel_thread(void); #include <asm/pgalloc.h> Loading Loading @@ -172,29 +173,21 @@ int copy_thread(unsigned long clone_flags, unsigned long usp, unsigned long topstk, struct task_struct *p, struct pt_regs *regs) { struct pt_regs *childregs0, *childregs, *regs0; struct pt_regs *childregs; regs0 = __kernel_frame0_ptr; childregs0 = (struct pt_regs *) childregs = (struct pt_regs *) (task_stack_page(p) + THREAD_SIZE - FRV_FRAME0_SIZE); childregs = childregs0; /* set up the userspace frame (the only place that the USP is stored) */ *childregs0 = *regs0; *childregs = *regs; childregs0->gr8 = 0; childregs0->sp = usp; childregs0->next_frame = NULL; childregs->sp = usp; childregs->next_frame = NULL; /* set up the return kernel frame if called from kernel_thread() */ if (regs != regs0) { childregs--; *childregs = *regs; childregs->sp = (unsigned long) childregs0; childregs->next_frame = childregs0; childregs->gr15 = (unsigned long) task_thread_info(p); childregs->gr29 = (unsigned long) p; } if (unlikely(!user_mode(regs))) p->thread.pc = (unsigned long) ret_from_kernel_thread; else p->thread.pc = (unsigned long) ret_from_fork; p->set_child_tid = p->clear_child_tid = NULL; Loading @@ -203,8 +196,7 @@ int copy_thread(unsigned long clone_flags, p->thread.sp = (unsigned long) childregs; p->thread.fp = 0; p->thread.lr = 0; p->thread.pc = (unsigned long) ret_from_fork; p->thread.frame0 = childregs0; p->thread.frame0 = childregs; /* the new TLS pointer is passed in as arg #5 to sys_clone() */ if (clone_flags & CLONE_SETTLS) Loading Loading @@ -347,3 +339,13 @@ int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpregs) sizeof(current->thread.user->f)); return 1; } int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags) { struct pt_regs regs = { .gr8 = (unsigned long)arg; .gr9 = (unsigned long)fn; .psr = PSR_S; }; return do_fork(flags|CLONE_VM|CLONE_UNTRACED, 0, ®s, 0, NULL, NULL); } Loading
arch/frv/kernel/Makefile +1 −1 Original line number Diff line number Diff line Loading @@ -7,7 +7,7 @@ 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 \ obj-y := $(heads-y) entry.o entry-table.o break.o switch_to.o \ kernel_execve.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 Loading
arch/frv/kernel/entry.S +8 −0 Original line number Diff line number Diff line Loading @@ -863,6 +863,14 @@ 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 ################################################################################################### # # Return to user mode is not as complex as all this looks, Loading
arch/frv/kernel/frv_ksyms.c +0 −1 Original line number Diff line number Diff line Loading @@ -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); Loading
arch/frv/kernel/kernel_thread.Sdeleted 100644 → 0 +0 −77 Original line number Diff line number Diff line /* 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 call printk ldi @(sp,#4),gr4 ldi @(sp,#0),gr8 subi sp,#8,sp jmpl @(gr4,gr0) .size kernel_thread,.-kernel_thread
arch/frv/kernel/process.c +23 −21 Original line number Diff line number Diff line Loading @@ -37,6 +37,7 @@ #include "local.h" asmlinkage void ret_from_fork(void); asmlinkage void ret_from_kernel_thread(void); #include <asm/pgalloc.h> Loading Loading @@ -172,29 +173,21 @@ int copy_thread(unsigned long clone_flags, unsigned long usp, unsigned long topstk, struct task_struct *p, struct pt_regs *regs) { struct pt_regs *childregs0, *childregs, *regs0; struct pt_regs *childregs; regs0 = __kernel_frame0_ptr; childregs0 = (struct pt_regs *) childregs = (struct pt_regs *) (task_stack_page(p) + THREAD_SIZE - FRV_FRAME0_SIZE); childregs = childregs0; /* set up the userspace frame (the only place that the USP is stored) */ *childregs0 = *regs0; *childregs = *regs; childregs0->gr8 = 0; childregs0->sp = usp; childregs0->next_frame = NULL; childregs->sp = usp; childregs->next_frame = NULL; /* set up the return kernel frame if called from kernel_thread() */ if (regs != regs0) { childregs--; *childregs = *regs; childregs->sp = (unsigned long) childregs0; childregs->next_frame = childregs0; childregs->gr15 = (unsigned long) task_thread_info(p); childregs->gr29 = (unsigned long) p; } if (unlikely(!user_mode(regs))) p->thread.pc = (unsigned long) ret_from_kernel_thread; else p->thread.pc = (unsigned long) ret_from_fork; p->set_child_tid = p->clear_child_tid = NULL; Loading @@ -203,8 +196,7 @@ int copy_thread(unsigned long clone_flags, p->thread.sp = (unsigned long) childregs; p->thread.fp = 0; p->thread.lr = 0; p->thread.pc = (unsigned long) ret_from_fork; p->thread.frame0 = childregs0; p->thread.frame0 = childregs; /* the new TLS pointer is passed in as arg #5 to sys_clone() */ if (clone_flags & CLONE_SETTLS) Loading Loading @@ -347,3 +339,13 @@ int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpregs) sizeof(current->thread.user->f)); return 1; } int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags) { struct pt_regs regs = { .gr8 = (unsigned long)arg; .gr9 = (unsigned long)fn; .psr = PSR_S; }; return do_fork(flags|CLONE_VM|CLONE_UNTRACED, 0, ®s, 0, NULL, NULL); }