aboutsummaryrefslogtreecommitdiffstats
path: root/arch/ppc
diff options
context:
space:
mode:
authorKumar Gala <galak@freescale.com>2005-04-16 18:24:22 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:24:22 -0400
commitf50b153b1966230e78034d5ab1641ca4bb5db56d (patch)
tree9f3f0971789ca2cbb59efbd694c172804f4547cd /arch/ppc
parentb464fce5edc08a825907e9d48a2d2f1af0393fef (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/Kconfig16
-rw-r--r--arch/ppc/kernel/head_fsl_booke.S113
-rw-r--r--arch/ppc/syslib/ppc85xx_common.c8
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
99config PTE_64BIT 99config 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
104config PHYS_64BIT 105config 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
109config ALTIVEC 115config 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)
4074: 4394:
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
5324: 5594:
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
5964: 6204:
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 */
7091: rlwinm r12, r11, 31, 29, 29 /* Extract _PAGE_HWWRITE into SW */ 7321: 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
7362: 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
739BEGIN_FTR_SECTION
740 srwi r10, r13, 8 /* grab RPN[8:31] */
741 mtspr SPRN_MAS7, r10
742END_FTR_SECTION_IFSET(CPU_FTR_BIG_PHYS)
743#else
7122: rlwimi r11, r12, 0, 20, 31 /* Extract RPN from PTE and merge with perms */ 7442: 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
33EXPORT_SYMBOL(get_ccsrbar); 33EXPORT_SYMBOL(get_ccsrbar);
34
35/* For now this is a pass through */
36phys_addr_t fixup_bigphys_addr(phys_addr_t addr, phys_addr_t size)
37{
38 return addr;
39};
40EXPORT_SYMBOL(fixup_bigphys_addr);
41