|
From: Paul M. <le...@us...> - 2006-08-09 02:33:43
|
Update of /cvsroot/linuxsh/linux/arch/sh/kernel In directory sc8-pr-cvs6.sourceforge.net:/tmp/cvs-serv6106/arch/sh/kernel Modified Files: entry.S head.S irq.c traps.c vmlinux.lds.S Log Message: Add support for 4K stacks. Index: entry.S =================================================================== RCS file: /cvsroot/linuxsh/linux/arch/sh/kernel/entry.S,v retrieving revision 1.48 retrieving revision 1.49 diff -u -d -r1.48 -r1.49 --- entry.S 31 Jul 2006 01:21:08 -0000 1.48 +++ entry.S 9 Aug 2006 02:33:40 -0000 1.49 @@ -717,8 +717,8 @@ bt/s 1f ! It's a kernel to kernel transition. mov r15, k0 ! save original stack to k0 /* User space to kernel */ - mov #0x20, k1 - shll8 k1 ! k1 := 8192 (== THREAD_SIZE) + mov #(THREAD_SIZE >> 8), k1 + shll8 k1 ! k1 := THREAD_SIZE add current, k1 mov k1, r15 ! change to kernel stack ! Index: head.S =================================================================== RCS file: /cvsroot/linuxsh/linux/arch/sh/kernel/head.S,v retrieving revision 1.10 retrieving revision 1.11 diff -u -d -r1.10 -r1.11 --- head.S 8 Aug 2006 03:07:13 -0000 1.10 +++ head.S 9 Aug 2006 02:33:40 -0000 1.11 @@ -12,7 +12,6 @@ */ #include <linux/linkage.h> #include <asm/thread_info.h> -#include <asm/page.h> #ifdef CONFIG_CPU_SH4A #define SYNCO() synco @@ -69,8 +68,8 @@ ! mov.l 2f, r0 mov r0, r15 ! Set initial r15 (stack pointer) - mov #0x20, r1 ! - shll8 r1 ! r1 = 8192 + mov #(THREAD_SIZE >> 8), r1 + shll8 r1 ! r1 = THREAD_SIZE sub r1, r0 ! ldc r0, r7_bank ! ... and initial thread_info Index: irq.c =================================================================== RCS file: /cvsroot/linuxsh/linux/arch/sh/kernel/irq.c,v retrieving revision 1.29 retrieving revision 1.30 diff -u -d -r1.29 -r1.30 --- irq.c 8 Aug 2006 03:07:13 -0000 1.29 +++ irq.c 9 Aug 2006 02:33:40 -0000 1.30 @@ -1,5 +1,4 @@ -/* $Id$ - * +/* * linux/arch/sh/kernel/irq.c * * Copyright (C) 1992, 1998 Linus Torvalds, Ingo Molnar @@ -7,13 +6,15 @@ * * SuperH version: Copyright (C) 1999 Niibe Yutaka */ - #include <linux/irq.h> #include <linux/interrupt.h> +#include <linux/module.h> #include <linux/kernel_stat.h> #include <linux/seq_file.h> #include <asm/irq.h> #include <asm/processor.h> +#include <asm/uaccess.h> +#include <asm/thread_info.h> #include <asm/cpu/mmu_context.h> /* @@ -60,11 +61,27 @@ } #endif +#ifdef CONFIG_4KSTACKS +/* + * per-CPU IRQ handling contexts (thread information and stack) + */ +union irq_ctx { + struct thread_info tinfo; + u32 stack[THREAD_SIZE/sizeof(u32)]; +}; + +static union irq_ctx *hardirq_ctx[NR_CPUS]; +static union irq_ctx *softirq_ctx[NR_CPUS]; +#endif + asmlinkage int do_IRQ(unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7, struct pt_regs regs) { int irq = r4; +#ifdef CONFIG_4KSTACKS + union irq_ctx *curctx, *irqctx; +#endif irq_enter(); @@ -102,7 +119,135 @@ #endif irq = irq_demux(irq); - __do_IRQ(irq, ®s); + +#ifdef CONFIG_4KSTACKS + curctx = (union irq_ctx *)current_thread_info(); + irqctx = hardirq_ctx[smp_processor_id()]; + + /* + * this is where we switch to the IRQ stack. However, if we are + * already using the IRQ stack (because we interrupted a hardirq + * handler) we can't do that and just have to keep using the + * current stack (which is the irq stack already after all) + */ + if (curctx != irqctx) { + u32 *isp; + + isp = (u32 *)((char *)irqctx + sizeof(*irqctx)); + irqctx->tinfo.task = curctx->tinfo.task; + irqctx->tinfo.previous_sp = current_stack_pointer; + + __asm__ __volatile__ ( + "mov %0, r4 \n" + "mov %1, r5 \n" + "mov r15, r9 \n" + "jsr @%2 \n" + /* swith to the irq stack */ + " mov %3, r15 \n" + /* restore the stack (ring zero) */ + "mov r9, r15 \n" + : /* no outputs */ + : "r" (irq), "r" (®s), "r" (__do_IRQ), "r" (isp) + /* XXX: A somewhat excessive clobber list? -PFM */ + : "memory", "r0", "r1", "r2", "r3", "r4", + "r5", "r6", "r7", "r8", "t", "pr" + ); + } else +#endif + __do_IRQ(irq, ®s); + irq_exit(); + return 1; } + +#ifdef CONFIG_4KSTACKS +/* + * These should really be __section__(".bss.page_aligned") as well, but + * gcc's 3.0 and earlier don't handle that correctly. + */ +static char softirq_stack[NR_CPUS * THREAD_SIZE] + __attribute__((__aligned__(THREAD_SIZE))); + +static char hardirq_stack[NR_CPUS * THREAD_SIZE] + __attribute__((__aligned__(THREAD_SIZE))); + +/* + * allocate per-cpu stacks for hardirq and for softirq processing + */ +void irq_ctx_init(int cpu) +{ + union irq_ctx *irqctx; + + if (hardirq_ctx[cpu]) + return; + + irqctx = (union irq_ctx *)&hardirq_stack[cpu * THREAD_SIZE]; + irqctx->tinfo.task = NULL; + irqctx->tinfo.exec_domain = NULL; + irqctx->tinfo.cpu = cpu; + irqctx->tinfo.preempt_count = HARDIRQ_OFFSET; + irqctx->tinfo.addr_limit = MAKE_MM_SEG(0); + + hardirq_ctx[cpu] = irqctx; + + irqctx = (union irq_ctx *)&softirq_stack[cpu * THREAD_SIZE]; + irqctx->tinfo.task = NULL; + irqctx->tinfo.exec_domain = NULL; + irqctx->tinfo.cpu = cpu; + irqctx->tinfo.preempt_count = SOFTIRQ_OFFSET; + irqctx->tinfo.addr_limit = MAKE_MM_SEG(0); + + softirq_ctx[cpu] = irqctx; + + printk("CPU %u irqstacks, hard=%p soft=%p\n", + cpu, hardirq_ctx[cpu], softirq_ctx[cpu]); +} + +void irq_ctx_exit(int cpu) +{ + hardirq_ctx[cpu] = NULL; +} + +extern asmlinkage void __do_softirq(void); + +asmlinkage void do_softirq(void) +{ + unsigned long flags; + struct thread_info *curctx; + union irq_ctx *irqctx; + u32 *isp; + + if (in_interrupt()) + return; + + local_irq_save(flags); + + if (local_softirq_pending()) { + curctx = current_thread_info(); + irqctx = softirq_ctx[smp_processor_id()]; + irqctx->tinfo.task = curctx->task; + irqctx->tinfo.previous_sp = current_stack_pointer; + + /* build the stack frame on the softirq stack */ + isp = (u32 *)((char *)irqctx + sizeof(*irqctx)); + + __asm__ __volatile__ ( + "mov r15, r9 \n" + "jsr @%0 \n" + /* switch to the softirq stack */ + " mov %1, r15 \n" + /* restore the thread stack */ + "mov r9, r15 \n" + : /* no outputs */ + : "r" (__do_softirq), "r" (isp) + /* XXX: A somewhat excessive clobber list? -PFM */ + : "memory", "r0", "r1", "r2", "r3", "r4", + "r5", "r6", "r7", "r8", "r9", "r15", "t", "pr" + ); + } + + local_irq_restore(flags); +} +EXPORT_SYMBOL(do_softirq); +#endif Index: traps.c =================================================================== RCS file: /cvsroot/linuxsh/linux/arch/sh/kernel/traps.c,v retrieving revision 1.21 retrieving revision 1.22 diff -u -d -r1.21 -r1.22 --- traps.c 12 Jul 2006 10:35:55 -0000 1.21 +++ traps.c 9 Aug 2006 02:33:40 -0000 1.22 @@ -742,20 +742,12 @@ unsigned long module_end = VMALLOC_END; int i = 1; - if (tsk && !sp) { + if (!tsk) + tsk = current; + if (tsk == current) + sp = (unsigned long *)current_stack_pointer; + else sp = (unsigned long *)tsk->thread.sp; - } - - if (!sp) { - __asm__ __volatile__ ( - "mov r15, %0\n\t" - "stc r7_bank, %1\n\t" - : "=r" (module_start), - "=r" (module_end) - ); - - sp = (unsigned long *)module_start; - } stack = sp; Index: vmlinux.lds.S =================================================================== RCS file: /cvsroot/linuxsh/linux/arch/sh/kernel/vmlinux.lds.S,v retrieving revision 1.8 retrieving revision 1.9 diff -u -d -r1.8 -r1.9 --- vmlinux.lds.S 8 Aug 2006 03:07:13 -0000 1.8 +++ vmlinux.lds.S 9 Aug 2006 02:33:40 -0000 1.9 @@ -4,7 +4,6 @@ */ #include <linux/config.h> #include <asm/thread_info.h> -#include <asm/page.h> #include <asm-generic/vmlinux.lds.h> #ifdef CONFIG_CPU_LITTLE_ENDIAN |