diff options
author | Ingo Molnar <mingo@elte.hu> | 2008-10-28 11:26:12 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-10-28 11:26:12 -0400 |
commit | 7a9787e1eba95a166265e6a260cf30af04ef0a99 (patch) | |
tree | e730a4565e0318140d2fbd2f0415d18a339d7336 /arch/mips/kernel | |
parent | 41b9eb264c8407655db57b60b4457fe1b2ec9977 (diff) | |
parent | 0173a3265b228da319ceb9c1ec6a5682fd1b2d92 (diff) |
Merge commit 'v2.6.28-rc2' into x86/pci-ioapic-boot-irq-quirks
Diffstat (limited to 'arch/mips/kernel')
33 files changed, 1361 insertions, 2091 deletions
diff --git a/arch/mips/kernel/.gitignore b/arch/mips/kernel/.gitignore new file mode 100644 index 000000000000..c5f676c3c224 --- /dev/null +++ b/arch/mips/kernel/.gitignore | |||
@@ -0,0 +1 @@ | |||
vmlinux.lds | |||
diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile index 0fd31974ba28..d9da7112aaf8 100644 --- a/arch/mips/kernel/Makefile +++ b/arch/mips/kernel/Makefile | |||
@@ -6,10 +6,11 @@ extra-y := head.o init_task.o vmlinux.lds | |||
6 | 6 | ||
7 | obj-y += cpu-probe.o branch.o entry.o genex.o irq.o process.o \ | 7 | obj-y += cpu-probe.o branch.o entry.o genex.o irq.o process.o \ |
8 | ptrace.o reset.o setup.o signal.o syscall.o \ | 8 | ptrace.o reset.o setup.o signal.o syscall.o \ |
9 | time.o topology.o traps.o unaligned.o | 9 | time.o topology.o traps.o unaligned.o watch.o |
10 | 10 | ||
11 | obj-$(CONFIG_CEVT_BCM1480) += cevt-bcm1480.o | 11 | obj-$(CONFIG_CEVT_BCM1480) += cevt-bcm1480.o |
12 | obj-$(CONFIG_CEVT_R4K) += cevt-r4k.o | 12 | obj-$(CONFIG_CEVT_R4K) += cevt-r4k.o |
13 | obj-$(CONFIG_MIPS_MT_SMTC) += cevt-smtc.o | ||
13 | obj-$(CONFIG_CEVT_DS1287) += cevt-ds1287.o | 14 | obj-$(CONFIG_CEVT_DS1287) += cevt-ds1287.o |
14 | obj-$(CONFIG_CEVT_GT641XX) += cevt-gt641xx.o | 15 | obj-$(CONFIG_CEVT_GT641XX) += cevt-gt641xx.o |
15 | obj-$(CONFIG_CEVT_SB1250) += cevt-sb1250.o | 16 | obj-$(CONFIG_CEVT_SB1250) += cevt-sb1250.o |
@@ -71,7 +72,7 @@ obj-$(CONFIG_MIPS32_COMPAT) += linux32.o ptrace32.o signal32.o | |||
71 | obj-$(CONFIG_MIPS32_N32) += binfmt_elfn32.o scall64-n32.o signal_n32.o | 72 | obj-$(CONFIG_MIPS32_N32) += binfmt_elfn32.o scall64-n32.o signal_n32.o |
72 | obj-$(CONFIG_MIPS32_O32) += binfmt_elfo32.o scall64-o32.o | 73 | obj-$(CONFIG_MIPS32_O32) += binfmt_elfo32.o scall64-o32.o |
73 | 74 | ||
74 | obj-$(CONFIG_KGDB) += gdb-low.o gdb-stub.o | 75 | obj-$(CONFIG_KGDB) += kgdb.o |
75 | obj-$(CONFIG_PROC_FS) += proc.o | 76 | obj-$(CONFIG_PROC_FS) += proc.o |
76 | 77 | ||
77 | obj-$(CONFIG_64BIT) += cpu-bugs64.o | 78 | obj-$(CONFIG_64BIT) += cpu-bugs64.o |
diff --git a/arch/mips/kernel/cevt-r4k.c b/arch/mips/kernel/cevt-r4k.c index 24a2d907aa0d..4a4c59f2737a 100644 --- a/arch/mips/kernel/cevt-r4k.c +++ b/arch/mips/kernel/cevt-r4k.c | |||
@@ -12,6 +12,14 @@ | |||
12 | 12 | ||
13 | #include <asm/smtc_ipi.h> | 13 | #include <asm/smtc_ipi.h> |
14 | #include <asm/time.h> | 14 | #include <asm/time.h> |
15 | #include <asm/cevt-r4k.h> | ||
16 | |||
17 | /* | ||
18 | * The SMTC Kernel for the 34K, 1004K, et. al. replaces several | ||
19 | * of these routines with SMTC-specific variants. | ||
20 | */ | ||
21 | |||
22 | #ifndef CONFIG_MIPS_MT_SMTC | ||
15 | 23 | ||
16 | static int mips_next_event(unsigned long delta, | 24 | static int mips_next_event(unsigned long delta, |
17 | struct clock_event_device *evt) | 25 | struct clock_event_device *evt) |
@@ -19,60 +27,27 @@ static int mips_next_event(unsigned long delta, | |||
19 | unsigned int cnt; | 27 | unsigned int cnt; |
20 | int res; | 28 | int res; |
21 | 29 | ||
22 | #ifdef CONFIG_MIPS_MT_SMTC | ||
23 | { | ||
24 | unsigned long flags, vpflags; | ||
25 | local_irq_save(flags); | ||
26 | vpflags = dvpe(); | ||
27 | #endif | ||
28 | cnt = read_c0_count(); | 30 | cnt = read_c0_count(); |
29 | cnt += delta; | 31 | cnt += delta; |
30 | write_c0_compare(cnt); | 32 | write_c0_compare(cnt); |
31 | res = ((int)(read_c0_count() - cnt) > 0) ? -ETIME : 0; | 33 | res = ((int)(read_c0_count() - cnt) > 0) ? -ETIME : 0; |
32 | #ifdef CONFIG_MIPS_MT_SMTC | ||
33 | evpe(vpflags); | ||
34 | local_irq_restore(flags); | ||
35 | } | ||
36 | #endif | ||
37 | return res; | 34 | return res; |
38 | } | 35 | } |
39 | 36 | ||
40 | static void mips_set_mode(enum clock_event_mode mode, | 37 | #endif /* CONFIG_MIPS_MT_SMTC */ |
41 | struct clock_event_device *evt) | 38 | |
39 | void mips_set_clock_mode(enum clock_event_mode mode, | ||
40 | struct clock_event_device *evt) | ||
42 | { | 41 | { |
43 | /* Nothing to do ... */ | 42 | /* Nothing to do ... */ |
44 | } | 43 | } |
45 | 44 | ||
46 | static DEFINE_PER_CPU(struct clock_event_device, mips_clockevent_device); | 45 | DEFINE_PER_CPU(struct clock_event_device, mips_clockevent_device); |
47 | static int cp0_timer_irq_installed; | 46 | int cp0_timer_irq_installed; |
48 | 47 | ||
49 | /* | 48 | #ifndef CONFIG_MIPS_MT_SMTC |
50 | * Timer ack for an R4k-compatible timer of a known frequency. | ||
51 | */ | ||
52 | static void c0_timer_ack(void) | ||
53 | { | ||
54 | write_c0_compare(read_c0_compare()); | ||
55 | } | ||
56 | 49 | ||
57 | /* | 50 | irqreturn_t c0_compare_interrupt(int irq, void *dev_id) |
58 | * Possibly handle a performance counter interrupt. | ||
59 | * Return true if the timer interrupt should not be checked | ||
60 | */ | ||
61 | static inline int handle_perf_irq(int r2) | ||
62 | { | ||
63 | /* | ||
64 | * The performance counter overflow interrupt may be shared with the | ||
65 | * timer interrupt (cp0_perfcount_irq < 0). If it is and a | ||
66 | * performance counter has overflowed (perf_irq() == IRQ_HANDLED) | ||
67 | * and we can't reliably determine if a counter interrupt has also | ||
68 | * happened (!r2) then don't check for a timer interrupt. | ||
69 | */ | ||
70 | return (cp0_perfcount_irq < 0) && | ||
71 | perf_irq() == IRQ_HANDLED && | ||
72 | !r2; | ||
73 | } | ||
74 | |||
75 | static irqreturn_t c0_compare_interrupt(int irq, void *dev_id) | ||
76 | { | 51 | { |
77 | const int r2 = cpu_has_mips_r2; | 52 | const int r2 = cpu_has_mips_r2; |
78 | struct clock_event_device *cd; | 53 | struct clock_event_device *cd; |
@@ -93,12 +68,8 @@ static irqreturn_t c0_compare_interrupt(int irq, void *dev_id) | |||
93 | * interrupt. Being the paranoiacs we are we check anyway. | 68 | * interrupt. Being the paranoiacs we are we check anyway. |
94 | */ | 69 | */ |
95 | if (!r2 || (read_c0_cause() & (1 << 30))) { | 70 | if (!r2 || (read_c0_cause() & (1 << 30))) { |
96 | c0_timer_ack(); | 71 | /* Clear Count/Compare Interrupt */ |
97 | #ifdef CONFIG_MIPS_MT_SMTC | 72 | write_c0_compare(read_c0_compare()); |
98 | if (cpu_data[cpu].vpe_id) | ||
99 | goto out; | ||
100 | cpu = 0; | ||
101 | #endif | ||
102 | cd = &per_cpu(mips_clockevent_device, cpu); | 73 | cd = &per_cpu(mips_clockevent_device, cpu); |
103 | cd->event_handler(cd); | 74 | cd->event_handler(cd); |
104 | } | 75 | } |
@@ -107,65 +78,16 @@ out: | |||
107 | return IRQ_HANDLED; | 78 | return IRQ_HANDLED; |
108 | } | 79 | } |
109 | 80 | ||
110 | static struct irqaction c0_compare_irqaction = { | 81 | #endif /* Not CONFIG_MIPS_MT_SMTC */ |
82 | |||
83 | struct irqaction c0_compare_irqaction = { | ||
111 | .handler = c0_compare_interrupt, | 84 | .handler = c0_compare_interrupt, |
112 | #ifdef CONFIG_MIPS_MT_SMTC | ||
113 | .flags = IRQF_DISABLED, | ||
114 | #else | ||
115 | .flags = IRQF_DISABLED | IRQF_PERCPU, | 85 | .flags = IRQF_DISABLED | IRQF_PERCPU, |
116 | #endif | ||
117 | .name = "timer", | 86 | .name = "timer", |
118 | }; | 87 | }; |
119 | 88 | ||
120 | #ifdef CONFIG_MIPS_MT_SMTC | ||
121 | DEFINE_PER_CPU(struct clock_event_device, smtc_dummy_clockevent_device); | ||
122 | |||
123 | static void smtc_set_mode(enum clock_event_mode mode, | ||
124 | struct clock_event_device *evt) | ||
125 | { | ||
126 | } | ||
127 | |||
128 | static void mips_broadcast(cpumask_t mask) | ||
129 | { | ||
130 | unsigned int cpu; | ||
131 | |||
132 | for_each_cpu_mask(cpu, mask) | ||
133 | smtc_send_ipi(cpu, SMTC_CLOCK_TICK, 0); | ||
134 | } | ||
135 | |||
136 | static void setup_smtc_dummy_clockevent_device(void) | ||
137 | { | ||
138 | //uint64_t mips_freq = mips_hpt_^frequency; | ||
139 | unsigned int cpu = smp_processor_id(); | ||
140 | struct clock_event_device *cd; | ||
141 | 89 | ||
142 | cd = &per_cpu(smtc_dummy_clockevent_device, cpu); | 90 | void mips_event_handler(struct clock_event_device *dev) |
143 | |||
144 | cd->name = "SMTC"; | ||
145 | cd->features = CLOCK_EVT_FEAT_DUMMY; | ||
146 | |||
147 | /* Calculate the min / max delta */ | ||
148 | cd->mult = 0; //div_sc((unsigned long) mips_freq, NSEC_PER_SEC, 32); | ||
149 | cd->shift = 0; //32; | ||
150 | cd->max_delta_ns = 0; //clockevent_delta2ns(0x7fffffff, cd); | ||
151 | cd->min_delta_ns = 0; //clockevent_delta2ns(0x30, cd); | ||
152 | |||
153 | cd->rating = 200; | ||
154 | cd->irq = 17; //-1; | ||
155 | // if (cpu) | ||
156 | // cd->cpumask = CPU_MASK_ALL; // cpumask_of_cpu(cpu); | ||
157 | // else | ||
158 | cd->cpumask = cpumask_of_cpu(cpu); | ||
159 | |||
160 | cd->set_mode = smtc_set_mode; | ||
161 | |||
162 | cd->broadcast = mips_broadcast; | ||
163 | |||
164 | clockevents_register_device(cd); | ||
165 | } | ||
166 | #endif | ||
167 | |||
168 | static void mips_event_handler(struct clock_event_device *dev) | ||
169 | { | 91 | { |
170 | } | 92 | } |
171 | 93 | ||
@@ -177,7 +99,23 @@ static int c0_compare_int_pending(void) | |||
177 | return (read_c0_cause() >> cp0_compare_irq) & 0x100; | 99 | return (read_c0_cause() >> cp0_compare_irq) & 0x100; |
178 | } | 100 | } |
179 | 101 | ||
180 | static int c0_compare_int_usable(void) | 102 | /* |
103 | * Compare interrupt can be routed and latched outside the core, | ||
104 | * so a single execution hazard barrier may not be enough to give | ||
105 | * it time to clear as seen in the Cause register. 4 time the | ||
106 | * pipeline depth seems reasonably conservative, and empirically | ||
107 | * works better in configurations with high CPU/bus clock ratios. | ||
108 | */ | ||
109 | |||
110 | #define compare_change_hazard() \ | ||
111 | do { \ | ||
112 | irq_disable_hazard(); \ | ||
113 | irq_disable_hazard(); \ | ||
114 | irq_disable_hazard(); \ | ||
115 | irq_disable_hazard(); \ | ||
116 | } while (0) | ||
117 | |||
118 | int c0_compare_int_usable(void) | ||
181 | { | 119 | { |
182 | unsigned int delta; | 120 | unsigned int delta; |
183 | unsigned int cnt; | 121 | unsigned int cnt; |
@@ -187,7 +125,7 @@ static int c0_compare_int_usable(void) | |||
187 | */ | 125 | */ |
188 | if (c0_compare_int_pending()) { | 126 | if (c0_compare_int_pending()) { |
189 | write_c0_compare(read_c0_count()); | 127 | write_c0_compare(read_c0_count()); |
190 | irq_disable_hazard(); | 128 | compare_change_hazard(); |
191 | if (c0_compare_int_pending()) | 129 | if (c0_compare_int_pending()) |
192 | return 0; | 130 | return 0; |
193 | } | 131 | } |
@@ -196,7 +134,7 @@ static int c0_compare_int_usable(void) | |||
196 | cnt = read_c0_count(); | 134 | cnt = read_c0_count(); |
197 | cnt += delta; | 135 | cnt += delta; |
198 | write_c0_compare(cnt); | 136 | write_c0_compare(cnt); |
199 | irq_disable_hazard(); | 137 | compare_change_hazard(); |
200 | if ((int)(read_c0_count() - cnt) < 0) | 138 | if ((int)(read_c0_count() - cnt) < 0) |
201 | break; | 139 | break; |
202 | /* increase delta if the timer was already expired */ | 140 | /* increase delta if the timer was already expired */ |
@@ -205,11 +143,12 @@ static int c0_compare_int_usable(void) | |||
205 | while ((int)(read_c0_count() - cnt) <= 0) | 143 | while ((int)(read_c0_count() - cnt) <= 0) |
206 | ; /* Wait for expiry */ | 144 | ; /* Wait for expiry */ |
207 | 145 | ||
146 | compare_change_hazard(); | ||
208 | if (!c0_compare_int_pending()) | 147 | if (!c0_compare_int_pending()) |
209 | return 0; | 148 | return 0; |
210 | 149 | ||
211 | write_c0_compare(read_c0_count()); | 150 | write_c0_compare(read_c0_count()); |
212 | irq_disable_hazard(); | 151 | compare_change_hazard(); |
213 | if (c0_compare_int_pending()) | 152 | if (c0_compare_int_pending()) |
214 | return 0; | 153 | return 0; |
215 | 154 | ||
@@ -219,6 +158,8 @@ static int c0_compare_int_usable(void) | |||
219 | return 1; | 158 | return 1; |
220 | } | 159 | } |
221 | 160 | ||
161 | #ifndef CONFIG_MIPS_MT_SMTC | ||
162 | |||
222 | int __cpuinit mips_clockevent_init(void) | 163 | int __cpuinit mips_clockevent_init(void) |
223 | { | 164 | { |
224 | uint64_t mips_freq = mips_hpt_frequency; | 165 | uint64_t mips_freq = mips_hpt_frequency; |
@@ -229,17 +170,6 @@ int __cpuinit mips_clockevent_init(void) | |||
229 | if (!cpu_has_counter || !mips_hpt_frequency) | 170 | if (!cpu_has_counter || !mips_hpt_frequency) |
230 | return -ENXIO; | 171 | return -ENXIO; |
231 | 172 | ||
232 | #ifdef CONFIG_MIPS_MT_SMTC | ||
233 | setup_smtc_dummy_clockevent_device(); | ||
234 | |||
235 | /* | ||
236 | * On SMTC we only register VPE0's compare interrupt as clockevent | ||
237 | * device. | ||
238 | */ | ||
239 | if (cpu) | ||
240 | return 0; | ||
241 | #endif | ||
242 | |||
243 | if (!c0_compare_int_usable()) | 173 | if (!c0_compare_int_usable()) |
244 | return -ENXIO; | 174 | return -ENXIO; |
245 | 175 | ||
@@ -265,13 +195,9 @@ int __cpuinit mips_clockevent_init(void) | |||
265 | 195 | ||
266 | cd->rating = 300; | 196 | cd->rating = 300; |
267 | cd->irq = irq; | 197 | cd->irq = irq; |
268 | #ifdef CONFIG_MIPS_MT_SMTC | ||
269 | cd->cpumask = CPU_MASK_ALL; | ||
270 | #else | ||
271 | cd->cpumask = cpumask_of_cpu(cpu); | 198 | cd->cpumask = cpumask_of_cpu(cpu); |
272 | #endif | ||
273 | cd->set_next_event = mips_next_event; | 199 | cd->set_next_event = mips_next_event; |
274 | cd->set_mode = mips_set_mode; | 200 | cd->set_mode = mips_set_clock_mode; |
275 | cd->event_handler = mips_event_handler; | 201 | cd->event_handler = mips_event_handler; |
276 | 202 | ||
277 | clockevents_register_device(cd); | 203 | clockevents_register_device(cd); |
@@ -281,12 +207,9 @@ int __cpuinit mips_clockevent_init(void) | |||
281 | 207 | ||
282 | cp0_timer_irq_installed = 1; | 208 | cp0_timer_irq_installed = 1; |
283 | 209 | ||
284 | #ifdef CONFIG_MIPS_MT_SMTC | ||
285 | #define CPUCTR_IMASKBIT (0x100 << cp0_compare_irq) | ||
286 | setup_irq_smtc(irq, &c0_compare_irqaction, CPUCTR_IMASKBIT); | ||
287 | #else | ||
288 | setup_irq(irq, &c0_compare_irqaction); | 210 | setup_irq(irq, &c0_compare_irqaction); |
289 | #endif | ||
290 | 211 | ||
291 | return 0; | 212 | return 0; |
292 | } | 213 | } |
214 | |||
215 | #endif /* Not CONFIG_MIPS_MT_SMTC */ | ||
diff --git a/arch/mips/kernel/cevt-smtc.c b/arch/mips/kernel/cevt-smtc.c new file mode 100644 index 000000000000..5162fe4b5952 --- /dev/null +++ b/arch/mips/kernel/cevt-smtc.c | |||
@@ -0,0 +1,321 @@ | |||
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) 2007 MIPS Technologies, Inc. | ||
7 | * Copyright (C) 2007 Ralf Baechle <ralf@linux-mips.org> | ||
8 | * Copyright (C) 2008 Kevin D. Kissell, Paralogos sarl | ||
9 | */ | ||
10 | #include <linux/clockchips.h> | ||
11 | #include <linux/interrupt.h> | ||
12 | #include <linux/percpu.h> | ||
13 | |||
14 | #include <asm/smtc_ipi.h> | ||
15 | #include <asm/time.h> | ||
16 | #include <asm/cevt-r4k.h> | ||
17 | |||
18 | /* | ||
19 | * Variant clock event timer support for SMTC on MIPS 34K, 1004K | ||
20 | * or other MIPS MT cores. | ||
21 | * | ||
22 | * Notes on SMTC Support: | ||
23 | * | ||
24 | * SMTC has multiple microthread TCs pretending to be Linux CPUs. | ||
25 | * But there's only one Count/Compare pair per VPE, and Compare | ||
26 | * interrupts are taken opportunisitically by available TCs | ||
27 | * bound to the VPE with the Count register. The new timer | ||
28 | * framework provides for global broadcasts, but we really | ||
29 | * want VPE-level multicasts for best behavior. So instead | ||
30 | * of invoking the high-level clock-event broadcast code, | ||
31 | * this version of SMTC support uses the historical SMTC | ||
32 | * multicast mechanisms "under the hood", appearing to the | ||
33 | * generic clock layer as if the interrupts are per-CPU. | ||
34 | * | ||
35 | * The approach taken here is to maintain a set of NR_CPUS | ||
36 | * virtual timers, and track which "CPU" needs to be alerted | ||
37 | * at each event. | ||
38 | * | ||
39 | * It's unlikely that we'll see a MIPS MT core with more than | ||
40 | * 2 VPEs, but we *know* that we won't need to handle more | ||
41 | * VPEs than we have "CPUs". So NCPUs arrays of NCPUs elements | ||
42 | * is always going to be overkill, but always going to be enough. | ||
43 | */ | ||
44 | |||
45 | unsigned long smtc_nexttime[NR_CPUS][NR_CPUS]; | ||
46 | static int smtc_nextinvpe[NR_CPUS]; | ||
47 | |||
48 | /* | ||
49 | * Timestamps stored are absolute values to be programmed | ||
50 | * into Count register. Valid timestamps will never be zero. | ||
51 | * If a Zero Count value is actually calculated, it is converted | ||
52 | * to be a 1, which will introduce 1 or two CPU cycles of error | ||
53 | * roughly once every four billion events, which at 1000 HZ means | ||
54 | * about once every 50 days. If that's actually a problem, one | ||
55 | * could alternate squashing 0 to 1 and to -1. | ||
56 | */ | ||
57 | |||
58 | #define MAKEVALID(x) (((x) == 0L) ? 1L : (x)) | ||
59 | #define ISVALID(x) ((x) != 0L) | ||
60 | |||
61 | /* | ||
62 | * Time comparison is subtle, as it's really truncated | ||
63 | * modular arithmetic. | ||
64 | */ | ||
65 | |||
66 | #define IS_SOONER(a, b, reference) \ | ||
67 | (((a) - (unsigned long)(reference)) < ((b) - (unsigned long)(reference))) | ||
68 | |||
69 | /* | ||
70 | * CATCHUP_INCREMENT, used when the function falls behind the counter. | ||
71 | * Could be an increasing function instead of a constant; | ||
72 | */ | ||
73 | |||
74 | #define CATCHUP_INCREMENT 64 | ||
75 | |||
76 | static int mips_next_event(unsigned long delta, | ||
77 | struct clock_event_device *evt) | ||
78 | { | ||
79 | unsigned long flags; | ||
80 | unsigned int mtflags; | ||
81 | unsigned long timestamp, reference, previous; | ||
82 | unsigned long nextcomp = 0L; | ||
83 | int vpe = current_cpu_data.vpe_id; | ||
84 | int cpu = smp_processor_id(); | ||
85 | local_irq_save(flags); | ||
86 | mtflags = dmt(); | ||
87 | |||
88 | /* | ||
89 | * Maintain the per-TC virtual timer | ||
90 | * and program the per-VPE shared Count register | ||
91 | * as appropriate here... | ||
92 | */ | ||
93 | reference = (unsigned long)read_c0_count(); | ||
94 | timestamp = MAKEVALID(reference + delta); | ||
95 | /* | ||
96 | * To really model the clock, we have to catch the case | ||
97 | * where the current next-in-VPE timestamp is the old | ||
98 | * timestamp for the calling CPE, but the new value is | ||
99 | * in fact later. In that case, we have to do a full | ||
100 | * scan and discover the new next-in-VPE CPU id and | ||
101 | * timestamp. | ||
102 | */ | ||
103 | previous = smtc_nexttime[vpe][cpu]; | ||
104 | if (cpu == smtc_nextinvpe[vpe] && ISVALID(previous) | ||
105 | && IS_SOONER(previous, timestamp, reference)) { | ||
106 | int i; | ||
107 | int soonest = cpu; | ||
108 | |||
109 | /* | ||
110 | * Update timestamp array here, so that new | ||
111 | * value gets considered along with those of | ||
112 | * other virtual CPUs on the VPE. | ||
113 | */ | ||
114 | smtc_nexttime[vpe][cpu] = timestamp; | ||
115 | for_each_online_cpu(i) { | ||
116 | if (ISVALID(smtc_nexttime[vpe][i]) | ||
117 | && IS_SOONER(smtc_nexttime[vpe][i], | ||
118 | smtc_nexttime[vpe][soonest], reference)) { | ||
119 | soonest = i; | ||
120 | } | ||
121 | } | ||
122 | smtc_nextinvpe[vpe] = soonest; | ||
123 | nextcomp = smtc_nexttime[vpe][soonest]; | ||
124 | /* | ||
125 | * Otherwise, we don't have to process the whole array rank, | ||
126 | * we just have to see if the event horizon has gotten closer. | ||
127 | */ | ||
128 | } else { | ||
129 | if (!ISVALID(smtc_nexttime[vpe][smtc_nextinvpe[vpe]]) || | ||
130 | IS_SOONER(timestamp, | ||
131 | smtc_nexttime[vpe][smtc_nextinvpe[vpe]], reference)) { | ||
132 | smtc_nextinvpe[vpe] = cpu; | ||
133 | nextcomp = timestamp; | ||
134 | } | ||
135 | /* | ||
136 | * Since next-in-VPE may me the same as the executing | ||
137 | * virtual CPU, we update the array *after* checking | ||
138 | * its value. | ||
139 | */ | ||
140 | smtc_nexttime[vpe][cpu] = timestamp; | ||
141 | } | ||
142 | |||
143 | /* | ||
144 | * It may be that, in fact, we don't need to update Compare, | ||
145 | * but if we do, we want to make sure we didn't fall into | ||
146 | * a crack just behind Count. | ||
147 | */ | ||
148 | if (ISVALID(nextcomp)) { | ||
149 | write_c0_compare(nextcomp); | ||
150 | ehb(); | ||
151 | /* | ||
152 | * We never return an error, we just make sure | ||
153 | * that we trigger the handlers as quickly as | ||
154 | * we can if we fell behind. | ||
155 | */ | ||
156 | while ((nextcomp - (unsigned long)read_c0_count()) | ||
157 | > (unsigned long)LONG_MAX) { | ||
158 | nextcomp += CATCHUP_INCREMENT; | ||
159 | write_c0_compare(nextcomp); | ||
160 | ehb(); | ||
161 | } | ||
162 | } | ||
163 | emt(mtflags); | ||
164 | local_irq_restore(flags); | ||
165 | return 0; | ||
166 | } | ||
167 | |||
168 | |||
169 | void smtc_distribute_timer(int vpe) | ||
170 | { | ||
171 | unsigned long flags; | ||
172 | unsigned int mtflags; | ||
173 | int cpu; | ||
174 | struct clock_event_device *cd; | ||
175 | unsigned long nextstamp = 0L; | ||
176 | unsigned long reference; | ||
177 | |||
178 | |||
179 | repeat: | ||
180 | for_each_online_cpu(cpu) { | ||
181 | /* | ||
182 | * Find virtual CPUs within the current VPE who have | ||
183 | * unserviced timer requests whose time is now past. | ||
184 | */ | ||
185 | local_irq_save(flags); | ||
186 | mtflags = dmt(); | ||
187 | if (cpu_data[cpu].vpe_id == vpe && | ||
188 | ISVALID(smtc_nexttime[vpe][cpu])) { | ||
189 | reference = (unsigned long)read_c0_count(); | ||
190 | if ((smtc_nexttime[vpe][cpu] - reference) | ||
191 | > (unsigned long)LONG_MAX) { | ||
192 | smtc_nexttime[vpe][cpu] = 0L; | ||
193 | emt(mtflags); | ||
194 | local_irq_restore(flags); | ||
195 | /* | ||
196 | * We don't send IPIs to ourself. | ||
197 | */ | ||
198 | if (cpu != smp_processor_id()) { | ||
199 | smtc_send_ipi(cpu, SMTC_CLOCK_TICK, 0); | ||
200 | } else { | ||
201 | cd = &per_cpu(mips_clockevent_device, cpu); | ||
202 | cd->event_handler(cd); | ||
203 | } | ||
204 | } else { | ||
205 | /* Local to VPE but Valid Time not yet reached. */ | ||
206 | if (!ISVALID(nextstamp) || | ||
207 | IS_SOONER(smtc_nexttime[vpe][cpu], nextstamp, | ||
208 | reference)) { | ||
209 | smtc_nextinvpe[vpe] = cpu; | ||
210 | nextstamp = smtc_nexttime[vpe][cpu]; | ||
211 | } | ||
212 | emt(mtflags); | ||
213 | local_irq_restore(flags); | ||
214 | } | ||
215 | } else { | ||
216 | emt(mtflags); | ||
217 | local_irq_restore(flags); | ||
218 | |||
219 | } | ||
220 | } | ||
221 | /* Reprogram for interrupt at next soonest timestamp for VPE */ | ||
222 | if (ISVALID(nextstamp)) { | ||
223 | write_c0_compare(nextstamp); | ||
224 | ehb(); | ||
225 | if ((nextstamp - (unsigned long)read_c0_count()) | ||
226 | > (unsigned long)LONG_MAX) | ||
227 | goto repeat; | ||
228 | } | ||
229 | } | ||
230 | |||
231 | |||
232 | irqreturn_t c0_compare_interrupt(int irq, void *dev_id) | ||
233 | { | ||
234 | int cpu = smp_processor_id(); | ||
235 | |||
236 | /* If we're running SMTC, we've got MIPS MT and therefore MIPS32R2 */ | ||
237 | handle_perf_irq(1); | ||
238 | |||
239 | if (read_c0_cause() & (1 << 30)) { | ||
240 | /* Clear Count/Compare Interrupt */ | ||
241 | write_c0_compare(read_c0_compare()); | ||
242 | smtc_distribute_timer(cpu_data[cpu].vpe_id); | ||
243 | } | ||
244 | return IRQ_HANDLED; | ||
245 | } | ||
246 | |||
247 | |||
248 | int __cpuinit mips_clockevent_init(void) | ||
249 | { | ||
250 | uint64_t mips_freq = mips_hpt_frequency; | ||
251 | unsigned int cpu = smp_processor_id(); | ||
252 | struct clock_event_device *cd; | ||
253 | unsigned int irq; | ||
254 | int i; | ||
255 | int j; | ||
256 | |||
257 | if (!cpu_has_counter || !mips_hpt_frequency) | ||
258 | return -ENXIO; | ||
259 | if (cpu == 0) { | ||
260 | for (i = 0; i < num_possible_cpus(); i++) { | ||
261 | smtc_nextinvpe[i] = 0; | ||
262 | for (j = 0; j < num_possible_cpus(); j++) | ||
263 | smtc_nexttime[i][j] = 0L; | ||
264 | } | ||
265 | /* | ||
266 | * SMTC also can't have the usablility test | ||
267 | * run by secondary TCs once Compare is in use. | ||
268 | */ | ||
269 | if (!c0_compare_int_usable()) | ||
270 | return -ENXIO; | ||
271 | } | ||
272 | |||
273 | /* | ||
274 | * With vectored interrupts things are getting platform specific. | ||
275 | * get_c0_compare_int is a hook to allow a platform to return the | ||
276 | * interrupt number of it's liking. | ||
277 | */ | ||
278 | irq = MIPS_CPU_IRQ_BASE + cp0_compare_irq; | ||
279 | if (get_c0_compare_int) | ||
280 | irq = get_c0_compare_int(); | ||
281 | |||
282 | cd = &per_cpu(mips_clockevent_device, cpu); | ||
283 | |||
284 | cd->name = "MIPS"; | ||
285 | cd->features = CLOCK_EVT_FEAT_ONESHOT; | ||
286 | |||
287 | /* Calculate the min / max delta */ | ||
288 | cd->mult = div_sc((unsigned long) mips_freq, NSEC_PER_SEC, 32); | ||
289 | cd->shift = 32; | ||
290 | cd->max_delta_ns = clockevent_delta2ns(0x7fffffff, cd); | ||
291 | cd->min_delta_ns = clockevent_delta2ns(0x300, cd); | ||
292 | |||
293 | cd->rating = 300; | ||
294 | cd->irq = irq; | ||
295 | cd->cpumask = cpumask_of_cpu(cpu); | ||
296 | cd->set_next_event = mips_next_event; | ||
297 | cd->set_mode = mips_set_clock_mode; | ||
298 | cd->event_handler = mips_event_handler; | ||
299 | |||
300 | clockevents_register_device(cd); | ||
301 | |||
302 | /* | ||
303 | * On SMTC we only want to do the data structure | ||
304 | * initialization and IRQ setup once. | ||
305 | */ | ||
306 | if (cpu) | ||
307 | return 0; | ||
308 | /* | ||
309 | * And we need the hwmask associated with the c0_compare | ||
310 | * vector to be initialized. | ||
311 | */ | ||
312 | irq_hwmask[irq] = (0x100 << cp0_compare_irq); | ||
313 | if (cp0_timer_irq_installed) | ||
314 | return 0; | ||
315 | |||
316 | cp0_timer_irq_installed = 1; | ||
317 | |||
318 | setup_irq(irq, &c0_compare_irqaction); | ||
319 | |||
320 | return 0; | ||
321 | } | ||
diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c index 335a6ae3d594..0cf15457ecac 100644 --- a/arch/mips/kernel/cpu-probe.c +++ b/arch/mips/kernel/cpu-probe.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <asm/fpu.h> | 21 | #include <asm/fpu.h> |
22 | #include <asm/mipsregs.h> | 22 | #include <asm/mipsregs.h> |
23 | #include <asm/system.h> | 23 | #include <asm/system.h> |
24 | #include <asm/watch.h> | ||
24 | 25 | ||
25 | /* | 26 | /* |
26 | * Not all of the MIPS CPUs have the "wait" instruction available. Moreover, | 27 | * Not all of the MIPS CPUs have the "wait" instruction available. Moreover, |
@@ -45,18 +46,7 @@ static void r39xx_wait(void) | |||
45 | local_irq_enable(); | 46 | local_irq_enable(); |
46 | } | 47 | } |
47 | 48 | ||
48 | /* | 49 | extern void r4k_wait(void); |
49 | * There is a race when WAIT instruction executed with interrupt | ||
50 | * enabled. | ||
51 | * But it is implementation-dependent wheter the pipelie restarts when | ||
52 | * a non-enabled interrupt is requested. | ||
53 | */ | ||
54 | static void r4k_wait(void) | ||
55 | { | ||
56 | __asm__(" .set mips3 \n" | ||
57 | " wait \n" | ||
58 | " .set mips0 \n"); | ||
59 | } | ||
60 | 50 | ||
61 | /* | 51 | /* |
62 | * This variant is preferable as it allows testing need_resched and going to | 52 | * This variant is preferable as it allows testing need_resched and going to |
@@ -65,14 +55,18 @@ static void r4k_wait(void) | |||
65 | * interrupt is requested" restriction in the MIPS32/MIPS64 architecture makes | 55 | * interrupt is requested" restriction in the MIPS32/MIPS64 architecture makes |
66 | * using this version a gamble. | 56 | * using this version a gamble. |
67 | */ | 57 | */ |
68 | static void r4k_wait_irqoff(void) | 58 | void r4k_wait_irqoff(void) |
69 | { | 59 | { |
70 | local_irq_disable(); | 60 | local_irq_disable(); |
71 | if (!need_resched()) | 61 | if (!need_resched()) |
72 | __asm__(" .set mips3 \n" | 62 | __asm__(" .set push \n" |
63 | " .set mips3 \n" | ||
73 | " wait \n" | 64 | " wait \n" |
74 | " .set mips0 \n"); | 65 | " .set pop \n"); |
75 | local_irq_enable(); | 66 | local_irq_enable(); |
67 | __asm__(" .globl __pastwait \n" | ||
68 | "__pastwait: \n"); | ||
69 | return; | ||
76 | } | 70 | } |
77 | 71 | ||
78 | /* | 72 | /* |
@@ -128,7 +122,7 @@ static int __init wait_disable(char *s) | |||
128 | 122 | ||
129 | __setup("nowait", wait_disable); | 123 | __setup("nowait", wait_disable); |
130 | 124 | ||
131 | static inline void check_wait(void) | 125 | void __init check_wait(void) |
132 | { | 126 | { |
133 | struct cpuinfo_mips *c = ¤t_cpu_data; | 127 | struct cpuinfo_mips *c = ¤t_cpu_data; |
134 | 128 | ||
@@ -242,7 +236,6 @@ static inline void check_errata(void) | |||
242 | 236 | ||
243 | void __init check_bugs32(void) | 237 | void __init check_bugs32(void) |
244 | { | 238 | { |
245 | check_wait(); | ||
246 | check_errata(); | 239 | check_errata(); |
247 | } | 240 | } |
248 | 241 | ||
@@ -685,6 +678,7 @@ static inline void spram_config(void) {} | |||
685 | static inline void cpu_probe_mips(struct cpuinfo_mips *c) | 678 | static inline void cpu_probe_mips(struct cpuinfo_mips *c) |
686 | { | 679 | { |
687 | decode_configs(c); | 680 | decode_configs(c); |
681 | mips_probe_watch_registers(c); | ||
688 | switch (c->processor_id & 0xff00) { | 682 | switch (c->processor_id & 0xff00) { |
689 | case PRID_IMP_4KC: | 683 | case PRID_IMP_4KC: |
690 | c->cputype = CPU_4KC; | 684 | c->cputype = CPU_4KC; |
diff --git a/arch/mips/kernel/entry.S b/arch/mips/kernel/entry.S index e29598ae939d..ffa331029e08 100644 --- a/arch/mips/kernel/entry.S +++ b/arch/mips/kernel/entry.S | |||
@@ -79,11 +79,6 @@ FEXPORT(syscall_exit) | |||
79 | 79 | ||
80 | FEXPORT(restore_all) # restore full frame | 80 | FEXPORT(restore_all) # restore full frame |
81 | #ifdef CONFIG_MIPS_MT_SMTC | 81 | #ifdef CONFIG_MIPS_MT_SMTC |
82 | /* Detect and execute deferred IPI "interrupts" */ | ||
83 | LONG_L s0, TI_REGS($28) | ||
84 | LONG_S sp, TI_REGS($28) | ||
85 | jal deferred_smtc_ipi | ||
86 | LONG_S s0, TI_REGS($28) | ||
87 | #ifdef CONFIG_MIPS_MT_SMTC_IM_BACKSTOP | 82 | #ifdef CONFIG_MIPS_MT_SMTC_IM_BACKSTOP |
88 | /* Re-arm any temporarily masked interrupts not explicitly "acked" */ | 83 | /* Re-arm any temporarily masked interrupts not explicitly "acked" */ |
89 | mfc0 v0, CP0_TCSTATUS | 84 | mfc0 v0, CP0_TCSTATUS |
@@ -112,6 +107,11 @@ FEXPORT(restore_all) # restore full frame | |||
112 | xor t0, t0, t3 | 107 | xor t0, t0, t3 |
113 | mtc0 t0, CP0_TCCONTEXT | 108 | mtc0 t0, CP0_TCCONTEXT |
114 | #endif /* CONFIG_MIPS_MT_SMTC_IM_BACKSTOP */ | 109 | #endif /* CONFIG_MIPS_MT_SMTC_IM_BACKSTOP */ |
110 | /* Detect and execute deferred IPI "interrupts" */ | ||
111 | LONG_L s0, TI_REGS($28) | ||
112 | LONG_S sp, TI_REGS($28) | ||
113 | jal deferred_smtc_ipi | ||
114 | LONG_S s0, TI_REGS($28) | ||
115 | #endif /* CONFIG_MIPS_MT_SMTC */ | 115 | #endif /* CONFIG_MIPS_MT_SMTC */ |
116 | .set noat | 116 | .set noat |
117 | RESTORE_TEMP | 117 | RESTORE_TEMP |
diff --git a/arch/mips/kernel/gdb-low.S b/arch/mips/kernel/gdb-low.S deleted file mode 100644 index 2c446063636a..000000000000 --- a/arch/mips/kernel/gdb-low.S +++ /dev/null | |||
@@ -1,394 +0,0 @@ | |||
1 | /* | ||
2 | * gdb-low.S contains the low-level trap handler for the GDB stub. | ||
3 | * | ||
4 | * Copyright (C) 1995 Andreas Busse | ||
5 | */ | ||
6 | #include <linux/sys.h> | ||
7 | |||
8 | #include <asm/asm.h> | ||
9 | #include <asm/errno.h> | ||
10 | #include <asm/irqflags.h> | ||
11 | #include <asm/mipsregs.h> | ||
12 | #include <asm/regdef.h> | ||
13 | #include <asm/stackframe.h> | ||
14 | #include <asm/gdb-stub.h> | ||
15 | |||
16 | #ifdef CONFIG_32BIT | ||
17 | #define DMFC0 mfc0 | ||
18 | #define DMTC0 mtc0 | ||
19 | #define LDC1 lwc1 | ||
20 | #define SDC1 lwc1 | ||
21 | #endif | ||
22 | #ifdef CONFIG_64BIT | ||
23 | #define DMFC0 dmfc0 | ||
24 | #define DMTC0 dmtc0 | ||
25 | #define LDC1 ldc1 | ||
26 | #define SDC1 ldc1 | ||
27 | #endif | ||
28 | |||
29 | /* | ||
30 | * [jsun] We reserves about 2x GDB_FR_SIZE in stack. The lower (addressed) | ||
31 | * part is used to store registers and passed to exception handler. | ||
32 | * The upper part is reserved for "call func" feature where gdb client | ||
33 | * saves some of the regs, setups call frame and passes args. | ||
34 | * | ||
35 | * A trace shows about 200 bytes are used to store about half of all regs. | ||
36 | * The rest should be big enough for frame setup and passing args. | ||
37 | */ | ||
38 | |||
39 | /* | ||
40 | * The low level trap handler | ||
41 | */ | ||
42 | .align 5 | ||
43 | NESTED(trap_low, GDB_FR_SIZE, sp) | ||
44 | .set noat | ||
45 | .set noreorder | ||
46 | |||
47 | mfc0 k0, CP0_STATUS | ||
48 | sll k0, 3 /* extract cu0 bit */ | ||
49 | bltz k0, 1f | ||
50 | move k1, sp | ||
51 | |||
52 | /* | ||
53 | * Called from user mode, go somewhere else. | ||
54 | */ | ||
55 | mfc0 k0, CP0_CAUSE | ||
56 | andi k0, k0, 0x7c | ||
57 | #ifdef CONFIG_64BIT | ||
58 | dsll k0, k0, 1 | ||
59 | #endif | ||
60 | PTR_L k1, saved_vectors(k0) | ||
61 | jr k1 | ||
62 | nop | ||
63 | 1: | ||
64 | move k0, sp | ||
65 | PTR_SUBU sp, k1, GDB_FR_SIZE*2 # see comment above | ||
66 | LONG_S k0, GDB_FR_REG29(sp) | ||
67 | LONG_S $2, GDB_FR_REG2(sp) | ||
68 | |||
69 | /* | ||
70 | * First save the CP0 and special registers | ||
71 | */ | ||
72 | |||
73 | mfc0 v0, CP0_STATUS | ||
74 | LONG_S v0, GDB_FR_STATUS(sp) | ||
75 | mfc0 v0, CP0_CAUSE | ||
76 | LONG_S v0, GDB_FR_CAUSE(sp) | ||
77 | DMFC0 v0, CP0_EPC | ||
78 | LONG_S v0, GDB_FR_EPC(sp) | ||
79 | DMFC0 v0, CP0_BADVADDR | ||
80 | LONG_S v0, GDB_FR_BADVADDR(sp) | ||
81 | mfhi v0 | ||
82 | LONG_S v0, GDB_FR_HI(sp) | ||
83 | mflo v0 | ||
84 | LONG_S v0, GDB_FR_LO(sp) | ||
85 | |||
86 | /* | ||
87 | * Now the integer registers | ||
88 | */ | ||
89 | |||
90 | LONG_S zero, GDB_FR_REG0(sp) /* I know... */ | ||
91 | LONG_S $1, GDB_FR_REG1(sp) | ||
92 | /* v0 already saved */ | ||
93 | LONG_S $3, GDB_FR_REG3(sp) | ||
94 | LONG_S $4, GDB_FR_REG4(sp) | ||
95 | LONG_S $5, GDB_FR_REG5(sp) | ||
96 | LONG_S $6, GDB_FR_REG6(sp) | ||
97 | LONG_S $7, GDB_FR_REG7(sp) | ||
98 | LONG_S $8, GDB_FR_REG8(sp) | ||
99 | LONG_S $9, GDB_FR_REG9(sp) | ||
100 | LONG_S $10, GDB_FR_REG10(sp) | ||
101 | LONG_S $11, GDB_FR_REG11(sp) | ||
102 | LONG_S $12, GDB_FR_REG12(sp) | ||
103 | LONG_S $13, GDB_FR_REG13(sp) | ||
104 | LONG_S $14, GDB_FR_REG14(sp) | ||
105 | LONG_S $15, GDB_FR_REG15(sp) | ||
106 | LONG_S $16, GDB_FR_REG16(sp) | ||
107 | LONG_S $17, GDB_FR_REG17(sp) | ||
108 | LONG_S $18, GDB_FR_REG18(sp) | ||
109 | LONG_S $19, GDB_FR_REG19(sp) | ||
110 | LONG_S $20, GDB_FR_REG20(sp) | ||
111 | LONG_S $21, GDB_FR_REG21(sp) | ||
112 | LONG_S $22, GDB_FR_REG22(sp) | ||
113 | LONG_S $23, GDB_FR_REG23(sp) | ||
114 | LONG_S $24, GDB_FR_REG24(sp) | ||
115 | LONG_S $25, GDB_FR_REG25(sp) | ||
116 | LONG_S $26, GDB_FR_REG26(sp) | ||
117 | LONG_S $27, GDB_FR_REG27(sp) | ||
118 | LONG_S $28, GDB_FR_REG28(sp) | ||
119 | /* sp already saved */ | ||
120 | LONG_S $30, GDB_FR_REG30(sp) | ||
121 | LONG_S $31, GDB_FR_REG31(sp) | ||
122 | |||
123 | CLI /* disable interrupts */ | ||
124 | TRACE_IRQS_OFF | ||
125 | |||
126 | /* | ||
127 | * Followed by the floating point registers | ||
128 | */ | ||
129 | mfc0 v0, CP0_STATUS /* FPU enabled? */ | ||
130 | srl v0, v0, 16 | ||
131 | andi v0, v0, (ST0_CU1 >> 16) | ||
132 | |||
133 | beqz v0,2f /* disabled, skip */ | ||
134 | nop | ||
135 | |||
136 | SDC1 $0, GDB_FR_FPR0(sp) | ||
137 | SDC1 $1, GDB_FR_FPR1(sp) | ||
138 | SDC1 $2, GDB_FR_FPR2(sp) | ||
139 | SDC1 $3, GDB_FR_FPR3(sp) | ||
140 | SDC1 $4, GDB_FR_FPR4(sp) | ||
141 | SDC1 $5, GDB_FR_FPR5(sp) | ||
142 | SDC1 $6, GDB_FR_FPR6(sp) | ||
143 | SDC1 $7, GDB_FR_FPR7(sp) | ||
144 | SDC1 $8, GDB_FR_FPR8(sp) | ||
145 | SDC1 $9, GDB_FR_FPR9(sp) | ||
146 | SDC1 $10, GDB_FR_FPR10(sp) | ||
147 | SDC1 $11, GDB_FR_FPR11(sp) | ||
148 | SDC1 $12, GDB_FR_FPR12(sp) | ||
149 | SDC1 $13, GDB_FR_FPR13(sp) | ||
150 | SDC1 $14, GDB_FR_FPR14(sp) | ||
151 | SDC1 $15, GDB_FR_FPR15(sp) | ||
152 | SDC1 $16, GDB_FR_FPR16(sp) | ||
153 | SDC1 $17, GDB_FR_FPR17(sp) | ||
154 | SDC1 $18, GDB_FR_FPR18(sp) | ||
155 | SDC1 $19, GDB_FR_FPR19(sp) | ||
156 | SDC1 $20, GDB_FR_FPR20(sp) | ||
157 | SDC1 $21, GDB_FR_FPR21(sp) | ||
158 | SDC1 $22, GDB_FR_FPR22(sp) | ||
159 | SDC1 $23, GDB_FR_FPR23(sp) | ||
160 | SDC1 $24, GDB_FR_FPR24(sp) | ||
161 | SDC1 $25, GDB_FR_FPR25(sp) | ||
162 | SDC1 $26, GDB_FR_FPR26(sp) | ||
163 | SDC1 $27, GDB_FR_FPR27(sp) | ||
164 | SDC1 $28, GDB_FR_FPR28(sp) | ||
165 | SDC1 $29, GDB_FR_FPR29(sp) | ||
166 | SDC1 $30, GDB_FR_FPR30(sp) | ||
167 | SDC1 $31, GDB_FR_FPR31(sp) | ||
168 | |||
169 | /* | ||
170 | * FPU control registers | ||
171 | */ | ||
172 | |||
173 | cfc1 v0, CP1_STATUS | ||
174 | LONG_S v0, GDB_FR_FSR(sp) | ||
175 | cfc1 v0, CP1_REVISION | ||
176 | LONG_S v0, GDB_FR_FIR(sp) | ||
177 | |||
178 | /* | ||
179 | * Current stack frame ptr | ||
180 | */ | ||
181 | |||
182 | 2: | ||
183 | LONG_S sp, GDB_FR_FRP(sp) | ||
184 | |||
185 | /* | ||
186 | * CP0 registers (R4000/R4400 unused registers skipped) | ||
187 | */ | ||
188 | |||
189 | mfc0 v0, CP0_INDEX | ||
190 | LONG_S v0, GDB_FR_CP0_INDEX(sp) | ||
191 | mfc0 v0, CP0_RANDOM | ||
192 | LONG_S v0, GDB_FR_CP0_RANDOM(sp) | ||
193 | DMFC0 v0, CP0_ENTRYLO0 | ||
194 | LONG_S v0, GDB_FR_CP0_ENTRYLO0(sp) | ||
195 | DMFC0 v0, CP0_ENTRYLO1 | ||
196 | LONG_S v0, GDB_FR_CP0_ENTRYLO1(sp) | ||
197 | DMFC0 v0, CP0_CONTEXT | ||
198 | LONG_S v0, GDB_FR_CP0_CONTEXT(sp) | ||
199 | mfc0 v0, CP0_PAGEMASK | ||
200 | LONG_S v0, GDB_FR_CP0_PAGEMASK(sp) | ||
201 | mfc0 v0, CP0_WIRED | ||
202 | LONG_S v0, GDB_FR_CP0_WIRED(sp) | ||
203 | DMFC0 v0, CP0_ENTRYHI | ||
204 | LONG_S v0, GDB_FR_CP0_ENTRYHI(sp) | ||
205 | mfc0 v0, CP0_PRID | ||
206 | LONG_S v0, GDB_FR_CP0_PRID(sp) | ||
207 | |||
208 | .set at | ||
209 | |||
210 | /* | ||
211 | * Continue with the higher level handler | ||
212 | */ | ||
213 | |||
214 | move a0,sp | ||
215 | |||
216 | jal handle_exception | ||
217 | nop | ||
218 | |||
219 | /* | ||
220 | * Restore all writable registers, in reverse order | ||
221 | */ | ||
222 | |||
223 | .set noat | ||
224 | |||
225 | LONG_L v0, GDB_FR_CP0_ENTRYHI(sp) | ||
226 | LONG_L v1, GDB_FR_CP0_WIRED(sp) | ||
227 | DMTC0 v0, CP0_ENTRYHI | ||
228 | mtc0 v1, CP0_WIRED | ||
229 | LONG_L v0, GDB_FR_CP0_PAGEMASK(sp) | ||
230 | LONG_L v1, GDB_FR_CP0_ENTRYLO1(sp) | ||
231 | mtc0 v0, CP0_PAGEMASK | ||
232 | DMTC0 v1, CP0_ENTRYLO1 | ||
233 | LONG_L v0, GDB_FR_CP0_ENTRYLO0(sp) | ||
234 | LONG_L v1, GDB_FR_CP0_INDEX(sp) | ||
235 | DMTC0 v0, CP0_ENTRYLO0 | ||
236 | LONG_L v0, GDB_FR_CP0_CONTEXT(sp) | ||
237 | mtc0 v1, CP0_INDEX | ||
238 | DMTC0 v0, CP0_CONTEXT | ||
239 | |||
240 | |||
241 | /* | ||
242 | * Next, the floating point registers | ||
243 | */ | ||
244 | mfc0 v0, CP0_STATUS /* check if the FPU is enabled */ | ||
245 | srl v0, v0, 16 | ||
246 | andi v0, v0, (ST0_CU1 >> 16) | ||
247 | |||
248 | beqz v0, 3f /* disabled, skip */ | ||
249 | nop | ||
250 | |||
251 | LDC1 $31, GDB_FR_FPR31(sp) | ||
252 | LDC1 $30, GDB_FR_FPR30(sp) | ||
253 | LDC1 $29, GDB_FR_FPR29(sp) | ||
254 | LDC1 $28, GDB_FR_FPR28(sp) | ||
255 | LDC1 $27, GDB_FR_FPR27(sp) | ||
256 | LDC1 $26, GDB_FR_FPR26(sp) | ||
257 | LDC1 $25, GDB_FR_FPR25(sp) | ||
258 | LDC1 $24, GDB_FR_FPR24(sp) | ||
259 | LDC1 $23, GDB_FR_FPR23(sp) | ||
260 | LDC1 $22, GDB_FR_FPR22(sp) | ||
261 | LDC1 $21, GDB_FR_FPR21(sp) | ||
262 | LDC1 $20, GDB_FR_FPR20(sp) | ||
263 | LDC1 $19, GDB_FR_FPR19(sp) | ||
264 | LDC1 $18, GDB_FR_FPR18(sp) | ||
265 | LDC1 $17, GDB_FR_FPR17(sp) | ||
266 | LDC1 $16, GDB_FR_FPR16(sp) | ||
267 | LDC1 $15, GDB_FR_FPR15(sp) | ||
268 | LDC1 $14, GDB_FR_FPR14(sp) | ||
269 | LDC1 $13, GDB_FR_FPR13(sp) | ||
270 | LDC1 $12, GDB_FR_FPR12(sp) | ||
271 | LDC1 $11, GDB_FR_FPR11(sp) | ||
272 | LDC1 $10, GDB_FR_FPR10(sp) | ||
273 | LDC1 $9, GDB_FR_FPR9(sp) | ||
274 | LDC1 $8, GDB_FR_FPR8(sp) | ||
275 | LDC1 $7, GDB_FR_FPR7(sp) | ||
276 | LDC1 $6, GDB_FR_FPR6(sp) | ||
277 | LDC1 $5, GDB_FR_FPR5(sp) | ||
278 | LDC1 $4, GDB_FR_FPR4(sp) | ||
279 | LDC1 $3, GDB_FR_FPR3(sp) | ||
280 | LDC1 $2, GDB_FR_FPR2(sp) | ||
281 | LDC1 $1, GDB_FR_FPR1(sp) | ||
282 | LDC1 $0, GDB_FR_FPR0(sp) | ||
283 | |||
284 | /* | ||
285 | * Now the CP0 and integer registers | ||
286 | */ | ||
287 | |||
288 | 3: | ||
289 | #ifdef CONFIG_MIPS_MT_SMTC | ||
290 | /* Read-modify write of Status must be atomic */ | ||
291 | mfc0 t2, CP0_TCSTATUS | ||
292 | ori t1, t2, TCSTATUS_IXMT | ||
293 | mtc0 t1, CP0_TCSTATUS | ||
294 | andi t2, t2, TCSTATUS_IXMT | ||
295 | _ehb | ||
296 | DMT 9 # dmt t1 | ||
297 | jal mips_ihb | ||
298 | nop | ||
299 | #endif /* CONFIG_MIPS_MT_SMTC */ | ||
300 | mfc0 t0, CP0_STATUS | ||
301 | ori t0, 0x1f | ||
302 | xori t0, 0x1f | ||
303 | mtc0 t0, CP0_STATUS | ||
304 | #ifdef CONFIG_MIPS_MT_SMTC | ||
305 | andi t1, t1, VPECONTROL_TE | ||
306 | beqz t1, 9f | ||
307 | nop | ||
308 | EMT # emt | ||
309 | 9: | ||
310 | mfc0 t1, CP0_TCSTATUS | ||
311 | xori t1, t1, TCSTATUS_IXMT | ||
312 | or t1, t1, t2 | ||
313 | mtc0 t1, CP0_TCSTATUS | ||
314 | _ehb | ||
315 | #endif /* CONFIG_MIPS_MT_SMTC */ | ||
316 | LONG_L v0, GDB_FR_STATUS(sp) | ||
317 | LONG_L v1, GDB_FR_EPC(sp) | ||
318 | mtc0 v0, CP0_STATUS | ||
319 | DMTC0 v1, CP0_EPC | ||
320 | LONG_L v0, GDB_FR_HI(sp) | ||
321 | LONG_L v1, GDB_FR_LO(sp) | ||
322 | mthi v0 | ||
323 | mtlo v1 | ||
324 | LONG_L $31, GDB_FR_REG31(sp) | ||
325 | LONG_L $30, GDB_FR_REG30(sp) | ||
326 | LONG_L $28, GDB_FR_REG28(sp) | ||
327 | LONG_L $27, GDB_FR_REG27(sp) | ||
328 | LONG_L $26, GDB_FR_REG26(sp) | ||
329 | LONG_L $25, GDB_FR_REG25(sp) | ||
330 | LONG_L $24, GDB_FR_REG24(sp) | ||
331 | LONG_L $23, GDB_FR_REG23(sp) | ||
332 | LONG_L $22, GDB_FR_REG22(sp) | ||
333 | LONG_L $21, GDB_FR_REG21(sp) | ||
334 | LONG_L $20, GDB_FR_REG20(sp) | ||
335 | LONG_L $19, GDB_FR_REG19(sp) | ||
336 | LONG_L $18, GDB_FR_REG18(sp) | ||
337 | LONG_L $17, GDB_FR_REG17(sp) | ||
338 | LONG_L $16, GDB_FR_REG16(sp) | ||
339 | LONG_L $15, GDB_FR_REG15(sp) | ||
340 | LONG_L $14, GDB_FR_REG14(sp) | ||
341 | LONG_L $13, GDB_FR_REG13(sp) | ||
342 | LONG_L $12, GDB_FR_REG12(sp) | ||
343 | LONG_L $11, GDB_FR_REG11(sp) | ||
344 | LONG_L $10, GDB_FR_REG10(sp) | ||
345 | LONG_L $9, GDB_FR_REG9(sp) | ||
346 | LONG_L $8, GDB_FR_REG8(sp) | ||
347 | LONG_L $7, GDB_FR_REG7(sp) | ||
348 | LONG_L $6, GDB_FR_REG6(sp) | ||
349 | LONG_L $5, GDB_FR_REG5(sp) | ||
350 | LONG_L $4, GDB_FR_REG4(sp) | ||
351 | LONG_L $3, GDB_FR_REG3(sp) | ||
352 | LONG_L $2, GDB_FR_REG2(sp) | ||
353 | LONG_L $1, GDB_FR_REG1(sp) | ||
354 | #if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX) | ||
355 | LONG_L k0, GDB_FR_EPC(sp) | ||
356 | LONG_L $29, GDB_FR_REG29(sp) /* Deallocate stack */ | ||
357 | jr k0 | ||
358 | rfe | ||
359 | #else | ||
360 | LONG_L sp, GDB_FR_REG29(sp) /* Deallocate stack */ | ||
361 | |||
362 | .set mips3 | ||
363 | eret | ||
364 | .set mips0 | ||
365 | #endif | ||
366 | .set at | ||
367 | .set reorder | ||
368 | END(trap_low) | ||
369 | |||
370 | LEAF(kgdb_read_byte) | ||
371 | 4: lb t0, (a0) | ||
372 | sb t0, (a1) | ||
373 | li v0, 0 | ||
374 | jr ra | ||
375 | .section __ex_table,"a" | ||
376 | PTR 4b, kgdbfault | ||
377 | .previous | ||
378 | END(kgdb_read_byte) | ||
379 | |||
380 | LEAF(kgdb_write_byte) | ||
381 | 5: sb a0, (a1) | ||
382 | li v0, 0 | ||
383 | jr ra | ||
384 | .section __ex_table,"a" | ||
385 | PTR 5b, kgdbfault | ||
386 | .previous | ||
387 | END(kgdb_write_byte) | ||
388 | |||
389 | .type kgdbfault@function | ||
390 | .ent kgdbfault | ||
391 | |||
392 | kgdbfault: li v0, -EFAULT | ||
393 | jr ra | ||
394 | .end kgdbfault | ||
diff --git a/arch/mips/kernel/gdb-stub.c b/arch/mips/kernel/gdb-stub.c deleted file mode 100644 index 25f4eab8ea9c..000000000000 --- a/arch/mips/kernel/gdb-stub.c +++ /dev/null | |||
@@ -1,1155 +0,0 @@ | |||
1 | /* | ||
2 | * arch/mips/kernel/gdb-stub.c | ||
3 | * | ||
4 | * Originally written by Glenn Engel, Lake Stevens Instrument Division | ||
5 | * | ||
6 | * Contributed by HP Systems | ||
7 | * | ||
8 | * Modified for SPARC by Stu Grossman, Cygnus Support. | ||
9 | * | ||
10 | * Modified for Linux/MIPS (and MIPS in general) by Andreas Busse | ||
11 | * Send complaints, suggestions etc. to <andy@waldorf-gmbh.de> | ||
12 | * | ||
13 | * Copyright (C) 1995 Andreas Busse | ||
14 | * | ||
15 | * Copyright (C) 2003 MontaVista Software Inc. | ||
16 | * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net | ||
17 | */ | ||
18 | |||
19 | /* | ||
20 | * To enable debugger support, two things need to happen. One, a | ||
21 | * call to set_debug_traps() is necessary in order to allow any breakpoints | ||
22 | * or error conditions to be properly intercepted and reported to gdb. | ||
23 | * Two, a breakpoint needs to be generated to begin communication. This | ||
24 | * is most easily accomplished by a call to breakpoint(). Breakpoint() | ||
25 | * simulates a breakpoint by executing a BREAK instruction. | ||
26 | * | ||
27 | * | ||
28 | * The following gdb commands are supported: | ||
29 | * | ||
30 | * command function Return value | ||
31 | * | ||
32 | * g return the value of the CPU registers hex data or ENN | ||
33 | * G set the value of the CPU registers OK or ENN | ||
34 | * | ||
35 | * mAA..AA,LLLL Read LLLL bytes at address AA..AA hex data or ENN | ||
36 | * MAA..AA,LLLL: Write LLLL bytes at address AA.AA OK or ENN | ||
37 | * | ||
38 | * c Resume at current address SNN ( signal NN) | ||
39 | * cAA..AA Continue at address AA..AA SNN | ||
40 | * | ||
41 | * s Step one instruction SNN | ||
42 | * sAA..AA Step one instruction from AA..AA SNN | ||
43 | * | ||
44 | * k kill | ||
45 | * | ||
46 | * ? What was the last sigval ? SNN (signal NN) | ||
47 | * | ||
48 | * bBB..BB Set baud rate to BB..BB OK or BNN, then sets | ||
49 | * baud rate | ||
50 | * | ||
51 | * All commands and responses are sent with a packet which includes a | ||
52 | * checksum. A packet consists of | ||
53 | * | ||
54 | * $<packet info>#<checksum>. | ||
55 | * | ||
56 | * where | ||
57 | * <packet info> :: <characters representing the command or response> | ||
58 | * <checksum> :: < two hex digits computed as modulo 256 sum of <packetinfo>> | ||
59 | * | ||
60 | * When a packet is received, it is first acknowledged with either '+' or '-'. | ||
61 | * '+' indicates a successful transfer. '-' indicates a failed transfer. | ||
62 | * | ||
63 | * Example: | ||
64 | * | ||
65 | * Host: Reply: | ||
66 | * $m0,10#2a +$00010203040506070809101112131415#42 | ||
67 | * | ||
68 | * | ||
69 | * ============== | ||
70 | * MORE EXAMPLES: | ||
71 | * ============== | ||
72 | * | ||
73 | * For reference -- the following are the steps that one | ||
74 | * company took (RidgeRun Inc) to get remote gdb debugging | ||
75 | * going. In this scenario the host machine was a PC and the | ||
76 | * target platform was a Galileo EVB64120A MIPS evaluation | ||
77 | * board. | ||
78 | * | ||
79 | * Step 1: | ||
80 | * First download gdb-5.0.tar.gz from the internet. | ||
81 | * and then build/install the package. | ||
82 | * | ||
83 | * Example: | ||
84 | * $ tar zxf gdb-5.0.tar.gz | ||
85 | * $ cd gdb-5.0 | ||
86 | * $ ./configure --target=mips-linux-elf | ||
87 | * $ make | ||
88 | * $ install | ||
89 | * $ which mips-linux-elf-gdb | ||
90 | * /usr/local/bin/mips-linux-elf-gdb | ||
91 | * | ||
92 | * Step 2: | ||
93 | * Configure linux for remote debugging and build it. | ||
94 | * | ||
95 | * Example: | ||
96 | * $ cd ~/linux | ||
97 | * $ make menuconfig <go to "Kernel Hacking" and turn on remote debugging> | ||
98 | * $ make | ||
99 | * | ||
100 | * Step 3: | ||
101 | * Download the kernel to the remote target and start | ||
102 | * the kernel running. It will promptly halt and wait | ||
103 | * for the host gdb session to connect. It does this | ||
104 | * since the "Kernel Hacking" option has defined | ||
105 | * CONFIG_KGDB which in turn enables your calls | ||
106 | * to: | ||
107 | * set_debug_traps(); | ||
108 | * breakpoint(); | ||
109 | * | ||
110 | * Step 4: | ||
111 | * Start the gdb session on the host. | ||
112 | * | ||
113 | * Example: | ||
114 | * $ mips-linux-elf-gdb vmlinux | ||
115 | * (gdb) set remotebaud 115200 | ||
116 | * (gdb) target remote /dev/ttyS1 | ||
117 | * ...at this point you are connected to | ||
118 | * the remote target and can use gdb | ||
119 | * in the normal fasion. Setting | ||
120 | * breakpoints, single stepping, | ||
121 | * printing variables, etc. | ||
122 | */ | ||
123 | #include <linux/string.h> | ||
124 | #include <linux/kernel.h> | ||
125 | #include <linux/signal.h> | ||
126 | #include <linux/sched.h> | ||
127 | #include <linux/mm.h> | ||
128 | #include <linux/console.h> | ||
129 | #include <linux/init.h> | ||
130 | #include <linux/smp.h> | ||
131 | #include <linux/spinlock.h> | ||
132 | #include <linux/slab.h> | ||
133 | #include <linux/reboot.h> | ||
134 | |||
135 | #include <asm/asm.h> | ||
136 | #include <asm/cacheflush.h> | ||
137 | #include <asm/mipsregs.h> | ||
138 | #include <asm/pgtable.h> | ||
139 | #include <asm/system.h> | ||
140 | #include <asm/gdb-stub.h> | ||
141 | #include <asm/inst.h> | ||
142 | |||
143 | /* | ||
144 | * external low-level support routines | ||
145 | */ | ||
146 | |||
147 | extern int putDebugChar(char c); /* write a single character */ | ||
148 | extern char getDebugChar(void); /* read and return a single char */ | ||
149 | extern void trap_low(void); | ||
150 | |||
151 | /* | ||
152 | * breakpoint and test functions | ||
153 | */ | ||
154 | extern void breakpoint(void); | ||
155 | extern void breakinst(void); | ||
156 | extern void async_breakpoint(void); | ||
157 | extern void async_breakinst(void); | ||
158 | extern void adel(void); | ||
159 | |||
160 | /* | ||
161 | * local prototypes | ||
162 | */ | ||
163 | |||
164 | static void getpacket(char *buffer); | ||
165 | static void putpacket(char *buffer); | ||
166 | static int computeSignal(int tt); | ||
167 | static int hex(unsigned char ch); | ||
168 | static int hexToInt(char **ptr, int *intValue); | ||
169 | static int hexToLong(char **ptr, long *longValue); | ||
170 | static unsigned char *mem2hex(char *mem, char *buf, int count, int may_fault); | ||
171 | void handle_exception(struct gdb_regs *regs); | ||
172 | |||
173 | int kgdb_enabled; | ||
174 | |||
175 | /* | ||
176 | * spin locks for smp case | ||
177 | */ | ||
178 | static DEFINE_SPINLOCK(kgdb_lock); | ||
179 | static raw_spinlock_t kgdb_cpulock[NR_CPUS] = { | ||
180 | [0 ... NR_CPUS-1] = __RAW_SPIN_LOCK_UNLOCKED, | ||
181 | }; | ||
182 | |||
183 | /* | ||
184 | * BUFMAX defines the maximum number of characters in inbound/outbound buffers | ||
185 | * at least NUMREGBYTES*2 are needed for register packets | ||
186 | */ | ||
187 | #define BUFMAX 2048 | ||
188 | |||
189 | static char input_buffer[BUFMAX]; | ||
190 | static char output_buffer[BUFMAX]; | ||
191 | static int initialized; /* !0 means we've been initialized */ | ||
192 | static int kgdb_started; | ||
193 | static const char hexchars[]="0123456789abcdef"; | ||
194 | |||
195 | /* Used to prevent crashes in memory access. Note that they'll crash anyway if | ||
196 | we haven't set up fault handlers yet... */ | ||
197 | int kgdb_read_byte(unsigned char *address, unsigned char *dest); | ||
198 | int kgdb_write_byte(unsigned char val, unsigned char *dest); | ||
199 | |||
200 | /* | ||
201 | * Convert ch from a hex digit to an int | ||
202 | */ | ||
203 | static int hex(unsigned char ch) | ||
204 | { | ||
205 | if (ch >= 'a' && ch <= 'f') | ||
206 | return ch-'a'+10; | ||
207 | if (ch >= '0' && ch <= '9') | ||
208 | return ch-'0'; | ||
209 | if (ch >= 'A' && ch <= 'F') | ||
210 | return ch-'A'+10; | ||
211 | return -1; | ||
212 | } | ||
213 | |||
214 | /* | ||
215 | * scan for the sequence $<data>#<checksum> | ||
216 | */ | ||
217 | static void getpacket(char *buffer) | ||
218 | { | ||
219 | unsigned char checksum; | ||
220 | unsigned char xmitcsum; | ||
221 | int i; | ||
222 | int count; | ||
223 | unsigned char ch; | ||
224 | |||
225 | do { | ||
226 | /* | ||
227 | * wait around for the start character, | ||
228 | * ignore all other characters | ||
229 | */ | ||
230 | while ((ch = (getDebugChar() & 0x7f)) != '$') ; | ||
231 | |||
232 | checksum = 0; | ||
233 | xmitcsum = -1; | ||
234 | count = 0; | ||
235 | |||
236 | /* | ||
237 | * now, read until a # or end of buffer is found | ||
238 | */ | ||
239 | while (count < BUFMAX) { | ||
240 | ch = getDebugChar(); | ||
241 | if (ch == '#') | ||
242 | break; | ||
243 | checksum = checksum + ch; | ||
244 | buffer[count] = ch; | ||
245 | count = count + 1; | ||
246 | } | ||
247 | |||
248 | if (count >= BUFMAX) | ||
249 | continue; | ||
250 | |||
251 | buffer[count] = 0; | ||
252 | |||
253 | if (ch == '#') { | ||
254 | xmitcsum = hex(getDebugChar() & 0x7f) << 4; | ||
255 | xmitcsum |= hex(getDebugChar() & 0x7f); | ||
256 | |||
257 | if (checksum != xmitcsum) | ||
258 | putDebugChar('-'); /* failed checksum */ | ||
259 | else { | ||
260 | putDebugChar('+'); /* successful transfer */ | ||
261 | |||
262 | /* | ||
263 | * if a sequence char is present, | ||
264 | * reply the sequence ID | ||
265 | */ | ||
266 | if (buffer[2] == ':') { | ||
267 | putDebugChar(buffer[0]); | ||
268 | putDebugChar(buffer[1]); | ||
269 | |||
270 | /* | ||
271 | * remove sequence chars from buffer | ||
272 | */ | ||
273 | count = strlen(buffer); | ||
274 | for (i=3; i <= count; i++) | ||
275 | buffer[i-3] = buffer[i]; | ||
276 | } | ||
277 | } | ||
278 | } | ||
279 | } | ||
280 | while (checksum != xmitcsum); | ||
281 | } | ||
282 | |||
283 | /* | ||
284 | * send the packet in buffer. | ||
285 | */ | ||
286 | static void putpacket(char *buffer) | ||
287 | { | ||
288 | unsigned char checksum; | ||
289 | int count; | ||
290 | unsigned char ch; | ||
291 | |||
292 | /* | ||
293 | * $<packet info>#<checksum>. | ||
294 | */ | ||
295 | |||
296 | do { | ||
297 | putDebugChar('$'); | ||
298 | checksum = 0; | ||
299 | count = 0; | ||
300 | |||
301 | while ((ch = buffer[count]) != 0) { | ||
302 | if (!(putDebugChar(ch))) | ||
303 | return; | ||
304 | checksum += ch; | ||
305 | count += 1; | ||
306 | } | ||
307 | |||
308 | putDebugChar('#'); | ||
309 | putDebugChar(hexchars[checksum >> 4]); | ||
310 | putDebugChar(hexchars[checksum & 0xf]); | ||
311 | |||
312 | } | ||
313 | while ((getDebugChar() & 0x7f) != '+'); | ||
314 | } | ||
315 | |||
316 | |||
317 | /* | ||
318 | * Convert the memory pointed to by mem into hex, placing result in buf. | ||
319 | * Return a pointer to the last char put in buf (null), in case of mem fault, | ||
320 | * return 0. | ||
321 | * may_fault is non-zero if we are reading from arbitrary memory, but is currently | ||
322 | * not used. | ||
323 | */ | ||
324 | static unsigned char *mem2hex(char *mem, char *buf, int count, int may_fault) | ||
325 | { | ||
326 | unsigned char ch; | ||
327 | |||
328 | while (count-- > 0) { | ||
329 | if (kgdb_read_byte(mem++, &ch) != 0) | ||
330 | return 0; | ||
331 | *buf++ = hexchars[ch >> 4]; | ||
332 | *buf++ = hexchars[ch & 0xf]; | ||
333 | } | ||
334 | |||
335 | *buf = 0; | ||
336 | |||
337 | return buf; | ||
338 | } | ||
339 | |||
340 | /* | ||
341 | * convert the hex array pointed to by buf into binary to be placed in mem | ||
342 | * return a pointer to the character AFTER the last byte written | ||
343 | * may_fault is non-zero if we are reading from arbitrary memory, but is currently | ||
344 | * not used. | ||
345 | */ | ||
346 | static char *hex2mem(char *buf, char *mem, int count, int binary, int may_fault) | ||
347 | { | ||
348 | int i; | ||
349 | unsigned char ch; | ||
350 | |||
351 | for (i=0; i<count; i++) | ||
352 | { | ||
353 | if (binary) { | ||
354 | ch = *buf++; | ||
355 | if (ch == 0x7d) | ||
356 | ch = 0x20 ^ *buf++; | ||
357 | } | ||
358 | else { | ||
359 | ch = hex(*buf++) << 4; | ||
360 | ch |= hex(*buf++); | ||
361 | } | ||
362 | if (kgdb_write_byte(ch, mem++) != 0) | ||
363 | return 0; | ||
364 | } | ||
365 | |||
366 | return mem; | ||
367 | } | ||
368 | |||
369 | /* | ||
370 | * This table contains the mapping between SPARC hardware trap types, and | ||
371 | * signals, which are primarily what GDB understands. It also indicates | ||
372 | * which hardware traps we need to commandeer when initializing the stub. | ||
373 | */ | ||
374 | static struct hard_trap_info { | ||
375 | unsigned char tt; /* Trap type code for MIPS R3xxx and R4xxx */ | ||
376 | unsigned char signo; /* Signal that we map this trap into */ | ||
377 | } hard_trap_info[] = { | ||
378 | { 6, SIGBUS }, /* instruction bus error */ | ||
379 | { 7, SIGBUS }, /* data bus error */ | ||
380 | { 9, SIGTRAP }, /* break */ | ||
381 | { 10, SIGILL }, /* reserved instruction */ | ||
382 | /* { 11, SIGILL }, */ /* CPU unusable */ | ||
383 | { 12, SIGFPE }, /* overflow */ | ||
384 | { 13, SIGTRAP }, /* trap */ | ||
385 | { 14, SIGSEGV }, /* virtual instruction cache coherency */ | ||
386 | { 15, SIGFPE }, /* floating point exception */ | ||
387 | { 23, SIGSEGV }, /* watch */ | ||
388 | { 31, SIGSEGV }, /* virtual data cache coherency */ | ||
389 | { 0, 0} /* Must be last */ | ||
390 | }; | ||
391 | |||
392 | /* Save the normal trap handlers for user-mode traps. */ | ||
393 | void *saved_vectors[32]; | ||
394 | |||
395 | /* | ||
396 | * Set up exception handlers for tracing and breakpoints | ||
397 | */ | ||
398 | void set_debug_traps(void) | ||
399 | { | ||
400 | struct hard_trap_info *ht; | ||
401 | unsigned long flags; | ||
402 | unsigned char c; | ||
403 | |||
404 | local_irq_save(flags); | ||
405 | for (ht = hard_trap_info; ht->tt && ht->signo; ht++) | ||
406 | saved_vectors[ht->tt] = set_except_vector(ht->tt, trap_low); | ||
407 | |||
408 | putDebugChar('+'); /* 'hello world' */ | ||
409 | /* | ||
410 | * In case GDB is started before us, ack any packets | ||
411 | * (presumably "$?#xx") sitting there. | ||
412 | */ | ||
413 | while((c = getDebugChar()) != '$'); | ||
414 | while((c = getDebugChar()) != '#'); | ||
415 | c = getDebugChar(); /* eat first csum byte */ | ||
416 | c = getDebugChar(); /* eat second csum byte */ | ||
417 | putDebugChar('+'); /* ack it */ | ||
418 | |||
419 | initialized = 1; | ||
420 | local_irq_restore(flags); | ||
421 | } | ||
422 | |||
423 | void restore_debug_traps(void) | ||
424 | { | ||
425 | struct hard_trap_info *ht; | ||
426 | unsigned long flags; | ||
427 | |||
428 | local_irq_save(flags); | ||
429 | for (ht = hard_trap_info; ht->tt && ht->signo; ht++) | ||
430 | set_except_vector(ht->tt, saved_vectors[ht->tt]); | ||
431 | local_irq_restore(flags); | ||
432 | } | ||
433 | |||
434 | /* | ||
435 | * Convert the MIPS hardware trap type code to a Unix signal number. | ||
436 | */ | ||
437 | static int computeSignal(int tt) | ||
438 | { | ||
439 | struct hard_trap_info *ht; | ||
440 | |||
441 | for (ht = hard_trap_info; ht->tt && ht->signo; ht++) | ||
442 | if (ht->tt == tt) | ||
443 | return ht->signo; | ||
444 | |||
445 | return SIGHUP; /* default for things we don't know about */ | ||
446 | } | ||
447 | |||
448 | /* | ||
449 | * While we find nice hex chars, build an int. | ||
450 | * Return number of chars processed. | ||
451 | */ | ||
452 | static int hexToInt(char **ptr, int *intValue) | ||
453 | { | ||
454 | int numChars = 0; | ||
455 | int hexValue; | ||
456 | |||
457 | *intValue = 0; | ||
458 | |||
459 | while (**ptr) { | ||
460 | hexValue = hex(**ptr); | ||
461 | if (hexValue < 0) | ||
462 | break; | ||
463 | |||
464 | *intValue = (*intValue << 4) | hexValue; | ||
465 | numChars ++; | ||
466 | |||
467 | (*ptr)++; | ||
468 | } | ||
469 | |||
470 | return (numChars); | ||
471 | } | ||
472 | |||
473 | static int hexToLong(char **ptr, long *longValue) | ||
474 | { | ||
475 | int numChars = 0; | ||
476 | int hexValue; | ||
477 | |||
478 | *longValue = 0; | ||
479 | |||
480 | while (**ptr) { | ||
481 | hexValue = hex(**ptr); | ||
482 | if (hexValue < 0) | ||
483 | break; | ||
484 | |||
485 | *longValue = (*longValue << 4) | hexValue; | ||
486 | numChars ++; | ||
487 | |||
488 | (*ptr)++; | ||
489 | } | ||
490 | |||
491 | return numChars; | ||
492 | } | ||
493 | |||
494 | |||
495 | #if 0 | ||
496 | /* | ||
497 | * Print registers (on target console) | ||
498 | * Used only to debug the stub... | ||
499 | */ | ||
500 | void show_gdbregs(struct gdb_regs * regs) | ||
501 | { | ||
502 | /* | ||
503 | * Saved main processor registers | ||
504 | */ | ||
505 | printk("$0 : %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n", | ||
506 | regs->reg0, regs->reg1, regs->reg2, regs->reg3, | ||
507 | regs->reg4, regs->reg5, regs->reg6, regs->reg7); | ||
508 | printk("$8 : %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n", | ||
509 | regs->reg8, regs->reg9, regs->reg10, regs->reg11, | ||
510 | regs->reg12, regs->reg13, regs->reg14, regs->reg15); | ||
511 | printk("$16: %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n", | ||
512 | regs->reg16, regs->reg17, regs->reg18, regs->reg19, | ||
513 | regs->reg20, regs->reg21, regs->reg22, regs->reg23); | ||
514 | printk("$24: %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n", | ||
515 | regs->reg24, regs->reg25, regs->reg26, regs->reg27, | ||
516 | regs->reg28, regs->reg29, regs->reg30, regs->reg31); | ||
517 | |||
518 | /* | ||
519 | * Saved cp0 registers | ||
520 | */ | ||
521 | printk("epc : %08lx\nStatus: %08lx\nCause : %08lx\n", | ||
522 | regs->cp0_epc, regs->cp0_status, regs->cp0_cause); | ||
523 | } | ||
524 | #endif /* dead code */ | ||
525 | |||
526 | /* | ||
527 | * We single-step by setting breakpoints. When an exception | ||
528 | * is handled, we need to restore the instructions hoisted | ||
529 | * when the breakpoints were set. | ||
530 | * | ||
531 | * This is where we save the original instructions. | ||
532 | */ | ||
533 | static struct gdb_bp_save { | ||
534 | unsigned long addr; | ||
535 | unsigned int val; | ||
536 | } step_bp[2]; | ||
537 | |||
538 | #define BP 0x0000000d /* break opcode */ | ||
539 | |||
540 | /* | ||
541 | * Set breakpoint instructions for single stepping. | ||
542 | */ | ||
543 | static void single_step(struct gdb_regs *regs) | ||
544 | { | ||
545 | union mips_instruction insn; | ||
546 | unsigned long targ; | ||
547 | int is_branch, is_cond, i; | ||
548 | |||
549 | targ = regs->cp0_epc; | ||
550 | insn.word = *(unsigned int *)targ; | ||
551 | is_branch = is_cond = 0; | ||
552 | |||
553 | switch (insn.i_format.opcode) { | ||
554 | /* | ||
555 | * jr and jalr are in r_format format. | ||
556 | */ | ||
557 | case spec_op: | ||
558 | switch (insn.r_format.func) { | ||
559 | case jalr_op: | ||
560 | case jr_op: | ||
561 | targ = *(®s->reg0 + insn.r_format.rs); | ||
562 | is_branch = 1; | ||
563 | break; | ||
564 | } | ||
565 | break; | ||
566 | |||
567 | /* | ||
568 | * This group contains: | ||
569 | * bltz_op, bgez_op, bltzl_op, bgezl_op, | ||
570 | * bltzal_op, bgezal_op, bltzall_op, bgezall_op. | ||
571 | */ | ||
572 | case bcond_op: | ||
573 | is_branch = is_cond = 1; | ||
574 | targ += 4 + (insn.i_format.simmediate << 2); | ||
575 | break; | ||
576 | |||
577 | /* | ||
578 | * These are unconditional and in j_format. | ||
579 | */ | ||
580 | case jal_op: | ||
581 | case j_op: | ||
582 | is_branch = 1; | ||
583 | targ += 4; | ||
584 | targ >>= 28; | ||
585 | targ <<= 28; | ||
586 | targ |= (insn.j_format.target << 2); | ||
587 | break; | ||
588 | |||
589 | /* | ||
590 | * These are conditional. | ||
591 | */ | ||
592 | case beq_op: | ||
593 | case beql_op: | ||
594 | case bne_op: | ||
595 | case bnel_op: | ||
596 | case blez_op: | ||
597 | case blezl_op: | ||
598 | case bgtz_op: | ||
599 | case bgtzl_op: | ||
600 | case cop0_op: | ||
601 | case cop1_op: | ||
602 | case cop2_op: | ||
603 | case cop1x_op: | ||
604 | is_branch = is_cond = 1; | ||
605 | targ += 4 + (insn.i_format.simmediate << 2); | ||
606 | break; | ||
607 | } | ||
608 | |||
609 | if (is_branch) { | ||
610 | i = 0; | ||
611 | if (is_cond && targ != (regs->cp0_epc + 8)) { | ||
612 | step_bp[i].addr = regs->cp0_epc + 8; | ||
613 | step_bp[i++].val = *(unsigned *)(regs->cp0_epc + 8); | ||
614 | *(unsigned *)(regs->cp0_epc + 8) = BP; | ||
615 | } | ||
616 | step_bp[i].addr = targ; | ||
617 | step_bp[i].val = *(unsigned *)targ; | ||
618 | *(unsigned *)targ = BP; | ||
619 | } else { | ||
620 | step_bp[0].addr = regs->cp0_epc + 4; | ||
621 | step_bp[0].val = *(unsigned *)(regs->cp0_epc + 4); | ||
622 | *(unsigned *)(regs->cp0_epc + 4) = BP; | ||
623 | } | ||
624 | } | ||
625 | |||
626 | /* | ||
627 | * If asynchronously interrupted by gdb, then we need to set a breakpoint | ||
628 | * at the interrupted instruction so that we wind up stopped with a | ||
629 | * reasonable stack frame. | ||
630 | */ | ||
631 | static struct gdb_bp_save async_bp; | ||
632 | |||
633 | /* | ||
634 | * Swap the interrupted EPC with our asynchronous breakpoint routine. | ||
635 | * This is safer than stuffing the breakpoint in-place, since no cache | ||
636 | * flushes (or resulting smp_call_functions) are required. The | ||
637 | * assumption is that only one CPU will be handling asynchronous bp's, | ||
638 | * and only one can be active at a time. | ||
639 | */ | ||
640 | extern spinlock_t smp_call_lock; | ||
641 | |||
642 | void set_async_breakpoint(unsigned long *epc) | ||
643 | { | ||
644 | /* skip breaking into userland */ | ||
645 | if ((*epc & 0x80000000) == 0) | ||
646 | return; | ||
647 | |||
648 | #ifdef CONFIG_SMP | ||
649 | /* avoid deadlock if someone is make IPC */ | ||
650 | if (spin_is_locked(&smp_call_lock)) | ||
651 | return; | ||
652 | #endif | ||
653 | |||
654 | async_bp.addr = *epc; | ||
655 | *epc = (unsigned long)async_breakpoint; | ||
656 | } | ||
657 | |||
658 | #ifdef CONFIG_SMP | ||
659 | static void kgdb_wait(void *arg) | ||
660 | { | ||
661 | unsigned flags; | ||
662 | int cpu = smp_processor_id(); | ||
663 | |||
664 | local_irq_save(flags); | ||
665 | |||
666 | __raw_spin_lock(&kgdb_cpulock[cpu]); | ||
667 | __raw_spin_unlock(&kgdb_cpulock[cpu]); | ||
668 | |||
669 | local_irq_restore(flags); | ||
670 | } | ||
671 | #endif | ||
672 | |||
673 | /* | ||
674 | * GDB stub needs to call kgdb_wait on all processor with interrupts | ||
675 | * disabled, so it uses it's own special variant. | ||
676 | */ | ||
677 | static int kgdb_smp_call_kgdb_wait(void) | ||
678 | { | ||
679 | #ifdef CONFIG_SMP | ||
680 | cpumask_t mask = cpu_online_map; | ||
681 | struct call_data_struct data; | ||
682 | int cpu = smp_processor_id(); | ||
683 | int cpus; | ||
684 | |||
685 | /* | ||
686 | * Can die spectacularly if this CPU isn't yet marked online | ||
687 | */ | ||
688 | BUG_ON(!cpu_online(cpu)); | ||
689 | |||
690 | cpu_clear(cpu, mask); | ||
691 | cpus = cpus_weight(mask); | ||
692 | if (!cpus) | ||
693 | return 0; | ||
694 | |||
695 | if (spin_is_locked(&smp_call_lock)) { | ||
696 | /* | ||
697 | * Some other processor is trying to make us do something | ||
698 | * but we're not going to respond... give up | ||
699 | */ | ||
700 | return -1; | ||
701 | } | ||
702 | |||
703 | /* | ||
704 | * We will continue here, accepting the fact that | ||
705 | * the kernel may deadlock if another CPU attempts | ||
706 | * to call smp_call_function now... | ||
707 | */ | ||
708 | |||
709 | data.func = kgdb_wait; | ||
710 | data.info = NULL; | ||
711 | atomic_set(&data.started, 0); | ||
712 | data.wait = 0; | ||
713 | |||
714 | spin_lock(&smp_call_lock); | ||
715 | call_data = &data; | ||
716 | mb(); | ||
717 | |||
718 | core_send_ipi_mask(mask, SMP_CALL_FUNCTION); | ||
719 | |||
720 | /* Wait for response */ | ||
721 | /* FIXME: lock-up detection, backtrace on lock-up */ | ||
722 | while (atomic_read(&data.started) != cpus) | ||
723 | barrier(); | ||
724 | |||
725 | call_data = NULL; | ||
726 | spin_unlock(&smp_call_lock); | ||
727 | #endif | ||
728 | |||
729 | return 0; | ||
730 | } | ||
731 | |||
732 | /* | ||
733 | * This function does all command processing for interfacing to gdb. It | ||
734 | * returns 1 if you should skip the instruction at the trap address, 0 | ||
735 | * otherwise. | ||
736 | */ | ||
737 | void handle_exception(struct gdb_regs *regs) | ||
738 | { | ||
739 | int trap; /* Trap type */ | ||
740 | int sigval; | ||
741 | long addr; | ||
742 | int length; | ||
743 | char *ptr; | ||
744 | unsigned long *stack; | ||
745 | int i; | ||
746 | int bflag = 0; | ||
747 | |||
748 | kgdb_started = 1; | ||
749 | |||
750 | /* | ||
751 | * acquire the big kgdb spinlock | ||
752 | */ | ||
753 | if (!spin_trylock(&kgdb_lock)) { | ||
754 | /* | ||
755 | * some other CPU has the lock, we should go back to | ||
756 | * receive the gdb_wait IPC | ||
757 | */ | ||
758 | return; | ||
759 | } | ||
760 | |||
761 | /* | ||
762 | * If we're in async_breakpoint(), restore the real EPC from | ||
763 | * the breakpoint. | ||
764 | */ | ||
765 | if (regs->cp0_epc == (unsigned long)async_breakinst) { | ||
766 | regs->cp0_epc = async_bp.addr; | ||
767 | async_bp.addr = 0; | ||
768 | } | ||
769 | |||
770 | /* | ||
771 | * acquire the CPU spinlocks | ||
772 | */ | ||
773 | for_each_online_cpu(i) | ||
774 | if (__raw_spin_trylock(&kgdb_cpulock[i]) == 0) | ||
775 | panic("kgdb: couldn't get cpulock %d\n", i); | ||
776 | |||
777 | /* | ||
778 | * force other cpus to enter kgdb | ||
779 | */ | ||
780 | kgdb_smp_call_kgdb_wait(); | ||
781 | |||
782 | /* | ||
783 | * If we're in breakpoint() increment the PC | ||
784 | */ | ||
785 | trap = (regs->cp0_cause & 0x7c) >> 2; | ||
786 | if (trap == 9 && regs->cp0_epc == (unsigned long)breakinst) | ||
787 | regs->cp0_epc += 4; | ||
788 | |||
789 | /* | ||
790 | * If we were single_stepping, restore the opcodes hoisted | ||
791 | * for the breakpoint[s]. | ||
792 | */ | ||
793 | if (step_bp[0].addr) { | ||
794 | *(unsigned *)step_bp[0].addr = step_bp[0].val; | ||
795 | step_bp[0].addr = 0; | ||
796 | |||
797 | if (step_bp[1].addr) { | ||
798 | *(unsigned *)step_bp[1].addr = step_bp[1].val; | ||
799 | step_bp[1].addr = 0; | ||
800 | } | ||
801 | } | ||
802 | |||
803 | stack = (long *)regs->reg29; /* stack ptr */ | ||
804 | sigval = computeSignal(trap); | ||
805 | |||
806 | /* | ||
807 | * reply to host that an exception has occurred | ||
808 | */ | ||
809 | ptr = output_buffer; | ||
810 | |||
811 | /* | ||
812 | * Send trap type (converted to signal) | ||
813 | */ | ||
814 | *ptr++ = 'T'; | ||
815 | *ptr++ = hexchars[sigval >> 4]; | ||
816 | *ptr++ = hexchars[sigval & 0xf]; | ||
817 | |||
818 | /* | ||
819 | * Send Error PC | ||
820 | */ | ||
821 | *ptr++ = hexchars[REG_EPC >> 4]; | ||
822 | *ptr++ = hexchars[REG_EPC & 0xf]; | ||
823 | *ptr++ = ':'; | ||
824 | ptr = mem2hex((char *)®s->cp0_epc, ptr, sizeof(long), 0); | ||
825 | *ptr++ = ';'; | ||
826 | |||
827 | /* | ||
828 | * Send frame pointer | ||
829 | */ | ||
830 | *ptr++ = hexchars[REG_FP >> 4]; | ||
831 | *ptr++ = hexchars[REG_FP & 0xf]; | ||
832 | *ptr++ = ':'; | ||
833 | ptr = mem2hex((char *)®s->reg30, ptr, sizeof(long), 0); | ||
834 | *ptr++ = ';'; | ||
835 | |||
836 | /* | ||
837 | * Send stack pointer | ||
838 | */ | ||
839 | *ptr++ = hexchars[REG_SP >> 4]; | ||
840 | *ptr++ = hexchars[REG_SP & 0xf]; | ||
841 | *ptr++ = ':'; | ||
842 | ptr = mem2hex((char *)®s->reg29, ptr, sizeof(long), 0); | ||
843 | *ptr++ = ';'; | ||
844 | |||
845 | *ptr++ = 0; | ||
846 | putpacket(output_buffer); /* send it off... */ | ||
847 | |||
848 | /* | ||
849 | * Wait for input from remote GDB | ||
850 | */ | ||
851 | while (1) { | ||
852 | output_buffer[0] = 0; | ||
853 | getpacket(input_buffer); | ||
854 | |||
855 | switch (input_buffer[0]) | ||
856 | { | ||
857 | case '?': | ||
858 | output_buffer[0] = 'S'; | ||
859 | output_buffer[1] = hexchars[sigval >> 4]; | ||
860 | output_buffer[2] = hexchars[sigval & 0xf]; | ||
861 | output_buffer[3] = 0; | ||
862 | break; | ||
863 | |||
864 | /* | ||
865 | * Detach debugger; let CPU run | ||
866 | */ | ||
867 | case 'D': | ||
868 | putpacket(output_buffer); | ||
869 | goto finish_kgdb; | ||
870 | break; | ||
871 | |||
872 | case 'd': | ||
873 | /* toggle debug flag */ | ||
874 | break; | ||
875 | |||
876 | /* | ||
877 | * Return the value of the CPU registers | ||
878 | */ | ||
879 | case 'g': | ||
880 | ptr = output_buffer; | ||
881 | ptr = mem2hex((char *)®s->reg0, ptr, 32*sizeof(long), 0); /* r0...r31 */ | ||
882 | ptr = mem2hex((char *)®s->cp0_status, ptr, 6*sizeof(long), 0); /* cp0 */ | ||
883 | ptr = mem2hex((char *)®s->fpr0, ptr, 32*sizeof(long), 0); /* f0...31 */ | ||
884 | ptr = mem2hex((char *)®s->cp1_fsr, ptr, 2*sizeof(long), 0); /* cp1 */ | ||
885 | ptr = mem2hex((char *)®s->frame_ptr, ptr, 2*sizeof(long), 0); /* frp */ | ||
886 | ptr = mem2hex((char *)®s->cp0_index, ptr, 16*sizeof(long), 0); /* cp0 */ | ||
887 | break; | ||
888 | |||
889 | /* | ||
890 | * set the value of the CPU registers - return OK | ||
891 | */ | ||
892 | case 'G': | ||
893 | { | ||
894 | ptr = &input_buffer[1]; | ||
895 | hex2mem(ptr, (char *)®s->reg0, 32*sizeof(long), 0, 0); | ||
896 | ptr += 32*(2*sizeof(long)); | ||
897 | hex2mem(ptr, (char *)®s->cp0_status, 6*sizeof(long), 0, 0); | ||
898 | ptr += 6*(2*sizeof(long)); | ||
899 | hex2mem(ptr, (char *)®s->fpr0, 32*sizeof(long), 0, 0); | ||
900 | ptr += 32*(2*sizeof(long)); | ||
901 | hex2mem(ptr, (char *)®s->cp1_fsr, 2*sizeof(long), 0, 0); | ||
902 | ptr += 2*(2*sizeof(long)); | ||
903 | hex2mem(ptr, (char *)®s->frame_ptr, 2*sizeof(long), 0, 0); | ||
904 | ptr += 2*(2*sizeof(long)); | ||
905 | hex2mem(ptr, (char *)®s->cp0_index, 16*sizeof(long), 0, 0); | ||
906 | strcpy(output_buffer, "OK"); | ||
907 | } | ||
908 | break; | ||
909 | |||
910 | /* | ||
911 | * mAA..AA,LLLL Read LLLL bytes at address AA..AA | ||
912 | */ | ||
913 | case 'm': | ||
914 | ptr = &input_buffer[1]; | ||
915 | |||
916 | if (hexToLong(&ptr, &addr) | ||
917 | && *ptr++ == ',' | ||
918 | && hexToInt(&ptr, &length)) { | ||
919 | if (mem2hex((char *)addr, output_buffer, length, 1)) | ||
920 | break; | ||
921 | strcpy(output_buffer, "E03"); | ||
922 | } else | ||
923 | strcpy(output_buffer, "E01"); | ||
924 | break; | ||
925 | |||
926 | /* | ||
927 | * XAA..AA,LLLL: Write LLLL escaped binary bytes at address AA.AA | ||
928 | */ | ||
929 | case 'X': | ||
930 | bflag = 1; | ||
931 | /* fall through */ | ||
932 | |||
933 | /* | ||
934 | * MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK | ||
935 | */ | ||
936 | case 'M': | ||
937 | ptr = &input_buffer[1]; | ||
938 | |||
939 | if (hexToLong(&ptr, &addr) | ||
940 | && *ptr++ == ',' | ||
941 | && hexToInt(&ptr, &length) | ||
942 | && *ptr++ == ':') { | ||
943 | if (hex2mem(ptr, (char *)addr, length, bflag, 1)) | ||
944 | strcpy(output_buffer, "OK"); | ||
945 | else | ||
946 | strcpy(output_buffer, "E03"); | ||
947 | } | ||
948 | else | ||
949 | strcpy(output_buffer, "E02"); | ||
950 | break; | ||
951 | |||
952 | /* | ||
953 | * cAA..AA Continue at address AA..AA(optional) | ||
954 | */ | ||
955 | case 'c': | ||
956 | /* try to read optional parameter, pc unchanged if no parm */ | ||
957 | |||
958 | ptr = &input_buffer[1]; | ||
959 | if (hexToLong(&ptr, &addr)) | ||
960 | regs->cp0_epc = addr; | ||
961 | |||
962 | goto exit_kgdb_exception; | ||
963 | break; | ||
964 | |||
965 | /* | ||
966 | * kill the program; let us try to restart the machine | ||
967 | * Reset the whole machine. | ||
968 | */ | ||
969 | case 'k': | ||
970 | case 'r': | ||
971 | machine_restart("kgdb restarts machine"); | ||
972 | break; | ||
973 | |||
974 | /* | ||
975 | * Step to next instruction | ||
976 | */ | ||
977 | case 's': | ||
978 | /* | ||
979 | * There is no single step insn in the MIPS ISA, so we | ||
980 | * use breakpoints and continue, instead. | ||
981 | */ | ||
982 | single_step(regs); | ||
983 | goto exit_kgdb_exception; | ||
984 | /* NOTREACHED */ | ||
985 | break; | ||
986 | |||
987 | /* | ||
988 | * Set baud rate (bBB) | ||
989 | * FIXME: Needs to be written | ||
990 | */ | ||
991 | case 'b': | ||
992 | { | ||
993 | #if 0 | ||
994 | int baudrate; | ||
995 | extern void set_timer_3(); | ||
996 | |||
997 | ptr = &input_buffer[1]; | ||
998 | if (!hexToInt(&ptr, &baudrate)) | ||
999 | { | ||
1000 | strcpy(output_buffer, "B01"); | ||
1001 | break; | ||
1002 | } | ||
1003 | |||
1004 | /* Convert baud rate to uart clock divider */ | ||
1005 | |||
1006 | switch (baudrate) | ||
1007 | { | ||
1008 | case 38400: | ||
1009 | baudrate = 16; | ||
1010 | break; | ||
1011 | case 19200: | ||
1012 | baudrate = 33; | ||
1013 | break; | ||
1014 | case 9600: | ||
1015 | baudrate = 65; | ||
1016 | break; | ||
1017 | default: | ||
1018 | baudrate = 0; | ||
1019 | strcpy(output_buffer, "B02"); | ||
1020 | goto x1; | ||
1021 | } | ||
1022 | |||
1023 | if (baudrate) { | ||
1024 | putpacket("OK"); /* Ack before changing speed */ | ||
1025 | set_timer_3(baudrate); /* Set it */ | ||
1026 | } | ||
1027 | #endif | ||
1028 | } | ||
1029 | break; | ||
1030 | |||
1031 | } /* switch */ | ||
1032 | |||
1033 | /* | ||
1034 | * reply to the request | ||
1035 | */ | ||
1036 | |||
1037 | putpacket(output_buffer); | ||
1038 | |||
1039 | } /* while */ | ||
1040 | |||
1041 | return; | ||
1042 | |||
1043 | finish_kgdb: | ||
1044 | restore_debug_traps(); | ||
1045 | |||
1046 | exit_kgdb_exception: | ||
1047 | /* release locks so other CPUs can go */ | ||
1048 | for_each_online_cpu(i) | ||
1049 | __raw_spin_unlock(&kgdb_cpulock[i]); | ||
1050 | spin_unlock(&kgdb_lock); | ||
1051 | |||
1052 | __flush_cache_all(); | ||
1053 | return; | ||
1054 | } | ||
1055 | |||
1056 | /* | ||
1057 | * This function will generate a breakpoint exception. It is used at the | ||
1058 | * beginning of a program to sync up with a debugger and can be used | ||
1059 | * otherwise as a quick means to stop program execution and "break" into | ||
1060 | * the debugger. | ||
1061 | */ | ||
1062 | void breakpoint(void) | ||
1063 | { | ||
1064 | if (!initialized) | ||
1065 | return; | ||
1066 | |||
1067 | __asm__ __volatile__( | ||
1068 | ".globl breakinst\n\t" | ||
1069 | ".set\tnoreorder\n\t" | ||
1070 | "nop\n" | ||
1071 | "breakinst:\tbreak\n\t" | ||
1072 | "nop\n\t" | ||
1073 | ".set\treorder" | ||
1074 | ); | ||
1075 | } | ||
1076 | |||
1077 | /* Nothing but the break; don't pollute any registers */ | ||
1078 | void async_breakpoint(void) | ||
1079 | { | ||
1080 | __asm__ __volatile__( | ||
1081 | ".globl async_breakinst\n\t" | ||
1082 | ".set\tnoreorder\n\t" | ||
1083 | "nop\n" | ||
1084 | "async_breakinst:\tbreak\n\t" | ||
1085 | "nop\n\t" | ||
1086 | ".set\treorder" | ||
1087 | ); | ||
1088 | } | ||
1089 | |||
1090 | void adel(void) | ||
1091 | { | ||
1092 | __asm__ __volatile__( | ||
1093 | ".globl\tadel\n\t" | ||
1094 | "lui\t$8,0x8000\n\t" | ||
1095 | "lw\t$9,1($8)\n\t" | ||
1096 | ); | ||
1097 | } | ||
1098 | |||
1099 | /* | ||
1100 | * malloc is needed by gdb client in "call func()", even a private one | ||
1101 | * will make gdb happy | ||
1102 | */ | ||
1103 | static void __used *malloc(size_t size) | ||
1104 | { | ||
1105 | return kmalloc(size, GFP_ATOMIC); | ||
1106 | } | ||
1107 | |||
1108 | static void __used free(void *where) | ||
1109 | { | ||
1110 | kfree(where); | ||
1111 | } | ||
1112 | |||
1113 | #ifdef CONFIG_GDB_CONSOLE | ||
1114 | |||
1115 | void gdb_putsn(const char *str, int l) | ||
1116 | { | ||
1117 | char outbuf[18]; | ||
1118 | |||
1119 | if (!kgdb_started) | ||
1120 | return; | ||
1121 | |||
1122 | outbuf[0]='O'; | ||
1123 | |||
1124 | while(l) { | ||
1125 | int i = (l>8)?8:l; | ||
1126 | mem2hex((char *)str, &outbuf[1], i, 0); | ||
1127 | outbuf[(i*2)+1]=0; | ||
1128 | putpacket(outbuf); | ||
1129 | str += i; | ||
1130 | l -= i; | ||
1131 | } | ||
1132 | } | ||
1133 | |||
1134 | static void gdb_console_write(struct console *con, const char *s, unsigned n) | ||
1135 | { | ||
1136 | gdb_putsn(s, n); | ||
1137 | } | ||
1138 | |||
1139 | static struct console gdb_console = { | ||
1140 | .name = "gdb", | ||
1141 | .write = gdb_console_write, | ||
1142 | .flags = CON_PRINTBUFFER, | ||
1143 | .index = -1 | ||
1144 | }; | ||
1145 | |||
1146 | static int __init register_gdb_console(void) | ||
1147 | { | ||
1148 | register_console(&gdb_console); | ||
1149 | |||
1150 | return 0; | ||
1151 | } | ||
1152 | |||
1153 | console_initcall(register_gdb_console); | ||
1154 | |||
1155 | #endif | ||
diff --git a/arch/mips/kernel/genex.S b/arch/mips/kernel/genex.S index c6ada98ee042..757d48f0d80f 100644 --- a/arch/mips/kernel/genex.S +++ b/arch/mips/kernel/genex.S | |||
@@ -20,6 +20,7 @@ | |||
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 | #include <asm/page.h> |
23 | #include <asm/thread_info.h> | ||
23 | 24 | ||
24 | #define PANIC_PIC(msg) \ | 25 | #define PANIC_PIC(msg) \ |
25 | .set push; \ | 26 | .set push; \ |
@@ -126,7 +127,42 @@ handle_vcei: | |||
126 | 127 | ||
127 | __FINIT | 128 | __FINIT |
128 | 129 | ||
130 | .align 5 /* 32 byte rollback region */ | ||
131 | LEAF(r4k_wait) | ||
132 | .set push | ||
133 | .set noreorder | ||
134 | /* start of rollback region */ | ||
135 | LONG_L t0, TI_FLAGS($28) | ||
136 | nop | ||
137 | andi t0, _TIF_NEED_RESCHED | ||
138 | bnez t0, 1f | ||
139 | nop | ||
140 | nop | ||
141 | nop | ||
142 | .set mips3 | ||
143 | wait | ||
144 | /* end of rollback region (the region size must be power of two) */ | ||
145 | .set pop | ||
146 | 1: | ||
147 | jr ra | ||
148 | END(r4k_wait) | ||
149 | |||
150 | .macro BUILD_ROLLBACK_PROLOGUE handler | ||
151 | FEXPORT(rollback_\handler) | ||
152 | .set push | ||
153 | .set noat | ||
154 | MFC0 k0, CP0_EPC | ||
155 | PTR_LA k1, r4k_wait | ||
156 | ori k0, 0x1f /* 32 byte rollback region */ | ||
157 | xori k0, 0x1f | ||
158 | bne k0, k1, 9f | ||
159 | MTC0 k0, CP0_EPC | ||
160 | 9: | ||
161 | .set pop | ||
162 | .endm | ||
163 | |||
129 | .align 5 | 164 | .align 5 |
165 | BUILD_ROLLBACK_PROLOGUE handle_int | ||
130 | NESTED(handle_int, PT_SIZE, sp) | 166 | NESTED(handle_int, PT_SIZE, sp) |
131 | #ifdef CONFIG_TRACE_IRQFLAGS | 167 | #ifdef CONFIG_TRACE_IRQFLAGS |
132 | /* | 168 | /* |
@@ -201,6 +237,7 @@ NESTED(except_vec_ejtag_debug, 0, sp) | |||
201 | * This prototype is copied to ebase + n*IntCtl.VS and patched | 237 | * This prototype is copied to ebase + n*IntCtl.VS and patched |
202 | * to invoke the handler | 238 | * to invoke the handler |
203 | */ | 239 | */ |
240 | BUILD_ROLLBACK_PROLOGUE except_vec_vi | ||
204 | NESTED(except_vec_vi, 0, sp) | 241 | NESTED(except_vec_vi, 0, sp) |
205 | SAVE_SOME | 242 | SAVE_SOME |
206 | SAVE_AT | 243 | SAVE_AT |
@@ -245,8 +282,8 @@ NESTED(except_vec_vi_handler, 0, sp) | |||
245 | and t0, a0, t1 | 282 | and t0, a0, t1 |
246 | #ifdef CONFIG_MIPS_MT_SMTC_IM_BACKSTOP | 283 | #ifdef CONFIG_MIPS_MT_SMTC_IM_BACKSTOP |
247 | mfc0 t2, CP0_TCCONTEXT | 284 | mfc0 t2, CP0_TCCONTEXT |
248 | or t0, t0, t2 | 285 | or t2, t0, t2 |
249 | mtc0 t0, CP0_TCCONTEXT | 286 | mtc0 t2, CP0_TCCONTEXT |
250 | #endif /* CONFIG_MIPS_MT_SMTC_IM_BACKSTOP */ | 287 | #endif /* CONFIG_MIPS_MT_SMTC_IM_BACKSTOP */ |
251 | xor t1, t1, t0 | 288 | xor t1, t1, t0 |
252 | mtc0 t1, CP0_STATUS | 289 | mtc0 t1, CP0_STATUS |
@@ -416,7 +453,11 @@ NESTED(nmi_handler, PT_SIZE, sp) | |||
416 | BUILD_HANDLER tr tr sti silent /* #13 */ | 453 | BUILD_HANDLER tr tr sti silent /* #13 */ |
417 | BUILD_HANDLER fpe fpe fpe silent /* #15 */ | 454 | BUILD_HANDLER fpe fpe fpe silent /* #15 */ |
418 | BUILD_HANDLER mdmx mdmx sti silent /* #22 */ | 455 | BUILD_HANDLER mdmx mdmx sti silent /* #22 */ |
456 | #ifdef CONFIG_HARDWARE_WATCHPOINTS | ||
457 | BUILD_HANDLER watch watch sti silent /* #23 */ | ||
458 | #else | ||
419 | BUILD_HANDLER watch watch sti verbose /* #23 */ | 459 | BUILD_HANDLER watch watch sti verbose /* #23 */ |
460 | #endif | ||
420 | BUILD_HANDLER mcheck mcheck cli verbose /* #24 */ | 461 | BUILD_HANDLER mcheck mcheck cli verbose /* #24 */ |
421 | BUILD_HANDLER mt mt sti silent /* #25 */ | 462 | BUILD_HANDLER mt mt sti silent /* #25 */ |
422 | BUILD_HANDLER dsp dsp sti silent /* #26 */ | 463 | BUILD_HANDLER dsp dsp sti silent /* #26 */ |
diff --git a/arch/mips/kernel/head.S b/arch/mips/kernel/head.S index 361364501d34..492a0a8d70fb 100644 --- a/arch/mips/kernel/head.S +++ b/arch/mips/kernel/head.S | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <asm/irqflags.h> | 22 | #include <asm/irqflags.h> |
23 | #include <asm/regdef.h> | 23 | #include <asm/regdef.h> |
24 | #include <asm/page.h> | 24 | #include <asm/page.h> |
25 | #include <asm/pgtable-bits.h> | ||
25 | #include <asm/mipsregs.h> | 26 | #include <asm/mipsregs.h> |
26 | #include <asm/stackframe.h> | 27 | #include <asm/stackframe.h> |
27 | 28 | ||
diff --git a/arch/mips/kernel/irq.c b/arch/mips/kernel/irq.c index 6045b9a51a35..4b4007b3083a 100644 --- a/arch/mips/kernel/irq.c +++ b/arch/mips/kernel/irq.c | |||
@@ -21,11 +21,16 @@ | |||
21 | #include <linux/sched.h> | 21 | #include <linux/sched.h> |
22 | #include <linux/seq_file.h> | 22 | #include <linux/seq_file.h> |
23 | #include <linux/kallsyms.h> | 23 | #include <linux/kallsyms.h> |
24 | #include <linux/kgdb.h> | ||
24 | 25 | ||
25 | #include <asm/atomic.h> | 26 | #include <asm/atomic.h> |
26 | #include <asm/system.h> | 27 | #include <asm/system.h> |
27 | #include <asm/uaccess.h> | 28 | #include <asm/uaccess.h> |
28 | 29 | ||
30 | #ifdef CONFIG_KGDB | ||
31 | int kgdb_early_setup; | ||
32 | #endif | ||
33 | |||
29 | static unsigned long irq_map[NR_IRQS / BITS_PER_LONG]; | 34 | static unsigned long irq_map[NR_IRQS / BITS_PER_LONG]; |
30 | 35 | ||
31 | int allocate_irqno(void) | 36 | int allocate_irqno(void) |
@@ -126,33 +131,22 @@ asmlinkage void spurious_interrupt(void) | |||
126 | atomic_inc(&irq_err_count); | 131 | atomic_inc(&irq_err_count); |
127 | } | 132 | } |
128 | 133 | ||
129 | #ifdef CONFIG_KGDB | ||
130 | extern void breakpoint(void); | ||
131 | extern void set_debug_traps(void); | ||
132 | |||
133 | static int kgdb_flag = 1; | ||
134 | static int __init nokgdb(char *str) | ||
135 | { | ||
136 | kgdb_flag = 0; | ||
137 | return 1; | ||
138 | } | ||
139 | __setup("nokgdb", nokgdb); | ||
140 | #endif | ||
141 | |||
142 | void __init init_IRQ(void) | 134 | void __init init_IRQ(void) |
143 | { | 135 | { |
144 | int i; | 136 | int i; |
145 | 137 | ||
138 | #ifdef CONFIG_KGDB | ||
139 | if (kgdb_early_setup) | ||
140 | return; | ||
141 | #endif | ||
142 | |||
146 | for (i = 0; i < NR_IRQS; i++) | 143 | for (i = 0; i < NR_IRQS; i++) |
147 | set_irq_noprobe(i); | 144 | set_irq_noprobe(i); |
148 | 145 | ||
149 | arch_init_irq(); | 146 | arch_init_irq(); |
150 | 147 | ||
151 | #ifdef CONFIG_KGDB | 148 | #ifdef CONFIG_KGDB |
152 | if (kgdb_flag) { | 149 | if (!kgdb_early_setup) |
153 | printk("Wait for gdb client connection ...\n"); | 150 | kgdb_early_setup = 1; |
154 | set_debug_traps(); | ||
155 | breakpoint(); | ||
156 | } | ||
157 | #endif | 151 | #endif |
158 | } | 152 | } |
diff --git a/arch/mips/kernel/kgdb.c b/arch/mips/kernel/kgdb.c new file mode 100644 index 000000000000..6e152c80cd4a --- /dev/null +++ b/arch/mips/kernel/kgdb.c | |||
@@ -0,0 +1,277 @@ | |||
1 | /* | ||
2 | * Originally written by Glenn Engel, Lake Stevens Instrument Division | ||
3 | * | ||
4 | * Contributed by HP Systems | ||
5 | * | ||
6 | * Modified for Linux/MIPS (and MIPS in general) by Andreas Busse | ||
7 | * Send complaints, suggestions etc. to <andy@waldorf-gmbh.de> | ||
8 | * | ||
9 | * Copyright (C) 1995 Andreas Busse | ||
10 | * | ||
11 | * Copyright (C) 2003 MontaVista Software Inc. | ||
12 | * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net | ||
13 | * | ||
14 | * Copyright (C) 2004-2005 MontaVista Software Inc. | ||
15 | * Author: Manish Lachwani, mlachwani@mvista.com or manish@koffee-break.com | ||
16 | * | ||
17 | * Copyright (C) 2007-2008 Wind River Systems, Inc. | ||
18 | * Author/Maintainer: Jason Wessel, jason.wessel@windriver.com | ||
19 | * | ||
20 | * This file is licensed under the terms of the GNU General Public License | ||
21 | * version 2. This program is licensed "as is" without any warranty of any | ||
22 | * kind, whether express or implied. | ||
23 | */ | ||
24 | |||
25 | #include <linux/ptrace.h> /* for linux pt_regs struct */ | ||
26 | #include <linux/kgdb.h> | ||
27 | #include <linux/kdebug.h> | ||
28 | #include <linux/sched.h> | ||
29 | #include <asm/inst.h> | ||
30 | #include <asm/fpu.h> | ||
31 | #include <asm/cacheflush.h> | ||
32 | #include <asm/processor.h> | ||
33 | #include <asm/sigcontext.h> | ||
34 | |||
35 | static struct hard_trap_info { | ||
36 | unsigned char tt; /* Trap type code for MIPS R3xxx and R4xxx */ | ||
37 | unsigned char signo; /* Signal that we map this trap into */ | ||
38 | } hard_trap_info[] = { | ||
39 | { 6, SIGBUS }, /* instruction bus error */ | ||
40 | { 7, SIGBUS }, /* data bus error */ | ||
41 | { 9, SIGTRAP }, /* break */ | ||
42 | /* { 11, SIGILL }, */ /* CPU unusable */ | ||
43 | { 12, SIGFPE }, /* overflow */ | ||
44 | { 13, SIGTRAP }, /* trap */ | ||
45 | { 14, SIGSEGV }, /* virtual instruction cache coherency */ | ||
46 | { 15, SIGFPE }, /* floating point exception */ | ||
47 | { 23, SIGSEGV }, /* watch */ | ||
48 | { 31, SIGSEGV }, /* virtual data cache coherency */ | ||
49 | { 0, 0} /* Must be last */ | ||
50 | }; | ||
51 | |||
52 | void arch_kgdb_breakpoint(void) | ||
53 | { | ||
54 | __asm__ __volatile__( | ||
55 | ".globl breakinst\n\t" | ||
56 | ".set\tnoreorder\n\t" | ||
57 | "nop\n" | ||
58 | "breakinst:\tbreak\n\t" | ||
59 | "nop\n\t" | ||
60 | ".set\treorder"); | ||
61 | } | ||
62 | |||
63 | static void kgdb_call_nmi_hook(void *ignored) | ||
64 | { | ||
65 | kgdb_nmicallback(raw_smp_processor_id(), NULL); | ||
66 | } | ||
67 | |||
68 | void kgdb_roundup_cpus(unsigned long flags) | ||
69 | { | ||
70 | local_irq_enable(); | ||
71 | smp_call_function(kgdb_call_nmi_hook, NULL, 0); | ||
72 | local_irq_disable(); | ||
73 | } | ||
74 | |||
75 | static int compute_signal(int tt) | ||
76 | { | ||
77 | struct hard_trap_info *ht; | ||
78 | |||
79 | for (ht = hard_trap_info; ht->tt && ht->signo; ht++) | ||
80 | if (ht->tt == tt) | ||
81 | return ht->signo; | ||
82 | |||
83 | return SIGHUP; /* default for things we don't know about */ | ||
84 | } | ||
85 | |||
86 | void pt_regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs) | ||
87 | { | ||
88 | int reg; | ||
89 | |||
90 | #if (KGDB_GDB_REG_SIZE == 32) | ||
91 | u32 *ptr = (u32 *)gdb_regs; | ||
92 | #else | ||
93 | u64 *ptr = (u64 *)gdb_regs; | ||
94 | #endif | ||
95 | |||
96 | for (reg = 0; reg < 32; reg++) | ||
97 | *(ptr++) = regs->regs[reg]; | ||
98 | |||
99 | *(ptr++) = regs->cp0_status; | ||
100 | *(ptr++) = regs->lo; | ||
101 | *(ptr++) = regs->hi; | ||
102 | *(ptr++) = regs->cp0_badvaddr; | ||
103 | *(ptr++) = regs->cp0_cause; | ||
104 | *(ptr++) = regs->cp0_epc; | ||
105 | |||
106 | /* FP REGS */ | ||
107 | if (!(current && (regs->cp0_status & ST0_CU1))) | ||
108 | return; | ||
109 | |||
110 | save_fp(current); | ||
111 | for (reg = 0; reg < 32; reg++) | ||
112 | *(ptr++) = current->thread.fpu.fpr[reg]; | ||
113 | } | ||
114 | |||
115 | void gdb_regs_to_pt_regs(unsigned long *gdb_regs, struct pt_regs *regs) | ||
116 | { | ||
117 | int reg; | ||
118 | |||
119 | #if (KGDB_GDB_REG_SIZE == 32) | ||
120 | const u32 *ptr = (u32 *)gdb_regs; | ||
121 | #else | ||
122 | const u64 *ptr = (u64 *)gdb_regs; | ||
123 | #endif | ||
124 | |||
125 | for (reg = 0; reg < 32; reg++) | ||
126 | regs->regs[reg] = *(ptr++); | ||
127 | |||
128 | regs->cp0_status = *(ptr++); | ||
129 | regs->lo = *(ptr++); | ||
130 | regs->hi = *(ptr++); | ||
131 | regs->cp0_badvaddr = *(ptr++); | ||
132 | regs->cp0_cause = *(ptr++); | ||
133 | regs->cp0_epc = *(ptr++); | ||
134 | |||
135 | /* FP REGS from current */ | ||
136 | if (!(current && (regs->cp0_status & ST0_CU1))) | ||
137 | return; | ||
138 | |||
139 | for (reg = 0; reg < 32; reg++) | ||
140 | current->thread.fpu.fpr[reg] = *(ptr++); | ||
141 | restore_fp(current); | ||
142 | } | ||
143 | |||
144 | /* | ||
145 | * Similar to regs_to_gdb_regs() except that process is sleeping and so | ||
146 | * we may not be able to get all the info. | ||
147 | */ | ||
148 | void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p) | ||
149 | { | ||
150 | int reg; | ||
151 | struct thread_info *ti = task_thread_info(p); | ||
152 | unsigned long ksp = (unsigned long)ti + THREAD_SIZE - 32; | ||
153 | struct pt_regs *regs = (struct pt_regs *)ksp - 1; | ||
154 | #if (KGDB_GDB_REG_SIZE == 32) | ||
155 | u32 *ptr = (u32 *)gdb_regs; | ||
156 | #else | ||
157 | u64 *ptr = (u64 *)gdb_regs; | ||
158 | #endif | ||
159 | |||
160 | for (reg = 0; reg < 16; reg++) | ||
161 | *(ptr++) = regs->regs[reg]; | ||
162 | |||
163 | /* S0 - S7 */ | ||
164 | for (reg = 16; reg < 24; reg++) | ||
165 | *(ptr++) = regs->regs[reg]; | ||
166 | |||
167 | for (reg = 24; reg < 28; reg++) | ||
168 | *(ptr++) = 0; | ||
169 | |||
170 | /* GP, SP, FP, RA */ | ||
171 | for (reg = 28; reg < 32; reg++) | ||
172 | *(ptr++) = regs->regs[reg]; | ||
173 | |||
174 | *(ptr++) = regs->cp0_status; | ||
175 | *(ptr++) = regs->lo; | ||
176 | *(ptr++) = regs->hi; | ||
177 | *(ptr++) = regs->cp0_badvaddr; | ||
178 | *(ptr++) = regs->cp0_cause; | ||
179 | *(ptr++) = regs->cp0_epc; | ||
180 | } | ||
181 | |||
182 | /* | ||
183 | * Calls linux_debug_hook before the kernel dies. If KGDB is enabled, | ||
184 | * then try to fall into the debugger | ||
185 | */ | ||
186 | static int kgdb_mips_notify(struct notifier_block *self, unsigned long cmd, | ||
187 | void *ptr) | ||
188 | { | ||
189 | struct die_args *args = (struct die_args *)ptr; | ||
190 | struct pt_regs *regs = args->regs; | ||
191 | int trap = (regs->cp0_cause & 0x7c) >> 2; | ||
192 | |||
193 | /* Userpace events, ignore. */ | ||
194 | if (user_mode(regs)) | ||
195 | return NOTIFY_DONE; | ||
196 | |||
197 | if (atomic_read(&kgdb_active) != -1) | ||
198 | kgdb_nmicallback(smp_processor_id(), regs); | ||
199 | |||
200 | if (kgdb_handle_exception(trap, compute_signal(trap), 0, regs)) | ||
201 | return NOTIFY_DONE; | ||
202 | |||
203 | if (atomic_read(&kgdb_setting_breakpoint)) | ||
204 | if ((trap == 9) && (regs->cp0_epc == (unsigned long)breakinst)) | ||
205 | regs->cp0_epc += 4; | ||
206 | |||
207 | /* In SMP mode, __flush_cache_all does IPI */ | ||
208 | local_irq_enable(); | ||
209 | __flush_cache_all(); | ||
210 | |||
211 | return NOTIFY_STOP; | ||
212 | } | ||
213 | |||
214 | static struct notifier_block kgdb_notifier = { | ||
215 | .notifier_call = kgdb_mips_notify, | ||
216 | }; | ||
217 | |||
218 | /* | ||
219 | * Handle the 's' and 'c' commands | ||
220 | */ | ||
221 | int kgdb_arch_handle_exception(int vector, int signo, int err_code, | ||
222 | char *remcom_in_buffer, char *remcom_out_buffer, | ||
223 | struct pt_regs *regs) | ||
224 | { | ||
225 | char *ptr; | ||
226 | unsigned long address; | ||
227 | int cpu = smp_processor_id(); | ||
228 | |||
229 | switch (remcom_in_buffer[0]) { | ||
230 | case 's': | ||
231 | case 'c': | ||
232 | /* handle the optional parameter */ | ||
233 | ptr = &remcom_in_buffer[1]; | ||
234 | if (kgdb_hex2long(&ptr, &address)) | ||
235 | regs->cp0_epc = address; | ||
236 | |||
237 | atomic_set(&kgdb_cpu_doing_single_step, -1); | ||
238 | if (remcom_in_buffer[0] == 's') | ||
239 | atomic_set(&kgdb_cpu_doing_single_step, cpu); | ||
240 | |||
241 | return 0; | ||
242 | } | ||
243 | |||
244 | return -1; | ||
245 | } | ||
246 | |||
247 | struct kgdb_arch arch_kgdb_ops; | ||
248 | |||
249 | /* | ||
250 | * We use kgdb_early_setup so that functions we need to call now don't | ||
251 | * cause trouble when called again later. | ||
252 | */ | ||
253 | int kgdb_arch_init(void) | ||
254 | { | ||
255 | union mips_instruction insn = { | ||
256 | .r_format = { | ||
257 | .opcode = spec_op, | ||
258 | .func = break_op, | ||
259 | } | ||
260 | }; | ||
261 | memcpy(arch_kgdb_ops.gdb_bpt_instr, insn.byte, BREAK_INSTR_SIZE); | ||
262 | |||
263 | register_die_notifier(&kgdb_notifier); | ||
264 | |||
265 | return 0; | ||
266 | } | ||
267 | |||
268 | /* | ||
269 | * kgdb_arch_exit - Perform any architecture specific uninitalization. | ||
270 | * | ||
271 | * This function will handle the uninitalization of any architecture | ||
272 | * specific callbacks, for dynamic registration and unregistration. | ||
273 | */ | ||
274 | void kgdb_arch_exit(void) | ||
275 | { | ||
276 | unregister_die_notifier(&kgdb_notifier); | ||
277 | } | ||
diff --git a/arch/mips/kernel/linux32.c b/arch/mips/kernel/linux32.c index 65af3cc90abb..aa2c55e3b55f 100644 --- a/arch/mips/kernel/linux32.c +++ b/arch/mips/kernel/linux32.c | |||
@@ -11,7 +11,6 @@ | |||
11 | #include <linux/file.h> | 11 | #include <linux/file.h> |
12 | #include <linux/smp_lock.h> | 12 | #include <linux/smp_lock.h> |
13 | #include <linux/highuid.h> | 13 | #include <linux/highuid.h> |
14 | #include <linux/dirent.h> | ||
15 | #include <linux/resource.h> | 14 | #include <linux/resource.h> |
16 | #include <linux/highmem.h> | 15 | #include <linux/highmem.h> |
17 | #include <linux/time.h> | 16 | #include <linux/time.h> |
@@ -64,41 +63,6 @@ | |||
64 | #define merge_64(r1, r2) ((((r2) & 0xffffffffUL) << 32) + ((r1) & 0xffffffffUL)) | 63 | #define merge_64(r1, r2) ((((r2) & 0xffffffffUL) << 32) + ((r1) & 0xffffffffUL)) |
65 | #endif | 64 | #endif |
66 | 65 | ||
67 | /* | ||
68 | * Revalidate the inode. This is required for proper NFS attribute caching. | ||
69 | */ | ||
70 | |||
71 | int cp_compat_stat(struct kstat *stat, struct compat_stat __user *statbuf) | ||
72 | { | ||
73 | struct compat_stat tmp; | ||
74 | |||
75 | if (!new_valid_dev(stat->dev) || !new_valid_dev(stat->rdev)) | ||
76 | return -EOVERFLOW; | ||
77 | |||
78 | memset(&tmp, 0, sizeof(tmp)); | ||
79 | tmp.st_dev = new_encode_dev(stat->dev); | ||
80 | tmp.st_ino = stat->ino; | ||
81 | if (sizeof(tmp.st_ino) < sizeof(stat->ino) && tmp.st_ino != stat->ino) | ||
82 | return -EOVERFLOW; | ||
83 | tmp.st_mode = stat->mode; | ||
84 | tmp.st_nlink = stat->nlink; | ||
85 | SET_UID(tmp.st_uid, stat->uid); | ||
86 | SET_GID(tmp.st_gid, stat->gid); | ||
87 | tmp.st_rdev = new_encode_dev(stat->rdev); | ||
88 | tmp.st_size = stat->size; | ||
89 | tmp.st_atime = stat->atime.tv_sec; | ||
90 | tmp.st_mtime = stat->mtime.tv_sec; | ||
91 | tmp.st_ctime = stat->ctime.tv_sec; | ||
92 | #ifdef STAT_HAVE_NSEC | ||
93 | tmp.st_atime_nsec = stat->atime.tv_nsec; | ||
94 | tmp.st_mtime_nsec = stat->mtime.tv_nsec; | ||
95 | tmp.st_ctime_nsec = stat->ctime.tv_nsec; | ||
96 | #endif | ||
97 | tmp.st_blocks = stat->blocks; | ||
98 | tmp.st_blksize = stat->blksize; | ||
99 | return copy_to_user(statbuf, &tmp, sizeof(tmp)) ? -EFAULT : 0; | ||
100 | } | ||
101 | |||
102 | asmlinkage unsigned long | 66 | asmlinkage unsigned long |
103 | sys32_mmap2(unsigned long addr, unsigned long len, unsigned long prot, | 67 | sys32_mmap2(unsigned long addr, unsigned long len, unsigned long prot, |
104 | unsigned long flags, unsigned long fd, unsigned long pgoff) | 68 | unsigned long flags, unsigned long fd, unsigned long pgoff) |
@@ -129,23 +93,6 @@ out: | |||
129 | return error; | 93 | return error; |
130 | } | 94 | } |
131 | 95 | ||
132 | |||
133 | asmlinkage int sys_truncate64(const char __user *path, unsigned int high, | ||
134 | unsigned int low) | ||
135 | { | ||
136 | if ((int)high < 0) | ||
137 | return -EINVAL; | ||
138 | return sys_truncate(path, ((long) high << 32) | low); | ||
139 | } | ||
140 | |||
141 | asmlinkage int sys_ftruncate64(unsigned int fd, unsigned int high, | ||
142 | unsigned int low) | ||
143 | { | ||
144 | if ((int)high < 0) | ||
145 | return -EINVAL; | ||
146 | return sys_ftruncate(fd, ((long) high << 32) | low); | ||
147 | } | ||
148 | |||
149 | /* | 96 | /* |
150 | * sys_execve() executes a new program. | 97 | * sys_execve() executes a new program. |
151 | */ | 98 | */ |
@@ -186,72 +133,6 @@ asmlinkage long sys32_ftruncate64(unsigned int fd, unsigned long __dummy, | |||
186 | return sys_ftruncate(fd, merge_64(a2, a3)); | 133 | return sys_ftruncate(fd, merge_64(a2, a3)); |
187 | } | 134 | } |
188 | 135 | ||
189 | static inline long | ||
190 | get_tv32(struct timeval *o, struct compat_timeval __user *i) | ||
191 | { | ||
192 | return (!access_ok(VERIFY_READ, i, sizeof(*i)) || | ||
193 | (__get_user(o->tv_sec, &i->tv_sec) | | ||
194 | __get_user(o->tv_usec, &i->tv_usec))); | ||
195 | } | ||
196 | |||
197 | static inline long | ||
198 | put_tv32(struct compat_timeval __user *o, struct timeval *i) | ||
199 | { | ||
200 | return (!access_ok(VERIFY_WRITE, o, sizeof(*o)) || | ||
201 | (__put_user(i->tv_sec, &o->tv_sec) | | ||
202 | __put_user(i->tv_usec, &o->tv_usec))); | ||
203 | } | ||
204 | |||
205 | extern struct timezone sys_tz; | ||
206 | |||
207 | asmlinkage int | ||
208 | sys32_gettimeofday(struct compat_timeval __user *tv, struct timezone __user *tz) | ||
209 | { | ||
210 | if (tv) { | ||
211 | struct timeval ktv; | ||
212 | do_gettimeofday(&ktv); | ||
213 | if (put_tv32(tv, &ktv)) | ||
214 | return -EFAULT; | ||
215 | } | ||
216 | if (tz) { | ||
217 | if (copy_to_user(tz, &sys_tz, sizeof(sys_tz))) | ||
218 | return -EFAULT; | ||
219 | } | ||
220 | return 0; | ||
221 | } | ||
222 | |||
223 | static inline long get_ts32(struct timespec *o, struct compat_timeval __user *i) | ||
224 | { | ||
225 | long usec; | ||
226 | |||
227 | if (!access_ok(VERIFY_READ, i, sizeof(*i))) | ||
228 | return -EFAULT; | ||
229 | if (__get_user(o->tv_sec, &i->tv_sec)) | ||
230 | return -EFAULT; | ||
231 | if (__get_user(usec, &i->tv_usec)) | ||
232 | return -EFAULT; | ||
233 | o->tv_nsec = usec * 1000; | ||
234 | return 0; | ||
235 | } | ||
236 | |||
237 | asmlinkage int | ||
238 | sys32_settimeofday(struct compat_timeval __user *tv, struct timezone __user *tz) | ||
239 | { | ||
240 | struct timespec kts; | ||
241 | struct timezone ktz; | ||
242 | |||
243 | if (tv) { | ||
244 | if (get_ts32(&kts, tv)) | ||
245 | return -EFAULT; | ||
246 | } | ||
247 | if (tz) { | ||
248 | if (copy_from_user(&ktz, tz, sizeof(ktz))) | ||
249 | return -EFAULT; | ||
250 | } | ||
251 | |||
252 | return do_sys_settimeofday(tv ? &kts : NULL, tz ? &ktz : NULL); | ||
253 | } | ||
254 | |||
255 | asmlinkage int sys32_llseek(unsigned int fd, unsigned int offset_high, | 136 | asmlinkage int sys32_llseek(unsigned int fd, unsigned int offset_high, |
256 | unsigned int offset_low, loff_t __user * result, | 137 | unsigned int offset_low, loff_t __user * result, |
257 | unsigned int origin) | 138 | unsigned int origin) |
diff --git a/arch/mips/kernel/mips-mt-fpaff.c b/arch/mips/kernel/mips-mt-fpaff.c index df4d3f2f740c..dc9eb72ed9de 100644 --- a/arch/mips/kernel/mips-mt-fpaff.c +++ b/arch/mips/kernel/mips-mt-fpaff.c | |||
@@ -159,7 +159,7 @@ __setup("fpaff=", fpaff_thresh); | |||
159 | /* | 159 | /* |
160 | * FPU Use Factor empirically derived from experiments on 34K | 160 | * FPU Use Factor empirically derived from experiments on 34K |
161 | */ | 161 | */ |
162 | #define FPUSEFACTOR 333 | 162 | #define FPUSEFACTOR 2000 |
163 | 163 | ||
164 | static __init int mt_fp_affinity_init(void) | 164 | static __init int mt_fp_affinity_init(void) |
165 | { | 165 | { |
diff --git a/arch/mips/kernel/module.c b/arch/mips/kernel/module.c index e7ed0ac48537..1f60e27523d9 100644 --- a/arch/mips/kernel/module.c +++ b/arch/mips/kernel/module.c | |||
@@ -22,6 +22,7 @@ | |||
22 | 22 | ||
23 | #include <linux/moduleloader.h> | 23 | #include <linux/moduleloader.h> |
24 | #include <linux/elf.h> | 24 | #include <linux/elf.h> |
25 | #include <linux/mm.h> | ||
25 | #include <linux/vmalloc.h> | 26 | #include <linux/vmalloc.h> |
26 | #include <linux/slab.h> | 27 | #include <linux/slab.h> |
27 | #include <linux/fs.h> | 28 | #include <linux/fs.h> |
diff --git a/arch/mips/kernel/proc.c b/arch/mips/kernel/proc.c index 36f065398243..26760cad8b69 100644 --- a/arch/mips/kernel/proc.c +++ b/arch/mips/kernel/proc.c | |||
@@ -23,6 +23,7 @@ static int show_cpuinfo(struct seq_file *m, void *v) | |||
23 | unsigned int version = cpu_data[n].processor_id; | 23 | unsigned int version = cpu_data[n].processor_id; |
24 | unsigned int fp_vers = cpu_data[n].fpu_id; | 24 | unsigned int fp_vers = cpu_data[n].fpu_id; |
25 | char fmt [64]; | 25 | char fmt [64]; |
26 | int i; | ||
26 | 27 | ||
27 | #ifdef CONFIG_SMP | 28 | #ifdef CONFIG_SMP |
28 | if (!cpu_isset(n, cpu_online_map)) | 29 | if (!cpu_isset(n, cpu_online_map)) |
@@ -38,7 +39,7 @@ static int show_cpuinfo(struct seq_file *m, void *v) | |||
38 | seq_printf(m, "processor\t\t: %ld\n", n); | 39 | seq_printf(m, "processor\t\t: %ld\n", n); |
39 | sprintf(fmt, "cpu model\t\t: %%s V%%d.%%d%s\n", | 40 | sprintf(fmt, "cpu model\t\t: %%s V%%d.%%d%s\n", |
40 | cpu_data[n].options & MIPS_CPU_FPU ? " FPU V%d.%d" : ""); | 41 | cpu_data[n].options & MIPS_CPU_FPU ? " FPU V%d.%d" : ""); |
41 | seq_printf(m, fmt, __cpu_name[smp_processor_id()], | 42 | seq_printf(m, fmt, __cpu_name[n], |
42 | (version >> 4) & 0x0f, version & 0x0f, | 43 | (version >> 4) & 0x0f, version & 0x0f, |
43 | (fp_vers >> 4) & 0x0f, fp_vers & 0x0f); | 44 | (fp_vers >> 4) & 0x0f, fp_vers & 0x0f); |
44 | seq_printf(m, "BogoMIPS\t\t: %lu.%02lu\n", | 45 | seq_printf(m, "BogoMIPS\t\t: %lu.%02lu\n", |
@@ -50,8 +51,16 @@ static int show_cpuinfo(struct seq_file *m, void *v) | |||
50 | seq_printf(m, "tlb_entries\t\t: %d\n", cpu_data[n].tlbsize); | 51 | seq_printf(m, "tlb_entries\t\t: %d\n", cpu_data[n].tlbsize); |
51 | seq_printf(m, "extra interrupt vector\t: %s\n", | 52 | seq_printf(m, "extra interrupt vector\t: %s\n", |
52 | cpu_has_divec ? "yes" : "no"); | 53 | cpu_has_divec ? "yes" : "no"); |
53 | seq_printf(m, "hardware watchpoint\t: %s\n", | 54 | seq_printf(m, "hardware watchpoint\t: %s", |
54 | cpu_has_watch ? "yes" : "no"); | 55 | cpu_has_watch ? "yes, " : "no\n"); |
56 | if (cpu_has_watch) { | ||
57 | seq_printf(m, "count: %d, address/irw mask: [", | ||
58 | cpu_data[n].watch_reg_count); | ||
59 | for (i = 0; i < cpu_data[n].watch_reg_count; i++) | ||
60 | seq_printf(m, "%s0x%04x", i ? ", " : "" , | ||
61 | cpu_data[n].watch_reg_masks[i]); | ||
62 | seq_printf(m, "]\n"); | ||
63 | } | ||
55 | seq_printf(m, "ASEs implemented\t:%s%s%s%s%s%s\n", | 64 | seq_printf(m, "ASEs implemented\t:%s%s%s%s%s%s\n", |
56 | cpu_has_mips16 ? " mips16" : "", | 65 | cpu_has_mips16 ? " mips16" : "", |
57 | cpu_has_mdmx ? " mdmx" : "", | 66 | cpu_has_mdmx ? " mdmx" : "", |
diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c index c06f5b5d764c..ca2e4026ad20 100644 --- a/arch/mips/kernel/process.c +++ b/arch/mips/kernel/process.c | |||
@@ -22,7 +22,6 @@ | |||
22 | #include <linux/personality.h> | 22 | #include <linux/personality.h> |
23 | #include <linux/sys.h> | 23 | #include <linux/sys.h> |
24 | #include <linux/user.h> | 24 | #include <linux/user.h> |
25 | #include <linux/a.out.h> | ||
26 | #include <linux/init.h> | 25 | #include <linux/init.h> |
27 | #include <linux/completion.h> | 26 | #include <linux/completion.h> |
28 | #include <linux/kallsyms.h> | 27 | #include <linux/kallsyms.h> |
@@ -53,9 +52,9 @@ void __noreturn cpu_idle(void) | |||
53 | { | 52 | { |
54 | /* endless idle loop with no priority at all */ | 53 | /* endless idle loop with no priority at all */ |
55 | while (1) { | 54 | while (1) { |
56 | tick_nohz_stop_sched_tick(); | 55 | tick_nohz_stop_sched_tick(1); |
57 | while (!need_resched()) { | 56 | while (!need_resched()) { |
58 | #ifdef CONFIG_SMTC_IDLE_HOOK_DEBUG | 57 | #ifdef CONFIG_MIPS_MT_SMTC |
59 | extern void smtc_idle_loop_hook(void); | 58 | extern void smtc_idle_loop_hook(void); |
60 | 59 | ||
61 | smtc_idle_loop_hook(); | 60 | smtc_idle_loop_hook(); |
@@ -145,17 +144,18 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp, | |||
145 | */ | 144 | */ |
146 | p->thread.cp0_status = read_c0_status() & ~(ST0_CU2|ST0_CU1); | 145 | p->thread.cp0_status = read_c0_status() & ~(ST0_CU2|ST0_CU1); |
147 | childregs->cp0_status &= ~(ST0_CU2|ST0_CU1); | 146 | childregs->cp0_status &= ~(ST0_CU2|ST0_CU1); |
148 | clear_tsk_thread_flag(p, TIF_USEDFPU); | ||
149 | 147 | ||
150 | #ifdef CONFIG_MIPS_MT_FPAFF | 148 | #ifdef CONFIG_MIPS_MT_SMTC |
151 | /* | 149 | /* |
152 | * FPU affinity support is cleaner if we track the | 150 | * SMTC restores TCStatus after Status, and the CU bits |
153 | * user-visible CPU affinity from the very beginning. | 151 | * are aliased there. |
154 | * The generic cpus_allowed mask will already have | ||
155 | * been copied from the parent before copy_thread | ||
156 | * is invoked. | ||
157 | */ | 152 | */ |
158 | p->thread.user_cpus_allowed = p->cpus_allowed; | 153 | childregs->cp0_tcstatus &= ~(ST0_CU2|ST0_CU1); |
154 | #endif | ||
155 | clear_tsk_thread_flag(p, TIF_USEDFPU); | ||
156 | |||
157 | #ifdef CONFIG_MIPS_MT_FPAFF | ||
158 | clear_tsk_thread_flag(p, TIF_FPUBOUND); | ||
159 | #endif /* CONFIG_MIPS_MT_FPAFF */ | 159 | #endif /* CONFIG_MIPS_MT_FPAFF */ |
160 | 160 | ||
161 | if (clone_flags & CLONE_SETTLS) | 161 | if (clone_flags & CLONE_SETTLS) |
diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c index 35234b92b9a5..054861ccb4dd 100644 --- a/arch/mips/kernel/ptrace.c +++ b/arch/mips/kernel/ptrace.c | |||
@@ -46,7 +46,8 @@ | |||
46 | */ | 46 | */ |
47 | void ptrace_disable(struct task_struct *child) | 47 | void ptrace_disable(struct task_struct *child) |
48 | { | 48 | { |
49 | /* Nothing to do.. */ | 49 | /* Don't load the watchpoint registers for the ex-child. */ |
50 | clear_tsk_thread_flag(child, TIF_LOAD_WATCH); | ||
50 | } | 51 | } |
51 | 52 | ||
52 | /* | 53 | /* |
@@ -167,6 +168,93 @@ int ptrace_setfpregs(struct task_struct *child, __u32 __user *data) | |||
167 | return 0; | 168 | return 0; |
168 | } | 169 | } |
169 | 170 | ||
171 | int ptrace_get_watch_regs(struct task_struct *child, | ||
172 | struct pt_watch_regs __user *addr) | ||
173 | { | ||
174 | enum pt_watch_style style; | ||
175 | int i; | ||
176 | |||
177 | if (!cpu_has_watch || current_cpu_data.watch_reg_use_cnt == 0) | ||
178 | return -EIO; | ||
179 | if (!access_ok(VERIFY_WRITE, addr, sizeof(struct pt_watch_regs))) | ||
180 | return -EIO; | ||
181 | |||
182 | #ifdef CONFIG_32BIT | ||
183 | style = pt_watch_style_mips32; | ||
184 | #define WATCH_STYLE mips32 | ||
185 | #else | ||
186 | style = pt_watch_style_mips64; | ||
187 | #define WATCH_STYLE mips64 | ||
188 | #endif | ||
189 | |||
190 | __put_user(style, &addr->style); | ||
191 | __put_user(current_cpu_data.watch_reg_use_cnt, | ||
192 | &addr->WATCH_STYLE.num_valid); | ||
193 | for (i = 0; i < current_cpu_data.watch_reg_use_cnt; i++) { | ||
194 | __put_user(child->thread.watch.mips3264.watchlo[i], | ||
195 | &addr->WATCH_STYLE.watchlo[i]); | ||
196 | __put_user(child->thread.watch.mips3264.watchhi[i] & 0xfff, | ||
197 | &addr->WATCH_STYLE.watchhi[i]); | ||
198 | __put_user(current_cpu_data.watch_reg_masks[i], | ||
199 | &addr->WATCH_STYLE.watch_masks[i]); | ||
200 | } | ||
201 | for (; i < 8; i++) { | ||
202 | __put_user(0, &addr->WATCH_STYLE.watchlo[i]); | ||
203 | __put_user(0, &addr->WATCH_STYLE.watchhi[i]); | ||
204 | __put_user(0, &addr->WATCH_STYLE.watch_masks[i]); | ||
205 | } | ||
206 | |||
207 | return 0; | ||
208 | } | ||
209 | |||
210 | int ptrace_set_watch_regs(struct task_struct *child, | ||
211 | struct pt_watch_regs __user *addr) | ||
212 | { | ||
213 | int i; | ||
214 | int watch_active = 0; | ||
215 | unsigned long lt[NUM_WATCH_REGS]; | ||
216 | u16 ht[NUM_WATCH_REGS]; | ||
217 | |||
218 | if (!cpu_has_watch || current_cpu_data.watch_reg_use_cnt == 0) | ||
219 | return -EIO; | ||
220 | if (!access_ok(VERIFY_READ, addr, sizeof(struct pt_watch_regs))) | ||
221 | return -EIO; | ||
222 | /* Check the values. */ | ||
223 | for (i = 0; i < current_cpu_data.watch_reg_use_cnt; i++) { | ||
224 | __get_user(lt[i], &addr->WATCH_STYLE.watchlo[i]); | ||
225 | #ifdef CONFIG_32BIT | ||
226 | if (lt[i] & __UA_LIMIT) | ||
227 | return -EINVAL; | ||
228 | #else | ||
229 | if (test_tsk_thread_flag(child, TIF_32BIT_ADDR)) { | ||
230 | if (lt[i] & 0xffffffff80000000UL) | ||
231 | return -EINVAL; | ||
232 | } else { | ||
233 | if (lt[i] & __UA_LIMIT) | ||
234 | return -EINVAL; | ||
235 | } | ||
236 | #endif | ||
237 | __get_user(ht[i], &addr->WATCH_STYLE.watchhi[i]); | ||
238 | if (ht[i] & ~0xff8) | ||
239 | return -EINVAL; | ||
240 | } | ||
241 | /* Install them. */ | ||
242 | for (i = 0; i < current_cpu_data.watch_reg_use_cnt; i++) { | ||
243 | if (lt[i] & 7) | ||
244 | watch_active = 1; | ||
245 | child->thread.watch.mips3264.watchlo[i] = lt[i]; | ||
246 | /* Set the G bit. */ | ||
247 | child->thread.watch.mips3264.watchhi[i] = ht[i]; | ||
248 | } | ||
249 | |||
250 | if (watch_active) | ||
251 | set_tsk_thread_flag(child, TIF_LOAD_WATCH); | ||
252 | else | ||
253 | clear_tsk_thread_flag(child, TIF_LOAD_WATCH); | ||
254 | |||
255 | return 0; | ||
256 | } | ||
257 | |||
170 | long arch_ptrace(struct task_struct *child, long request, long addr, long data) | 258 | long arch_ptrace(struct task_struct *child, long request, long addr, long data) |
171 | { | 259 | { |
172 | int ret; | 260 | int ret; |
@@ -238,7 +326,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
238 | case FPC_EIR: { /* implementation / version register */ | 326 | case FPC_EIR: { /* implementation / version register */ |
239 | unsigned int flags; | 327 | unsigned int flags; |
240 | #ifdef CONFIG_MIPS_MT_SMTC | 328 | #ifdef CONFIG_MIPS_MT_SMTC |
241 | unsigned int irqflags; | 329 | unsigned long irqflags; |
242 | unsigned int mtflags; | 330 | unsigned int mtflags; |
243 | #endif /* CONFIG_MIPS_MT_SMTC */ | 331 | #endif /* CONFIG_MIPS_MT_SMTC */ |
244 | 332 | ||
@@ -440,6 +528,16 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
440 | (unsigned long __user *) data); | 528 | (unsigned long __user *) data); |
441 | break; | 529 | break; |
442 | 530 | ||
531 | case PTRACE_GET_WATCH_REGS: | ||
532 | ret = ptrace_get_watch_regs(child, | ||
533 | (struct pt_watch_regs __user *) addr); | ||
534 | break; | ||
535 | |||
536 | case PTRACE_SET_WATCH_REGS: | ||
537 | ret = ptrace_set_watch_regs(child, | ||
538 | (struct pt_watch_regs __user *) addr); | ||
539 | break; | ||
540 | |||
443 | default: | 541 | default: |
444 | ret = ptrace_request(child, request, addr, data); | 542 | ret = ptrace_request(child, request, addr, data); |
445 | break; | 543 | break; |
diff --git a/arch/mips/kernel/ptrace32.c b/arch/mips/kernel/ptrace32.c index 76818be6ba7c..1ca34104e593 100644 --- a/arch/mips/kernel/ptrace32.c +++ b/arch/mips/kernel/ptrace32.c | |||
@@ -15,6 +15,7 @@ | |||
15 | * binaries. | 15 | * binaries. |
16 | */ | 16 | */ |
17 | #include <linux/compiler.h> | 17 | #include <linux/compiler.h> |
18 | #include <linux/compat.h> | ||
18 | #include <linux/kernel.h> | 19 | #include <linux/kernel.h> |
19 | #include <linux/sched.h> | 20 | #include <linux/sched.h> |
20 | #include <linux/mm.h> | 21 | #include <linux/mm.h> |
@@ -36,47 +37,17 @@ | |||
36 | #include <asm/uaccess.h> | 37 | #include <asm/uaccess.h> |
37 | #include <asm/bootinfo.h> | 38 | #include <asm/bootinfo.h> |
38 | 39 | ||
39 | int ptrace_getregs(struct task_struct *child, __s64 __user *data); | ||
40 | int ptrace_setregs(struct task_struct *child, __s64 __user *data); | ||
41 | |||
42 | int ptrace_getfpregs(struct task_struct *child, __u32 __user *data); | ||
43 | int ptrace_setfpregs(struct task_struct *child, __u32 __user *data); | ||
44 | |||
45 | /* | 40 | /* |
46 | * Tracing a 32-bit process with a 64-bit strace and vice versa will not | 41 | * Tracing a 32-bit process with a 64-bit strace and vice versa will not |
47 | * work. I don't know how to fix this. | 42 | * work. I don't know how to fix this. |
48 | */ | 43 | */ |
49 | asmlinkage int sys32_ptrace(int request, int pid, int addr, int data) | 44 | long compat_arch_ptrace(struct task_struct *child, compat_long_t request, |
45 | compat_ulong_t caddr, compat_ulong_t cdata) | ||
50 | { | 46 | { |
51 | struct task_struct *child; | 47 | int addr = caddr; |
48 | int data = cdata; | ||
52 | int ret; | 49 | int ret; |
53 | 50 | ||
54 | #if 0 | ||
55 | printk("ptrace(r=%d,pid=%d,addr=%08lx,data=%08lx)\n", | ||
56 | (int) request, (int) pid, (unsigned long) addr, | ||
57 | (unsigned long) data); | ||
58 | #endif | ||
59 | lock_kernel(); | ||
60 | if (request == PTRACE_TRACEME) { | ||
61 | ret = ptrace_traceme(); | ||
62 | goto out; | ||
63 | } | ||
64 | |||
65 | child = ptrace_get_task_struct(pid); | ||
66 | if (IS_ERR(child)) { | ||
67 | ret = PTR_ERR(child); | ||
68 | goto out; | ||
69 | } | ||
70 | |||
71 | if (request == PTRACE_ATTACH) { | ||
72 | ret = ptrace_attach(child); | ||
73 | goto out_tsk; | ||
74 | } | ||
75 | |||
76 | ret = ptrace_check_attach(child, request == PTRACE_KILL); | ||
77 | if (ret < 0) | ||
78 | goto out_tsk; | ||
79 | |||
80 | switch (request) { | 51 | switch (request) { |
81 | /* when I and D space are separate, these will need to be fixed. */ | 52 | /* when I and D space are separate, these will need to be fixed. */ |
82 | case PTRACE_PEEKTEXT: /* read word at location addr. */ | 53 | case PTRACE_PEEKTEXT: /* read word at location addr. */ |
@@ -214,7 +185,7 @@ asmlinkage int sys32_ptrace(int request, int pid, int addr, int data) | |||
214 | if (!cpu_has_dsp) { | 185 | if (!cpu_has_dsp) { |
215 | tmp = 0; | 186 | tmp = 0; |
216 | ret = -EIO; | 187 | ret = -EIO; |
217 | goto out_tsk; | 188 | goto out; |
218 | } | 189 | } |
219 | dregs = __get_dsp_regs(child); | 190 | dregs = __get_dsp_regs(child); |
220 | tmp = (unsigned long) (dregs[addr - DSP_BASE]); | 191 | tmp = (unsigned long) (dregs[addr - DSP_BASE]); |
@@ -224,14 +195,14 @@ asmlinkage int sys32_ptrace(int request, int pid, int addr, int data) | |||
224 | if (!cpu_has_dsp) { | 195 | if (!cpu_has_dsp) { |
225 | tmp = 0; | 196 | tmp = 0; |
226 | ret = -EIO; | 197 | ret = -EIO; |
227 | goto out_tsk; | 198 | goto out; |
228 | } | 199 | } |
229 | tmp = child->thread.dsp.dspcontrol; | 200 | tmp = child->thread.dsp.dspcontrol; |
230 | break; | 201 | break; |
231 | default: | 202 | default: |
232 | tmp = 0; | 203 | tmp = 0; |
233 | ret = -EIO; | 204 | ret = -EIO; |
234 | goto out_tsk; | 205 | goto out; |
235 | } | 206 | } |
236 | ret = put_user(tmp, (unsigned __user *) (unsigned long) data); | 207 | ret = put_user(tmp, (unsigned __user *) (unsigned long) data); |
237 | break; | 208 | break; |
@@ -410,14 +381,20 @@ asmlinkage int sys32_ptrace(int request, int pid, int addr, int data) | |||
410 | (unsigned long __user *) (unsigned long) data); | 381 | (unsigned long __user *) (unsigned long) data); |
411 | break; | 382 | break; |
412 | 383 | ||
384 | case PTRACE_GET_WATCH_REGS: | ||
385 | ret = ptrace_get_watch_regs(child, | ||
386 | (struct pt_watch_regs __user *) (unsigned long) addr); | ||
387 | break; | ||
388 | |||
389 | case PTRACE_SET_WATCH_REGS: | ||
390 | ret = ptrace_set_watch_regs(child, | ||
391 | (struct pt_watch_regs __user *) (unsigned long) addr); | ||
392 | break; | ||
393 | |||
413 | default: | 394 | default: |
414 | ret = ptrace_request(child, request, addr, data); | 395 | ret = ptrace_request(child, request, addr, data); |
415 | break; | 396 | break; |
416 | } | 397 | } |
417 | |||
418 | out_tsk: | ||
419 | put_task_struct(child); | ||
420 | out: | 398 | out: |
421 | unlock_kernel(); | ||
422 | return ret; | 399 | return ret; |
423 | } | 400 | } |
diff --git a/arch/mips/kernel/rtlx.c b/arch/mips/kernel/rtlx.c index b55641961232..4ce93aa7b372 100644 --- a/arch/mips/kernel/rtlx.c +++ b/arch/mips/kernel/rtlx.c | |||
@@ -522,8 +522,8 @@ static int __init rtlx_module_init(void) | |||
522 | atomic_set(&channel_wqs[i].in_open, 0); | 522 | atomic_set(&channel_wqs[i].in_open, 0); |
523 | mutex_init(&channel_wqs[i].mutex); | 523 | mutex_init(&channel_wqs[i].mutex); |
524 | 524 | ||
525 | dev = device_create(mt_class, NULL, MKDEV(major, i), | 525 | dev = device_create(mt_class, NULL, MKDEV(major, i), NULL, |
526 | "%s%d", module_name, i); | 526 | "%s%d", module_name, i); |
527 | if (IS_ERR(dev)) { | 527 | if (IS_ERR(dev)) { |
528 | err = PTR_ERR(dev); | 528 | err = PTR_ERR(dev); |
529 | goto out_chrdev; | 529 | goto out_chrdev; |
diff --git a/arch/mips/kernel/scall32-o32.S b/arch/mips/kernel/scall32-o32.S index c058c0b61a2a..5e75a316f6b1 100644 --- a/arch/mips/kernel/scall32-o32.S +++ b/arch/mips/kernel/scall32-o32.S | |||
@@ -354,7 +354,7 @@ einval: li v0, -EINVAL | |||
354 | sys sys_mkdir 2 | 354 | sys sys_mkdir 2 |
355 | sys sys_rmdir 1 /* 4040 */ | 355 | sys sys_rmdir 1 /* 4040 */ |
356 | sys sys_dup 1 | 356 | sys sys_dup 1 |
357 | sys sys_pipe 0 | 357 | sys sysm_pipe 0 |
358 | sys sys_times 1 | 358 | sys sys_times 1 |
359 | sys sys_ni_syscall 0 | 359 | sys sys_ni_syscall 0 |
360 | sys sys_brk 1 /* 4045 */ | 360 | sys sys_brk 1 /* 4045 */ |
@@ -647,6 +647,12 @@ einval: li v0, -EINVAL | |||
647 | sys sys_timerfd_create 2 | 647 | sys sys_timerfd_create 2 |
648 | sys sys_timerfd_gettime 2 | 648 | sys sys_timerfd_gettime 2 |
649 | sys sys_timerfd_settime 4 | 649 | sys sys_timerfd_settime 4 |
650 | sys sys_signalfd4 4 | ||
651 | sys sys_eventfd2 2 /* 4325 */ | ||
652 | sys sys_epoll_create1 1 | ||
653 | sys sys_dup3 3 | ||
654 | sys sys_pipe2 2 | ||
655 | sys sys_inotify_init1 1 | ||
650 | .endm | 656 | .endm |
651 | 657 | ||
652 | /* We pre-compute the number of _instruction_ bytes needed to | 658 | /* We pre-compute the number of _instruction_ bytes needed to |
diff --git a/arch/mips/kernel/scall64-64.S b/arch/mips/kernel/scall64-64.S index dc597b600c68..3d58204c9d44 100644 --- a/arch/mips/kernel/scall64-64.S +++ b/arch/mips/kernel/scall64-64.S | |||
@@ -219,7 +219,7 @@ sys_call_table: | |||
219 | PTR sys_readv | 219 | PTR sys_readv |
220 | PTR sys_writev | 220 | PTR sys_writev |
221 | PTR sys_access /* 5020 */ | 221 | PTR sys_access /* 5020 */ |
222 | PTR sys_pipe | 222 | PTR sysm_pipe |
223 | PTR sys_select | 223 | PTR sys_select |
224 | PTR sys_sched_yield | 224 | PTR sys_sched_yield |
225 | PTR sys_mremap | 225 | PTR sys_mremap |
@@ -481,4 +481,10 @@ sys_call_table: | |||
481 | PTR sys_timerfd_create /* 5280 */ | 481 | PTR sys_timerfd_create /* 5280 */ |
482 | PTR sys_timerfd_gettime | 482 | PTR sys_timerfd_gettime |
483 | PTR sys_timerfd_settime | 483 | PTR sys_timerfd_settime |
484 | PTR sys_signalfd4 | ||
485 | PTR sys_eventfd2 | ||
486 | PTR sys_epoll_create1 /* 5285 */ | ||
487 | PTR sys_dup3 | ||
488 | PTR sys_pipe2 | ||
489 | PTR sys_inotify_init1 | ||
484 | .size sys_call_table,.-sys_call_table | 490 | .size sys_call_table,.-sys_call_table |
diff --git a/arch/mips/kernel/scall64-n32.S b/arch/mips/kernel/scall64-n32.S index 12940eca7893..e266b3aa6560 100644 --- a/arch/mips/kernel/scall64-n32.S +++ b/arch/mips/kernel/scall64-n32.S | |||
@@ -141,7 +141,7 @@ EXPORT(sysn32_call_table) | |||
141 | PTR compat_sys_readv | 141 | PTR compat_sys_readv |
142 | PTR compat_sys_writev | 142 | PTR compat_sys_writev |
143 | PTR sys_access /* 6020 */ | 143 | PTR sys_access /* 6020 */ |
144 | PTR sys_pipe | 144 | PTR sysm_pipe |
145 | PTR compat_sys_select | 145 | PTR compat_sys_select |
146 | PTR sys_sched_yield | 146 | PTR sys_sched_yield |
147 | PTR sys_mremap | 147 | PTR sys_mremap |
@@ -214,12 +214,12 @@ EXPORT(sysn32_call_table) | |||
214 | PTR sys_fchown | 214 | PTR sys_fchown |
215 | PTR sys_lchown | 215 | PTR sys_lchown |
216 | PTR sys_umask | 216 | PTR sys_umask |
217 | PTR sys32_gettimeofday | 217 | PTR compat_sys_gettimeofday |
218 | PTR compat_sys_getrlimit /* 6095 */ | 218 | PTR compat_sys_getrlimit /* 6095 */ |
219 | PTR compat_sys_getrusage | 219 | PTR compat_sys_getrusage |
220 | PTR compat_sys_sysinfo | 220 | PTR compat_sys_sysinfo |
221 | PTR compat_sys_times | 221 | PTR compat_sys_times |
222 | PTR sys32_ptrace | 222 | PTR compat_sys_ptrace |
223 | PTR sys_getuid /* 6100 */ | 223 | PTR sys_getuid /* 6100 */ |
224 | PTR sys_syslog | 224 | PTR sys_syslog |
225 | PTR sys_getgid | 225 | PTR sys_getgid |
@@ -279,7 +279,7 @@ EXPORT(sysn32_call_table) | |||
279 | PTR sys_chroot | 279 | PTR sys_chroot |
280 | PTR sys_sync | 280 | PTR sys_sync |
281 | PTR sys_acct | 281 | PTR sys_acct |
282 | PTR sys32_settimeofday | 282 | PTR compat_sys_settimeofday |
283 | PTR compat_sys_mount /* 6160 */ | 283 | PTR compat_sys_mount /* 6160 */ |
284 | PTR sys_umount | 284 | PTR sys_umount |
285 | PTR sys_swapon | 285 | PTR sys_swapon |
@@ -407,4 +407,10 @@ EXPORT(sysn32_call_table) | |||
407 | PTR sys_timerfd_create | 407 | PTR sys_timerfd_create |
408 | PTR sys_timerfd_gettime /* 5285 */ | 408 | PTR sys_timerfd_gettime /* 5285 */ |
409 | PTR sys_timerfd_settime | 409 | PTR sys_timerfd_settime |
410 | PTR sys_signalfd4 | ||
411 | PTR sys_eventfd2 | ||
412 | PTR sys_epoll_create1 | ||
413 | PTR sys_dup3 /* 5290 */ | ||
414 | PTR sys_pipe2 | ||
415 | PTR sys_inotify_init1 | ||
410 | .size sysn32_call_table,.-sysn32_call_table | 416 | .size sysn32_call_table,.-sysn32_call_table |
diff --git a/arch/mips/kernel/scall64-o32.S b/arch/mips/kernel/scall64-o32.S index 9a275efb4f04..6c7ef8313ebd 100644 --- a/arch/mips/kernel/scall64-o32.S +++ b/arch/mips/kernel/scall64-o32.S | |||
@@ -231,7 +231,7 @@ sys_call_table: | |||
231 | PTR sys_setuid | 231 | PTR sys_setuid |
232 | PTR sys_getuid | 232 | PTR sys_getuid |
233 | PTR compat_sys_stime /* 4025 */ | 233 | PTR compat_sys_stime /* 4025 */ |
234 | PTR sys32_ptrace | 234 | PTR compat_sys_ptrace |
235 | PTR sys_alarm | 235 | PTR sys_alarm |
236 | PTR sys_ni_syscall /* was sys_fstat */ | 236 | PTR sys_ni_syscall /* was sys_fstat */ |
237 | PTR sys_pause | 237 | PTR sys_pause |
@@ -247,7 +247,7 @@ sys_call_table: | |||
247 | PTR sys_mkdir | 247 | PTR sys_mkdir |
248 | PTR sys_rmdir /* 4040 */ | 248 | PTR sys_rmdir /* 4040 */ |
249 | PTR sys_dup | 249 | PTR sys_dup |
250 | PTR sys_pipe | 250 | PTR sysm_pipe |
251 | PTR compat_sys_times | 251 | PTR compat_sys_times |
252 | PTR sys_ni_syscall | 252 | PTR sys_ni_syscall |
253 | PTR sys_brk /* 4045 */ | 253 | PTR sys_brk /* 4045 */ |
@@ -283,8 +283,8 @@ sys_call_table: | |||
283 | PTR compat_sys_setrlimit /* 4075 */ | 283 | PTR compat_sys_setrlimit /* 4075 */ |
284 | PTR compat_sys_getrlimit | 284 | PTR compat_sys_getrlimit |
285 | PTR compat_sys_getrusage | 285 | PTR compat_sys_getrusage |
286 | PTR sys32_gettimeofday | 286 | PTR compat_sys_gettimeofday |
287 | PTR sys32_settimeofday | 287 | PTR compat_sys_settimeofday |
288 | PTR sys_getgroups /* 4080 */ | 288 | PTR sys_getgroups /* 4080 */ |
289 | PTR sys_setgroups | 289 | PTR sys_setgroups |
290 | PTR sys_ni_syscall /* old_select */ | 290 | PTR sys_ni_syscall /* old_select */ |
@@ -529,4 +529,10 @@ sys_call_table: | |||
529 | PTR sys_timerfd_create | 529 | PTR sys_timerfd_create |
530 | PTR sys_timerfd_gettime | 530 | PTR sys_timerfd_gettime |
531 | PTR sys_timerfd_settime | 531 | PTR sys_timerfd_settime |
532 | PTR compat_sys_signalfd4 | ||
533 | PTR sys_eventfd2 /* 4325 */ | ||
534 | PTR sys_epoll_create1 | ||
535 | PTR sys_dup3 | ||
536 | PTR sys_pipe2 | ||
537 | PTR sys_inotify_init1 | ||
532 | .size sys_call_table,.-sys_call_table | 538 | .size sys_call_table,.-sys_call_table |
diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c index 8af84867e74d..16f8edfe5cdc 100644 --- a/arch/mips/kernel/setup.c +++ b/arch/mips/kernel/setup.c | |||
@@ -78,7 +78,7 @@ void __init add_memory_region(phys_t start, phys_t size, long type) | |||
78 | 78 | ||
79 | /* Sanity check */ | 79 | /* Sanity check */ |
80 | if (start + size < start) { | 80 | if (start + size < start) { |
81 | printk("Trying to add an invalid memory region, skipped\n"); | 81 | pr_warning("Trying to add an invalid memory region, skipped\n"); |
82 | return; | 82 | return; |
83 | } | 83 | } |
84 | 84 | ||
@@ -92,7 +92,7 @@ void __init add_memory_region(phys_t start, phys_t size, long type) | |||
92 | } | 92 | } |
93 | 93 | ||
94 | if (x == BOOT_MEM_MAP_MAX) { | 94 | if (x == BOOT_MEM_MAP_MAX) { |
95 | printk("Ooops! Too many entries in the memory map!\n"); | 95 | pr_err("Ooops! Too many entries in the memory map!\n"); |
96 | return; | 96 | return; |
97 | } | 97 | } |
98 | 98 | ||
@@ -108,22 +108,22 @@ static void __init print_memory_map(void) | |||
108 | const int field = 2 * sizeof(unsigned long); | 108 | const int field = 2 * sizeof(unsigned long); |
109 | 109 | ||
110 | for (i = 0; i < boot_mem_map.nr_map; i++) { | 110 | for (i = 0; i < boot_mem_map.nr_map; i++) { |
111 | printk(" memory: %0*Lx @ %0*Lx ", | 111 | printk(KERN_INFO " memory: %0*Lx @ %0*Lx ", |
112 | field, (unsigned long long) boot_mem_map.map[i].size, | 112 | field, (unsigned long long) boot_mem_map.map[i].size, |
113 | field, (unsigned long long) boot_mem_map.map[i].addr); | 113 | field, (unsigned long long) boot_mem_map.map[i].addr); |
114 | 114 | ||
115 | switch (boot_mem_map.map[i].type) { | 115 | switch (boot_mem_map.map[i].type) { |
116 | case BOOT_MEM_RAM: | 116 | case BOOT_MEM_RAM: |
117 | printk("(usable)\n"); | 117 | printk(KERN_CONT "(usable)\n"); |
118 | break; | 118 | break; |
119 | case BOOT_MEM_ROM_DATA: | 119 | case BOOT_MEM_ROM_DATA: |
120 | printk("(ROM data)\n"); | 120 | printk(KERN_CONT "(ROM data)\n"); |
121 | break; | 121 | break; |
122 | case BOOT_MEM_RESERVED: | 122 | case BOOT_MEM_RESERVED: |
123 | printk("(reserved)\n"); | 123 | printk(KERN_CONT "(reserved)\n"); |
124 | break; | 124 | break; |
125 | default: | 125 | default: |
126 | printk("type %lu\n", boot_mem_map.map[i].type); | 126 | printk(KERN_CONT "type %lu\n", boot_mem_map.map[i].type); |
127 | break; | 127 | break; |
128 | } | 128 | } |
129 | } | 129 | } |
@@ -160,36 +160,39 @@ early_param("rd_size", rd_size_early); | |||
160 | static unsigned long __init init_initrd(void) | 160 | static unsigned long __init init_initrd(void) |
161 | { | 161 | { |
162 | unsigned long end; | 162 | unsigned long end; |
163 | u32 *initrd_header; | ||
164 | 163 | ||
165 | /* | 164 | /* |
166 | * Board specific code or command line parser should have | 165 | * Board specific code or command line parser should have |
167 | * already set up initrd_start and initrd_end. In these cases | 166 | * already set up initrd_start and initrd_end. In these cases |
168 | * perfom sanity checks and use them if all looks good. | 167 | * perfom sanity checks and use them if all looks good. |
169 | */ | 168 | */ |
170 | if (initrd_start && initrd_end > initrd_start) | 169 | if (!initrd_start || initrd_end <= initrd_start) { |
171 | goto sanitize; | 170 | #ifdef CONFIG_PROBE_INITRD_HEADER |
171 | u32 *initrd_header; | ||
172 | 172 | ||
173 | /* | 173 | /* |
174 | * See if initrd has been added to the kernel image by | 174 | * See if initrd has been added to the kernel image by |
175 | * arch/mips/boot/addinitrd.c. In that case a header is | 175 | * arch/mips/boot/addinitrd.c. In that case a header is |
176 | * prepended to initrd and is made up by 8 bytes. The fisrt | 176 | * prepended to initrd and is made up by 8 bytes. The first |
177 | * word is a magic number and the second one is the size of | 177 | * word is a magic number and the second one is the size of |
178 | * initrd. Initrd start must be page aligned in any cases. | 178 | * initrd. Initrd start must be page aligned in any cases. |
179 | */ | 179 | */ |
180 | initrd_header = __va(PAGE_ALIGN(__pa_symbol(&_end) + 8)) - 8; | 180 | initrd_header = __va(PAGE_ALIGN(__pa_symbol(&_end) + 8)) - 8; |
181 | if (initrd_header[0] != 0x494E5244) | 181 | if (initrd_header[0] != 0x494E5244) |
182 | goto disable; | ||
183 | initrd_start = (unsigned long)(initrd_header + 2); | ||
184 | initrd_end = initrd_start + initrd_header[1]; | ||
185 | #else | ||
182 | goto disable; | 186 | goto disable; |
183 | initrd_start = (unsigned long)(initrd_header + 2); | 187 | #endif |
184 | initrd_end = initrd_start + initrd_header[1]; | 188 | } |
185 | 189 | ||
186 | sanitize: | ||
187 | if (initrd_start & ~PAGE_MASK) { | 190 | if (initrd_start & ~PAGE_MASK) { |
188 | printk(KERN_ERR "initrd start must be page aligned\n"); | 191 | pr_err("initrd start must be page aligned\n"); |
189 | goto disable; | 192 | goto disable; |
190 | } | 193 | } |
191 | if (initrd_start < PAGE_OFFSET) { | 194 | if (initrd_start < PAGE_OFFSET) { |
192 | printk(KERN_ERR "initrd start < PAGE_OFFSET\n"); | 195 | pr_err("initrd start < PAGE_OFFSET\n"); |
193 | goto disable; | 196 | goto disable; |
194 | } | 197 | } |
195 | 198 | ||
@@ -221,18 +224,18 @@ static void __init finalize_initrd(void) | |||
221 | goto disable; | 224 | goto disable; |
222 | } | 225 | } |
223 | if (__pa(initrd_end) > PFN_PHYS(max_low_pfn)) { | 226 | if (__pa(initrd_end) > PFN_PHYS(max_low_pfn)) { |
224 | printk("Initrd extends beyond end of memory"); | 227 | printk(KERN_ERR "Initrd extends beyond end of memory"); |
225 | goto disable; | 228 | goto disable; |
226 | } | 229 | } |
227 | 230 | ||
228 | reserve_bootmem(__pa(initrd_start), size, BOOTMEM_DEFAULT); | 231 | reserve_bootmem(__pa(initrd_start), size, BOOTMEM_DEFAULT); |
229 | initrd_below_start_ok = 1; | 232 | initrd_below_start_ok = 1; |
230 | 233 | ||
231 | printk(KERN_INFO "Initial ramdisk at: 0x%lx (%lu bytes)\n", | 234 | pr_info("Initial ramdisk at: 0x%lx (%lu bytes)\n", |
232 | initrd_start, size); | 235 | initrd_start, size); |
233 | return; | 236 | return; |
234 | disable: | 237 | disable: |
235 | printk(" - disabling initrd\n"); | 238 | printk(KERN_CONT " - disabling initrd\n"); |
236 | initrd_start = 0; | 239 | initrd_start = 0; |
237 | initrd_end = 0; | 240 | initrd_end = 0; |
238 | } | 241 | } |
@@ -310,14 +313,12 @@ static void __init bootmem_init(void) | |||
310 | if (min_low_pfn >= max_low_pfn) | 313 | if (min_low_pfn >= max_low_pfn) |
311 | panic("Incorrect memory mapping !!!"); | 314 | panic("Incorrect memory mapping !!!"); |
312 | if (min_low_pfn > ARCH_PFN_OFFSET) { | 315 | if (min_low_pfn > ARCH_PFN_OFFSET) { |
313 | printk(KERN_INFO | 316 | pr_info("Wasting %lu bytes for tracking %lu unused pages\n", |
314 | "Wasting %lu bytes for tracking %lu unused pages\n", | 317 | (min_low_pfn - ARCH_PFN_OFFSET) * sizeof(struct page), |
315 | (min_low_pfn - ARCH_PFN_OFFSET) * sizeof(struct page), | 318 | min_low_pfn - ARCH_PFN_OFFSET); |
316 | min_low_pfn - ARCH_PFN_OFFSET); | ||
317 | } else if (min_low_pfn < ARCH_PFN_OFFSET) { | 319 | } else if (min_low_pfn < ARCH_PFN_OFFSET) { |
318 | printk(KERN_INFO | 320 | pr_info("%lu free pages won't be used\n", |
319 | "%lu free pages won't be used\n", | 321 | ARCH_PFN_OFFSET - min_low_pfn); |
320 | ARCH_PFN_OFFSET - min_low_pfn); | ||
321 | } | 322 | } |
322 | min_low_pfn = ARCH_PFN_OFFSET; | 323 | min_low_pfn = ARCH_PFN_OFFSET; |
323 | 324 | ||
@@ -471,7 +472,7 @@ static void __init arch_mem_init(char **cmdline_p) | |||
471 | /* call board setup routine */ | 472 | /* call board setup routine */ |
472 | plat_mem_setup(); | 473 | plat_mem_setup(); |
473 | 474 | ||
474 | printk("Determined physical RAM map:\n"); | 475 | pr_info("Determined physical RAM map:\n"); |
475 | print_memory_map(); | 476 | print_memory_map(); |
476 | 477 | ||
477 | strlcpy(command_line, arcs_cmdline, sizeof(command_line)); | 478 | strlcpy(command_line, arcs_cmdline, sizeof(command_line)); |
@@ -482,7 +483,7 @@ static void __init arch_mem_init(char **cmdline_p) | |||
482 | parse_early_param(); | 483 | parse_early_param(); |
483 | 484 | ||
484 | if (usermem) { | 485 | if (usermem) { |
485 | printk("User-defined physical RAM map:\n"); | 486 | pr_info("User-defined physical RAM map:\n"); |
486 | print_memory_map(); | 487 | print_memory_map(); |
487 | } | 488 | } |
488 | 489 | ||
diff --git a/arch/mips/kernel/signal32.c b/arch/mips/kernel/signal32.c index 572c610db1b1..652709b353ad 100644 --- a/arch/mips/kernel/signal32.c +++ b/arch/mips/kernel/signal32.c | |||
@@ -482,6 +482,18 @@ int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from) | |||
482 | return err; | 482 | return err; |
483 | } | 483 | } |
484 | 484 | ||
485 | int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from) | ||
486 | { | ||
487 | memset(to, 0, sizeof *to); | ||
488 | |||
489 | if (copy_from_user(to, from, 3*sizeof(int)) || | ||
490 | copy_from_user(to->_sifields._pad, | ||
491 | from->_sifields._pad, SI_PAD_SIZE32)) | ||
492 | return -EFAULT; | ||
493 | |||
494 | return 0; | ||
495 | } | ||
496 | |||
485 | asmlinkage void sys32_sigreturn(nabi_no_regargs struct pt_regs regs) | 497 | asmlinkage void sys32_sigreturn(nabi_no_regargs struct pt_regs regs) |
486 | { | 498 | { |
487 | struct sigframe32 __user *frame; | 499 | struct sigframe32 __user *frame; |
diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c index 4410f172b8ab..7b59cfb7e602 100644 --- a/arch/mips/kernel/smp.c +++ b/arch/mips/kernel/smp.c | |||
@@ -121,6 +121,8 @@ asmlinkage __cpuinit void start_secondary(void) | |||
121 | cpu = smp_processor_id(); | 121 | cpu = smp_processor_id(); |
122 | cpu_data[cpu].udelay_val = loops_per_jiffy; | 122 | cpu_data[cpu].udelay_val = loops_per_jiffy; |
123 | 123 | ||
124 | notify_cpu_starting(cpu); | ||
125 | |||
124 | mp_ops->smp_finish(); | 126 | mp_ops->smp_finish(); |
125 | set_cpu_sibling_map(cpu); | 127 | set_cpu_sibling_map(cpu); |
126 | 128 | ||
diff --git a/arch/mips/kernel/smtc.c b/arch/mips/kernel/smtc.c index a516286532ab..897fb2b4751c 100644 --- a/arch/mips/kernel/smtc.c +++ b/arch/mips/kernel/smtc.c | |||
@@ -1,4 +1,21 @@ | |||
1 | /* Copyright (C) 2004 Mips Technologies, Inc */ | 1 | /* |
2 | * This program is free software; you can redistribute it and/or | ||
3 | * modify it under the terms of the GNU General Public License | ||
4 | * as published by the Free Software Foundation; either version 2 | ||
5 | * of the License, or (at your option) any later version. | ||
6 | * | ||
7 | * This program is distributed in the hope that it will be useful, | ||
8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
10 | * GNU General Public License for more details. | ||
11 | * | ||
12 | * You should have received a copy of the GNU General Public License | ||
13 | * along with this program; if not, write to the Free Software | ||
14 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
15 | * | ||
16 | * Copyright (C) 2004 Mips Technologies, Inc | ||
17 | * Copyright (C) 2008 Kevin D. Kissell | ||
18 | */ | ||
2 | 19 | ||
3 | #include <linux/clockchips.h> | 20 | #include <linux/clockchips.h> |
4 | #include <linux/kernel.h> | 21 | #include <linux/kernel.h> |
@@ -21,7 +38,6 @@ | |||
21 | #include <asm/time.h> | 38 | #include <asm/time.h> |
22 | #include <asm/addrspace.h> | 39 | #include <asm/addrspace.h> |
23 | #include <asm/smtc.h> | 40 | #include <asm/smtc.h> |
24 | #include <asm/smtc_ipi.h> | ||
25 | #include <asm/smtc_proc.h> | 41 | #include <asm/smtc_proc.h> |
26 | 42 | ||
27 | /* | 43 | /* |
@@ -58,11 +74,6 @@ unsigned long irq_hwmask[NR_IRQS]; | |||
58 | 74 | ||
59 | asiduse smtc_live_asid[MAX_SMTC_TLBS][MAX_SMTC_ASIDS]; | 75 | asiduse smtc_live_asid[MAX_SMTC_TLBS][MAX_SMTC_ASIDS]; |
60 | 76 | ||
61 | /* | ||
62 | * Clock interrupt "latch" buffers, per "CPU" | ||
63 | */ | ||
64 | |||
65 | static atomic_t ipi_timer_latch[NR_CPUS]; | ||
66 | 77 | ||
67 | /* | 78 | /* |
68 | * Number of InterProcessor Interrupt (IPI) message buffers to allocate | 79 | * Number of InterProcessor Interrupt (IPI) message buffers to allocate |
@@ -70,7 +81,7 @@ static atomic_t ipi_timer_latch[NR_CPUS]; | |||
70 | 81 | ||
71 | #define IPIBUF_PER_CPU 4 | 82 | #define IPIBUF_PER_CPU 4 |
72 | 83 | ||
73 | static struct smtc_ipi_q IPIQ[NR_CPUS]; | 84 | struct smtc_ipi_q IPIQ[NR_CPUS]; |
74 | static struct smtc_ipi_q freeIPIq; | 85 | static struct smtc_ipi_q freeIPIq; |
75 | 86 | ||
76 | 87 | ||
@@ -282,7 +293,7 @@ static void smtc_configure_tlb(void) | |||
282 | * phys_cpu_present_map and the logical/physical mappings. | 293 | * phys_cpu_present_map and the logical/physical mappings. |
283 | */ | 294 | */ |
284 | 295 | ||
285 | int __init mipsmt_build_cpu_map(int start_cpu_slot) | 296 | int __init smtc_build_cpu_map(int start_cpu_slot) |
286 | { | 297 | { |
287 | int i, ntcs; | 298 | int i, ntcs; |
288 | 299 | ||
@@ -325,7 +336,12 @@ static void smtc_tc_setup(int vpe, int tc, int cpu) | |||
325 | write_tc_c0_tcstatus((read_tc_c0_tcstatus() | 336 | write_tc_c0_tcstatus((read_tc_c0_tcstatus() |
326 | & ~(TCSTATUS_TKSU | TCSTATUS_DA | TCSTATUS_IXMT)) | 337 | & ~(TCSTATUS_TKSU | TCSTATUS_DA | TCSTATUS_IXMT)) |
327 | | TCSTATUS_A); | 338 | | TCSTATUS_A); |
328 | write_tc_c0_tccontext(0); | 339 | /* |
340 | * TCContext gets an offset from the base of the IPIQ array | ||
341 | * to be used in low-level code to detect the presence of | ||
342 | * an active IPI queue | ||
343 | */ | ||
344 | write_tc_c0_tccontext((sizeof(struct smtc_ipi_q) * cpu) << 16); | ||
329 | /* Bind tc to vpe */ | 345 | /* Bind tc to vpe */ |
330 | write_tc_c0_tcbind(vpe); | 346 | write_tc_c0_tcbind(vpe); |
331 | /* In general, all TCs should have the same cpu_data indications */ | 347 | /* In general, all TCs should have the same cpu_data indications */ |
@@ -336,10 +352,18 @@ static void smtc_tc_setup(int vpe, int tc, int cpu) | |||
336 | cpu_data[cpu].options &= ~MIPS_CPU_FPU; | 352 | cpu_data[cpu].options &= ~MIPS_CPU_FPU; |
337 | cpu_data[cpu].vpe_id = vpe; | 353 | cpu_data[cpu].vpe_id = vpe; |
338 | cpu_data[cpu].tc_id = tc; | 354 | cpu_data[cpu].tc_id = tc; |
355 | /* Multi-core SMTC hasn't been tested, but be prepared */ | ||
356 | cpu_data[cpu].core = (read_vpe_c0_ebase() >> 1) & 0xff; | ||
339 | } | 357 | } |
340 | 358 | ||
359 | /* | ||
360 | * Tweak to get Count registes in as close a sync as possible. | ||
361 | * Value seems good for 34K-class cores. | ||
362 | */ | ||
363 | |||
364 | #define CP0_SKEW 8 | ||
341 | 365 | ||
342 | void mipsmt_prepare_cpus(void) | 366 | void smtc_prepare_cpus(int cpus) |
343 | { | 367 | { |
344 | int i, vpe, tc, ntc, nvpe, tcpervpe[NR_CPUS], slop, cpu; | 368 | int i, vpe, tc, ntc, nvpe, tcpervpe[NR_CPUS], slop, cpu; |
345 | unsigned long flags; | 369 | unsigned long flags; |
@@ -363,13 +387,13 @@ void mipsmt_prepare_cpus(void) | |||
363 | IPIQ[i].head = IPIQ[i].tail = NULL; | 387 | IPIQ[i].head = IPIQ[i].tail = NULL; |
364 | spin_lock_init(&IPIQ[i].lock); | 388 | spin_lock_init(&IPIQ[i].lock); |
365 | IPIQ[i].depth = 0; | 389 | IPIQ[i].depth = 0; |
366 | atomic_set(&ipi_timer_latch[i], 0); | ||
367 | } | 390 | } |
368 | 391 | ||
369 | /* cpu_data index starts at zero */ | 392 | /* cpu_data index starts at zero */ |
370 | cpu = 0; | 393 | cpu = 0; |
371 | cpu_data[cpu].vpe_id = 0; | 394 | cpu_data[cpu].vpe_id = 0; |
372 | cpu_data[cpu].tc_id = 0; | 395 | cpu_data[cpu].tc_id = 0; |
396 | cpu_data[cpu].core = (read_c0_ebase() >> 1) & 0xff; | ||
373 | cpu++; | 397 | cpu++; |
374 | 398 | ||
375 | /* Report on boot-time options */ | 399 | /* Report on boot-time options */ |
@@ -484,7 +508,8 @@ void mipsmt_prepare_cpus(void) | |||
484 | write_vpe_c0_compare(0); | 508 | write_vpe_c0_compare(0); |
485 | /* Propagate Config7 */ | 509 | /* Propagate Config7 */ |
486 | write_vpe_c0_config7(read_c0_config7()); | 510 | write_vpe_c0_config7(read_c0_config7()); |
487 | write_vpe_c0_count(read_c0_count()); | 511 | write_vpe_c0_count(read_c0_count() + CP0_SKEW); |
512 | ehb(); | ||
488 | } | 513 | } |
489 | /* enable multi-threading within VPE */ | 514 | /* enable multi-threading within VPE */ |
490 | write_vpe_c0_vpecontrol(read_vpe_c0_vpecontrol() | VPECONTROL_TE); | 515 | write_vpe_c0_vpecontrol(read_vpe_c0_vpecontrol() | VPECONTROL_TE); |
@@ -556,7 +581,7 @@ void mipsmt_prepare_cpus(void) | |||
556 | void __cpuinit smtc_boot_secondary(int cpu, struct task_struct *idle) | 581 | void __cpuinit smtc_boot_secondary(int cpu, struct task_struct *idle) |
557 | { | 582 | { |
558 | extern u32 kernelsp[NR_CPUS]; | 583 | extern u32 kernelsp[NR_CPUS]; |
559 | long flags; | 584 | unsigned long flags; |
560 | int mtflags; | 585 | int mtflags; |
561 | 586 | ||
562 | LOCK_MT_PRA(); | 587 | LOCK_MT_PRA(); |
@@ -585,24 +610,22 @@ void __cpuinit smtc_boot_secondary(int cpu, struct task_struct *idle) | |||
585 | 610 | ||
586 | void smtc_init_secondary(void) | 611 | void smtc_init_secondary(void) |
587 | { | 612 | { |
588 | /* | ||
589 | * Start timer on secondary VPEs if necessary. | ||
590 | * plat_timer_setup has already have been invoked by init/main | ||
591 | * on "boot" TC. Like per_cpu_trap_init() hack, this assumes that | ||
592 | * SMTC init code assigns TCs consdecutively and in ascending order | ||
593 | * to across available VPEs. | ||
594 | */ | ||
595 | if (((read_c0_tcbind() & TCBIND_CURTC) != 0) && | ||
596 | ((read_c0_tcbind() & TCBIND_CURVPE) | ||
597 | != cpu_data[smp_processor_id() - 1].vpe_id)){ | ||
598 | write_c0_compare(read_c0_count() + mips_hpt_frequency/HZ); | ||
599 | } | ||
600 | |||
601 | local_irq_enable(); | 613 | local_irq_enable(); |
602 | } | 614 | } |
603 | 615 | ||
604 | void smtc_smp_finish(void) | 616 | void smtc_smp_finish(void) |
605 | { | 617 | { |
618 | int cpu = smp_processor_id(); | ||
619 | |||
620 | /* | ||
621 | * Lowest-numbered CPU per VPE starts a clock tick. | ||
622 | * Like per_cpu_trap_init() hack, this assumes that | ||
623 | * SMTC init code assigns TCs consdecutively and | ||
624 | * in ascending order across available VPEs. | ||
625 | */ | ||
626 | if (cpu > 0 && (cpu_data[cpu].vpe_id != cpu_data[cpu - 1].vpe_id)) | ||
627 | write_c0_compare(read_c0_count() + mips_hpt_frequency/HZ); | ||
628 | |||
606 | printk("TC %d going on-line as CPU %d\n", | 629 | printk("TC %d going on-line as CPU %d\n", |
607 | cpu_data[smp_processor_id()].tc_id, smp_processor_id()); | 630 | cpu_data[smp_processor_id()].tc_id, smp_processor_id()); |
608 | } | 631 | } |
@@ -753,8 +776,10 @@ void smtc_send_ipi(int cpu, int type, unsigned int action) | |||
753 | { | 776 | { |
754 | int tcstatus; | 777 | int tcstatus; |
755 | struct smtc_ipi *pipi; | 778 | struct smtc_ipi *pipi; |
756 | long flags; | 779 | unsigned long flags; |
757 | int mtflags; | 780 | int mtflags; |
781 | unsigned long tcrestart; | ||
782 | extern void r4k_wait_irqoff(void), __pastwait(void); | ||
758 | 783 | ||
759 | if (cpu == smp_processor_id()) { | 784 | if (cpu == smp_processor_id()) { |
760 | printk("Cannot Send IPI to self!\n"); | 785 | printk("Cannot Send IPI to self!\n"); |
@@ -771,8 +796,6 @@ void smtc_send_ipi(int cpu, int type, unsigned int action) | |||
771 | pipi->arg = (void *)action; | 796 | pipi->arg = (void *)action; |
772 | pipi->dest = cpu; | 797 | pipi->dest = cpu; |
773 | if (cpu_data[cpu].vpe_id != cpu_data[smp_processor_id()].vpe_id) { | 798 | if (cpu_data[cpu].vpe_id != cpu_data[smp_processor_id()].vpe_id) { |
774 | if (type == SMTC_CLOCK_TICK) | ||
775 | atomic_inc(&ipi_timer_latch[cpu]); | ||
776 | /* If not on same VPE, enqueue and send cross-VPE interrupt */ | 799 | /* If not on same VPE, enqueue and send cross-VPE interrupt */ |
777 | smtc_ipi_nq(&IPIQ[cpu], pipi); | 800 | smtc_ipi_nq(&IPIQ[cpu], pipi); |
778 | LOCK_CORE_PRA(); | 801 | LOCK_CORE_PRA(); |
@@ -800,22 +823,29 @@ void smtc_send_ipi(int cpu, int type, unsigned int action) | |||
800 | 823 | ||
801 | if ((tcstatus & TCSTATUS_IXMT) != 0) { | 824 | if ((tcstatus & TCSTATUS_IXMT) != 0) { |
802 | /* | 825 | /* |
803 | * Spin-waiting here can deadlock, | 826 | * If we're in the the irq-off version of the wait |
804 | * so we queue the message for the target TC. | 827 | * loop, we need to force exit from the wait and |
828 | * do a direct post of the IPI. | ||
829 | */ | ||
830 | if (cpu_wait == r4k_wait_irqoff) { | ||
831 | tcrestart = read_tc_c0_tcrestart(); | ||
832 | if (tcrestart >= (unsigned long)r4k_wait_irqoff | ||
833 | && tcrestart < (unsigned long)__pastwait) { | ||
834 | write_tc_c0_tcrestart(__pastwait); | ||
835 | tcstatus &= ~TCSTATUS_IXMT; | ||
836 | write_tc_c0_tcstatus(tcstatus); | ||
837 | goto postdirect; | ||
838 | } | ||
839 | } | ||
840 | /* | ||
841 | * Otherwise we queue the message for the target TC | ||
842 | * to pick up when he does a local_irq_restore() | ||
805 | */ | 843 | */ |
806 | write_tc_c0_tchalt(0); | 844 | write_tc_c0_tchalt(0); |
807 | UNLOCK_CORE_PRA(); | 845 | UNLOCK_CORE_PRA(); |
808 | /* Try to reduce redundant timer interrupt messages */ | ||
809 | if (type == SMTC_CLOCK_TICK) { | ||
810 | if (atomic_postincrement(&ipi_timer_latch[cpu])!=0){ | ||
811 | smtc_ipi_nq(&freeIPIq, pipi); | ||
812 | return; | ||
813 | } | ||
814 | } | ||
815 | smtc_ipi_nq(&IPIQ[cpu], pipi); | 846 | smtc_ipi_nq(&IPIQ[cpu], pipi); |
816 | } else { | 847 | } else { |
817 | if (type == SMTC_CLOCK_TICK) | 848 | postdirect: |
818 | atomic_inc(&ipi_timer_latch[cpu]); | ||
819 | post_direct_ipi(cpu, pipi); | 849 | post_direct_ipi(cpu, pipi); |
820 | write_tc_c0_tchalt(0); | 850 | write_tc_c0_tchalt(0); |
821 | UNLOCK_CORE_PRA(); | 851 | UNLOCK_CORE_PRA(); |
@@ -883,7 +913,7 @@ static void ipi_call_interrupt(void) | |||
883 | smp_call_function_interrupt(); | 913 | smp_call_function_interrupt(); |
884 | } | 914 | } |
885 | 915 | ||
886 | DECLARE_PER_CPU(struct clock_event_device, smtc_dummy_clockevent_device); | 916 | DECLARE_PER_CPU(struct clock_event_device, mips_clockevent_device); |
887 | 917 | ||
888 | void ipi_decode(struct smtc_ipi *pipi) | 918 | void ipi_decode(struct smtc_ipi *pipi) |
889 | { | 919 | { |
@@ -891,20 +921,13 @@ void ipi_decode(struct smtc_ipi *pipi) | |||
891 | struct clock_event_device *cd; | 921 | struct clock_event_device *cd; |
892 | void *arg_copy = pipi->arg; | 922 | void *arg_copy = pipi->arg; |
893 | int type_copy = pipi->type; | 923 | int type_copy = pipi->type; |
894 | int ticks; | ||
895 | |||
896 | smtc_ipi_nq(&freeIPIq, pipi); | 924 | smtc_ipi_nq(&freeIPIq, pipi); |
897 | switch (type_copy) { | 925 | switch (type_copy) { |
898 | case SMTC_CLOCK_TICK: | 926 | case SMTC_CLOCK_TICK: |
899 | irq_enter(); | 927 | irq_enter(); |
900 | kstat_this_cpu.irqs[MIPS_CPU_IRQ_BASE + 1]++; | 928 | kstat_this_cpu.irqs[MIPS_CPU_IRQ_BASE + 1]++; |
901 | cd = &per_cpu(smtc_dummy_clockevent_device, cpu); | 929 | cd = &per_cpu(mips_clockevent_device, cpu); |
902 | ticks = atomic_read(&ipi_timer_latch[cpu]); | 930 | cd->event_handler(cd); |
903 | atomic_sub(ticks, &ipi_timer_latch[cpu]); | ||
904 | while (ticks) { | ||
905 | cd->event_handler(cd); | ||
906 | ticks--; | ||
907 | } | ||
908 | irq_exit(); | 931 | irq_exit(); |
909 | break; | 932 | break; |
910 | 933 | ||
@@ -937,24 +960,48 @@ void ipi_decode(struct smtc_ipi *pipi) | |||
937 | } | 960 | } |
938 | } | 961 | } |
939 | 962 | ||
963 | /* | ||
964 | * Similar to smtc_ipi_replay(), but invoked from context restore, | ||
965 | * so it reuses the current exception frame rather than set up a | ||
966 | * new one with self_ipi. | ||
967 | */ | ||
968 | |||
940 | void deferred_smtc_ipi(void) | 969 | void deferred_smtc_ipi(void) |
941 | { | 970 | { |
942 | struct smtc_ipi *pipi; | 971 | int cpu = smp_processor_id(); |
943 | unsigned long flags; | ||
944 | /* DEBUG */ | ||
945 | int q = smp_processor_id(); | ||
946 | 972 | ||
947 | /* | 973 | /* |
948 | * Test is not atomic, but much faster than a dequeue, | 974 | * Test is not atomic, but much faster than a dequeue, |
949 | * and the vast majority of invocations will have a null queue. | 975 | * and the vast majority of invocations will have a null queue. |
976 | * If irq_disabled when this was called, then any IPIs queued | ||
977 | * after we test last will be taken on the next irq_enable/restore. | ||
978 | * If interrupts were enabled, then any IPIs added after the | ||
979 | * last test will be taken directly. | ||
950 | */ | 980 | */ |
951 | if (IPIQ[q].head != NULL) { | 981 | |
952 | while((pipi = smtc_ipi_dq(&IPIQ[q])) != NULL) { | 982 | while (IPIQ[cpu].head != NULL) { |
953 | /* ipi_decode() should be called with interrupts off */ | 983 | struct smtc_ipi_q *q = &IPIQ[cpu]; |
954 | local_irq_save(flags); | 984 | struct smtc_ipi *pipi; |
985 | unsigned long flags; | ||
986 | |||
987 | /* | ||
988 | * It may be possible we'll come in with interrupts | ||
989 | * already enabled. | ||
990 | */ | ||
991 | local_irq_save(flags); | ||
992 | |||
993 | spin_lock(&q->lock); | ||
994 | pipi = __smtc_ipi_dq(q); | ||
995 | spin_unlock(&q->lock); | ||
996 | if (pipi != NULL) | ||
955 | ipi_decode(pipi); | 997 | ipi_decode(pipi); |
956 | local_irq_restore(flags); | 998 | /* |
957 | } | 999 | * The use of the __raw_local restore isn't |
1000 | * as obviously necessary here as in smtc_ipi_replay(), | ||
1001 | * but it's more efficient, given that we're already | ||
1002 | * running down the IPI queue. | ||
1003 | */ | ||
1004 | __raw_local_irq_restore(flags); | ||
958 | } | 1005 | } |
959 | } | 1006 | } |
960 | 1007 | ||
@@ -975,7 +1022,7 @@ static irqreturn_t ipi_interrupt(int irq, void *dev_idm) | |||
975 | struct smtc_ipi *pipi; | 1022 | struct smtc_ipi *pipi; |
976 | unsigned long tcstatus; | 1023 | unsigned long tcstatus; |
977 | int sent; | 1024 | int sent; |
978 | long flags; | 1025 | unsigned long flags; |
979 | unsigned int mtflags; | 1026 | unsigned int mtflags; |
980 | unsigned int vpflags; | 1027 | unsigned int vpflags; |
981 | 1028 | ||
@@ -1066,55 +1113,53 @@ static void setup_cross_vpe_interrupts(unsigned int nvpe) | |||
1066 | 1113 | ||
1067 | /* | 1114 | /* |
1068 | * SMTC-specific hacks invoked from elsewhere in the kernel. | 1115 | * SMTC-specific hacks invoked from elsewhere in the kernel. |
1069 | * | ||
1070 | * smtc_ipi_replay is called from raw_local_irq_restore which is only ever | ||
1071 | * called with interrupts disabled. We do rely on interrupts being disabled | ||
1072 | * here because using spin_lock_irqsave()/spin_unlock_irqrestore() would | ||
1073 | * result in a recursive call to raw_local_irq_restore(). | ||
1074 | */ | 1116 | */ |
1075 | 1117 | ||
1076 | static void __smtc_ipi_replay(void) | 1118 | /* |
1119 | * smtc_ipi_replay is called from raw_local_irq_restore | ||
1120 | */ | ||
1121 | |||
1122 | void smtc_ipi_replay(void) | ||
1077 | { | 1123 | { |
1078 | unsigned int cpu = smp_processor_id(); | 1124 | unsigned int cpu = smp_processor_id(); |
1079 | 1125 | ||
1080 | /* | 1126 | /* |
1081 | * To the extent that we've ever turned interrupts off, | 1127 | * To the extent that we've ever turned interrupts off, |
1082 | * we may have accumulated deferred IPIs. This is subtle. | 1128 | * we may have accumulated deferred IPIs. This is subtle. |
1083 | * If we use the smtc_ipi_qdepth() macro, we'll get an | ||
1084 | * exact number - but we'll also disable interrupts | ||
1085 | * and create a window of failure where a new IPI gets | ||
1086 | * queued after we test the depth but before we re-enable | ||
1087 | * interrupts. So long as IXMT never gets set, however, | ||
1088 | * we should be OK: If we pick up something and dispatch | 1129 | * we should be OK: If we pick up something and dispatch |
1089 | * it here, that's great. If we see nothing, but concurrent | 1130 | * it here, that's great. If we see nothing, but concurrent |
1090 | * with this operation, another TC sends us an IPI, IXMT | 1131 | * with this operation, another TC sends us an IPI, IXMT |
1091 | * is clear, and we'll handle it as a real pseudo-interrupt | 1132 | * is clear, and we'll handle it as a real pseudo-interrupt |
1092 | * and not a pseudo-pseudo interrupt. | 1133 | * and not a pseudo-pseudo interrupt. The important thing |
1134 | * is to do the last check for queued message *after* the | ||
1135 | * re-enabling of interrupts. | ||
1093 | */ | 1136 | */ |
1094 | if (IPIQ[cpu].depth > 0) { | 1137 | while (IPIQ[cpu].head != NULL) { |
1095 | while (1) { | 1138 | struct smtc_ipi_q *q = &IPIQ[cpu]; |
1096 | struct smtc_ipi_q *q = &IPIQ[cpu]; | 1139 | struct smtc_ipi *pipi; |
1097 | struct smtc_ipi *pipi; | 1140 | unsigned long flags; |
1098 | extern void self_ipi(struct smtc_ipi *); | 1141 | |
1099 | 1142 | /* | |
1100 | spin_lock(&q->lock); | 1143 | * It's just possible we'll come in with interrupts |
1101 | pipi = __smtc_ipi_dq(q); | 1144 | * already enabled. |
1102 | spin_unlock(&q->lock); | 1145 | */ |
1103 | if (!pipi) | 1146 | local_irq_save(flags); |
1104 | break; | 1147 | |
1148 | spin_lock(&q->lock); | ||
1149 | pipi = __smtc_ipi_dq(q); | ||
1150 | spin_unlock(&q->lock); | ||
1151 | /* | ||
1152 | ** But use a raw restore here to avoid recursion. | ||
1153 | */ | ||
1154 | __raw_local_irq_restore(flags); | ||
1105 | 1155 | ||
1156 | if (pipi) { | ||
1106 | self_ipi(pipi); | 1157 | self_ipi(pipi); |
1107 | smtc_cpu_stats[cpu].selfipis++; | 1158 | smtc_cpu_stats[cpu].selfipis++; |
1108 | } | 1159 | } |
1109 | } | 1160 | } |
1110 | } | 1161 | } |
1111 | 1162 | ||
1112 | void smtc_ipi_replay(void) | ||
1113 | { | ||
1114 | raw_local_irq_disable(); | ||
1115 | __smtc_ipi_replay(); | ||
1116 | } | ||
1117 | |||
1118 | EXPORT_SYMBOL(smtc_ipi_replay); | 1163 | EXPORT_SYMBOL(smtc_ipi_replay); |
1119 | 1164 | ||
1120 | void smtc_idle_loop_hook(void) | 1165 | void smtc_idle_loop_hook(void) |
@@ -1193,40 +1238,13 @@ void smtc_idle_loop_hook(void) | |||
1193 | } | 1238 | } |
1194 | } | 1239 | } |
1195 | 1240 | ||
1196 | /* | ||
1197 | * Now that we limit outstanding timer IPIs, check for hung TC | ||
1198 | */ | ||
1199 | for (tc = 0; tc < NR_CPUS; tc++) { | ||
1200 | /* Don't check ourself - we'll dequeue IPIs just below */ | ||
1201 | if ((tc != smp_processor_id()) && | ||
1202 | atomic_read(&ipi_timer_latch[tc]) > timerq_limit) { | ||
1203 | if (clock_hang_reported[tc] == 0) { | ||
1204 | pdb_msg += sprintf(pdb_msg, | ||
1205 | "TC %d looks hung with timer latch at %d\n", | ||
1206 | tc, atomic_read(&ipi_timer_latch[tc])); | ||
1207 | clock_hang_reported[tc]++; | ||
1208 | } | ||
1209 | } | ||
1210 | } | ||
1211 | emt(mtflags); | 1241 | emt(mtflags); |
1212 | local_irq_restore(flags); | 1242 | local_irq_restore(flags); |
1213 | if (pdb_msg != &id_ho_db_msg[0]) | 1243 | if (pdb_msg != &id_ho_db_msg[0]) |
1214 | printk("CPU%d: %s", smp_processor_id(), id_ho_db_msg); | 1244 | printk("CPU%d: %s", smp_processor_id(), id_ho_db_msg); |
1215 | #endif /* CONFIG_SMTC_IDLE_HOOK_DEBUG */ | 1245 | #endif /* CONFIG_SMTC_IDLE_HOOK_DEBUG */ |
1216 | 1246 | ||
1217 | /* | 1247 | smtc_ipi_replay(); |
1218 | * Replay any accumulated deferred IPIs. If "Instant Replay" | ||
1219 | * is in use, there should never be any. | ||
1220 | */ | ||
1221 | #ifndef CONFIG_MIPS_MT_SMTC_INSTANT_REPLAY | ||
1222 | { | ||
1223 | unsigned long flags; | ||
1224 | |||
1225 | local_irq_save(flags); | ||
1226 | __smtc_ipi_replay(); | ||
1227 | local_irq_restore(flags); | ||
1228 | } | ||
1229 | #endif /* CONFIG_MIPS_MT_SMTC_INSTANT_REPLAY */ | ||
1230 | } | 1248 | } |
1231 | 1249 | ||
1232 | void smtc_soft_dump(void) | 1250 | void smtc_soft_dump(void) |
@@ -1242,10 +1260,6 @@ void smtc_soft_dump(void) | |||
1242 | printk("%d: %ld\n", i, smtc_cpu_stats[i].selfipis); | 1260 | printk("%d: %ld\n", i, smtc_cpu_stats[i].selfipis); |
1243 | } | 1261 | } |
1244 | smtc_ipi_qdump(); | 1262 | smtc_ipi_qdump(); |
1245 | printk("Timer IPI Backlogs:\n"); | ||
1246 | for (i=0; i < NR_CPUS; i++) { | ||
1247 | printk("%d: %d\n", i, atomic_read(&ipi_timer_latch[i])); | ||
1248 | } | ||
1249 | printk("%d Recoveries of \"stolen\" FPU\n", | 1263 | printk("%d Recoveries of \"stolen\" FPU\n", |
1250 | atomic_read(&smtc_fpu_recoveries)); | 1264 | atomic_read(&smtc_fpu_recoveries)); |
1251 | } | 1265 | } |
diff --git a/arch/mips/kernel/stacktrace.c b/arch/mips/kernel/stacktrace.c index 5eb4681a73d2..0632e2a849c0 100644 --- a/arch/mips/kernel/stacktrace.c +++ b/arch/mips/kernel/stacktrace.c | |||
@@ -7,6 +7,7 @@ | |||
7 | */ | 7 | */ |
8 | #include <linux/sched.h> | 8 | #include <linux/sched.h> |
9 | #include <linux/stacktrace.h> | 9 | #include <linux/stacktrace.h> |
10 | #include <linux/module.h> | ||
10 | #include <asm/stacktrace.h> | 11 | #include <asm/stacktrace.h> |
11 | 12 | ||
12 | /* | 13 | /* |
diff --git a/arch/mips/kernel/syscall.c b/arch/mips/kernel/syscall.c index af1bdc897488..37970d9b2186 100644 --- a/arch/mips/kernel/syscall.c +++ b/arch/mips/kernel/syscall.c | |||
@@ -7,7 +7,6 @@ | |||
7 | * Copyright (C) 1999, 2000 Silicon Graphics, Inc. | 7 | * Copyright (C) 1999, 2000 Silicon Graphics, Inc. |
8 | * Copyright (C) 2001 MIPS Technologies, Inc. | 8 | * Copyright (C) 2001 MIPS Technologies, Inc. |
9 | */ | 9 | */ |
10 | #include <linux/a.out.h> | ||
11 | #include <linux/capability.h> | 10 | #include <linux/capability.h> |
12 | #include <linux/errno.h> | 11 | #include <linux/errno.h> |
13 | #include <linux/linkage.h> | 12 | #include <linux/linkage.h> |
@@ -40,12 +39,19 @@ | |||
40 | #include <asm/sysmips.h> | 39 | #include <asm/sysmips.h> |
41 | #include <asm/uaccess.h> | 40 | #include <asm/uaccess.h> |
42 | 41 | ||
43 | asmlinkage int sys_pipe(nabi_no_regargs volatile struct pt_regs regs) | 42 | /* |
43 | * For historic reasons the pipe(2) syscall on MIPS has an unusual calling | ||
44 | * convention. It returns results in registers $v0 / $v1 which means there | ||
45 | * is no need for it to do verify the validity of a userspace pointer | ||
46 | * argument. Historically that used to be expensive in Linux. These days | ||
47 | * the performance advantage is negligible. | ||
48 | */ | ||
49 | asmlinkage int sysm_pipe(nabi_no_regargs volatile struct pt_regs regs) | ||
44 | { | 50 | { |
45 | int fd[2]; | 51 | int fd[2]; |
46 | int error, res; | 52 | int error, res; |
47 | 53 | ||
48 | error = do_pipe(fd); | 54 | error = do_pipe_flags(fd, 0); |
49 | if (error) { | 55 | if (error) { |
50 | res = error; | 56 | res = error; |
51 | goto out; | 57 | goto out; |
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index b8ea4e9d0d87..80b9e070c207 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c | |||
@@ -23,6 +23,8 @@ | |||
23 | #include <linux/bootmem.h> | 23 | #include <linux/bootmem.h> |
24 | #include <linux/interrupt.h> | 24 | #include <linux/interrupt.h> |
25 | #include <linux/ptrace.h> | 25 | #include <linux/ptrace.h> |
26 | #include <linux/kgdb.h> | ||
27 | #include <linux/kdebug.h> | ||
26 | 28 | ||
27 | #include <asm/bootinfo.h> | 29 | #include <asm/bootinfo.h> |
28 | #include <asm/branch.h> | 30 | #include <asm/branch.h> |
@@ -40,10 +42,14 @@ | |||
40 | #include <asm/tlbdebug.h> | 42 | #include <asm/tlbdebug.h> |
41 | #include <asm/traps.h> | 43 | #include <asm/traps.h> |
42 | #include <asm/uaccess.h> | 44 | #include <asm/uaccess.h> |
45 | #include <asm/watch.h> | ||
43 | #include <asm/mmu_context.h> | 46 | #include <asm/mmu_context.h> |
44 | #include <asm/types.h> | 47 | #include <asm/types.h> |
45 | #include <asm/stacktrace.h> | 48 | #include <asm/stacktrace.h> |
46 | 49 | ||
50 | extern void check_wait(void); | ||
51 | extern asmlinkage void r4k_wait(void); | ||
52 | extern asmlinkage void rollback_handle_int(void); | ||
47 | extern asmlinkage void handle_int(void); | 53 | extern asmlinkage void handle_int(void); |
48 | extern asmlinkage void handle_tlbm(void); | 54 | extern asmlinkage void handle_tlbm(void); |
49 | extern asmlinkage void handle_tlbl(void); | 55 | extern asmlinkage void handle_tlbl(void); |
@@ -371,8 +377,8 @@ void __noreturn die(const char * str, const struct pt_regs * regs) | |||
371 | do_exit(SIGSEGV); | 377 | do_exit(SIGSEGV); |
372 | } | 378 | } |
373 | 379 | ||
374 | extern const struct exception_table_entry __start___dbe_table[]; | 380 | extern struct exception_table_entry __start___dbe_table[]; |
375 | extern const struct exception_table_entry __stop___dbe_table[]; | 381 | extern struct exception_table_entry __stop___dbe_table[]; |
376 | 382 | ||
377 | __asm__( | 383 | __asm__( |
378 | " .section __dbe_table, \"a\"\n" | 384 | " .section __dbe_table, \"a\"\n" |
@@ -425,6 +431,10 @@ asmlinkage void do_be(struct pt_regs *regs) | |||
425 | printk(KERN_ALERT "%s bus error, epc == %0*lx, ra == %0*lx\n", | 431 | printk(KERN_ALERT "%s bus error, epc == %0*lx, ra == %0*lx\n", |
426 | data ? "Data" : "Instruction", | 432 | data ? "Data" : "Instruction", |
427 | field, regs->cp0_epc, field, regs->regs[31]); | 433 | field, regs->cp0_epc, field, regs->regs[31]); |
434 | if (notify_die(DIE_OOPS, "bus error", regs, SIGBUS, 0, 0) | ||
435 | == NOTIFY_STOP) | ||
436 | return; | ||
437 | |||
428 | die_if_kernel("Oops", regs); | 438 | die_if_kernel("Oops", regs); |
429 | force_sig(SIGBUS, current); | 439 | force_sig(SIGBUS, current); |
430 | } | 440 | } |
@@ -623,6 +633,9 @@ asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31) | |||
623 | { | 633 | { |
624 | siginfo_t info; | 634 | siginfo_t info; |
625 | 635 | ||
636 | if (notify_die(DIE_FP, "FP exception", regs, SIGFPE, 0, 0) | ||
637 | == NOTIFY_STOP) | ||
638 | return; | ||
626 | die_if_kernel("FP exception in kernel code", regs); | 639 | die_if_kernel("FP exception in kernel code", regs); |
627 | 640 | ||
628 | if (fcr31 & FPU_CSR_UNI_X) { | 641 | if (fcr31 & FPU_CSR_UNI_X) { |
@@ -682,6 +695,9 @@ static void do_trap_or_bp(struct pt_regs *regs, unsigned int code, | |||
682 | siginfo_t info; | 695 | siginfo_t info; |
683 | char b[40]; | 696 | char b[40]; |
684 | 697 | ||
698 | if (notify_die(DIE_TRAP, str, regs, code, 0, 0) == NOTIFY_STOP) | ||
699 | return; | ||
700 | |||
685 | /* | 701 | /* |
686 | * A short test says that IRIX 5.3 sends SIGTRAP for all trap | 702 | * A short test says that IRIX 5.3 sends SIGTRAP for all trap |
687 | * insns, even for trap and break codes that indicate arithmetic | 703 | * insns, even for trap and break codes that indicate arithmetic |
@@ -762,6 +778,10 @@ asmlinkage void do_ri(struct pt_regs *regs) | |||
762 | unsigned int opcode = 0; | 778 | unsigned int opcode = 0; |
763 | int status = -1; | 779 | int status = -1; |
764 | 780 | ||
781 | if (notify_die(DIE_RI, "RI Fault", regs, SIGSEGV, 0, 0) | ||
782 | == NOTIFY_STOP) | ||
783 | return; | ||
784 | |||
765 | die_if_kernel("Reserved instruction in kernel code", regs); | 785 | die_if_kernel("Reserved instruction in kernel code", regs); |
766 | 786 | ||
767 | if (unlikely(compute_return_epc(regs) < 0)) | 787 | if (unlikely(compute_return_epc(regs) < 0)) |
@@ -806,8 +826,10 @@ static void mt_ase_fp_affinity(void) | |||
806 | if (cpus_intersects(current->cpus_allowed, mt_fpu_cpumask)) { | 826 | if (cpus_intersects(current->cpus_allowed, mt_fpu_cpumask)) { |
807 | cpumask_t tmask; | 827 | cpumask_t tmask; |
808 | 828 | ||
809 | cpus_and(tmask, current->thread.user_cpus_allowed, | 829 | current->thread.user_cpus_allowed |
810 | mt_fpu_cpumask); | 830 | = current->cpus_allowed; |
831 | cpus_and(tmask, current->cpus_allowed, | ||
832 | mt_fpu_cpumask); | ||
811 | set_cpus_allowed(current, tmask); | 833 | set_cpus_allowed(current, tmask); |
812 | set_thread_flag(TIF_FPUBOUND); | 834 | set_thread_flag(TIF_FPUBOUND); |
813 | } | 835 | } |
@@ -891,13 +913,26 @@ asmlinkage void do_mdmx(struct pt_regs *regs) | |||
891 | 913 | ||
892 | asmlinkage void do_watch(struct pt_regs *regs) | 914 | asmlinkage void do_watch(struct pt_regs *regs) |
893 | { | 915 | { |
916 | u32 cause; | ||
917 | |||
894 | /* | 918 | /* |
895 | * We use the watch exception where available to detect stack | 919 | * Clear WP (bit 22) bit of cause register so we don't loop |
896 | * overflows. | 920 | * forever. |
897 | */ | 921 | */ |
898 | dump_tlb_all(); | 922 | cause = read_c0_cause(); |
899 | show_regs(regs); | 923 | cause &= ~(1 << 22); |
900 | panic("Caught WATCH exception - probably caused by stack overflow."); | 924 | write_c0_cause(cause); |
925 | |||
926 | /* | ||
927 | * If the current thread has the watch registers loaded, save | ||
928 | * their values and send SIGTRAP. Otherwise another thread | ||
929 | * left the registers set, clear them and continue. | ||
930 | */ | ||
931 | if (test_tsk_thread_flag(current, TIF_LOAD_WATCH)) { | ||
932 | mips_read_watch_registers(); | ||
933 | force_sig(SIGTRAP, current); | ||
934 | } else | ||
935 | mips_clear_watch_registers(); | ||
901 | } | 936 | } |
902 | 937 | ||
903 | asmlinkage void do_mcheck(struct pt_regs *regs) | 938 | asmlinkage void do_mcheck(struct pt_regs *regs) |
@@ -1184,7 +1219,7 @@ void *set_except_vector(int n, void *addr) | |||
1184 | if (n == 0 && cpu_has_divec) { | 1219 | if (n == 0 && cpu_has_divec) { |
1185 | *(u32 *)(ebase + 0x200) = 0x08000000 | | 1220 | *(u32 *)(ebase + 0x200) = 0x08000000 | |
1186 | (0x03ffffff & (handler >> 2)); | 1221 | (0x03ffffff & (handler >> 2)); |
1187 | flush_icache_range(ebase + 0x200, ebase + 0x204); | 1222 | local_flush_icache_range(ebase + 0x200, ebase + 0x204); |
1188 | } | 1223 | } |
1189 | return (void *)old_handler; | 1224 | return (void *)old_handler; |
1190 | } | 1225 | } |
@@ -1235,6 +1270,9 @@ static void *set_vi_srs_handler(int n, vi_handler_t addr, int srs) | |||
1235 | 1270 | ||
1236 | extern char except_vec_vi, except_vec_vi_lui; | 1271 | extern char except_vec_vi, except_vec_vi_lui; |
1237 | extern char except_vec_vi_ori, except_vec_vi_end; | 1272 | extern char except_vec_vi_ori, except_vec_vi_end; |
1273 | extern char rollback_except_vec_vi; | ||
1274 | char *vec_start = (cpu_wait == r4k_wait) ? | ||
1275 | &rollback_except_vec_vi : &except_vec_vi; | ||
1238 | #ifdef CONFIG_MIPS_MT_SMTC | 1276 | #ifdef CONFIG_MIPS_MT_SMTC |
1239 | /* | 1277 | /* |
1240 | * We need to provide the SMTC vectored interrupt handler | 1278 | * We need to provide the SMTC vectored interrupt handler |
@@ -1242,11 +1280,11 @@ static void *set_vi_srs_handler(int n, vi_handler_t addr, int srs) | |||
1242 | * Status.IM bit to be masked before going there. | 1280 | * Status.IM bit to be masked before going there. |
1243 | */ | 1281 | */ |
1244 | extern char except_vec_vi_mori; | 1282 | extern char except_vec_vi_mori; |
1245 | const int mori_offset = &except_vec_vi_mori - &except_vec_vi; | 1283 | const int mori_offset = &except_vec_vi_mori - vec_start; |
1246 | #endif /* CONFIG_MIPS_MT_SMTC */ | 1284 | #endif /* CONFIG_MIPS_MT_SMTC */ |
1247 | const int handler_len = &except_vec_vi_end - &except_vec_vi; | 1285 | const int handler_len = &except_vec_vi_end - vec_start; |
1248 | const int lui_offset = &except_vec_vi_lui - &except_vec_vi; | 1286 | const int lui_offset = &except_vec_vi_lui - vec_start; |
1249 | const int ori_offset = &except_vec_vi_ori - &except_vec_vi; | 1287 | const int ori_offset = &except_vec_vi_ori - vec_start; |
1250 | 1288 | ||
1251 | if (handler_len > VECTORSPACING) { | 1289 | if (handler_len > VECTORSPACING) { |
1252 | /* | 1290 | /* |
@@ -1256,7 +1294,7 @@ static void *set_vi_srs_handler(int n, vi_handler_t addr, int srs) | |||
1256 | panic("VECTORSPACING too small"); | 1294 | panic("VECTORSPACING too small"); |
1257 | } | 1295 | } |
1258 | 1296 | ||
1259 | memcpy(b, &except_vec_vi, handler_len); | 1297 | memcpy(b, vec_start, handler_len); |
1260 | #ifdef CONFIG_MIPS_MT_SMTC | 1298 | #ifdef CONFIG_MIPS_MT_SMTC |
1261 | BUG_ON(n > 7); /* Vector index %d exceeds SMTC maximum. */ | 1299 | BUG_ON(n > 7); /* Vector index %d exceeds SMTC maximum. */ |
1262 | 1300 | ||
@@ -1267,7 +1305,8 @@ static void *set_vi_srs_handler(int n, vi_handler_t addr, int srs) | |||
1267 | *w = (*w & 0xffff0000) | (((u32)handler >> 16) & 0xffff); | 1305 | *w = (*w & 0xffff0000) | (((u32)handler >> 16) & 0xffff); |
1268 | w = (u32 *)(b + ori_offset); | 1306 | w = (u32 *)(b + ori_offset); |
1269 | *w = (*w & 0xffff0000) | ((u32)handler & 0xffff); | 1307 | *w = (*w & 0xffff0000) | ((u32)handler & 0xffff); |
1270 | flush_icache_range((unsigned long)b, (unsigned long)(b+handler_len)); | 1308 | local_flush_icache_range((unsigned long)b, |
1309 | (unsigned long)(b+handler_len)); | ||
1271 | } | 1310 | } |
1272 | else { | 1311 | else { |
1273 | /* | 1312 | /* |
@@ -1279,7 +1318,8 @@ static void *set_vi_srs_handler(int n, vi_handler_t addr, int srs) | |||
1279 | w = (u32 *)b; | 1318 | w = (u32 *)b; |
1280 | *w++ = 0x08000000 | (((u32)handler >> 2) & 0x03fffff); /* j handler */ | 1319 | *w++ = 0x08000000 | (((u32)handler >> 2) & 0x03fffff); /* j handler */ |
1281 | *w = 0; | 1320 | *w = 0; |
1282 | flush_icache_range((unsigned long)b, (unsigned long)(b+8)); | 1321 | local_flush_icache_range((unsigned long)b, |
1322 | (unsigned long)(b+8)); | ||
1283 | } | 1323 | } |
1284 | 1324 | ||
1285 | return (void *)old_handler; | 1325 | return (void *)old_handler; |
@@ -1499,7 +1539,7 @@ void __cpuinit per_cpu_trap_init(void) | |||
1499 | void __init set_handler(unsigned long offset, void *addr, unsigned long size) | 1539 | void __init set_handler(unsigned long offset, void *addr, unsigned long size) |
1500 | { | 1540 | { |
1501 | memcpy((void *)(ebase + offset), addr, size); | 1541 | memcpy((void *)(ebase + offset), addr, size); |
1502 | flush_icache_range(ebase + offset, ebase + offset + size); | 1542 | local_flush_icache_range(ebase + offset, ebase + offset + size); |
1503 | } | 1543 | } |
1504 | 1544 | ||
1505 | static char panic_null_cerr[] __cpuinitdata = | 1545 | static char panic_null_cerr[] __cpuinitdata = |
@@ -1536,6 +1576,15 @@ void __init trap_init(void) | |||
1536 | extern char except_vec3_generic, except_vec3_r4000; | 1576 | extern char except_vec3_generic, except_vec3_r4000; |
1537 | extern char except_vec4; | 1577 | extern char except_vec4; |
1538 | unsigned long i; | 1578 | unsigned long i; |
1579 | int rollback; | ||
1580 | |||
1581 | check_wait(); | ||
1582 | rollback = (cpu_wait == r4k_wait); | ||
1583 | |||
1584 | #if defined(CONFIG_KGDB) | ||
1585 | if (kgdb_early_setup) | ||
1586 | return; /* Already done */ | ||
1587 | #endif | ||
1539 | 1588 | ||
1540 | if (cpu_has_veic || cpu_has_vint) | 1589 | if (cpu_has_veic || cpu_has_vint) |
1541 | ebase = (unsigned long) alloc_bootmem_low_pages(0x200 + VECTORSPACING*64); | 1590 | ebase = (unsigned long) alloc_bootmem_low_pages(0x200 + VECTORSPACING*64); |
@@ -1595,7 +1644,7 @@ void __init trap_init(void) | |||
1595 | if (board_be_init) | 1644 | if (board_be_init) |
1596 | board_be_init(); | 1645 | board_be_init(); |
1597 | 1646 | ||
1598 | set_except_vector(0, handle_int); | 1647 | set_except_vector(0, rollback ? rollback_handle_int : handle_int); |
1599 | set_except_vector(1, handle_tlbm); | 1648 | set_except_vector(1, handle_tlbm); |
1600 | set_except_vector(2, handle_tlbl); | 1649 | set_except_vector(2, handle_tlbl); |
1601 | set_except_vector(3, handle_tlbs); | 1650 | set_except_vector(3, handle_tlbs); |
@@ -1659,6 +1708,8 @@ void __init trap_init(void) | |||
1659 | signal32_init(); | 1708 | signal32_init(); |
1660 | #endif | 1709 | #endif |
1661 | 1710 | ||
1662 | flush_icache_range(ebase, ebase + 0x400); | 1711 | local_flush_icache_range(ebase, ebase + 0x400); |
1663 | flush_tlb_handlers(); | 1712 | flush_tlb_handlers(); |
1713 | |||
1714 | sort_extable(__start___dbe_table, __stop___dbe_table); | ||
1664 | } | 1715 | } |
diff --git a/arch/mips/kernel/vmlinux.lds.S b/arch/mips/kernel/vmlinux.lds.S index b5470ceb418b..58738c8d754f 100644 --- a/arch/mips/kernel/vmlinux.lds.S +++ b/arch/mips/kernel/vmlinux.lds.S | |||
@@ -36,6 +36,7 @@ SECTIONS | |||
36 | SCHED_TEXT | 36 | SCHED_TEXT |
37 | LOCK_TEXT | 37 | LOCK_TEXT |
38 | KPROBES_TEXT | 38 | KPROBES_TEXT |
39 | *(.text.*) | ||
39 | *(.fixup) | 40 | *(.fixup) |
40 | *(.gnu.warning) | 41 | *(.gnu.warning) |
41 | } :text = 0 | 42 | } :text = 0 |
@@ -103,7 +104,7 @@ SECTIONS | |||
103 | . = ALIGN(_PAGE_SIZE); | 104 | . = ALIGN(_PAGE_SIZE); |
104 | __nosave_end = .; | 105 | __nosave_end = .; |
105 | 106 | ||
106 | . = ALIGN(32); | 107 | . = ALIGN(1 << CONFIG_MIPS_L1_CACHE_SHIFT); |
107 | .data.cacheline_aligned : { | 108 | .data.cacheline_aligned : { |
108 | *(.data.cacheline_aligned) | 109 | *(.data.cacheline_aligned) |
109 | } | 110 | } |
diff --git a/arch/mips/kernel/watch.c b/arch/mips/kernel/watch.c new file mode 100644 index 000000000000..c15406968030 --- /dev/null +++ b/arch/mips/kernel/watch.c | |||
@@ -0,0 +1,188 @@ | |||
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) 2008 David Daney | ||
7 | */ | ||
8 | |||
9 | #include <linux/sched.h> | ||
10 | |||
11 | #include <asm/processor.h> | ||
12 | #include <asm/watch.h> | ||
13 | |||
14 | /* | ||
15 | * Install the watch registers for the current thread. A maximum of | ||
16 | * four registers are installed although the machine may have more. | ||
17 | */ | ||
18 | void mips_install_watch_registers(void) | ||
19 | { | ||
20 | struct mips3264_watch_reg_state *watches = | ||
21 | ¤t->thread.watch.mips3264; | ||
22 | switch (current_cpu_data.watch_reg_use_cnt) { | ||
23 | default: | ||
24 | BUG(); | ||
25 | case 4: | ||
26 | write_c0_watchlo3(watches->watchlo[3]); | ||
27 | /* Write 1 to the I, R, and W bits to clear them, and | ||
28 | 1 to G so all ASIDs are trapped. */ | ||
29 | write_c0_watchhi3(0x40000007 | watches->watchhi[3]); | ||
30 | case 3: | ||
31 | write_c0_watchlo2(watches->watchlo[2]); | ||
32 | write_c0_watchhi2(0x40000007 | watches->watchhi[2]); | ||
33 | case 2: | ||
34 | write_c0_watchlo1(watches->watchlo[1]); | ||
35 | write_c0_watchhi1(0x40000007 | watches->watchhi[1]); | ||
36 | case 1: | ||
37 | write_c0_watchlo0(watches->watchlo[0]); | ||
38 | write_c0_watchhi0(0x40000007 | watches->watchhi[0]); | ||
39 | } | ||
40 | } | ||
41 | |||
42 | /* | ||
43 | * Read back the watchhi registers so the user space debugger has | ||
44 | * access to the I, R, and W bits. A maximum of four registers are | ||
45 | * read although the machine may have more. | ||
46 | */ | ||
47 | void mips_read_watch_registers(void) | ||
48 | { | ||
49 | struct mips3264_watch_reg_state *watches = | ||
50 | ¤t->thread.watch.mips3264; | ||
51 | switch (current_cpu_data.watch_reg_use_cnt) { | ||
52 | default: | ||
53 | BUG(); | ||
54 | case 4: | ||
55 | watches->watchhi[3] = (read_c0_watchhi3() & 0x0fff); | ||
56 | case 3: | ||
57 | watches->watchhi[2] = (read_c0_watchhi2() & 0x0fff); | ||
58 | case 2: | ||
59 | watches->watchhi[1] = (read_c0_watchhi1() & 0x0fff); | ||
60 | case 1: | ||
61 | watches->watchhi[0] = (read_c0_watchhi0() & 0x0fff); | ||
62 | } | ||
63 | if (current_cpu_data.watch_reg_use_cnt == 1 && | ||
64 | (watches->watchhi[0] & 7) == 0) { | ||
65 | /* Pathological case of release 1 architecture that | ||
66 | * doesn't set the condition bits. We assume that | ||
67 | * since we got here, the watch condition was met and | ||
68 | * signal that the conditions requested in watchlo | ||
69 | * were met. */ | ||
70 | watches->watchhi[0] |= (watches->watchlo[0] & 7); | ||
71 | } | ||
72 | } | ||
73 | |||
74 | /* | ||
75 | * Disable all watch registers. Although only four registers are | ||
76 | * installed, all are cleared to eliminate the possibility of endless | ||
77 | * looping in the watch handler. | ||
78 | */ | ||
79 | void mips_clear_watch_registers(void) | ||
80 | { | ||
81 | switch (current_cpu_data.watch_reg_count) { | ||
82 | default: | ||
83 | BUG(); | ||
84 | case 8: | ||
85 | write_c0_watchlo7(0); | ||
86 | case 7: | ||
87 | write_c0_watchlo6(0); | ||
88 | case 6: | ||
89 | write_c0_watchlo5(0); | ||
90 | case 5: | ||
91 | write_c0_watchlo4(0); | ||
92 | case 4: | ||
93 | write_c0_watchlo3(0); | ||
94 | case 3: | ||
95 | write_c0_watchlo2(0); | ||
96 | case 2: | ||
97 | write_c0_watchlo1(0); | ||
98 | case 1: | ||
99 | write_c0_watchlo0(0); | ||
100 | } | ||
101 | } | ||
102 | |||
103 | __cpuinit void mips_probe_watch_registers(struct cpuinfo_mips *c) | ||
104 | { | ||
105 | unsigned int t; | ||
106 | |||
107 | if ((c->options & MIPS_CPU_WATCH) == 0) | ||
108 | return; | ||
109 | /* | ||
110 | * Check which of the I,R and W bits are supported, then | ||
111 | * disable the register. | ||
112 | */ | ||
113 | write_c0_watchlo0(7); | ||
114 | t = read_c0_watchlo0(); | ||
115 | write_c0_watchlo0(0); | ||
116 | c->watch_reg_masks[0] = t & 7; | ||
117 | |||
118 | /* Write the mask bits and read them back to determine which | ||
119 | * can be used. */ | ||
120 | c->watch_reg_count = 1; | ||
121 | c->watch_reg_use_cnt = 1; | ||
122 | t = read_c0_watchhi0(); | ||
123 | write_c0_watchhi0(t | 0xff8); | ||
124 | t = read_c0_watchhi0(); | ||
125 | c->watch_reg_masks[0] |= (t & 0xff8); | ||
126 | if ((t & 0x80000000) == 0) | ||
127 | return; | ||
128 | |||
129 | write_c0_watchlo1(7); | ||
130 | t = read_c0_watchlo1(); | ||
131 | write_c0_watchlo1(0); | ||
132 | c->watch_reg_masks[1] = t & 7; | ||
133 | |||
134 | c->watch_reg_count = 2; | ||
135 | c->watch_reg_use_cnt = 2; | ||
136 | t = read_c0_watchhi1(); | ||
137 | write_c0_watchhi1(t | 0xff8); | ||
138 | t = read_c0_watchhi1(); | ||
139 | c->watch_reg_masks[1] |= (t & 0xff8); | ||
140 | if ((t & 0x80000000) == 0) | ||
141 | return; | ||
142 | |||
143 | write_c0_watchlo2(7); | ||
144 | t = read_c0_watchlo2(); | ||
145 | write_c0_watchlo2(0); | ||
146 | c->watch_reg_masks[2] = t & 7; | ||
147 | |||
148 | c->watch_reg_count = 3; | ||
149 | c->watch_reg_use_cnt = 3; | ||
150 | t = read_c0_watchhi2(); | ||
151 | write_c0_watchhi2(t | 0xff8); | ||
152 | t = read_c0_watchhi2(); | ||
153 | c->watch_reg_masks[2] |= (t & 0xff8); | ||
154 | if ((t & 0x80000000) == 0) | ||
155 | return; | ||
156 | |||
157 | write_c0_watchlo3(7); | ||
158 | t = read_c0_watchlo3(); | ||
159 | write_c0_watchlo3(0); | ||
160 | c->watch_reg_masks[3] = t & 7; | ||
161 | |||
162 | c->watch_reg_count = 4; | ||
163 | c->watch_reg_use_cnt = 4; | ||
164 | t = read_c0_watchhi3(); | ||
165 | write_c0_watchhi3(t | 0xff8); | ||
166 | t = read_c0_watchhi3(); | ||
167 | c->watch_reg_masks[3] |= (t & 0xff8); | ||
168 | if ((t & 0x80000000) == 0) | ||
169 | return; | ||
170 | |||
171 | /* We use at most 4, but probe and report up to 8. */ | ||
172 | c->watch_reg_count = 5; | ||
173 | t = read_c0_watchhi4(); | ||
174 | if ((t & 0x80000000) == 0) | ||
175 | return; | ||
176 | |||
177 | c->watch_reg_count = 6; | ||
178 | t = read_c0_watchhi5(); | ||
179 | if ((t & 0x80000000) == 0) | ||
180 | return; | ||
181 | |||
182 | c->watch_reg_count = 7; | ||
183 | t = read_c0_watchhi6(); | ||
184 | if ((t & 0x80000000) == 0) | ||
185 | return; | ||
186 | |||
187 | c->watch_reg_count = 8; | ||
188 | } | ||