aboutsummaryrefslogtreecommitdiffstats
path: root/arch
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
parent618e9ed98aed924a1fc664eb6522db4a5e927043 (diff)
[SPARC64]: SUN4V memory exception trap handlers.
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'arch')
-rw-r--r--arch/sparc64/kernel/sun4v_tlb_miss.S170
-rw-r--r--arch/sparc64/kernel/traps.c108
-rw-r--r--arch/sparc64/kernel/unaligned.c45
-rw-r--r--arch/sparc64/kernel/winfixup.S26
4 files changed, 325 insertions, 24 deletions
diff --git a/arch/sparc64/kernel/sun4v_tlb_miss.S b/arch/sparc64/kernel/sun4v_tlb_miss.S
index b8678b5557aa..c408b05a5f0a 100644
--- a/arch/sparc64/kernel/sun4v_tlb_miss.S
+++ b/arch/sparc64/kernel/sun4v_tlb_miss.S
@@ -237,6 +237,167 @@ sun4v_tsb_miss_common:
237 ba,pt %xcc, tsb_miss_page_table_walk 237 ba,pt %xcc, tsb_miss_page_table_walk
238 add %g1, %g2, %g1 238 add %g1, %g2, %g1
239 239
240 /* Instruction Access Exception, tl0. */
241sun4v_iacc:
242 mov SCRATCHPAD_CPUID, %g1
243 ldxa [%g1] ASI_SCRATCHPAD, %g3
244 sethi %hi(trap_block), %g2
245 or %g2, %lo(trap_block), %g2
246 sllx %g3, TRAP_BLOCK_SZ_SHIFT, %g3
247 add %g2, %g3, %g2
248 ldx [%g2 + TRAP_PER_CPU_FAULT_INFO + HV_FAULT_I_TYPE_OFFSET], %g3
249 ldx [%g2 + TRAP_PER_CPU_FAULT_INFO + HV_FAULT_I_ADDR_OFFSET], %g4
250 ldx [%g2 + TRAP_PER_CPU_FAULT_INFO + HV_FAULT_I_CTX_OFFSET], %g5
251 sllx %g3, 16, %g3
252 or %g5, %g3, %g5
253 ba,pt %xcc, etrap
254 rd %pc, %g7
255 mov %l4, %o1
256 mov %l5, %o2
257 call sun4v_insn_access_exception
258 add %sp, PTREGS_OFF, %o0
259 ba,a,pt %xcc, rtrap_clr_l6
260
261 /* Instruction Access Exception, tl1. */
262sun4v_iacc_tl1:
263 mov SCRATCHPAD_CPUID, %g1
264 ldxa [%g1] ASI_SCRATCHPAD, %g3
265 sethi %hi(trap_block), %g2
266 or %g2, %lo(trap_block), %g2
267 sllx %g3, TRAP_BLOCK_SZ_SHIFT, %g3
268 add %g2, %g3, %g2
269 ldx [%g2 + TRAP_PER_CPU_FAULT_INFO + HV_FAULT_I_TYPE_OFFSET], %g3
270 ldx [%g2 + TRAP_PER_CPU_FAULT_INFO + HV_FAULT_I_ADDR_OFFSET], %g4
271 ldx [%g2 + TRAP_PER_CPU_FAULT_INFO + HV_FAULT_I_CTX_OFFSET], %g5
272 sllx %g3, 16, %g3
273 or %g5, %g3, %g5
274 ba,pt %xcc, etraptl1
275 rd %pc, %g7
276 mov %l4, %o1
277 mov %l5, %o2
278 call sun4v_insn_access_exception_tl1
279 add %sp, PTREGS_OFF, %o0
280 ba,a,pt %xcc, rtrap_clr_l6
281
282 /* Data Access Exception, tl0. */
283sun4v_dacc:
284 mov SCRATCHPAD_CPUID, %g1
285 ldxa [%g1] ASI_SCRATCHPAD, %g3
286 sethi %hi(trap_block), %g2
287 or %g2, %lo(trap_block), %g2
288 sllx %g3, TRAP_BLOCK_SZ_SHIFT, %g3
289 add %g2, %g3, %g2
290 ldx [%g2 + TRAP_PER_CPU_FAULT_INFO + HV_FAULT_D_TYPE_OFFSET], %g3
291 ldx [%g2 + TRAP_PER_CPU_FAULT_INFO + HV_FAULT_D_ADDR_OFFSET], %g4
292 ldx [%g2 + TRAP_PER_CPU_FAULT_INFO + HV_FAULT_D_CTX_OFFSET], %g5
293 sllx %g3, 16, %g3
294 or %g5, %g3, %g5
295 ba,pt %xcc, etrap
296 rd %pc, %g7
297 mov %l4, %o1
298 mov %l5, %o2
299 call sun4v_data_access_exception
300 add %sp, PTREGS_OFF, %o0
301 ba,a,pt %xcc, rtrap_clr_l6
302
303 /* Data Access Exception, tl1. */
304sun4v_dacc_tl1:
305 mov SCRATCHPAD_CPUID, %g1
306 ldxa [%g1] ASI_SCRATCHPAD, %g3
307 sethi %hi(trap_block), %g2
308 or %g2, %lo(trap_block), %g2
309 sllx %g3, TRAP_BLOCK_SZ_SHIFT, %g3
310 add %g2, %g3, %g2
311 ldx [%g2 + TRAP_PER_CPU_FAULT_INFO + HV_FAULT_D_TYPE_OFFSET], %g3
312 ldx [%g2 + TRAP_PER_CPU_FAULT_INFO + HV_FAULT_D_ADDR_OFFSET], %g4
313 ldx [%g2 + TRAP_PER_CPU_FAULT_INFO + HV_FAULT_D_CTX_OFFSET], %g5
314 sllx %g3, 16, %g3
315 or %g5, %g3, %g5
316 ba,pt %xcc, etraptl1
317 rd %pc, %g7
318 mov %l4, %o1
319 mov %l5, %o2
320 call sun4v_data_access_exception_tl1
321 add %sp, PTREGS_OFF, %o0
322 ba,a,pt %xcc, rtrap_clr_l6
323
324 /* Memory Address Unaligned. */
325sun4v_mna:
326 mov SCRATCHPAD_CPUID, %g1
327 ldxa [%g1] ASI_SCRATCHPAD, %g3
328 sethi %hi(trap_block), %g2
329 or %g2, %lo(trap_block), %g2
330 sllx %g3, TRAP_BLOCK_SZ_SHIFT, %g3
331 add %g2, %g3, %g2
332 mov HV_FAULT_TYPE_UNALIGNED, %g3
333 ldx [%g2 + TRAP_PER_CPU_FAULT_INFO + HV_FAULT_D_ADDR_OFFSET], %g4
334 ldx [%g2 + TRAP_PER_CPU_FAULT_INFO + HV_FAULT_D_CTX_OFFSET], %g5
335 sllx %g3, 16, %g3
336 or %g5, %g3, %g5
337
338 /* Window fixup? */
339 rdpr %tl, %g2
340 cmp %g2, 1
341 bgu,pn %icc, winfix_mna
342 rdpr %tpc, %g3
343
344 ba,pt %xcc, etrap
345 rd %pc, %g7
346 mov %l4, %o1
347 mov %l5, %o2
348 call sun4v_mna
349 add %sp, PTREGS_OFF, %o0
350 ba,a,pt %xcc, rtrap_clr_l6
351
352 /* Privileged Action. */
353sun4v_privact:
354 ba,pt %xcc, etrap
355 rd %pc, %g7
356 call do_privact
357 add %sp, PTREGS_OFF, %o0
358 ba,a,pt %xcc, rtrap_clr_l6
359
360 /* Unaligned ldd float, tl0. */
361sun4v_lddfmna:
362 mov SCRATCHPAD_CPUID, %g1
363 ldxa [%g1] ASI_SCRATCHPAD, %g3
364 sethi %hi(trap_block), %g2
365 or %g2, %lo(trap_block), %g2
366 sllx %g3, TRAP_BLOCK_SZ_SHIFT, %g3
367 add %g2, %g3, %g2
368 ldx [%g2 + TRAP_PER_CPU_FAULT_INFO + HV_FAULT_D_TYPE_OFFSET], %g3
369 ldx [%g2 + TRAP_PER_CPU_FAULT_INFO + HV_FAULT_D_ADDR_OFFSET], %g4
370 ldx [%g2 + TRAP_PER_CPU_FAULT_INFO + HV_FAULT_D_CTX_OFFSET], %g5
371 sllx %g3, 16, %g3
372 or %g5, %g3, %g5
373 ba,pt %xcc, etrap
374 rd %pc, %g7
375 mov %l4, %o1
376 mov %l5, %o2
377 call handle_lddfmna
378 add %sp, PTREGS_OFF, %o0
379 ba,a,pt %xcc, rtrap_clr_l6
380
381 /* Unaligned std float, tl0. */
382sun4v_stdfmna:
383 mov SCRATCHPAD_CPUID, %g1
384 ldxa [%g1] ASI_SCRATCHPAD, %g3
385 sethi %hi(trap_block), %g2
386 or %g2, %lo(trap_block), %g2
387 sllx %g3, TRAP_BLOCK_SZ_SHIFT, %g3
388 add %g2, %g3, %g2
389 ldx [%g2 + TRAP_PER_CPU_FAULT_INFO + HV_FAULT_D_TYPE_OFFSET], %g3
390 ldx [%g2 + TRAP_PER_CPU_FAULT_INFO + HV_FAULT_D_ADDR_OFFSET], %g4
391 ldx [%g2 + TRAP_PER_CPU_FAULT_INFO + HV_FAULT_D_CTX_OFFSET], %g5
392 sllx %g3, 16, %g3
393 or %g5, %g3, %g5
394 ba,pt %xcc, etrap
395 rd %pc, %g7
396 mov %l4, %o1
397 mov %l5, %o2
398 call handle_stdfmna
399 add %sp, PTREGS_OFF, %o0
400 ba,a,pt %xcc, rtrap_clr_l6
240 401
241#define BRANCH_ALWAYS 0x10680000 402#define BRANCH_ALWAYS 0x10680000
242#define NOP 0x01000000 403#define NOP 0x01000000
@@ -265,6 +426,15 @@ sun4v_patch_tlb_handlers:
265 SUN4V_DO_PATCH(tl1_damiss, sun4v_dtlb_miss) 426 SUN4V_DO_PATCH(tl1_damiss, sun4v_dtlb_miss)
266 SUN4V_DO_PATCH(tl0_daprot, sun4v_dtlb_prot) 427 SUN4V_DO_PATCH(tl0_daprot, sun4v_dtlb_prot)
267 SUN4V_DO_PATCH(tl1_daprot, sun4v_dtlb_prot) 428 SUN4V_DO_PATCH(tl1_daprot, sun4v_dtlb_prot)
429 SUN4V_DO_PATCH(tl0_iax, sun4v_iacc)
430 SUN4V_DO_PATCH(tl1_iax, sun4v_iacc_tl1)
431 SUN4V_DO_PATCH(tl0_dax, sun4v_dacc)
432 SUN4V_DO_PATCH(tl1_dax, sun4v_dacc_tl1)
433 SUN4V_DO_PATCH(tl0_mna, sun4v_mna)
434 SUN4V_DO_PATCH(tl1_mna, sun4v_mna)
435 SUN4V_DO_PATCH(tl0_lddfmna, sun4v_lddfmna)
436 SUN4V_DO_PATCH(tl0_stdfmna, sun4v_stdfmna)
437 SUN4V_DO_PATCH(tl0_privact, sun4v_privact)
268 retl 438 retl
269 nop 439 nop
270 .size sun4v_patch_tlb_handlers,.-sun4v_patch_tlb_handlers 440 .size sun4v_patch_tlb_handlers,.-sun4v_patch_tlb_handlers
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;
diff --git a/arch/sparc64/kernel/unaligned.c b/arch/sparc64/kernel/unaligned.c
index 70faf630603b..001e8518331f 100644
--- a/arch/sparc64/kernel/unaligned.c
+++ b/arch/sparc64/kernel/unaligned.c
@@ -277,7 +277,7 @@ static void kernel_mna_trap_fault(void)
277 regs->tstate |= (ASI_AIUS << 24UL); 277 regs->tstate |= (ASI_AIUS << 24UL);
278} 278}
279 279
280asmlinkage void kernel_unaligned_trap(struct pt_regs *regs, unsigned int insn, unsigned long sfar, unsigned long sfsr) 280asmlinkage void kernel_unaligned_trap(struct pt_regs *regs, unsigned int insn)
281{ 281{
282 enum direction dir = decode_direction(insn); 282 enum direction dir = decode_direction(insn);
283 int size = decode_access_size(insn); 283 int size = decode_access_size(insn);
@@ -405,6 +405,9 @@ extern void do_privact(struct pt_regs *regs);
405extern void spitfire_data_access_exception(struct pt_regs *regs, 405extern void spitfire_data_access_exception(struct pt_regs *regs,
406 unsigned long sfsr, 406 unsigned long sfsr,
407 unsigned long sfar); 407 unsigned long sfar);
408extern void sun4v_data_access_exception(struct pt_regs *regs,
409 unsigned long addr,
410 unsigned long type_ctx);
408 411
409int handle_ldf_stq(u32 insn, struct pt_regs *regs) 412int handle_ldf_stq(u32 insn, struct pt_regs *regs)
410{ 413{
@@ -447,14 +450,20 @@ int handle_ldf_stq(u32 insn, struct pt_regs *regs)
447 break; 450 break;
448 } 451 }
449 default: 452 default:
450 spitfire_data_access_exception(regs, 0, addr); 453 if (tlb_type == hypervisor)
454 sun4v_data_access_exception(regs, addr, 0);
455 else
456 spitfire_data_access_exception(regs, 0, addr);
451 return 1; 457 return 1;
452 } 458 }
453 if (put_user (first >> 32, (u32 __user *)addr) || 459 if (put_user (first >> 32, (u32 __user *)addr) ||
454 __put_user ((u32)first, (u32 __user *)(addr + 4)) || 460 __put_user ((u32)first, (u32 __user *)(addr + 4)) ||
455 __put_user (second >> 32, (u32 __user *)(addr + 8)) || 461 __put_user (second >> 32, (u32 __user *)(addr + 8)) ||
456 __put_user ((u32)second, (u32 __user *)(addr + 12))) { 462 __put_user ((u32)second, (u32 __user *)(addr + 12))) {
457 spitfire_data_access_exception(regs, 0, addr); 463 if (tlb_type == hypervisor)
464 sun4v_data_access_exception(regs, addr, 0);
465 else
466 spitfire_data_access_exception(regs, 0, addr);
458 return 1; 467 return 1;
459 } 468 }
460 } else { 469 } else {
@@ -467,7 +476,10 @@ int handle_ldf_stq(u32 insn, struct pt_regs *regs)
467 do_privact(regs); 476 do_privact(regs);
468 return 1; 477 return 1;
469 } else if (asi > ASI_SNFL) { 478 } else if (asi > ASI_SNFL) {
470 spitfire_data_access_exception(regs, 0, addr); 479 if (tlb_type == hypervisor)
480 sun4v_data_access_exception(regs, addr, 0);
481 else
482 spitfire_data_access_exception(regs, 0, addr);
471 return 1; 483 return 1;
472 } 484 }
473 switch (insn & 0x180000) { 485 switch (insn & 0x180000) {
@@ -484,7 +496,10 @@ int handle_ldf_stq(u32 insn, struct pt_regs *regs)
484 err |= __get_user (data[i], (u32 __user *)(addr + 4*i)); 496 err |= __get_user (data[i], (u32 __user *)(addr + 4*i));
485 } 497 }
486 if (err && !(asi & 0x2 /* NF */)) { 498 if (err && !(asi & 0x2 /* NF */)) {
487 spitfire_data_access_exception(regs, 0, addr); 499 if (tlb_type == hypervisor)
500 sun4v_data_access_exception(regs, addr, 0);
501 else
502 spitfire_data_access_exception(regs, 0, addr);
488 return 1; 503 return 1;
489 } 504 }
490 if (asi & 0x8) /* Little */ { 505 if (asi & 0x8) /* Little */ {
@@ -548,7 +563,7 @@ void handle_lddfmna(struct pt_regs *regs, unsigned long sfar, unsigned long sfsr
548 u32 insn; 563 u32 insn;
549 u32 first, second; 564 u32 first, second;
550 u64 value; 565 u64 value;
551 u8 asi, freg; 566 u8 freg;
552 int flag; 567 int flag;
553 struct fpustate *f = FPUSTATE; 568 struct fpustate *f = FPUSTATE;
554 569
@@ -557,7 +572,7 @@ void handle_lddfmna(struct pt_regs *regs, unsigned long sfar, unsigned long sfsr
557 if (test_thread_flag(TIF_32BIT)) 572 if (test_thread_flag(TIF_32BIT))
558 pc = (u32)pc; 573 pc = (u32)pc;
559 if (get_user(insn, (u32 __user *) pc) != -EFAULT) { 574 if (get_user(insn, (u32 __user *) pc) != -EFAULT) {
560 asi = sfsr >> 16; 575 int asi = decode_asi(insn, regs);
561 if ((asi > ASI_SNFL) || 576 if ((asi > ASI_SNFL) ||
562 (asi < ASI_P)) 577 (asi < ASI_P))
563 goto daex; 578 goto daex;
@@ -587,7 +602,11 @@ void handle_lddfmna(struct pt_regs *regs, unsigned long sfar, unsigned long sfsr
587 *(u64 *)(f->regs + freg) = value; 602 *(u64 *)(f->regs + freg) = value;
588 current_thread_info()->fpsaved[0] |= flag; 603 current_thread_info()->fpsaved[0] |= flag;
589 } else { 604 } else {
590daex: spitfire_data_access_exception(regs, sfsr, sfar); 605daex:
606 if (tlb_type == hypervisor)
607 sun4v_data_access_exception(regs, sfar, sfsr);
608 else
609 spitfire_data_access_exception(regs, sfsr, sfar);
591 return; 610 return;
592 } 611 }
593 advance(regs); 612 advance(regs);
@@ -600,7 +619,7 @@ void handle_stdfmna(struct pt_regs *regs, unsigned long sfar, unsigned long sfsr
600 unsigned long tstate = regs->tstate; 619 unsigned long tstate = regs->tstate;
601 u32 insn; 620 u32 insn;
602 u64 value; 621 u64 value;
603 u8 asi, freg; 622 u8 freg;
604 int flag; 623 int flag;
605 struct fpustate *f = FPUSTATE; 624 struct fpustate *f = FPUSTATE;
606 625
@@ -609,8 +628,8 @@ void handle_stdfmna(struct pt_regs *regs, unsigned long sfar, unsigned long sfsr
609 if (test_thread_flag(TIF_32BIT)) 628 if (test_thread_flag(TIF_32BIT))
610 pc = (u32)pc; 629 pc = (u32)pc;
611 if (get_user(insn, (u32 __user *) pc) != -EFAULT) { 630 if (get_user(insn, (u32 __user *) pc) != -EFAULT) {
631 int asi = decode_asi(insn, regs);
612 freg = ((insn >> 25) & 0x1e) | ((insn >> 20) & 0x20); 632 freg = ((insn >> 25) & 0x1e) | ((insn >> 20) & 0x20);
613 asi = sfsr >> 16;
614 value = 0; 633 value = 0;
615 flag = (freg < 32) ? FPRS_DL : FPRS_DU; 634 flag = (freg < 32) ? FPRS_DL : FPRS_DU;
616 if ((asi > ASI_SNFL) || 635 if ((asi > ASI_SNFL) ||
@@ -631,7 +650,11 @@ void handle_stdfmna(struct pt_regs *regs, unsigned long sfar, unsigned long sfsr
631 __put_user ((u32)value, (u32 __user *)(sfar + 4))) 650 __put_user ((u32)value, (u32 __user *)(sfar + 4)))
632 goto daex; 651 goto daex;
633 } else { 652 } else {
634daex: spitfire_data_access_exception(regs, sfsr, sfar); 653daex:
654 if (tlb_type == hypervisor)
655 sun4v_data_access_exception(regs, sfar, sfsr);
656 else
657 spitfire_data_access_exception(regs, sfsr, sfar);
635 return; 658 return;
636 } 659 }
637 advance(regs); 660 advance(regs);
diff --git a/arch/sparc64/kernel/winfixup.S b/arch/sparc64/kernel/winfixup.S
index efe2770e8f5d..aca2a98b930b 100644
--- a/arch/sparc64/kernel/winfixup.S
+++ b/arch/sparc64/kernel/winfixup.S
@@ -109,16 +109,23 @@ winfix_mna:
109 done 109 done
110 110
111fill_fixup_mna: 111fill_fixup_mna:
112 TRAP_LOAD_THREAD_REG(%g6, %g1)
113 rdpr %tstate, %g1 112 rdpr %tstate, %g1
114 and %g1, TSTATE_CWP, %g1 113 and %g1, TSTATE_CWP, %g1
115 wrpr %g1, %cwp 114 wrpr %g1, %cwp
116 ba,pt %xcc, etrap 115 ba,pt %xcc, etrap
117 rd %pc, %g7 116 rd %pc, %g7
118 mov %l4, %o2 117 sethi %hi(tlb_type), %g1
119 mov %l5, %o1 118 mov %l4, %o1
120 call mem_address_unaligned 119 lduw [%g1 + %lo(tlb_type)], %g1
120 mov %l5, %o2
121 cmp %g1, 3
122 bne,pt %icc, 1f
121 add %sp, PTREGS_OFF, %o0 123 add %sp, PTREGS_OFF, %o0
124 call sun4v_mna
125 nop
126 ba,a,pt %xcc, rtrap_clr_l6
1271: call mem_address_unaligned
128 nop
122 ba,a,pt %xcc, rtrap_clr_l6 129 ba,a,pt %xcc, rtrap_clr_l6
123 130
124winfix_dax: 131winfix_dax:
@@ -128,14 +135,21 @@ winfix_dax:
128 done 135 done
129 136
130fill_fixup_dax: 137fill_fixup_dax:
131 TRAP_LOAD_THREAD_REG(%g6, %g1)
132 rdpr %tstate, %g1 138 rdpr %tstate, %g1
133 and %g1, TSTATE_CWP, %g1 139 and %g1, TSTATE_CWP, %g1
134 wrpr %g1, %cwp 140 wrpr %g1, %cwp
135 ba,pt %xcc, etrap 141 ba,pt %xcc, etrap
136 rd %pc, %g7 142 rd %pc, %g7
143 sethi %hi(tlb_type), %g1
137 mov %l4, %o1 144 mov %l4, %o1
145 lduw [%g1 + %lo(tlb_type)], %g1
138 mov %l5, %o2 146 mov %l5, %o2
139 call spitfire_data_access_exception 147 cmp %g1, 3
148 bne,pt %icc, 1f
140 add %sp, PTREGS_OFF, %o0 149 add %sp, PTREGS_OFF, %o0
150 call sun4v_data_access_exception
151 nop
152 ba,a,pt %xcc, rtrap_clr_l6
1531: call spitfire_data_access_exception
154 nop
141 ba,a,pt %xcc, rtrap_clr_l6 155 ba,a,pt %xcc, rtrap_clr_l6