aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel
diff options
context:
space:
mode:
authorKumar Gala <galak@kernel.crashing.org>2008-07-09 11:03:28 -0400
committerKumar Gala <galak@kernel.crashing.org>2008-07-16 18:57:51 -0400
commit6cfd8990e27d3a491c1c605d6cbc18a46ae51fef (patch)
tree89ff46a4d744fa20e236186deef82971a36e9498 /arch/powerpc/kernel
parent2d07db33d1875dcaada8eb7e69c68aeede722bb5 (diff)
powerpc: rework FSL Book-E PTE access and TLB miss
This converts the FSL Book-E PTE access and TLB miss handling to match with the recent changes to 44x that introduce support for non-atomic PTE operations in pgtable-ppc32.h and removes write back to the PTE from the TLB miss handlers. In addition, the DSI interrupt code no longer tries to fixup write permission, this is left to generic code, and _PAGE_HWWRITE is gone. Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
Diffstat (limited to 'arch/powerpc/kernel')
-rw-r--r--arch/powerpc/kernel/head_fsl_booke.S168
1 files changed, 44 insertions, 124 deletions
diff --git a/arch/powerpc/kernel/head_fsl_booke.S b/arch/powerpc/kernel/head_fsl_booke.S
index c4268500e856..7d554968b635 100644
--- a/arch/powerpc/kernel/head_fsl_booke.S
+++ b/arch/powerpc/kernel/head_fsl_booke.S
@@ -483,90 +483,16 @@ interrupt_base:
483 483
484 /* Data Storage Interrupt */ 484 /* Data Storage Interrupt */
485 START_EXCEPTION(DataStorage) 485 START_EXCEPTION(DataStorage)
486 mtspr SPRN_SPRG0, r10 /* Save some working registers */ 486 NORMAL_EXCEPTION_PROLOG
487 mtspr SPRN_SPRG1, r11 487 mfspr r5,SPRN_ESR /* Grab the ESR, save it, pass arg3 */
488 mtspr SPRN_SPRG4W, r12 488 stw r5,_ESR(r11)
489 mtspr SPRN_SPRG5W, r13 489 mfspr r4,SPRN_DEAR /* Grab the DEAR, save it, pass arg2 */
490 mfcr r11 490 andis. r10,r5,(ESR_ILK|ESR_DLK)@h
491 mtspr SPRN_SPRG7W, r11 491 bne 1f
492 492 EXC_XFER_EE_LITE(0x0300, handle_page_fault)
493 /* 4931:
494 * Check if it was a store fault, if not then bail 494 addi r3,r1,STACK_FRAME_OVERHEAD
495 * because a user tried to access a kernel or 495 EXC_XFER_EE_LITE(0x0300, CacheLockingException)
496 * read-protected page. Otherwise, get the
497 * offending address and handle it.
498 */
499 mfspr r10, SPRN_ESR
500 andis. r10, r10, ESR_ST@h
501 beq 2f
502
503 mfspr r10, SPRN_DEAR /* Get faulting address */
504
505 /* If we are faulting a kernel address, we have to use the
506 * kernel page tables.
507 */
508 lis r11, PAGE_OFFSET@h
509 cmplw 0, r10, r11
510 bge 2f
511
512 /* Get the PGD for the current thread */
5133:
514 mfspr r11,SPRN_SPRG3
515 lwz r11,PGDIR(r11)
5164:
517 FIND_PTE
518
519 /* Are _PAGE_USER & _PAGE_RW set & _PAGE_HWWRITE not? */
520 andi. r13, r11, _PAGE_RW|_PAGE_USER|_PAGE_HWWRITE
521 cmpwi 0, r13, _PAGE_RW|_PAGE_USER
522 bne 2f /* Bail if not */
523
524 /* Update 'changed'. */
525 ori r11, r11, _PAGE_DIRTY|_PAGE_ACCESSED|_PAGE_HWWRITE
526 stw r11, PTE_FLAGS_OFFSET(r12) /* Update Linux page table */
527
528 /* MAS2 not updated as the entry does exist in the tlb, this
529 fault taken to detect state transition (eg: COW -> DIRTY)
530 */
531 andi. r11, r11, _PAGE_HWEXEC
532 rlwimi r11, r11, 31, 27, 27 /* SX <- _PAGE_HWEXEC */
533 ori r11, r11, (MAS3_UW|MAS3_SW|MAS3_UR|MAS3_SR)@l /* set static perms */
534
535 /* update search PID in MAS6, AS = 0 */
536 mfspr r12, SPRN_PID0
537 slwi r12, r12, 16
538 mtspr SPRN_MAS6, r12
539
540 /* find the TLB index that caused the fault. It has to be here. */
541 tlbsx 0, r10
542
543 /* only update the perm bits, assume the RPN is fine */
544 mfspr r12, SPRN_MAS3
545 rlwimi r12, r11, 0, 20, 31
546 mtspr SPRN_MAS3,r12
547 tlbwe
548
549 /* Done...restore registers and get out of here. */
550 mfspr r11, SPRN_SPRG7R
551 mtcr r11
552 mfspr r13, SPRN_SPRG5R
553 mfspr r12, SPRN_SPRG4R
554 mfspr r11, SPRN_SPRG1
555 mfspr r10, SPRN_SPRG0
556 rfi /* Force context change */
557
5582:
559 /*
560 * The bailout. Restore registers to pre-exception conditions
561 * and call the heavyweights to help us out.
562 */
563 mfspr r11, SPRN_SPRG7R
564 mtcr r11
565 mfspr r13, SPRN_SPRG5R
566 mfspr r12, SPRN_SPRG4R
567 mfspr r11, SPRN_SPRG1
568 mfspr r10, SPRN_SPRG0
569 b data_access
570 496
571 /* Instruction Storage Interrupt */ 497 /* Instruction Storage Interrupt */
572 INSTRUCTION_STORAGE_EXCEPTION 498 INSTRUCTION_STORAGE_EXCEPTION
@@ -645,15 +571,30 @@ interrupt_base:
645 lwz r11,PGDIR(r11) 571 lwz r11,PGDIR(r11)
646 572
6474: 5734:
574 /* Mask of required permission bits. Note that while we
575 * do copy ESR:ST to _PAGE_RW position as trying to write
576 * to an RO page is pretty common, we don't do it with
577 * _PAGE_DIRTY. We could do it, but it's a fairly rare
578 * event so I'd rather take the overhead when it happens
579 * rather than adding an instruction here. We should measure
580 * whether the whole thing is worth it in the first place
581 * as we could avoid loading SPRN_ESR completely in the first
582 * place...
583 *
584 * TODO: Is it worth doing that mfspr & rlwimi in the first
585 * place or can we save a couple of instructions here ?
586 */
587 mfspr r12,SPRN_ESR
588 li r13,_PAGE_PRESENT|_PAGE_ACCESSED
589 rlwimi r13,r12,11,29,29
590
648 FIND_PTE 591 FIND_PTE
649 andi. r13, r11, _PAGE_PRESENT /* Is the page present? */ 592 andc. r13,r13,r11 /* Check permission */
650 beq 2f /* Bail if not present */ 593 bne 2f /* Bail if permission mismach */
651 594
652#ifdef CONFIG_PTE_64BIT 595#ifdef CONFIG_PTE_64BIT
653 lwz r13, 0(r12) 596 lwz r13, 0(r12)
654#endif 597#endif
655 ori r11, r11, _PAGE_ACCESSED
656 stw r11, PTE_FLAGS_OFFSET(r12)
657 598
658 /* Jump to common tlb load */ 599 /* Jump to common tlb load */
659 b finish_tlb_load 600 b finish_tlb_load
@@ -667,7 +608,7 @@ interrupt_base:
667 mfspr r12, SPRN_SPRG4R 608 mfspr r12, SPRN_SPRG4R
668 mfspr r11, SPRN_SPRG1 609 mfspr r11, SPRN_SPRG1
669 mfspr r10, SPRN_SPRG0 610 mfspr r10, SPRN_SPRG0
670 b data_access 611 b DataStorage
671 612
672 /* Instruction TLB Error Interrupt */ 613 /* Instruction TLB Error Interrupt */
673 /* 614 /*
@@ -705,15 +646,16 @@ interrupt_base:
705 lwz r11,PGDIR(r11) 646 lwz r11,PGDIR(r11)
706 647
7074: 6484:
649 /* Make up the required permissions */
650 li r13,_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_HWEXEC
651
708 FIND_PTE 652 FIND_PTE
709 andi. r13, r11, _PAGE_PRESENT /* Is the page present? */ 653 andc. r13,r13,r11 /* Check permission */
710 beq 2f /* Bail if not present */ 654 bne 2f /* Bail if permission mismach */
711 655
712#ifdef CONFIG_PTE_64BIT 656#ifdef CONFIG_PTE_64BIT
713 lwz r13, 0(r12) 657 lwz r13, 0(r12)
714#endif 658#endif
715 ori r11, r11, _PAGE_ACCESSED
716 stw r11, PTE_FLAGS_OFFSET(r12)
717 659
718 /* Jump to common TLB load point */ 660 /* Jump to common TLB load point */
719 b finish_tlb_load 661 b finish_tlb_load
@@ -768,29 +710,13 @@ interrupt_base:
768 * Local functions 710 * Local functions
769 */ 711 */
770 712
771 /*
772 * Data TLB exceptions will bail out to this point
773 * if they can't resolve the lightweight TLB fault.
774 */
775data_access:
776 NORMAL_EXCEPTION_PROLOG
777 mfspr r5,SPRN_ESR /* Grab the ESR, save it, pass arg3 */
778 stw r5,_ESR(r11)
779 mfspr r4,SPRN_DEAR /* Grab the DEAR, save it, pass arg2 */
780 andis. r10,r5,(ESR_ILK|ESR_DLK)@h
781 bne 1f
782 EXC_XFER_EE_LITE(0x0300, handle_page_fault)
7831:
784 addi r3,r1,STACK_FRAME_OVERHEAD
785 EXC_XFER_EE_LITE(0x0300, CacheLockingException)
786
787/* 713/*
788
789 * Both the instruction and data TLB miss get to this 714 * Both the instruction and data TLB miss get to this
790 * point to load the TLB. 715 * point to load the TLB.
791 * r10 - EA of fault 716 * r10 - EA of fault
792 * r11 - TLB (info from Linux PTE) 717 * r11 - TLB (info from Linux PTE)
793 * r12, r13 - available to use 718 * r12 - available to use
719 * r13 - upper bits of PTE (if PTE_64BIT) or available to use
794 * CR5 - results of addr >= PAGE_OFFSET 720 * CR5 - results of addr >= PAGE_OFFSET
795 * MAS0, MAS1 - loaded with proper value when we get here 721 * MAS0, MAS1 - loaded with proper value when we get here
796 * MAS2, MAS3 - will need additional info from Linux PTE 722 * MAS2, MAS3 - will need additional info from Linux PTE
@@ -812,20 +738,14 @@ finish_tlb_load:
812#endif 738#endif
813 mtspr SPRN_MAS2, r12 739 mtspr SPRN_MAS2, r12
814 740
815 bge 5, 1f 741 li r10, (_PAGE_HWEXEC | _PAGE_PRESENT)
816 742 rlwimi r10, r11, 31, 29, 29 /* extract _PAGE_DIRTY into SW */
817 /* is user addr */ 743 and r12, r11, r10
818 andi. r12, r11, (_PAGE_USER | _PAGE_HWWRITE | _PAGE_HWEXEC)
819 andi. r10, r11, _PAGE_USER /* Test for _PAGE_USER */ 744 andi. r10, r11, _PAGE_USER /* Test for _PAGE_USER */
820 srwi r10, r12, 1 745 slwi r10, r12, 1
821 or r12, r12, r10 /* Copy user perms into supervisor */ 746 or r10, r10, r12
822 iseleq r12, 0, r12 747 iseleq r12, r12, r10
823 b 2f 748
824
825 /* is kernel addr */
8261: rlwinm r12, r11, 31, 29, 29 /* Extract _PAGE_HWWRITE into SW */
827 ori r12, r12, (MAS3_SX | MAS3_SR)
828
829#ifdef CONFIG_PTE_64BIT 749#ifdef CONFIG_PTE_64BIT
8302: rlwimi r12, r13, 24, 0, 7 /* grab RPN[32:39] */ 7502: rlwimi r12, r13, 24, 0, 7 /* grab RPN[32:39] */
831 rlwimi r12, r11, 24, 8, 19 /* grab RPN[40:51] */ 751 rlwimi r12, r11, 24, 8, 19 /* grab RPN[40:51] */