diff options
Diffstat (limited to 'arch/powerpc/kernel/head_8xx.S')
-rw-r--r-- | arch/powerpc/kernel/head_8xx.S | 150 |
1 files changed, 56 insertions, 94 deletions
diff --git a/arch/powerpc/kernel/head_8xx.S b/arch/powerpc/kernel/head_8xx.S index 7ee876d2adb5..fafff8dbd5d9 100644 --- a/arch/powerpc/kernel/head_8xx.S +++ b/arch/powerpc/kernel/head_8xx.S | |||
@@ -104,12 +104,15 @@ turn_on_mmu: | |||
104 | * task's thread_struct. | 104 | * task's thread_struct. |
105 | */ | 105 | */ |
106 | #define EXCEPTION_PROLOG \ | 106 | #define EXCEPTION_PROLOG \ |
107 | mtspr SPRN_SPRG_SCRATCH0,r10; \ | 107 | EXCEPTION_PROLOG_0; \ |
108 | mtspr SPRN_SPRG_SCRATCH1,r11; \ | ||
109 | mfcr r10; \ | ||
110 | EXCEPTION_PROLOG_1; \ | 108 | EXCEPTION_PROLOG_1; \ |
111 | EXCEPTION_PROLOG_2 | 109 | EXCEPTION_PROLOG_2 |
112 | 110 | ||
111 | #define EXCEPTION_PROLOG_0 \ | ||
112 | mtspr SPRN_SPRG_SCRATCH0,r10; \ | ||
113 | mtspr SPRN_SPRG_SCRATCH1,r11; \ | ||
114 | mfcr r10 | ||
115 | |||
113 | #define EXCEPTION_PROLOG_1 \ | 116 | #define EXCEPTION_PROLOG_1 \ |
114 | mfspr r11,SPRN_SRR1; /* check whether user or kernel */ \ | 117 | mfspr r11,SPRN_SRR1; /* check whether user or kernel */ \ |
115 | andi. r11,r11,MSR_PR; \ | 118 | andi. r11,r11,MSR_PR; \ |
@@ -145,6 +148,14 @@ turn_on_mmu: | |||
145 | SAVE_2GPRS(7, r11) | 148 | SAVE_2GPRS(7, r11) |
146 | 149 | ||
147 | /* | 150 | /* |
151 | * Exception exit code. | ||
152 | */ | ||
153 | #define EXCEPTION_EPILOG_0 \ | ||
154 | mtcr r10; \ | ||
155 | mfspr r10,SPRN_SPRG_SCRATCH0; \ | ||
156 | mfspr r11,SPRN_SPRG_SCRATCH1 | ||
157 | |||
158 | /* | ||
148 | * Note: code which follows this uses cr0.eq (set if from kernel), | 159 | * Note: code which follows this uses cr0.eq (set if from kernel), |
149 | * r11, r12 (SRR0), and r9 (SRR1). | 160 | * r11, r12 (SRR0), and r9 (SRR1). |
150 | * | 161 | * |
@@ -293,16 +304,8 @@ InstructionTLBMiss: | |||
293 | #ifdef CONFIG_8xx_CPU6 | 304 | #ifdef CONFIG_8xx_CPU6 |
294 | stw r3, 8(r0) | 305 | stw r3, 8(r0) |
295 | #endif | 306 | #endif |
296 | DO_8xx_CPU6(0x3f80, r3) | 307 | EXCEPTION_PROLOG_0 |
297 | mtspr SPRN_M_TW, r10 /* Save a couple of working registers */ | 308 | mtspr SPRN_SPRG_SCRATCH2, r10 |
298 | mfcr r10 | ||
299 | #ifdef CONFIG_8xx_CPU6 | ||
300 | stw r10, 0(r0) | ||
301 | stw r11, 4(r0) | ||
302 | #else | ||
303 | mtspr SPRN_DAR, r10 | ||
304 | mtspr SPRN_SPRG2, r11 | ||
305 | #endif | ||
306 | mfspr r10, SPRN_SRR0 /* Get effective address of fault */ | 309 | mfspr r10, SPRN_SRR0 /* Get effective address of fault */ |
307 | #ifdef CONFIG_8xx_CPU15 | 310 | #ifdef CONFIG_8xx_CPU15 |
308 | addi r11, r10, 0x1000 | 311 | addi r11, r10, 0x1000 |
@@ -359,18 +362,11 @@ InstructionTLBMiss: | |||
359 | mtspr SPRN_MI_RPN, r10 /* Update TLB entry */ | 362 | mtspr SPRN_MI_RPN, r10 /* Update TLB entry */ |
360 | 363 | ||
361 | /* Restore registers */ | 364 | /* Restore registers */ |
362 | #ifndef CONFIG_8xx_CPU6 | 365 | #ifdef CONFIG_8xx_CPU6 |
363 | mfspr r10, SPRN_DAR | ||
364 | mtcr r10 | ||
365 | mtspr SPRN_DAR, r11 /* Tag DAR */ | ||
366 | mfspr r11, SPRN_SPRG2 | ||
367 | #else | ||
368 | lwz r11, 0(r0) | ||
369 | mtcr r11 | ||
370 | lwz r11, 4(r0) | ||
371 | lwz r3, 8(r0) | 366 | lwz r3, 8(r0) |
372 | #endif | 367 | #endif |
373 | mfspr r10, SPRN_M_TW | 368 | mfspr r10, SPRN_SPRG_SCRATCH2 |
369 | EXCEPTION_EPILOG_0 | ||
374 | rfi | 370 | rfi |
375 | 2: | 371 | 2: |
376 | mfspr r11, SPRN_SRR1 | 372 | mfspr r11, SPRN_SRR1 |
@@ -381,19 +377,11 @@ InstructionTLBMiss: | |||
381 | mtspr SPRN_SRR1, r11 | 377 | mtspr SPRN_SRR1, r11 |
382 | 378 | ||
383 | /* Restore registers */ | 379 | /* Restore registers */ |
384 | #ifndef CONFIG_8xx_CPU6 | 380 | #ifdef CONFIG_8xx_CPU6 |
385 | mfspr r10, SPRN_DAR | ||
386 | mtcr r10 | ||
387 | li r11, 0x00f0 | ||
388 | mtspr SPRN_DAR, r11 /* Tag DAR */ | ||
389 | mfspr r11, SPRN_SPRG2 | ||
390 | #else | ||
391 | lwz r11, 0(r0) | ||
392 | mtcr r11 | ||
393 | lwz r11, 4(r0) | ||
394 | lwz r3, 8(r0) | 381 | lwz r3, 8(r0) |
395 | #endif | 382 | #endif |
396 | mfspr r10, SPRN_M_TW | 383 | mfspr r10, SPRN_SPRG_SCRATCH2 |
384 | EXCEPTION_EPILOG_0 | ||
397 | b InstructionAccess | 385 | b InstructionAccess |
398 | 386 | ||
399 | . = 0x1200 | 387 | . = 0x1200 |
@@ -401,16 +389,8 @@ DataStoreTLBMiss: | |||
401 | #ifdef CONFIG_8xx_CPU6 | 389 | #ifdef CONFIG_8xx_CPU6 |
402 | stw r3, 8(r0) | 390 | stw r3, 8(r0) |
403 | #endif | 391 | #endif |
404 | DO_8xx_CPU6(0x3f80, r3) | 392 | EXCEPTION_PROLOG_0 |
405 | mtspr SPRN_M_TW, r10 /* Save a couple of working registers */ | 393 | mtspr SPRN_SPRG_SCRATCH2, r10 |
406 | mfcr r10 | ||
407 | #ifdef CONFIG_8xx_CPU6 | ||
408 | stw r10, 0(r0) | ||
409 | stw r11, 4(r0) | ||
410 | #else | ||
411 | mtspr SPRN_DAR, r10 | ||
412 | mtspr SPRN_SPRG2, r11 | ||
413 | #endif | ||
414 | mfspr r10, SPRN_M_TWB /* Get level 1 table entry address */ | 394 | mfspr r10, SPRN_M_TWB /* Get level 1 table entry address */ |
415 | 395 | ||
416 | /* If we are faulting a kernel address, we have to use the | 396 | /* If we are faulting a kernel address, we have to use the |
@@ -483,19 +463,12 @@ DataStoreTLBMiss: | |||
483 | mtspr SPRN_MD_RPN, r10 /* Update TLB entry */ | 463 | mtspr SPRN_MD_RPN, r10 /* Update TLB entry */ |
484 | 464 | ||
485 | /* Restore registers */ | 465 | /* Restore registers */ |
486 | #ifndef CONFIG_8xx_CPU6 | 466 | #ifdef CONFIG_8xx_CPU6 |
487 | mfspr r10, SPRN_DAR | ||
488 | mtcr r10 | ||
489 | mtspr SPRN_DAR, r11 /* Tag DAR */ | ||
490 | mfspr r11, SPRN_SPRG2 | ||
491 | #else | ||
492 | mtspr SPRN_DAR, r11 /* Tag DAR */ | ||
493 | lwz r11, 0(r0) | ||
494 | mtcr r11 | ||
495 | lwz r11, 4(r0) | ||
496 | lwz r3, 8(r0) | 467 | lwz r3, 8(r0) |
497 | #endif | 468 | #endif |
498 | mfspr r10, SPRN_M_TW | 469 | mtspr SPRN_DAR, r11 /* Tag DAR */ |
470 | mfspr r10, SPRN_SPRG_SCRATCH2 | ||
471 | EXCEPTION_EPILOG_0 | ||
499 | rfi | 472 | rfi |
500 | 473 | ||
501 | /* This is an instruction TLB error on the MPC8xx. This could be due | 474 | /* This is an instruction TLB error on the MPC8xx. This could be due |
@@ -507,35 +480,18 @@ InstructionTLBError: | |||
507 | b InstructionAccess | 480 | b InstructionAccess |
508 | 481 | ||
509 | /* This is the data TLB error on the MPC8xx. This could be due to | 482 | /* This is the data TLB error on the MPC8xx. This could be due to |
510 | * many reasons, including a dirty update to a pte. We can catch that | 483 | * many reasons, including a dirty update to a pte. We bail out to |
511 | * one here, but anything else is an error. First, we track down the | 484 | * a higher level function that can handle it. |
512 | * Linux pte. If it is valid, write access is allowed, but the | ||
513 | * page dirty bit is not set, we will set it and reload the TLB. For | ||
514 | * any other case, we bail out to a higher level function that can | ||
515 | * handle it. | ||
516 | */ | 485 | */ |
517 | . = 0x1400 | 486 | . = 0x1400 |
518 | DataTLBError: | 487 | DataTLBError: |
519 | #ifdef CONFIG_8xx_CPU6 | 488 | EXCEPTION_PROLOG_0 |
520 | stw r3, 8(r0) | ||
521 | #endif | ||
522 | DO_8xx_CPU6(0x3f80, r3) | ||
523 | mtspr SPRN_M_TW, r10 /* Save a couple of working registers */ | ||
524 | mfcr r10 | ||
525 | stw r10, 0(r0) | ||
526 | stw r11, 4(r0) | ||
527 | 489 | ||
528 | mfspr r10, SPRN_DAR | 490 | mfspr r11, SPRN_DAR |
529 | cmpwi cr0, r10, 0x00f0 | 491 | cmpwi cr0, r11, 0x00f0 |
530 | beq- FixupDAR /* must be a buggy dcbX, icbi insn. */ | 492 | beq- FixupDAR /* must be a buggy dcbX, icbi insn. */ |
531 | DARFixed:/* Return from dcbx instruction bug workaround, r10 holds value of DAR */ | 493 | DARFixed:/* Return from dcbx instruction bug workaround */ |
532 | mfspr r10, SPRN_M_TW /* Restore registers */ | 494 | EXCEPTION_EPILOG_0 |
533 | lwz r11, 0(r0) | ||
534 | mtcr r11 | ||
535 | lwz r11, 4(r0) | ||
536 | #ifdef CONFIG_8xx_CPU6 | ||
537 | lwz r3, 8(r0) | ||
538 | #endif | ||
539 | b DataAccess | 495 | b DataAccess |
540 | 496 | ||
541 | EXCEPTION(0x1500, Trap_15, unknown_exception, EXC_XFER_EE) | 497 | EXCEPTION(0x1500, Trap_15, unknown_exception, EXC_XFER_EE) |
@@ -559,11 +515,15 @@ DARFixed:/* Return from dcbx instruction bug workaround, r10 holds value of DAR | |||
559 | 515 | ||
560 | /* This is the procedure to calculate the data EA for buggy dcbx,dcbi instructions | 516 | /* This is the procedure to calculate the data EA for buggy dcbx,dcbi instructions |
561 | * by decoding the registers used by the dcbx instruction and adding them. | 517 | * by decoding the registers used by the dcbx instruction and adding them. |
562 | * DAR is set to the calculated address and r10 also holds the EA on exit. | 518 | * DAR is set to the calculated address. |
563 | */ | 519 | */ |
564 | /* define if you don't want to use self modifying code */ | 520 | /* define if you don't want to use self modifying code */ |
565 | #define NO_SELF_MODIFYING_CODE | 521 | #define NO_SELF_MODIFYING_CODE |
566 | FixupDAR:/* Entry point for dcbx workaround. */ | 522 | FixupDAR:/* Entry point for dcbx workaround. */ |
523 | #ifdef CONFIG_8xx_CPU6 | ||
524 | stw r3, 8(r0) | ||
525 | #endif | ||
526 | mtspr SPRN_SPRG_SCRATCH2, r10 | ||
567 | /* fetch instruction from memory. */ | 527 | /* fetch instruction from memory. */ |
568 | mfspr r10, SPRN_SRR0 | 528 | mfspr r10, SPRN_SRR0 |
569 | andis. r11, r10, 0x8000 /* Address >= 0x80000000 */ | 529 | andis. r11, r10, 0x8000 /* Address >= 0x80000000 */ |
@@ -579,16 +539,17 @@ FixupDAR:/* Entry point for dcbx workaround. */ | |||
579 | mtspr SPRN_MD_TWC, r11 /* Load pte table base address */ | 539 | mtspr SPRN_MD_TWC, r11 /* Load pte table base address */ |
580 | mfspr r11, SPRN_MD_TWC /* ....and get the pte address */ | 540 | mfspr r11, SPRN_MD_TWC /* ....and get the pte address */ |
581 | lwz r11, 0(r11) /* Get the pte */ | 541 | lwz r11, 0(r11) /* Get the pte */ |
542 | #ifdef CONFIG_8xx_CPU6 | ||
543 | lwz r3, 8(r0) /* restore r3 from memory */ | ||
544 | #endif | ||
582 | /* concat physical page address(r11) and page offset(r10) */ | 545 | /* concat physical page address(r11) and page offset(r10) */ |
583 | rlwimi r11, r10, 0, 20, 31 | 546 | rlwimi r11, r10, 0, 20, 31 |
584 | lwz r11,0(r11) | 547 | lwz r11,0(r11) |
585 | /* Check if it really is a dcbx instruction. */ | 548 | /* Check if it really is a dcbx instruction. */ |
586 | /* dcbt and dcbtst does not generate DTLB Misses/Errors, | 549 | /* dcbt and dcbtst does not generate DTLB Misses/Errors, |
587 | * no need to include them here */ | 550 | * no need to include them here */ |
588 | srwi r10, r11, 26 /* check if major OP code is 31 */ | 551 | xoris r10, r11, 0x7c00 /* check if major OP code is 31 */ |
589 | cmpwi cr0, r10, 31 | 552 | rlwinm r10, r10, 0, 21, 5 |
590 | bne- 141f | ||
591 | rlwinm r10, r11, 0, 21, 30 | ||
592 | cmpwi cr0, r10, 2028 /* Is dcbz? */ | 553 | cmpwi cr0, r10, 2028 /* Is dcbz? */ |
593 | beq+ 142f | 554 | beq+ 142f |
594 | cmpwi cr0, r10, 940 /* Is dcbi? */ | 555 | cmpwi cr0, r10, 940 /* Is dcbi? */ |
@@ -599,16 +560,13 @@ FixupDAR:/* Entry point for dcbx workaround. */ | |||
599 | beq+ 142f | 560 | beq+ 142f |
600 | cmpwi cr0, r10, 1964 /* Is icbi? */ | 561 | cmpwi cr0, r10, 1964 /* Is icbi? */ |
601 | beq+ 142f | 562 | beq+ 142f |
602 | 141: mfspr r10, SPRN_DAR /* r10 must hold DAR at exit */ | 563 | 141: mfspr r10,SPRN_SPRG_SCRATCH2 |
603 | b DARFixed /* Nope, go back to normal TLB processing */ | 564 | b DARFixed /* Nope, go back to normal TLB processing */ |
604 | 565 | ||
605 | 144: mfspr r10, SPRN_DSISR | 566 | 144: mfspr r10, SPRN_DSISR |
606 | rlwinm r10, r10,0,7,5 /* Clear store bit for buggy dcbst insn */ | 567 | rlwinm r10, r10,0,7,5 /* Clear store bit for buggy dcbst insn */ |
607 | mtspr SPRN_DSISR, r10 | 568 | mtspr SPRN_DSISR, r10 |
608 | 142: /* continue, it was a dcbx, dcbi instruction. */ | 569 | 142: /* continue, it was a dcbx, dcbi instruction. */ |
609 | #ifdef CONFIG_8xx_CPU6 | ||
610 | lwz r3, 8(r0) /* restore r3 from memory */ | ||
611 | #endif | ||
612 | #ifndef NO_SELF_MODIFYING_CODE | 570 | #ifndef NO_SELF_MODIFYING_CODE |
613 | andis. r10,r11,0x1f /* test if reg RA is r0 */ | 571 | andis. r10,r11,0x1f /* test if reg RA is r0 */ |
614 | li r10,modified_instr@l | 572 | li r10,modified_instr@l |
@@ -619,14 +577,15 @@ FixupDAR:/* Entry point for dcbx workaround. */ | |||
619 | stw r11,0(r10) /* store add/and instruction */ | 577 | stw r11,0(r10) /* store add/and instruction */ |
620 | dcbf 0,r10 /* flush new instr. to memory. */ | 578 | dcbf 0,r10 /* flush new instr. to memory. */ |
621 | icbi 0,r10 /* invalidate instr. cache line */ | 579 | icbi 0,r10 /* invalidate instr. cache line */ |
622 | lwz r11, 4(r0) /* restore r11 from memory */ | 580 | mfspr r11, SPRN_SPRG_SCRATCH1 /* restore r11 */ |
623 | mfspr r10, SPRN_M_TW /* restore r10 from M_TW */ | 581 | mfspr r10, SPRN_SPRG_SCRATCH0 /* restore r10 */ |
624 | isync /* Wait until new instr is loaded from memory */ | 582 | isync /* Wait until new instr is loaded from memory */ |
625 | modified_instr: | 583 | modified_instr: |
626 | .space 4 /* this is where the add instr. is stored */ | 584 | .space 4 /* this is where the add instr. is stored */ |
627 | bne+ 143f | 585 | bne+ 143f |
628 | subf r10,r0,r10 /* r10=r10-r0, only if reg RA is r0 */ | 586 | subf r10,r0,r10 /* r10=r10-r0, only if reg RA is r0 */ |
629 | 143: mtdar r10 /* store faulting EA in DAR */ | 587 | 143: mtdar r10 /* store faulting EA in DAR */ |
588 | mfspr r10,SPRN_SPRG_SCRATCH2 | ||
630 | b DARFixed /* Go back to normal TLB handling */ | 589 | b DARFixed /* Go back to normal TLB handling */ |
631 | #else | 590 | #else |
632 | mfctr r10 | 591 | mfctr r10 |
@@ -680,13 +639,16 @@ modified_instr: | |||
680 | mfdar r11 | 639 | mfdar r11 |
681 | mtctr r11 /* restore ctr reg from DAR */ | 640 | mtctr r11 /* restore ctr reg from DAR */ |
682 | mtdar r10 /* save fault EA to DAR */ | 641 | mtdar r10 /* save fault EA to DAR */ |
642 | mfspr r10,SPRN_SPRG_SCRATCH2 | ||
683 | b DARFixed /* Go back to normal TLB handling */ | 643 | b DARFixed /* Go back to normal TLB handling */ |
684 | 644 | ||
685 | /* special handling for r10,r11 since these are modified already */ | 645 | /* special handling for r10,r11 since these are modified already */ |
686 | 153: lwz r11, 4(r0) /* load r11 from memory */ | 646 | 153: mfspr r11, SPRN_SPRG_SCRATCH1 /* load r11 from SPRN_SPRG_SCRATCH1 */ |
687 | b 155f | 647 | add r10, r10, r11 /* add it */ |
688 | 154: mfspr r11, SPRN_M_TW /* load r10 from M_TW */ | 648 | mfctr r11 /* restore r11 */ |
689 | 155: add r10, r10, r11 /* add it */ | 649 | b 151b |
650 | 154: mfspr r11, SPRN_SPRG_SCRATCH0 /* load r10 from SPRN_SPRG_SCRATCH0 */ | ||
651 | add r10, r10, r11 /* add it */ | ||
690 | mfctr r11 /* restore r11 */ | 652 | mfctr r11 /* restore r11 */ |
691 | b 151b | 653 | b 151b |
692 | #endif | 654 | #endif |