diff options
Diffstat (limited to 'arch/mips/mm')
-rw-r--r-- | arch/mips/mm/c-octeon.c | 2 | ||||
-rw-r--r-- | arch/mips/mm/c-r4k.c | 77 | ||||
-rw-r--r-- | arch/mips/mm/init.c | 82 | ||||
-rw-r--r-- | arch/mips/mm/tlb-r4k.c | 88 | ||||
-rw-r--r-- | arch/mips/mm/tlbex.c | 2 | ||||
-rw-r--r-- | arch/mips/mm/uasm-micromips.c | 14 | ||||
-rw-r--r-- | arch/mips/mm/uasm-mips.c | 15 | ||||
-rw-r--r-- | arch/mips/mm/uasm.c | 51 |
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(¤t->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(¤t->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 | ||
106 | static inline void r4k_blast_dcache_page_dc64(unsigned long addr) | 107 | static 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 | ||
112 | static inline void r4k_blast_dcache_page_dc128(unsigned long addr) | ||
113 | { | ||
114 | blast_dcache128_page(addr); | ||
115 | } | ||
116 | |||
112 | static void r4k_blast_dcache_page_setup(void) | 117 | static 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 | ||
164 | void (* r4k_blast_dcache)(void); | 182 | void (* 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 | ||
343 | static void (* r4k_blast_scache_page)(unsigned long addr); | 367 | static void (* r4k_blast_scache_page)(unsigned long addr); |
@@ -428,7 +452,7 @@ static void r4k___flush_cache_all(void) | |||
428 | 452 | ||
429 | static inline int has_valid_asid(const struct mm_struct *mm) | 453 | static 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 | |||
1688 | static 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 | |||
1701 | static struct notifier_block r4k_cache_pm_notifier_block = { | ||
1702 | .notifier_call = r4k_cache_pm_notifier, | ||
1703 | }; | ||
1704 | |||
1705 | int __init r4k_cache_init_pm(void) | ||
1706 | { | ||
1707 | return cpu_pm_register_notifier(&r4k_cache_pm_notifier_block); | ||
1708 | } | ||
1709 | arch_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 | 82 | static void *__kmap_pgprot(struct page *page, unsigned long addr, pgprot_t prot) |
104 | static pte_t *kmap_coherent_pte; | ||
105 | static 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 | ||
114 | static inline void kmap_coherent_init(void) {} | ||
115 | #endif | ||
116 | |||
117 | void *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 | ||
120 | void *kmap_coherent(struct page *page, unsigned long addr) | ||
121 | { | ||
122 | return __kmap_pgprot(page, addr, PAGE_KERNEL); | ||
123 | } | ||
124 | |||
125 | void *kmap_noncoherent(struct page *page, unsigned long addr) | ||
126 | { | ||
127 | return __kmap_pgprot(page, addr, PAGE_KERNEL_NC); | ||
128 | } | ||
129 | |||
174 | void kunmap_coherent(void) | 130 | void 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); | |||
256 | void __init fixrange_init(unsigned long start, unsigned long end, | 210 | void __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 | ||
26 | extern void build_tlb_refill_handler(void); | 27 | extern 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 | } |
117 | EXPORT_SYMBOL(local_flush_tlb_all); | 96 | EXPORT_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 | ||
226 | void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page) | 205 | void 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 | ||
364 | void add_wired_entry(unsigned long entrylo0, unsigned long entrylo1, | 343 | void 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 | ||
424 | void tlb_init(void) | 403 | /* |
404 | * Configure TLB (for init or after a CPU has been powered off). | ||
405 | */ | ||
406 | static 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 | |||
440 | void 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 | |||
457 | static 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 | |||
470 | static struct notifier_block r4k_tlb_pm_notifier_block = { | ||
471 | .notifier_call = r4k_tlb_pm_notifier, | ||
472 | }; | ||
473 | |||
474 | static int __init r4k_tlb_init_pm(void) | ||
475 | { | ||
476 | return cpu_pm_register_notifier(&r4k_tlb_pm_notifier_block); | ||
477 | } | ||
478 | arch_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 | ||
60 | struct insn { | 62 | struct insn { |
@@ -144,6 +146,13 @@ Ip_u2u1u3(op) \ | |||
144 | } \ | 146 | } \ |
145 | UASM_EXPORT_SYMBOL(uasm_i##op); | 147 | UASM_EXPORT_SYMBOL(uasm_i##op); |
146 | 148 | ||
149 | #define I_u3u2u1(op) \ | ||
150 | Ip_u3u2u1(op) \ | ||
151 | { \ | ||
152 | build_insn(buf, insn##op, c, b, a); \ | ||
153 | } \ | ||
154 | UASM_EXPORT_SYMBOL(uasm_i##op); | ||
155 | |||
147 | #define I_u3u1u2(op) \ | 156 | #define I_u3u1u2(op) \ |
148 | Ip_u3u1u2(op) \ | 157 | Ip_u3u1u2(op) \ |
149 | { \ | 158 | { \ |
@@ -200,6 +209,13 @@ Ip_u1u2(op) \ | |||
200 | } \ | 209 | } \ |
201 | UASM_EXPORT_SYMBOL(uasm_i##op); | 210 | UASM_EXPORT_SYMBOL(uasm_i##op); |
202 | 211 | ||
212 | #define I_u2u1(op) \ | ||
213 | Ip_u1u2(op) \ | ||
214 | { \ | ||
215 | build_insn(buf, insn##op, b, a); \ | ||
216 | } \ | ||
217 | UASM_EXPORT_SYMBOL(uasm_i##op); | ||
218 | |||
203 | #define I_u1s2(op) \ | 219 | #define I_u1s2(op) \ |
204 | Ip_u1s2(op) \ | 220 | Ip_u1s2(op) \ |
205 | { \ | 221 | { \ |
@@ -237,6 +253,7 @@ I_u1u2u3(_dmfc0) | |||
237 | I_u1u2u3(_dmtc0) | 253 | I_u1u2u3(_dmtc0) |
238 | I_u2u1s3(_daddiu) | 254 | I_u2u1s3(_daddiu) |
239 | I_u3u1u2(_daddu) | 255 | I_u3u1u2(_daddu) |
256 | I_u1u2(_divu) | ||
240 | I_u2u1u3(_dsll) | 257 | I_u2u1u3(_dsll) |
241 | I_u2u1u3(_dsll32) | 258 | I_u2u1u3(_dsll32) |
242 | I_u2u1u3(_dsra) | 259 | I_u2u1u3(_dsra) |
@@ -250,14 +267,20 @@ I_u2u1msbdu3(_ext) | |||
250 | I_u2u1msbu3(_ins) | 267 | I_u2u1msbu3(_ins) |
251 | I_u1(_j) | 268 | I_u1(_j) |
252 | I_u1(_jal) | 269 | I_u1(_jal) |
270 | I_u2u1(_jalr) | ||
253 | I_u1(_jr) | 271 | I_u1(_jr) |
272 | I_u2s3u1(_lb) | ||
254 | I_u2s3u1(_ld) | 273 | I_u2s3u1(_ld) |
274 | I_u2s3u1(_lh) | ||
255 | I_u2s3u1(_ll) | 275 | I_u2s3u1(_ll) |
256 | I_u2s3u1(_lld) | 276 | I_u2s3u1(_lld) |
257 | I_u1s2(_lui) | 277 | I_u1s2(_lui) |
258 | I_u2s3u1(_lw) | 278 | I_u2s3u1(_lw) |
259 | I_u1u2u3(_mfc0) | 279 | I_u1u2u3(_mfc0) |
280 | I_u1(_mfhi) | ||
281 | I_u1(_mflo) | ||
260 | I_u1u2u3(_mtc0) | 282 | I_u1u2u3(_mtc0) |
283 | I_u3u1u2(_mul) | ||
261 | I_u2u1u3(_ori) | 284 | I_u2u1u3(_ori) |
262 | I_u3u1u2(_or) | 285 | I_u3u1u2(_or) |
263 | I_0(_rfe) | 286 | I_0(_rfe) |
@@ -265,17 +288,25 @@ I_u2s3u1(_sc) | |||
265 | I_u2s3u1(_scd) | 288 | I_u2s3u1(_scd) |
266 | I_u2s3u1(_sd) | 289 | I_u2s3u1(_sd) |
267 | I_u2u1u3(_sll) | 290 | I_u2u1u3(_sll) |
291 | I_u3u2u1(_sllv) | ||
292 | I_u2u1s3(_sltiu) | ||
293 | I_u3u1u2(_sltu) | ||
268 | I_u2u1u3(_sra) | 294 | I_u2u1u3(_sra) |
269 | I_u2u1u3(_srl) | 295 | I_u2u1u3(_srl) |
296 | I_u3u2u1(_srlv) | ||
270 | I_u2u1u3(_rotr) | 297 | I_u2u1u3(_rotr) |
271 | I_u3u1u2(_subu) | 298 | I_u3u1u2(_subu) |
272 | I_u2s3u1(_sw) | 299 | I_u2s3u1(_sw) |
300 | I_u1(_sync) | ||
273 | I_0(_tlbp) | 301 | I_0(_tlbp) |
274 | I_0(_tlbr) | 302 | I_0(_tlbr) |
275 | I_0(_tlbwi) | 303 | I_0(_tlbwi) |
276 | I_0(_tlbwr) | 304 | I_0(_tlbwr) |
305 | I_u1(_wait); | ||
306 | I_u2u1(_wsbh) | ||
277 | I_u3u1u2(_xor) | 307 | I_u3u1u2(_xor) |
278 | I_u2u1u3(_xori) | 308 | I_u2u1u3(_xori) |
309 | I_u2u1(_yield) | ||
279 | I_u2u1msbu3(_dins); | 310 | I_u2u1msbu3(_dins); |
280 | I_u2u1msb32u3(_dinsm); | 311 | I_u2u1msb32u3(_dinsm); |
281 | I_u1(_syscall); | 312 | I_u1(_syscall); |
@@ -469,6 +500,14 @@ void ISAFUNC(uasm_il_b)(u32 **p, struct uasm_reloc **r, int lid) | |||
469 | } | 500 | } |
470 | UASM_EXPORT_SYMBOL(ISAFUNC(uasm_il_b)); | 501 | UASM_EXPORT_SYMBOL(ISAFUNC(uasm_il_b)); |
471 | 502 | ||
503 | void 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 | } | ||
509 | UASM_EXPORT_SYMBOL(ISAFUNC(uasm_il_beq)); | ||
510 | |||
472 | void ISAFUNC(uasm_il_beqz)(u32 **p, struct uasm_reloc **r, unsigned int reg, | 511 | void ISAFUNC(uasm_il_beqz)(u32 **p, struct uasm_reloc **r, unsigned int reg, |
473 | int lid) | 512 | int lid) |
474 | { | 513 | { |