aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel/exceptions-64e.S
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/kernel/exceptions-64e.S')
-rw-r--r--arch/powerpc/kernel/exceptions-64e.S204
1 files changed, 197 insertions, 7 deletions
diff --git a/arch/powerpc/kernel/exceptions-64e.S b/arch/powerpc/kernel/exceptions-64e.S
index 5c43063d2506..d24d4400cc79 100644
--- a/arch/powerpc/kernel/exceptions-64e.S
+++ b/arch/powerpc/kernel/exceptions-64e.S
@@ -17,6 +17,7 @@
17#include <asm/cputable.h> 17#include <asm/cputable.h>
18#include <asm/setup.h> 18#include <asm/setup.h>
19#include <asm/thread_info.h> 19#include <asm/thread_info.h>
20#include <asm/reg_a2.h>
20#include <asm/exception-64e.h> 21#include <asm/exception-64e.h>
21#include <asm/bug.h> 22#include <asm/bug.h>
22#include <asm/irqflags.h> 23#include <asm/irqflags.h>
@@ -252,9 +253,6 @@ exception_marker:
252 .balign 0x1000 253 .balign 0x1000
253 .globl interrupt_base_book3e 254 .globl interrupt_base_book3e
254interrupt_base_book3e: /* fake trap */ 255interrupt_base_book3e: /* fake trap */
255 /* Note: If real debug exceptions are supported by the HW, the vector
256 * below will have to be patched up to point to an appropriate handler
257 */
258 EXCEPTION_STUB(0x000, machine_check) /* 0x0200 */ 256 EXCEPTION_STUB(0x000, machine_check) /* 0x0200 */
259 EXCEPTION_STUB(0x020, critical_input) /* 0x0580 */ 257 EXCEPTION_STUB(0x020, critical_input) /* 0x0580 */
260 EXCEPTION_STUB(0x040, debug_crit) /* 0x0d00 */ 258 EXCEPTION_STUB(0x040, debug_crit) /* 0x0d00 */
@@ -271,8 +269,13 @@ interrupt_base_book3e: /* fake trap */
271 EXCEPTION_STUB(0x1a0, watchdog) /* 0x09f0 */ 269 EXCEPTION_STUB(0x1a0, watchdog) /* 0x09f0 */
272 EXCEPTION_STUB(0x1c0, data_tlb_miss) 270 EXCEPTION_STUB(0x1c0, data_tlb_miss)
273 EXCEPTION_STUB(0x1e0, instruction_tlb_miss) 271 EXCEPTION_STUB(0x1e0, instruction_tlb_miss)
272 EXCEPTION_STUB(0x260, perfmon)
274 EXCEPTION_STUB(0x280, doorbell) 273 EXCEPTION_STUB(0x280, doorbell)
275 EXCEPTION_STUB(0x2a0, doorbell_crit) 274 EXCEPTION_STUB(0x2a0, doorbell_crit)
275 EXCEPTION_STUB(0x2c0, guest_doorbell)
276 EXCEPTION_STUB(0x2e0, guest_doorbell_crit)
277 EXCEPTION_STUB(0x300, hypercall)
278 EXCEPTION_STUB(0x320, ehpriv)
276 279
277 .globl interrupt_end_book3e 280 .globl interrupt_end_book3e
278interrupt_end_book3e: 281interrupt_end_book3e:
@@ -379,7 +382,7 @@ interrupt_end_book3e:
379 mfspr r13,SPRN_SPRG_PACA /* get our PACA */ 382 mfspr r13,SPRN_SPRG_PACA /* get our PACA */
380 b system_call_common 383 b system_call_common
381 384
382/* Auxillary Processor Unavailable Interrupt */ 385/* Auxiliary Processor Unavailable Interrupt */
383 START_EXCEPTION(ap_unavailable); 386 START_EXCEPTION(ap_unavailable);
384 NORMAL_EXCEPTION_PROLOG(0xf20, PROLOG_ADDITION_NONE) 387 NORMAL_EXCEPTION_PROLOG(0xf20, PROLOG_ADDITION_NONE)
385 EXCEPTION_COMMON(0xf20, PACA_EXGEN, INTS_KEEP) 388 EXCEPTION_COMMON(0xf20, PACA_EXGEN, INTS_KEEP)
@@ -454,6 +457,70 @@ interrupt_end_book3e:
454kernel_dbg_exc: 457kernel_dbg_exc:
455 b . /* NYI */ 458 b . /* NYI */
456 459
460/* Debug exception as a debug interrupt*/
461 START_EXCEPTION(debug_debug);
462 DBG_EXCEPTION_PROLOG(0xd00, PROLOG_ADDITION_2REGS)
463
464 /*
465 * If there is a single step or branch-taken exception in an
466 * exception entry sequence, it was probably meant to apply to
467 * the code where the exception occurred (since exception entry
468 * doesn't turn off DE automatically). We simulate the effect
469 * of turning off DE on entry to an exception handler by turning
470 * off DE in the DSRR1 value and clearing the debug status.
471 */
472
473 mfspr r14,SPRN_DBSR /* check single-step/branch taken */
474 andis. r15,r14,DBSR_IC@h
475 beq+ 1f
476
477 LOAD_REG_IMMEDIATE(r14,interrupt_base_book3e)
478 LOAD_REG_IMMEDIATE(r15,interrupt_end_book3e)
479 cmpld cr0,r10,r14
480 cmpld cr1,r10,r15
481 blt+ cr0,1f
482 bge+ cr1,1f
483
484 /* here it looks like we got an inappropriate debug exception. */
485 lis r14,DBSR_IC@h /* clear the IC event */
486 rlwinm r11,r11,0,~MSR_DE /* clear DE in the DSRR1 value */
487 mtspr SPRN_DBSR,r14
488 mtspr SPRN_DSRR1,r11
489 lwz r10,PACA_EXDBG+EX_CR(r13) /* restore registers */
490 ld r1,PACA_EXDBG+EX_R1(r13)
491 ld r14,PACA_EXDBG+EX_R14(r13)
492 ld r15,PACA_EXDBG+EX_R15(r13)
493 mtcr r10
494 ld r10,PACA_EXDBG+EX_R10(r13) /* restore registers */
495 ld r11,PACA_EXDBG+EX_R11(r13)
496 mfspr r13,SPRN_SPRG_DBG_SCRATCH
497 rfdi
498
499 /* Normal debug exception */
500 /* XXX We only handle coming from userspace for now since we can't
501 * quite save properly an interrupted kernel state yet
502 */
5031: andi. r14,r11,MSR_PR; /* check for userspace again */
504 beq kernel_dbg_exc; /* if from kernel mode */
505
506 /* Now we mash up things to make it look like we are coming on a
507 * normal exception
508 */
509 mfspr r15,SPRN_SPRG_DBG_SCRATCH
510 mtspr SPRN_SPRG_GEN_SCRATCH,r15
511 mfspr r14,SPRN_DBSR
512 EXCEPTION_COMMON(0xd00, PACA_EXDBG, INTS_DISABLE_ALL)
513 std r14,_DSISR(r1)
514 addi r3,r1,STACK_FRAME_OVERHEAD
515 mr r4,r14
516 ld r14,PACA_EXDBG+EX_R14(r13)
517 ld r15,PACA_EXDBG+EX_R15(r13)
518 bl .save_nvgprs
519 bl .DebugException
520 b .ret_from_except
521
522 MASKABLE_EXCEPTION(0x260, perfmon, .performance_monitor_exception, ACK_NONE)
523
457/* Doorbell interrupt */ 524/* Doorbell interrupt */
458 MASKABLE_EXCEPTION(0x2070, doorbell, .doorbell_exception, ACK_NONE) 525 MASKABLE_EXCEPTION(0x2070, doorbell, .doorbell_exception, ACK_NONE)
459 526
@@ -468,6 +535,11 @@ kernel_dbg_exc:
468// b ret_from_crit_except 535// b ret_from_crit_except
469 b . 536 b .
470 537
538 MASKABLE_EXCEPTION(0x2c0, guest_doorbell, .unknown_exception, ACK_NONE)
539 MASKABLE_EXCEPTION(0x2e0, guest_doorbell_crit, .unknown_exception, ACK_NONE)
540 MASKABLE_EXCEPTION(0x310, hypercall, .unknown_exception, ACK_NONE)
541 MASKABLE_EXCEPTION(0x320, ehpriv, .unknown_exception, ACK_NONE)
542
471 543
472/* 544/*
473 * An interrupt came in while soft-disabled; clear EE in SRR1, 545 * An interrupt came in while soft-disabled; clear EE in SRR1,
@@ -587,7 +659,12 @@ fast_exception_return:
587BAD_STACK_TRAMPOLINE(0x000) 659BAD_STACK_TRAMPOLINE(0x000)
588BAD_STACK_TRAMPOLINE(0x100) 660BAD_STACK_TRAMPOLINE(0x100)
589BAD_STACK_TRAMPOLINE(0x200) 661BAD_STACK_TRAMPOLINE(0x200)
662BAD_STACK_TRAMPOLINE(0x260)
663BAD_STACK_TRAMPOLINE(0x2c0)
664BAD_STACK_TRAMPOLINE(0x2e0)
590BAD_STACK_TRAMPOLINE(0x300) 665BAD_STACK_TRAMPOLINE(0x300)
666BAD_STACK_TRAMPOLINE(0x310)
667BAD_STACK_TRAMPOLINE(0x320)
591BAD_STACK_TRAMPOLINE(0x400) 668BAD_STACK_TRAMPOLINE(0x400)
592BAD_STACK_TRAMPOLINE(0x500) 669BAD_STACK_TRAMPOLINE(0x500)
593BAD_STACK_TRAMPOLINE(0x600) 670BAD_STACK_TRAMPOLINE(0x600)
@@ -864,8 +941,23 @@ have_hes:
864 * that will have to be made dependent on whether we are running under 941 * that will have to be made dependent on whether we are running under
865 * a hypervisor I suppose. 942 * a hypervisor I suppose.
866 */ 943 */
867 ori r3,r3,MAS0_HES | MAS0_WQ_ALLWAYS 944
868 mtspr SPRN_MAS0,r3 945 /* BEWARE, MAGIC
946 * This code is called as an ordinary function on the boot CPU. But to
947 * avoid duplication, this code is also used in SCOM bringup of
948 * secondary CPUs. We read the code between the initial_tlb_code_start
949 * and initial_tlb_code_end labels one instruction at a time and RAM it
950 * into the new core via SCOM. That doesn't process branches, so there
951 * must be none between those two labels. It also means if this code
952 * ever takes any parameters, the SCOM code must also be updated to
953 * provide them.
954 */
955 .globl a2_tlbinit_code_start
956a2_tlbinit_code_start:
957
958 ori r11,r3,MAS0_WQ_ALLWAYS
959 oris r11,r11,MAS0_ESEL(3)@h /* Use way 3: workaround A2 erratum 376 */
960 mtspr SPRN_MAS0,r11
869 lis r3,(MAS1_VALID | MAS1_IPROT)@h 961 lis r3,(MAS1_VALID | MAS1_IPROT)@h
870 ori r3,r3,BOOK3E_PAGESZ_1GB << MAS1_TSIZE_SHIFT 962 ori r3,r3,BOOK3E_PAGESZ_1GB << MAS1_TSIZE_SHIFT
871 mtspr SPRN_MAS1,r3 963 mtspr SPRN_MAS1,r3
@@ -879,18 +971,86 @@ have_hes:
879 /* Write the TLB entry */ 971 /* Write the TLB entry */
880 tlbwe 972 tlbwe
881 973
974 .globl a2_tlbinit_after_linear_map
975a2_tlbinit_after_linear_map:
976
882 /* Now we branch the new virtual address mapped by this entry */ 977 /* Now we branch the new virtual address mapped by this entry */
883 LOAD_REG_IMMEDIATE(r3,1f) 978 LOAD_REG_IMMEDIATE(r3,1f)
884 mtctr r3 979 mtctr r3
885 bctr 980 bctr
886 981
8871: /* We are now running at PAGE_OFFSET, clean the TLB of everything 9821: /* We are now running at PAGE_OFFSET, clean the TLB of everything
888 * else (XXX we should scan for bolted crap from the firmware too) 983 * else (including IPROTed things left by firmware)
984 * r4 = TLBnCFG
985 * r3 = current address (more or less)
889 */ 986 */
987
988 li r5,0
989 mtspr SPRN_MAS6,r5
990 tlbsx 0,r3
991
992 rlwinm r9,r4,0,TLBnCFG_N_ENTRY
993 rlwinm r10,r4,8,0xff
994 addi r10,r10,-1 /* Get inner loop mask */
995
996 li r3,1
997
998 mfspr r5,SPRN_MAS1
999 rlwinm r5,r5,0,(~(MAS1_VALID|MAS1_IPROT))
1000
1001 mfspr r6,SPRN_MAS2
1002 rldicr r6,r6,0,51 /* Extract EPN */
1003
1004 mfspr r7,SPRN_MAS0
1005 rlwinm r7,r7,0,0xffff0fff /* Clear HES and WQ */
1006
1007 rlwinm r8,r7,16,0xfff /* Extract ESEL */
1008
10092: add r4,r3,r8
1010 and r4,r4,r10
1011
1012 rlwimi r7,r4,16,MAS0_ESEL_MASK
1013
1014 mtspr SPRN_MAS0,r7
1015 mtspr SPRN_MAS1,r5
1016 mtspr SPRN_MAS2,r6
1017 tlbwe
1018
1019 addi r3,r3,1
1020 and. r4,r3,r10
1021
1022 bne 3f
1023 addis r6,r6,(1<<30)@h
10243:
1025 cmpw r3,r9
1026 blt 2b
1027
1028 .globl a2_tlbinit_after_iprot_flush
1029a2_tlbinit_after_iprot_flush:
1030
1031#ifdef CONFIG_PPC_EARLY_DEBUG_WSP
1032 /* Now establish early debug mappings if applicable */
1033 /* Restore the MAS0 we used for linear mapping load */
1034 mtspr SPRN_MAS0,r11
1035
1036 lis r3,(MAS1_VALID | MAS1_IPROT)@h
1037 ori r3,r3,(BOOK3E_PAGESZ_4K << MAS1_TSIZE_SHIFT)
1038 mtspr SPRN_MAS1,r3
1039 LOAD_REG_IMMEDIATE(r3, WSP_UART_VIRT | MAS2_I | MAS2_G)
1040 mtspr SPRN_MAS2,r3
1041 LOAD_REG_IMMEDIATE(r3, WSP_UART_PHYS | MAS3_SR | MAS3_SW)
1042 mtspr SPRN_MAS7_MAS3,r3
1043 /* re-use the MAS8 value from the linear mapping */
1044 tlbwe
1045#endif /* CONFIG_PPC_EARLY_DEBUG_WSP */
1046
890 PPC_TLBILX(0,0,0) 1047 PPC_TLBILX(0,0,0)
891 sync 1048 sync
892 isync 1049 isync
893 1050
1051 .globl a2_tlbinit_code_end
1052a2_tlbinit_code_end:
1053
894 /* We translate LR and return */ 1054 /* We translate LR and return */
895 mflr r3 1055 mflr r3
896 tovirt(r3,r3) 1056 tovirt(r3,r3)
@@ -1040,3 +1200,33 @@ _GLOBAL(__setup_base_ivors)
1040 sync 1200 sync
1041 1201
1042 blr 1202 blr
1203
1204_GLOBAL(setup_perfmon_ivor)
1205 SET_IVOR(35, 0x260) /* Performance Monitor */
1206 blr
1207
1208_GLOBAL(setup_doorbell_ivors)
1209 SET_IVOR(36, 0x280) /* Processor Doorbell */
1210 SET_IVOR(37, 0x2a0) /* Processor Doorbell Crit */
1211
1212 /* Check MMUCFG[LPIDSIZE] to determine if we have category E.HV */
1213 mfspr r10,SPRN_MMUCFG
1214 rlwinm. r10,r10,0,MMUCFG_LPIDSIZE
1215 beqlr
1216
1217 SET_IVOR(38, 0x2c0) /* Guest Processor Doorbell */
1218 SET_IVOR(39, 0x2e0) /* Guest Processor Doorbell Crit/MC */
1219 blr
1220
1221_GLOBAL(setup_ehv_ivors)
1222 /*
1223 * We may be running as a guest and lack E.HV even on a chip
1224 * that normally has it.
1225 */
1226 mfspr r10,SPRN_MMUCFG
1227 rlwinm. r10,r10,0,MMUCFG_LPIDSIZE
1228 beqlr
1229
1230 SET_IVOR(40, 0x300) /* Embedded Hypervisor System Call */
1231 SET_IVOR(41, 0x320) /* Embedded Hypervisor Privilege */
1232 blr