diff options
author | Nitin Gupta <nitin.m.gupta@oracle.com> | 2016-03-30 14:17:13 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2016-05-20 21:44:27 -0400 |
commit | 24e49ee3d76b70853a96520e46b8837e5eae65b2 (patch) | |
tree | 4893dd3011dc7a4db11082ce6953d1e1d2c13803 /arch/sparc | |
parent | b1ac6b7b4061f6c92bacf6938f94fb61b2fbf7f3 (diff) |
sparc64: Reduce TLB flushes during hugepte changes
During hugepage map/unmap, TSB and TLB flushes are currently
issued at every PAGE_SIZE'd boundary which is unnecessary.
We now issue the flush at REAL_HPAGE_SIZE boundaries only.
Without this patch workloads which unmap a large hugepage
backed VMA region get CPU lockups due to excessive TLB
flush calls.
Orabug: 22365539, 22643230, 22995196
Signed-off-by: Nitin Gupta <nitin.m.gupta@oracle.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'arch/sparc')
-rw-r--r-- | arch/sparc/include/asm/pgtable_64.h | 43 | ||||
-rw-r--r-- | arch/sparc/include/asm/tlbflush_64.h | 3 | ||||
-rw-r--r-- | arch/sparc/mm/hugetlbpage.c | 33 | ||||
-rw-r--r-- | arch/sparc/mm/init_64.c | 12 | ||||
-rw-r--r-- | arch/sparc/mm/tlb.c | 25 | ||||
-rw-r--r-- | arch/sparc/mm/tsb.c | 32 |
6 files changed, 97 insertions, 51 deletions
diff --git a/arch/sparc/include/asm/pgtable_64.h b/arch/sparc/include/asm/pgtable_64.h index f089cfa249f3..5a189bf3c8ac 100644 --- a/arch/sparc/include/asm/pgtable_64.h +++ b/arch/sparc/include/asm/pgtable_64.h | |||
@@ -375,7 +375,7 @@ static inline pgprot_t pgprot_noncached(pgprot_t prot) | |||
375 | #define pgprot_noncached pgprot_noncached | 375 | #define pgprot_noncached pgprot_noncached |
376 | 376 | ||
377 | #if defined(CONFIG_HUGETLB_PAGE) || defined(CONFIG_TRANSPARENT_HUGEPAGE) | 377 | #if defined(CONFIG_HUGETLB_PAGE) || defined(CONFIG_TRANSPARENT_HUGEPAGE) |
378 | static inline pte_t pte_mkhuge(pte_t pte) | 378 | static inline unsigned long __pte_huge_mask(void) |
379 | { | 379 | { |
380 | unsigned long mask; | 380 | unsigned long mask; |
381 | 381 | ||
@@ -390,8 +390,19 @@ static inline pte_t pte_mkhuge(pte_t pte) | |||
390 | : "=r" (mask) | 390 | : "=r" (mask) |
391 | : "i" (_PAGE_SZHUGE_4U), "i" (_PAGE_SZHUGE_4V)); | 391 | : "i" (_PAGE_SZHUGE_4U), "i" (_PAGE_SZHUGE_4V)); |
392 | 392 | ||
393 | return __pte(pte_val(pte) | mask); | 393 | return mask; |
394 | } | ||
395 | |||
396 | static inline pte_t pte_mkhuge(pte_t pte) | ||
397 | { | ||
398 | return __pte(pte_val(pte) | __pte_huge_mask()); | ||
399 | } | ||
400 | |||
401 | static inline bool is_hugetlb_pte(pte_t pte) | ||
402 | { | ||
403 | return !!(pte_val(pte) & __pte_huge_mask()); | ||
394 | } | 404 | } |
405 | |||
395 | #ifdef CONFIG_TRANSPARENT_HUGEPAGE | 406 | #ifdef CONFIG_TRANSPARENT_HUGEPAGE |
396 | static inline pmd_t pmd_mkhuge(pmd_t pmd) | 407 | static inline pmd_t pmd_mkhuge(pmd_t pmd) |
397 | { | 408 | { |
@@ -403,6 +414,11 @@ static inline pmd_t pmd_mkhuge(pmd_t pmd) | |||
403 | return __pmd(pte_val(pte)); | 414 | return __pmd(pte_val(pte)); |
404 | } | 415 | } |
405 | #endif | 416 | #endif |
417 | #else | ||
418 | static inline bool is_hugetlb_pte(pte_t pte) | ||
419 | { | ||
420 | return false; | ||
421 | } | ||
406 | #endif | 422 | #endif |
407 | 423 | ||
408 | static inline pte_t pte_mkdirty(pte_t pte) | 424 | static inline pte_t pte_mkdirty(pte_t pte) |
@@ -858,6 +874,19 @@ static inline unsigned long pud_pfn(pud_t pud) | |||
858 | void tlb_batch_add(struct mm_struct *mm, unsigned long vaddr, | 874 | void tlb_batch_add(struct mm_struct *mm, unsigned long vaddr, |
859 | pte_t *ptep, pte_t orig, int fullmm); | 875 | pte_t *ptep, pte_t orig, int fullmm); |
860 | 876 | ||
877 | static void maybe_tlb_batch_add(struct mm_struct *mm, unsigned long vaddr, | ||
878 | pte_t *ptep, pte_t orig, int fullmm) | ||
879 | { | ||
880 | /* It is more efficient to let flush_tlb_kernel_range() | ||
881 | * handle init_mm tlb flushes. | ||
882 | * | ||
883 | * SUN4V NOTE: _PAGE_VALID is the same value in both the SUN4U | ||
884 | * and SUN4V pte layout, so this inline test is fine. | ||
885 | */ | ||
886 | if (likely(mm != &init_mm) && pte_accessible(mm, orig)) | ||
887 | tlb_batch_add(mm, vaddr, ptep, orig, fullmm); | ||
888 | } | ||
889 | |||
861 | #define __HAVE_ARCH_PMDP_HUGE_GET_AND_CLEAR | 890 | #define __HAVE_ARCH_PMDP_HUGE_GET_AND_CLEAR |
862 | static inline pmd_t pmdp_huge_get_and_clear(struct mm_struct *mm, | 891 | static inline pmd_t pmdp_huge_get_and_clear(struct mm_struct *mm, |
863 | unsigned long addr, | 892 | unsigned long addr, |
@@ -874,15 +903,7 @@ static inline void __set_pte_at(struct mm_struct *mm, unsigned long addr, | |||
874 | pte_t orig = *ptep; | 903 | pte_t orig = *ptep; |
875 | 904 | ||
876 | *ptep = pte; | 905 | *ptep = pte; |
877 | 906 | maybe_tlb_batch_add(mm, addr, ptep, orig, fullmm); | |
878 | /* It is more efficient to let flush_tlb_kernel_range() | ||
879 | * handle init_mm tlb flushes. | ||
880 | * | ||
881 | * SUN4V NOTE: _PAGE_VALID is the same value in both the SUN4U | ||
882 | * and SUN4V pte layout, so this inline test is fine. | ||
883 | */ | ||
884 | if (likely(mm != &init_mm) && pte_accessible(mm, orig)) | ||
885 | tlb_batch_add(mm, addr, ptep, orig, fullmm); | ||
886 | } | 907 | } |
887 | 908 | ||
888 | #define set_pte_at(mm,addr,ptep,pte) \ | 909 | #define set_pte_at(mm,addr,ptep,pte) \ |
diff --git a/arch/sparc/include/asm/tlbflush_64.h b/arch/sparc/include/asm/tlbflush_64.h index dea1cfa2122b..a8e192e90700 100644 --- a/arch/sparc/include/asm/tlbflush_64.h +++ b/arch/sparc/include/asm/tlbflush_64.h | |||
@@ -8,6 +8,7 @@ | |||
8 | #define TLB_BATCH_NR 192 | 8 | #define TLB_BATCH_NR 192 |
9 | 9 | ||
10 | struct tlb_batch { | 10 | struct tlb_batch { |
11 | bool huge; | ||
11 | struct mm_struct *mm; | 12 | struct mm_struct *mm; |
12 | unsigned long tlb_nr; | 13 | unsigned long tlb_nr; |
13 | unsigned long active; | 14 | unsigned long active; |
@@ -16,7 +17,7 @@ struct tlb_batch { | |||
16 | 17 | ||
17 | void flush_tsb_kernel_range(unsigned long start, unsigned long end); | 18 | void flush_tsb_kernel_range(unsigned long start, unsigned long end); |
18 | void flush_tsb_user(struct tlb_batch *tb); | 19 | void flush_tsb_user(struct tlb_batch *tb); |
19 | void flush_tsb_user_page(struct mm_struct *mm, unsigned long vaddr); | 20 | void flush_tsb_user_page(struct mm_struct *mm, unsigned long vaddr, bool huge); |
20 | 21 | ||
21 | /* TLB flush operations. */ | 22 | /* TLB flush operations. */ |
22 | 23 | ||
diff --git a/arch/sparc/mm/hugetlbpage.c b/arch/sparc/mm/hugetlbpage.c index 4977800e9770..ba52e6466a82 100644 --- a/arch/sparc/mm/hugetlbpage.c +++ b/arch/sparc/mm/hugetlbpage.c | |||
@@ -176,17 +176,31 @@ void set_huge_pte_at(struct mm_struct *mm, unsigned long addr, | |||
176 | pte_t *ptep, pte_t entry) | 176 | pte_t *ptep, pte_t entry) |
177 | { | 177 | { |
178 | int i; | 178 | int i; |
179 | pte_t orig[2]; | ||
180 | unsigned long nptes; | ||
179 | 181 | ||
180 | if (!pte_present(*ptep) && pte_present(entry)) | 182 | if (!pte_present(*ptep) && pte_present(entry)) |
181 | mm->context.huge_pte_count++; | 183 | mm->context.huge_pte_count++; |
182 | 184 | ||
183 | addr &= HPAGE_MASK; | 185 | addr &= HPAGE_MASK; |
184 | for (i = 0; i < (1 << HUGETLB_PAGE_ORDER); i++) { | 186 | |
185 | set_pte_at(mm, addr, ptep, entry); | 187 | nptes = 1 << HUGETLB_PAGE_ORDER; |
188 | orig[0] = *ptep; | ||
189 | orig[1] = *(ptep + nptes / 2); | ||
190 | for (i = 0; i < nptes; i++) { | ||
191 | *ptep = entry; | ||
186 | ptep++; | 192 | ptep++; |
187 | addr += PAGE_SIZE; | 193 | addr += PAGE_SIZE; |
188 | pte_val(entry) += PAGE_SIZE; | 194 | pte_val(entry) += PAGE_SIZE; |
189 | } | 195 | } |
196 | |||
197 | /* Issue TLB flush at REAL_HPAGE_SIZE boundaries */ | ||
198 | addr -= REAL_HPAGE_SIZE; | ||
199 | ptep -= nptes / 2; | ||
200 | maybe_tlb_batch_add(mm, addr, ptep, orig[1], 0); | ||
201 | addr -= REAL_HPAGE_SIZE; | ||
202 | ptep -= nptes / 2; | ||
203 | maybe_tlb_batch_add(mm, addr, ptep, orig[0], 0); | ||
190 | } | 204 | } |
191 | 205 | ||
192 | pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, | 206 | pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, |
@@ -194,19 +208,28 @@ pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, | |||
194 | { | 208 | { |
195 | pte_t entry; | 209 | pte_t entry; |
196 | int i; | 210 | int i; |
211 | unsigned long nptes; | ||
197 | 212 | ||
198 | entry = *ptep; | 213 | entry = *ptep; |
199 | if (pte_present(entry)) | 214 | if (pte_present(entry)) |
200 | mm->context.huge_pte_count--; | 215 | mm->context.huge_pte_count--; |
201 | 216 | ||
202 | addr &= HPAGE_MASK; | 217 | addr &= HPAGE_MASK; |
203 | 218 | nptes = 1 << HUGETLB_PAGE_ORDER; | |
204 | for (i = 0; i < (1 << HUGETLB_PAGE_ORDER); i++) { | 219 | for (i = 0; i < nptes; i++) { |
205 | pte_clear(mm, addr, ptep); | 220 | *ptep = __pte(0UL); |
206 | addr += PAGE_SIZE; | 221 | addr += PAGE_SIZE; |
207 | ptep++; | 222 | ptep++; |
208 | } | 223 | } |
209 | 224 | ||
225 | /* Issue TLB flush at REAL_HPAGE_SIZE boundaries */ | ||
226 | addr -= REAL_HPAGE_SIZE; | ||
227 | ptep -= nptes / 2; | ||
228 | maybe_tlb_batch_add(mm, addr, ptep, entry, 0); | ||
229 | addr -= REAL_HPAGE_SIZE; | ||
230 | ptep -= nptes / 2; | ||
231 | maybe_tlb_batch_add(mm, addr, ptep, entry, 0); | ||
232 | |||
210 | return entry; | 233 | return entry; |
211 | } | 234 | } |
212 | 235 | ||
diff --git a/arch/sparc/mm/init_64.c b/arch/sparc/mm/init_64.c index 09e838801e39..652683cb4b4b 100644 --- a/arch/sparc/mm/init_64.c +++ b/arch/sparc/mm/init_64.c | |||
@@ -324,18 +324,6 @@ static void __update_mmu_tsb_insert(struct mm_struct *mm, unsigned long tsb_inde | |||
324 | tsb_insert(tsb, tag, tte); | 324 | tsb_insert(tsb, tag, tte); |
325 | } | 325 | } |
326 | 326 | ||
327 | #if defined(CONFIG_HUGETLB_PAGE) || defined(CONFIG_TRANSPARENT_HUGEPAGE) | ||
328 | static inline bool is_hugetlb_pte(pte_t pte) | ||
329 | { | ||
330 | if ((tlb_type == hypervisor && | ||
331 | (pte_val(pte) & _PAGE_SZALL_4V) == _PAGE_SZHUGE_4V) || | ||
332 | (tlb_type != hypervisor && | ||
333 | (pte_val(pte) & _PAGE_SZALL_4U) == _PAGE_SZHUGE_4U)) | ||
334 | return true; | ||
335 | return false; | ||
336 | } | ||
337 | #endif | ||
338 | |||
339 | void update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t *ptep) | 327 | void update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t *ptep) |
340 | { | 328 | { |
341 | struct mm_struct *mm; | 329 | struct mm_struct *mm; |
diff --git a/arch/sparc/mm/tlb.c b/arch/sparc/mm/tlb.c index 9df2190c097e..f81cd9736700 100644 --- a/arch/sparc/mm/tlb.c +++ b/arch/sparc/mm/tlb.c | |||
@@ -67,7 +67,7 @@ void arch_leave_lazy_mmu_mode(void) | |||
67 | } | 67 | } |
68 | 68 | ||
69 | static void tlb_batch_add_one(struct mm_struct *mm, unsigned long vaddr, | 69 | static void tlb_batch_add_one(struct mm_struct *mm, unsigned long vaddr, |
70 | bool exec) | 70 | bool exec, bool huge) |
71 | { | 71 | { |
72 | struct tlb_batch *tb = &get_cpu_var(tlb_batch); | 72 | struct tlb_batch *tb = &get_cpu_var(tlb_batch); |
73 | unsigned long nr; | 73 | unsigned long nr; |
@@ -84,13 +84,21 @@ static void tlb_batch_add_one(struct mm_struct *mm, unsigned long vaddr, | |||
84 | } | 84 | } |
85 | 85 | ||
86 | if (!tb->active) { | 86 | if (!tb->active) { |
87 | flush_tsb_user_page(mm, vaddr); | 87 | flush_tsb_user_page(mm, vaddr, huge); |
88 | global_flush_tlb_page(mm, vaddr); | 88 | global_flush_tlb_page(mm, vaddr); |
89 | goto out; | 89 | goto out; |
90 | } | 90 | } |
91 | 91 | ||
92 | if (nr == 0) | 92 | if (nr == 0) { |
93 | tb->mm = mm; | 93 | tb->mm = mm; |
94 | tb->huge = huge; | ||
95 | } | ||
96 | |||
97 | if (tb->huge != huge) { | ||
98 | flush_tlb_pending(); | ||
99 | tb->huge = huge; | ||
100 | nr = 0; | ||
101 | } | ||
94 | 102 | ||
95 | tb->vaddrs[nr] = vaddr; | 103 | tb->vaddrs[nr] = vaddr; |
96 | tb->tlb_nr = ++nr; | 104 | tb->tlb_nr = ++nr; |
@@ -104,6 +112,8 @@ out: | |||
104 | void tlb_batch_add(struct mm_struct *mm, unsigned long vaddr, | 112 | void tlb_batch_add(struct mm_struct *mm, unsigned long vaddr, |
105 | pte_t *ptep, pte_t orig, int fullmm) | 113 | pte_t *ptep, pte_t orig, int fullmm) |
106 | { | 114 | { |
115 | bool huge = is_hugetlb_pte(orig); | ||
116 | |||
107 | if (tlb_type != hypervisor && | 117 | if (tlb_type != hypervisor && |
108 | pte_dirty(orig)) { | 118 | pte_dirty(orig)) { |
109 | unsigned long paddr, pfn = pte_pfn(orig); | 119 | unsigned long paddr, pfn = pte_pfn(orig); |
@@ -129,7 +139,7 @@ void tlb_batch_add(struct mm_struct *mm, unsigned long vaddr, | |||
129 | 139 | ||
130 | no_cache_flush: | 140 | no_cache_flush: |
131 | if (!fullmm) | 141 | if (!fullmm) |
132 | tlb_batch_add_one(mm, vaddr, pte_exec(orig)); | 142 | tlb_batch_add_one(mm, vaddr, pte_exec(orig), huge); |
133 | } | 143 | } |
134 | 144 | ||
135 | #ifdef CONFIG_TRANSPARENT_HUGEPAGE | 145 | #ifdef CONFIG_TRANSPARENT_HUGEPAGE |
@@ -145,7 +155,7 @@ static void tlb_batch_pmd_scan(struct mm_struct *mm, unsigned long vaddr, | |||
145 | if (pte_val(*pte) & _PAGE_VALID) { | 155 | if (pte_val(*pte) & _PAGE_VALID) { |
146 | bool exec = pte_exec(*pte); | 156 | bool exec = pte_exec(*pte); |
147 | 157 | ||
148 | tlb_batch_add_one(mm, vaddr, exec); | 158 | tlb_batch_add_one(mm, vaddr, exec, false); |
149 | } | 159 | } |
150 | pte++; | 160 | pte++; |
151 | vaddr += PAGE_SIZE; | 161 | vaddr += PAGE_SIZE; |
@@ -185,8 +195,9 @@ void set_pmd_at(struct mm_struct *mm, unsigned long addr, | |||
185 | pte_t orig_pte = __pte(pmd_val(orig)); | 195 | pte_t orig_pte = __pte(pmd_val(orig)); |
186 | bool exec = pte_exec(orig_pte); | 196 | bool exec = pte_exec(orig_pte); |
187 | 197 | ||
188 | tlb_batch_add_one(mm, addr, exec); | 198 | tlb_batch_add_one(mm, addr, exec, true); |
189 | tlb_batch_add_one(mm, addr + REAL_HPAGE_SIZE, exec); | 199 | tlb_batch_add_one(mm, addr + REAL_HPAGE_SIZE, exec, |
200 | true); | ||
190 | } else { | 201 | } else { |
191 | tlb_batch_pmd_scan(mm, addr, orig); | 202 | tlb_batch_pmd_scan(mm, addr, orig); |
192 | } | 203 | } |
diff --git a/arch/sparc/mm/tsb.c b/arch/sparc/mm/tsb.c index a06576683c38..a0604a493a36 100644 --- a/arch/sparc/mm/tsb.c +++ b/arch/sparc/mm/tsb.c | |||
@@ -76,14 +76,15 @@ void flush_tsb_user(struct tlb_batch *tb) | |||
76 | 76 | ||
77 | spin_lock_irqsave(&mm->context.lock, flags); | 77 | spin_lock_irqsave(&mm->context.lock, flags); |
78 | 78 | ||
79 | base = (unsigned long) mm->context.tsb_block[MM_TSB_BASE].tsb; | 79 | if (!tb->huge) { |
80 | nentries = mm->context.tsb_block[MM_TSB_BASE].tsb_nentries; | 80 | base = (unsigned long) mm->context.tsb_block[MM_TSB_BASE].tsb; |
81 | if (tlb_type == cheetah_plus || tlb_type == hypervisor) | 81 | nentries = mm->context.tsb_block[MM_TSB_BASE].tsb_nentries; |
82 | base = __pa(base); | 82 | if (tlb_type == cheetah_plus || tlb_type == hypervisor) |
83 | __flush_tsb_one(tb, PAGE_SHIFT, base, nentries); | 83 | base = __pa(base); |
84 | 84 | __flush_tsb_one(tb, PAGE_SHIFT, base, nentries); | |
85 | } | ||
85 | #if defined(CONFIG_HUGETLB_PAGE) || defined(CONFIG_TRANSPARENT_HUGEPAGE) | 86 | #if defined(CONFIG_HUGETLB_PAGE) || defined(CONFIG_TRANSPARENT_HUGEPAGE) |
86 | if (mm->context.tsb_block[MM_TSB_HUGE].tsb) { | 87 | if (tb->huge && mm->context.tsb_block[MM_TSB_HUGE].tsb) { |
87 | base = (unsigned long) mm->context.tsb_block[MM_TSB_HUGE].tsb; | 88 | base = (unsigned long) mm->context.tsb_block[MM_TSB_HUGE].tsb; |
88 | nentries = mm->context.tsb_block[MM_TSB_HUGE].tsb_nentries; | 89 | nentries = mm->context.tsb_block[MM_TSB_HUGE].tsb_nentries; |
89 | if (tlb_type == cheetah_plus || tlb_type == hypervisor) | 90 | if (tlb_type == cheetah_plus || tlb_type == hypervisor) |
@@ -94,20 +95,21 @@ void flush_tsb_user(struct tlb_batch *tb) | |||
94 | spin_unlock_irqrestore(&mm->context.lock, flags); | 95 | spin_unlock_irqrestore(&mm->context.lock, flags); |
95 | } | 96 | } |
96 | 97 | ||
97 | void flush_tsb_user_page(struct mm_struct *mm, unsigned long vaddr) | 98 | void flush_tsb_user_page(struct mm_struct *mm, unsigned long vaddr, bool huge) |
98 | { | 99 | { |
99 | unsigned long nentries, base, flags; | 100 | unsigned long nentries, base, flags; |
100 | 101 | ||
101 | spin_lock_irqsave(&mm->context.lock, flags); | 102 | spin_lock_irqsave(&mm->context.lock, flags); |
102 | 103 | ||
103 | base = (unsigned long) mm->context.tsb_block[MM_TSB_BASE].tsb; | 104 | if (!huge) { |
104 | nentries = mm->context.tsb_block[MM_TSB_BASE].tsb_nentries; | 105 | base = (unsigned long) mm->context.tsb_block[MM_TSB_BASE].tsb; |
105 | if (tlb_type == cheetah_plus || tlb_type == hypervisor) | 106 | nentries = mm->context.tsb_block[MM_TSB_BASE].tsb_nentries; |
106 | base = __pa(base); | 107 | if (tlb_type == cheetah_plus || tlb_type == hypervisor) |
107 | __flush_tsb_one_entry(base, vaddr, PAGE_SHIFT, nentries); | 108 | base = __pa(base); |
108 | 109 | __flush_tsb_one_entry(base, vaddr, PAGE_SHIFT, nentries); | |
110 | } | ||
109 | #if defined(CONFIG_HUGETLB_PAGE) || defined(CONFIG_TRANSPARENT_HUGEPAGE) | 111 | #if defined(CONFIG_HUGETLB_PAGE) || defined(CONFIG_TRANSPARENT_HUGEPAGE) |
110 | if (mm->context.tsb_block[MM_TSB_HUGE].tsb) { | 112 | if (huge && mm->context.tsb_block[MM_TSB_HUGE].tsb) { |
111 | base = (unsigned long) mm->context.tsb_block[MM_TSB_HUGE].tsb; | 113 | base = (unsigned long) mm->context.tsb_block[MM_TSB_HUGE].tsb; |
112 | nentries = mm->context.tsb_block[MM_TSB_HUGE].tsb_nentries; | 114 | nentries = mm->context.tsb_block[MM_TSB_HUGE].tsb_nentries; |
113 | if (tlb_type == cheetah_plus || tlb_type == hypervisor) | 115 | if (tlb_type == cheetah_plus || tlb_type == hypervisor) |