aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc/include/asm/tsb.h
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sparc/include/asm/tsb.h')
-rw-r--r--arch/sparc/include/asm/tsb.h47
1 files changed, 41 insertions, 6 deletions
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