diff options
| -rw-r--r-- | arch/sh/Kconfig.debug | 10 | ||||
| -rw-r--r-- | arch/sh/kernel/cpu/irq/ipr.c | 2 | ||||
| -rw-r--r-- | arch/sh/kernel/entry.S | 4 | ||||
| -rw-r--r-- | arch/sh/kernel/head.S | 5 | ||||
| -rw-r--r-- | arch/sh/kernel/irq.c | 153 | ||||
| -rw-r--r-- | arch/sh/kernel/traps.c | 18 | ||||
| -rw-r--r-- | arch/sh/kernel/vmlinux.lds.S | 1 | ||||
| -rw-r--r-- | include/asm-sh/irq.h | 9 | ||||
| -rw-r--r-- | include/asm-sh/thread_info.h | 12 | 
9 files changed, 190 insertions, 24 deletions
| diff --git a/arch/sh/Kconfig.debug b/arch/sh/Kconfig.debug index f0188e626be0..48479e014dac 100644 --- a/arch/sh/Kconfig.debug +++ b/arch/sh/Kconfig.debug | |||
| @@ -46,6 +46,16 @@ config DEBUG_STACK_USAGE | |||
| 46 | 46 | ||
| 47 | This option will slow down process creation somewhat. | 47 | This option will slow down process creation somewhat. | 
| 48 | 48 | ||
| 49 | config 4KSTACKS | ||
| 50 | bool "Use 4Kb for kernel stacks instead of 8Kb" | ||
| 51 | depends on DEBUG_KERNEL | ||
| 52 | help | ||
| 53 | If you say Y here the kernel will use a 4Kb stacksize for the | ||
| 54 | kernel stack attached to each process/thread. This facilitates | ||
| 55 | running more threads on a system and also reduces the pressure | ||
| 56 | on the VM subsystem for higher order allocations. This option | ||
| 57 | will also use IRQ stacks to compensate for the reduced stackspace. | ||
| 58 | |||
| 49 | config KGDB | 59 | config KGDB | 
| 50 | bool "Include KGDB kernel debugger" | 60 | bool "Include KGDB kernel debugger" | 
| 51 | select FRAME_POINTER | 61 | select FRAME_POINTER | 
| diff --git a/arch/sh/kernel/cpu/irq/ipr.c b/arch/sh/kernel/cpu/irq/ipr.c index 4c4fd4118d1a..f785822cd5de 100644 --- a/arch/sh/kernel/cpu/irq/ipr.c +++ b/arch/sh/kernel/cpu/irq/ipr.c | |||
| @@ -190,6 +190,8 @@ void __init init_IRQ(void) | |||
| 190 | /* Perform the machine specific initialisation */ | 190 | /* Perform the machine specific initialisation */ | 
| 191 | if (sh_mv.mv_init_irq != NULL) | 191 | if (sh_mv.mv_init_irq != NULL) | 
| 192 | sh_mv.mv_init_irq(); | 192 | sh_mv.mv_init_irq(); | 
| 193 | |||
| 194 | irq_ctx_init(smp_processor_id()); | ||
| 193 | } | 195 | } | 
| 194 | 196 | ||
| 195 | #if !defined(CONFIG_CPU_HAS_PINT_IRQ) | 197 | #if !defined(CONFIG_CPU_HAS_PINT_IRQ) | 
| diff --git a/arch/sh/kernel/entry.S b/arch/sh/kernel/entry.S index fd5fe2349f20..fe8221855b28 100644 --- a/arch/sh/kernel/entry.S +++ b/arch/sh/kernel/entry.S | |||
| @@ -716,8 +716,8 @@ ENTRY(handle_exception) | |||
| 716 | bt/s 1f ! It's a kernel to kernel transition. | 716 | bt/s 1f ! It's a kernel to kernel transition. | 
| 717 | mov r15, k0 ! save original stack to k0 | 717 | mov r15, k0 ! save original stack to k0 | 
| 718 | /* User space to kernel */ | 718 | /* User space to kernel */ | 
| 719 | mov #0x20, k1 | 719 | mov #(THREAD_SIZE >> 8), k1 | 
| 720 | shll8 k1 ! k1 := 8192 (== THREAD_SIZE) | 720 | shll8 k1 ! k1 := THREAD_SIZE | 
| 721 | add current, k1 | 721 | add current, k1 | 
| 722 | mov k1, r15 ! change to kernel stack | 722 | mov k1, r15 ! change to kernel stack | 
| 723 | ! | 723 | ! | 
| diff --git a/arch/sh/kernel/head.S b/arch/sh/kernel/head.S index 3e7d00b7985a..f5f53d14f245 100644 --- a/arch/sh/kernel/head.S +++ b/arch/sh/kernel/head.S | |||
| @@ -12,7 +12,6 @@ | |||
| 12 | */ | 12 | */ | 
| 13 | #include <linux/linkage.h> | 13 | #include <linux/linkage.h> | 
| 14 | #include <asm/thread_info.h> | 14 | #include <asm/thread_info.h> | 
| 15 | #include <asm/page.h> | ||
| 16 | 15 | ||
| 17 | #ifdef CONFIG_CPU_SH4A | 16 | #ifdef CONFIG_CPU_SH4A | 
| 18 | #define SYNCO() synco | 17 | #define SYNCO() synco | 
| @@ -69,8 +68,8 @@ ENTRY(_stext) | |||
| 69 | ! | 68 | ! | 
| 70 | mov.l 2f, r0 | 69 | mov.l 2f, r0 | 
| 71 | mov r0, r15 ! Set initial r15 (stack pointer) | 70 | mov r0, r15 ! Set initial r15 (stack pointer) | 
| 72 | mov #0x20, r1 ! | 71 | mov #(THREAD_SIZE >> 8), r1 | 
| 73 | shll8 r1 ! r1 = 8192 | 72 | shll8 r1 ! r1 = THREAD_SIZE | 
| 74 | sub r1, r0 ! | 73 | sub r1, r0 ! | 
| 75 | ldc r0, r7_bank ! ... and initial thread_info | 74 | ldc r0, r7_bank ! ... and initial thread_info | 
| 76 | 75 | ||
| diff --git a/arch/sh/kernel/irq.c b/arch/sh/kernel/irq.c index 7066611aeb72..c7ebd6aec951 100644 --- a/arch/sh/kernel/irq.c +++ b/arch/sh/kernel/irq.c | |||
| @@ -1,5 +1,4 @@ | |||
| 1 | /* $Id: irq.c,v 1.20 2004/01/13 05:52:11 kkojima Exp $ | 1 | /* | 
| 2 | * | ||
| 3 | * linux/arch/sh/kernel/irq.c | 2 | * linux/arch/sh/kernel/irq.c | 
| 4 | * | 3 | * | 
| 5 | * Copyright (C) 1992, 1998 Linus Torvalds, Ingo Molnar | 4 | * Copyright (C) 1992, 1998 Linus Torvalds, Ingo Molnar | 
| @@ -7,13 +6,15 @@ | |||
| 7 | * | 6 | * | 
| 8 | * SuperH version: Copyright (C) 1999 Niibe Yutaka | 7 | * SuperH version: Copyright (C) 1999 Niibe Yutaka | 
| 9 | */ | 8 | */ | 
| 10 | |||
| 11 | #include <linux/irq.h> | 9 | #include <linux/irq.h> | 
| 12 | #include <linux/interrupt.h> | 10 | #include <linux/interrupt.h> | 
| 11 | #include <linux/module.h> | ||
| 13 | #include <linux/kernel_stat.h> | 12 | #include <linux/kernel_stat.h> | 
| 14 | #include <linux/seq_file.h> | 13 | #include <linux/seq_file.h> | 
| 15 | #include <asm/irq.h> | 14 | #include <asm/irq.h> | 
| 16 | #include <asm/processor.h> | 15 | #include <asm/processor.h> | 
| 16 | #include <asm/uaccess.h> | ||
| 17 | #include <asm/thread_info.h> | ||
| 17 | #include <asm/cpu/mmu_context.h> | 18 | #include <asm/cpu/mmu_context.h> | 
| 18 | 19 | ||
| 19 | /* | 20 | /* | 
| @@ -60,11 +61,27 @@ unlock: | |||
| 60 | } | 61 | } | 
| 61 | #endif | 62 | #endif | 
| 62 | 63 | ||
| 64 | #ifdef CONFIG_4KSTACKS | ||
| 65 | /* | ||
| 66 | * per-CPU IRQ handling contexts (thread information and stack) | ||
| 67 | */ | ||
| 68 | union irq_ctx { | ||
| 69 | struct thread_info tinfo; | ||
| 70 | u32 stack[THREAD_SIZE/sizeof(u32)]; | ||
| 71 | }; | ||
| 72 | |||
| 73 | static union irq_ctx *hardirq_ctx[NR_CPUS]; | ||
| 74 | static union irq_ctx *softirq_ctx[NR_CPUS]; | ||
| 75 | #endif | ||
| 76 | |||
| 63 | asmlinkage int do_IRQ(unsigned long r4, unsigned long r5, | 77 | asmlinkage int do_IRQ(unsigned long r4, unsigned long r5, | 
| 64 | unsigned long r6, unsigned long r7, | 78 | unsigned long r6, unsigned long r7, | 
| 65 | struct pt_regs regs) | 79 | struct pt_regs regs) | 
| 66 | { | 80 | { | 
| 67 | int irq = r4; | 81 | int irq = r4; | 
| 82 | #ifdef CONFIG_4KSTACKS | ||
| 83 | union irq_ctx *curctx, *irqctx; | ||
| 84 | #endif | ||
| 68 | 85 | ||
| 69 | irq_enter(); | 86 | irq_enter(); | 
| 70 | 87 | ||
| @@ -102,7 +119,135 @@ asmlinkage int do_IRQ(unsigned long r4, unsigned long r5, | |||
| 102 | #endif | 119 | #endif | 
| 103 | 120 | ||
| 104 | irq = irq_demux(irq); | 121 | irq = irq_demux(irq); | 
| 105 | __do_IRQ(irq, ®s); | 122 | |
| 123 | #ifdef CONFIG_4KSTACKS | ||
| 124 | curctx = (union irq_ctx *)current_thread_info(); | ||
| 125 | irqctx = hardirq_ctx[smp_processor_id()]; | ||
| 126 | |||
| 127 | /* | ||
| 128 | * this is where we switch to the IRQ stack. However, if we are | ||
| 129 | * already using the IRQ stack (because we interrupted a hardirq | ||
| 130 | * handler) we can't do that and just have to keep using the | ||
| 131 | * current stack (which is the irq stack already after all) | ||
| 132 | */ | ||
| 133 | if (curctx != irqctx) { | ||
| 134 | u32 *isp; | ||
| 135 | |||
| 136 | isp = (u32 *)((char *)irqctx + sizeof(*irqctx)); | ||
| 137 | irqctx->tinfo.task = curctx->tinfo.task; | ||
| 138 | irqctx->tinfo.previous_sp = current_stack_pointer; | ||
| 139 | |||
| 140 | __asm__ __volatile__ ( | ||
| 141 | "mov %0, r4 \n" | ||
| 142 | "mov %1, r5 \n" | ||
| 143 | "mov r15, r9 \n" | ||
| 144 | "jsr @%2 \n" | ||
| 145 | /* swith to the irq stack */ | ||
| 146 | " mov %3, r15 \n" | ||
| 147 | /* restore the stack (ring zero) */ | ||
| 148 | "mov r9, r15 \n" | ||
| 149 | : /* no outputs */ | ||
| 150 | : "r" (irq), "r" (®s), "r" (__do_IRQ), "r" (isp) | ||
| 151 | /* XXX: A somewhat excessive clobber list? -PFM */ | ||
| 152 | : "memory", "r0", "r1", "r2", "r3", "r4", | ||
| 153 | "r5", "r6", "r7", "r8", "t", "pr" | ||
| 154 | ); | ||
| 155 | } else | ||
| 156 | #endif | ||
| 157 | __do_IRQ(irq, ®s); | ||
| 158 | |||
| 106 | irq_exit(); | 159 | irq_exit(); | 
| 160 | |||
| 107 | return 1; | 161 | return 1; | 
| 108 | } | 162 | } | 
| 163 | |||
| 164 | #ifdef CONFIG_4KSTACKS | ||
| 165 | /* | ||
| 166 | * These should really be __section__(".bss.page_aligned") as well, but | ||
| 167 | * gcc's 3.0 and earlier don't handle that correctly. | ||
| 168 | */ | ||
| 169 | static char softirq_stack[NR_CPUS * THREAD_SIZE] | ||
| 170 | __attribute__((__aligned__(THREAD_SIZE))); | ||
| 171 | |||
| 172 | static char hardirq_stack[NR_CPUS * THREAD_SIZE] | ||
| 173 | __attribute__((__aligned__(THREAD_SIZE))); | ||
| 174 | |||
| 175 | /* | ||
| 176 | * allocate per-cpu stacks for hardirq and for softirq processing | ||
| 177 | */ | ||
| 178 | void irq_ctx_init(int cpu) | ||
| 179 | { | ||
| 180 | union irq_ctx *irqctx; | ||
| 181 | |||
| 182 | if (hardirq_ctx[cpu]) | ||
| 183 | return; | ||
| 184 | |||
| 185 | irqctx = (union irq_ctx *)&hardirq_stack[cpu * THREAD_SIZE]; | ||
| 186 | irqctx->tinfo.task = NULL; | ||
| 187 | irqctx->tinfo.exec_domain = NULL; | ||
| 188 | irqctx->tinfo.cpu = cpu; | ||
| 189 | irqctx->tinfo.preempt_count = HARDIRQ_OFFSET; | ||
| 190 | irqctx->tinfo.addr_limit = MAKE_MM_SEG(0); | ||
| 191 | |||
| 192 | hardirq_ctx[cpu] = irqctx; | ||
| 193 | |||
| 194 | irqctx = (union irq_ctx *)&softirq_stack[cpu * THREAD_SIZE]; | ||
| 195 | irqctx->tinfo.task = NULL; | ||
| 196 | irqctx->tinfo.exec_domain = NULL; | ||
| 197 | irqctx->tinfo.cpu = cpu; | ||
| 198 | irqctx->tinfo.preempt_count = SOFTIRQ_OFFSET; | ||
| 199 | irqctx->tinfo.addr_limit = MAKE_MM_SEG(0); | ||
| 200 | |||
| 201 | softirq_ctx[cpu] = irqctx; | ||
| 202 | |||
| 203 | printk("CPU %u irqstacks, hard=%p soft=%p\n", | ||
| 204 | cpu, hardirq_ctx[cpu], softirq_ctx[cpu]); | ||
| 205 | } | ||
| 206 | |||
| 207 | void irq_ctx_exit(int cpu) | ||
| 208 | { | ||
| 209 | hardirq_ctx[cpu] = NULL; | ||
| 210 | } | ||
| 211 | |||
| 212 | extern asmlinkage void __do_softirq(void); | ||
| 213 | |||
| 214 | asmlinkage void do_softirq(void) | ||
| 215 | { | ||
| 216 | unsigned long flags; | ||
| 217 | struct thread_info *curctx; | ||
| 218 | union irq_ctx *irqctx; | ||
| 219 | u32 *isp; | ||
| 220 | |||
| 221 | if (in_interrupt()) | ||
| 222 | return; | ||
| 223 | |||
| 224 | local_irq_save(flags); | ||
| 225 | |||
| 226 | if (local_softirq_pending()) { | ||
| 227 | curctx = current_thread_info(); | ||
| 228 | irqctx = softirq_ctx[smp_processor_id()]; | ||
| 229 | irqctx->tinfo.task = curctx->task; | ||
| 230 | irqctx->tinfo.previous_sp = current_stack_pointer; | ||
| 231 | |||
| 232 | /* build the stack frame on the softirq stack */ | ||
| 233 | isp = (u32 *)((char *)irqctx + sizeof(*irqctx)); | ||
| 234 | |||
| 235 | __asm__ __volatile__ ( | ||
| 236 | "mov r15, r9 \n" | ||
| 237 | "jsr @%0 \n" | ||
| 238 | /* switch to the softirq stack */ | ||
| 239 | " mov %1, r15 \n" | ||
| 240 | /* restore the thread stack */ | ||
| 241 | "mov r9, r15 \n" | ||
| 242 | : /* no outputs */ | ||
| 243 | : "r" (__do_softirq), "r" (isp) | ||
| 244 | /* XXX: A somewhat excessive clobber list? -PFM */ | ||
| 245 | : "memory", "r0", "r1", "r2", "r3", "r4", | ||
| 246 | "r5", "r6", "r7", "r8", "r9", "r15", "t", "pr" | ||
| 247 | ); | ||
| 248 | } | ||
| 249 | |||
| 250 | local_irq_restore(flags); | ||
| 251 | } | ||
| 252 | EXPORT_SYMBOL(do_softirq); | ||
| 253 | #endif | ||
| diff --git a/arch/sh/kernel/traps.c b/arch/sh/kernel/traps.c index 95c810b3c97e..c2c597e09482 100644 --- a/arch/sh/kernel/traps.c +++ b/arch/sh/kernel/traps.c | |||
| @@ -741,20 +741,12 @@ void show_stack(struct task_struct *tsk, unsigned long *sp) | |||
| 741 | unsigned long module_end = VMALLOC_END; | 741 | unsigned long module_end = VMALLOC_END; | 
| 742 | int i = 1; | 742 | int i = 1; | 
| 743 | 743 | ||
| 744 | if (tsk && !sp) { | 744 | if (!tsk) | 
| 745 | tsk = current; | ||
| 746 | if (tsk == current) | ||
| 747 | sp = (unsigned long *)current_stack_pointer; | ||
| 748 | else | ||
| 745 | sp = (unsigned long *)tsk->thread.sp; | 749 | sp = (unsigned long *)tsk->thread.sp; | 
| 746 | } | ||
| 747 | |||
| 748 | if (!sp) { | ||
| 749 | __asm__ __volatile__ ( | ||
| 750 | "mov r15, %0\n\t" | ||
| 751 | "stc r7_bank, %1\n\t" | ||
| 752 | : "=r" (module_start), | ||
| 753 | "=r" (module_end) | ||
| 754 | ); | ||
| 755 | |||
| 756 | sp = (unsigned long *)module_start; | ||
| 757 | } | ||
| 758 | 750 | ||
| 759 | stack = sp; | 751 | stack = sp; | 
| 760 | 752 | ||
| diff --git a/arch/sh/kernel/vmlinux.lds.S b/arch/sh/kernel/vmlinux.lds.S index 0220d8a838a7..5eb930918186 100644 --- a/arch/sh/kernel/vmlinux.lds.S +++ b/arch/sh/kernel/vmlinux.lds.S | |||
| @@ -3,7 +3,6 @@ | |||
| 3 | * Written by Niibe Yutaka | 3 | * Written by Niibe Yutaka | 
| 4 | */ | 4 | */ | 
| 5 | #include <asm/thread_info.h> | 5 | #include <asm/thread_info.h> | 
| 6 | #include <asm/page.h> | ||
| 7 | #include <asm-generic/vmlinux.lds.h> | 6 | #include <asm-generic/vmlinux.lds.h> | 
| 8 | 7 | ||
| 9 | #ifdef CONFIG_CPU_LITTLE_ENDIAN | 8 | #ifdef CONFIG_CPU_LITTLE_ENDIAN | 
| diff --git a/include/asm-sh/irq.h b/include/asm-sh/irq.h index dd05e102fc0e..0e5f365aff70 100644 --- a/include/asm-sh/irq.h +++ b/include/asm-sh/irq.h | |||
| @@ -719,6 +719,15 @@ static inline int generic_irq_demux(int irq) | |||
| 719 | #define irq_canonicalize(irq) (irq) | 719 | #define irq_canonicalize(irq) (irq) | 
| 720 | #define irq_demux(irq) __irq_demux(sh_mv.mv_irq_demux(irq)) | 720 | #define irq_demux(irq) __irq_demux(sh_mv.mv_irq_demux(irq)) | 
| 721 | 721 | ||
| 722 | #ifdef CONFIG_4KSTACKS | ||
| 723 | extern void irq_ctx_init(int cpu); | ||
| 724 | extern void irq_ctx_exit(int cpu); | ||
| 725 | # define __ARCH_HAS_DO_SOFTIRQ | ||
| 726 | #else | ||
| 727 | # define irq_ctx_init(cpu) do { } while (0) | ||
| 728 | # define irq_ctx_exit(cpu) do { } while (0) | ||
| 729 | #endif | ||
| 730 | |||
| 722 | #if defined(CONFIG_CPU_SUBTYPE_SH73180) | 731 | #if defined(CONFIG_CPU_SUBTYPE_SH73180) | 
| 723 | #include <asm/irq-sh73180.h> | 732 | #include <asm/irq-sh73180.h> | 
| 724 | #endif | 733 | #endif | 
| diff --git a/include/asm-sh/thread_info.h b/include/asm-sh/thread_info.h index 605259f88113..3ebc3f9039eb 100644 --- a/include/asm-sh/thread_info.h +++ b/include/asm-sh/thread_info.h | |||
| @@ -9,8 +9,8 @@ | |||
| 9 | * Copyright (C) 2002 David Howells (dhowells@redhat.com) | 9 | * Copyright (C) 2002 David Howells (dhowells@redhat.com) | 
| 10 | * - Incorporating suggestions made by Linus Torvalds and Dave Miller | 10 | * - Incorporating suggestions made by Linus Torvalds and Dave Miller | 
| 11 | */ | 11 | */ | 
| 12 | |||
| 13 | #ifdef __KERNEL__ | 12 | #ifdef __KERNEL__ | 
| 13 | #include <asm/page.h> | ||
| 14 | 14 | ||
| 15 | #ifndef __ASSEMBLY__ | 15 | #ifndef __ASSEMBLY__ | 
| 16 | #include <asm/processor.h> | 16 | #include <asm/processor.h> | 
| @@ -23,13 +23,20 @@ struct thread_info { | |||
| 23 | int preempt_count; /* 0 => preemptable, <0 => BUG */ | 23 | int preempt_count; /* 0 => preemptable, <0 => BUG */ | 
| 24 | mm_segment_t addr_limit; /* thread address space */ | 24 | mm_segment_t addr_limit; /* thread address space */ | 
| 25 | struct restart_block restart_block; | 25 | struct restart_block restart_block; | 
| 26 | unsigned long previous_sp; /* sp of previous stack in case | ||
| 27 | of nested IRQ stacks */ | ||
| 26 | __u8 supervisor_stack[0]; | 28 | __u8 supervisor_stack[0]; | 
| 27 | }; | 29 | }; | 
| 28 | 30 | ||
| 29 | #endif | 31 | #endif | 
| 30 | 32 | ||
| 31 | #define PREEMPT_ACTIVE 0x10000000 | 33 | #define PREEMPT_ACTIVE 0x10000000 | 
| 34 | |||
| 35 | #ifdef CONFIG_4KSTACKS | ||
| 36 | #define THREAD_SIZE (PAGE_SIZE) | ||
| 37 | #else | ||
| 32 | #define THREAD_SIZE (PAGE_SIZE * 2) | 38 | #define THREAD_SIZE (PAGE_SIZE * 2) | 
| 39 | #endif | ||
| 33 | #define STACK_WARN (THREAD_SIZE / 8) | 40 | #define STACK_WARN (THREAD_SIZE / 8) | 
| 34 | 41 | ||
| 35 | /* | 42 | /* | 
| @@ -52,6 +59,9 @@ struct thread_info { | |||
| 52 | #define init_thread_info (init_thread_union.thread_info) | 59 | #define init_thread_info (init_thread_union.thread_info) | 
| 53 | #define init_stack (init_thread_union.stack) | 60 | #define init_stack (init_thread_union.stack) | 
| 54 | 61 | ||
| 62 | /* how to get the current stack pointer from C */ | ||
| 63 | register unsigned long current_stack_pointer asm("r15") __attribute_used__; | ||
| 64 | |||
| 55 | /* how to get the thread information struct from C */ | 65 | /* how to get the thread information struct from C */ | 
| 56 | static inline struct thread_info *current_thread_info(void) | 66 | static inline struct thread_info *current_thread_info(void) | 
| 57 | { | 67 | { | 
