[PATCH] boot time scheduling w hile atomic fix
Takeharu KATO
kato.takeharu at jp.fujitsu.com
Tue Mar 15 21:24:37 EST 2005
Hi
I've fixed the problem by changing the implementation of
kernel_thread function.
> Mount-cache hash table entries: 512 (order: 0, 4096 bytes)
> scheduling while atomic: swapper/0x00000002/0
> Call trace:
> [c0007620] dump_stack+0x18/0x28
> [c01de704] schedule+0x678/0x67c
> [c0004500] syscall_exit_work+0x108/0x10c
> [c02a97b4] proc_root_init+0x168/0x174
> [ff847288] 0xff847288
> [c02945e8] start_kernel+0x144/0x170
> [00003a30] 0x3a30
As I mentioned before, it was caused by calling kernel_thread function via
trap call.
So, I've replaced the implementation of kernel_thread with function call like as
other architectures.
I tested this patch on PowerPC440GP (ebony evaluation board).
Please apply this patch.
I show the boot log for your information:
-- boot-log
Linux/PPC load: console=ttyS0,9600 nfsroot=192.168.0.1:/opt/fje/devkit/ppc/440/0
Uncompressing Linux...done.
Now booting the kernel
Linux version 2.6.11 (tkato at XXXX) (gcc version 3.4.0 20040331 (prerelease))5
IBM Ebony port (MontaVista Software, Inc. (source at mvista.com))
Built 1 zonelists
Kernel command line: console=ttyS0,9600 nfsroot=192.168.0.1:/opt/fje/devkit/ppc0
PID hash table entries: 1024 (order: 10, 16384 bytes)
Console: colour dummy device 80x25
Dentry cache hash table entries: 32768 (order: 5, 131072 bytes)
Inode-cache hash table entries: 16384 (order: 4, 65536 bytes)
Memory: 126720k available (2064k kernel code, 600k data, 332k init, 0k highmem)
Mount-cache hash table entries: 512 (order: 0, 4096 bytes)
NET: Registered protocol family 16
PCI: Probing PCI hardware
SCSI subsystem initialized
usbcore: registered new driver usbfs
usbcore: registered new driver hub
i8042.c: i8042 controller self test timeout.
Serial: 8250/16550 driver $Revision: 1.90 $ 6 ports, IRQ sharing enabled
ttyS0 at MMIO 0x0 (irq = 0) is a 16550A
ttyS1 at MMIO 0x0 (irq = 1) is a 16550A
io scheduler noop registered
io scheduler anticipatory registered
[snip]
-- boot-log
Regards,
--
Takeharu KATO
Fujitsu Limited
Email:kato.takeharu at jp.fujitsu.com
Signed-off-by: Takeharu KATO <kato.takeharu at jp.fujitsu.com>
diff -Nupr linux-2.6.11/arch/ppc/kernel/misc.S linux-2.6.11-preempt/arch/ppc/kernel/misc.S
--- linux-2.6.11/arch/ppc/kernel/misc.S 2005-03-11 17:26:14.000000000 +0900
+++ linux-2.6.11-preempt/arch/ppc/kernel/misc.S 2005-03-15 17:57:30.000000000 +0900
@@ -1125,36 +1125,23 @@ _GLOBAL(cvt_df)
stfd 0,-4(r5)
blr
#endif
-
/*
- * Create a kernel thread
- * kernel_thread(fn, arg, flags)
+ * void kernel_thread_helper(void)
+ * This gets run with r13 containing the
+ * function to call, and r14 containing
+ * the "args".
+ * These register is set in ``kernel_thread'' function in
+ * arch/ppc/kernel/process.c.
+ * Note:
+ * Registers used for arguments for this function should NOT be caller-saves.
*/
-_GLOBAL(kernel_thread)
+_GLOBAL(kernel_thread_helper)
stwu r1,-16(r1)
- stw r30,8(r1)
- stw r31,12(r1)
- mr r30,r3 /* function */
- mr r31,r4 /* argument */
- ori r3,r5,CLONE_VM /* flags */
- oris r3,r3,CLONE_UNTRACED>>16
- li r4,0 /* new sp (unused) */
- li r0,__NR_clone
- sc
- cmpwi 0,r3,0 /* parent or child? */
- bne 1f /* return if parent */
- li r0,0 /* make top-level stack frame */
- stwu r0,-16(r1)
- mtlr r30 /* fn addr in lr */
- mr r3,r31 /* load arg and call fn */
+ mtlr r13
+ mr r3,r14
blrl
- li r0,__NR_exit /* exit if function returns */
- li r3,0
- sc
-1: lwz r30,8(r1)
- lwz r31,12(r1)
- addi r1,r1,16
- blr
+ bl do_exit
+ /* Never return here */
/*
* This routine is just here to keep GCC happy - sigh...
diff -Nupr linux-2.6.11/arch/ppc/kernel/process.c linux-2.6.11-preempt/arch/ppc/kernel/process.c
--- linux-2.6.11/arch/ppc/kernel/process.c 2005-03-11 17:23:13.000000000 +0900
+++ linux-2.6.11-preempt/arch/ppc/kernel/process.c 2005-03-15 17:57:31.000000000 +0900
@@ -405,6 +405,31 @@ void prepare_to_copy(struct task_struct
#endif /* CONFIG_SPE */
preempt_enable();
}
+/*
+ * Kernel thread relevant functions
+ */
+extern void kernel_thread_helper(void);
+/*
+ * Create a kernel thread
+ */
+long kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
+{
+ struct pt_regs regs;
+
+ memset(®s, 0, sizeof(regs));
+ /* We use r13,14 for arguments for kernel_thread_helper.
+ * Because registers used for arguments for this function
+ * should NOT be caller-saves.
+ */
+ regs.gpr[13] = (unsigned long) fn;
+ regs.gpr[14] = (unsigned long) arg;
+
+ regs.nip = (unsigned long) kernel_thread_helper;
+ regs.msr = MSR_KERNEL;
+
+ /* Ok, create the new process.. */
+ return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, ®s, 0, NULL, NULL);
+}
/*
* Copy a thread..
More information about the Linuxppc-dev
mailing list