diff options
-rw-r--r-- | arch/powerpc/Kconfig | 8 | ||||
-rw-r--r-- | arch/powerpc/configs/ppc64_defconfig | 1 | ||||
-rw-r--r-- | arch/powerpc/configs/pseries_defconfig | 1 | ||||
-rw-r--r-- | arch/powerpc/include/asm/ppc-opcode.h | 3 | ||||
-rw-r--r-- | arch/powerpc/include/asm/reg.h | 1 | ||||
-rw-r--r-- | arch/powerpc/kernel/exceptions-64s.S | 123 |
6 files changed, 137 insertions, 0 deletions
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 98e513b62709..748ccaa3b4b3 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig | |||
@@ -560,6 +560,14 @@ config SCHED_SMT | |||
560 | when dealing with POWER5 cpus at a cost of slightly increased | 560 | when dealing with POWER5 cpus at a cost of slightly increased |
561 | overhead in some places. If unsure say N here. | 561 | overhead in some places. If unsure say N here. |
562 | 562 | ||
563 | config PPC_DENORMALISATION | ||
564 | bool "PowerPC denormalisation exception handling" | ||
565 | depends on PPC_BOOK3S_64 | ||
566 | default "n" | ||
567 | ---help--- | ||
568 | Add support for handling denormalisation of single precision | ||
569 | values. Useful for bare metal only. If unsure say Y here. | ||
570 | |||
563 | config CMDLINE_BOOL | 571 | config CMDLINE_BOOL |
564 | bool "Default bootloader kernel arguments" | 572 | bool "Default bootloader kernel arguments" |
565 | 573 | ||
diff --git a/arch/powerpc/configs/ppc64_defconfig b/arch/powerpc/configs/ppc64_defconfig index db27c82e0542..e263e6a5aca1 100644 --- a/arch/powerpc/configs/ppc64_defconfig +++ b/arch/powerpc/configs/ppc64_defconfig | |||
@@ -51,6 +51,7 @@ CONFIG_KEXEC=y | |||
51 | CONFIG_IRQ_ALL_CPUS=y | 51 | CONFIG_IRQ_ALL_CPUS=y |
52 | CONFIG_MEMORY_HOTREMOVE=y | 52 | CONFIG_MEMORY_HOTREMOVE=y |
53 | CONFIG_SCHED_SMT=y | 53 | CONFIG_SCHED_SMT=y |
54 | CONFIG_PPC_DENORMALISATION=y | ||
54 | CONFIG_PCCARD=y | 55 | CONFIG_PCCARD=y |
55 | CONFIG_ELECTRA_CF=y | 56 | CONFIG_ELECTRA_CF=y |
56 | CONFIG_HOTPLUG_PCI=m | 57 | CONFIG_HOTPLUG_PCI=m |
diff --git a/arch/powerpc/configs/pseries_defconfig b/arch/powerpc/configs/pseries_defconfig index 1f65b3c9b59a..c169dfb3e42d 100644 --- a/arch/powerpc/configs/pseries_defconfig +++ b/arch/powerpc/configs/pseries_defconfig | |||
@@ -48,6 +48,7 @@ CONFIG_MEMORY_HOTREMOVE=y | |||
48 | CONFIG_PPC_64K_PAGES=y | 48 | CONFIG_PPC_64K_PAGES=y |
49 | CONFIG_PPC_SUBPAGE_PROT=y | 49 | CONFIG_PPC_SUBPAGE_PROT=y |
50 | CONFIG_SCHED_SMT=y | 50 | CONFIG_SCHED_SMT=y |
51 | CONFIG_PPC_DENORMALISATION=y | ||
51 | CONFIG_HOTPLUG_PCI=m | 52 | CONFIG_HOTPLUG_PCI=m |
52 | CONFIG_HOTPLUG_PCI_RPA=m | 53 | CONFIG_HOTPLUG_PCI_RPA=m |
53 | CONFIG_HOTPLUG_PCI_RPA_DLPAR=m | 54 | CONFIG_HOTPLUG_PCI_RPA_DLPAR=m |
diff --git a/arch/powerpc/include/asm/ppc-opcode.h b/arch/powerpc/include/asm/ppc-opcode.h index 4c25319f2fbc..5f73ce63fcae 100644 --- a/arch/powerpc/include/asm/ppc-opcode.h +++ b/arch/powerpc/include/asm/ppc-opcode.h | |||
@@ -126,6 +126,7 @@ | |||
126 | #define PPC_INST_TLBIVAX 0x7c000624 | 126 | #define PPC_INST_TLBIVAX 0x7c000624 |
127 | #define PPC_INST_TLBSRX_DOT 0x7c0006a5 | 127 | #define PPC_INST_TLBSRX_DOT 0x7c0006a5 |
128 | #define PPC_INST_XXLOR 0xf0000510 | 128 | #define PPC_INST_XXLOR 0xf0000510 |
129 | #define PPC_INST_XVCPSGNDP 0xf0000780 | ||
129 | 130 | ||
130 | #define PPC_INST_NAP 0x4c000364 | 131 | #define PPC_INST_NAP 0x4c000364 |
131 | #define PPC_INST_SLEEP 0x4c0003a4 | 132 | #define PPC_INST_SLEEP 0x4c0003a4 |
@@ -277,6 +278,8 @@ | |||
277 | VSX_XX1((s), a, b)) | 278 | VSX_XX1((s), a, b)) |
278 | #define XXLOR(t, a, b) stringify_in_c(.long PPC_INST_XXLOR | \ | 279 | #define XXLOR(t, a, b) stringify_in_c(.long PPC_INST_XXLOR | \ |
279 | VSX_XX3((t), a, b)) | 280 | VSX_XX3((t), a, b)) |
281 | #define XVCPSGNDP(t, a, b) stringify_in_c(.long (PPC_INST_XVCPSGNDP | \ | ||
282 | VSX_XX3((t), (a), (b)))) | ||
280 | 283 | ||
281 | #define PPC_NAP stringify_in_c(.long PPC_INST_NAP) | 284 | #define PPC_NAP stringify_in_c(.long PPC_INST_NAP) |
282 | #define PPC_SLEEP stringify_in_c(.long PPC_INST_SLEEP) | 285 | #define PPC_SLEEP stringify_in_c(.long PPC_INST_SLEEP) |
diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h index 121a90bbf778..a1096fb62816 100644 --- a/arch/powerpc/include/asm/reg.h +++ b/arch/powerpc/include/asm/reg.h | |||
@@ -524,6 +524,7 @@ | |||
524 | 524 | ||
525 | #define SPRN_HSRR0 0x13A /* Save/Restore Register 0 */ | 525 | #define SPRN_HSRR0 0x13A /* Save/Restore Register 0 */ |
526 | #define SPRN_HSRR1 0x13B /* Save/Restore Register 1 */ | 526 | #define SPRN_HSRR1 0x13B /* Save/Restore Register 1 */ |
527 | #define HSRR1_DENORM 0x00100000 /* Denorm exception */ | ||
527 | 528 | ||
528 | #define SPRN_TBCTL 0x35f /* PA6T Timebase control register */ | 529 | #define SPRN_TBCTL 0x35f /* PA6T Timebase control register */ |
529 | #define TBCTL_FREEZE 0x0000000000000000ull /* Freeze all tbs */ | 530 | #define TBCTL_FREEZE 0x0000000000000000ull /* Freeze all tbs */ |
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 | ||
280 | denorm_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 | ||
365 | denorm_assist: | ||
366 | BEGIN_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 | ||
408 | FTR_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) | ||
449 | ALT_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 |