aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel
diff options
context:
space:
mode:
authorMichael Neuling <mikey@neuling.org>2012-09-09 20:35:26 -0400
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2012-09-17 02:31:47 -0400
commitb92a66a65cb4480774066d9a3080c77eb34b7232 (patch)
treeba40ef5be8bdb9b76e36ec1da29db90189d2a821 /arch/powerpc/kernel
parenteda485f06d17f98bd58559fb5dd331951ffd1608 (diff)
powerpc: Add denormalisation exception handling for POWER6/7
On POWER6 and POWER7 if the input operand to an instruction is a denormalised single precision binary floating point value we can take a denormalisation exception where it's expected that the hypervisor (HV=1) will fix up the inputs before the instruction is run. This adds code to handle this denormalisation exception for POWER6 and POWER7. It also add a CONFIG_PPC_DENORMALISATION option and sets it in pseries/ppc64_defconfig. This is useful on bare metal systems only. Based on patch from Milton Miller. Signed-off-by: Michael Neuling <mikey@neuling.org> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'arch/powerpc/kernel')
-rw-r--r--arch/powerpc/kernel/exceptions-64s.S123
1 files changed, 123 insertions, 0 deletions
diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S
index 39aa97d3ff88..5eb00569199f 100644
--- a/arch/powerpc/kernel/exceptions-64s.S
+++ b/arch/powerpc/kernel/exceptions-64s.S
@@ -275,6 +275,31 @@ vsx_unavailable_pSeries_1:
275 STD_EXCEPTION_PSERIES(0x1300, 0x1300, instruction_breakpoint) 275 STD_EXCEPTION_PSERIES(0x1300, 0x1300, instruction_breakpoint)
276 KVM_HANDLER_PR_SKIP(PACA_EXGEN, EXC_STD, 0x1300) 276 KVM_HANDLER_PR_SKIP(PACA_EXGEN, EXC_STD, 0x1300)
277 277
278 . = 0x1500
279 .global denorm_Hypervisor
280denorm_exception_hv:
281 HMT_MEDIUM
282 mtspr SPRN_SPRG_HSCRATCH0,r13
283 mfspr r13,SPRN_SPRG_HPACA
284 std r9,PACA_EXGEN+EX_R9(r13)
285 std r10,PACA_EXGEN+EX_R10(r13)
286 std r11,PACA_EXGEN+EX_R11(r13)
287 std r12,PACA_EXGEN+EX_R12(r13)
288 mfspr r9,SPRN_SPRG_HSCRATCH0
289 std r9,PACA_EXGEN+EX_R13(r13)
290 mfcr r9
291
292#ifdef CONFIG_PPC_DENORMALISATION
293 mfspr r10,SPRN_HSRR1
294 mfspr r11,SPRN_HSRR0 /* save HSRR0 */
295 andis. r10,r10,(HSRR1_DENORM)@h /* denorm? */
296 addi r11,r11,-4 /* HSRR0 is next instruction */
297 bne+ denorm_assist
298#endif
299
300 EXCEPTION_PROLOG_PSERIES_1(denorm_common, EXC_HV)
301 KVM_HANDLER_SKIP(PACA_EXGEN, EXC_STD, 0x1500)
302
278#ifdef CONFIG_CBE_RAS 303#ifdef CONFIG_CBE_RAS
279 STD_EXCEPTION_HV(0x1600, 0x1602, cbe_maintenance) 304 STD_EXCEPTION_HV(0x1600, 0x1602, cbe_maintenance)
280 KVM_HANDLER_SKIP(PACA_EXGEN, EXC_HV, 0x1602) 305 KVM_HANDLER_SKIP(PACA_EXGEN, EXC_HV, 0x1602)
@@ -336,6 +361,103 @@ do_stab_bolted_pSeries:
336 KVM_HANDLER_PR(PACA_EXGEN, EXC_STD, 0x900) 361 KVM_HANDLER_PR(PACA_EXGEN, EXC_STD, 0x900)
337 KVM_HANDLER(PACA_EXGEN, EXC_HV, 0x982) 362 KVM_HANDLER(PACA_EXGEN, EXC_HV, 0x982)
338 363
364#ifdef CONFIG_PPC_DENORMALISATION
365denorm_assist:
366BEGIN_FTR_SECTION
367/*
368 * To denormalise we need to move a copy of the register to itself.
369 * For POWER6 do that here for all FP regs.
370 */
371 mfmsr r10
372 ori r10,r10,(MSR_FP|MSR_FE0|MSR_FE1)
373 xori r10,r10,(MSR_FE0|MSR_FE1)
374 mtmsrd r10
375 sync
376 fmr 0,0
377 fmr 1,1
378 fmr 2,2
379 fmr 3,3
380 fmr 4,4
381 fmr 5,5
382 fmr 6,6
383 fmr 7,7
384 fmr 8,8
385 fmr 9,9
386 fmr 10,10
387 fmr 11,11
388 fmr 12,12
389 fmr 13,13
390 fmr 14,14
391 fmr 15,15
392 fmr 16,16
393 fmr 17,17
394 fmr 18,18
395 fmr 19,19
396 fmr 20,20
397 fmr 21,21
398 fmr 22,22
399 fmr 23,23
400 fmr 24,24
401 fmr 25,25
402 fmr 26,26
403 fmr 27,27
404 fmr 28,28
405 fmr 29,29
406 fmr 30,30
407 fmr 31,31
408FTR_SECTION_ELSE
409/*
410 * To denormalise we need to move a copy of the register to itself.
411 * For POWER7 do that here for the first 32 VSX registers only.
412 */
413 mfmsr r10
414 oris r10,r10,MSR_VSX@h
415 mtmsrd r10
416 sync
417 XVCPSGNDP(0,0,0)
418 XVCPSGNDP(1,1,1)
419 XVCPSGNDP(2,2,2)
420 XVCPSGNDP(3,3,3)
421 XVCPSGNDP(4,4,4)
422 XVCPSGNDP(5,5,5)
423 XVCPSGNDP(6,6,6)
424 XVCPSGNDP(7,7,7)
425 XVCPSGNDP(8,8,8)
426 XVCPSGNDP(9,9,9)
427 XVCPSGNDP(10,10,10)
428 XVCPSGNDP(11,11,11)
429 XVCPSGNDP(12,12,12)
430 XVCPSGNDP(13,13,13)
431 XVCPSGNDP(14,14,14)
432 XVCPSGNDP(15,15,15)
433 XVCPSGNDP(16,16,16)
434 XVCPSGNDP(17,17,17)
435 XVCPSGNDP(18,18,18)
436 XVCPSGNDP(19,19,19)
437 XVCPSGNDP(20,20,20)
438 XVCPSGNDP(21,21,21)
439 XVCPSGNDP(22,22,22)
440 XVCPSGNDP(23,23,23)
441 XVCPSGNDP(24,24,24)
442 XVCPSGNDP(25,25,25)
443 XVCPSGNDP(26,26,26)
444 XVCPSGNDP(27,27,27)
445 XVCPSGNDP(28,28,28)
446 XVCPSGNDP(29,29,29)
447 XVCPSGNDP(30,30,30)
448 XVCPSGNDP(31,31,31)
449ALT_FTR_SECTION_END_IFCLR(CPU_FTR_ARCH_206)
450 mtspr SPRN_HSRR0,r11
451 mtcrf 0x80,r9
452 ld r9,PACA_EXGEN+EX_R9(r13)
453 ld r10,PACA_EXGEN+EX_R10(r13)
454 ld r11,PACA_EXGEN+EX_R11(r13)
455 ld r12,PACA_EXGEN+EX_R12(r13)
456 ld r13,PACA_EXGEN+EX_R13(r13)
457 HRFID
458 b .
459#endif
460
339 .align 7 461 .align 7
340 /* moved from 0xe00 */ 462 /* moved from 0xe00 */
341 STD_EXCEPTION_HV(., 0xe02, h_data_storage) 463 STD_EXCEPTION_HV(., 0xe02, h_data_storage)
@@ -495,6 +617,7 @@ machine_check_common:
495 STD_EXCEPTION_COMMON(0xe60, hmi_exception, .unknown_exception) 617 STD_EXCEPTION_COMMON(0xe60, hmi_exception, .unknown_exception)
496 STD_EXCEPTION_COMMON_ASYNC(0xf00, performance_monitor, .performance_monitor_exception) 618 STD_EXCEPTION_COMMON_ASYNC(0xf00, performance_monitor, .performance_monitor_exception)
497 STD_EXCEPTION_COMMON(0x1300, instruction_breakpoint, .instruction_breakpoint_exception) 619 STD_EXCEPTION_COMMON(0x1300, instruction_breakpoint, .instruction_breakpoint_exception)
620 STD_EXCEPTION_COMMON(0x1502, denorm, .unknown_exception)
498#ifdef CONFIG_ALTIVEC 621#ifdef CONFIG_ALTIVEC
499 STD_EXCEPTION_COMMON(0x1700, altivec_assist, .altivec_assist_exception) 622 STD_EXCEPTION_COMMON(0x1700, altivec_assist, .altivec_assist_exception)
500#else 623#else