Commit 110ed28246a0063a5984d7f72ba5c97f154a51cf

Authored by Paul Mundt
1 parent 0e670685e4

sh: Decouple 4k and soft/hardirq stacks.

While using separate IRQ stacks can cut down on stack consumption,
many users can also use 4k stacks directly without the additional
need of separate stacks for soft and hardirqs.

With this split, we support the same rationale for 4KSTACKS as
m68knommu, with the IRQSTACKS abstraction as per ppc64.

Signed-off-by: Paul Mundt <lethal@linux-sh.org>

Showing 3 changed files with 13 additions and 5 deletions Inline Diff

arch/sh/Kconfig.debug
1 menu "Kernel hacking" 1 menu "Kernel hacking"
2 2
3 config TRACE_IRQFLAGS_SUPPORT 3 config TRACE_IRQFLAGS_SUPPORT
4 bool 4 bool
5 default y 5 default y
6 6
7 source "lib/Kconfig.debug" 7 source "lib/Kconfig.debug"
8 8
9 config SH_STANDARD_BIOS 9 config SH_STANDARD_BIOS
10 bool "Use LinuxSH standard BIOS" 10 bool "Use LinuxSH standard BIOS"
11 help 11 help
12 Say Y here if your target has the gdb-sh-stub 12 Say Y here if your target has the gdb-sh-stub
13 package from www.m17n.org (or any conforming standard LinuxSH BIOS) 13 package from www.m17n.org (or any conforming standard LinuxSH BIOS)
14 in FLASH or EPROM. The kernel will use standard BIOS calls during 14 in FLASH or EPROM. The kernel will use standard BIOS calls during
15 boot for various housekeeping tasks (including calls to read and 15 boot for various housekeeping tasks (including calls to read and
16 write characters to a system console, get a MAC address from an 16 write characters to a system console, get a MAC address from an
17 on-board Ethernet interface, and shut down the hardware). Note this 17 on-board Ethernet interface, and shut down the hardware). Note this
18 does not work with machines with an existing operating system in 18 does not work with machines with an existing operating system in
19 mask ROM and no flash (WindowsCE machines fall in this category). 19 mask ROM and no flash (WindowsCE machines fall in this category).
20 If unsure, say N. 20 If unsure, say N.
21 21
22 config EARLY_SCIF_CONSOLE 22 config EARLY_SCIF_CONSOLE
23 bool "Use early SCIF console" 23 bool "Use early SCIF console"
24 help 24 help
25 This enables an early console using a fixed SCIF port. This can 25 This enables an early console using a fixed SCIF port. This can
26 be used by platforms that are either not running the SH 26 be used by platforms that are either not running the SH
27 standard BIOS, or do not wish to use the BIOS callbacks for the 27 standard BIOS, or do not wish to use the BIOS callbacks for the
28 serial I/O. 28 serial I/O.
29 29
30 config EARLY_SCIF_CONSOLE_PORT 30 config EARLY_SCIF_CONSOLE_PORT
31 hex 31 hex
32 depends on EARLY_SCIF_CONSOLE 32 depends on EARLY_SCIF_CONSOLE
33 default "0xffe00000" if CPU_SUBTYPE_SH7780 33 default "0xffe00000" if CPU_SUBTYPE_SH7780
34 default "0xffea0000" if CPU_SUBTYPE_SH7785 34 default "0xffea0000" if CPU_SUBTYPE_SH7785
35 default "0xfffe9800" if CPU_SUBTYPE_SH7206 35 default "0xfffe9800" if CPU_SUBTYPE_SH7206
36 default "0xf8420000" if CPU_SUBTYPE_SH7619 36 default "0xf8420000" if CPU_SUBTYPE_SH7619
37 default "0xa4400000" if CPU_SUBTYPE_SH7712 || CPU_SUBTYPE_SH7705 37 default "0xa4400000" if CPU_SUBTYPE_SH7712 || CPU_SUBTYPE_SH7705
38 default "0xa4430000" if CPU_SUBTYPE_SH7720 38 default "0xa4430000" if CPU_SUBTYPE_SH7720
39 default "0xffc30000" if CPU_SUBTYPE_SHX3 39 default "0xffc30000" if CPU_SUBTYPE_SHX3
40 default "0xffe80000" if CPU_SH4 40 default "0xffe80000" if CPU_SH4
41 default "0x00000000" 41 default "0x00000000"
42 42
43 config EARLY_PRINTK 43 config EARLY_PRINTK
44 bool "Early printk support" 44 bool "Early printk support"
45 depends on SH_STANDARD_BIOS || EARLY_SCIF_CONSOLE 45 depends on SH_STANDARD_BIOS || EARLY_SCIF_CONSOLE
46 help 46 help
47 Say Y here to redirect kernel printk messages to the serial port 47 Say Y here to redirect kernel printk messages to the serial port
48 used by the SH-IPL bootloader, starting very early in the boot 48 used by the SH-IPL bootloader, starting very early in the boot
49 process and ending when the kernel's serial console is initialised. 49 process and ending when the kernel's serial console is initialised.
50 This option is only useful porting the kernel to a new machine, 50 This option is only useful porting the kernel to a new machine,
51 when the kernel may crash or hang before the serial console is 51 when the kernel may crash or hang before the serial console is
52 initialised. If unsure, say N. 52 initialised. If unsure, say N.
53 53
54 On devices that are running SH-IPL and want to keep the port 54 On devices that are running SH-IPL and want to keep the port
55 initialization consistent while not using the BIOS callbacks, 55 initialization consistent while not using the BIOS callbacks,
56 select both the EARLY_SCIF_CONSOLE and SH_STANDARD_BIOS, using 56 select both the EARLY_SCIF_CONSOLE and SH_STANDARD_BIOS, using
57 the kernel command line option to toggle back and forth. 57 the kernel command line option to toggle back and forth.
58 58
59 config DEBUG_BOOTMEM 59 config DEBUG_BOOTMEM
60 depends on DEBUG_KERNEL 60 depends on DEBUG_KERNEL
61 bool "Debug BOOTMEM initialization" 61 bool "Debug BOOTMEM initialization"
62 62
63 config DEBUG_STACKOVERFLOW 63 config DEBUG_STACKOVERFLOW
64 bool "Check for stack overflows" 64 bool "Check for stack overflows"
65 depends on DEBUG_KERNEL 65 depends on DEBUG_KERNEL
66 help 66 help
67 This option will cause messages to be printed if free stack space 67 This option will cause messages to be printed if free stack space
68 drops below a certain limit. 68 drops below a certain limit.
69 69
70 config DEBUG_STACK_USAGE 70 config DEBUG_STACK_USAGE
71 bool "Stack utilization instrumentation" 71 bool "Stack utilization instrumentation"
72 depends on DEBUG_KERNEL 72 depends on DEBUG_KERNEL
73 help 73 help
74 Enables the display of the minimum amount of free stack which each 74 Enables the display of the minimum amount of free stack which each
75 task has ever had available in the sysrq-T and sysrq-P debug output. 75 task has ever had available in the sysrq-T and sysrq-P debug output.
76 76
77 This option will slow down process creation somewhat. 77 This option will slow down process creation somewhat.
78 78
79 config 4KSTACKS 79 config 4KSTACKS
80 bool "Use 4Kb for kernel stacks instead of 8Kb" 80 bool "Use 4Kb for kernel stacks instead of 8Kb"
81 depends on DEBUG_KERNEL 81 depends on DEBUG_KERNEL
82 help 82 help
83 If you say Y here the kernel will use a 4Kb stacksize for the 83 If you say Y here the kernel will use a 4Kb stacksize for the
84 kernel stack attached to each process/thread. This facilitates 84 kernel stack attached to each process/thread. This facilitates
85 running more threads on a system and also reduces the pressure 85 running more threads on a system and also reduces the pressure
86 on the VM subsystem for higher order allocations. This option 86 on the VM subsystem for higher order allocations. This option
87 will also use IRQ stacks to compensate for the reduced stackspace. 87 will also use IRQ stacks to compensate for the reduced stackspace.
88 88
89 config IRQSTACKS
90 bool "Use separate kernel stacks when processing interrupts"
91 depends on DEBUG_KERNEL
92 help
93 If you say Y here the kernel will use separate kernel stacks
94 for handling hard and soft interrupts. This can help avoid
95 overflowing the process kernel stacks.
96
89 config SH_KGDB 97 config SH_KGDB
90 bool "Include KGDB kernel debugger" 98 bool "Include KGDB kernel debugger"
91 select FRAME_POINTER 99 select FRAME_POINTER
92 select DEBUG_INFO 100 select DEBUG_INFO
93 depends on CPU_SH3 || CPU_SH4 101 depends on CPU_SH3 || CPU_SH4
94 help 102 help
95 Include in-kernel hooks for kgdb, the Linux kernel source level 103 Include in-kernel hooks for kgdb, the Linux kernel source level
96 debugger. See <http://kgdb.sourceforge.net/> for more information. 104 debugger. See <http://kgdb.sourceforge.net/> for more information.
97 Unless you are intending to debug the kernel, say N here. 105 Unless you are intending to debug the kernel, say N here.
98 106
99 menu "KGDB configuration options" 107 menu "KGDB configuration options"
100 depends on SH_KGDB 108 depends on SH_KGDB
101 109
102 config MORE_COMPILE_OPTIONS 110 config MORE_COMPILE_OPTIONS
103 bool "Add any additional compile options" 111 bool "Add any additional compile options"
104 help 112 help
105 If you want to add additional CFLAGS to the kernel build, enable this 113 If you want to add additional CFLAGS to the kernel build, enable this
106 option and then enter what you would like to add in the next question. 114 option and then enter what you would like to add in the next question.
107 Note however that -g is already appended with the selection of KGDB. 115 Note however that -g is already appended with the selection of KGDB.
108 116
109 config COMPILE_OPTIONS 117 config COMPILE_OPTIONS
110 string "Additional compile arguments" 118 string "Additional compile arguments"
111 depends on MORE_COMPILE_OPTIONS 119 depends on MORE_COMPILE_OPTIONS
112 120
113 config KGDB_NMI 121 config KGDB_NMI
114 bool "Enter KGDB on NMI" 122 bool "Enter KGDB on NMI"
115 default n 123 default n
116 124
117 config SH_KGDB_CONSOLE 125 config SH_KGDB_CONSOLE
118 bool "Console messages through GDB" 126 bool "Console messages through GDB"
119 depends on !SERIAL_SH_SCI_CONSOLE 127 depends on !SERIAL_SH_SCI_CONSOLE
120 select SERIAL_CORE_CONSOLE 128 select SERIAL_CORE_CONSOLE
121 default n 129 default n
122 130
123 config KGDB_SYSRQ 131 config KGDB_SYSRQ
124 bool "Allow SysRq 'G' to enter KGDB" 132 bool "Allow SysRq 'G' to enter KGDB"
125 default y 133 default y
126 134
127 comment "Serial port setup" 135 comment "Serial port setup"
128 136
129 config KGDB_DEFPORT 137 config KGDB_DEFPORT
130 int "Port number (ttySCn)" 138 int "Port number (ttySCn)"
131 default "1" 139 default "1"
132 140
133 config KGDB_DEFBAUD 141 config KGDB_DEFBAUD
134 int "Baud rate" 142 int "Baud rate"
135 default "115200" 143 default "115200"
136 144
137 choice 145 choice
138 prompt "Parity" 146 prompt "Parity"
139 depends on SH_KGDB 147 depends on SH_KGDB
140 default KGDB_DEFPARITY_N 148 default KGDB_DEFPARITY_N
141 149
142 config KGDB_DEFPARITY_N 150 config KGDB_DEFPARITY_N
143 bool "None" 151 bool "None"
144 152
145 config KGDB_DEFPARITY_E 153 config KGDB_DEFPARITY_E
146 bool "Even" 154 bool "Even"
147 155
148 config KGDB_DEFPARITY_O 156 config KGDB_DEFPARITY_O
149 bool "Odd" 157 bool "Odd"
150 158
151 endchoice 159 endchoice
152 160
153 choice 161 choice
154 prompt "Data bits" 162 prompt "Data bits"
155 depends on SH_KGDB 163 depends on SH_KGDB
156 default KGDB_DEFBITS_8 164 default KGDB_DEFBITS_8
157 165
158 config KGDB_DEFBITS_8 166 config KGDB_DEFBITS_8
159 bool "8" 167 bool "8"
160 168
161 config KGDB_DEFBITS_7 169 config KGDB_DEFBITS_7
162 bool "7" 170 bool "7"
163 171
164 endchoice 172 endchoice
165 173
166 endmenu 174 endmenu
167 175
168 endmenu 176 endmenu
169 177
arch/sh/kernel/irq.c
1 /* 1 /*
2 * linux/arch/sh/kernel/irq.c 2 * linux/arch/sh/kernel/irq.c
3 * 3 *
4 * Copyright (C) 1992, 1998 Linus Torvalds, Ingo Molnar 4 * Copyright (C) 1992, 1998 Linus Torvalds, Ingo Molnar
5 * 5 *
6 * 6 *
7 * SuperH version: Copyright (C) 1999 Niibe Yutaka 7 * SuperH version: Copyright (C) 1999 Niibe Yutaka
8 */ 8 */
9 #include <linux/irq.h> 9 #include <linux/irq.h>
10 #include <linux/interrupt.h> 10 #include <linux/interrupt.h>
11 #include <linux/module.h> 11 #include <linux/module.h>
12 #include <linux/kernel_stat.h> 12 #include <linux/kernel_stat.h>
13 #include <linux/seq_file.h> 13 #include <linux/seq_file.h>
14 #include <linux/irq.h> 14 #include <linux/irq.h>
15 #include <asm/processor.h> 15 #include <asm/processor.h>
16 #include <asm/machvec.h> 16 #include <asm/machvec.h>
17 #include <asm/uaccess.h> 17 #include <asm/uaccess.h>
18 #include <asm/thread_info.h> 18 #include <asm/thread_info.h>
19 #include <asm/cpu/mmu_context.h> 19 #include <asm/cpu/mmu_context.h>
20 20
21 atomic_t irq_err_count; 21 atomic_t irq_err_count;
22 22
23 /* 23 /*
24 * 'what should we do if we get a hw irq event on an illegal vector'. 24 * 'what should we do if we get a hw irq event on an illegal vector'.
25 * each architecture has to answer this themselves, it doesn't deserve 25 * each architecture has to answer this themselves, it doesn't deserve
26 * a generic callback i think. 26 * a generic callback i think.
27 */ 27 */
28 void ack_bad_irq(unsigned int irq) 28 void ack_bad_irq(unsigned int irq)
29 { 29 {
30 atomic_inc(&irq_err_count); 30 atomic_inc(&irq_err_count);
31 printk("unexpected IRQ trap at vector %02x\n", irq); 31 printk("unexpected IRQ trap at vector %02x\n", irq);
32 } 32 }
33 33
34 #if defined(CONFIG_PROC_FS) 34 #if defined(CONFIG_PROC_FS)
35 int show_interrupts(struct seq_file *p, void *v) 35 int show_interrupts(struct seq_file *p, void *v)
36 { 36 {
37 int i = *(loff_t *) v, j; 37 int i = *(loff_t *) v, j;
38 struct irqaction * action; 38 struct irqaction * action;
39 unsigned long flags; 39 unsigned long flags;
40 40
41 if (i == 0) { 41 if (i == 0) {
42 seq_puts(p, " "); 42 seq_puts(p, " ");
43 for_each_online_cpu(j) 43 for_each_online_cpu(j)
44 seq_printf(p, "CPU%d ",j); 44 seq_printf(p, "CPU%d ",j);
45 seq_putc(p, '\n'); 45 seq_putc(p, '\n');
46 } 46 }
47 47
48 if (i < sh_mv.mv_nr_irqs) { 48 if (i < sh_mv.mv_nr_irqs) {
49 spin_lock_irqsave(&irq_desc[i].lock, flags); 49 spin_lock_irqsave(&irq_desc[i].lock, flags);
50 action = irq_desc[i].action; 50 action = irq_desc[i].action;
51 if (!action) 51 if (!action)
52 goto unlock; 52 goto unlock;
53 seq_printf(p, "%3d: ",i); 53 seq_printf(p, "%3d: ",i);
54 for_each_online_cpu(j) 54 for_each_online_cpu(j)
55 seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]); 55 seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
56 seq_printf(p, " %14s", irq_desc[i].chip->name); 56 seq_printf(p, " %14s", irq_desc[i].chip->name);
57 seq_printf(p, "-%-8s", irq_desc[i].name); 57 seq_printf(p, "-%-8s", irq_desc[i].name);
58 seq_printf(p, " %s", action->name); 58 seq_printf(p, " %s", action->name);
59 59
60 for (action=action->next; action; action = action->next) 60 for (action=action->next; action; action = action->next)
61 seq_printf(p, ", %s", action->name); 61 seq_printf(p, ", %s", action->name);
62 seq_putc(p, '\n'); 62 seq_putc(p, '\n');
63 unlock: 63 unlock:
64 spin_unlock_irqrestore(&irq_desc[i].lock, flags); 64 spin_unlock_irqrestore(&irq_desc[i].lock, flags);
65 } else if (i == sh_mv.mv_nr_irqs) 65 } else if (i == sh_mv.mv_nr_irqs)
66 seq_printf(p, "Err: %10u\n", atomic_read(&irq_err_count)); 66 seq_printf(p, "Err: %10u\n", atomic_read(&irq_err_count));
67 67
68 return 0; 68 return 0;
69 } 69 }
70 #endif 70 #endif
71 71
72 #ifdef CONFIG_4KSTACKS 72 #ifdef CONFIG_IRQSTACKS
73 /* 73 /*
74 * per-CPU IRQ handling contexts (thread information and stack) 74 * per-CPU IRQ handling contexts (thread information and stack)
75 */ 75 */
76 union irq_ctx { 76 union irq_ctx {
77 struct thread_info tinfo; 77 struct thread_info tinfo;
78 u32 stack[THREAD_SIZE/sizeof(u32)]; 78 u32 stack[THREAD_SIZE/sizeof(u32)];
79 }; 79 };
80 80
81 static union irq_ctx *hardirq_ctx[NR_CPUS] __read_mostly; 81 static union irq_ctx *hardirq_ctx[NR_CPUS] __read_mostly;
82 static union irq_ctx *softirq_ctx[NR_CPUS] __read_mostly; 82 static union irq_ctx *softirq_ctx[NR_CPUS] __read_mostly;
83 #endif 83 #endif
84 84
85 asmlinkage int do_IRQ(unsigned int irq, struct pt_regs *regs) 85 asmlinkage int do_IRQ(unsigned int irq, struct pt_regs *regs)
86 { 86 {
87 struct pt_regs *old_regs = set_irq_regs(regs); 87 struct pt_regs *old_regs = set_irq_regs(regs);
88 #ifdef CONFIG_4KSTACKS 88 #ifdef CONFIG_IRQSTACKS
89 union irq_ctx *curctx, *irqctx; 89 union irq_ctx *curctx, *irqctx;
90 #endif 90 #endif
91 91
92 irq_enter(); 92 irq_enter();
93 93
94 #ifdef CONFIG_DEBUG_STACKOVERFLOW 94 #ifdef CONFIG_DEBUG_STACKOVERFLOW
95 /* Debugging check for stack overflow: is there less than 1KB free? */ 95 /* Debugging check for stack overflow: is there less than 1KB free? */
96 { 96 {
97 long sp; 97 long sp;
98 98
99 __asm__ __volatile__ ("and r15, %0" : 99 __asm__ __volatile__ ("and r15, %0" :
100 "=r" (sp) : "0" (THREAD_SIZE - 1)); 100 "=r" (sp) : "0" (THREAD_SIZE - 1));
101 101
102 if (unlikely(sp < (sizeof(struct thread_info) + STACK_WARN))) { 102 if (unlikely(sp < (sizeof(struct thread_info) + STACK_WARN))) {
103 printk("do_IRQ: stack overflow: %ld\n", 103 printk("do_IRQ: stack overflow: %ld\n",
104 sp - sizeof(struct thread_info)); 104 sp - sizeof(struct thread_info));
105 dump_stack(); 105 dump_stack();
106 } 106 }
107 } 107 }
108 #endif 108 #endif
109 109
110 irq = irq_demux(evt2irq(irq)); 110 irq = irq_demux(evt2irq(irq));
111 111
112 #ifdef CONFIG_4KSTACKS 112 #ifdef CONFIG_IRQSTACKS
113 curctx = (union irq_ctx *)current_thread_info(); 113 curctx = (union irq_ctx *)current_thread_info();
114 irqctx = hardirq_ctx[smp_processor_id()]; 114 irqctx = hardirq_ctx[smp_processor_id()];
115 115
116 /* 116 /*
117 * this is where we switch to the IRQ stack. However, if we are 117 * this is where we switch to the IRQ stack. However, if we are
118 * already using the IRQ stack (because we interrupted a hardirq 118 * already using the IRQ stack (because we interrupted a hardirq
119 * handler) we can't do that and just have to keep using the 119 * handler) we can't do that and just have to keep using the
120 * current stack (which is the irq stack already after all) 120 * current stack (which is the irq stack already after all)
121 */ 121 */
122 if (curctx != irqctx) { 122 if (curctx != irqctx) {
123 u32 *isp; 123 u32 *isp;
124 124
125 isp = (u32 *)((char *)irqctx + sizeof(*irqctx)); 125 isp = (u32 *)((char *)irqctx + sizeof(*irqctx));
126 irqctx->tinfo.task = curctx->tinfo.task; 126 irqctx->tinfo.task = curctx->tinfo.task;
127 irqctx->tinfo.previous_sp = current_stack_pointer; 127 irqctx->tinfo.previous_sp = current_stack_pointer;
128 128
129 /* 129 /*
130 * Copy the softirq bits in preempt_count so that the 130 * Copy the softirq bits in preempt_count so that the
131 * softirq checks work in the hardirq context. 131 * softirq checks work in the hardirq context.
132 */ 132 */
133 irqctx->tinfo.preempt_count = 133 irqctx->tinfo.preempt_count =
134 (irqctx->tinfo.preempt_count & ~SOFTIRQ_MASK) | 134 (irqctx->tinfo.preempt_count & ~SOFTIRQ_MASK) |
135 (curctx->tinfo.preempt_count & SOFTIRQ_MASK); 135 (curctx->tinfo.preempt_count & SOFTIRQ_MASK);
136 136
137 __asm__ __volatile__ ( 137 __asm__ __volatile__ (
138 "mov %0, r4 \n" 138 "mov %0, r4 \n"
139 "mov r15, r8 \n" 139 "mov r15, r8 \n"
140 "jsr @%1 \n" 140 "jsr @%1 \n"
141 /* swith to the irq stack */ 141 /* swith to the irq stack */
142 " mov %2, r15 \n" 142 " mov %2, r15 \n"
143 /* restore the stack (ring zero) */ 143 /* restore the stack (ring zero) */
144 "mov r8, r15 \n" 144 "mov r8, r15 \n"
145 : /* no outputs */ 145 : /* no outputs */
146 : "r" (irq), "r" (generic_handle_irq), "r" (isp) 146 : "r" (irq), "r" (generic_handle_irq), "r" (isp)
147 : "memory", "r0", "r1", "r2", "r3", "r4", 147 : "memory", "r0", "r1", "r2", "r3", "r4",
148 "r5", "r6", "r7", "r8", "t", "pr" 148 "r5", "r6", "r7", "r8", "t", "pr"
149 ); 149 );
150 } else 150 } else
151 #endif 151 #endif
152 generic_handle_irq(irq); 152 generic_handle_irq(irq);
153 153
154 irq_exit(); 154 irq_exit();
155 155
156 set_irq_regs(old_regs); 156 set_irq_regs(old_regs);
157 return 1; 157 return 1;
158 } 158 }
159 159
160 #ifdef CONFIG_4KSTACKS 160 #ifdef CONFIG_IRQSTACKS
161 static char softirq_stack[NR_CPUS * THREAD_SIZE] 161 static char softirq_stack[NR_CPUS * THREAD_SIZE]
162 __attribute__((__section__(".bss.page_aligned"))); 162 __attribute__((__section__(".bss.page_aligned")));
163 163
164 static char hardirq_stack[NR_CPUS * THREAD_SIZE] 164 static char hardirq_stack[NR_CPUS * THREAD_SIZE]
165 __attribute__((__section__(".bss.page_aligned"))); 165 __attribute__((__section__(".bss.page_aligned")));
166 166
167 /* 167 /*
168 * allocate per-cpu stacks for hardirq and for softirq processing 168 * allocate per-cpu stacks for hardirq and for softirq processing
169 */ 169 */
170 void irq_ctx_init(int cpu) 170 void irq_ctx_init(int cpu)
171 { 171 {
172 union irq_ctx *irqctx; 172 union irq_ctx *irqctx;
173 173
174 if (hardirq_ctx[cpu]) 174 if (hardirq_ctx[cpu])
175 return; 175 return;
176 176
177 irqctx = (union irq_ctx *)&hardirq_stack[cpu * THREAD_SIZE]; 177 irqctx = (union irq_ctx *)&hardirq_stack[cpu * THREAD_SIZE];
178 irqctx->tinfo.task = NULL; 178 irqctx->tinfo.task = NULL;
179 irqctx->tinfo.exec_domain = NULL; 179 irqctx->tinfo.exec_domain = NULL;
180 irqctx->tinfo.cpu = cpu; 180 irqctx->tinfo.cpu = cpu;
181 irqctx->tinfo.preempt_count = HARDIRQ_OFFSET; 181 irqctx->tinfo.preempt_count = HARDIRQ_OFFSET;
182 irqctx->tinfo.addr_limit = MAKE_MM_SEG(0); 182 irqctx->tinfo.addr_limit = MAKE_MM_SEG(0);
183 183
184 hardirq_ctx[cpu] = irqctx; 184 hardirq_ctx[cpu] = irqctx;
185 185
186 irqctx = (union irq_ctx *)&softirq_stack[cpu * THREAD_SIZE]; 186 irqctx = (union irq_ctx *)&softirq_stack[cpu * THREAD_SIZE];
187 irqctx->tinfo.task = NULL; 187 irqctx->tinfo.task = NULL;
188 irqctx->tinfo.exec_domain = NULL; 188 irqctx->tinfo.exec_domain = NULL;
189 irqctx->tinfo.cpu = cpu; 189 irqctx->tinfo.cpu = cpu;
190 irqctx->tinfo.preempt_count = 0; 190 irqctx->tinfo.preempt_count = 0;
191 irqctx->tinfo.addr_limit = MAKE_MM_SEG(0); 191 irqctx->tinfo.addr_limit = MAKE_MM_SEG(0);
192 192
193 softirq_ctx[cpu] = irqctx; 193 softirq_ctx[cpu] = irqctx;
194 194
195 printk("CPU %u irqstacks, hard=%p soft=%p\n", 195 printk("CPU %u irqstacks, hard=%p soft=%p\n",
196 cpu, hardirq_ctx[cpu], softirq_ctx[cpu]); 196 cpu, hardirq_ctx[cpu], softirq_ctx[cpu]);
197 } 197 }
198 198
199 void irq_ctx_exit(int cpu) 199 void irq_ctx_exit(int cpu)
200 { 200 {
201 hardirq_ctx[cpu] = NULL; 201 hardirq_ctx[cpu] = NULL;
202 } 202 }
203 203
204 extern asmlinkage void __do_softirq(void); 204 extern asmlinkage void __do_softirq(void);
205 205
206 asmlinkage void do_softirq(void) 206 asmlinkage void do_softirq(void)
207 { 207 {
208 unsigned long flags; 208 unsigned long flags;
209 struct thread_info *curctx; 209 struct thread_info *curctx;
210 union irq_ctx *irqctx; 210 union irq_ctx *irqctx;
211 u32 *isp; 211 u32 *isp;
212 212
213 if (in_interrupt()) 213 if (in_interrupt())
214 return; 214 return;
215 215
216 local_irq_save(flags); 216 local_irq_save(flags);
217 217
218 if (local_softirq_pending()) { 218 if (local_softirq_pending()) {
219 curctx = current_thread_info(); 219 curctx = current_thread_info();
220 irqctx = softirq_ctx[smp_processor_id()]; 220 irqctx = softirq_ctx[smp_processor_id()];
221 irqctx->tinfo.task = curctx->task; 221 irqctx->tinfo.task = curctx->task;
222 irqctx->tinfo.previous_sp = current_stack_pointer; 222 irqctx->tinfo.previous_sp = current_stack_pointer;
223 223
224 /* build the stack frame on the softirq stack */ 224 /* build the stack frame on the softirq stack */
225 isp = (u32 *)((char *)irqctx + sizeof(*irqctx)); 225 isp = (u32 *)((char *)irqctx + sizeof(*irqctx));
226 226
227 __asm__ __volatile__ ( 227 __asm__ __volatile__ (
228 "mov r15, r9 \n" 228 "mov r15, r9 \n"
229 "jsr @%0 \n" 229 "jsr @%0 \n"
230 /* switch to the softirq stack */ 230 /* switch to the softirq stack */
231 " mov %1, r15 \n" 231 " mov %1, r15 \n"
232 /* restore the thread stack */ 232 /* restore the thread stack */
233 "mov r9, r15 \n" 233 "mov r9, r15 \n"
234 : /* no outputs */ 234 : /* no outputs */
235 : "r" (__do_softirq), "r" (isp) 235 : "r" (__do_softirq), "r" (isp)
236 : "memory", "r0", "r1", "r2", "r3", "r4", 236 : "memory", "r0", "r1", "r2", "r3", "r4",
237 "r5", "r6", "r7", "r8", "r9", "r15", "t", "pr" 237 "r5", "r6", "r7", "r8", "r9", "r15", "t", "pr"
238 ); 238 );
239 239
240 /* 240 /*
241 * Shouldnt happen, we returned above if in_interrupt(): 241 * Shouldnt happen, we returned above if in_interrupt():
242 */ 242 */
243 WARN_ON_ONCE(softirq_count()); 243 WARN_ON_ONCE(softirq_count());
244 } 244 }
245 245
246 local_irq_restore(flags); 246 local_irq_restore(flags);
247 } 247 }
248 #endif 248 #endif
249 249
250 void __init init_IRQ(void) 250 void __init init_IRQ(void)
251 { 251 {
252 #ifdef CONFIG_CPU_HAS_PINT_IRQ 252 #ifdef CONFIG_CPU_HAS_PINT_IRQ
253 init_IRQ_pint(); 253 init_IRQ_pint();
254 #endif 254 #endif
255 plat_irq_setup(); 255 plat_irq_setup();
256 256
257 /* Perform the machine specific initialisation */ 257 /* Perform the machine specific initialisation */
258 if (sh_mv.mv_init_irq) 258 if (sh_mv.mv_init_irq)
259 sh_mv.mv_init_irq(); 259 sh_mv.mv_init_irq();
260 260
261 irq_ctx_init(smp_processor_id()); 261 irq_ctx_init(smp_processor_id());
262 } 262 }
263 263
include/asm-sh/irq.h
1 #ifndef __ASM_SH_IRQ_H 1 #ifndef __ASM_SH_IRQ_H
2 #define __ASM_SH_IRQ_H 2 #define __ASM_SH_IRQ_H
3 3
4 #include <asm/machvec.h> 4 #include <asm/machvec.h>
5 5
6 /* 6 /*
7 * A sane default based on a reasonable vector table size, platforms are 7 * A sane default based on a reasonable vector table size, platforms are
8 * advised to cap this at the hard limit that they're interested in 8 * advised to cap this at the hard limit that they're interested in
9 * through the machvec. 9 * through the machvec.
10 */ 10 */
11 #define NR_IRQS 256 11 #define NR_IRQS 256
12 12
13 /* 13 /*
14 * Convert back and forth between INTEVT and IRQ values. 14 * Convert back and forth between INTEVT and IRQ values.
15 */ 15 */
16 #ifdef CONFIG_CPU_HAS_INTEVT 16 #ifdef CONFIG_CPU_HAS_INTEVT
17 #define evt2irq(evt) (((evt) >> 5) - 16) 17 #define evt2irq(evt) (((evt) >> 5) - 16)
18 #define irq2evt(irq) (((irq) + 16) << 5) 18 #define irq2evt(irq) (((irq) + 16) << 5)
19 #else 19 #else
20 #define evt2irq(evt) (evt) 20 #define evt2irq(evt) (evt)
21 #define irq2evt(irq) (irq) 21 #define irq2evt(irq) (irq)
22 #endif 22 #endif
23 23
24 /* 24 /*
25 * Simple Mask Register Support 25 * Simple Mask Register Support
26 */ 26 */
27 extern void make_maskreg_irq(unsigned int irq); 27 extern void make_maskreg_irq(unsigned int irq);
28 extern unsigned short *irq_mask_register; 28 extern unsigned short *irq_mask_register;
29 29
30 /* 30 /*
31 * PINT IRQs 31 * PINT IRQs
32 */ 32 */
33 void init_IRQ_pint(void); 33 void init_IRQ_pint(void);
34 void make_imask_irq(unsigned int irq); 34 void make_imask_irq(unsigned int irq);
35 35
36 static inline int generic_irq_demux(int irq) 36 static inline int generic_irq_demux(int irq)
37 { 37 {
38 return irq; 38 return irq;
39 } 39 }
40 40
41 #define irq_canonicalize(irq) (irq) 41 #define irq_canonicalize(irq) (irq)
42 #define irq_demux(irq) sh_mv.mv_irq_demux(irq) 42 #define irq_demux(irq) sh_mv.mv_irq_demux(irq)
43 43
44 #ifdef CONFIG_4KSTACKS 44 #ifdef CONFIG_IRQSTACKS
45 extern void irq_ctx_init(int cpu); 45 extern void irq_ctx_init(int cpu);
46 extern void irq_ctx_exit(int cpu); 46 extern void irq_ctx_exit(int cpu);
47 # define __ARCH_HAS_DO_SOFTIRQ 47 # define __ARCH_HAS_DO_SOFTIRQ
48 #else 48 #else
49 # define irq_ctx_init(cpu) do { } while (0) 49 # define irq_ctx_init(cpu) do { } while (0)
50 # define irq_ctx_exit(cpu) do { } while (0) 50 # define irq_ctx_exit(cpu) do { } while (0)
51 #endif 51 #endif
52 52
53 #endif /* __ASM_SH_IRQ_H */ 53 #endif /* __ASM_SH_IRQ_H */
54 54