aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips/kernel')
-rw-r--r--arch/mips/kernel/Makefile3
-rw-r--r--arch/mips/kernel/cpu-probe.c19
-rw-r--r--arch/mips/kernel/dma-no-isa.c28
-rw-r--r--arch/mips/kernel/genex.S63
-rw-r--r--arch/mips/kernel/head.S3
-rw-r--r--arch/mips/kernel/i8259.c21
-rw-r--r--arch/mips/kernel/irq-msc01.c47
-rw-r--r--arch/mips/kernel/irq-mv6434x.c54
-rw-r--r--arch/mips/kernel/irq-rm7000.c54
-rw-r--r--arch/mips/kernel/irq-rm9000.c47
-rw-r--r--arch/mips/kernel/irq.c32
-rw-r--r--arch/mips/kernel/irq_cpu.c80
-rw-r--r--arch/mips/kernel/machine_kexec.c85
-rw-r--r--arch/mips/kernel/module.c15
-rw-r--r--arch/mips/kernel/relocate_kernel.S80
-rw-r--r--arch/mips/kernel/scall32-o32.S2
-rw-r--r--arch/mips/kernel/scall64-64.S2
-rw-r--r--arch/mips/kernel/scall64-n32.S2
-rw-r--r--arch/mips/kernel/scall64-o32.S2
-rw-r--r--arch/mips/kernel/setup.c87
-rw-r--r--arch/mips/kernel/signal_n32.c1
-rw-r--r--arch/mips/kernel/smp-mt.c2
-rw-r--r--arch/mips/kernel/smtc.c1
-rw-r--r--arch/mips/kernel/time.c64
-rw-r--r--arch/mips/kernel/traps.c72
25 files changed, 438 insertions, 428 deletions
diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile
index 6bfbbed0897e..bbbb8d7cb89b 100644
--- a/arch/mips/kernel/Makefile
+++ b/arch/mips/kernel/Makefile
@@ -45,7 +45,6 @@ obj-$(CONFIG_MIPS_APSP_KSPD) += kspd.o
45obj-$(CONFIG_MIPS_VPE_LOADER) += vpe.o 45obj-$(CONFIG_MIPS_VPE_LOADER) += vpe.o
46obj-$(CONFIG_MIPS_VPE_APSP_API) += rtlx.o 46obj-$(CONFIG_MIPS_VPE_APSP_API) += rtlx.o
47 47
48obj-$(CONFIG_NO_ISA) += dma-no-isa.o
49obj-$(CONFIG_I8259) += i8259.o 48obj-$(CONFIG_I8259) += i8259.o
50obj-$(CONFIG_IRQ_CPU) += irq_cpu.o 49obj-$(CONFIG_IRQ_CPU) += irq_cpu.o
51obj-$(CONFIG_IRQ_CPU_RM7K) += irq-rm7000.o 50obj-$(CONFIG_IRQ_CPU_RM7K) += irq-rm7000.o
@@ -67,6 +66,8 @@ obj-$(CONFIG_64BIT) += cpu-bugs64.o
67 66
68obj-$(CONFIG_I8253) += i8253.o 67obj-$(CONFIG_I8253) += i8253.o
69 68
69obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o
70
70CFLAGS_cpu-bugs64.o = $(shell if $(CC) $(CFLAGS) -Wa,-mdaddi -c -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-DHAVE_AS_SET_DADDI"; fi) 71CFLAGS_cpu-bugs64.o = $(shell if $(CC) $(CFLAGS) -Wa,-mdaddi -c -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-DHAVE_AS_SET_DADDI"; fi)
71 72
72EXTRA_AFLAGS := $(CFLAGS) 73EXTRA_AFLAGS := $(CFLAGS)
diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
index 8485af340ee1..442839e9578c 100644
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -110,9 +110,8 @@ static inline void check_wait(void)
110{ 110{
111 struct cpuinfo_mips *c = &current_cpu_data; 111 struct cpuinfo_mips *c = &current_cpu_data;
112 112
113 printk("Checking for 'wait' instruction... ");
114 if (nowait) { 113 if (nowait) {
115 printk (" disabled.\n"); 114 printk("Wait instruction disabled.\n");
116 return; 115 return;
117 } 116 }
118 117
@@ -120,11 +119,9 @@ static inline void check_wait(void)
120 case CPU_R3081: 119 case CPU_R3081:
121 case CPU_R3081E: 120 case CPU_R3081E:
122 cpu_wait = r3081_wait; 121 cpu_wait = r3081_wait;
123 printk(" available.\n");
124 break; 122 break;
125 case CPU_TX3927: 123 case CPU_TX3927:
126 cpu_wait = r39xx_wait; 124 cpu_wait = r39xx_wait;
127 printk(" available.\n");
128 break; 125 break;
129 case CPU_R4200: 126 case CPU_R4200:
130/* case CPU_R4300: */ 127/* case CPU_R4300: */
@@ -146,33 +143,23 @@ static inline void check_wait(void)
146 case CPU_74K: 143 case CPU_74K:
147 case CPU_PR4450: 144 case CPU_PR4450:
148 cpu_wait = r4k_wait; 145 cpu_wait = r4k_wait;
149 printk(" available.\n");
150 break; 146 break;
151 case CPU_TX49XX: 147 case CPU_TX49XX:
152 cpu_wait = r4k_wait_irqoff; 148 cpu_wait = r4k_wait_irqoff;
153 printk(" available.\n");
154 break; 149 break;
155 case CPU_AU1000: 150 case CPU_AU1000:
156 case CPU_AU1100: 151 case CPU_AU1100:
157 case CPU_AU1500: 152 case CPU_AU1500:
158 case CPU_AU1550: 153 case CPU_AU1550:
159 case CPU_AU1200: 154 case CPU_AU1200:
160 if (allow_au1k_wait) { 155 if (allow_au1k_wait)
161 cpu_wait = au1k_wait; 156 cpu_wait = au1k_wait;
162 printk(" available.\n");
163 } else
164 printk(" unavailable.\n");
165 break; 157 break;
166 case CPU_RM9000: 158 case CPU_RM9000:
167 if ((c->processor_id & 0x00ff) >= 0x40) { 159 if ((c->processor_id & 0x00ff) >= 0x40)
168 cpu_wait = r4k_wait; 160 cpu_wait = r4k_wait;
169 printk(" available.\n");
170 } else {
171 printk(" unavailable.\n");
172 }
173 break; 161 break;
174 default: 162 default:
175 printk(" unavailable.\n");
176 break; 163 break;
177 } 164 }
178} 165}
diff --git a/arch/mips/kernel/dma-no-isa.c b/arch/mips/kernel/dma-no-isa.c
deleted file mode 100644
index 6df8b07741e3..000000000000
--- a/arch/mips/kernel/dma-no-isa.c
+++ /dev/null
@@ -1,28 +0,0 @@
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Copyright (C) 2004 by Ralf Baechle
7 *
8 * Dummy ISA DMA functions for systems that don't have ISA but share drivers
9 * with ISA such as legacy free PCI.
10 */
11#include <linux/errno.h>
12#include <linux/module.h>
13#include <linux/spinlock.h>
14
15DEFINE_SPINLOCK(dma_spin_lock);
16
17int request_dma(unsigned int dmanr, const char * device_id)
18{
19 return -EINVAL;
20}
21
22void free_dma(unsigned int dmanr)
23{
24}
25
26EXPORT_SYMBOL(dma_spin_lock);
27EXPORT_SYMBOL(request_dma);
28EXPORT_SYMBOL(free_dma);
diff --git a/arch/mips/kernel/genex.S b/arch/mips/kernel/genex.S
index 5baca16993d0..aacd4a005c5f 100644
--- a/arch/mips/kernel/genex.S
+++ b/arch/mips/kernel/genex.S
@@ -19,6 +19,7 @@
19#include <asm/mipsregs.h> 19#include <asm/mipsregs.h>
20#include <asm/stackframe.h> 20#include <asm/stackframe.h>
21#include <asm/war.h> 21#include <asm/war.h>
22#include <asm/page.h>
22 23
23#define PANIC_PIC(msg) \ 24#define PANIC_PIC(msg) \
24 .set push; \ 25 .set push; \
@@ -378,6 +379,68 @@ NESTED(nmi_handler, PT_SIZE, sp)
378 BUILD_HANDLER dsp dsp sti silent /* #26 */ 379 BUILD_HANDLER dsp dsp sti silent /* #26 */
379 BUILD_HANDLER reserved reserved sti verbose /* others */ 380 BUILD_HANDLER reserved reserved sti verbose /* others */
380 381
382 .align 5
383 LEAF(handle_ri_rdhwr_vivt)
384#ifdef CONFIG_MIPS_MT_SMTC
385 PANIC_PIC("handle_ri_rdhwr_vivt called")
386#else
387 .set push
388 .set noat
389 .set noreorder
390 /* check if TLB contains a entry for EPC */
391 MFC0 k1, CP0_ENTRYHI
392 andi k1, 0xff /* ASID_MASK */
393 MFC0 k0, CP0_EPC
394 PTR_SRL k0, PAGE_SHIFT + 1
395 PTR_SLL k0, PAGE_SHIFT + 1
396 or k1, k0
397 MTC0 k1, CP0_ENTRYHI
398 mtc0_tlbw_hazard
399 tlbp
400 tlb_probe_hazard
401 mfc0 k1, CP0_INDEX
402 .set pop
403 bltz k1, handle_ri /* slow path */
404 /* fall thru */
405#endif
406 END(handle_ri_rdhwr_vivt)
407
408 LEAF(handle_ri_rdhwr)
409 .set push
410 .set noat
411 .set noreorder
412 /* 0x7c03e83b: rdhwr v1,$29 */
413 MFC0 k1, CP0_EPC
414 lui k0, 0x7c03
415 lw k1, (k1)
416 ori k0, 0xe83b
417 .set reorder
418 bne k0, k1, handle_ri /* if not ours */
419 /* The insn is rdhwr. No need to check CAUSE.BD here. */
420 get_saved_sp /* k1 := current_thread_info */
421 .set noreorder
422 MFC0 k0, CP0_EPC
423#if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX)
424 ori k1, _THREAD_MASK
425 xori k1, _THREAD_MASK
426 LONG_L v1, TI_TP_VALUE(k1)
427 LONG_ADDIU k0, 4
428 jr k0
429 rfe
430#else
431 LONG_ADDIU k0, 4 /* stall on $k0 */
432 MTC0 k0, CP0_EPC
433 /* I hope three instructions between MTC0 and ERET are enough... */
434 ori k1, _THREAD_MASK
435 xori k1, _THREAD_MASK
436 LONG_L v1, TI_TP_VALUE(k1)
437 .set mips3
438 eret
439 .set mips0
440#endif
441 .set pop
442 END(handle_ri_rdhwr)
443
381#ifdef CONFIG_64BIT 444#ifdef CONFIG_64BIT
382/* A temporary overflow handler used by check_daddi(). */ 445/* A temporary overflow handler used by check_daddi(). */
383 446
diff --git a/arch/mips/kernel/head.S b/arch/mips/kernel/head.S
index ddc1b71c9378..a2e095adaa3f 100644
--- a/arch/mips/kernel/head.S
+++ b/arch/mips/kernel/head.S
@@ -250,6 +250,9 @@ NESTED(smp_bootstrap, 16, sp)
250 */ 250 */
251 page swapper_pg_dir, _PGD_ORDER 251 page swapper_pg_dir, _PGD_ORDER
252#ifdef CONFIG_64BIT 252#ifdef CONFIG_64BIT
253#if defined(CONFIG_MODULES) && !defined(CONFIG_BUILD_ELF64)
254 page module_pg_dir, _PGD_ORDER
255#endif
253 page invalid_pmd_table, _PMD_ORDER 256 page invalid_pmd_table, _PMD_ORDER
254#endif 257#endif
255 page invalid_pte_table, _PTE_ORDER 258 page invalid_pte_table, _PTE_ORDER
diff --git a/arch/mips/kernel/i8259.c b/arch/mips/kernel/i8259.c
index 48e3418c217b..2526c0ca4d81 100644
--- a/arch/mips/kernel/i8259.c
+++ b/arch/mips/kernel/i8259.c
@@ -40,21 +40,10 @@ static void end_8259A_irq (unsigned int irq)
40 enable_8259A_irq(irq); 40 enable_8259A_irq(irq);
41} 41}
42 42
43#define shutdown_8259A_irq disable_8259A_irq
44
45void mask_and_ack_8259A(unsigned int); 43void mask_and_ack_8259A(unsigned int);
46 44
47static unsigned int startup_8259A_irq(unsigned int irq)
48{
49 enable_8259A_irq(irq);
50
51 return 0; /* never anything pending */
52}
53
54static struct irq_chip i8259A_irq_type = { 45static struct irq_chip i8259A_irq_type = {
55 .typename = "XT-PIC", 46 .typename = "XT-PIC",
56 .startup = startup_8259A_irq,
57 .shutdown = shutdown_8259A_irq,
58 .enable = enable_8259A_irq, 47 .enable = enable_8259A_irq,
59 .disable = disable_8259A_irq, 48 .disable = disable_8259A_irq,
60 .ack = mask_and_ack_8259A, 49 .ack = mask_and_ack_8259A,
@@ -120,7 +109,7 @@ int i8259A_irq_pending(unsigned int irq)
120void make_8259A_irq(unsigned int irq) 109void make_8259A_irq(unsigned int irq)
121{ 110{
122 disable_irq_nosync(irq); 111 disable_irq_nosync(irq);
123 irq_desc[irq].chip = &i8259A_irq_type; 112 set_irq_chip(irq, &i8259A_irq_type);
124 enable_irq(irq); 113 enable_irq(irq);
125} 114}
126 115
@@ -323,12 +312,8 @@ void __init init_i8259_irqs (void)
323 312
324 init_8259A(0); 313 init_8259A(0);
325 314
326 for (i = 0; i < 16; i++) { 315 for (i = 0; i < 16; i++)
327 irq_desc[i].status = IRQ_DISABLED; 316 set_irq_chip(i, &i8259A_irq_type);
328 irq_desc[i].action = NULL;
329 irq_desc[i].depth = 1;
330 irq_desc[i].chip = &i8259A_irq_type;
331 }
332 317
333 setup_irq(2, &irq2); 318 setup_irq(2, &irq2);
334} 319}
diff --git a/arch/mips/kernel/irq-msc01.c b/arch/mips/kernel/irq-msc01.c
index 650a80ca3741..bcaad6696082 100644
--- a/arch/mips/kernel/irq-msc01.c
+++ b/arch/mips/kernel/irq-msc01.c
@@ -45,31 +45,6 @@ static inline void unmask_msc_irq(unsigned int irq)
45} 45}
46 46
47/* 47/*
48 * Enables the IRQ on SOC-it
49 */
50static void enable_msc_irq(unsigned int irq)
51{
52 unmask_msc_irq(irq);
53}
54
55/*
56 * Initialize the IRQ on SOC-it
57 */
58static unsigned int startup_msc_irq(unsigned int irq)
59{
60 unmask_msc_irq(irq);
61 return 0;
62}
63
64/*
65 * Disables the IRQ on SOC-it
66 */
67static void disable_msc_irq(unsigned int irq)
68{
69 mask_msc_irq(irq);
70}
71
72/*
73 * Masks and ACKs an IRQ 48 * Masks and ACKs an IRQ
74 */ 49 */
75static void level_mask_and_ack_msc_irq(unsigned int irq) 50static void level_mask_and_ack_msc_irq(unsigned int irq)
@@ -136,25 +111,23 @@ msc_bind_eic_interrupt (unsigned int irq, unsigned int set)
136 (irq<<MSC01_IC_RAMW_ADDR_SHF) | (set<<MSC01_IC_RAMW_DATA_SHF)); 111 (irq<<MSC01_IC_RAMW_ADDR_SHF) | (set<<MSC01_IC_RAMW_DATA_SHF));
137} 112}
138 113
139#define shutdown_msc_irq disable_msc_irq
140
141struct irq_chip msc_levelirq_type = { 114struct irq_chip msc_levelirq_type = {
142 .typename = "SOC-it-Level", 115 .typename = "SOC-it-Level",
143 .startup = startup_msc_irq,
144 .shutdown = shutdown_msc_irq,
145 .enable = enable_msc_irq,
146 .disable = disable_msc_irq,
147 .ack = level_mask_and_ack_msc_irq, 116 .ack = level_mask_and_ack_msc_irq,
117 .mask = mask_msc_irq,
118 .mask_ack = level_mask_and_ack_msc_irq,
119 .unmask = unmask_msc_irq,
120 .eoi = unmask_msc_irq,
148 .end = end_msc_irq, 121 .end = end_msc_irq,
149}; 122};
150 123
151struct irq_chip msc_edgeirq_type = { 124struct irq_chip msc_edgeirq_type = {
152 .typename = "SOC-it-Edge", 125 .typename = "SOC-it-Edge",
153 .startup =startup_msc_irq,
154 .shutdown = shutdown_msc_irq,
155 .enable = enable_msc_irq,
156 .disable = disable_msc_irq,
157 .ack = edge_mask_and_ack_msc_irq, 126 .ack = edge_mask_and_ack_msc_irq,
127 .mask = mask_msc_irq,
128 .mask_ack = edge_mask_and_ack_msc_irq,
129 .unmask = unmask_msc_irq,
130 .eoi = unmask_msc_irq,
158 .end = end_msc_irq, 131 .end = end_msc_irq,
159}; 132};
160 133
@@ -175,14 +148,14 @@ void __init init_msc_irqs(unsigned int base, msc_irqmap_t *imp, int nirq)
175 148
176 switch (imp->im_type) { 149 switch (imp->im_type) {
177 case MSC01_IRQ_EDGE: 150 case MSC01_IRQ_EDGE:
178 irq_desc[base+n].chip = &msc_edgeirq_type; 151 set_irq_chip(base+n, &msc_edgeirq_type);
179 if (cpu_has_veic) 152 if (cpu_has_veic)
180 MSCIC_WRITE(MSC01_IC_SUP+n*8, MSC01_IC_SUP_EDGE_BIT); 153 MSCIC_WRITE(MSC01_IC_SUP+n*8, MSC01_IC_SUP_EDGE_BIT);
181 else 154 else
182 MSCIC_WRITE(MSC01_IC_SUP+n*8, MSC01_IC_SUP_EDGE_BIT | imp->im_lvl); 155 MSCIC_WRITE(MSC01_IC_SUP+n*8, MSC01_IC_SUP_EDGE_BIT | imp->im_lvl);
183 break; 156 break;
184 case MSC01_IRQ_LEVEL: 157 case MSC01_IRQ_LEVEL:
185 irq_desc[base+n].chip = &msc_levelirq_type; 158 set_irq_chip(base+n, &msc_levelirq_type);
186 if (cpu_has_veic) 159 if (cpu_has_veic)
187 MSCIC_WRITE(MSC01_IC_SUP+n*8, 0); 160 MSCIC_WRITE(MSC01_IC_SUP+n*8, 0);
188 else 161 else
diff --git a/arch/mips/kernel/irq-mv6434x.c b/arch/mips/kernel/irq-mv6434x.c
index 37d106202b83..6cfb31cafde2 100644
--- a/arch/mips/kernel/irq-mv6434x.c
+++ b/arch/mips/kernel/irq-mv6434x.c
@@ -67,39 +67,6 @@ static inline void unmask_mv64340_irq(unsigned int irq)
67} 67}
68 68
69/* 69/*
70 * Enables the IRQ on Marvell Chip
71 */
72static void enable_mv64340_irq(unsigned int irq)
73{
74 unmask_mv64340_irq(irq);
75}
76
77/*
78 * Initialize the IRQ on Marvell Chip
79 */
80static unsigned int startup_mv64340_irq(unsigned int irq)
81{
82 unmask_mv64340_irq(irq);
83 return 0;
84}
85
86/*
87 * Disables the IRQ on Marvell Chip
88 */
89static void disable_mv64340_irq(unsigned int irq)
90{
91 mask_mv64340_irq(irq);
92}
93
94/*
95 * Masks and ACKs an IRQ
96 */
97static void mask_and_ack_mv64340_irq(unsigned int irq)
98{
99 mask_mv64340_irq(irq);
100}
101
102/*
103 * End IRQ processing 70 * End IRQ processing
104 */ 71 */
105static void end_mv64340_irq(unsigned int irq) 72static void end_mv64340_irq(unsigned int irq)
@@ -133,15 +100,12 @@ void ll_mv64340_irq(void)
133 do_IRQ(ls1bit32(irq_src_high) + irq_base + 32); 100 do_IRQ(ls1bit32(irq_src_high) + irq_base + 32);
134} 101}
135 102
136#define shutdown_mv64340_irq disable_mv64340_irq
137
138struct irq_chip mv64340_irq_type = { 103struct irq_chip mv64340_irq_type = {
139 .typename = "MV-64340", 104 .typename = "MV-64340",
140 .startup = startup_mv64340_irq, 105 .ack = mask_mv64340_irq,
141 .shutdown = shutdown_mv64340_irq, 106 .mask = mask_mv64340_irq,
142 .enable = enable_mv64340_irq, 107 .mask_ack = mask_mv64340_irq,
143 .disable = disable_mv64340_irq, 108 .unmask = unmask_mv64340_irq,
144 .ack = mask_and_ack_mv64340_irq,
145 .end = end_mv64340_irq, 109 .end = end_mv64340_irq,
146}; 110};
147 111
@@ -149,13 +113,9 @@ void __init mv64340_irq_init(unsigned int base)
149{ 113{
150 int i; 114 int i;
151 115
152 /* Reset irq handlers pointers to NULL */ 116 for (i = base; i < base + 64; i++)
153 for (i = base; i < base + 64; i++) { 117 set_irq_chip_and_handler(i, &mv64340_irq_type,
154 irq_desc[i].status = IRQ_DISABLED; 118 handle_level_irq);
155 irq_desc[i].action = 0;
156 irq_desc[i].depth = 2;
157 irq_desc[i].chip = &mv64340_irq_type;
158 }
159 119
160 irq_base = base; 120 irq_base = base;
161} 121}
diff --git a/arch/mips/kernel/irq-rm7000.c b/arch/mips/kernel/irq-rm7000.c
index 6b54c7109e2e..ddcc2a5f8a06 100644
--- a/arch/mips/kernel/irq-rm7000.c
+++ b/arch/mips/kernel/irq-rm7000.c
@@ -29,42 +29,6 @@ static inline void mask_rm7k_irq(unsigned int irq)
29 clear_c0_intcontrol(0x100 << (irq - irq_base)); 29 clear_c0_intcontrol(0x100 << (irq - irq_base));
30} 30}
31 31
32static inline void rm7k_cpu_irq_enable(unsigned int irq)
33{
34 unsigned long flags;
35
36 local_irq_save(flags);
37 unmask_rm7k_irq(irq);
38 local_irq_restore(flags);
39}
40
41static void rm7k_cpu_irq_disable(unsigned int irq)
42{
43 unsigned long flags;
44
45 local_irq_save(flags);
46 mask_rm7k_irq(irq);
47 local_irq_restore(flags);
48}
49
50static unsigned int rm7k_cpu_irq_startup(unsigned int irq)
51{
52 rm7k_cpu_irq_enable(irq);
53
54 return 0;
55}
56
57#define rm7k_cpu_irq_shutdown rm7k_cpu_irq_disable
58
59/*
60 * While we ack the interrupt interrupts are disabled and thus we don't need
61 * to deal with concurrency issues. Same for rm7k_cpu_irq_end.
62 */
63static void rm7k_cpu_irq_ack(unsigned int irq)
64{
65 mask_rm7k_irq(irq);
66}
67
68static void rm7k_cpu_irq_end(unsigned int irq) 32static void rm7k_cpu_irq_end(unsigned int irq)
69{ 33{
70 if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) 34 if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
@@ -73,11 +37,10 @@ static void rm7k_cpu_irq_end(unsigned int irq)
73 37
74static struct irq_chip rm7k_irq_controller = { 38static struct irq_chip rm7k_irq_controller = {
75 .typename = "RM7000", 39 .typename = "RM7000",
76 .startup = rm7k_cpu_irq_startup, 40 .ack = mask_rm7k_irq,
77 .shutdown = rm7k_cpu_irq_shutdown, 41 .mask = mask_rm7k_irq,
78 .enable = rm7k_cpu_irq_enable, 42 .mask_ack = mask_rm7k_irq,
79 .disable = rm7k_cpu_irq_disable, 43 .unmask = unmask_rm7k_irq,
80 .ack = rm7k_cpu_irq_ack,
81 .end = rm7k_cpu_irq_end, 44 .end = rm7k_cpu_irq_end,
82}; 45};
83 46
@@ -87,12 +50,9 @@ void __init rm7k_cpu_irq_init(int base)
87 50
88 clear_c0_intcontrol(0x00000f00); /* Mask all */ 51 clear_c0_intcontrol(0x00000f00); /* Mask all */
89 52
90 for (i = base; i < base + 4; i++) { 53 for (i = base; i < base + 4; i++)
91 irq_desc[i].status = IRQ_DISABLED; 54 set_irq_chip_and_handler(i, &rm7k_irq_controller,
92 irq_desc[i].action = NULL; 55 handle_level_irq);
93 irq_desc[i].depth = 1;
94 irq_desc[i].chip = &rm7k_irq_controller;
95 }
96 56
97 irq_base = base; 57 irq_base = base;
98} 58}
diff --git a/arch/mips/kernel/irq-rm9000.c b/arch/mips/kernel/irq-rm9000.c
index 62f011ba97a2..ba6440c88abd 100644
--- a/arch/mips/kernel/irq-rm9000.c
+++ b/arch/mips/kernel/irq-rm9000.c
@@ -48,15 +48,6 @@ static void rm9k_cpu_irq_disable(unsigned int irq)
48 local_irq_restore(flags); 48 local_irq_restore(flags);
49} 49}
50 50
51static unsigned int rm9k_cpu_irq_startup(unsigned int irq)
52{
53 rm9k_cpu_irq_enable(irq);
54
55 return 0;
56}
57
58#define rm9k_cpu_irq_shutdown rm9k_cpu_irq_disable
59
60/* 51/*
61 * Performance counter interrupts are global on all processors. 52 * Performance counter interrupts are global on all processors.
62 */ 53 */
@@ -89,16 +80,6 @@ static void rm9k_perfcounter_irq_shutdown(unsigned int irq)
89 on_each_cpu(local_rm9k_perfcounter_irq_shutdown, (void *) irq, 0, 1); 80 on_each_cpu(local_rm9k_perfcounter_irq_shutdown, (void *) irq, 0, 1);
90} 81}
91 82
92
93/*
94 * While we ack the interrupt interrupts are disabled and thus we don't need
95 * to deal with concurrency issues. Same for rm9k_cpu_irq_end.
96 */
97static void rm9k_cpu_irq_ack(unsigned int irq)
98{
99 mask_rm9k_irq(irq);
100}
101
102static void rm9k_cpu_irq_end(unsigned int irq) 83static void rm9k_cpu_irq_end(unsigned int irq)
103{ 84{
104 if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) 85 if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
@@ -107,11 +88,10 @@ static void rm9k_cpu_irq_end(unsigned int irq)
107 88
108static struct irq_chip rm9k_irq_controller = { 89static struct irq_chip rm9k_irq_controller = {
109 .typename = "RM9000", 90 .typename = "RM9000",
110 .startup = rm9k_cpu_irq_startup, 91 .ack = mask_rm9k_irq,
111 .shutdown = rm9k_cpu_irq_shutdown, 92 .mask = mask_rm9k_irq,
112 .enable = rm9k_cpu_irq_enable, 93 .mask_ack = mask_rm9k_irq,
113 .disable = rm9k_cpu_irq_disable, 94 .unmask = unmask_rm9k_irq,
114 .ack = rm9k_cpu_irq_ack,
115 .end = rm9k_cpu_irq_end, 95 .end = rm9k_cpu_irq_end,
116}; 96};
117 97
@@ -119,9 +99,10 @@ static struct irq_chip rm9k_perfcounter_irq = {
119 .typename = "RM9000", 99 .typename = "RM9000",
120 .startup = rm9k_perfcounter_irq_startup, 100 .startup = rm9k_perfcounter_irq_startup,
121 .shutdown = rm9k_perfcounter_irq_shutdown, 101 .shutdown = rm9k_perfcounter_irq_shutdown,
122 .enable = rm9k_cpu_irq_enable, 102 .ack = mask_rm9k_irq,
123 .disable = rm9k_cpu_irq_disable, 103 .mask = mask_rm9k_irq,
124 .ack = rm9k_cpu_irq_ack, 104 .mask_ack = mask_rm9k_irq,
105 .unmask = unmask_rm9k_irq,
125 .end = rm9k_cpu_irq_end, 106 .end = rm9k_cpu_irq_end,
126}; 107};
127 108
@@ -135,15 +116,13 @@ void __init rm9k_cpu_irq_init(int base)
135 116
136 clear_c0_intcontrol(0x0000f000); /* Mask all */ 117 clear_c0_intcontrol(0x0000f000); /* Mask all */
137 118
138 for (i = base; i < base + 4; i++) { 119 for (i = base; i < base + 4; i++)
139 irq_desc[i].status = IRQ_DISABLED; 120 set_irq_chip_and_handler(i, &rm9k_irq_controller,
140 irq_desc[i].action = NULL; 121 handle_level_irq);
141 irq_desc[i].depth = 1;
142 irq_desc[i].chip = &rm9k_irq_controller;
143 }
144 122
145 rm9000_perfcount_irq = base + 1; 123 rm9000_perfcount_irq = base + 1;
146 irq_desc[rm9000_perfcount_irq].chip = &rm9k_perfcounter_irq; 124 set_irq_chip_and_handler(rm9000_perfcount_irq, &rm9k_perfcounter_irq,
125 handle_level_irq);
147 126
148 irq_base = base; 127 irq_base = base;
149} 128}
diff --git a/arch/mips/kernel/irq.c b/arch/mips/kernel/irq.c
index 9b0e49d63d7b..b339798b3172 100644
--- a/arch/mips/kernel/irq.c
+++ b/arch/mips/kernel/irq.c
@@ -88,25 +88,6 @@ atomic_t irq_err_count;
88unsigned long irq_hwmask[NR_IRQS]; 88unsigned long irq_hwmask[NR_IRQS];
89#endif /* CONFIG_MIPS_MT_SMTC */ 89#endif /* CONFIG_MIPS_MT_SMTC */
90 90
91#undef do_IRQ
92
93/*
94 * do_IRQ handles all normal device IRQ's (the special
95 * SMP cross-CPU interrupts have their own specific
96 * handlers).
97 */
98asmlinkage unsigned int do_IRQ(unsigned int irq)
99{
100 irq_enter();
101
102 __DO_IRQ_SMTC_HOOK();
103 __do_IRQ(irq);
104
105 irq_exit();
106
107 return 1;
108}
109
110/* 91/*
111 * Generic, controller-independent functions: 92 * Generic, controller-independent functions:
112 */ 93 */
@@ -172,19 +153,6 @@ __setup("nokgdb", nokgdb);
172 153
173void __init init_IRQ(void) 154void __init init_IRQ(void)
174{ 155{
175 int i;
176
177 for (i = 0; i < NR_IRQS; i++) {
178 irq_desc[i].status = IRQ_DISABLED;
179 irq_desc[i].action = NULL;
180 irq_desc[i].depth = 1;
181 irq_desc[i].chip = &no_irq_chip;
182 spin_lock_init(&irq_desc[i].lock);
183#ifdef CONFIG_MIPS_MT_SMTC
184 irq_hwmask[i] = 0;
185#endif /* CONFIG_MIPS_MT_SMTC */
186 }
187
188 arch_init_irq(); 156 arch_init_irq();
189 157
190#ifdef CONFIG_KGDB 158#ifdef CONFIG_KGDB
diff --git a/arch/mips/kernel/irq_cpu.c b/arch/mips/kernel/irq_cpu.c
index 9bb21c7f2149..be5ac23d3812 100644
--- a/arch/mips/kernel/irq_cpu.c
+++ b/arch/mips/kernel/irq_cpu.c
@@ -50,44 +50,6 @@ static inline void mask_mips_irq(unsigned int irq)
50 irq_disable_hazard(); 50 irq_disable_hazard();
51} 51}
52 52
53static inline void mips_cpu_irq_enable(unsigned int irq)
54{
55 unsigned long flags;
56
57 local_irq_save(flags);
58 unmask_mips_irq(irq);
59 back_to_back_c0_hazard();
60 local_irq_restore(flags);
61}
62
63static void mips_cpu_irq_disable(unsigned int irq)
64{
65 unsigned long flags;
66
67 local_irq_save(flags);
68 mask_mips_irq(irq);
69 back_to_back_c0_hazard();
70 local_irq_restore(flags);
71}
72
73static unsigned int mips_cpu_irq_startup(unsigned int irq)
74{
75 mips_cpu_irq_enable(irq);
76
77 return 0;
78}
79
80#define mips_cpu_irq_shutdown mips_cpu_irq_disable
81
82/*
83 * While we ack the interrupt interrupts are disabled and thus we don't need
84 * to deal with concurrency issues. Same for mips_cpu_irq_end.
85 */
86static void mips_cpu_irq_ack(unsigned int irq)
87{
88 mask_mips_irq(irq);
89}
90
91static void mips_cpu_irq_end(unsigned int irq) 53static void mips_cpu_irq_end(unsigned int irq)
92{ 54{
93 if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) 55 if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
@@ -96,11 +58,11 @@ static void mips_cpu_irq_end(unsigned int irq)
96 58
97static struct irq_chip mips_cpu_irq_controller = { 59static struct irq_chip mips_cpu_irq_controller = {
98 .typename = "MIPS", 60 .typename = "MIPS",
99 .startup = mips_cpu_irq_startup, 61 .ack = mask_mips_irq,
100 .shutdown = mips_cpu_irq_shutdown, 62 .mask = mask_mips_irq,
101 .enable = mips_cpu_irq_enable, 63 .mask_ack = mask_mips_irq,
102 .disable = mips_cpu_irq_disable, 64 .unmask = unmask_mips_irq,
103 .ack = mips_cpu_irq_ack, 65 .eoi = unmask_mips_irq,
104 .end = mips_cpu_irq_end, 66 .end = mips_cpu_irq_end,
105}; 67};
106 68
@@ -110,8 +72,6 @@ static struct irq_chip mips_cpu_irq_controller = {
110 72
111#define unmask_mips_mt_irq unmask_mips_irq 73#define unmask_mips_mt_irq unmask_mips_irq
112#define mask_mips_mt_irq mask_mips_irq 74#define mask_mips_mt_irq mask_mips_irq
113#define mips_mt_cpu_irq_enable mips_cpu_irq_enable
114#define mips_mt_cpu_irq_disable mips_cpu_irq_disable
115 75
116static unsigned int mips_mt_cpu_irq_startup(unsigned int irq) 76static unsigned int mips_mt_cpu_irq_startup(unsigned int irq)
117{ 77{
@@ -119,13 +79,11 @@ static unsigned int mips_mt_cpu_irq_startup(unsigned int irq)
119 79
120 clear_c0_cause(0x100 << (irq - mips_cpu_irq_base)); 80 clear_c0_cause(0x100 << (irq - mips_cpu_irq_base));
121 evpe(vpflags); 81 evpe(vpflags);
122 mips_mt_cpu_irq_enable(irq); 82 unmask_mips_mt_irq(irq);
123 83
124 return 0; 84 return 0;
125} 85}
126 86
127#define mips_mt_cpu_irq_shutdown mips_mt_cpu_irq_disable
128
129/* 87/*
130 * While we ack the interrupt interrupts are disabled and thus we don't need 88 * While we ack the interrupt interrupts are disabled and thus we don't need
131 * to deal with concurrency issues. Same for mips_cpu_irq_end. 89 * to deal with concurrency issues. Same for mips_cpu_irq_end.
@@ -143,10 +101,11 @@ static void mips_mt_cpu_irq_ack(unsigned int irq)
143static struct irq_chip mips_mt_cpu_irq_controller = { 101static struct irq_chip mips_mt_cpu_irq_controller = {
144 .typename = "MIPS", 102 .typename = "MIPS",
145 .startup = mips_mt_cpu_irq_startup, 103 .startup = mips_mt_cpu_irq_startup,
146 .shutdown = mips_mt_cpu_irq_shutdown,
147 .enable = mips_mt_cpu_irq_enable,
148 .disable = mips_mt_cpu_irq_disable,
149 .ack = mips_mt_cpu_irq_ack, 104 .ack = mips_mt_cpu_irq_ack,
105 .mask = mask_mips_mt_irq,
106 .mask_ack = mips_mt_cpu_irq_ack,
107 .unmask = unmask_mips_mt_irq,
108 .eoi = unmask_mips_mt_irq,
150 .end = mips_mt_cpu_irq_end, 109 .end = mips_mt_cpu_irq_end,
151}; 110};
152 111
@@ -163,19 +122,12 @@ void __init mips_cpu_irq_init(int irq_base)
163 * leave them uninitialized for other processors. 122 * leave them uninitialized for other processors.
164 */ 123 */
165 if (cpu_has_mipsmt) 124 if (cpu_has_mipsmt)
166 for (i = irq_base; i < irq_base + 2; i++) { 125 for (i = irq_base; i < irq_base + 2; i++)
167 irq_desc[i].status = IRQ_DISABLED; 126 set_irq_chip(i, &mips_mt_cpu_irq_controller);
168 irq_desc[i].action = NULL; 127
169 irq_desc[i].depth = 1; 128 for (i = irq_base + 2; i < irq_base + 8; i++)
170 irq_desc[i].chip = &mips_mt_cpu_irq_controller; 129 set_irq_chip_and_handler(i, &mips_cpu_irq_controller,
171 } 130 handle_level_irq);
172
173 for (i = irq_base + 2; i < irq_base + 8; i++) {
174 irq_desc[i].status = IRQ_DISABLED;
175 irq_desc[i].action = NULL;
176 irq_desc[i].depth = 1;
177 irq_desc[i].chip = &mips_cpu_irq_controller;
178 }
179 131
180 mips_cpu_irq_base = irq_base; 132 mips_cpu_irq_base = irq_base;
181} 133}
diff --git a/arch/mips/kernel/machine_kexec.c b/arch/mips/kernel/machine_kexec.c
new file mode 100644
index 000000000000..e0ad754c7edd
--- /dev/null
+++ b/arch/mips/kernel/machine_kexec.c
@@ -0,0 +1,85 @@
1/*
2 * machine_kexec.c for kexec
3 * Created by <nschichan@corp.free.fr> on Thu Oct 12 15:15:06 2006
4 *
5 * This source code is licensed under the GNU General Public License,
6 * Version 2. See the file COPYING for more details.
7 */
8
9#include <linux/kexec.h>
10#include <linux/mm.h>
11#include <linux/delay.h>
12
13#include <asm/cacheflush.h>
14#include <asm/page.h>
15
16const extern unsigned char relocate_new_kernel[];
17const extern unsigned int relocate_new_kernel_size;
18
19extern unsigned long kexec_start_address;
20extern unsigned long kexec_indirection_page;
21
22int
23machine_kexec_prepare(struct kimage *kimage)
24{
25 return 0;
26}
27
28void
29machine_kexec_cleanup(struct kimage *kimage)
30{
31}
32
33void
34machine_shutdown(void)
35{
36}
37
38void
39machine_crash_shutdown(struct pt_regs *regs)
40{
41}
42
43void
44machine_kexec(struct kimage *image)
45{
46 unsigned long reboot_code_buffer;
47 unsigned long entry;
48 unsigned long *ptr;
49
50 reboot_code_buffer =
51 (unsigned long)page_address(image->control_code_page);
52
53 kexec_start_address = image->start;
54 kexec_indirection_page = phys_to_virt(image->head & PAGE_MASK);
55
56 memcpy((void*)reboot_code_buffer, relocate_new_kernel,
57 relocate_new_kernel_size);
58
59 /*
60 * The generic kexec code builds a page list with physical
61 * addresses. they are directly accessible through KSEG0 (or
62 * CKSEG0 or XPHYS if on 64bit system), hence the
63 * pys_to_virt() call.
64 */
65 for (ptr = &image->head; (entry = *ptr) && !(entry &IND_DONE);
66 ptr = (entry & IND_INDIRECTION) ?
67 phys_to_virt(entry & PAGE_MASK) : ptr + 1) {
68 if (*ptr & IND_SOURCE || *ptr & IND_INDIRECTION ||
69 *ptr & IND_DESTINATION)
70 *ptr = phys_to_virt(*ptr);
71 }
72
73 /*
74 * we do not want to be bothered.
75 */
76 local_irq_disable();
77
78 flush_icache_range(reboot_code_buffer,
79 reboot_code_buffer + KEXEC_CONTROL_CODE_SIZE);
80
81 printk("Will call new kernel at %08x\n", image->start);
82 printk("Bye ...\n");
83 flush_cache_all();
84 ((void (*)(void))reboot_code_buffer)();
85}
diff --git a/arch/mips/kernel/module.c b/arch/mips/kernel/module.c
index d7bf0215bc1d..cb0801437b66 100644
--- a/arch/mips/kernel/module.c
+++ b/arch/mips/kernel/module.c
@@ -29,6 +29,7 @@
29#include <linux/kernel.h> 29#include <linux/kernel.h>
30#include <linux/module.h> 30#include <linux/module.h>
31#include <linux/spinlock.h> 31#include <linux/spinlock.h>
32#include <asm/pgtable.h> /* MODULE_START */
32 33
33struct mips_hi16 { 34struct mips_hi16 {
34 struct mips_hi16 *next; 35 struct mips_hi16 *next;
@@ -43,9 +44,23 @@ static DEFINE_SPINLOCK(dbe_lock);
43 44
44void *module_alloc(unsigned long size) 45void *module_alloc(unsigned long size)
45{ 46{
47#ifdef MODULE_START
48 struct vm_struct *area;
49
50 size = PAGE_ALIGN(size);
51 if (!size)
52 return NULL;
53
54 area = __get_vm_area(size, VM_ALLOC, MODULE_START, MODULE_END);
55 if (!area)
56 return NULL;
57
58 return __vmalloc_area(area, GFP_KERNEL, PAGE_KERNEL);
59#else
46 if (size == 0) 60 if (size == 0)
47 return NULL; 61 return NULL;
48 return vmalloc(size); 62 return vmalloc(size);
63#endif
49} 64}
50 65
51/* Free memory returned from module_alloc */ 66/* Free memory returned from module_alloc */
diff --git a/arch/mips/kernel/relocate_kernel.S b/arch/mips/kernel/relocate_kernel.S
new file mode 100644
index 000000000000..a3f0d00c1334
--- /dev/null
+++ b/arch/mips/kernel/relocate_kernel.S
@@ -0,0 +1,80 @@
1/*
2 * relocate_kernel.S for kexec
3 * Created by <nschichan@corp.free.fr> on Thu Oct 12 17:49:57 2006
4 *
5 * This source code is licensed under the GNU General Public License,
6 * Version 2. See the file COPYING for more details.
7 */
8
9#include <asm/asm.h>
10#include <asm/asmmacro.h>
11#include <asm/regdef.h>
12#include <asm/page.h>
13#include <asm/mipsregs.h>
14#include <asm/stackframe.h>
15#include <asm/addrspace.h>
16
17 .globl relocate_new_kernel
18relocate_new_kernel:
19
20 PTR_L s0, kexec_indirection_page
21 PTR_L s1, kexec_start_address
22
23process_entry:
24 PTR_L s2, (s0)
25 PTR_ADD s0, s0, SZREG
26
27 /* destination page */
28 and s3, s2, 0x1
29 beq s3, zero, 1f
30 and s4, s2, ~0x1 /* store destination addr in s4 */
31 move a0, s4
32 b process_entry
33
341:
35 /* indirection page, update s0 */
36 and s3, s2, 0x2
37 beq s3, zero, 1f
38 and s0, s2, ~0x2
39 b process_entry
40
411:
42 /* done page */
43 and s3, s2, 0x4
44 beq s3, zero, 1f
45 b done
461:
47 /* source page */
48 and s3, s2, 0x8
49 beq s3, zero, process_entry
50 and s2, s2, ~0x8
51 li s6, (1 << PAGE_SHIFT) / SZREG
52
53copy_word:
54 /* copy page word by word */
55 REG_L s5, (s2)
56 REG_S s5, (s4)
57 INT_ADD s4, s4, SZREG
58 INT_ADD s2, s2, SZREG
59 INT_SUB s6, s6, 1
60 beq s6, zero, process_entry
61 b copy_word
62 b process_entry
63
64done:
65 /* jump to kexec_start_address */
66 j s1
67
68 .globl kexec_start_address
69kexec_start_address:
70 .long 0x0
71
72 .globl kexec_indirection_page
73kexec_indirection_page:
74 .long 0x0
75
76relocate_new_kernel_end:
77
78 .globl relocate_new_kernel_size
79relocate_new_kernel_size:
80 .long relocate_new_kernel_end - relocate_new_kernel
diff --git a/arch/mips/kernel/scall32-o32.S b/arch/mips/kernel/scall32-o32.S
index a95f37de080e..7c0b3936ba44 100644
--- a/arch/mips/kernel/scall32-o32.S
+++ b/arch/mips/kernel/scall32-o32.S
@@ -653,7 +653,7 @@ einval: li v0, -EINVAL
653 sys sys_move_pages 6 653 sys sys_move_pages 6
654 sys sys_set_robust_list 2 654 sys sys_set_robust_list 2
655 sys sys_get_robust_list 3 /* 4310 */ 655 sys sys_get_robust_list 3 /* 4310 */
656 sys sys_ni_syscall 0 656 sys sys_kexec_load 4
657 sys sys_getcpu 3 657 sys sys_getcpu 3
658 sys sys_epoll_pwait 6 658 sys sys_epoll_pwait 6
659 .endm 659 .endm
diff --git a/arch/mips/kernel/scall64-64.S b/arch/mips/kernel/scall64-64.S
index 8fb0f60f657b..e569b846e9a3 100644
--- a/arch/mips/kernel/scall64-64.S
+++ b/arch/mips/kernel/scall64-64.S
@@ -468,6 +468,6 @@ sys_call_table:
468 PTR sys_move_pages 468 PTR sys_move_pages
469 PTR sys_set_robust_list 469 PTR sys_set_robust_list
470 PTR sys_get_robust_list 470 PTR sys_get_robust_list
471 PTR sys_ni_syscall /* 5270 */ 471 PTR sys_kexec_load /* 5270 */
472 PTR sys_getcpu 472 PTR sys_getcpu
473 PTR sys_epoll_pwait 473 PTR sys_epoll_pwait
diff --git a/arch/mips/kernel/scall64-n32.S b/arch/mips/kernel/scall64-n32.S
index 0da5ca2040ff..5b18f265d75b 100644
--- a/arch/mips/kernel/scall64-n32.S
+++ b/arch/mips/kernel/scall64-n32.S
@@ -394,6 +394,6 @@ EXPORT(sysn32_call_table)
394 PTR sys_move_pages 394 PTR sys_move_pages
395 PTR compat_sys_set_robust_list 395 PTR compat_sys_set_robust_list
396 PTR compat_sys_get_robust_list 396 PTR compat_sys_get_robust_list
397 PTR sys_ni_syscall 397 PTR compat_sys_kexec_load
398 PTR sys_getcpu 398 PTR sys_getcpu
399 PTR sys_epoll_pwait 399 PTR sys_epoll_pwait
diff --git a/arch/mips/kernel/scall64-o32.S b/arch/mips/kernel/scall64-o32.S
index b9d00cae8b5f..e91379c1be1d 100644
--- a/arch/mips/kernel/scall64-o32.S
+++ b/arch/mips/kernel/scall64-o32.S
@@ -516,7 +516,7 @@ sys_call_table:
516 PTR compat_sys_move_pages 516 PTR compat_sys_move_pages
517 PTR compat_sys_set_robust_list 517 PTR compat_sys_set_robust_list
518 PTR compat_sys_get_robust_list /* 4310 */ 518 PTR compat_sys_get_robust_list /* 4310 */
519 PTR sys_ni_syscall 519 PTR compat_sys_kexec_load
520 PTR sys_getcpu 520 PTR sys_getcpu
521 PTR sys_epoll_pwait 521 PTR sys_epoll_pwait
522 .size sys_call_table,.-sys_call_table 522 .size sys_call_table,.-sys_call_table
diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c
index 8f6e89697ccf..89440a0d8528 100644
--- a/arch/mips/kernel/setup.c
+++ b/arch/mips/kernel/setup.c
@@ -145,13 +145,12 @@ static int __init rd_start_early(char *p)
145 unsigned long start = memparse(p, &p); 145 unsigned long start = memparse(p, &p);
146 146
147#ifdef CONFIG_64BIT 147#ifdef CONFIG_64BIT
148 /* HACK: Guess if the sign extension was forgotten */ 148 /* Guess if the sign extension was forgotten by bootloader */
149 if (start > 0x0000000080000000 && start < 0x00000000ffffffff) 149 if (start < XKPHYS)
150 start |= 0xffffffff00000000UL; 150 start = (int)start;
151#endif 151#endif
152 initrd_start = start; 152 initrd_start = start;
153 initrd_end += start; 153 initrd_end += start;
154
155 return 0; 154 return 0;
156} 155}
157early_param("rd_start", rd_start_early); 156early_param("rd_start", rd_start_early);
@@ -159,41 +158,64 @@ early_param("rd_start", rd_start_early);
159static int __init rd_size_early(char *p) 158static int __init rd_size_early(char *p)
160{ 159{
161 initrd_end += memparse(p, &p); 160 initrd_end += memparse(p, &p);
162
163 return 0; 161 return 0;
164} 162}
165early_param("rd_size", rd_size_early); 163early_param("rd_size", rd_size_early);
166 164
165/* it returns the next free pfn after initrd */
167static unsigned long __init init_initrd(void) 166static unsigned long __init init_initrd(void)
168{ 167{
169 unsigned long tmp, end, size; 168 unsigned long end;
170 u32 *initrd_header; 169 u32 *initrd_header;
171 170
172 ROOT_DEV = Root_RAM0;
173
174 /* 171 /*
175 * Board specific code or command line parser should have 172 * Board specific code or command line parser should have
176 * already set up initrd_start and initrd_end. In these cases 173 * already set up initrd_start and initrd_end. In these cases
177 * perfom sanity checks and use them if all looks good. 174 * perfom sanity checks and use them if all looks good.
178 */ 175 */
179 size = initrd_end - initrd_start; 176 if (initrd_start && initrd_end > initrd_start)
180 if (initrd_end == 0 || size == 0) { 177 goto sanitize;
181 initrd_start = 0; 178
182 initrd_end = 0; 179 /*
183 } else 180 * See if initrd has been added to the kernel image by
184 return initrd_end; 181 * arch/mips/boot/addinitrd.c. In that case a header is
185 182 * prepended to initrd and is made up by 8 bytes. The fisrt
186 end = (unsigned long)&_end; 183 * word is a magic number and the second one is the size of
187 tmp = PAGE_ALIGN(end) - sizeof(u32) * 2; 184 * initrd. Initrd start must be page aligned in any cases.
188 if (tmp < end) 185 */
189 tmp += PAGE_SIZE; 186 initrd_header = __va(PAGE_ALIGN(__pa_symbol(&_end) + 8)) - 8;
190 187 if (initrd_header[0] != 0x494E5244)
191 initrd_header = (u32 *)tmp; 188 goto disable;
192 if (initrd_header[0] == 0x494E5244) { 189 initrd_start = (unsigned long)(initrd_header + 2);
193 initrd_start = (unsigned long)&initrd_header[2]; 190 initrd_end = initrd_start + initrd_header[1];
194 initrd_end = initrd_start + initrd_header[1]; 191
192sanitize:
193 if (initrd_start & ~PAGE_MASK) {
194 printk(KERN_ERR "initrd start must be page aligned\n");
195 goto disable;
195 } 196 }
196 return initrd_end; 197 if (initrd_start < PAGE_OFFSET) {
198 printk(KERN_ERR "initrd start < PAGE_OFFSET\n");
199 goto disable;
200 }
201
202 /*
203 * Sanitize initrd addresses. For example firmware
204 * can't guess if they need to pass them through
205 * 64-bits values if the kernel has been built in pure
206 * 32-bit. We need also to switch from KSEG0 to XKPHYS
207 * addresses now, so the code can now safely use __pa().
208 */
209 end = __pa(initrd_end);
210 initrd_end = (unsigned long)__va(end);
211 initrd_start = (unsigned long)__va(__pa(initrd_start));
212
213 ROOT_DEV = Root_RAM0;
214 return PFN_UP(end);
215disable:
216 initrd_start = 0;
217 initrd_end = 0;
218 return 0;
197} 219}
198 220
199static void __init finalize_initrd(void) 221static void __init finalize_initrd(void)
@@ -204,12 +226,12 @@ static void __init finalize_initrd(void)
204 printk(KERN_INFO "Initrd not found or empty"); 226 printk(KERN_INFO "Initrd not found or empty");
205 goto disable; 227 goto disable;
206 } 228 }
207 if (CPHYSADDR(initrd_end) > PFN_PHYS(max_low_pfn)) { 229 if (__pa(initrd_end) > PFN_PHYS(max_low_pfn)) {
208 printk("Initrd extends beyond end of memory"); 230 printk("Initrd extends beyond end of memory");
209 goto disable; 231 goto disable;
210 } 232 }
211 233
212 reserve_bootmem(CPHYSADDR(initrd_start), size); 234 reserve_bootmem(__pa(initrd_start), size);
213 initrd_below_start_ok = 1; 235 initrd_below_start_ok = 1;
214 236
215 printk(KERN_INFO "Initial ramdisk at: 0x%lx (%lu bytes)\n", 237 printk(KERN_INFO "Initial ramdisk at: 0x%lx (%lu bytes)\n",
@@ -259,8 +281,7 @@ static void __init bootmem_init(void)
259 * not selected. Once that done we can determine the low bound 281 * not selected. Once that done we can determine the low bound
260 * of usable memory. 282 * of usable memory.
261 */ 283 */
262 reserved_end = init_initrd(); 284 reserved_end = max(init_initrd(), PFN_UP(__pa_symbol(&_end)));
263 reserved_end = PFN_UP(CPHYSADDR(max(reserved_end, (unsigned long)&_end)));
264 285
265 /* 286 /*
266 * Find the highest page frame number we have available. 287 * Find the highest page frame number we have available.
@@ -432,10 +453,10 @@ static void __init resource_init(void)
432 if (UNCAC_BASE != IO_BASE) 453 if (UNCAC_BASE != IO_BASE)
433 return; 454 return;
434 455
435 code_resource.start = virt_to_phys(&_text); 456 code_resource.start = __pa_symbol(&_text);
436 code_resource.end = virt_to_phys(&_etext) - 1; 457 code_resource.end = __pa_symbol(&_etext) - 1;
437 data_resource.start = virt_to_phys(&_etext); 458 data_resource.start = __pa_symbol(&_etext);
438 data_resource.end = virt_to_phys(&_edata) - 1; 459 data_resource.end = __pa_symbol(&_edata) - 1;
439 460
440 /* 461 /*
441 * Request address space for all standard RAM. 462 * Request address space for all standard RAM.
diff --git a/arch/mips/kernel/signal_n32.c b/arch/mips/kernel/signal_n32.c
index 477c5334ec1b..a67c18555ed3 100644
--- a/arch/mips/kernel/signal_n32.c
+++ b/arch/mips/kernel/signal_n32.c
@@ -17,7 +17,6 @@
17 */ 17 */
18#include <linux/cache.h> 18#include <linux/cache.h>
19#include <linux/sched.h> 19#include <linux/sched.h>
20#include <linux/sched.h>
21#include <linux/mm.h> 20#include <linux/mm.h>
22#include <linux/smp.h> 21#include <linux/smp.h>
23#include <linux/smp_lock.h> 22#include <linux/smp_lock.h>
diff --git a/arch/mips/kernel/smp-mt.c b/arch/mips/kernel/smp-mt.c
index 2ac19a6cbf68..1ee689c0e0c9 100644
--- a/arch/mips/kernel/smp-mt.c
+++ b/arch/mips/kernel/smp-mt.c
@@ -278,7 +278,9 @@ void __init plat_prepare_cpus(unsigned int max_cpus)
278 278
279 /* need to mark IPI's as IRQ_PER_CPU */ 279 /* need to mark IPI's as IRQ_PER_CPU */
280 irq_desc[cpu_ipi_resched_irq].status |= IRQ_PER_CPU; 280 irq_desc[cpu_ipi_resched_irq].status |= IRQ_PER_CPU;
281 set_irq_handler(cpu_ipi_resched_irq, handle_percpu_irq);
281 irq_desc[cpu_ipi_call_irq].status |= IRQ_PER_CPU; 282 irq_desc[cpu_ipi_call_irq].status |= IRQ_PER_CPU;
283 set_irq_handler(cpu_ipi_call_irq, handle_percpu_irq);
282} 284}
283 285
284/* 286/*
diff --git a/arch/mips/kernel/smtc.c b/arch/mips/kernel/smtc.c
index 3b78caf112f5..802febed7df5 100644
--- a/arch/mips/kernel/smtc.c
+++ b/arch/mips/kernel/smtc.c
@@ -1009,6 +1009,7 @@ void setup_cross_vpe_interrupts(void)
1009 setup_irq_smtc(cpu_ipi_irq, &irq_ipi, (0x100 << MIPS_CPU_IPI_IRQ)); 1009 setup_irq_smtc(cpu_ipi_irq, &irq_ipi, (0x100 << MIPS_CPU_IPI_IRQ));
1010 1010
1011 irq_desc[cpu_ipi_irq].status |= IRQ_PER_CPU; 1011 irq_desc[cpu_ipi_irq].status |= IRQ_PER_CPU;
1012 set_irq_handler(cpu_ipi_irq, handle_percpu_irq);
1012} 1013}
1013 1014
1014/* 1015/*
diff --git a/arch/mips/kernel/time.c b/arch/mips/kernel/time.c
index e535f86efa2f..11aab6d6bfe5 100644
--- a/arch/mips/kernel/time.c
+++ b/arch/mips/kernel/time.c
@@ -11,7 +11,6 @@
11 * Free Software Foundation; either version 2 of the License, or (at your 11 * Free Software Foundation; either version 2 of the License, or (at your
12 * option) any later version. 12 * option) any later version.
13 */ 13 */
14#include <linux/clocksource.h>
15#include <linux/types.h> 14#include <linux/types.h>
16#include <linux/kernel.h> 15#include <linux/kernel.h>
17#include <linux/init.h> 16#include <linux/init.h>
@@ -83,17 +82,11 @@ static void null_timer_ack(void) { /* nothing */ }
83/* 82/*
84 * Null high precision timer functions for systems lacking one. 83 * Null high precision timer functions for systems lacking one.
85 */ 84 */
86static unsigned int null_hpt_read(void) 85static cycle_t null_hpt_read(void)
87{ 86{
88 return 0; 87 return 0;
89} 88}
90 89
91static void __init null_hpt_init(void)
92{
93 /* nothing */
94}
95
96
97/* 90/*
98 * Timer ack for an R4k-compatible timer of a known frequency. 91 * Timer ack for an R4k-compatible timer of a known frequency.
99 */ 92 */
@@ -118,7 +111,7 @@ static void c0_timer_ack(void)
118/* 111/*
119 * High precision timer functions for a R4k-compatible timer. 112 * High precision timer functions for a R4k-compatible timer.
120 */ 113 */
121static unsigned int c0_hpt_read(void) 114static cycle_t c0_hpt_read(void)
122{ 115{
123 return read_c0_count(); 116 return read_c0_count();
124} 117}
@@ -132,9 +125,6 @@ static void __init c0_hpt_timer_init(void)
132 125
133int (*mips_timer_state)(void); 126int (*mips_timer_state)(void);
134void (*mips_timer_ack)(void); 127void (*mips_timer_ack)(void);
135unsigned int (*mips_hpt_read)(void);
136void (*mips_hpt_init)(void) __initdata = null_hpt_init;
137unsigned int mips_hpt_mask = 0xffffffff;
138 128
139/* last time when xtime and rtc are sync'ed up */ 129/* last time when xtime and rtc are sync'ed up */
140static long last_rtc_update; 130static long last_rtc_update;
@@ -276,8 +266,7 @@ static struct irqaction timer_irqaction = {
276 266
277static unsigned int __init calibrate_hpt(void) 267static unsigned int __init calibrate_hpt(void)
278{ 268{
279 u64 frequency; 269 cycle_t frequency, hpt_start, hpt_end, hpt_count, hz;
280 u32 hpt_start, hpt_end, hpt_count, hz;
281 270
282 const int loops = HZ / 10; 271 const int loops = HZ / 10;
283 int log_2_loops = 0; 272 int log_2_loops = 0;
@@ -303,28 +292,23 @@ static unsigned int __init calibrate_hpt(void)
303 * during the calculated number of periods between timer 292 * during the calculated number of periods between timer
304 * interrupts. 293 * interrupts.
305 */ 294 */
306 hpt_start = mips_hpt_read(); 295 hpt_start = clocksource_mips.read();
307 do { 296 do {
308 while (mips_timer_state()); 297 while (mips_timer_state());
309 while (!mips_timer_state()); 298 while (!mips_timer_state());
310 } while (--i); 299 } while (--i);
311 hpt_end = mips_hpt_read(); 300 hpt_end = clocksource_mips.read();
312 301
313 hpt_count = (hpt_end - hpt_start) & mips_hpt_mask; 302 hpt_count = (hpt_end - hpt_start) & clocksource_mips.mask;
314 hz = HZ; 303 hz = HZ;
315 frequency = (u64)hpt_count * (u64)hz; 304 frequency = hpt_count * hz;
316 305
317 return frequency >> log_2_loops; 306 return frequency >> log_2_loops;
318} 307}
319 308
320static cycle_t read_mips_hpt(void) 309struct clocksource clocksource_mips = {
321{
322 return (cycle_t)mips_hpt_read();
323}
324
325static struct clocksource clocksource_mips = {
326 .name = "MIPS", 310 .name = "MIPS",
327 .read = read_mips_hpt, 311 .mask = 0xffffffff,
328 .is_continuous = 1, 312 .is_continuous = 1,
329}; 313};
330 314
@@ -333,7 +317,7 @@ static void __init init_mips_clocksource(void)
333 u64 temp; 317 u64 temp;
334 u32 shift; 318 u32 shift;
335 319
336 if (!mips_hpt_frequency || mips_hpt_read == null_hpt_read) 320 if (!mips_hpt_frequency || clocksource_mips.read == null_hpt_read)
337 return; 321 return;
338 322
339 /* Calclate a somewhat reasonable rating value */ 323 /* Calclate a somewhat reasonable rating value */
@@ -347,7 +331,6 @@ static void __init init_mips_clocksource(void)
347 } 331 }
348 clocksource_mips.shift = shift; 332 clocksource_mips.shift = shift;
349 clocksource_mips.mult = (u32)temp; 333 clocksource_mips.mult = (u32)temp;
350 clocksource_mips.mask = mips_hpt_mask;
351 334
352 clocksource_register(&clocksource_mips); 335 clocksource_register(&clocksource_mips);
353} 336}
@@ -367,32 +350,36 @@ void __init time_init(void)
367 -xtime.tv_sec, -xtime.tv_nsec); 350 -xtime.tv_sec, -xtime.tv_nsec);
368 351
369 /* Choose appropriate high precision timer routines. */ 352 /* Choose appropriate high precision timer routines. */
370 if (!cpu_has_counter && !mips_hpt_read) 353 if (!cpu_has_counter && !clocksource_mips.read)
371 /* No high precision timer -- sorry. */ 354 /* No high precision timer -- sorry. */
372 mips_hpt_read = null_hpt_read; 355 clocksource_mips.read = null_hpt_read;
373 else if (!mips_hpt_frequency && !mips_timer_state) { 356 else if (!mips_hpt_frequency && !mips_timer_state) {
374 /* A high precision timer of unknown frequency. */ 357 /* A high precision timer of unknown frequency. */
375 if (!mips_hpt_read) 358 if (!clocksource_mips.read)
376 /* No external high precision timer -- use R4k. */ 359 /* No external high precision timer -- use R4k. */
377 mips_hpt_read = c0_hpt_read; 360 clocksource_mips.read = c0_hpt_read;
378 } else { 361 } else {
379 /* We know counter frequency. Or we can get it. */ 362 /* We know counter frequency. Or we can get it. */
380 if (!mips_hpt_read) { 363 if (!clocksource_mips.read) {
381 /* No external high precision timer -- use R4k. */ 364 /* No external high precision timer -- use R4k. */
382 mips_hpt_read = c0_hpt_read; 365 clocksource_mips.read = c0_hpt_read;
383 366
384 if (!mips_timer_state) { 367 if (!mips_timer_state) {
385 /* No external timer interrupt -- use R4k. */ 368 /* No external timer interrupt -- use R4k. */
386 mips_hpt_init = c0_hpt_timer_init;
387 mips_timer_ack = c0_timer_ack; 369 mips_timer_ack = c0_timer_ack;
370 /* Calculate cache parameters. */
371 cycles_per_jiffy =
372 (mips_hpt_frequency + HZ / 2) / HZ;
373 /*
374 * This sets up the high precision
375 * timer for the first interrupt.
376 */
377 c0_hpt_timer_init();
388 } 378 }
389 } 379 }
390 if (!mips_hpt_frequency) 380 if (!mips_hpt_frequency)
391 mips_hpt_frequency = calibrate_hpt(); 381 mips_hpt_frequency = calibrate_hpt();
392 382
393 /* Calculate cache parameters. */
394 cycles_per_jiffy = (mips_hpt_frequency + HZ / 2) / HZ;
395
396 /* Report the high precision timer rate for a reference. */ 383 /* Report the high precision timer rate for a reference. */
397 printk("Using %u.%03u MHz high precision timer.\n", 384 printk("Using %u.%03u MHz high precision timer.\n",
398 ((mips_hpt_frequency + 500) / 1000) / 1000, 385 ((mips_hpt_frequency + 500) / 1000) / 1000,
@@ -403,9 +390,6 @@ void __init time_init(void)
403 /* No timer interrupt ack (e.g. i8254). */ 390 /* No timer interrupt ack (e.g. i8254). */
404 mips_timer_ack = null_timer_ack; 391 mips_timer_ack = null_timer_ack;
405 392
406 /* This sets up the high precision timer for the first interrupt. */
407 mips_hpt_init();
408
409 /* 393 /*
410 * Call board specific timer interrupt setup. 394 * Call board specific timer interrupt setup.
411 * 395 *
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index 9fda1b8be3a7..2a932cada244 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -54,6 +54,8 @@ extern asmlinkage void handle_dbe(void);
54extern asmlinkage void handle_sys(void); 54extern asmlinkage void handle_sys(void);
55extern asmlinkage void handle_bp(void); 55extern asmlinkage void handle_bp(void);
56extern asmlinkage void handle_ri(void); 56extern asmlinkage void handle_ri(void);
57extern asmlinkage void handle_ri_rdhwr_vivt(void);
58extern asmlinkage void handle_ri_rdhwr(void);
57extern asmlinkage void handle_cpu(void); 59extern asmlinkage void handle_cpu(void);
58extern asmlinkage void handle_ov(void); 60extern asmlinkage void handle_ov(void);
59extern asmlinkage void handle_tr(void); 61extern asmlinkage void handle_tr(void);
@@ -397,19 +399,6 @@ asmlinkage void do_be(struct pt_regs *regs)
397 force_sig(SIGBUS, current); 399 force_sig(SIGBUS, current);
398} 400}
399 401
400static inline int get_insn_opcode(struct pt_regs *regs, unsigned int *opcode)
401{
402 unsigned int __user *epc;
403
404 epc = (unsigned int __user *) regs->cp0_epc +
405 ((regs->cp0_cause & CAUSEF_BD) != 0);
406 if (!get_user(*opcode, epc))
407 return 0;
408
409 force_sig(SIGSEGV, current);
410 return 1;
411}
412
413/* 402/*
414 * ll/sc emulation 403 * ll/sc emulation
415 */ 404 */
@@ -544,8 +533,8 @@ static inline int simulate_llsc(struct pt_regs *regs)
544{ 533{
545 unsigned int opcode; 534 unsigned int opcode;
546 535
547 if (unlikely(get_insn_opcode(regs, &opcode))) 536 if (get_user(opcode, (unsigned int __user *) exception_epc(regs)))
548 return -EFAULT; 537 goto out_sigsegv;
549 538
550 if ((opcode & OPCODE) == LL) { 539 if ((opcode & OPCODE) == LL) {
551 simulate_ll(regs, opcode); 540 simulate_ll(regs, opcode);
@@ -557,6 +546,10 @@ static inline int simulate_llsc(struct pt_regs *regs)
557 } 546 }
558 547
559 return -EFAULT; /* Strange things going on ... */ 548 return -EFAULT; /* Strange things going on ... */
549
550out_sigsegv:
551 force_sig(SIGSEGV, current);
552 return -EFAULT;
560} 553}
561 554
562/* 555/*
@@ -569,8 +562,8 @@ static inline int simulate_rdhwr(struct pt_regs *regs)
569 struct thread_info *ti = task_thread_info(current); 562 struct thread_info *ti = task_thread_info(current);
570 unsigned int opcode; 563 unsigned int opcode;
571 564
572 if (unlikely(get_insn_opcode(regs, &opcode))) 565 if (get_user(opcode, (unsigned int __user *) exception_epc(regs)))
573 return -EFAULT; 566 goto out_sigsegv;
574 567
575 if (unlikely(compute_return_epc(regs))) 568 if (unlikely(compute_return_epc(regs)))
576 return -EFAULT; 569 return -EFAULT;
@@ -589,6 +582,10 @@ static inline int simulate_rdhwr(struct pt_regs *regs)
589 582
590 /* Not ours. */ 583 /* Not ours. */
591 return -EFAULT; 584 return -EFAULT;
585
586out_sigsegv:
587 force_sig(SIGSEGV, current);
588 return -EFAULT;
592} 589}
593 590
594asmlinkage void do_ov(struct pt_regs *regs) 591asmlinkage void do_ov(struct pt_regs *regs)
@@ -672,10 +669,8 @@ asmlinkage void do_bp(struct pt_regs *regs)
672 unsigned int opcode, bcode; 669 unsigned int opcode, bcode;
673 siginfo_t info; 670 siginfo_t info;
674 671
675 die_if_kernel("Break instruction in kernel code", regs); 672 if (get_user(opcode, (unsigned int __user *) exception_epc(regs)))
676 673 goto out_sigsegv;
677 if (get_insn_opcode(regs, &opcode))
678 return;
679 674
680 /* 675 /*
681 * There is the ancient bug in the MIPS assemblers that the break 676 * There is the ancient bug in the MIPS assemblers that the break
@@ -696,6 +691,7 @@ asmlinkage void do_bp(struct pt_regs *regs)
696 switch (bcode) { 691 switch (bcode) {
697 case BRK_OVERFLOW << 10: 692 case BRK_OVERFLOW << 10:
698 case BRK_DIVZERO << 10: 693 case BRK_DIVZERO << 10:
694 die_if_kernel("Break instruction in kernel code", regs);
699 if (bcode == (BRK_DIVZERO << 10)) 695 if (bcode == (BRK_DIVZERO << 10))
700 info.si_code = FPE_INTDIV; 696 info.si_code = FPE_INTDIV;
701 else 697 else
@@ -705,9 +701,16 @@ asmlinkage void do_bp(struct pt_regs *regs)
705 info.si_addr = (void __user *) regs->cp0_epc; 701 info.si_addr = (void __user *) regs->cp0_epc;
706 force_sig_info(SIGFPE, &info, current); 702 force_sig_info(SIGFPE, &info, current);
707 break; 703 break;
704 case BRK_BUG:
705 die("Kernel bug detected", regs);
706 break;
708 default: 707 default:
708 die_if_kernel("Break instruction in kernel code", regs);
709 force_sig(SIGTRAP, current); 709 force_sig(SIGTRAP, current);
710 } 710 }
711
712out_sigsegv:
713 force_sig(SIGSEGV, current);
711} 714}
712 715
713asmlinkage void do_tr(struct pt_regs *regs) 716asmlinkage void do_tr(struct pt_regs *regs)
@@ -715,10 +718,8 @@ asmlinkage void do_tr(struct pt_regs *regs)
715 unsigned int opcode, tcode = 0; 718 unsigned int opcode, tcode = 0;
716 siginfo_t info; 719 siginfo_t info;
717 720
718 die_if_kernel("Trap instruction in kernel code", regs); 721 if (get_user(opcode, (unsigned int __user *) exception_epc(regs)))
719 722 goto out_sigsegv;
720 if (get_insn_opcode(regs, &opcode))
721 return;
722 723
723 /* Immediate versions don't provide a code. */ 724 /* Immediate versions don't provide a code. */
724 if (!(opcode & OPCODE)) 725 if (!(opcode & OPCODE))
@@ -733,6 +734,7 @@ asmlinkage void do_tr(struct pt_regs *regs)
733 switch (tcode) { 734 switch (tcode) {
734 case BRK_OVERFLOW: 735 case BRK_OVERFLOW:
735 case BRK_DIVZERO: 736 case BRK_DIVZERO:
737 die_if_kernel("Trap instruction in kernel code", regs);
736 if (tcode == BRK_DIVZERO) 738 if (tcode == BRK_DIVZERO)
737 info.si_code = FPE_INTDIV; 739 info.si_code = FPE_INTDIV;
738 else 740 else
@@ -742,9 +744,16 @@ asmlinkage void do_tr(struct pt_regs *regs)
742 info.si_addr = (void __user *) regs->cp0_epc; 744 info.si_addr = (void __user *) regs->cp0_epc;
743 force_sig_info(SIGFPE, &info, current); 745 force_sig_info(SIGFPE, &info, current);
744 break; 746 break;
747 case BRK_BUG:
748 die("Kernel bug detected", regs);
749 break;
745 default: 750 default:
751 die_if_kernel("Trap instruction in kernel code", regs);
746 force_sig(SIGTRAP, current); 752 force_sig(SIGTRAP, current);
747 } 753 }
754
755out_sigsegv:
756 force_sig(SIGSEGV, current);
748} 757}
749 758
750asmlinkage void do_ri(struct pt_regs *regs) 759asmlinkage void do_ri(struct pt_regs *regs)
@@ -1423,6 +1432,15 @@ void __init set_uncached_handler (unsigned long offset, void *addr, unsigned lon
1423 memcpy((void *)(uncached_ebase + offset), addr, size); 1432 memcpy((void *)(uncached_ebase + offset), addr, size);
1424} 1433}
1425 1434
1435static int __initdata rdhwr_noopt;
1436static int __init set_rdhwr_noopt(char *str)
1437{
1438 rdhwr_noopt = 1;
1439 return 1;
1440}
1441
1442__setup("rdhwr_noopt", set_rdhwr_noopt);
1443
1426void __init trap_init(void) 1444void __init trap_init(void)
1427{ 1445{
1428 extern char except_vec3_generic, except_vec3_r4000; 1446 extern char except_vec3_generic, except_vec3_r4000;
@@ -1502,7 +1520,9 @@ void __init trap_init(void)
1502 1520
1503 set_except_vector(8, handle_sys); 1521 set_except_vector(8, handle_sys);
1504 set_except_vector(9, handle_bp); 1522 set_except_vector(9, handle_bp);
1505 set_except_vector(10, handle_ri); 1523 set_except_vector(10, rdhwr_noopt ? handle_ri :
1524 (cpu_has_vtag_icache ?
1525 handle_ri_rdhwr_vivt : handle_ri_rdhwr));
1506 set_except_vector(11, handle_cpu); 1526 set_except_vector(11, handle_cpu);
1507 set_except_vector(12, handle_ov); 1527 set_except_vector(12, handle_ov);
1508 set_except_vector(13, handle_tr); 1528 set_except_vector(13, handle_tr);