diff options
author | Kumar Gala <galak@freescale.com> | 2005-04-16 18:24:22 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:24:22 -0400 |
commit | f50b153b1966230e78034d5ab1641ca4bb5db56d (patch) | |
tree | 9f3f0971789ca2cbb59efbd694c172804f4547cd /arch/ppc | |
parent | b464fce5edc08a825907e9d48a2d2f1af0393fef (diff) |
[PATCH] ppc32: Support 36-bit physical addressing on e500
To add support for 36-bit physical addressing on e500 the following changes
have been made. The changes are generalized to support any physical address
size larger than 32-bits:
* Allow FSL Book-E parts to use a 64-bit PTE, it is 44-bits of pfn, 20-bits
of flags.
* Introduced new CPU feature (CPU_FTR_BIG_PHYS) to allow runtime handling of
updating hardware register (SPRN_MAS7) which holds the upper 32-bits of
physical address that will be written into the TLB. This is useful since
not all e500 cores support 36-bit physical addressing.
* Currently have a pass through implementation of fixup_bigphys_addr
* Moved _PAGE_DIRTY in the 64-bit PTE case to free room for three additional
storage attributes that may exist in future FSL Book-E cores and updated
fault handler to copy these bits into the hardware TLBs.
Signed-off-by: Kumar Gala <kumar.gala@freescale.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'arch/ppc')
-rw-r--r-- | arch/ppc/Kconfig | 16 | ||||
-rw-r--r-- | arch/ppc/kernel/head_fsl_booke.S | 113 | ||||
-rw-r--r-- | arch/ppc/syslib/ppc85xx_common.c | 8 |
3 files changed, 92 insertions, 45 deletions
diff --git a/arch/ppc/Kconfig b/arch/ppc/Kconfig index 813c6c9a6d99..74aa1e92a395 100644 --- a/arch/ppc/Kconfig +++ b/arch/ppc/Kconfig | |||
@@ -98,13 +98,19 @@ config FSL_BOOKE | |||
98 | 98 | ||
99 | config PTE_64BIT | 99 | config PTE_64BIT |
100 | bool | 100 | bool |
101 | depends on 44x | 101 | depends on 44x || E500 |
102 | default y | 102 | default y if 44x |
103 | default y if E500 && PHYS_64BIT | ||
103 | 104 | ||
104 | config PHYS_64BIT | 105 | config PHYS_64BIT |
105 | bool | 106 | bool 'Large physical address support' if E500 |
106 | depends on 44x | 107 | depends on 44x || E500 |
107 | default y | 108 | default y if 44x |
109 | ---help--- | ||
110 | This option enables kernel support for larger than 32-bit physical | ||
111 | addresses. This features is not be available on all e500 cores. | ||
112 | |||
113 | If in doubt, say N here. | ||
108 | 114 | ||
109 | config ALTIVEC | 115 | config ALTIVEC |
110 | bool "AltiVec Support" | 116 | bool "AltiVec Support" |
diff --git a/arch/ppc/kernel/head_fsl_booke.S b/arch/ppc/kernel/head_fsl_booke.S index dea19c216fc3..d64bf61d2b1f 100644 --- a/arch/ppc/kernel/head_fsl_booke.S +++ b/arch/ppc/kernel/head_fsl_booke.S | |||
@@ -347,6 +347,38 @@ skpinv: addi r6,r6,1 /* Increment */ | |||
347 | mtspr SPRN_SRR1,r3 | 347 | mtspr SPRN_SRR1,r3 |
348 | rfi /* change context and jump to start_kernel */ | 348 | rfi /* change context and jump to start_kernel */ |
349 | 349 | ||
350 | /* Macros to hide the PTE size differences | ||
351 | * | ||
352 | * FIND_PTE -- walks the page tables given EA & pgdir pointer | ||
353 | * r10 -- EA of fault | ||
354 | * r11 -- PGDIR pointer | ||
355 | * r12 -- free | ||
356 | * label 2: is the bailout case | ||
357 | * | ||
358 | * if we find the pte (fall through): | ||
359 | * r11 is low pte word | ||
360 | * r12 is pointer to the pte | ||
361 | */ | ||
362 | #ifdef CONFIG_PTE_64BIT | ||
363 | #define PTE_FLAGS_OFFSET 4 | ||
364 | #define FIND_PTE \ | ||
365 | rlwinm r12, r10, 13, 19, 29; /* Compute pgdir/pmd offset */ \ | ||
366 | lwzx r11, r12, r11; /* Get pgd/pmd entry */ \ | ||
367 | rlwinm. r12, r11, 0, 0, 20; /* Extract pt base address */ \ | ||
368 | beq 2f; /* Bail if no table */ \ | ||
369 | rlwimi r12, r10, 23, 20, 28; /* Compute pte address */ \ | ||
370 | lwz r11, 4(r12); /* Get pte entry */ | ||
371 | #else | ||
372 | #define PTE_FLAGS_OFFSET 0 | ||
373 | #define FIND_PTE \ | ||
374 | rlwimi r11, r10, 12, 20, 29; /* Create L1 (pgdir/pmd) address */ \ | ||
375 | lwz r11, 0(r11); /* Get L1 entry */ \ | ||
376 | rlwinm. r12, r11, 0, 0, 19; /* Extract L2 (pte) base address */ \ | ||
377 | beq 2f; /* Bail if no table */ \ | ||
378 | rlwimi r12, r10, 22, 20, 29; /* Compute PTE address */ \ | ||
379 | lwz r11, 0(r12); /* Get Linux PTE */ | ||
380 | #endif | ||
381 | |||
350 | /* | 382 | /* |
351 | * Interrupt vector entry code | 383 | * Interrupt vector entry code |
352 | * | 384 | * |
@@ -405,13 +437,7 @@ interrupt_base: | |||
405 | mfspr r11,SPRN_SPRG3 | 437 | mfspr r11,SPRN_SPRG3 |
406 | lwz r11,PGDIR(r11) | 438 | lwz r11,PGDIR(r11) |
407 | 4: | 439 | 4: |
408 | rlwimi r11, r10, 12, 20, 29 /* Create L1 (pgdir/pmd) address */ | 440 | FIND_PTE |
409 | lwz r11, 0(r11) /* Get L1 entry */ | ||
410 | rlwinm. r12, r11, 0, 0, 19 /* Extract L2 (pte) base address */ | ||
411 | beq 2f /* Bail if no table */ | ||
412 | |||
413 | rlwimi r12, r10, 22, 20, 29 /* Compute PTE address */ | ||
414 | lwz r11, 0(r12) /* Get Linux PTE */ | ||
415 | 441 | ||
416 | /* Are _PAGE_USER & _PAGE_RW set & _PAGE_HWWRITE not? */ | 442 | /* Are _PAGE_USER & _PAGE_RW set & _PAGE_HWWRITE not? */ |
417 | andi. r13, r11, _PAGE_RW|_PAGE_USER|_PAGE_HWWRITE | 443 | andi. r13, r11, _PAGE_RW|_PAGE_USER|_PAGE_HWWRITE |
@@ -420,14 +446,12 @@ interrupt_base: | |||
420 | 446 | ||
421 | /* Update 'changed'. */ | 447 | /* Update 'changed'. */ |
422 | ori r11, r11, _PAGE_DIRTY|_PAGE_ACCESSED|_PAGE_HWWRITE | 448 | ori r11, r11, _PAGE_DIRTY|_PAGE_ACCESSED|_PAGE_HWWRITE |
423 | stw r11, 0(r12) /* Update Linux page table */ | 449 | stw r11, PTE_FLAGS_OFFSET(r12) /* Update Linux page table */ |
424 | 450 | ||
425 | /* MAS2 not updated as the entry does exist in the tlb, this | 451 | /* MAS2 not updated as the entry does exist in the tlb, this |
426 | fault taken to detect state transition (eg: COW -> DIRTY) | 452 | fault taken to detect state transition (eg: COW -> DIRTY) |
427 | */ | 453 | */ |
428 | lis r12, MAS3_RPN@h | 454 | andi. r11, r11, _PAGE_HWEXEC |
429 | ori r12, r12, _PAGE_HWEXEC | MAS3_RPN@l | ||
430 | and r11, r11, r12 | ||
431 | rlwimi r11, r11, 31, 27, 27 /* SX <- _PAGE_HWEXEC */ | 455 | rlwimi r11, r11, 31, 27, 27 /* SX <- _PAGE_HWEXEC */ |
432 | ori r11, r11, (MAS3_UW|MAS3_SW|MAS3_UR|MAS3_SR)@l /* set static perms */ | 456 | ori r11, r11, (MAS3_UW|MAS3_SW|MAS3_UR|MAS3_SR)@l /* set static perms */ |
433 | 457 | ||
@@ -439,7 +463,10 @@ interrupt_base: | |||
439 | /* find the TLB index that caused the fault. It has to be here. */ | 463 | /* find the TLB index that caused the fault. It has to be here. */ |
440 | tlbsx 0, r10 | 464 | tlbsx 0, r10 |
441 | 465 | ||
442 | mtspr SPRN_MAS3,r11 | 466 | /* only update the perm bits, assume the RPN is fine */ |
467 | mfspr r12, SPRN_MAS3 | ||
468 | rlwimi r12, r11, 0, 20, 31 | ||
469 | mtspr SPRN_MAS3,r12 | ||
443 | tlbwe | 470 | tlbwe |
444 | 471 | ||
445 | /* Done...restore registers and get out of here. */ | 472 | /* Done...restore registers and get out of here. */ |
@@ -530,18 +557,15 @@ interrupt_base: | |||
530 | lwz r11,PGDIR(r11) | 557 | lwz r11,PGDIR(r11) |
531 | 558 | ||
532 | 4: | 559 | 4: |
533 | rlwimi r11, r10, 12, 20, 29 /* Create L1 (pgdir/pmd) address */ | 560 | FIND_PTE |
534 | lwz r11, 0(r11) /* Get L1 entry */ | 561 | andi. r13, r11, _PAGE_PRESENT /* Is the page present? */ |
535 | rlwinm. r12, r11, 0, 0, 19 /* Extract L2 (pte) base address */ | 562 | beq 2f /* Bail if not present */ |
536 | beq 2f /* Bail if no table */ | ||
537 | |||
538 | rlwimi r12, r10, 22, 20, 29 /* Compute PTE address */ | ||
539 | lwz r11, 0(r12) /* Get Linux PTE */ | ||
540 | andi. r13, r11, _PAGE_PRESENT | ||
541 | beq 2f | ||
542 | 563 | ||
564 | #ifdef CONFIG_PTE_64BIT | ||
565 | lwz r13, 0(r12) | ||
566 | #endif | ||
543 | ori r11, r11, _PAGE_ACCESSED | 567 | ori r11, r11, _PAGE_ACCESSED |
544 | stw r11, 0(r12) | 568 | stw r11, PTE_FLAGS_OFFSET(r12) |
545 | 569 | ||
546 | /* Jump to common tlb load */ | 570 | /* Jump to common tlb load */ |
547 | b finish_tlb_load | 571 | b finish_tlb_load |
@@ -594,18 +618,15 @@ interrupt_base: | |||
594 | lwz r11,PGDIR(r11) | 618 | lwz r11,PGDIR(r11) |
595 | 619 | ||
596 | 4: | 620 | 4: |
597 | rlwimi r11, r10, 12, 20, 29 /* Create L1 (pgdir/pmd) address */ | 621 | FIND_PTE |
598 | lwz r11, 0(r11) /* Get L1 entry */ | 622 | andi. r13, r11, _PAGE_PRESENT /* Is the page present? */ |
599 | rlwinm. r12, r11, 0, 0, 19 /* Extract L2 (pte) base address */ | 623 | beq 2f /* Bail if not present */ |
600 | beq 2f /* Bail if no table */ | ||
601 | |||
602 | rlwimi r12, r10, 22, 20, 29 /* Compute PTE address */ | ||
603 | lwz r11, 0(r12) /* Get Linux PTE */ | ||
604 | andi. r13, r11, _PAGE_PRESENT | ||
605 | beq 2f | ||
606 | 624 | ||
625 | #ifdef CONFIG_PTE_64BIT | ||
626 | lwz r13, 0(r12) | ||
627 | #endif | ||
607 | ori r11, r11, _PAGE_ACCESSED | 628 | ori r11, r11, _PAGE_ACCESSED |
608 | stw r11, 0(r12) | 629 | stw r11, PTE_FLAGS_OFFSET(r12) |
609 | 630 | ||
610 | /* Jump to common TLB load point */ | 631 | /* Jump to common TLB load point */ |
611 | b finish_tlb_load | 632 | b finish_tlb_load |
@@ -690,27 +711,39 @@ finish_tlb_load: | |||
690 | */ | 711 | */ |
691 | 712 | ||
692 | mfspr r12, SPRN_MAS2 | 713 | mfspr r12, SPRN_MAS2 |
714 | #ifdef CONFIG_PTE_64BIT | ||
715 | rlwimi r12, r11, 26, 24, 31 /* extract ...WIMGE from pte */ | ||
716 | #else | ||
693 | rlwimi r12, r11, 26, 27, 31 /* extract WIMGE from pte */ | 717 | rlwimi r12, r11, 26, 27, 31 /* extract WIMGE from pte */ |
718 | #endif | ||
694 | mtspr SPRN_MAS2, r12 | 719 | mtspr SPRN_MAS2, r12 |
695 | 720 | ||
696 | bge 5, 1f | 721 | bge 5, 1f |
697 | 722 | ||
698 | /* addr > TASK_SIZE */ | 723 | /* is user addr */ |
699 | li r10, (MAS3_UX | MAS3_UW | MAS3_UR) | 724 | andi. r12, r11, (_PAGE_USER | _PAGE_HWWRITE | _PAGE_HWEXEC) |
700 | andi. r13, r11, (_PAGE_USER | _PAGE_HWWRITE | _PAGE_HWEXEC) | 725 | andi. r10, r11, _PAGE_USER /* Test for _PAGE_USER */ |
701 | andi. r12, r11, _PAGE_USER /* Test for _PAGE_USER */ | 726 | srwi r10, r12, 1 |
702 | iseleq r12, 0, r10 | ||
703 | and r10, r12, r13 | ||
704 | srwi r12, r10, 1 | ||
705 | or r12, r12, r10 /* Copy user perms into supervisor */ | 727 | or r12, r12, r10 /* Copy user perms into supervisor */ |
728 | iseleq r12, 0, r12 | ||
706 | b 2f | 729 | b 2f |
707 | 730 | ||
708 | /* addr <= TASK_SIZE */ | 731 | /* is kernel addr */ |
709 | 1: rlwinm r12, r11, 31, 29, 29 /* Extract _PAGE_HWWRITE into SW */ | 732 | 1: rlwinm r12, r11, 31, 29, 29 /* Extract _PAGE_HWWRITE into SW */ |
710 | ori r12, r12, (MAS3_SX | MAS3_SR) | 733 | ori r12, r12, (MAS3_SX | MAS3_SR) |
711 | 734 | ||
735 | #ifdef CONFIG_PTE_64BIT | ||
736 | 2: rlwimi r12, r13, 24, 0, 7 /* grab RPN[32:39] */ | ||
737 | rlwimi r12, r11, 24, 8, 19 /* grab RPN[40:51] */ | ||
738 | mtspr SPRN_MAS3, r12 | ||
739 | BEGIN_FTR_SECTION | ||
740 | srwi r10, r13, 8 /* grab RPN[8:31] */ | ||
741 | mtspr SPRN_MAS7, r10 | ||
742 | END_FTR_SECTION_IFSET(CPU_FTR_BIG_PHYS) | ||
743 | #else | ||
712 | 2: rlwimi r11, r12, 0, 20, 31 /* Extract RPN from PTE and merge with perms */ | 744 | 2: rlwimi r11, r12, 0, 20, 31 /* Extract RPN from PTE and merge with perms */ |
713 | mtspr SPRN_MAS3, r11 | 745 | mtspr SPRN_MAS3, r11 |
746 | #endif | ||
714 | tlbwe | 747 | tlbwe |
715 | 748 | ||
716 | /* Done...restore registers and get out of here. */ | 749 | /* Done...restore registers and get out of here. */ |
diff --git a/arch/ppc/syslib/ppc85xx_common.c b/arch/ppc/syslib/ppc85xx_common.c index e83f2f8686d3..da841dacdc13 100644 --- a/arch/ppc/syslib/ppc85xx_common.c +++ b/arch/ppc/syslib/ppc85xx_common.c | |||
@@ -31,3 +31,11 @@ get_ccsrbar(void) | |||
31 | } | 31 | } |
32 | 32 | ||
33 | EXPORT_SYMBOL(get_ccsrbar); | 33 | EXPORT_SYMBOL(get_ccsrbar); |
34 | |||
35 | /* For now this is a pass through */ | ||
36 | phys_addr_t fixup_bigphys_addr(phys_addr_t addr, phys_addr_t size) | ||
37 | { | ||
38 | return addr; | ||
39 | }; | ||
40 | EXPORT_SYMBOL(fixup_bigphys_addr); | ||
41 | |||