diff options
-rw-r--r-- | arch/powerpc/include/asm/book3s/64/mmu-hash.h | 37 | ||||
-rw-r--r-- | arch/powerpc/include/asm/kvm_book3s_64.h | 87 | ||||
-rw-r--r-- | arch/powerpc/include/asm/mmu.h | 1 | ||||
-rw-r--r-- | arch/powerpc/mm/hash_native_64.c | 42 | ||||
-rw-r--r-- | arch/powerpc/mm/hash_utils_64.c | 55 |
5 files changed, 102 insertions, 120 deletions
diff --git a/arch/powerpc/include/asm/book3s/64/mmu-hash.h b/arch/powerpc/include/asm/book3s/64/mmu-hash.h index 287a656ceb57..e407af2b7333 100644 --- a/arch/powerpc/include/asm/book3s/64/mmu-hash.h +++ b/arch/powerpc/include/asm/book3s/64/mmu-hash.h | |||
@@ -245,6 +245,43 @@ static inline int segment_shift(int ssize) | |||
245 | } | 245 | } |
246 | 246 | ||
247 | /* | 247 | /* |
248 | * This array is indexed by the LP field of the HPTE second dword. | ||
249 | * Since this field may contain some RPN bits, some entries are | ||
250 | * replicated so that we get the same value irrespective of RPN. | ||
251 | * The top 4 bits are the page size index (MMU_PAGE_*) for the | ||
252 | * actual page size, the bottom 4 bits are the base page size. | ||
253 | */ | ||
254 | extern u8 hpte_page_sizes[1 << LP_BITS]; | ||
255 | |||
256 | static inline unsigned long __hpte_page_size(unsigned long h, unsigned long l, | ||
257 | bool is_base_size) | ||
258 | { | ||
259 | unsigned int i, lp; | ||
260 | |||
261 | if (!(h & HPTE_V_LARGE)) | ||
262 | return 1ul << 12; | ||
263 | |||
264 | /* Look at the 8 bit LP value */ | ||
265 | lp = (l >> LP_SHIFT) & ((1 << LP_BITS) - 1); | ||
266 | i = hpte_page_sizes[lp]; | ||
267 | if (!i) | ||
268 | return 0; | ||
269 | if (!is_base_size) | ||
270 | i >>= 4; | ||
271 | return 1ul << mmu_psize_defs[i & 0xf].shift; | ||
272 | } | ||
273 | |||
274 | static inline unsigned long hpte_page_size(unsigned long h, unsigned long l) | ||
275 | { | ||
276 | return __hpte_page_size(h, l, 0); | ||
277 | } | ||
278 | |||
279 | static inline unsigned long hpte_base_page_size(unsigned long h, unsigned long l) | ||
280 | { | ||
281 | return __hpte_page_size(h, l, 1); | ||
282 | } | ||
283 | |||
284 | /* | ||
248 | * The current system page and segment sizes | 285 | * The current system page and segment sizes |
249 | */ | 286 | */ |
250 | extern int mmu_kernel_ssize; | 287 | extern int mmu_kernel_ssize; |
diff --git a/arch/powerpc/include/asm/kvm_book3s_64.h b/arch/powerpc/include/asm/kvm_book3s_64.h index 88d17b4ea9c8..4ffd5a1e788d 100644 --- a/arch/powerpc/include/asm/kvm_book3s_64.h +++ b/arch/powerpc/include/asm/kvm_book3s_64.h | |||
@@ -20,6 +20,8 @@ | |||
20 | #ifndef __ASM_KVM_BOOK3S_64_H__ | 20 | #ifndef __ASM_KVM_BOOK3S_64_H__ |
21 | #define __ASM_KVM_BOOK3S_64_H__ | 21 | #define __ASM_KVM_BOOK3S_64_H__ |
22 | 22 | ||
23 | #include <asm/book3s/64/mmu-hash.h> | ||
24 | |||
23 | #ifdef CONFIG_KVM_BOOK3S_PR_POSSIBLE | 25 | #ifdef CONFIG_KVM_BOOK3S_PR_POSSIBLE |
24 | static inline struct kvmppc_book3s_shadow_vcpu *svcpu_get(struct kvm_vcpu *vcpu) | 26 | static inline struct kvmppc_book3s_shadow_vcpu *svcpu_get(struct kvm_vcpu *vcpu) |
25 | { | 27 | { |
@@ -97,56 +99,20 @@ static inline void __unlock_hpte(__be64 *hpte, unsigned long hpte_v) | |||
97 | hpte[0] = cpu_to_be64(hpte_v); | 99 | hpte[0] = cpu_to_be64(hpte_v); |
98 | } | 100 | } |
99 | 101 | ||
100 | static inline int __hpte_actual_psize(unsigned int lp, int psize) | ||
101 | { | ||
102 | int i, shift; | ||
103 | unsigned int mask; | ||
104 | |||
105 | /* start from 1 ignoring MMU_PAGE_4K */ | ||
106 | for (i = 1; i < MMU_PAGE_COUNT; i++) { | ||
107 | |||
108 | /* invalid penc */ | ||
109 | if (mmu_psize_defs[psize].penc[i] == -1) | ||
110 | continue; | ||
111 | /* | ||
112 | * encoding bits per actual page size | ||
113 | * PTE LP actual page size | ||
114 | * rrrr rrrz >=8KB | ||
115 | * rrrr rrzz >=16KB | ||
116 | * rrrr rzzz >=32KB | ||
117 | * rrrr zzzz >=64KB | ||
118 | * ....... | ||
119 | */ | ||
120 | shift = mmu_psize_defs[i].shift - LP_SHIFT; | ||
121 | if (shift > LP_BITS) | ||
122 | shift = LP_BITS; | ||
123 | mask = (1 << shift) - 1; | ||
124 | if ((lp & mask) == mmu_psize_defs[psize].penc[i]) | ||
125 | return i; | ||
126 | } | ||
127 | return -1; | ||
128 | } | ||
129 | |||
130 | static inline unsigned long compute_tlbie_rb(unsigned long v, unsigned long r, | 102 | static inline unsigned long compute_tlbie_rb(unsigned long v, unsigned long r, |
131 | unsigned long pte_index) | 103 | unsigned long pte_index) |
132 | { | 104 | { |
133 | int b_psize = MMU_PAGE_4K, a_psize = MMU_PAGE_4K; | 105 | int i, b_psize = MMU_PAGE_4K, a_psize = MMU_PAGE_4K; |
134 | unsigned int penc; | 106 | unsigned int penc; |
135 | unsigned long rb = 0, va_low, sllp; | 107 | unsigned long rb = 0, va_low, sllp; |
136 | unsigned int lp = (r >> LP_SHIFT) & ((1 << LP_BITS) - 1); | 108 | unsigned int lp = (r >> LP_SHIFT) & ((1 << LP_BITS) - 1); |
137 | 109 | ||
138 | if (v & HPTE_V_LARGE) { | 110 | if (v & HPTE_V_LARGE) { |
139 | for (b_psize = 0; b_psize < MMU_PAGE_COUNT; b_psize++) { | 111 | i = hpte_page_sizes[lp]; |
140 | 112 | b_psize = i & 0xf; | |
141 | /* valid entries have a shift value */ | 113 | a_psize = i >> 4; |
142 | if (!mmu_psize_defs[b_psize].shift) | ||
143 | continue; | ||
144 | |||
145 | a_psize = __hpte_actual_psize(lp, b_psize); | ||
146 | if (a_psize != -1) | ||
147 | break; | ||
148 | } | ||
149 | } | 114 | } |
115 | |||
150 | /* | 116 | /* |
151 | * Ignore the top 14 bits of va | 117 | * Ignore the top 14 bits of va |
152 | * v have top two bits covering segment size, hence move | 118 | * v have top two bits covering segment size, hence move |
@@ -215,45 +181,6 @@ static inline unsigned long compute_tlbie_rb(unsigned long v, unsigned long r, | |||
215 | return rb; | 181 | return rb; |
216 | } | 182 | } |
217 | 183 | ||
218 | static inline unsigned long __hpte_page_size(unsigned long h, unsigned long l, | ||
219 | bool is_base_size) | ||
220 | { | ||
221 | |||
222 | int size, a_psize; | ||
223 | /* Look at the 8 bit LP value */ | ||
224 | unsigned int lp = (l >> LP_SHIFT) & ((1 << LP_BITS) - 1); | ||
225 | |||
226 | /* only handle 4k, 64k and 16M pages for now */ | ||
227 | if (!(h & HPTE_V_LARGE)) | ||
228 | return 1ul << 12; | ||
229 | else { | ||
230 | for (size = 0; size < MMU_PAGE_COUNT; size++) { | ||
231 | /* valid entries have a shift value */ | ||
232 | if (!mmu_psize_defs[size].shift) | ||
233 | continue; | ||
234 | |||
235 | a_psize = __hpte_actual_psize(lp, size); | ||
236 | if (a_psize != -1) { | ||
237 | if (is_base_size) | ||
238 | return 1ul << mmu_psize_defs[size].shift; | ||
239 | return 1ul << mmu_psize_defs[a_psize].shift; | ||
240 | } | ||
241 | } | ||
242 | |||
243 | } | ||
244 | return 0; | ||
245 | } | ||
246 | |||
247 | static inline unsigned long hpte_page_size(unsigned long h, unsigned long l) | ||
248 | { | ||
249 | return __hpte_page_size(h, l, 0); | ||
250 | } | ||
251 | |||
252 | static inline unsigned long hpte_base_page_size(unsigned long h, unsigned long l) | ||
253 | { | ||
254 | return __hpte_page_size(h, l, 1); | ||
255 | } | ||
256 | |||
257 | static inline unsigned long hpte_rpn(unsigned long ptel, unsigned long psize) | 184 | static inline unsigned long hpte_rpn(unsigned long ptel, unsigned long psize) |
258 | { | 185 | { |
259 | return ((ptel & HPTE_R_RPN) & ~(psize - 1)) >> PAGE_SHIFT; | 186 | return ((ptel & HPTE_R_RPN) & ~(psize - 1)) >> PAGE_SHIFT; |
diff --git a/arch/powerpc/include/asm/mmu.h b/arch/powerpc/include/asm/mmu.h index e2fb408f8398..b78e8d3377f6 100644 --- a/arch/powerpc/include/asm/mmu.h +++ b/arch/powerpc/include/asm/mmu.h | |||
@@ -271,6 +271,7 @@ static inline bool early_radix_enabled(void) | |||
271 | #define MMU_PAGE_16G 13 | 271 | #define MMU_PAGE_16G 13 |
272 | #define MMU_PAGE_64G 14 | 272 | #define MMU_PAGE_64G 14 |
273 | 273 | ||
274 | /* N.B. we need to change the type of hpte_page_sizes if this gets to be > 16 */ | ||
274 | #define MMU_PAGE_COUNT 15 | 275 | #define MMU_PAGE_COUNT 15 |
275 | 276 | ||
276 | #ifdef CONFIG_PPC_BOOK3S_64 | 277 | #ifdef CONFIG_PPC_BOOK3S_64 |
diff --git a/arch/powerpc/mm/hash_native_64.c b/arch/powerpc/mm/hash_native_64.c index 0e4e9654bd2c..83ddc0e171b0 100644 --- a/arch/powerpc/mm/hash_native_64.c +++ b/arch/powerpc/mm/hash_native_64.c | |||
@@ -493,36 +493,6 @@ static void native_hugepage_invalidate(unsigned long vsid, | |||
493 | } | 493 | } |
494 | #endif | 494 | #endif |
495 | 495 | ||
496 | static inline int __hpte_actual_psize(unsigned int lp, int psize) | ||
497 | { | ||
498 | int i, shift; | ||
499 | unsigned int mask; | ||
500 | |||
501 | /* start from 1 ignoring MMU_PAGE_4K */ | ||
502 | for (i = 1; i < MMU_PAGE_COUNT; i++) { | ||
503 | |||
504 | /* invalid penc */ | ||
505 | if (mmu_psize_defs[psize].penc[i] == -1) | ||
506 | continue; | ||
507 | /* | ||
508 | * encoding bits per actual page size | ||
509 | * PTE LP actual page size | ||
510 | * rrrr rrrz >=8KB | ||
511 | * rrrr rrzz >=16KB | ||
512 | * rrrr rzzz >=32KB | ||
513 | * rrrr zzzz >=64KB | ||
514 | * ....... | ||
515 | */ | ||
516 | shift = mmu_psize_defs[i].shift - LP_SHIFT; | ||
517 | if (shift > LP_BITS) | ||
518 | shift = LP_BITS; | ||
519 | mask = (1 << shift) - 1; | ||
520 | if ((lp & mask) == mmu_psize_defs[psize].penc[i]) | ||
521 | return i; | ||
522 | } | ||
523 | return -1; | ||
524 | } | ||
525 | |||
526 | static void hpte_decode(struct hash_pte *hpte, unsigned long slot, | 496 | static void hpte_decode(struct hash_pte *hpte, unsigned long slot, |
527 | int *psize, int *apsize, int *ssize, unsigned long *vpn) | 497 | int *psize, int *apsize, int *ssize, unsigned long *vpn) |
528 | { | 498 | { |
@@ -538,16 +508,8 @@ static void hpte_decode(struct hash_pte *hpte, unsigned long slot, | |||
538 | size = MMU_PAGE_4K; | 508 | size = MMU_PAGE_4K; |
539 | a_size = MMU_PAGE_4K; | 509 | a_size = MMU_PAGE_4K; |
540 | } else { | 510 | } else { |
541 | for (size = 0; size < MMU_PAGE_COUNT; size++) { | 511 | size = hpte_page_sizes[lp] & 0xf; |
542 | 512 | a_size = hpte_page_sizes[lp] >> 4; | |
543 | /* valid entries have a shift value */ | ||
544 | if (!mmu_psize_defs[size].shift) | ||
545 | continue; | ||
546 | |||
547 | a_size = __hpte_actual_psize(lp, size); | ||
548 | if (a_size != -1) | ||
549 | break; | ||
550 | } | ||
551 | } | 513 | } |
552 | /* This works for all page sizes, and for 256M and 1T segments */ | 514 | /* This works for all page sizes, and for 256M and 1T segments */ |
553 | if (cpu_has_feature(CPU_FTR_ARCH_300)) | 515 | if (cpu_has_feature(CPU_FTR_ARCH_300)) |
diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c index 0821556e16f4..ef3ae891a3db 100644 --- a/arch/powerpc/mm/hash_utils_64.c +++ b/arch/powerpc/mm/hash_utils_64.c | |||
@@ -93,6 +93,9 @@ static unsigned long _SDR1; | |||
93 | struct mmu_psize_def mmu_psize_defs[MMU_PAGE_COUNT]; | 93 | struct mmu_psize_def mmu_psize_defs[MMU_PAGE_COUNT]; |
94 | EXPORT_SYMBOL_GPL(mmu_psize_defs); | 94 | EXPORT_SYMBOL_GPL(mmu_psize_defs); |
95 | 95 | ||
96 | u8 hpte_page_sizes[1 << LP_BITS]; | ||
97 | EXPORT_SYMBOL_GPL(hpte_page_sizes); | ||
98 | |||
96 | struct hash_pte *htab_address; | 99 | struct hash_pte *htab_address; |
97 | unsigned long htab_size_bytes; | 100 | unsigned long htab_size_bytes; |
98 | unsigned long htab_hash_mask; | 101 | unsigned long htab_hash_mask; |
@@ -564,8 +567,60 @@ static void __init htab_scan_page_sizes(void) | |||
564 | #endif /* CONFIG_HUGETLB_PAGE */ | 567 | #endif /* CONFIG_HUGETLB_PAGE */ |
565 | } | 568 | } |
566 | 569 | ||
570 | /* | ||
571 | * Fill in the hpte_page_sizes[] array. | ||
572 | * We go through the mmu_psize_defs[] array looking for all the | ||
573 | * supported base/actual page size combinations. Each combination | ||
574 | * has a unique pagesize encoding (penc) value in the low bits of | ||
575 | * the LP field of the HPTE. For actual page sizes less than 1MB, | ||
576 | * some of the upper LP bits are used for RPN bits, meaning that | ||
577 | * we need to fill in several entries in hpte_page_sizes[]. | ||
578 | * | ||
579 | * In diagrammatic form, with r = RPN bits and z = page size bits: | ||
580 | * PTE LP actual page size | ||
581 | * rrrr rrrz >=8KB | ||
582 | * rrrr rrzz >=16KB | ||
583 | * rrrr rzzz >=32KB | ||
584 | * rrrr zzzz >=64KB | ||
585 | * ... | ||
586 | * | ||
587 | * The zzzz bits are implementation-specific but are chosen so that | ||
588 | * no encoding for a larger page size uses the same value in its | ||
589 | * low-order N bits as the encoding for the 2^(12+N) byte page size | ||
590 | * (if it exists). | ||
591 | */ | ||
592 | static void init_hpte_page_sizes(void) | ||
593 | { | ||
594 | long int ap, bp; | ||
595 | long int shift, penc; | ||
596 | |||
597 | for (bp = 0; bp < MMU_PAGE_COUNT; ++bp) { | ||
598 | if (!mmu_psize_defs[bp].shift) | ||
599 | continue; /* not a supported page size */ | ||
600 | for (ap = bp; ap < MMU_PAGE_COUNT; ++ap) { | ||
601 | penc = mmu_psize_defs[bp].penc[ap]; | ||
602 | if (penc == -1) | ||
603 | continue; | ||
604 | shift = mmu_psize_defs[ap].shift - LP_SHIFT; | ||
605 | if (shift <= 0) | ||
606 | continue; /* should never happen */ | ||
607 | /* | ||
608 | * For page sizes less than 1MB, this loop | ||
609 | * replicates the entry for all possible values | ||
610 | * of the rrrr bits. | ||
611 | */ | ||
612 | while (penc < (1 << LP_BITS)) { | ||
613 | hpte_page_sizes[penc] = (ap << 4) | bp; | ||
614 | penc += 1 << shift; | ||
615 | } | ||
616 | } | ||
617 | } | ||
618 | } | ||
619 | |||
567 | static void __init htab_init_page_sizes(void) | 620 | static void __init htab_init_page_sizes(void) |
568 | { | 621 | { |
622 | init_hpte_page_sizes(); | ||
623 | |||
569 | if (!debug_pagealloc_enabled()) { | 624 | if (!debug_pagealloc_enabled()) { |
570 | /* | 625 | /* |
571 | * Pick a size for the linear mapping. Currently, we only | 626 | * Pick a size for the linear mapping. Currently, we only |