aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2016-05-22 22:24:13 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2016-05-22 22:24:13 -0400
commit21f9debf74c3ae8fdd26fd2bc3c0169a08eba6b4 (patch)
treea7e9cdcaf0177bb9606d6e5982937cce55df9898 /arch/sparc
parentbd28b14591b98f696bc9f94c5ba2e598ca487dfd (diff)
parent24e49ee3d76b70853a96520e46b8837e5eae65b2 (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc
Pull sparc updates from David Miller: "Some 32-bit kgdb cleanups from Sam Ravnborg, and a hugepage TLB flush overhead fix on 64-bit from Nitin Gupta" * git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc: sparc64: Reduce TLB flushes during hugepte changes aeroflex/greth: fix warning about unused variable openprom: fix warning sparc32: drop superfluous cast in calls to __nocache_pa() sparc32: fix build with STRICT_MM_TYPECHECKS sparc32: use proper prototype for trapbase sparc32: drop local prototype in kgdb_32 sparc32: drop hardcoding trap_level in kgdb_trap
Diffstat (limited to 'arch/sparc')
-rw-r--r--arch/sparc/include/asm/head_32.h8
-rw-r--r--arch/sparc/include/asm/kgdb.h2
-rw-r--r--arch/sparc/include/asm/page_32.h2
-rw-r--r--arch/sparc/include/asm/pgalloc_32.h4
-rw-r--r--arch/sparc/include/asm/pgtable_32.h2
-rw-r--r--arch/sparc/include/asm/pgtable_64.h43
-rw-r--r--arch/sparc/include/asm/tlbflush_64.h3
-rw-r--r--arch/sparc/kernel/entry.S10
-rw-r--r--arch/sparc/kernel/kernel.h1
-rw-r--r--arch/sparc/kernel/kgdb_32.c11
-rw-r--r--arch/sparc/kernel/setup_32.c4
-rw-r--r--arch/sparc/mm/hugetlbpage.c33
-rw-r--r--arch/sparc/mm/init_64.c12
-rw-r--r--arch/sparc/mm/io-unit.c4
-rw-r--r--arch/sparc/mm/srmmu.c19
-rw-r--r--arch/sparc/mm/tlb.c25
-rw-r--r--arch/sparc/mm/tsb.c32
17 files changed, 130 insertions, 85 deletions
diff --git a/arch/sparc/include/asm/head_32.h b/arch/sparc/include/asm/head_32.h
index 5f1dbe315bc8..6fc60fd182c4 100644
--- a/arch/sparc/include/asm/head_32.h
+++ b/arch/sparc/include/asm/head_32.h
@@ -43,10 +43,10 @@
43 nop; 43 nop;
44 44
45#ifdef CONFIG_KGDB 45#ifdef CONFIG_KGDB
46#define KGDB_TRAP(num) \ 46#define KGDB_TRAP(num) \
47 b kgdb_trap_low; \ 47 mov num, %l7; \
48 rd %psr,%l0; \ 48 b kgdb_trap_low; \
49 nop; \ 49 rd %psr,%l0; \
50 nop; 50 nop;
51#else 51#else
52#define KGDB_TRAP(num) \ 52#define KGDB_TRAP(num) \
diff --git a/arch/sparc/include/asm/kgdb.h b/arch/sparc/include/asm/kgdb.h
index 47366af7a589..a6ad7bf84bac 100644
--- a/arch/sparc/include/asm/kgdb.h
+++ b/arch/sparc/include/asm/kgdb.h
@@ -28,10 +28,10 @@ enum regnames {
28#define NUMREGBYTES ((GDB_CSR + 1) * 4) 28#define NUMREGBYTES ((GDB_CSR + 1) * 4)
29#else 29#else
30#define NUMREGBYTES ((GDB_Y + 1) * 8) 30#define NUMREGBYTES ((GDB_Y + 1) * 8)
31#endif
31 32
32struct pt_regs; 33struct pt_regs;
33asmlinkage void kgdb_trap(unsigned long trap_level, struct pt_regs *regs); 34asmlinkage void kgdb_trap(unsigned long trap_level, struct pt_regs *regs);
34#endif
35 35
36void arch_kgdb_breakpoint(void); 36void arch_kgdb_breakpoint(void);
37 37
diff --git a/arch/sparc/include/asm/page_32.h b/arch/sparc/include/asm/page_32.h
index f82a1f36b655..0efd0583a8c9 100644
--- a/arch/sparc/include/asm/page_32.h
+++ b/arch/sparc/include/asm/page_32.h
@@ -69,7 +69,6 @@ typedef struct { unsigned long iopgprot; } iopgprot_t;
69 69
70#define __pte(x) ((pte_t) { (x) } ) 70#define __pte(x) ((pte_t) { (x) } )
71#define __iopte(x) ((iopte_t) { (x) } ) 71#define __iopte(x) ((iopte_t) { (x) } )
72/* #define __pmd(x) ((pmd_t) { (x) } ) */ /* XXX procedure with loop */
73#define __pgd(x) ((pgd_t) { (x) } ) 72#define __pgd(x) ((pgd_t) { (x) } )
74#define __ctxd(x) ((ctxd_t) { (x) } ) 73#define __ctxd(x) ((ctxd_t) { (x) } )
75#define __pgprot(x) ((pgprot_t) { (x) } ) 74#define __pgprot(x) ((pgprot_t) { (x) } )
@@ -97,7 +96,6 @@ typedef unsigned long iopgprot_t;
97 96
98#define __pte(x) (x) 97#define __pte(x) (x)
99#define __iopte(x) (x) 98#define __iopte(x) (x)
100/* #define __pmd(x) (x) */ /* XXX later */
101#define __pgd(x) (x) 99#define __pgd(x) (x)
102#define __ctxd(x) (x) 100#define __ctxd(x) (x)
103#define __pgprot(x) (x) 101#define __pgprot(x) (x)
diff --git a/arch/sparc/include/asm/pgalloc_32.h b/arch/sparc/include/asm/pgalloc_32.h
index a3890da94428..0346c7e62452 100644
--- a/arch/sparc/include/asm/pgalloc_32.h
+++ b/arch/sparc/include/asm/pgalloc_32.h
@@ -29,9 +29,9 @@ static inline void free_pgd_fast(pgd_t *pgd)
29 29
30static inline void pgd_set(pgd_t * pgdp, pmd_t * pmdp) 30static inline void pgd_set(pgd_t * pgdp, pmd_t * pmdp)
31{ 31{
32 unsigned long pa = __nocache_pa((unsigned long)pmdp); 32 unsigned long pa = __nocache_pa(pmdp);
33 33
34 set_pte((pte_t *)pgdp, (SRMMU_ET_PTD | (pa >> 4))); 34 set_pte((pte_t *)pgdp, __pte((SRMMU_ET_PTD | (pa >> 4))));
35} 35}
36 36
37#define pgd_populate(MM, PGD, PMD) pgd_set(PGD, PMD) 37#define pgd_populate(MM, PGD, PMD) pgd_set(PGD, PMD)
diff --git a/arch/sparc/include/asm/pgtable_32.h b/arch/sparc/include/asm/pgtable_32.h
index 91b963a887b7..ce6f56980aef 100644
--- a/arch/sparc/include/asm/pgtable_32.h
+++ b/arch/sparc/include/asm/pgtable_32.h
@@ -298,7 +298,7 @@ static inline pte_t mk_pte_io(unsigned long page, pgprot_t pgprot, int space)
298#define pgprot_noncached pgprot_noncached 298#define pgprot_noncached pgprot_noncached
299static inline pgprot_t pgprot_noncached(pgprot_t prot) 299static inline pgprot_t pgprot_noncached(pgprot_t prot)
300{ 300{
301 prot &= ~__pgprot(SRMMU_CACHE); 301 pgprot_val(prot) &= ~pgprot_val(__pgprot(SRMMU_CACHE));
302 return prot; 302 return prot;
303} 303}
304 304
diff --git a/arch/sparc/include/asm/pgtable_64.h b/arch/sparc/include/asm/pgtable_64.h
index 93ce0ada3c63..e7d82803a48f 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)
378static inline pte_t pte_mkhuge(pte_t pte) 378static 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
396static inline pte_t pte_mkhuge(pte_t pte)
397{
398 return __pte(pte_val(pte) | __pte_huge_mask());
399}
400
401static 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
396static inline pmd_t pmd_mkhuge(pmd_t pmd) 407static 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
418static inline bool is_hugetlb_pte(pte_t pte)
419{
420 return false;
421}
406#endif 422#endif
407 423
408static inline pte_t pte_mkdirty(pte_t pte) 424static inline pte_t pte_mkdirty(pte_t pte)
@@ -856,6 +872,19 @@ static inline unsigned long pud_pfn(pud_t pud)
856void tlb_batch_add(struct mm_struct *mm, unsigned long vaddr, 872void tlb_batch_add(struct mm_struct *mm, unsigned long vaddr,
857 pte_t *ptep, pte_t orig, int fullmm); 873 pte_t *ptep, pte_t orig, int fullmm);
858 874
875static void maybe_tlb_batch_add(struct mm_struct *mm, unsigned long vaddr,
876 pte_t *ptep, pte_t orig, int fullmm)
877{
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, vaddr, ptep, orig, fullmm);
886}
887
859#define __HAVE_ARCH_PMDP_HUGE_GET_AND_CLEAR 888#define __HAVE_ARCH_PMDP_HUGE_GET_AND_CLEAR
860static inline pmd_t pmdp_huge_get_and_clear(struct mm_struct *mm, 889static inline pmd_t pmdp_huge_get_and_clear(struct mm_struct *mm,
861 unsigned long addr, 890 unsigned long addr,
@@ -872,15 +901,7 @@ static inline void __set_pte_at(struct mm_struct *mm, unsigned long addr,
872 pte_t orig = *ptep; 901 pte_t orig = *ptep;
873 902
874 *ptep = pte; 903 *ptep = pte;
875 904 maybe_tlb_batch_add(mm, addr, ptep, orig, fullmm);
876 /* It is more efficient to let flush_tlb_kernel_range()
877 * handle init_mm tlb flushes.
878 *
879 * SUN4V NOTE: _PAGE_VALID is the same value in both the SUN4U
880 * and SUN4V pte layout, so this inline test is fine.
881 */
882 if (likely(mm != &init_mm) && pte_accessible(mm, orig))
883 tlb_batch_add(mm, addr, ptep, orig, fullmm);
884} 905}
885 906
886#define set_pte_at(mm,addr,ptep,pte) \ 907#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
10struct tlb_batch { 10struct 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
17void flush_tsb_kernel_range(unsigned long start, unsigned long end); 18void flush_tsb_kernel_range(unsigned long start, unsigned long end);
18void flush_tsb_user(struct tlb_batch *tb); 19void flush_tsb_user(struct tlb_batch *tb);
19void flush_tsb_user_page(struct mm_struct *mm, unsigned long vaddr); 20void 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/kernel/entry.S b/arch/sparc/kernel/entry.S
index 51aa6e86a5f8..07918ab3062e 100644
--- a/arch/sparc/kernel/entry.S
+++ b/arch/sparc/kernel/entry.S
@@ -1225,20 +1225,18 @@ breakpoint_trap:
1225 RESTORE_ALL 1225 RESTORE_ALL
1226 1226
1227#ifdef CONFIG_KGDB 1227#ifdef CONFIG_KGDB
1228 .align 4 1228 ENTRY(kgdb_trap_low)
1229 .globl kgdb_trap_low
1230 .type kgdb_trap_low,#function
1231kgdb_trap_low:
1232 rd %wim,%l3 1229 rd %wim,%l3
1233 SAVE_ALL 1230 SAVE_ALL
1234 wr %l0, PSR_ET, %psr 1231 wr %l0, PSR_ET, %psr
1235 WRITE_PAUSE 1232 WRITE_PAUSE
1236 1233
1234 mov %l7, %o0 ! trap_level
1237 call kgdb_trap 1235 call kgdb_trap
1238 add %sp, STACKFRAME_SZ, %o0 1236 add %sp, STACKFRAME_SZ, %o1 ! struct pt_regs *regs
1239 1237
1240 RESTORE_ALL 1238 RESTORE_ALL
1241 .size kgdb_trap_low,.-kgdb_trap_low 1239 ENDPROC(kgdb_trap_low)
1242#endif 1240#endif
1243 1241
1244 .align 4 1242 .align 4
diff --git a/arch/sparc/kernel/kernel.h b/arch/sparc/kernel/kernel.h
index 5057ec2e4af6..c9804551262c 100644
--- a/arch/sparc/kernel/kernel.h
+++ b/arch/sparc/kernel/kernel.h
@@ -127,6 +127,7 @@ extern unsigned int t_nmi[];
127extern unsigned int linux_trap_ipi15_sun4d[]; 127extern unsigned int linux_trap_ipi15_sun4d[];
128extern unsigned int linux_trap_ipi15_sun4m[]; 128extern unsigned int linux_trap_ipi15_sun4m[];
129 129
130extern struct tt_entry trapbase;
130extern struct tt_entry trapbase_cpu1; 131extern struct tt_entry trapbase_cpu1;
131extern struct tt_entry trapbase_cpu2; 132extern struct tt_entry trapbase_cpu2;
132extern struct tt_entry trapbase_cpu3; 133extern struct tt_entry trapbase_cpu3;
diff --git a/arch/sparc/kernel/kgdb_32.c b/arch/sparc/kernel/kgdb_32.c
index dcf210811af4..6e8e318c57be 100644
--- a/arch/sparc/kernel/kgdb_32.c
+++ b/arch/sparc/kernel/kgdb_32.c
@@ -12,7 +12,8 @@
12#include <asm/irq.h> 12#include <asm/irq.h>
13#include <asm/cacheflush.h> 13#include <asm/cacheflush.h>
14 14
15extern unsigned long trapbase; 15#include "kernel.h"
16#include "entry.h"
16 17
17void pt_regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs) 18void pt_regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs)
18{ 19{
@@ -133,21 +134,19 @@ int kgdb_arch_handle_exception(int e_vector, int signo, int err_code,
133 return -1; 134 return -1;
134} 135}
135 136
136extern void do_hw_interrupt(struct pt_regs *regs, unsigned long type); 137asmlinkage void kgdb_trap(unsigned long trap_level, struct pt_regs *regs)
137
138asmlinkage void kgdb_trap(struct pt_regs *regs)
139{ 138{
140 unsigned long flags; 139 unsigned long flags;
141 140
142 if (user_mode(regs)) { 141 if (user_mode(regs)) {
143 do_hw_interrupt(regs, 0xfd); 142 do_hw_interrupt(regs, trap_level);
144 return; 143 return;
145 } 144 }
146 145
147 flushw_all(); 146 flushw_all();
148 147
149 local_irq_save(flags); 148 local_irq_save(flags);
150 kgdb_handle_exception(0x172, SIGTRAP, 0, regs); 149 kgdb_handle_exception(trap_level, SIGTRAP, 0, regs);
151 local_irq_restore(flags); 150 local_irq_restore(flags);
152} 151}
153 152
diff --git a/arch/sparc/kernel/setup_32.c b/arch/sparc/kernel/setup_32.c
index 69d75ff1c25c..c4e65cb3280f 100644
--- a/arch/sparc/kernel/setup_32.c
+++ b/arch/sparc/kernel/setup_32.c
@@ -68,8 +68,6 @@ struct screen_info screen_info = {
68 * prints out pretty messages and returns. 68 * prints out pretty messages and returns.
69 */ 69 */
70 70
71extern unsigned long trapbase;
72
73/* Pretty sick eh? */ 71/* Pretty sick eh? */
74static void prom_sync_me(void) 72static void prom_sync_me(void)
75{ 73{
@@ -300,7 +298,7 @@ void __init setup_arch(char **cmdline_p)
300 int i; 298 int i;
301 unsigned long highest_paddr; 299 unsigned long highest_paddr;
302 300
303 sparc_ttable = (struct tt_entry *) &trapbase; 301 sparc_ttable = &trapbase;
304 302
305 /* Initialize PROM console and command line. */ 303 /* Initialize PROM console and command line. */
306 *cmdline_p = prom_getbootargs(); 304 *cmdline_p = prom_getbootargs();
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
192pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, 206pte_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)
328static 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
339void update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t *ptep) 327void 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/io-unit.c b/arch/sparc/mm/io-unit.c
index f311bf219016..338fb71535de 100644
--- a/arch/sparc/mm/io-unit.c
+++ b/arch/sparc/mm/io-unit.c
@@ -133,7 +133,7 @@ nexti: scan = find_next_zero_bit(iounit->bmap, limit, scan);
133 vaddr = IOUNIT_DMA_BASE + (scan << PAGE_SHIFT) + (vaddr & ~PAGE_MASK); 133 vaddr = IOUNIT_DMA_BASE + (scan << PAGE_SHIFT) + (vaddr & ~PAGE_MASK);
134 for (k = 0; k < npages; k++, iopte = __iopte(iopte_val(iopte) + 0x100), scan++) { 134 for (k = 0; k < npages; k++, iopte = __iopte(iopte_val(iopte) + 0x100), scan++) {
135 set_bit(scan, iounit->bmap); 135 set_bit(scan, iounit->bmap);
136 sbus_writel(iopte, &iounit->page_table[scan]); 136 sbus_writel(iopte_val(iopte), &iounit->page_table[scan]);
137 } 137 }
138 IOD(("%08lx\n", vaddr)); 138 IOD(("%08lx\n", vaddr));
139 return vaddr; 139 return vaddr;
@@ -228,7 +228,7 @@ static int iounit_map_dma_area(struct device *dev, dma_addr_t *pba, unsigned lon
228 i = ((addr - IOUNIT_DMA_BASE) >> PAGE_SHIFT); 228 i = ((addr - IOUNIT_DMA_BASE) >> PAGE_SHIFT);
229 229
230 iopte = iounit->page_table + i; 230 iopte = iounit->page_table + i;
231 sbus_writel(MKIOPTE(__pa(page)), iopte); 231 sbus_writel(iopte_val(MKIOPTE(__pa(page))), iopte);
232 } 232 }
233 addr += PAGE_SIZE; 233 addr += PAGE_SIZE;
234 va += PAGE_SIZE; 234 va += PAGE_SIZE;
diff --git a/arch/sparc/mm/srmmu.c b/arch/sparc/mm/srmmu.c
index 5cbc96d801ff..c7f2a5295b3a 100644
--- a/arch/sparc/mm/srmmu.c
+++ b/arch/sparc/mm/srmmu.c
@@ -107,17 +107,22 @@ static inline int srmmu_pmd_none(pmd_t pmd)
107 107
108/* XXX should we hyper_flush_whole_icache here - Anton */ 108/* XXX should we hyper_flush_whole_icache here - Anton */
109static inline void srmmu_ctxd_set(ctxd_t *ctxp, pgd_t *pgdp) 109static inline void srmmu_ctxd_set(ctxd_t *ctxp, pgd_t *pgdp)
110{ set_pte((pte_t *)ctxp, (SRMMU_ET_PTD | (__nocache_pa((unsigned long) pgdp) >> 4))); } 110{
111 pte_t pte;
112
113 pte = __pte((SRMMU_ET_PTD | (__nocache_pa(pgdp) >> 4)));
114 set_pte((pte_t *)ctxp, pte);
115}
111 116
112void pmd_set(pmd_t *pmdp, pte_t *ptep) 117void pmd_set(pmd_t *pmdp, pte_t *ptep)
113{ 118{
114 unsigned long ptp; /* Physical address, shifted right by 4 */ 119 unsigned long ptp; /* Physical address, shifted right by 4 */
115 int i; 120 int i;
116 121
117 ptp = __nocache_pa((unsigned long) ptep) >> 4; 122 ptp = __nocache_pa(ptep) >> 4;
118 for (i = 0; i < PTRS_PER_PTE/SRMMU_REAL_PTRS_PER_PTE; i++) { 123 for (i = 0; i < PTRS_PER_PTE/SRMMU_REAL_PTRS_PER_PTE; i++) {
119 set_pte((pte_t *)&pmdp->pmdv[i], SRMMU_ET_PTD | ptp); 124 set_pte((pte_t *)&pmdp->pmdv[i], __pte(SRMMU_ET_PTD | ptp));
120 ptp += (SRMMU_REAL_PTRS_PER_PTE*sizeof(pte_t) >> 4); 125 ptp += (SRMMU_REAL_PTRS_PER_PTE * sizeof(pte_t) >> 4);
121 } 126 }
122} 127}
123 128
@@ -128,8 +133,8 @@ void pmd_populate(struct mm_struct *mm, pmd_t *pmdp, struct page *ptep)
128 133
129 ptp = page_to_pfn(ptep) << (PAGE_SHIFT-4); /* watch for overflow */ 134 ptp = page_to_pfn(ptep) << (PAGE_SHIFT-4); /* watch for overflow */
130 for (i = 0; i < PTRS_PER_PTE/SRMMU_REAL_PTRS_PER_PTE; i++) { 135 for (i = 0; i < PTRS_PER_PTE/SRMMU_REAL_PTRS_PER_PTE; i++) {
131 set_pte((pte_t *)&pmdp->pmdv[i], SRMMU_ET_PTD | ptp); 136 set_pte((pte_t *)&pmdp->pmdv[i], __pte(SRMMU_ET_PTD | ptp));
132 ptp += (SRMMU_REAL_PTRS_PER_PTE*sizeof(pte_t) >> 4); 137 ptp += (SRMMU_REAL_PTRS_PER_PTE * sizeof(pte_t) >> 4);
133 } 138 }
134} 139}
135 140
@@ -911,7 +916,7 @@ void __init srmmu_paging_init(void)
911 916
912 /* ctx table has to be physically aligned to its size */ 917 /* ctx table has to be physically aligned to its size */
913 srmmu_context_table = __srmmu_get_nocache(num_contexts * sizeof(ctxd_t), num_contexts * sizeof(ctxd_t)); 918 srmmu_context_table = __srmmu_get_nocache(num_contexts * sizeof(ctxd_t), num_contexts * sizeof(ctxd_t));
914 srmmu_ctx_table_phys = (ctxd_t *)__nocache_pa((unsigned long)srmmu_context_table); 919 srmmu_ctx_table_phys = (ctxd_t *)__nocache_pa(srmmu_context_table);
915 920
916 for (i = 0; i < num_contexts; i++) 921 for (i = 0; i < num_contexts; i++)
917 srmmu_ctxd_set((ctxd_t *)__nocache_fix(&srmmu_context_table[i]), srmmu_swapper_pg_dir); 922 srmmu_ctxd_set((ctxd_t *)__nocache_fix(&srmmu_context_table[i]), srmmu_swapper_pg_dir);
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 }
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
97void flush_tsb_user_page(struct mm_struct *mm, unsigned long vaddr) 98void 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)