aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc/mm/tlb.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sparc/mm/tlb.c')
-rw-r--r--arch/sparc/mm/tlb.c25
1 files changed, 18 insertions, 7 deletions
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
69static void tlb_batch_add_one(struct mm_struct *mm, unsigned long vaddr, 69static 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:
104void tlb_batch_add(struct mm_struct *mm, unsigned long vaddr, 112void 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
130no_cache_flush: 140no_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 }