aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc64/kernel/traps.c
diff options
context:
space:
mode:
authorDavid S. Miller <davem@sunset.davemloft.net>2006-02-09 23:20:34 -0500
committerDavid S. Miller <davem@sunset.davemloft.net>2006-03-20 04:12:07 -0500
commited6b0b45437dcf7ef1c48b3be413bebcc84771d8 (patch)
treee52dbcebe1435f9d2957b55c100824cb7b8b1f98 /arch/sparc64/kernel/traps.c
parent618e9ed98aed924a1fc664eb6522db4a5e927043 (diff)
[SPARC64]: SUN4V memory exception trap handlers.
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'arch/sparc64/kernel/traps.c')
-rw-r--r--arch/sparc64/kernel/traps.c108
1 files changed, 101 insertions, 7 deletions
diff --git a/arch/sparc64/kernel/traps.c b/arch/sparc64/kernel/traps.c
index ac171161e794..1e9a4b6b1fec 100644
--- a/arch/sparc64/kernel/traps.c
+++ b/arch/sparc64/kernel/traps.c
@@ -180,6 +180,45 @@ void spitfire_insn_access_exception_tl1(struct pt_regs *regs, unsigned long sfsr
180 spitfire_insn_access_exception(regs, sfsr, sfar); 180 spitfire_insn_access_exception(regs, sfsr, sfar);
181} 181}
182 182
183void sun4v_insn_access_exception(struct pt_regs *regs, unsigned long addr, unsigned long type_ctx)
184{
185 unsigned short type = (type_ctx >> 16);
186 unsigned short ctx = (type_ctx & 0xffff);
187 siginfo_t info;
188
189 if (notify_die(DIE_TRAP, "instruction access exception", regs,
190 0, 0x8, SIGTRAP) == NOTIFY_STOP)
191 return;
192
193 if (regs->tstate & TSTATE_PRIV) {
194 printk("sun4v_insn_access_exception: ADDR[%016lx] "
195 "CTX[%04x] TYPE[%04x], going.\n",
196 addr, ctx, type);
197 die_if_kernel("Iax", regs);
198 }
199
200 if (test_thread_flag(TIF_32BIT)) {
201 regs->tpc &= 0xffffffff;
202 regs->tnpc &= 0xffffffff;
203 }
204 info.si_signo = SIGSEGV;
205 info.si_errno = 0;
206 info.si_code = SEGV_MAPERR;
207 info.si_addr = (void __user *) addr;
208 info.si_trapno = 0;
209 force_sig_info(SIGSEGV, &info, current);
210}
211
212void sun4v_insn_access_exception_tl1(struct pt_regs *regs, unsigned long addr, unsigned long type_ctx)
213{
214 if (notify_die(DIE_TRAP_TL1, "instruction access exception tl1", regs,
215 0, 0x8, SIGTRAP) == NOTIFY_STOP)
216 return;
217
218 dump_tl1_traplog((struct tl1_traplog *)(regs + 1));
219 sun4v_insn_access_exception(regs, addr, type_ctx);
220}
221
183void spitfire_data_access_exception(struct pt_regs *regs, unsigned long sfsr, unsigned long sfar) 222void spitfire_data_access_exception(struct pt_regs *regs, unsigned long sfsr, unsigned long sfar)
184{ 223{
185 siginfo_t info; 224 siginfo_t info;
@@ -228,6 +267,45 @@ void spitfire_data_access_exception_tl1(struct pt_regs *regs, unsigned long sfsr
228 spitfire_data_access_exception(regs, sfsr, sfar); 267 spitfire_data_access_exception(regs, sfsr, sfar);
229} 268}
230 269
270void sun4v_data_access_exception(struct pt_regs *regs, unsigned long addr, unsigned long type_ctx)
271{
272 unsigned short type = (type_ctx >> 16);
273 unsigned short ctx = (type_ctx & 0xffff);
274 siginfo_t info;
275
276 if (notify_die(DIE_TRAP, "data access exception", regs,
277 0, 0x8, SIGTRAP) == NOTIFY_STOP)
278 return;
279
280 if (regs->tstate & TSTATE_PRIV) {
281 printk("sun4v_data_access_exception: ADDR[%016lx] "
282 "CTX[%04x] TYPE[%04x], going.\n",
283 addr, ctx, type);
284 die_if_kernel("Iax", regs);
285 }
286
287 if (test_thread_flag(TIF_32BIT)) {
288 regs->tpc &= 0xffffffff;
289 regs->tnpc &= 0xffffffff;
290 }
291 info.si_signo = SIGSEGV;
292 info.si_errno = 0;
293 info.si_code = SEGV_MAPERR;
294 info.si_addr = (void __user *) addr;
295 info.si_trapno = 0;
296 force_sig_info(SIGSEGV, &info, current);
297}
298
299void sun4v_data_access_exception_tl1(struct pt_regs *regs, unsigned long addr, unsigned long type_ctx)
300{
301 if (notify_die(DIE_TRAP_TL1, "data access exception tl1", regs,
302 0, 0x8, SIGTRAP) == NOTIFY_STOP)
303 return;
304
305 dump_tl1_traplog((struct tl1_traplog *)(regs + 1));
306 sun4v_data_access_exception(regs, addr, type_ctx);
307}
308
231#ifdef CONFIG_PCI 309#ifdef CONFIG_PCI
232/* This is really pathetic... */ 310/* This is really pathetic... */
233extern volatile int pci_poke_in_progress; 311extern volatile int pci_poke_in_progress;
@@ -2150,6 +2228,8 @@ void do_illegal_instruction(struct pt_regs *regs)
2150 force_sig_info(SIGILL, &info, current); 2228 force_sig_info(SIGILL, &info, current);
2151} 2229}
2152 2230
2231extern void kernel_unaligned_trap(struct pt_regs *regs, unsigned int insn);
2232
2153void mem_address_unaligned(struct pt_regs *regs, unsigned long sfar, unsigned long sfsr) 2233void mem_address_unaligned(struct pt_regs *regs, unsigned long sfar, unsigned long sfsr)
2154{ 2234{
2155 siginfo_t info; 2235 siginfo_t info;
@@ -2159,13 +2239,7 @@ void mem_address_unaligned(struct pt_regs *regs, unsigned long sfar, unsigned lo
2159 return; 2239 return;
2160 2240
2161 if (regs->tstate & TSTATE_PRIV) { 2241 if (regs->tstate & TSTATE_PRIV) {
2162 extern void kernel_unaligned_trap(struct pt_regs *regs, 2242 kernel_unaligned_trap(regs, *((unsigned int *)regs->tpc));
2163 unsigned int insn,
2164 unsigned long sfar,
2165 unsigned long sfsr);
2166
2167 kernel_unaligned_trap(regs, *((unsigned int *)regs->tpc),
2168 sfar, sfsr);
2169 return; 2243 return;
2170 } 2244 }
2171 info.si_signo = SIGBUS; 2245 info.si_signo = SIGBUS;
@@ -2176,6 +2250,26 @@ void mem_address_unaligned(struct pt_regs *regs, unsigned long sfar, unsigned lo
2176 force_sig_info(SIGBUS, &info, current); 2250 force_sig_info(SIGBUS, &info, current);
2177} 2251}
2178 2252
2253void sun4v_mna(struct pt_regs *regs, unsigned long addr, unsigned long type_ctx)
2254{
2255 siginfo_t info;
2256
2257 if (notify_die(DIE_TRAP, "memory address unaligned", regs,
2258 0, 0x34, SIGSEGV) == NOTIFY_STOP)
2259 return;
2260
2261 if (regs->tstate & TSTATE_PRIV) {
2262 kernel_unaligned_trap(regs, *((unsigned int *)regs->tpc));
2263 return;
2264 }
2265 info.si_signo = SIGBUS;
2266 info.si_errno = 0;
2267 info.si_code = BUS_ADRALN;
2268 info.si_addr = (void __user *) addr;
2269 info.si_trapno = 0;
2270 force_sig_info(SIGBUS, &info, current);
2271}
2272
2179void do_privop(struct pt_regs *regs) 2273void do_privop(struct pt_regs *regs)
2180{ 2274{
2181 siginfo_t info; 2275 siginfo_t info;