diff options
Diffstat (limited to 'arch/sparc/include')
-rw-r--r-- | arch/sparc/include/asm/page_64.h | 3 | ||||
-rw-r--r-- | arch/sparc/include/asm/pgtable_64.h | 55 | ||||
-rw-r--r-- | arch/sparc/include/asm/tsb.h | 47 |
3 files changed, 67 insertions, 38 deletions
diff --git a/arch/sparc/include/asm/page_64.h b/arch/sparc/include/asm/page_64.h index 2211a8036bfa..732ba178a289 100644 --- a/arch/sparc/include/asm/page_64.h +++ b/arch/sparc/include/asm/page_64.h | |||
@@ -128,9 +128,6 @@ extern unsigned long PAGE_OFFSET; | |||
128 | */ | 128 | */ |
129 | #define MAX_PHYS_ADDRESS_BITS 47 | 129 | #define MAX_PHYS_ADDRESS_BITS 47 |
130 | 130 | ||
131 | /* These two shift counts are used when indexing sparc64_valid_addr_bitmap | ||
132 | * and kpte_linear_bitmap. | ||
133 | */ | ||
134 | #define ILOG2_4MB 22 | 131 | #define ILOG2_4MB 22 |
135 | #define ILOG2_256MB 28 | 132 | #define ILOG2_256MB 28 |
136 | 133 | ||
diff --git a/arch/sparc/include/asm/pgtable_64.h b/arch/sparc/include/asm/pgtable_64.h index 31ac919920a9..a305b22ab581 100644 --- a/arch/sparc/include/asm/pgtable_64.h +++ b/arch/sparc/include/asm/pgtable_64.h | |||
@@ -79,22 +79,7 @@ | |||
79 | 79 | ||
80 | #include <linux/sched.h> | 80 | #include <linux/sched.h> |
81 | 81 | ||
82 | extern unsigned long sparc64_valid_addr_bitmap[]; | 82 | bool kern_addr_valid(unsigned long addr); |
83 | |||
84 | /* Needs to be defined here and not in linux/mm.h, as it is arch dependent */ | ||
85 | static inline bool __kern_addr_valid(unsigned long paddr) | ||
86 | { | ||
87 | if ((paddr >> MAX_PHYS_ADDRESS_BITS) != 0UL) | ||
88 | return false; | ||
89 | return test_bit(paddr >> ILOG2_4MB, sparc64_valid_addr_bitmap); | ||
90 | } | ||
91 | |||
92 | static inline bool kern_addr_valid(unsigned long addr) | ||
93 | { | ||
94 | unsigned long paddr = __pa(addr); | ||
95 | |||
96 | return __kern_addr_valid(paddr); | ||
97 | } | ||
98 | 83 | ||
99 | /* Entries per page directory level. */ | 84 | /* Entries per page directory level. */ |
100 | #define PTRS_PER_PTE (1UL << (PAGE_SHIFT-3)) | 85 | #define PTRS_PER_PTE (1UL << (PAGE_SHIFT-3)) |
@@ -122,6 +107,7 @@ static inline bool kern_addr_valid(unsigned long addr) | |||
122 | #define _PAGE_R _AC(0x8000000000000000,UL) /* Keep ref bit uptodate*/ | 107 | #define _PAGE_R _AC(0x8000000000000000,UL) /* Keep ref bit uptodate*/ |
123 | #define _PAGE_SPECIAL _AC(0x0200000000000000,UL) /* Special page */ | 108 | #define _PAGE_SPECIAL _AC(0x0200000000000000,UL) /* Special page */ |
124 | #define _PAGE_PMD_HUGE _AC(0x0100000000000000,UL) /* Huge page */ | 109 | #define _PAGE_PMD_HUGE _AC(0x0100000000000000,UL) /* Huge page */ |
110 | #define _PAGE_PUD_HUGE _PAGE_PMD_HUGE | ||
125 | 111 | ||
126 | /* Advertise support for _PAGE_SPECIAL */ | 112 | /* Advertise support for _PAGE_SPECIAL */ |
127 | #define __HAVE_ARCH_PTE_SPECIAL | 113 | #define __HAVE_ARCH_PTE_SPECIAL |
@@ -668,26 +654,26 @@ static inline unsigned long pmd_large(pmd_t pmd) | |||
668 | return pte_val(pte) & _PAGE_PMD_HUGE; | 654 | return pte_val(pte) & _PAGE_PMD_HUGE; |
669 | } | 655 | } |
670 | 656 | ||
671 | #ifdef CONFIG_TRANSPARENT_HUGEPAGE | 657 | static inline unsigned long pmd_pfn(pmd_t pmd) |
672 | static inline unsigned long pmd_young(pmd_t pmd) | ||
673 | { | 658 | { |
674 | pte_t pte = __pte(pmd_val(pmd)); | 659 | pte_t pte = __pte(pmd_val(pmd)); |
675 | 660 | ||
676 | return pte_young(pte); | 661 | return pte_pfn(pte); |
677 | } | 662 | } |
678 | 663 | ||
679 | static inline unsigned long pmd_write(pmd_t pmd) | 664 | #ifdef CONFIG_TRANSPARENT_HUGEPAGE |
665 | static inline unsigned long pmd_young(pmd_t pmd) | ||
680 | { | 666 | { |
681 | pte_t pte = __pte(pmd_val(pmd)); | 667 | pte_t pte = __pte(pmd_val(pmd)); |
682 | 668 | ||
683 | return pte_write(pte); | 669 | return pte_young(pte); |
684 | } | 670 | } |
685 | 671 | ||
686 | static inline unsigned long pmd_pfn(pmd_t pmd) | 672 | static inline unsigned long pmd_write(pmd_t pmd) |
687 | { | 673 | { |
688 | pte_t pte = __pte(pmd_val(pmd)); | 674 | pte_t pte = __pte(pmd_val(pmd)); |
689 | 675 | ||
690 | return pte_pfn(pte); | 676 | return pte_write(pte); |
691 | } | 677 | } |
692 | 678 | ||
693 | static inline unsigned long pmd_trans_huge(pmd_t pmd) | 679 | static inline unsigned long pmd_trans_huge(pmd_t pmd) |
@@ -781,18 +767,15 @@ static inline int pmd_present(pmd_t pmd) | |||
781 | * the top bits outside of the range of any physical address size we | 767 | * the top bits outside of the range of any physical address size we |
782 | * support are clear as well. We also validate the physical itself. | 768 | * support are clear as well. We also validate the physical itself. |
783 | */ | 769 | */ |
784 | #define pmd_bad(pmd) ((pmd_val(pmd) & ~PAGE_MASK) || \ | 770 | #define pmd_bad(pmd) (pmd_val(pmd) & ~PAGE_MASK) |
785 | !__kern_addr_valid(pmd_val(pmd))) | ||
786 | 771 | ||
787 | #define pud_none(pud) (!pud_val(pud)) | 772 | #define pud_none(pud) (!pud_val(pud)) |
788 | 773 | ||
789 | #define pud_bad(pud) ((pud_val(pud) & ~PAGE_MASK) || \ | 774 | #define pud_bad(pud) (pud_val(pud) & ~PAGE_MASK) |
790 | !__kern_addr_valid(pud_val(pud))) | ||
791 | 775 | ||
792 | #define pgd_none(pgd) (!pgd_val(pgd)) | 776 | #define pgd_none(pgd) (!pgd_val(pgd)) |
793 | 777 | ||
794 | #define pgd_bad(pgd) ((pgd_val(pgd) & ~PAGE_MASK) || \ | 778 | #define pgd_bad(pgd) (pgd_val(pgd) & ~PAGE_MASK) |
795 | !__kern_addr_valid(pgd_val(pgd))) | ||
796 | 779 | ||
797 | #ifdef CONFIG_TRANSPARENT_HUGEPAGE | 780 | #ifdef CONFIG_TRANSPARENT_HUGEPAGE |
798 | void set_pmd_at(struct mm_struct *mm, unsigned long addr, | 781 | void set_pmd_at(struct mm_struct *mm, unsigned long addr, |
@@ -835,6 +818,20 @@ static inline unsigned long __pmd_page(pmd_t pmd) | |||
835 | #define pgd_present(pgd) (pgd_val(pgd) != 0U) | 818 | #define pgd_present(pgd) (pgd_val(pgd) != 0U) |
836 | #define pgd_clear(pgdp) (pgd_val(*(pgd)) = 0UL) | 819 | #define pgd_clear(pgdp) (pgd_val(*(pgd)) = 0UL) |
837 | 820 | ||
821 | static inline unsigned long pud_large(pud_t pud) | ||
822 | { | ||
823 | pte_t pte = __pte(pud_val(pud)); | ||
824 | |||
825 | return pte_val(pte) & _PAGE_PMD_HUGE; | ||
826 | } | ||
827 | |||
828 | static inline unsigned long pud_pfn(pud_t pud) | ||
829 | { | ||
830 | pte_t pte = __pte(pud_val(pud)); | ||
831 | |||
832 | return pte_pfn(pte); | ||
833 | } | ||
834 | |||
838 | /* Same in both SUN4V and SUN4U. */ | 835 | /* Same in both SUN4V and SUN4U. */ |
839 | #define pte_none(pte) (!pte_val(pte)) | 836 | #define pte_none(pte) (!pte_val(pte)) |
840 | 837 | ||
diff --git a/arch/sparc/include/asm/tsb.h b/arch/sparc/include/asm/tsb.h index a2f541905715..ecb49cfa3be9 100644 --- a/arch/sparc/include/asm/tsb.h +++ b/arch/sparc/include/asm/tsb.h | |||
@@ -133,9 +133,24 @@ extern struct tsb_phys_patch_entry __tsb_phys_patch, __tsb_phys_patch_end; | |||
133 | sub TSB, 0x8, TSB; \ | 133 | sub TSB, 0x8, TSB; \ |
134 | TSB_STORE(TSB, TAG); | 134 | TSB_STORE(TSB, TAG); |
135 | 135 | ||
136 | /* Do a kernel page table walk. Leaves physical PTE pointer in | 136 | /* Do a kernel page table walk. Leaves valid PTE value in |
137 | * REG1. Jumps to FAIL_LABEL on early page table walk termination. | 137 | * REG1. Jumps to FAIL_LABEL on early page table walk |
138 | * VADDR will not be clobbered, but REG2 will. | 138 | * termination. VADDR will not be clobbered, but REG2 will. |
139 | * | ||
140 | * There are two masks we must apply to propagate bits from | ||
141 | * the virtual address into the PTE physical address field | ||
142 | * when dealing with huge pages. This is because the page | ||
143 | * table boundaries do not match the huge page size(s) the | ||
144 | * hardware supports. | ||
145 | * | ||
146 | * In these cases we propagate the bits that are below the | ||
147 | * page table level where we saw the huge page mapping, but | ||
148 | * are still within the relevant physical bits for the huge | ||
149 | * page size in question. So for PMD mappings (which fall on | ||
150 | * bit 23, for 8MB per PMD) we must propagate bit 22 for a | ||
151 | * 4MB huge page. For huge PUDs (which fall on bit 33, for | ||
152 | * 8GB per PUD), we have to accomodate 256MB and 2GB huge | ||
153 | * pages. So for those we propagate bits 32 to 28. | ||
139 | */ | 154 | */ |
140 | #define KERN_PGTABLE_WALK(VADDR, REG1, REG2, FAIL_LABEL) \ | 155 | #define KERN_PGTABLE_WALK(VADDR, REG1, REG2, FAIL_LABEL) \ |
141 | sethi %hi(swapper_pg_dir), REG1; \ | 156 | sethi %hi(swapper_pg_dir), REG1; \ |
@@ -150,15 +165,35 @@ extern struct tsb_phys_patch_entry __tsb_phys_patch, __tsb_phys_patch_end; | |||
150 | andn REG2, 0x7, REG2; \ | 165 | andn REG2, 0x7, REG2; \ |
151 | ldxa [REG1 + REG2] ASI_PHYS_USE_EC, REG1; \ | 166 | ldxa [REG1 + REG2] ASI_PHYS_USE_EC, REG1; \ |
152 | brz,pn REG1, FAIL_LABEL; \ | 167 | brz,pn REG1, FAIL_LABEL; \ |
153 | sllx VADDR, 64 - (PMD_SHIFT + PMD_BITS), REG2; \ | 168 | sethi %uhi(_PAGE_PUD_HUGE), REG2; \ |
169 | brz,pn REG1, FAIL_LABEL; \ | ||
170 | sllx REG2, 32, REG2; \ | ||
171 | andcc REG1, REG2, %g0; \ | ||
172 | sethi %hi(0xf8000000), REG2; \ | ||
173 | bne,pt %xcc, 697f; \ | ||
174 | sllx REG2, 1, REG2; \ | ||
175 | sllx VADDR, 64 - (PMD_SHIFT + PMD_BITS), REG2; \ | ||
154 | srlx REG2, 64 - PAGE_SHIFT, REG2; \ | 176 | srlx REG2, 64 - PAGE_SHIFT, REG2; \ |
155 | andn REG2, 0x7, REG2; \ | 177 | andn REG2, 0x7, REG2; \ |
156 | ldxa [REG1 + REG2] ASI_PHYS_USE_EC, REG1; \ | 178 | ldxa [REG1 + REG2] ASI_PHYS_USE_EC, REG1; \ |
179 | sethi %uhi(_PAGE_PMD_HUGE), REG2; \ | ||
157 | brz,pn REG1, FAIL_LABEL; \ | 180 | brz,pn REG1, FAIL_LABEL; \ |
158 | sllx VADDR, 64 - PMD_SHIFT, REG2; \ | 181 | sllx REG2, 32, REG2; \ |
182 | andcc REG1, REG2, %g0; \ | ||
183 | be,pn %xcc, 698f; \ | ||
184 | sethi %hi(0x400000), REG2; \ | ||
185 | 697: brgez,pn REG1, FAIL_LABEL; \ | ||
186 | andn REG1, REG2, REG1; \ | ||
187 | and VADDR, REG2, REG2; \ | ||
188 | ba,pt %xcc, 699f; \ | ||
189 | or REG1, REG2, REG1; \ | ||
190 | 698: sllx VADDR, 64 - PMD_SHIFT, REG2; \ | ||
159 | srlx REG2, 64 - PAGE_SHIFT, REG2; \ | 191 | srlx REG2, 64 - PAGE_SHIFT, REG2; \ |
160 | andn REG2, 0x7, REG2; \ | 192 | andn REG2, 0x7, REG2; \ |
161 | add REG1, REG2, REG1; | 193 | ldxa [REG1 + REG2] ASI_PHYS_USE_EC, REG1; \ |
194 | brgez,pn REG1, FAIL_LABEL; \ | ||
195 | nop; \ | ||
196 | 699: | ||
162 | 197 | ||
163 | /* PMD has been loaded into REG1, interpret the value, seeing | 198 | /* PMD has been loaded into REG1, interpret the value, seeing |
164 | * if it is a HUGE PMD or a normal one. If it is not valid | 199 | * if it is a HUGE PMD or a normal one. If it is not valid |