aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/mm
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips/mm')
-rw-r--r--arch/mips/mm/c-octeon.c2
-rw-r--r--arch/mips/mm/c-r4k.c77
-rw-r--r--arch/mips/mm/init.c82
-rw-r--r--arch/mips/mm/tlb-r4k.c88
-rw-r--r--arch/mips/mm/tlbex.c2
-rw-r--r--arch/mips/mm/uasm-micromips.c14
-rw-r--r--arch/mips/mm/uasm-mips.c15
-rw-r--r--arch/mips/mm/uasm.c51
8 files changed, 213 insertions, 118 deletions
diff --git a/arch/mips/mm/c-octeon.c b/arch/mips/mm/c-octeon.c
index f41a5c5b0865..05b1d7cf9514 100644
--- a/arch/mips/mm/c-octeon.c
+++ b/arch/mips/mm/c-octeon.c
@@ -137,8 +137,10 @@ static void octeon_flush_cache_sigtramp(unsigned long addr)
137{ 137{
138 struct vm_area_struct *vma; 138 struct vm_area_struct *vma;
139 139
140 down_read(&current->mm->mmap_sem);
140 vma = find_vma(current->mm, addr); 141 vma = find_vma(current->mm, addr);
141 octeon_flush_icache_all_cores(vma); 142 octeon_flush_icache_all_cores(vma);
143 up_read(&current->mm->mmap_sem);
142} 144}
143 145
144 146
diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c
index 1c74a6ad072a..f2e8302fa70f 100644
--- a/arch/mips/mm/c-r4k.c
+++ b/arch/mips/mm/c-r4k.c
@@ -7,6 +7,7 @@
7 * Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Ralf Baechle (ralf@gnu.org) 7 * Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Ralf Baechle (ralf@gnu.org)
8 * Copyright (C) 1999, 2000 Silicon Graphics, Inc. 8 * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
9 */ 9 */
10#include <linux/cpu_pm.h>
10#include <linux/hardirq.h> 11#include <linux/hardirq.h>
11#include <linux/init.h> 12#include <linux/init.h>
12#include <linux/highmem.h> 13#include <linux/highmem.h>
@@ -50,7 +51,7 @@ static inline void r4k_on_each_cpu(void (*func) (void *info), void *info)
50{ 51{
51 preempt_disable(); 52 preempt_disable();
52 53
53#if !defined(CONFIG_MIPS_MT_SMP) && !defined(CONFIG_MIPS_MT_SMTC) 54#ifndef CONFIG_MIPS_MT_SMP
54 smp_call_function(func, info, 1); 55 smp_call_function(func, info, 1);
55#endif 56#endif
56 func(info); 57 func(info);
@@ -105,22 +106,37 @@ static inline void r4k_blast_dcache_page_dc32(unsigned long addr)
105 106
106static inline void r4k_blast_dcache_page_dc64(unsigned long addr) 107static inline void r4k_blast_dcache_page_dc64(unsigned long addr)
107{ 108{
108 R4600_HIT_CACHEOP_WAR_IMPL;
109 blast_dcache64_page(addr); 109 blast_dcache64_page(addr);
110} 110}
111 111
112static inline void r4k_blast_dcache_page_dc128(unsigned long addr)
113{
114 blast_dcache128_page(addr);
115}
116
112static void r4k_blast_dcache_page_setup(void) 117static void r4k_blast_dcache_page_setup(void)
113{ 118{
114 unsigned long dc_lsize = cpu_dcache_line_size(); 119 unsigned long dc_lsize = cpu_dcache_line_size();
115 120
116 if (dc_lsize == 0) 121 switch (dc_lsize) {
122 case 0:
117 r4k_blast_dcache_page = (void *)cache_noop; 123 r4k_blast_dcache_page = (void *)cache_noop;
118 else if (dc_lsize == 16) 124 break;
125 case 16:
119 r4k_blast_dcache_page = blast_dcache16_page; 126 r4k_blast_dcache_page = blast_dcache16_page;
120 else if (dc_lsize == 32) 127 break;
128 case 32:
121 r4k_blast_dcache_page = r4k_blast_dcache_page_dc32; 129 r4k_blast_dcache_page = r4k_blast_dcache_page_dc32;
122 else if (dc_lsize == 64) 130 break;
131 case 64:
123 r4k_blast_dcache_page = r4k_blast_dcache_page_dc64; 132 r4k_blast_dcache_page = r4k_blast_dcache_page_dc64;
133 break;
134 case 128:
135 r4k_blast_dcache_page = r4k_blast_dcache_page_dc128;
136 break;
137 default:
138 break;
139 }
124} 140}
125 141
126#ifndef CONFIG_EVA 142#ifndef CONFIG_EVA
@@ -159,6 +175,8 @@ static void r4k_blast_dcache_page_indexed_setup(void)
159 r4k_blast_dcache_page_indexed = blast_dcache32_page_indexed; 175 r4k_blast_dcache_page_indexed = blast_dcache32_page_indexed;
160 else if (dc_lsize == 64) 176 else if (dc_lsize == 64)
161 r4k_blast_dcache_page_indexed = blast_dcache64_page_indexed; 177 r4k_blast_dcache_page_indexed = blast_dcache64_page_indexed;
178 else if (dc_lsize == 128)
179 r4k_blast_dcache_page_indexed = blast_dcache128_page_indexed;
162} 180}
163 181
164void (* r4k_blast_dcache)(void); 182void (* r4k_blast_dcache)(void);
@@ -176,6 +194,8 @@ static void r4k_blast_dcache_setup(void)
176 r4k_blast_dcache = blast_dcache32; 194 r4k_blast_dcache = blast_dcache32;
177 else if (dc_lsize == 64) 195 else if (dc_lsize == 64)
178 r4k_blast_dcache = blast_dcache64; 196 r4k_blast_dcache = blast_dcache64;
197 else if (dc_lsize == 128)
198 r4k_blast_dcache = blast_dcache128;
179} 199}
180 200
181/* force code alignment (used for TX49XX_ICACHE_INDEX_INV_WAR) */ 201/* force code alignment (used for TX49XX_ICACHE_INDEX_INV_WAR) */
@@ -265,6 +285,8 @@ static void r4k_blast_icache_page_setup(void)
265 r4k_blast_icache_page = blast_icache32_page; 285 r4k_blast_icache_page = blast_icache32_page;
266 else if (ic_lsize == 64) 286 else if (ic_lsize == 64)
267 r4k_blast_icache_page = blast_icache64_page; 287 r4k_blast_icache_page = blast_icache64_page;
288 else if (ic_lsize == 128)
289 r4k_blast_icache_page = blast_icache128_page;
268} 290}
269 291
270#ifndef CONFIG_EVA 292#ifndef CONFIG_EVA
@@ -338,6 +360,8 @@ static void r4k_blast_icache_setup(void)
338 r4k_blast_icache = blast_icache32; 360 r4k_blast_icache = blast_icache32;
339 } else if (ic_lsize == 64) 361 } else if (ic_lsize == 64)
340 r4k_blast_icache = blast_icache64; 362 r4k_blast_icache = blast_icache64;
363 else if (ic_lsize == 128)
364 r4k_blast_icache = blast_icache128;
341} 365}
342 366
343static void (* r4k_blast_scache_page)(unsigned long addr); 367static void (* r4k_blast_scache_page)(unsigned long addr);
@@ -428,7 +452,7 @@ static void r4k___flush_cache_all(void)
428 452
429static inline int has_valid_asid(const struct mm_struct *mm) 453static inline int has_valid_asid(const struct mm_struct *mm)
430{ 454{
431#if defined(CONFIG_MIPS_MT_SMP) || defined(CONFIG_MIPS_MT_SMTC) 455#ifdef CONFIG_MIPS_MT_SMP
432 int i; 456 int i;
433 457
434 for_each_online_cpu(i) 458 for_each_online_cpu(i)
@@ -1094,6 +1118,21 @@ static void probe_pcache(void)
1094 c->dcache.waybit = 0; 1118 c->dcache.waybit = 0;
1095 break; 1119 break;
1096 1120
1121 case CPU_CAVIUM_OCTEON3:
1122 /* For now lie about the number of ways. */
1123 c->icache.linesz = 128;
1124 c->icache.sets = 16;
1125 c->icache.ways = 8;
1126 c->icache.flags |= MIPS_CACHE_VTAG;
1127 icache_size = c->icache.sets * c->icache.ways * c->icache.linesz;
1128
1129 c->dcache.linesz = 128;
1130 c->dcache.ways = 8;
1131 c->dcache.sets = 8;
1132 dcache_size = c->dcache.sets * c->dcache.ways * c->dcache.linesz;
1133 c->options |= MIPS_CPU_PREFETCH;
1134 break;
1135
1097 default: 1136 default:
1098 if (!(config & MIPS_CONF_M)) 1137 if (!(config & MIPS_CONF_M))
1099 panic("Don't know how to probe P-caches on this cpu."); 1138 panic("Don't know how to probe P-caches on this cpu.");
@@ -1414,6 +1453,7 @@ static void setup_scache(void)
1414 loongson3_sc_init(); 1453 loongson3_sc_init();
1415 return; 1454 return;
1416 1455
1456 case CPU_CAVIUM_OCTEON3:
1417 case CPU_XLP: 1457 case CPU_XLP:
1418 /* don't need to worry about L2, fully coherent */ 1458 /* don't need to worry about L2, fully coherent */
1419 return; 1459 return;
@@ -1644,3 +1684,26 @@ void r4k_cache_init(void)
1644 coherency_setup(); 1684 coherency_setup();
1645 board_cache_error_setup = r4k_cache_error_setup; 1685 board_cache_error_setup = r4k_cache_error_setup;
1646} 1686}
1687
1688static int r4k_cache_pm_notifier(struct notifier_block *self, unsigned long cmd,
1689 void *v)
1690{
1691 switch (cmd) {
1692 case CPU_PM_ENTER_FAILED:
1693 case CPU_PM_EXIT:
1694 coherency_setup();
1695 break;
1696 }
1697
1698 return NOTIFY_OK;
1699}
1700
1701static struct notifier_block r4k_cache_pm_notifier_block = {
1702 .notifier_call = r4k_cache_pm_notifier,
1703};
1704
1705int __init r4k_cache_init_pm(void)
1706{
1707 return cpu_pm_register_notifier(&r4k_cache_pm_notifier_block);
1708}
1709arch_initcall(r4k_cache_init_pm);
diff --git a/arch/mips/mm/init.c b/arch/mips/mm/init.c
index 4fc74c78265a..6e4413330e36 100644
--- a/arch/mips/mm/init.c
+++ b/arch/mips/mm/init.c
@@ -44,27 +44,6 @@
44#include <asm/tlb.h> 44#include <asm/tlb.h>
45#include <asm/fixmap.h> 45#include <asm/fixmap.h>
46 46
47/* Atomicity and interruptability */
48#ifdef CONFIG_MIPS_MT_SMTC
49
50#include <asm/mipsmtregs.h>
51
52#define ENTER_CRITICAL(flags) \
53 { \
54 unsigned int mvpflags; \
55 local_irq_save(flags);\
56 mvpflags = dvpe()
57#define EXIT_CRITICAL(flags) \
58 evpe(mvpflags); \
59 local_irq_restore(flags); \
60 }
61#else
62
63#define ENTER_CRITICAL(flags) local_irq_save(flags)
64#define EXIT_CRITICAL(flags) local_irq_restore(flags)
65
66#endif /* CONFIG_MIPS_MT_SMTC */
67
68/* 47/*
69 * We have up to 8 empty zeroed pages so we can map one of the right colour 48 * We have up to 8 empty zeroed pages so we can map one of the right colour
70 * when needed. This is necessary only on R4000 / R4400 SC and MC versions 49 * when needed. This is necessary only on R4000 / R4400 SC and MC versions
@@ -100,21 +79,7 @@ void setup_zero_pages(void)
100 zero_page_mask = ((PAGE_SIZE << order) - 1) & PAGE_MASK; 79 zero_page_mask = ((PAGE_SIZE << order) - 1) & PAGE_MASK;
101} 80}
102 81
103#ifdef CONFIG_MIPS_MT_SMTC 82static void *__kmap_pgprot(struct page *page, unsigned long addr, pgprot_t prot)
104static pte_t *kmap_coherent_pte;
105static void __init kmap_coherent_init(void)
106{
107 unsigned long vaddr;
108
109 /* cache the first coherent kmap pte */
110 vaddr = __fix_to_virt(FIX_CMAP_BEGIN);
111 kmap_coherent_pte = kmap_get_fixmap_pte(vaddr);
112}
113#else
114static inline void kmap_coherent_init(void) {}
115#endif
116
117void *kmap_coherent(struct page *page, unsigned long addr)
118{ 83{
119 enum fixed_addresses idx; 84 enum fixed_addresses idx;
120 unsigned long vaddr, flags, entrylo; 85 unsigned long vaddr, flags, entrylo;
@@ -126,58 +91,48 @@ void *kmap_coherent(struct page *page, unsigned long addr)
126 91
127 pagefault_disable(); 92 pagefault_disable();
128 idx = (addr >> PAGE_SHIFT) & (FIX_N_COLOURS - 1); 93 idx = (addr >> PAGE_SHIFT) & (FIX_N_COLOURS - 1);
129#ifdef CONFIG_MIPS_MT_SMTC
130 idx += FIX_N_COLOURS * smp_processor_id() +
131 (in_interrupt() ? (FIX_N_COLOURS * NR_CPUS) : 0);
132#else
133 idx += in_interrupt() ? FIX_N_COLOURS : 0; 94 idx += in_interrupt() ? FIX_N_COLOURS : 0;
134#endif
135 vaddr = __fix_to_virt(FIX_CMAP_END - idx); 95 vaddr = __fix_to_virt(FIX_CMAP_END - idx);
136 pte = mk_pte(page, PAGE_KERNEL); 96 pte = mk_pte(page, prot);
137#if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32) 97#if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32)
138 entrylo = pte.pte_high; 98 entrylo = pte.pte_high;
139#else 99#else
140 entrylo = pte_to_entrylo(pte_val(pte)); 100 entrylo = pte_to_entrylo(pte_val(pte));
141#endif 101#endif
142 102
143 ENTER_CRITICAL(flags); 103 local_irq_save(flags);
144 old_ctx = read_c0_entryhi(); 104 old_ctx = read_c0_entryhi();
145 write_c0_entryhi(vaddr & (PAGE_MASK << 1)); 105 write_c0_entryhi(vaddr & (PAGE_MASK << 1));
146 write_c0_entrylo0(entrylo); 106 write_c0_entrylo0(entrylo);
147 write_c0_entrylo1(entrylo); 107 write_c0_entrylo1(entrylo);
148#ifdef CONFIG_MIPS_MT_SMTC
149 set_pte(kmap_coherent_pte - (FIX_CMAP_END - idx), pte);
150 /* preload TLB instead of local_flush_tlb_one() */
151 mtc0_tlbw_hazard();
152 tlb_probe();
153 tlb_probe_hazard();
154 tlbidx = read_c0_index();
155 mtc0_tlbw_hazard();
156 if (tlbidx < 0)
157 tlb_write_random();
158 else
159 tlb_write_indexed();
160#else
161 tlbidx = read_c0_wired(); 108 tlbidx = read_c0_wired();
162 write_c0_wired(tlbidx + 1); 109 write_c0_wired(tlbidx + 1);
163 write_c0_index(tlbidx); 110 write_c0_index(tlbidx);
164 mtc0_tlbw_hazard(); 111 mtc0_tlbw_hazard();
165 tlb_write_indexed(); 112 tlb_write_indexed();
166#endif
167 tlbw_use_hazard(); 113 tlbw_use_hazard();
168 write_c0_entryhi(old_ctx); 114 write_c0_entryhi(old_ctx);
169 EXIT_CRITICAL(flags); 115 local_irq_restore(flags);
170 116
171 return (void*) vaddr; 117 return (void*) vaddr;
172} 118}
173 119
120void *kmap_coherent(struct page *page, unsigned long addr)
121{
122 return __kmap_pgprot(page, addr, PAGE_KERNEL);
123}
124
125void *kmap_noncoherent(struct page *page, unsigned long addr)
126{
127 return __kmap_pgprot(page, addr, PAGE_KERNEL_NC);
128}
129
174void kunmap_coherent(void) 130void kunmap_coherent(void)
175{ 131{
176#ifndef CONFIG_MIPS_MT_SMTC
177 unsigned int wired; 132 unsigned int wired;
178 unsigned long flags, old_ctx; 133 unsigned long flags, old_ctx;
179 134
180 ENTER_CRITICAL(flags); 135 local_irq_save(flags);
181 old_ctx = read_c0_entryhi(); 136 old_ctx = read_c0_entryhi();
182 wired = read_c0_wired() - 1; 137 wired = read_c0_wired() - 1;
183 write_c0_wired(wired); 138 write_c0_wired(wired);
@@ -189,8 +144,7 @@ void kunmap_coherent(void)
189 tlb_write_indexed(); 144 tlb_write_indexed();
190 tlbw_use_hazard(); 145 tlbw_use_hazard();
191 write_c0_entryhi(old_ctx); 146 write_c0_entryhi(old_ctx);
192 EXIT_CRITICAL(flags); 147 local_irq_restore(flags);
193#endif
194 pagefault_enable(); 148 pagefault_enable();
195} 149}
196 150
@@ -256,7 +210,7 @@ EXPORT_SYMBOL_GPL(copy_from_user_page);
256void __init fixrange_init(unsigned long start, unsigned long end, 210void __init fixrange_init(unsigned long start, unsigned long end,
257 pgd_t *pgd_base) 211 pgd_t *pgd_base)
258{ 212{
259#if defined(CONFIG_HIGHMEM) || defined(CONFIG_MIPS_MT_SMTC) 213#ifdef CONFIG_HIGHMEM
260 pgd_t *pgd; 214 pgd_t *pgd;
261 pud_t *pud; 215 pud_t *pud;
262 pmd_t *pmd; 216 pmd_t *pmd;
@@ -327,8 +281,6 @@ void __init paging_init(void)
327#ifdef CONFIG_HIGHMEM 281#ifdef CONFIG_HIGHMEM
328 kmap_init(); 282 kmap_init();
329#endif 283#endif
330 kmap_coherent_init();
331
332#ifdef CONFIG_ZONE_DMA 284#ifdef CONFIG_ZONE_DMA
333 max_zone_pfns[ZONE_DMA] = MAX_DMA_PFN; 285 max_zone_pfns[ZONE_DMA] = MAX_DMA_PFN;
334#endif 286#endif
diff --git a/arch/mips/mm/tlb-r4k.c b/arch/mips/mm/tlb-r4k.c
index eeaf50f5df2b..3914e27456f2 100644
--- a/arch/mips/mm/tlb-r4k.c
+++ b/arch/mips/mm/tlb-r4k.c
@@ -8,6 +8,7 @@
8 * Carsten Langgaard, carstenl@mips.com 8 * Carsten Langgaard, carstenl@mips.com
9 * Copyright (C) 2002 MIPS Technologies, Inc. All rights reserved. 9 * Copyright (C) 2002 MIPS Technologies, Inc. All rights reserved.
10 */ 10 */
11#include <linux/cpu_pm.h>
11#include <linux/init.h> 12#include <linux/init.h>
12#include <linux/sched.h> 13#include <linux/sched.h>
13#include <linux/smp.h> 14#include <linux/smp.h>
@@ -25,28 +26,6 @@
25 26
26extern void build_tlb_refill_handler(void); 27extern void build_tlb_refill_handler(void);
27 28
28/* Atomicity and interruptability */
29#ifdef CONFIG_MIPS_MT_SMTC
30
31#include <asm/smtc.h>
32#include <asm/mipsmtregs.h>
33
34#define ENTER_CRITICAL(flags) \
35 { \
36 unsigned int mvpflags; \
37 local_irq_save(flags);\
38 mvpflags = dvpe()
39#define EXIT_CRITICAL(flags) \
40 evpe(mvpflags); \
41 local_irq_restore(flags); \
42 }
43#else
44
45#define ENTER_CRITICAL(flags) local_irq_save(flags)
46#define EXIT_CRITICAL(flags) local_irq_restore(flags)
47
48#endif /* CONFIG_MIPS_MT_SMTC */
49
50/* 29/*
51 * LOONGSON2/3 has a 4 entry itlb which is a subset of dtlb, 30 * LOONGSON2/3 has a 4 entry itlb which is a subset of dtlb,
52 * unfortunately, itlb is not totally transparent to software. 31 * unfortunately, itlb is not totally transparent to software.
@@ -75,7 +54,7 @@ void local_flush_tlb_all(void)
75 unsigned long old_ctx; 54 unsigned long old_ctx;
76 int entry, ftlbhighset; 55 int entry, ftlbhighset;
77 56
78 ENTER_CRITICAL(flags); 57 local_irq_save(flags);
79 /* Save old context and create impossible VPN2 value */ 58 /* Save old context and create impossible VPN2 value */
80 old_ctx = read_c0_entryhi(); 59 old_ctx = read_c0_entryhi();
81 write_c0_entrylo0(0); 60 write_c0_entrylo0(0);
@@ -112,7 +91,7 @@ void local_flush_tlb_all(void)
112 tlbw_use_hazard(); 91 tlbw_use_hazard();
113 write_c0_entryhi(old_ctx); 92 write_c0_entryhi(old_ctx);
114 flush_itlb(); 93 flush_itlb();
115 EXIT_CRITICAL(flags); 94 local_irq_restore(flags);
116} 95}
117EXPORT_SYMBOL(local_flush_tlb_all); 96EXPORT_SYMBOL(local_flush_tlb_all);
118 97
@@ -142,7 +121,7 @@ void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
142 if (cpu_context(cpu, mm) != 0) { 121 if (cpu_context(cpu, mm) != 0) {
143 unsigned long size, flags; 122 unsigned long size, flags;
144 123
145 ENTER_CRITICAL(flags); 124 local_irq_save(flags);
146 start = round_down(start, PAGE_SIZE << 1); 125 start = round_down(start, PAGE_SIZE << 1);
147 end = round_up(end, PAGE_SIZE << 1); 126 end = round_up(end, PAGE_SIZE << 1);
148 size = (end - start) >> (PAGE_SHIFT + 1); 127 size = (end - start) >> (PAGE_SHIFT + 1);
@@ -176,7 +155,7 @@ void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
176 drop_mmu_context(mm, cpu); 155 drop_mmu_context(mm, cpu);
177 } 156 }
178 flush_itlb(); 157 flush_itlb();
179 EXIT_CRITICAL(flags); 158 local_irq_restore(flags);
180 } 159 }
181} 160}
182 161
@@ -184,7 +163,7 @@ void local_flush_tlb_kernel_range(unsigned long start, unsigned long end)
184{ 163{
185 unsigned long size, flags; 164 unsigned long size, flags;
186 165
187 ENTER_CRITICAL(flags); 166 local_irq_save(flags);
188 size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT; 167 size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
189 size = (size + 1) >> 1; 168 size = (size + 1) >> 1;
190 if (size <= (current_cpu_data.tlbsizeftlbsets ? 169 if (size <= (current_cpu_data.tlbsizeftlbsets ?
@@ -220,7 +199,7 @@ void local_flush_tlb_kernel_range(unsigned long start, unsigned long end)
220 local_flush_tlb_all(); 199 local_flush_tlb_all();
221 } 200 }
222 flush_itlb(); 201 flush_itlb();
223 EXIT_CRITICAL(flags); 202 local_irq_restore(flags);
224} 203}
225 204
226void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page) 205void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
@@ -233,7 +212,7 @@ void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
233 212
234 newpid = cpu_asid(cpu, vma->vm_mm); 213 newpid = cpu_asid(cpu, vma->vm_mm);
235 page &= (PAGE_MASK << 1); 214 page &= (PAGE_MASK << 1);
236 ENTER_CRITICAL(flags); 215 local_irq_save(flags);
237 oldpid = read_c0_entryhi(); 216 oldpid = read_c0_entryhi();
238 write_c0_entryhi(page | newpid); 217 write_c0_entryhi(page | newpid);
239 mtc0_tlbw_hazard(); 218 mtc0_tlbw_hazard();
@@ -253,7 +232,7 @@ void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
253 finish: 232 finish:
254 write_c0_entryhi(oldpid); 233 write_c0_entryhi(oldpid);
255 flush_itlb_vm(vma); 234 flush_itlb_vm(vma);
256 EXIT_CRITICAL(flags); 235 local_irq_restore(flags);
257 } 236 }
258} 237}
259 238
@@ -266,7 +245,7 @@ void local_flush_tlb_one(unsigned long page)
266 unsigned long flags; 245 unsigned long flags;
267 int oldpid, idx; 246 int oldpid, idx;
268 247
269 ENTER_CRITICAL(flags); 248 local_irq_save(flags);
270 oldpid = read_c0_entryhi(); 249 oldpid = read_c0_entryhi();
271 page &= (PAGE_MASK << 1); 250 page &= (PAGE_MASK << 1);
272 write_c0_entryhi(page); 251 write_c0_entryhi(page);
@@ -285,7 +264,7 @@ void local_flush_tlb_one(unsigned long page)
285 } 264 }
286 write_c0_entryhi(oldpid); 265 write_c0_entryhi(oldpid);
287 flush_itlb(); 266 flush_itlb();
288 EXIT_CRITICAL(flags); 267 local_irq_restore(flags);
289} 268}
290 269
291/* 270/*
@@ -308,7 +287,7 @@ void __update_tlb(struct vm_area_struct * vma, unsigned long address, pte_t pte)
308 if (current->active_mm != vma->vm_mm) 287 if (current->active_mm != vma->vm_mm)
309 return; 288 return;
310 289
311 ENTER_CRITICAL(flags); 290 local_irq_save(flags);
312 291
313 pid = read_c0_entryhi() & ASID_MASK; 292 pid = read_c0_entryhi() & ASID_MASK;
314 address &= (PAGE_MASK << 1); 293 address &= (PAGE_MASK << 1);
@@ -358,7 +337,7 @@ void __update_tlb(struct vm_area_struct * vma, unsigned long address, pte_t pte)
358 } 337 }
359 tlbw_use_hazard(); 338 tlbw_use_hazard();
360 flush_itlb_vm(vma); 339 flush_itlb_vm(vma);
361 EXIT_CRITICAL(flags); 340 local_irq_restore(flags);
362} 341}
363 342
364void add_wired_entry(unsigned long entrylo0, unsigned long entrylo1, 343void add_wired_entry(unsigned long entrylo0, unsigned long entrylo1,
@@ -369,7 +348,7 @@ void add_wired_entry(unsigned long entrylo0, unsigned long entrylo1,
369 unsigned long old_pagemask; 348 unsigned long old_pagemask;
370 unsigned long old_ctx; 349 unsigned long old_ctx;
371 350
372 ENTER_CRITICAL(flags); 351 local_irq_save(flags);
373 /* Save old context and create impossible VPN2 value */ 352 /* Save old context and create impossible VPN2 value */
374 old_ctx = read_c0_entryhi(); 353 old_ctx = read_c0_entryhi();
375 old_pagemask = read_c0_pagemask(); 354 old_pagemask = read_c0_pagemask();
@@ -389,7 +368,7 @@ void add_wired_entry(unsigned long entrylo0, unsigned long entrylo1,
389 tlbw_use_hazard(); /* What is the hazard here? */ 368 tlbw_use_hazard(); /* What is the hazard here? */
390 write_c0_pagemask(old_pagemask); 369 write_c0_pagemask(old_pagemask);
391 local_flush_tlb_all(); 370 local_flush_tlb_all();
392 EXIT_CRITICAL(flags); 371 local_irq_restore(flags);
393} 372}
394 373
395#ifdef CONFIG_TRANSPARENT_HUGEPAGE 374#ifdef CONFIG_TRANSPARENT_HUGEPAGE
@@ -399,13 +378,13 @@ int __init has_transparent_hugepage(void)
399 unsigned int mask; 378 unsigned int mask;
400 unsigned long flags; 379 unsigned long flags;
401 380
402 ENTER_CRITICAL(flags); 381 local_irq_save(flags);
403 write_c0_pagemask(PM_HUGE_MASK); 382 write_c0_pagemask(PM_HUGE_MASK);
404 back_to_back_c0_hazard(); 383 back_to_back_c0_hazard();
405 mask = read_c0_pagemask(); 384 mask = read_c0_pagemask();
406 write_c0_pagemask(PM_DEFAULT_MASK); 385 write_c0_pagemask(PM_DEFAULT_MASK);
407 386
408 EXIT_CRITICAL(flags); 387 local_irq_restore(flags);
409 388
410 return mask == PM_HUGE_MASK; 389 return mask == PM_HUGE_MASK;
411} 390}
@@ -421,7 +400,10 @@ static int __init set_ntlb(char *str)
421 400
422__setup("ntlb=", set_ntlb); 401__setup("ntlb=", set_ntlb);
423 402
424void tlb_init(void) 403/*
404 * Configure TLB (for init or after a CPU has been powered off).
405 */
406static void r4k_tlb_configure(void)
425{ 407{
426 /* 408 /*
427 * You should never change this register: 409 * You should never change this register:
@@ -453,6 +435,11 @@ void tlb_init(void)
453 local_flush_tlb_all(); 435 local_flush_tlb_all();
454 436
455 /* Did I tell you that ARC SUCKS? */ 437 /* Did I tell you that ARC SUCKS? */
438}
439
440void tlb_init(void)
441{
442 r4k_tlb_configure();
456 443
457 if (ntlb) { 444 if (ntlb) {
458 if (ntlb > 1 && ntlb <= current_cpu_data.tlbsize) { 445 if (ntlb > 1 && ntlb <= current_cpu_data.tlbsize) {
@@ -466,3 +453,26 @@ void tlb_init(void)
466 453
467 build_tlb_refill_handler(); 454 build_tlb_refill_handler();
468} 455}
456
457static int r4k_tlb_pm_notifier(struct notifier_block *self, unsigned long cmd,
458 void *v)
459{
460 switch (cmd) {
461 case CPU_PM_ENTER_FAILED:
462 case CPU_PM_EXIT:
463 r4k_tlb_configure();
464 break;
465 }
466
467 return NOTIFY_OK;
468}
469
470static struct notifier_block r4k_tlb_pm_notifier_block = {
471 .notifier_call = r4k_tlb_pm_notifier,
472};
473
474static int __init r4k_tlb_init_pm(void)
475{
476 return cpu_pm_register_notifier(&r4k_tlb_pm_notifier_block);
477}
478arch_initcall(r4k_tlb_init_pm);
diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c
index f99ec587b151..e80e10bafc83 100644
--- a/arch/mips/mm/tlbex.c
+++ b/arch/mips/mm/tlbex.c
@@ -1256,7 +1256,7 @@ static void build_r4000_tlb_refill_handler(void)
1256 memset(relocs, 0, sizeof(relocs)); 1256 memset(relocs, 0, sizeof(relocs));
1257 memset(final_handler, 0, sizeof(final_handler)); 1257 memset(final_handler, 0, sizeof(final_handler));
1258 1258
1259 if ((scratch_reg >= 0 || scratchpad_available()) && use_bbit_insns()) { 1259 if (IS_ENABLED(CONFIG_64BIT) && (scratch_reg >= 0 || scratchpad_available()) && use_bbit_insns()) {
1260 htlb_info = build_fast_tlb_refill_handler(&p, &l, &r, K0, K1, 1260 htlb_info = build_fast_tlb_refill_handler(&p, &l, &r, K0, K1,
1261 scratch_reg); 1261 scratch_reg);
1262 vmalloc_mode = refill_scratch; 1262 vmalloc_mode = refill_scratch;
diff --git a/arch/mips/mm/uasm-micromips.c b/arch/mips/mm/uasm-micromips.c
index b8d580ca02e5..775c2800cba2 100644
--- a/arch/mips/mm/uasm-micromips.c
+++ b/arch/mips/mm/uasm-micromips.c
@@ -63,6 +63,7 @@ static struct insn insn_table_MM[] = {
63 { insn_cache, M(mm_pool32b_op, 0, 0, mm_cache_func, 0, 0), RT | RS | SIMM }, 63 { insn_cache, M(mm_pool32b_op, 0, 0, mm_cache_func, 0, 0), RT | RS | SIMM },
64 { insn_daddu, 0, 0 }, 64 { insn_daddu, 0, 0 },
65 { insn_daddiu, 0, 0 }, 65 { insn_daddiu, 0, 0 },
66 { insn_divu, M(mm_pool32a_op, 0, 0, 0, mm_divu_op, mm_pool32axf_op), RT | RS },
66 { insn_dmfc0, 0, 0 }, 67 { insn_dmfc0, 0, 0 },
67 { insn_dmtc0, 0, 0 }, 68 { insn_dmtc0, 0, 0 },
68 { insn_dsll, 0, 0 }, 69 { insn_dsll, 0, 0 },
@@ -78,14 +79,20 @@ static struct insn insn_table_MM[] = {
78 { insn_ext, M(mm_pool32a_op, 0, 0, 0, 0, mm_ext_op), RT | RS | RD | RE }, 79 { insn_ext, M(mm_pool32a_op, 0, 0, 0, 0, mm_ext_op), RT | RS | RD | RE },
79 { insn_j, M(mm_j32_op, 0, 0, 0, 0, 0), JIMM }, 80 { insn_j, M(mm_j32_op, 0, 0, 0, 0, 0), JIMM },
80 { insn_jal, M(mm_jal32_op, 0, 0, 0, 0, 0), JIMM }, 81 { insn_jal, M(mm_jal32_op, 0, 0, 0, 0, 0), JIMM },
82 { insn_jalr, M(mm_pool32a_op, 0, 0, 0, mm_jalr_op, mm_pool32axf_op), RT | RS },
81 { insn_jr, M(mm_pool32a_op, 0, 0, 0, mm_jalr_op, mm_pool32axf_op), RS }, 83 { insn_jr, M(mm_pool32a_op, 0, 0, 0, mm_jalr_op, mm_pool32axf_op), RS },
84 { insn_lb, M(mm_lb32_op, 0, 0, 0, 0, 0), RT | RS | SIMM },
82 { insn_ld, 0, 0 }, 85 { insn_ld, 0, 0 },
86 { insn_lh, M(mm_lh32_op, 0, 0, 0, 0, 0), RS | RS | SIMM },
83 { insn_ll, M(mm_pool32c_op, 0, 0, (mm_ll_func << 1), 0, 0), RS | RT | SIMM }, 87 { insn_ll, M(mm_pool32c_op, 0, 0, (mm_ll_func << 1), 0, 0), RS | RT | SIMM },
84 { insn_lld, 0, 0 }, 88 { insn_lld, 0, 0 },
85 { insn_lui, M(mm_pool32i_op, mm_lui_op, 0, 0, 0, 0), RS | SIMM }, 89 { insn_lui, M(mm_pool32i_op, mm_lui_op, 0, 0, 0, 0), RS | SIMM },
86 { insn_lw, M(mm_lw32_op, 0, 0, 0, 0, 0), RT | RS | SIMM }, 90 { insn_lw, M(mm_lw32_op, 0, 0, 0, 0, 0), RT | RS | SIMM },
87 { insn_mfc0, M(mm_pool32a_op, 0, 0, 0, mm_mfc0_op, mm_pool32axf_op), RT | RS | RD }, 91 { insn_mfc0, M(mm_pool32a_op, 0, 0, 0, mm_mfc0_op, mm_pool32axf_op), RT | RS | RD },
92 { insn_mfhi, M(mm_pool32a_op, 0, 0, 0, mm_mfhi32_op, mm_pool32axf_op), RS },
93 { insn_mflo, M(mm_pool32a_op, 0, 0, 0, mm_mflo32_op, mm_pool32axf_op), RS },
88 { insn_mtc0, M(mm_pool32a_op, 0, 0, 0, mm_mtc0_op, mm_pool32axf_op), RT | RS | RD }, 94 { insn_mtc0, M(mm_pool32a_op, 0, 0, 0, mm_mtc0_op, mm_pool32axf_op), RT | RS | RD },
95 { insn_mul, M(mm_pool32a_op, 0, 0, 0, 0, mm_mul_op), RT | RS | RD },
89 { insn_or, M(mm_pool32a_op, 0, 0, 0, 0, mm_or32_op), RT | RS | RD }, 96 { insn_or, M(mm_pool32a_op, 0, 0, 0, 0, mm_or32_op), RT | RS | RD },
90 { insn_ori, M(mm_ori32_op, 0, 0, 0, 0, 0), RT | RS | UIMM }, 97 { insn_ori, M(mm_ori32_op, 0, 0, 0, 0, 0), RT | RS | UIMM },
91 { insn_pref, M(mm_pool32c_op, 0, 0, (mm_pref_func << 1), 0, 0), RT | RS | SIMM }, 98 { insn_pref, M(mm_pool32c_op, 0, 0, (mm_pref_func << 1), 0, 0), RT | RS | SIMM },
@@ -94,15 +101,22 @@ static struct insn insn_table_MM[] = {
94 { insn_scd, 0, 0 }, 101 { insn_scd, 0, 0 },
95 { insn_sd, 0, 0 }, 102 { insn_sd, 0, 0 },
96 { insn_sll, M(mm_pool32a_op, 0, 0, 0, 0, mm_sll32_op), RT | RS | RD }, 103 { insn_sll, M(mm_pool32a_op, 0, 0, 0, 0, mm_sll32_op), RT | RS | RD },
104 { insn_sllv, M(mm_pool32a_op, 0, 0, 0, 0, mm_sllv32_op), RT | RS | RD },
105 { insn_sltiu, M(mm_sltiu32_op, 0, 0, 0, 0, 0), RT | RS | SIMM },
106 { insn_sltu, M(mm_pool32a_op, 0, 0, 0, 0, mm_sltu_op), RT | RS | RD },
97 { insn_sra, M(mm_pool32a_op, 0, 0, 0, 0, mm_sra_op), RT | RS | RD }, 107 { insn_sra, M(mm_pool32a_op, 0, 0, 0, 0, mm_sra_op), RT | RS | RD },
98 { insn_srl, M(mm_pool32a_op, 0, 0, 0, 0, mm_srl32_op), RT | RS | RD }, 108 { insn_srl, M(mm_pool32a_op, 0, 0, 0, 0, mm_srl32_op), RT | RS | RD },
109 { insn_srlv, M(mm_pool32a_op, 0, 0, 0, 0, mm_srlv32_op), RT | RS | RD },
99 { insn_rotr, M(mm_pool32a_op, 0, 0, 0, 0, mm_rotr_op), RT | RS | RD }, 110 { insn_rotr, M(mm_pool32a_op, 0, 0, 0, 0, mm_rotr_op), RT | RS | RD },
100 { insn_subu, M(mm_pool32a_op, 0, 0, 0, 0, mm_subu32_op), RT | RS | RD }, 111 { insn_subu, M(mm_pool32a_op, 0, 0, 0, 0, mm_subu32_op), RT | RS | RD },
101 { insn_sw, M(mm_sw32_op, 0, 0, 0, 0, 0), RT | RS | SIMM }, 112 { insn_sw, M(mm_sw32_op, 0, 0, 0, 0, 0), RT | RS | SIMM },
113 { insn_sync, M(mm_pool32a_op, 0, 0, 0, mm_sync_op, mm_pool32axf_op), RS },
102 { insn_tlbp, M(mm_pool32a_op, 0, 0, 0, mm_tlbp_op, mm_pool32axf_op), 0 }, 114 { insn_tlbp, M(mm_pool32a_op, 0, 0, 0, mm_tlbp_op, mm_pool32axf_op), 0 },
103 { insn_tlbr, M(mm_pool32a_op, 0, 0, 0, mm_tlbr_op, mm_pool32axf_op), 0 }, 115 { insn_tlbr, M(mm_pool32a_op, 0, 0, 0, mm_tlbr_op, mm_pool32axf_op), 0 },
104 { insn_tlbwi, M(mm_pool32a_op, 0, 0, 0, mm_tlbwi_op, mm_pool32axf_op), 0 }, 116 { insn_tlbwi, M(mm_pool32a_op, 0, 0, 0, mm_tlbwi_op, mm_pool32axf_op), 0 },
105 { insn_tlbwr, M(mm_pool32a_op, 0, 0, 0, mm_tlbwr_op, mm_pool32axf_op), 0 }, 117 { insn_tlbwr, M(mm_pool32a_op, 0, 0, 0, mm_tlbwr_op, mm_pool32axf_op), 0 },
118 { insn_wait, M(mm_pool32a_op, 0, 0, 0, mm_wait_op, mm_pool32axf_op), SCIMM },
119 { insn_wsbh, M(mm_pool32a_op, 0, 0, 0, mm_wsbh_op, mm_pool32axf_op), RT | RS },
106 { insn_xor, M(mm_pool32a_op, 0, 0, 0, 0, mm_xor32_op), RT | RS | RD }, 120 { insn_xor, M(mm_pool32a_op, 0, 0, 0, 0, mm_xor32_op), RT | RS | RD },
107 { insn_xori, M(mm_xori32_op, 0, 0, 0, 0, 0), RT | RS | UIMM }, 121 { insn_xori, M(mm_xori32_op, 0, 0, 0, 0, 0), RT | RS | UIMM },
108 { insn_dins, 0, 0 }, 122 { insn_dins, 0, 0 },
diff --git a/arch/mips/mm/uasm-mips.c b/arch/mips/mm/uasm-mips.c
index 3abd609518c9..38792c2364f5 100644
--- a/arch/mips/mm/uasm-mips.c
+++ b/arch/mips/mm/uasm-mips.c
@@ -67,6 +67,7 @@ static struct insn insn_table[] = {
67 { insn_daddu, M(spec_op, 0, 0, 0, 0, daddu_op), RS | RT | RD }, 67 { insn_daddu, M(spec_op, 0, 0, 0, 0, daddu_op), RS | RT | RD },
68 { insn_dinsm, M(spec3_op, 0, 0, 0, 0, dinsm_op), RS | RT | RD | RE }, 68 { insn_dinsm, M(spec3_op, 0, 0, 0, 0, dinsm_op), RS | RT | RD | RE },
69 { insn_dins, M(spec3_op, 0, 0, 0, 0, dins_op), RS | RT | RD | RE }, 69 { insn_dins, M(spec3_op, 0, 0, 0, 0, dins_op), RS | RT | RD | RE },
70 { insn_divu, M(spec_op, 0, 0, 0, 0, divu_op), RS | RT },
70 { insn_dmfc0, M(cop0_op, dmfc_op, 0, 0, 0, 0), RT | RD | SET}, 71 { insn_dmfc0, M(cop0_op, dmfc_op, 0, 0, 0, 0), RT | RD | SET},
71 { insn_dmtc0, M(cop0_op, dmtc_op, 0, 0, 0, 0), RT | RD | SET}, 72 { insn_dmtc0, M(cop0_op, dmtc_op, 0, 0, 0, 0), RT | RD | SET},
72 { insn_drotr32, M(spec_op, 1, 0, 0, 0, dsrl32_op), RT | RD | RE }, 73 { insn_drotr32, M(spec_op, 1, 0, 0, 0, dsrl32_op), RT | RD | RE },
@@ -82,17 +83,23 @@ static struct insn insn_table[] = {
82 { insn_ins, M(spec3_op, 0, 0, 0, 0, ins_op), RS | RT | RD | RE }, 83 { insn_ins, M(spec3_op, 0, 0, 0, 0, ins_op), RS | RT | RD | RE },
83 { insn_j, M(j_op, 0, 0, 0, 0, 0), JIMM }, 84 { insn_j, M(j_op, 0, 0, 0, 0, 0), JIMM },
84 { insn_jal, M(jal_op, 0, 0, 0, 0, 0), JIMM }, 85 { insn_jal, M(jal_op, 0, 0, 0, 0, 0), JIMM },
86 { insn_jalr, M(spec_op, 0, 0, 0, 0, jalr_op), RS | RD },
85 { insn_j, M(j_op, 0, 0, 0, 0, 0), JIMM }, 87 { insn_j, M(j_op, 0, 0, 0, 0, 0), JIMM },
86 { insn_jr, M(spec_op, 0, 0, 0, 0, jr_op), RS }, 88 { insn_jr, M(spec_op, 0, 0, 0, 0, jr_op), RS },
89 { insn_lb, M(lb_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
87 { insn_ld, M(ld_op, 0, 0, 0, 0, 0), RS | RT | SIMM }, 90 { insn_ld, M(ld_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
88 { insn_ldx, M(spec3_op, 0, 0, 0, ldx_op, lx_op), RS | RT | RD }, 91 { insn_ldx, M(spec3_op, 0, 0, 0, ldx_op, lx_op), RS | RT | RD },
92 { insn_lh, M(lw_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
89 { insn_lld, M(lld_op, 0, 0, 0, 0, 0), RS | RT | SIMM }, 93 { insn_lld, M(lld_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
90 { insn_ll, M(ll_op, 0, 0, 0, 0, 0), RS | RT | SIMM }, 94 { insn_ll, M(ll_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
91 { insn_lui, M(lui_op, 0, 0, 0, 0, 0), RT | SIMM }, 95 { insn_lui, M(lui_op, 0, 0, 0, 0, 0), RT | SIMM },
92 { insn_lw, M(lw_op, 0, 0, 0, 0, 0), RS | RT | SIMM }, 96 { insn_lw, M(lw_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
93 { insn_lwx, M(spec3_op, 0, 0, 0, lwx_op, lx_op), RS | RT | RD }, 97 { insn_lwx, M(spec3_op, 0, 0, 0, lwx_op, lx_op), RS | RT | RD },
94 { insn_mfc0, M(cop0_op, mfc_op, 0, 0, 0, 0), RT | RD | SET}, 98 { insn_mfc0, M(cop0_op, mfc_op, 0, 0, 0, 0), RT | RD | SET},
99 { insn_mfhi, M(spec_op, 0, 0, 0, 0, mfhi_op), RD },
100 { insn_mflo, M(spec_op, 0, 0, 0, 0, mflo_op), RD },
95 { insn_mtc0, M(cop0_op, mtc_op, 0, 0, 0, 0), RT | RD | SET}, 101 { insn_mtc0, M(cop0_op, mtc_op, 0, 0, 0, 0), RT | RD | SET},
102 { insn_mul, M(spec2_op, 0, 0, 0, 0, mul_op), RS | RT | RD},
96 { insn_ori, M(ori_op, 0, 0, 0, 0, 0), RS | RT | UIMM }, 103 { insn_ori, M(ori_op, 0, 0, 0, 0, 0), RS | RT | UIMM },
97 { insn_or, M(spec_op, 0, 0, 0, 0, or_op), RS | RT | RD }, 104 { insn_or, M(spec_op, 0, 0, 0, 0, or_op), RS | RT | RD },
98 { insn_pref, M(pref_op, 0, 0, 0, 0, 0), RS | RT | SIMM }, 105 { insn_pref, M(pref_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
@@ -102,17 +109,25 @@ static struct insn insn_table[] = {
102 { insn_sc, M(sc_op, 0, 0, 0, 0, 0), RS | RT | SIMM }, 109 { insn_sc, M(sc_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
103 { insn_sd, M(sd_op, 0, 0, 0, 0, 0), RS | RT | SIMM }, 110 { insn_sd, M(sd_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
104 { insn_sll, M(spec_op, 0, 0, 0, 0, sll_op), RT | RD | RE }, 111 { insn_sll, M(spec_op, 0, 0, 0, 0, sll_op), RT | RD | RE },
112 { insn_sllv, M(spec_op, 0, 0, 0, 0, sllv_op), RS | RT | RD },
113 { insn_sltiu, M(sltiu_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
114 { insn_sltu, M(spec_op, 0, 0, 0, 0, sltu_op), RS | RT | RD },
105 { insn_sra, M(spec_op, 0, 0, 0, 0, sra_op), RT | RD | RE }, 115 { insn_sra, M(spec_op, 0, 0, 0, 0, sra_op), RT | RD | RE },
106 { insn_srl, M(spec_op, 0, 0, 0, 0, srl_op), RT | RD | RE }, 116 { insn_srl, M(spec_op, 0, 0, 0, 0, srl_op), RT | RD | RE },
117 { insn_srlv, M(spec_op, 0, 0, 0, 0, srlv_op), RS | RT | RD },
107 { insn_subu, M(spec_op, 0, 0, 0, 0, subu_op), RS | RT | RD }, 118 { insn_subu, M(spec_op, 0, 0, 0, 0, subu_op), RS | RT | RD },
108 { insn_sw, M(sw_op, 0, 0, 0, 0, 0), RS | RT | SIMM }, 119 { insn_sw, M(sw_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
120 { insn_sync, M(spec_op, 0, 0, 0, 0, sync_op), RE },
109 { insn_syscall, M(spec_op, 0, 0, 0, 0, syscall_op), SCIMM}, 121 { insn_syscall, M(spec_op, 0, 0, 0, 0, syscall_op), SCIMM},
110 { insn_tlbp, M(cop0_op, cop_op, 0, 0, 0, tlbp_op), 0 }, 122 { insn_tlbp, M(cop0_op, cop_op, 0, 0, 0, tlbp_op), 0 },
111 { insn_tlbr, M(cop0_op, cop_op, 0, 0, 0, tlbr_op), 0 }, 123 { insn_tlbr, M(cop0_op, cop_op, 0, 0, 0, tlbr_op), 0 },
112 { insn_tlbwi, M(cop0_op, cop_op, 0, 0, 0, tlbwi_op), 0 }, 124 { insn_tlbwi, M(cop0_op, cop_op, 0, 0, 0, tlbwi_op), 0 },
113 { insn_tlbwr, M(cop0_op, cop_op, 0, 0, 0, tlbwr_op), 0 }, 125 { insn_tlbwr, M(cop0_op, cop_op, 0, 0, 0, tlbwr_op), 0 },
126 { insn_wait, M(cop0_op, cop_op, 0, 0, 0, wait_op), SCIMM },
127 { insn_wsbh, M(spec3_op, 0, 0, 0, wsbh_op, bshfl_op), RT | RD },
114 { insn_xori, M(xori_op, 0, 0, 0, 0, 0), RS | RT | UIMM }, 128 { insn_xori, M(xori_op, 0, 0, 0, 0, 0), RS | RT | UIMM },
115 { insn_xor, M(spec_op, 0, 0, 0, 0, xor_op), RS | RT | RD }, 129 { insn_xor, M(spec_op, 0, 0, 0, 0, xor_op), RS | RT | RD },
130 { insn_yield, M(spec3_op, 0, 0, 0, 0, yield_op), RS | RD },
116 { insn_invalid, 0, 0 } 131 { insn_invalid, 0, 0 }
117}; 132};
118 133
diff --git a/arch/mips/mm/uasm.c b/arch/mips/mm/uasm.c
index b9d14b6c7f58..00515805fe41 100644
--- a/arch/mips/mm/uasm.c
+++ b/arch/mips/mm/uasm.c
@@ -47,14 +47,16 @@ enum opcode {
47 insn_addiu, insn_addu, insn_and, insn_andi, insn_bbit0, insn_bbit1, 47 insn_addiu, insn_addu, insn_and, insn_andi, insn_bbit0, insn_bbit1,
48 insn_beq, insn_beql, insn_bgez, insn_bgezl, insn_bltz, insn_bltzl, 48 insn_beq, insn_beql, insn_bgez, insn_bgezl, insn_bltz, insn_bltzl,
49 insn_bne, insn_cache, insn_daddiu, insn_daddu, insn_dins, insn_dinsm, 49 insn_bne, insn_cache, insn_daddiu, insn_daddu, insn_dins, insn_dinsm,
50 insn_dmfc0, insn_dmtc0, insn_drotr, insn_drotr32, insn_dsll, 50 insn_divu, insn_dmfc0, insn_dmtc0, insn_drotr, insn_drotr32, insn_dsll,
51 insn_dsll32, insn_dsra, insn_dsrl, insn_dsrl32, insn_dsubu, insn_eret, 51 insn_dsll32, insn_dsra, insn_dsrl, insn_dsrl32, insn_dsubu, insn_eret,
52 insn_ext, insn_ins, insn_j, insn_jal, insn_jr, insn_ld, insn_ldx, 52 insn_ext, insn_ins, insn_j, insn_jal, insn_jalr, insn_jr, insn_lb,
53 insn_ll, insn_lld, insn_lui, insn_lw, insn_lwx, insn_mfc0, insn_mtc0, 53 insn_ld, insn_ldx, insn_lh, insn_ll, insn_lld, insn_lui, insn_lw,
54 insn_lwx, insn_mfc0, insn_mfhi, insn_mflo, insn_mtc0, insn_mul,
54 insn_or, insn_ori, insn_pref, insn_rfe, insn_rotr, insn_sc, insn_scd, 55 insn_or, insn_ori, insn_pref, insn_rfe, insn_rotr, insn_sc, insn_scd,
55 insn_sd, insn_sll, insn_sra, insn_srl, insn_subu, insn_sw, 56 insn_sd, insn_sll, insn_sllv, insn_sltiu, insn_sltu, insn_sra,
56 insn_syscall, insn_tlbp, insn_tlbr, insn_tlbwi, insn_tlbwr, insn_xor, 57 insn_srl, insn_srlv, insn_subu, insn_sw, insn_sync, insn_syscall,
57 insn_xori, 58 insn_tlbp, insn_tlbr, insn_tlbwi, insn_tlbwr, insn_wait, insn_wsbh,
59 insn_xor, insn_xori, insn_yield,
58}; 60};
59 61
60struct insn { 62struct insn {
@@ -144,6 +146,13 @@ Ip_u2u1u3(op) \
144} \ 146} \
145UASM_EXPORT_SYMBOL(uasm_i##op); 147UASM_EXPORT_SYMBOL(uasm_i##op);
146 148
149#define I_u3u2u1(op) \
150Ip_u3u2u1(op) \
151{ \
152 build_insn(buf, insn##op, c, b, a); \
153} \
154UASM_EXPORT_SYMBOL(uasm_i##op);
155
147#define I_u3u1u2(op) \ 156#define I_u3u1u2(op) \
148Ip_u3u1u2(op) \ 157Ip_u3u1u2(op) \
149{ \ 158{ \
@@ -200,6 +209,13 @@ Ip_u1u2(op) \
200} \ 209} \
201UASM_EXPORT_SYMBOL(uasm_i##op); 210UASM_EXPORT_SYMBOL(uasm_i##op);
202 211
212#define I_u2u1(op) \
213Ip_u1u2(op) \
214{ \
215 build_insn(buf, insn##op, b, a); \
216} \
217UASM_EXPORT_SYMBOL(uasm_i##op);
218
203#define I_u1s2(op) \ 219#define I_u1s2(op) \
204Ip_u1s2(op) \ 220Ip_u1s2(op) \
205{ \ 221{ \
@@ -237,6 +253,7 @@ I_u1u2u3(_dmfc0)
237I_u1u2u3(_dmtc0) 253I_u1u2u3(_dmtc0)
238I_u2u1s3(_daddiu) 254I_u2u1s3(_daddiu)
239I_u3u1u2(_daddu) 255I_u3u1u2(_daddu)
256I_u1u2(_divu)
240I_u2u1u3(_dsll) 257I_u2u1u3(_dsll)
241I_u2u1u3(_dsll32) 258I_u2u1u3(_dsll32)
242I_u2u1u3(_dsra) 259I_u2u1u3(_dsra)
@@ -250,14 +267,20 @@ I_u2u1msbdu3(_ext)
250I_u2u1msbu3(_ins) 267I_u2u1msbu3(_ins)
251I_u1(_j) 268I_u1(_j)
252I_u1(_jal) 269I_u1(_jal)
270I_u2u1(_jalr)
253I_u1(_jr) 271I_u1(_jr)
272I_u2s3u1(_lb)
254I_u2s3u1(_ld) 273I_u2s3u1(_ld)
274I_u2s3u1(_lh)
255I_u2s3u1(_ll) 275I_u2s3u1(_ll)
256I_u2s3u1(_lld) 276I_u2s3u1(_lld)
257I_u1s2(_lui) 277I_u1s2(_lui)
258I_u2s3u1(_lw) 278I_u2s3u1(_lw)
259I_u1u2u3(_mfc0) 279I_u1u2u3(_mfc0)
280I_u1(_mfhi)
281I_u1(_mflo)
260I_u1u2u3(_mtc0) 282I_u1u2u3(_mtc0)
283I_u3u1u2(_mul)
261I_u2u1u3(_ori) 284I_u2u1u3(_ori)
262I_u3u1u2(_or) 285I_u3u1u2(_or)
263I_0(_rfe) 286I_0(_rfe)
@@ -265,17 +288,25 @@ I_u2s3u1(_sc)
265I_u2s3u1(_scd) 288I_u2s3u1(_scd)
266I_u2s3u1(_sd) 289I_u2s3u1(_sd)
267I_u2u1u3(_sll) 290I_u2u1u3(_sll)
291I_u3u2u1(_sllv)
292I_u2u1s3(_sltiu)
293I_u3u1u2(_sltu)
268I_u2u1u3(_sra) 294I_u2u1u3(_sra)
269I_u2u1u3(_srl) 295I_u2u1u3(_srl)
296I_u3u2u1(_srlv)
270I_u2u1u3(_rotr) 297I_u2u1u3(_rotr)
271I_u3u1u2(_subu) 298I_u3u1u2(_subu)
272I_u2s3u1(_sw) 299I_u2s3u1(_sw)
300I_u1(_sync)
273I_0(_tlbp) 301I_0(_tlbp)
274I_0(_tlbr) 302I_0(_tlbr)
275I_0(_tlbwi) 303I_0(_tlbwi)
276I_0(_tlbwr) 304I_0(_tlbwr)
305I_u1(_wait);
306I_u2u1(_wsbh)
277I_u3u1u2(_xor) 307I_u3u1u2(_xor)
278I_u2u1u3(_xori) 308I_u2u1u3(_xori)
309I_u2u1(_yield)
279I_u2u1msbu3(_dins); 310I_u2u1msbu3(_dins);
280I_u2u1msb32u3(_dinsm); 311I_u2u1msb32u3(_dinsm);
281I_u1(_syscall); 312I_u1(_syscall);
@@ -469,6 +500,14 @@ void ISAFUNC(uasm_il_b)(u32 **p, struct uasm_reloc **r, int lid)
469} 500}
470UASM_EXPORT_SYMBOL(ISAFUNC(uasm_il_b)); 501UASM_EXPORT_SYMBOL(ISAFUNC(uasm_il_b));
471 502
503void ISAFUNC(uasm_il_beq)(u32 **p, struct uasm_reloc **r, unsigned int r1,
504 unsigned int r2, int lid)
505{
506 uasm_r_mips_pc16(r, *p, lid);
507 ISAFUNC(uasm_i_beq)(p, r1, r2, 0);
508}
509UASM_EXPORT_SYMBOL(ISAFUNC(uasm_il_beq));
510
472void ISAFUNC(uasm_il_beqz)(u32 **p, struct uasm_reloc **r, unsigned int reg, 511void ISAFUNC(uasm_il_beqz)(u32 **p, struct uasm_reloc **r, unsigned int reg,
473 int lid) 512 int lid)
474{ 513{