aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc/include
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sparc/include')
-rw-r--r--arch/sparc/include/asm/page_64.h3
-rw-r--r--arch/sparc/include/asm/pgtable_64.h55
-rw-r--r--arch/sparc/include/asm/tsb.h47
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
82extern unsigned long sparc64_valid_addr_bitmap[]; 82bool kern_addr_valid(unsigned long addr);
83
84/* Needs to be defined here and not in linux/mm.h, as it is arch dependent */
85static 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
92static 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 657static inline unsigned long pmd_pfn(pmd_t pmd)
672static 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
679static inline unsigned long pmd_write(pmd_t pmd) 664#ifdef CONFIG_TRANSPARENT_HUGEPAGE
665static 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
686static inline unsigned long pmd_pfn(pmd_t pmd) 672static 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
693static inline unsigned long pmd_trans_huge(pmd_t pmd) 679static 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
798void set_pmd_at(struct mm_struct *mm, unsigned long addr, 781void 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
821static 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
828static 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; \
185697: 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; \
190698: 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; \
196699:
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