0001
0002 #ifndef __HEAD_BOOKE_H__
0003 #define __HEAD_BOOKE_H__
0004
0005 #include <asm/ptrace.h> /* for STACK_FRAME_REGS_MARKER */
0006 #include <asm/kvm_asm.h>
0007 #include <asm/kvm_booke_hv_asm.h>
0008
0009 #ifdef __ASSEMBLY__
0010
0011
0012
0013
0014
0015 #define SET_IVOR(vector_number, vector_label) \
0016 li r26,vector_label@l; \
0017 mtspr SPRN_IVOR##vector_number,r26; \
0018 sync
0019
0020 #if (THREAD_SHIFT < 15)
0021 #define ALLOC_STACK_FRAME(reg, val) \
0022 addi reg,reg,val
0023 #else
0024 #define ALLOC_STACK_FRAME(reg, val) \
0025 addis reg,reg,val@ha; \
0026 addi reg,reg,val@l
0027 #endif
0028
0029
0030
0031
0032
0033
0034
0035 #define THREAD_NORMSAVE(offset) (THREAD_NORMSAVES + (offset * 4))
0036
0037 #ifdef CONFIG_PPC_FSL_BOOK3E
0038 #define BOOKE_CLEAR_BTB(reg) \
0039 START_BTB_FLUSH_SECTION \
0040 BTB_FLUSH(reg) \
0041 END_BTB_FLUSH_SECTION
0042 #else
0043 #define BOOKE_CLEAR_BTB(reg)
0044 #endif
0045
0046
0047 #define NORMAL_EXCEPTION_PROLOG(trapno, intno) \
0048 mtspr SPRN_SPRG_WSCRATCH0, r10; \
0049 mfspr r10, SPRN_SPRG_THREAD; \
0050 stw r11, THREAD_NORMSAVE(0)(r10); \
0051 stw r13, THREAD_NORMSAVE(2)(r10); \
0052 mfcr r13; \
0053 mfspr r11, SPRN_SRR1; \
0054 DO_KVM BOOKE_INTERRUPT_##intno SPRN_SRR1; \
0055 andi. r11, r11, MSR_PR; \
0056 LOAD_REG_IMMEDIATE(r11, MSR_KERNEL); \
0057 mtmsr r11; \
0058 mr r11, r1; \
0059 beq 1f; \
0060 BOOKE_CLEAR_BTB(r11) \
0061 \
0062 lwz r11, TASK_STACK - THREAD(r10); \
0063 ALLOC_STACK_FRAME(r11, THREAD_SIZE); \
0064 1 : subi r11, r11, INT_FRAME_SIZE; \
0065 stw r13, _CCR(r11); \
0066 stw r12,GPR12(r11); \
0067 stw r9,GPR9(r11); \
0068 mfspr r13, SPRN_SPRG_RSCRATCH0; \
0069 stw r13, GPR10(r11); \
0070 lwz r12, THREAD_NORMSAVE(0)(r10); \
0071 stw r12,GPR11(r11); \
0072 lwz r13, THREAD_NORMSAVE(2)(r10); \
0073 mflr r10; \
0074 stw r10,_LINK(r11); \
0075 mfspr r12,SPRN_SRR0; \
0076 stw r1, GPR1(r11); \
0077 mfspr r9,SPRN_SRR1; \
0078 stw r1, 0(r11); \
0079 mr r1, r11; \
0080 rlwinm r9,r9,0,14,12; \
0081 COMMON_EXCEPTION_PROLOG_END trapno
0082
0083 .macro COMMON_EXCEPTION_PROLOG_END trapno
0084 stw r0,GPR0(r1)
0085 lis r10, STACK_FRAME_REGS_MARKER@ha
0086 addi r10, r10, STACK_FRAME_REGS_MARKER@l
0087 stw r10, 8(r1)
0088 li r10, \trapno
0089 stw r10,_TRAP(r1)
0090 SAVE_GPRS(3, 8, r1)
0091 SAVE_NVGPRS(r1)
0092 stw r2,GPR2(r1)
0093 stw r12,_NIP(r1)
0094 stw r9,_MSR(r1)
0095 mfctr r10
0096 mfspr r2,SPRN_SPRG_THREAD
0097 stw r10,_CTR(r1)
0098 tovirt(r2, r2)
0099 mfspr r10,SPRN_XER
0100 addi r2, r2, -THREAD
0101 stw r10,_XER(r1)
0102 addi r3,r1,STACK_FRAME_OVERHEAD
0103 .endm
0104
0105 .macro prepare_transfer_to_handler
0106 #ifdef CONFIG_E500
0107 andi. r12,r9,MSR_PR
0108 bne 777f
0109 bl prepare_transfer_to_handler
0110 777:
0111 #endif
0112 .endm
0113
0114 .macro SYSCALL_ENTRY trapno intno srr1
0115 mfspr r10, SPRN_SPRG_THREAD
0116 #ifdef CONFIG_KVM_BOOKE_HV
0117 BEGIN_FTR_SECTION
0118 mtspr SPRN_SPRG_WSCRATCH0, r10
0119 stw r11, THREAD_NORMSAVE(0)(r10)
0120 stw r13, THREAD_NORMSAVE(2)(r10)
0121 mfcr r13
0122 mfspr r11, SPRN_SRR1
0123 mtocrf 0x80, r11
0124 bf 3, 1975f
0125 b kvmppc_handler_\intno\()_\srr1
0126 1975:
0127 mr r12, r13
0128 lwz r13, THREAD_NORMSAVE(2)(r10)
0129 FTR_SECTION_ELSE
0130 mfcr r12
0131 ALT_FTR_SECTION_END_IFSET(CPU_FTR_EMB_HV)
0132 #else
0133 mfcr r12
0134 #endif
0135 mfspr r9, SPRN_SRR1
0136 BOOKE_CLEAR_BTB(r11)
0137 mr r11, r1
0138 lwz r1, TASK_STACK - THREAD(r10)
0139 rlwinm r12,r12,0,4,2
0140 ALLOC_STACK_FRAME(r1, THREAD_SIZE - INT_FRAME_SIZE)
0141 stw r12, _CCR(r1)
0142 mfspr r12,SPRN_SRR0
0143 stw r12,_NIP(r1)
0144 b transfer_to_syscall
0145 .endm
0146
0147
0148
0149
0150
0151
0152
0153
0154
0155
0156
0157
0158
0159
0160
0161
0162
0163
0164 #define MC_STACK_BASE mcheckirq_ctx
0165 #define CRIT_STACK_BASE critirq_ctx
0166
0167
0168 #define DBG_STACK_BASE dbgirq_ctx
0169
0170 #ifdef CONFIG_SMP
0171 #define BOOKE_LOAD_EXC_LEVEL_STACK(level) \
0172 mfspr r8,SPRN_PIR; \
0173 slwi r8,r8,2; \
0174 addis r8,r8,level##_STACK_BASE@ha; \
0175 lwz r8,level##_STACK_BASE@l(r8); \
0176 addi r8,r8,THREAD_SIZE - INT_FRAME_SIZE;
0177 #else
0178 #define BOOKE_LOAD_EXC_LEVEL_STACK(level) \
0179 lis r8,level##_STACK_BASE@ha; \
0180 lwz r8,level##_STACK_BASE@l(r8); \
0181 addi r8,r8,THREAD_SIZE - INT_FRAME_SIZE;
0182 #endif
0183
0184
0185
0186
0187
0188
0189
0190
0191
0192 #define EXC_LEVEL_EXCEPTION_PROLOG(exc_level, trapno, intno, exc_level_srr0, exc_level_srr1) \
0193 mtspr SPRN_SPRG_WSCRATCH_##exc_level,r8; \
0194 BOOKE_LOAD_EXC_LEVEL_STACK(exc_level); \
0195 stw r9,GPR9(r8); \
0196 mfcr r9; \
0197 stw r10,GPR10(r8); \
0198 stw r11,GPR11(r8); \
0199 stw r9,_CCR(r8); \
0200 mfspr r11,exc_level_srr1; \
0201 DO_KVM BOOKE_INTERRUPT_##intno exc_level_srr1; \
0202 BOOKE_CLEAR_BTB(r10) \
0203 andi. r11,r11,MSR_PR; \
0204 LOAD_REG_IMMEDIATE(r11, MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)); \
0205 mtmsr r11; \
0206 mfspr r11,SPRN_SPRG_THREAD; \
0207 lwz r11, TASK_STACK - THREAD(r11); \
0208 addi r11,r11,THREAD_SIZE - INT_FRAME_SIZE; \
0209 beq 1f; \
0210 \
0211 stw r9,_CCR(r11); \
0212 lwz r10,GPR10(r8); \
0213 lwz r9,GPR9(r8); \
0214 stw r10,GPR10(r11); \
0215 lwz r10,GPR11(r8); \
0216 stw r9,GPR9(r11); \
0217 stw r10,GPR11(r11); \
0218 b 2f; \
0219 \
0220 1: mr r11, r8; \
0221 2: mfspr r8,SPRN_SPRG_RSCRATCH_##exc_level; \
0222 stw r12,GPR12(r11); \
0223 mflr r10; \
0224 stw r10,_LINK(r11); \
0225 mfspr r12,SPRN_DEAR; \
0226 stw r12,_DEAR(r11); \
0227 mfspr r9,SPRN_ESR; \
0228 stw r9,_ESR(r11); \
0229 mfspr r12,exc_level_srr0; \
0230 stw r1,GPR1(r11); \
0231 mfspr r9,exc_level_srr1; \
0232 stw r1,0(r11); \
0233 mr r1,r11; \
0234 rlwinm r9,r9,0,14,12; \
0235 COMMON_EXCEPTION_PROLOG_END trapno
0236
0237 #define SAVE_xSRR(xSRR) \
0238 mfspr r0,SPRN_##xSRR##0; \
0239 stw r0,_##xSRR##0(r1); \
0240 mfspr r0,SPRN_##xSRR##1; \
0241 stw r0,_##xSRR##1(r1)
0242
0243
0244 .macro SAVE_MMU_REGS
0245 #ifdef CONFIG_PPC_BOOK3E_MMU
0246 mfspr r0,SPRN_MAS0
0247 stw r0,MAS0(r1)
0248 mfspr r0,SPRN_MAS1
0249 stw r0,MAS1(r1)
0250 mfspr r0,SPRN_MAS2
0251 stw r0,MAS2(r1)
0252 mfspr r0,SPRN_MAS3
0253 stw r0,MAS3(r1)
0254 mfspr r0,SPRN_MAS6
0255 stw r0,MAS6(r1)
0256 #ifdef CONFIG_PHYS_64BIT
0257 mfspr r0,SPRN_MAS7
0258 stw r0,MAS7(r1)
0259 #endif
0260 #endif
0261 #ifdef CONFIG_44x
0262 mfspr r0,SPRN_MMUCR
0263 stw r0,MMUCR(r1)
0264 #endif
0265 .endm
0266
0267 #define CRITICAL_EXCEPTION_PROLOG(trapno, intno) \
0268 EXC_LEVEL_EXCEPTION_PROLOG(CRIT, trapno+2, intno, SPRN_CSRR0, SPRN_CSRR1)
0269 #define DEBUG_EXCEPTION_PROLOG(trapno) \
0270 EXC_LEVEL_EXCEPTION_PROLOG(DBG, trapno+8, DEBUG, SPRN_DSRR0, SPRN_DSRR1)
0271 #define MCHECK_EXCEPTION_PROLOG(trapno) \
0272 EXC_LEVEL_EXCEPTION_PROLOG(MC, trapno+4, MACHINE_CHECK, \
0273 SPRN_MCSRR0, SPRN_MCSRR1)
0274
0275
0276
0277
0278
0279
0280
0281 #define GUEST_DOORBELL_EXCEPTION \
0282 START_EXCEPTION(GuestDoorbell); \
0283 mtspr SPRN_SPRG_WSCRATCH0, r10; \
0284 mfspr r10, SPRN_SPRG_THREAD; \
0285 stw r11, THREAD_NORMSAVE(0)(r10); \
0286 mfspr r11, SPRN_SRR1; \
0287 stw r13, THREAD_NORMSAVE(2)(r10); \
0288 mfcr r13; \
0289 DO_KVM BOOKE_INTERRUPT_GUEST_DBELL SPRN_GSRR1; \
0290 trap
0291
0292
0293
0294
0295 #define START_EXCEPTION(label) \
0296 .align 5; \
0297 label:
0298
0299 #define EXCEPTION(n, intno, label, hdlr) \
0300 START_EXCEPTION(label); \
0301 NORMAL_EXCEPTION_PROLOG(n, intno); \
0302 prepare_transfer_to_handler; \
0303 bl hdlr; \
0304 b interrupt_return
0305
0306 #define CRITICAL_EXCEPTION(n, intno, label, hdlr) \
0307 START_EXCEPTION(label); \
0308 CRITICAL_EXCEPTION_PROLOG(n, intno); \
0309 SAVE_MMU_REGS; \
0310 SAVE_xSRR(SRR); \
0311 prepare_transfer_to_handler; \
0312 bl hdlr; \
0313 b ret_from_crit_exc
0314
0315 #define MCHECK_EXCEPTION(n, label, hdlr) \
0316 START_EXCEPTION(label); \
0317 MCHECK_EXCEPTION_PROLOG(n); \
0318 mfspr r5,SPRN_ESR; \
0319 stw r5,_ESR(r11); \
0320 SAVE_xSRR(DSRR); \
0321 SAVE_xSRR(CSRR); \
0322 SAVE_MMU_REGS; \
0323 SAVE_xSRR(SRR); \
0324 prepare_transfer_to_handler; \
0325 bl hdlr; \
0326 b ret_from_mcheck_exc
0327
0328
0329
0330
0331
0332
0333
0334
0335
0336
0337
0338
0339
0340
0341 #define DEBUG_DEBUG_EXCEPTION \
0342 START_EXCEPTION(DebugDebug); \
0343 DEBUG_EXCEPTION_PROLOG(2000); \
0344 \
0345
0346
0347
0348
0349
0350
0351
0352 \
0353 mfspr r10,SPRN_DBSR; \
0354 andis. r10,r10,(DBSR_IC|DBSR_BT)@h; \
0355 beq+ 2f; \
0356 \
0357 lis r10,interrupt_base@h; \
0358 ori r10,r10,interrupt_base@l; \
0359 cmplw r12,r10; \
0360 blt+ 2f; \
0361 \
0362 lis r10,interrupt_end@h; \
0363 ori r10,r10,interrupt_end@l; \
0364 cmplw r12,r10; \
0365 bgt+ 2f; \
0366 \
0367 \
0368 1: rlwinm r9,r9,0,~MSR_DE; \
0369 lis r10,(DBSR_IC|DBSR_BT)@h; \
0370 mtspr SPRN_DBSR,r10; \
0371 \
0372 lwz r10,_CCR(r11); \
0373 lwz r0,GPR0(r11); \
0374 lwz r1,GPR1(r11); \
0375 mtcrf 0x80,r10; \
0376 mtspr SPRN_DSRR0,r12; \
0377 mtspr SPRN_DSRR1,r9; \
0378 lwz r9,GPR9(r11); \
0379 lwz r12,GPR12(r11); \
0380 mtspr SPRN_SPRG_WSCRATCH_DBG,r8; \
0381 BOOKE_LOAD_EXC_LEVEL_STACK(DBG); \
0382 lwz r10,GPR10(r8); \
0383 lwz r11,GPR11(r8); \
0384 mfspr r8,SPRN_SPRG_RSCRATCH_DBG; \
0385 \
0386 PPC_RFDI; \
0387 b .; \
0388 \
0389 \
0390 2: mfspr r4,SPRN_DBSR; \
0391 stw r4,_ESR(r11); \
0392 SAVE_xSRR(CSRR); \
0393 SAVE_MMU_REGS; \
0394 SAVE_xSRR(SRR); \
0395 prepare_transfer_to_handler; \
0396 bl DebugException; \
0397 b ret_from_debug_exc
0398
0399 #define DEBUG_CRIT_EXCEPTION \
0400 START_EXCEPTION(DebugCrit); \
0401 CRITICAL_EXCEPTION_PROLOG(2000,DEBUG); \
0402 \
0403
0404
0405
0406
0407
0408
0409
0410 \
0411 mfspr r10,SPRN_DBSR; \
0412 andis. r10,r10,(DBSR_IC|DBSR_BT)@h; \
0413 beq+ 2f; \
0414 \
0415 lis r10,interrupt_base@h; \
0416 ori r10,r10,interrupt_base@l; \
0417 cmplw r12,r10; \
0418 blt+ 2f; \
0419 \
0420 lis r10,interrupt_end@h; \
0421 ori r10,r10,interrupt_end@l; \
0422 cmplw r12,r10; \
0423 bgt+ 2f; \
0424 \
0425 \
0426 1: rlwinm r9,r9,0,~MSR_DE; \
0427 lis r10,(DBSR_IC|DBSR_BT)@h; \
0428 mtspr SPRN_DBSR,r10; \
0429 \
0430 lwz r10,_CCR(r11); \
0431 lwz r0,GPR0(r11); \
0432 lwz r1,GPR1(r11); \
0433 mtcrf 0x80,r10; \
0434 mtspr SPRN_CSRR0,r12; \
0435 mtspr SPRN_CSRR1,r9; \
0436 lwz r9,GPR9(r11); \
0437 lwz r12,GPR12(r11); \
0438 mtspr SPRN_SPRG_WSCRATCH_CRIT,r8; \
0439 BOOKE_LOAD_EXC_LEVEL_STACK(CRIT); \
0440 lwz r10,GPR10(r8); \
0441 lwz r11,GPR11(r8); \
0442 mfspr r8,SPRN_SPRG_RSCRATCH_CRIT; \
0443 \
0444 rfci; \
0445 b .; \
0446 \
0447 \
0448 2: mfspr r4,SPRN_DBSR; \
0449 stw r4,_ESR(r11); \
0450 SAVE_MMU_REGS; \
0451 SAVE_xSRR(SRR); \
0452 prepare_transfer_to_handler; \
0453 bl DebugException; \
0454 b ret_from_crit_exc
0455
0456 #define DATA_STORAGE_EXCEPTION \
0457 START_EXCEPTION(DataStorage) \
0458 NORMAL_EXCEPTION_PROLOG(0x300, DATA_STORAGE); \
0459 mfspr r5,SPRN_ESR; \
0460 stw r5,_ESR(r11); \
0461 mfspr r4,SPRN_DEAR; \
0462 stw r4, _DEAR(r11); \
0463 prepare_transfer_to_handler; \
0464 bl do_page_fault; \
0465 b interrupt_return
0466
0467
0468
0469
0470
0471
0472
0473
0474
0475
0476 #define INSTRUCTION_STORAGE_EXCEPTION \
0477 START_EXCEPTION(InstructionStorage) \
0478 NORMAL_EXCEPTION_PROLOG(0x400, INST_STORAGE); \
0479 li r5,0; \
0480 stw r5,_ESR(r11); \
0481 stw r12, _DEAR(r11); \
0482 prepare_transfer_to_handler; \
0483 bl do_page_fault; \
0484 b interrupt_return
0485
0486 #define ALIGNMENT_EXCEPTION \
0487 START_EXCEPTION(Alignment) \
0488 NORMAL_EXCEPTION_PROLOG(0x600, ALIGNMENT); \
0489 mfspr r4,SPRN_DEAR; \
0490 stw r4,_DEAR(r11); \
0491 prepare_transfer_to_handler; \
0492 bl alignment_exception; \
0493 REST_NVGPRS(r1); \
0494 b interrupt_return
0495
0496 #define PROGRAM_EXCEPTION \
0497 START_EXCEPTION(Program) \
0498 NORMAL_EXCEPTION_PROLOG(0x700, PROGRAM); \
0499 mfspr r4,SPRN_ESR; \
0500 stw r4,_ESR(r11); \
0501 prepare_transfer_to_handler; \
0502 bl program_check_exception; \
0503 REST_NVGPRS(r1); \
0504 b interrupt_return
0505
0506 #define DECREMENTER_EXCEPTION \
0507 START_EXCEPTION(Decrementer) \
0508 NORMAL_EXCEPTION_PROLOG(0x900, DECREMENTER); \
0509 lis r0,TSR_DIS@h; \
0510 mtspr SPRN_TSR,r0; \
0511 prepare_transfer_to_handler; \
0512 bl timer_interrupt; \
0513 b interrupt_return
0514
0515 #define FP_UNAVAILABLE_EXCEPTION \
0516 START_EXCEPTION(FloatingPointUnavailable) \
0517 NORMAL_EXCEPTION_PROLOG(0x800, FP_UNAVAIL); \
0518 beq 1f; \
0519 bl load_up_fpu; \
0520 b fast_exception_return; \
0521 1: prepare_transfer_to_handler; \
0522 bl kernel_fp_unavailable_exception; \
0523 b interrupt_return
0524
0525 #endif
0526 #endif