aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/mm
diff options
context:
space:
mode:
authorJames Bottomley <jejb@mulgrave.il.steeleye.com>2006-06-10 14:47:26 -0400
committerJames Bottomley <jejb@mulgrave.il.steeleye.com>2006-06-10 14:47:26 -0400
commitf0cd91a68acdc9b49d7f6738b514a426da627649 (patch)
tree8ad73564015794197583b094217ae0a71e71e753 /arch/mips/mm
parent60eef25701d25e99c991dd0f4a9f3832a0c3ad3e (diff)
parent128e6ced247cda88f96fa9f2e4ba8b2c4a681560 (diff)
Merge ../linux-2.6
Diffstat (limited to 'arch/mips/mm')
-rw-r--r--arch/mips/mm/c-r3k.c5
-rw-r--r--arch/mips/mm/c-r4k.c98
-rw-r--r--arch/mips/mm/c-sb1.c1
-rw-r--r--arch/mips/mm/c-tx39.c7
-rw-r--r--arch/mips/mm/cache.c1
-rw-r--r--arch/mips/mm/fault.c13
-rw-r--r--arch/mips/mm/highmem.c2
-rw-r--r--arch/mips/mm/init.c50
-rw-r--r--arch/mips/mm/pg-r4k.c1
-rw-r--r--arch/mips/mm/sc-rm7k.c2
-rw-r--r--arch/mips/mm/tlb-r4k.c85
-rw-r--r--arch/mips/mm/tlbex.c89
12 files changed, 267 insertions, 87 deletions
diff --git a/arch/mips/mm/c-r3k.c b/arch/mips/mm/c-r3k.c
index 9dd1352d5748..bb041a22f20a 100644
--- a/arch/mips/mm/c-r3k.c
+++ b/arch/mips/mm/c-r3k.c
@@ -260,6 +260,10 @@ static void r3k_flush_cache_page(struct vm_area_struct *vma, unsigned long page,
260{ 260{
261} 261}
262 262
263static void local_r3k_flush_data_cache_page(unsigned long addr)
264{
265}
266
263static void r3k_flush_data_cache_page(unsigned long addr) 267static void r3k_flush_data_cache_page(unsigned long addr)
264{ 268{
265} 269}
@@ -335,6 +339,7 @@ void __init r3k_cache_init(void)
335 flush_icache_range = r3k_flush_icache_range; 339 flush_icache_range = r3k_flush_icache_range;
336 340
337 flush_cache_sigtramp = r3k_flush_cache_sigtramp; 341 flush_cache_sigtramp = r3k_flush_cache_sigtramp;
342 local_flush_data_cache_page = local_r3k_flush_data_cache_page;
338 flush_data_cache_page = r3k_flush_data_cache_page; 343 flush_data_cache_page = r3k_flush_data_cache_page;
339 344
340 _dma_cache_wback_inv = r3k_dma_cache_wback_inv; 345 _dma_cache_wback_inv = r3k_dma_cache_wback_inv;
diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c
index 32b7f6aeb983..4a43924cd4fc 100644
--- a/arch/mips/mm/c-r4k.c
+++ b/arch/mips/mm/c-r4k.c
@@ -29,6 +29,27 @@
29#include <asm/war.h> 29#include <asm/war.h>
30#include <asm/cacheflush.h> /* for run_uncached() */ 30#include <asm/cacheflush.h> /* for run_uncached() */
31 31
32
33/*
34 * Special Variant of smp_call_function for use by cache functions:
35 *
36 * o No return value
37 * o collapses to normal function call on UP kernels
38 * o collapses to normal function call on systems with a single shared
39 * primary cache.
40 */
41static inline void r4k_on_each_cpu(void (*func) (void *info), void *info,
42 int retry, int wait)
43{
44 preempt_disable();
45
46#if !defined(CONFIG_MIPS_MT_SMP) && !defined(CONFIG_MIPS_MT_SMTC)
47 smp_call_function(func, info, retry, wait);
48#endif
49 func(info);
50 preempt_enable();
51}
52
32/* 53/*
33 * Must die. 54 * Must die.
34 */ 55 */
@@ -154,7 +175,8 @@ static inline void blast_icache32_r4600_v1_page_indexed(unsigned long page)
154 175
155static inline void tx49_blast_icache32_page_indexed(unsigned long page) 176static inline void tx49_blast_icache32_page_indexed(unsigned long page)
156{ 177{
157 unsigned long start = page; 178 unsigned long indexmask = current_cpu_data.icache.waysize - 1;
179 unsigned long start = INDEX_BASE + (page & indexmask);
158 unsigned long end = start + PAGE_SIZE; 180 unsigned long end = start + PAGE_SIZE;
159 unsigned long ws_inc = 1UL << current_cpu_data.icache.waybit; 181 unsigned long ws_inc = 1UL << current_cpu_data.icache.waybit;
160 unsigned long ws_end = current_cpu_data.icache.ways << 182 unsigned long ws_end = current_cpu_data.icache.ways <<
@@ -298,7 +320,7 @@ static void r4k_flush_cache_all(void)
298 if (!cpu_has_dc_aliases) 320 if (!cpu_has_dc_aliases)
299 return; 321 return;
300 322
301 on_each_cpu(local_r4k_flush_cache_all, NULL, 1, 1); 323 r4k_on_each_cpu(local_r4k_flush_cache_all, NULL, 1, 1);
302} 324}
303 325
304static inline void local_r4k___flush_cache_all(void * args) 326static inline void local_r4k___flush_cache_all(void * args)
@@ -313,13 +335,14 @@ static inline void local_r4k___flush_cache_all(void * args)
313 case CPU_R4400MC: 335 case CPU_R4400MC:
314 case CPU_R10000: 336 case CPU_R10000:
315 case CPU_R12000: 337 case CPU_R12000:
338 case CPU_R14000:
316 r4k_blast_scache(); 339 r4k_blast_scache();
317 } 340 }
318} 341}
319 342
320static void r4k___flush_cache_all(void) 343static void r4k___flush_cache_all(void)
321{ 344{
322 on_each_cpu(local_r4k___flush_cache_all, NULL, 1, 1); 345 r4k_on_each_cpu(local_r4k___flush_cache_all, NULL, 1, 1);
323} 346}
324 347
325static inline void local_r4k_flush_cache_range(void * args) 348static inline void local_r4k_flush_cache_range(void * args)
@@ -340,7 +363,7 @@ static inline void local_r4k_flush_cache_range(void * args)
340static void r4k_flush_cache_range(struct vm_area_struct *vma, 363static void r4k_flush_cache_range(struct vm_area_struct *vma,
341 unsigned long start, unsigned long end) 364 unsigned long start, unsigned long end)
342{ 365{
343 on_each_cpu(local_r4k_flush_cache_range, vma, 1, 1); 366 r4k_on_each_cpu(local_r4k_flush_cache_range, vma, 1, 1);
344} 367}
345 368
346static inline void local_r4k_flush_cache_mm(void * args) 369static inline void local_r4k_flush_cache_mm(void * args)
@@ -369,7 +392,7 @@ static void r4k_flush_cache_mm(struct mm_struct *mm)
369 if (!cpu_has_dc_aliases) 392 if (!cpu_has_dc_aliases)
370 return; 393 return;
371 394
372 on_each_cpu(local_r4k_flush_cache_mm, mm, 1, 1); 395 r4k_on_each_cpu(local_r4k_flush_cache_mm, mm, 1, 1);
373} 396}
374 397
375struct flush_cache_page_args { 398struct flush_cache_page_args {
@@ -460,7 +483,7 @@ static void r4k_flush_cache_page(struct vm_area_struct *vma,
460 args.addr = addr; 483 args.addr = addr;
461 args.pfn = pfn; 484 args.pfn = pfn;
462 485
463 on_each_cpu(local_r4k_flush_cache_page, &args, 1, 1); 486 r4k_on_each_cpu(local_r4k_flush_cache_page, &args, 1, 1);
464} 487}
465 488
466static inline void local_r4k_flush_data_cache_page(void * addr) 489static inline void local_r4k_flush_data_cache_page(void * addr)
@@ -470,7 +493,7 @@ static inline void local_r4k_flush_data_cache_page(void * addr)
470 493
471static void r4k_flush_data_cache_page(unsigned long addr) 494static void r4k_flush_data_cache_page(unsigned long addr)
472{ 495{
473 on_each_cpu(local_r4k_flush_data_cache_page, (void *) addr, 1, 1); 496 r4k_on_each_cpu(local_r4k_flush_data_cache_page, (void *) addr, 1, 1);
474} 497}
475 498
476struct flush_icache_range_args { 499struct flush_icache_range_args {
@@ -513,7 +536,7 @@ static void r4k_flush_icache_range(unsigned long start, unsigned long end)
513 args.start = start; 536 args.start = start;
514 args.end = end; 537 args.end = end;
515 538
516 on_each_cpu(local_r4k_flush_icache_range, &args, 1, 1); 539 r4k_on_each_cpu(local_r4k_flush_icache_range, &args, 1, 1);
517 instruction_hazard(); 540 instruction_hazard();
518} 541}
519 542
@@ -589,7 +612,7 @@ static void r4k_flush_icache_page(struct vm_area_struct *vma,
589 args.vma = vma; 612 args.vma = vma;
590 args.page = page; 613 args.page = page;
591 614
592 on_each_cpu(local_r4k_flush_icache_page, &args, 1, 1); 615 r4k_on_each_cpu(local_r4k_flush_icache_page, &args, 1, 1);
593} 616}
594 617
595 618
@@ -688,7 +711,7 @@ static void local_r4k_flush_cache_sigtramp(void * arg)
688 711
689static void r4k_flush_cache_sigtramp(unsigned long addr) 712static void r4k_flush_cache_sigtramp(unsigned long addr)
690{ 713{
691 on_each_cpu(local_r4k_flush_cache_sigtramp, (void *) addr, 1, 1); 714 r4k_on_each_cpu(local_r4k_flush_cache_sigtramp, (void *) addr, 1, 1);
692} 715}
693 716
694static void r4k_flush_icache_all(void) 717static void r4k_flush_icache_all(void)
@@ -749,12 +772,12 @@ static void __init probe_pcache(void)
749 icache_size = 1 << (12 + ((config & CONF_IC) >> 9)); 772 icache_size = 1 << (12 + ((config & CONF_IC) >> 9));
750 c->icache.linesz = 16 << ((config & CONF_IB) >> 5); 773 c->icache.linesz = 16 << ((config & CONF_IB) >> 5);
751 c->icache.ways = 2; 774 c->icache.ways = 2;
752 c->icache.waybit = ffs(icache_size/2) - 1; 775 c->icache.waybit = __ffs(icache_size/2);
753 776
754 dcache_size = 1 << (12 + ((config & CONF_DC) >> 6)); 777 dcache_size = 1 << (12 + ((config & CONF_DC) >> 6));
755 c->dcache.linesz = 16 << ((config & CONF_DB) >> 4); 778 c->dcache.linesz = 16 << ((config & CONF_DB) >> 4);
756 c->dcache.ways = 2; 779 c->dcache.ways = 2;
757 c->dcache.waybit= ffs(dcache_size/2) - 1; 780 c->dcache.waybit= __ffs(dcache_size/2);
758 781
759 c->options |= MIPS_CPU_CACHE_CDEX_P; 782 c->options |= MIPS_CPU_CACHE_CDEX_P;
760 break; 783 break;
@@ -811,6 +834,7 @@ static void __init probe_pcache(void)
811 834
812 case CPU_R10000: 835 case CPU_R10000:
813 case CPU_R12000: 836 case CPU_R12000:
837 case CPU_R14000:
814 icache_size = 1 << (12 + ((config & R10K_CONF_IC) >> 29)); 838 icache_size = 1 << (12 + ((config & R10K_CONF_IC) >> 29));
815 c->icache.linesz = 64; 839 c->icache.linesz = 64;
816 c->icache.ways = 2; 840 c->icache.ways = 2;
@@ -837,12 +861,12 @@ static void __init probe_pcache(void)
837 icache_size = 1 << (10 + ((config & CONF_IC) >> 9)); 861 icache_size = 1 << (10 + ((config & CONF_IC) >> 9));
838 c->icache.linesz = 16 << ((config & CONF_IB) >> 5); 862 c->icache.linesz = 16 << ((config & CONF_IB) >> 5);
839 c->icache.ways = 2; 863 c->icache.ways = 2;
840 c->icache.waybit = ffs(icache_size/2) - 1; 864 c->icache.waybit = __ffs(icache_size/2);
841 865
842 dcache_size = 1 << (10 + ((config & CONF_DC) >> 6)); 866 dcache_size = 1 << (10 + ((config & CONF_DC) >> 6));
843 c->dcache.linesz = 16 << ((config & CONF_DB) >> 4); 867 c->dcache.linesz = 16 << ((config & CONF_DB) >> 4);
844 c->dcache.ways = 2; 868 c->dcache.ways = 2;
845 c->dcache.waybit = ffs(dcache_size/2) - 1; 869 c->dcache.waybit = __ffs(dcache_size/2);
846 870
847 c->options |= MIPS_CPU_CACHE_CDEX_P; 871 c->options |= MIPS_CPU_CACHE_CDEX_P;
848 break; 872 break;
@@ -873,12 +897,12 @@ static void __init probe_pcache(void)
873 icache_size = 1 << (12 + ((config & CONF_IC) >> 9)); 897 icache_size = 1 << (12 + ((config & CONF_IC) >> 9));
874 c->icache.linesz = 16 << ((config & CONF_IB) >> 5); 898 c->icache.linesz = 16 << ((config & CONF_IB) >> 5);
875 c->icache.ways = 4; 899 c->icache.ways = 4;
876 c->icache.waybit = ffs(icache_size / c->icache.ways) - 1; 900 c->icache.waybit = __ffs(icache_size / c->icache.ways);
877 901
878 dcache_size = 1 << (12 + ((config & CONF_DC) >> 6)); 902 dcache_size = 1 << (12 + ((config & CONF_DC) >> 6));
879 c->dcache.linesz = 16 << ((config & CONF_DB) >> 4); 903 c->dcache.linesz = 16 << ((config & CONF_DB) >> 4);
880 c->dcache.ways = 4; 904 c->dcache.ways = 4;
881 c->dcache.waybit = ffs(dcache_size / c->dcache.ways) - 1; 905 c->dcache.waybit = __ffs(dcache_size / c->dcache.ways);
882 906
883#if !defined(CONFIG_SMP) || !defined(RM9000_CDEX_SMP_WAR) 907#if !defined(CONFIG_SMP) || !defined(RM9000_CDEX_SMP_WAR)
884 c->options |= MIPS_CPU_CACHE_CDEX_P; 908 c->options |= MIPS_CPU_CACHE_CDEX_P;
@@ -906,7 +930,7 @@ static void __init probe_pcache(void)
906 icache_size = c->icache.sets * 930 icache_size = c->icache.sets *
907 c->icache.ways * 931 c->icache.ways *
908 c->icache.linesz; 932 c->icache.linesz;
909 c->icache.waybit = ffs(icache_size/c->icache.ways) - 1; 933 c->icache.waybit = __ffs(icache_size/c->icache.ways);
910 934
911 if (config & 0x8) /* VI bit */ 935 if (config & 0x8) /* VI bit */
912 c->icache.flags |= MIPS_CACHE_VTAG; 936 c->icache.flags |= MIPS_CACHE_VTAG;
@@ -926,7 +950,7 @@ static void __init probe_pcache(void)
926 dcache_size = c->dcache.sets * 950 dcache_size = c->dcache.sets *
927 c->dcache.ways * 951 c->dcache.ways *
928 c->dcache.linesz; 952 c->dcache.linesz;
929 c->dcache.waybit = ffs(dcache_size/c->dcache.ways) - 1; 953 c->dcache.waybit = __ffs(dcache_size/c->dcache.ways);
930 954
931 c->options |= MIPS_CPU_PREFETCH; 955 c->options |= MIPS_CPU_PREFETCH;
932 break; 956 break;
@@ -964,9 +988,11 @@ static void __init probe_pcache(void)
964 c->dcache.flags |= MIPS_CACHE_PINDEX; 988 c->dcache.flags |= MIPS_CACHE_PINDEX;
965 case CPU_R10000: 989 case CPU_R10000:
966 case CPU_R12000: 990 case CPU_R12000:
991 case CPU_R14000:
967 case CPU_SB1: 992 case CPU_SB1:
968 break; 993 break;
969 case CPU_24K: 994 case CPU_24K:
995 case CPU_34K:
970 if (!(read_c0_config7() & (1 << 16))) 996 if (!(read_c0_config7() & (1 << 16)))
971 default: 997 default:
972 if (c->dcache.waysize > PAGE_SIZE) 998 if (c->dcache.waysize > PAGE_SIZE)
@@ -1090,6 +1116,7 @@ static void __init setup_scache(void)
1090 1116
1091 case CPU_R10000: 1117 case CPU_R10000:
1092 case CPU_R12000: 1118 case CPU_R12000:
1119 case CPU_R14000:
1093 scache_size = 0x80000 << ((config & R10K_CONF_SS) >> 16); 1120 scache_size = 0x80000 << ((config & R10K_CONF_SS) >> 16);
1094 c->scache.linesz = 64 << ((config >> 13) & 1); 1121 c->scache.linesz = 64 << ((config >> 13) & 1);
1095 c->scache.ways = 2; 1122 c->scache.ways = 2;
@@ -1134,6 +1161,31 @@ static void __init setup_scache(void)
1134 c->options |= MIPS_CPU_SUBSET_CACHES; 1161 c->options |= MIPS_CPU_SUBSET_CACHES;
1135} 1162}
1136 1163
1164void au1x00_fixup_config_od(void)
1165{
1166 /*
1167 * c0_config.od (bit 19) was write only (and read as 0)
1168 * on the early revisions of Alchemy SOCs. It disables the bus
1169 * transaction overlapping and needs to be set to fix various errata.
1170 */
1171 switch (read_c0_prid()) {
1172 case 0x00030100: /* Au1000 DA */
1173 case 0x00030201: /* Au1000 HA */
1174 case 0x00030202: /* Au1000 HB */
1175 case 0x01030200: /* Au1500 AB */
1176 /*
1177 * Au1100 errata actually keeps silence about this bit, so we set it
1178 * just in case for those revisions that require it to be set according
1179 * to arch/mips/au1000/common/cputable.c
1180 */
1181 case 0x02030200: /* Au1100 AB */
1182 case 0x02030201: /* Au1100 BA */
1183 case 0x02030202: /* Au1100 BC */
1184 set_c0_config(1 << 19);
1185 break;
1186 }
1187}
1188
1137static inline void coherency_setup(void) 1189static inline void coherency_setup(void)
1138{ 1190{
1139 change_c0_config(CONF_CM_CMASK, CONF_CM_DEFAULT); 1191 change_c0_config(CONF_CM_CMASK, CONF_CM_DEFAULT);
@@ -1154,6 +1206,15 @@ static inline void coherency_setup(void)
1154 case CPU_R4400MC: 1206 case CPU_R4400MC:
1155 clear_c0_config(CONF_CU); 1207 clear_c0_config(CONF_CU);
1156 break; 1208 break;
1209 /*
1210 * We need to catch the ealry Alchemy SOCs with
1211 * the write-only co_config.od bit and set it back to one...
1212 */
1213 case CPU_AU1000: /* rev. DA, HA, HB */
1214 case CPU_AU1100: /* rev. AB, BA, BC ?? */
1215 case CPU_AU1500: /* rev. AB */
1216 au1x00_fixup_config_od();
1217 break;
1157 } 1218 }
1158} 1219}
1159 1220
@@ -1198,6 +1259,7 @@ void __init r4k_cache_init(void)
1198 1259
1199 flush_cache_sigtramp = r4k_flush_cache_sigtramp; 1260 flush_cache_sigtramp = r4k_flush_cache_sigtramp;
1200 flush_icache_all = r4k_flush_icache_all; 1261 flush_icache_all = r4k_flush_icache_all;
1262 local_flush_data_cache_page = local_r4k_flush_data_cache_page;
1201 flush_data_cache_page = r4k_flush_data_cache_page; 1263 flush_data_cache_page = r4k_flush_data_cache_page;
1202 flush_icache_range = r4k_flush_icache_range; 1264 flush_icache_range = r4k_flush_icache_range;
1203 1265
diff --git a/arch/mips/mm/c-sb1.c b/arch/mips/mm/c-sb1.c
index 2f08b535f20e..f9b129491b1e 100644
--- a/arch/mips/mm/c-sb1.c
+++ b/arch/mips/mm/c-sb1.c
@@ -528,6 +528,7 @@ void sb1_cache_init(void)
528 flush_cache_page = sb1_flush_cache_page; 528 flush_cache_page = sb1_flush_cache_page;
529 529
530 flush_cache_sigtramp = sb1_flush_cache_sigtramp; 530 flush_cache_sigtramp = sb1_flush_cache_sigtramp;
531 local_flush_data_cache_page = (void *) sb1_nop;
531 flush_data_cache_page = (void *) sb1_nop; 532 flush_data_cache_page = (void *) sb1_nop;
532 533
533 /* Full flush */ 534 /* Full flush */
diff --git a/arch/mips/mm/c-tx39.c b/arch/mips/mm/c-tx39.c
index fe232e3988e3..5dfc9b1901f6 100644
--- a/arch/mips/mm/c-tx39.c
+++ b/arch/mips/mm/c-tx39.c
@@ -216,6 +216,11 @@ static void tx39_flush_cache_page(struct vm_area_struct *vma, unsigned long page
216 tx39_blast_icache_page_indexed(page); 216 tx39_blast_icache_page_indexed(page);
217} 217}
218 218
219static void local_tx39_flush_data_cache_page(void * addr)
220{
221 tx39_blast_dcache_page(addr);
222}
223
219static void tx39_flush_data_cache_page(unsigned long addr) 224static void tx39_flush_data_cache_page(unsigned long addr)
220{ 225{
221 tx39_blast_dcache_page(addr); 226 tx39_blast_dcache_page(addr);
@@ -381,6 +386,7 @@ void __init tx39_cache_init(void)
381 flush_icache_range = (void *) tx39h_flush_icache_all; 386 flush_icache_range = (void *) tx39h_flush_icache_all;
382 387
383 flush_cache_sigtramp = (void *) tx39h_flush_icache_all; 388 flush_cache_sigtramp = (void *) tx39h_flush_icache_all;
389 local_flush_data_cache_page = (void *) tx39h_flush_icache_all;
384 flush_data_cache_page = (void *) tx39h_flush_icache_all; 390 flush_data_cache_page = (void *) tx39h_flush_icache_all;
385 391
386 _dma_cache_wback_inv = tx39h_dma_cache_wback_inv; 392 _dma_cache_wback_inv = tx39h_dma_cache_wback_inv;
@@ -406,6 +412,7 @@ void __init tx39_cache_init(void)
406 flush_icache_range = tx39_flush_icache_range; 412 flush_icache_range = tx39_flush_icache_range;
407 413
408 flush_cache_sigtramp = tx39_flush_cache_sigtramp; 414 flush_cache_sigtramp = tx39_flush_cache_sigtramp;
415 local_flush_data_cache_page = local_tx39_flush_data_cache_page;
409 flush_data_cache_page = tx39_flush_data_cache_page; 416 flush_data_cache_page = tx39_flush_data_cache_page;
410 417
411 _dma_cache_wback_inv = tx39_dma_cache_wback_inv; 418 _dma_cache_wback_inv = tx39_dma_cache_wback_inv;
diff --git a/arch/mips/mm/cache.c b/arch/mips/mm/cache.c
index 591c22b080e4..83a56296be86 100644
--- a/arch/mips/mm/cache.c
+++ b/arch/mips/mm/cache.c
@@ -30,6 +30,7 @@ void (*flush_icache_page)(struct vm_area_struct *vma, struct page *page);
30 30
31/* MIPS specific cache operations */ 31/* MIPS specific cache operations */
32void (*flush_cache_sigtramp)(unsigned long addr); 32void (*flush_cache_sigtramp)(unsigned long addr);
33void (*local_flush_data_cache_page)(void * addr);
33void (*flush_data_cache_page)(unsigned long addr); 34void (*flush_data_cache_page)(unsigned long addr);
34void (*flush_icache_all)(void); 35void (*flush_icache_all)(void);
35 36
diff --git a/arch/mips/mm/fault.c b/arch/mips/mm/fault.c
index 2d9624fd10ec..e3a617224868 100644
--- a/arch/mips/mm/fault.c
+++ b/arch/mips/mm/fault.c
@@ -157,7 +157,6 @@ no_context:
157 * Oops. The kernel tried to access some bad page. We'll have to 157 * Oops. The kernel tried to access some bad page. We'll have to
158 * terminate things with extreme prejudice. 158 * terminate things with extreme prejudice.
159 */ 159 */
160
161 bust_spinlocks(1); 160 bust_spinlocks(1);
162 161
163 printk(KERN_ALERT "CPU %d Unable to handle kernel paging request at " 162 printk(KERN_ALERT "CPU %d Unable to handle kernel paging request at "
@@ -188,11 +187,20 @@ do_sigbus:
188 /* Kernel mode? Handle exceptions or die */ 187 /* Kernel mode? Handle exceptions or die */
189 if (!user_mode(regs)) 188 if (!user_mode(regs))
190 goto no_context; 189 goto no_context;
191 190 else
192 /* 191 /*
193 * Send a sigbus, regardless of whether we were in kernel 192 * Send a sigbus, regardless of whether we were in kernel
194 * or user mode. 193 * or user mode.
195 */ 194 */
195#if 0
196 printk("do_page_fault() #3: sending SIGBUS to %s for "
197 "invalid %s\n%0*lx (epc == %0*lx, ra == %0*lx)\n",
198 tsk->comm,
199 write ? "write access to" : "read access from",
200 field, address,
201 field, (unsigned long) regs->cp0_epc,
202 field, (unsigned long) regs->regs[31]);
203#endif
196 tsk->thread.cp0_badvaddr = address; 204 tsk->thread.cp0_badvaddr = address;
197 info.si_signo = SIGBUS; 205 info.si_signo = SIGBUS;
198 info.si_errno = 0; 206 info.si_errno = 0;
@@ -201,7 +209,6 @@ do_sigbus:
201 force_sig_info(SIGBUS, &info, tsk); 209 force_sig_info(SIGBUS, &info, tsk);
202 210
203 return; 211 return;
204
205vmalloc_fault: 212vmalloc_fault:
206 { 213 {
207 /* 214 /*
diff --git a/arch/mips/mm/highmem.c b/arch/mips/mm/highmem.c
index 1f7b37b38f5c..0c544375b856 100644
--- a/arch/mips/mm/highmem.c
+++ b/arch/mips/mm/highmem.c
@@ -83,6 +83,7 @@ void __kunmap_atomic(void *kvaddr, enum km_type type)
83 preempt_check_resched(); 83 preempt_check_resched();
84} 84}
85 85
86#ifndef CONFIG_LIMITED_DMA
86/* 87/*
87 * This is the same as kmap_atomic() but can map memory that doesn't 88 * This is the same as kmap_atomic() but can map memory that doesn't
88 * have a struct page associated with it. 89 * have a struct page associated with it.
@@ -101,6 +102,7 @@ void *kmap_atomic_pfn(unsigned long pfn, enum km_type type)
101 102
102 return (void*) vaddr; 103 return (void*) vaddr;
103} 104}
105#endif /* CONFIG_LIMITED_DMA */
104 106
105struct page *__kmap_atomic_to_page(void *ptr) 107struct page *__kmap_atomic_to_page(void *ptr)
106{ 108{
diff --git a/arch/mips/mm/init.c b/arch/mips/mm/init.c
index ad89c442f299..33f6e1cdfd5b 100644
--- a/arch/mips/mm/init.c
+++ b/arch/mips/mm/init.c
@@ -227,7 +227,7 @@ void __init mem_init(void)
227 for (tmp = 0; tmp < max_low_pfn; tmp++) 227 for (tmp = 0; tmp < max_low_pfn; tmp++)
228 if (page_is_ram(tmp)) { 228 if (page_is_ram(tmp)) {
229 ram++; 229 ram++;
230 if (PageReserved(mem_map+tmp)) 230 if (PageReserved(pfn_to_page(tmp)))
231 reservedpages++; 231 reservedpages++;
232 } 232 }
233 233
@@ -276,6 +276,20 @@ void __init mem_init(void)
276} 276}
277#endif /* !CONFIG_NEED_MULTIPLE_NODES */ 277#endif /* !CONFIG_NEED_MULTIPLE_NODES */
278 278
279void free_init_pages(char *what, unsigned long begin, unsigned long end)
280{
281 unsigned long addr;
282
283 for (addr = begin; addr < end; addr += PAGE_SIZE) {
284 ClearPageReserved(virt_to_page(addr));
285 init_page_count(virt_to_page(addr));
286 memset((void *)addr, 0xcc, PAGE_SIZE);
287 free_page(addr);
288 totalram_pages++;
289 }
290 printk(KERN_INFO "Freeing %s: %ldk freed\n", what, (end - begin) >> 10);
291}
292
279#ifdef CONFIG_BLK_DEV_INITRD 293#ifdef CONFIG_BLK_DEV_INITRD
280void free_initrd_mem(unsigned long start, unsigned long end) 294void free_initrd_mem(unsigned long start, unsigned long end)
281{ 295{
@@ -284,16 +298,7 @@ void free_initrd_mem(unsigned long start, unsigned long end)
284 start = (unsigned long)phys_to_virt(CPHYSADDR(start)); 298 start = (unsigned long)phys_to_virt(CPHYSADDR(start));
285 end = (unsigned long)phys_to_virt(CPHYSADDR(end)); 299 end = (unsigned long)phys_to_virt(CPHYSADDR(end));
286#endif 300#endif
287 if (start < end) 301 free_init_pages("initrd memory", start, end);
288 printk(KERN_INFO "Freeing initrd memory: %ldk freed\n",
289 (end - start) >> 10);
290
291 for (; start < end; start += PAGE_SIZE) {
292 ClearPageReserved(virt_to_page(start));
293 init_page_count(virt_to_page(start));
294 free_page(start);
295 totalram_pages++;
296 }
297} 302}
298#endif 303#endif
299 304
@@ -301,24 +306,17 @@ extern unsigned long prom_free_prom_memory(void);
301 306
302void free_initmem(void) 307void free_initmem(void)
303{ 308{
304 unsigned long addr, page, freed; 309 unsigned long start, end, freed;
305 310
306 freed = prom_free_prom_memory(); 311 freed = prom_free_prom_memory();
312 if (freed)
313 printk(KERN_INFO "Freeing firmware memory: %ldk freed\n",freed);
307 314
308 addr = (unsigned long) &__init_begin; 315 start = (unsigned long)(&__init_begin);
309 while (addr < (unsigned long) &__init_end) { 316 end = (unsigned long)(&__init_end);
310#ifdef CONFIG_64BIT 317#ifdef CONFIG_64BIT
311 page = PAGE_OFFSET | CPHYSADDR(addr); 318 start = PAGE_OFFSET | CPHYSADDR(start);
312#else 319 end = PAGE_OFFSET | CPHYSADDR(end);
313 page = addr;
314#endif 320#endif
315 ClearPageReserved(virt_to_page(page)); 321 free_init_pages("unused kernel memory", start, end);
316 init_page_count(virt_to_page(page));
317 free_page(page);
318 totalram_pages++;
319 freed += PAGE_SIZE;
320 addr += PAGE_SIZE;
321 }
322 printk(KERN_INFO "Freeing unused kernel memory: %ldk freed\n",
323 freed >> 10);
324} 322}
diff --git a/arch/mips/mm/pg-r4k.c b/arch/mips/mm/pg-r4k.c
index e4390dc3eb48..b7c749232ffe 100644
--- a/arch/mips/mm/pg-r4k.c
+++ b/arch/mips/mm/pg-r4k.c
@@ -357,6 +357,7 @@ void __init build_clear_page(void)
357 357
358 case CPU_R10000: 358 case CPU_R10000:
359 case CPU_R12000: 359 case CPU_R12000:
360 case CPU_R14000:
360 pref_src_mode = Pref_LoadStreamed; 361 pref_src_mode = Pref_LoadStreamed;
361 pref_dst_mode = Pref_StoreStreamed; 362 pref_dst_mode = Pref_StoreStreamed;
362 break; 363 break;
diff --git a/arch/mips/mm/sc-rm7k.c b/arch/mips/mm/sc-rm7k.c
index 3b6cc9ba1b05..31ec73052423 100644
--- a/arch/mips/mm/sc-rm7k.c
+++ b/arch/mips/mm/sc-rm7k.c
@@ -138,7 +138,7 @@ void __init rm7k_sc_init(void)
138 138
139 c->scache.linesz = sc_lsize; 139 c->scache.linesz = sc_lsize;
140 c->scache.ways = 4; 140 c->scache.ways = 4;
141 c->scache.waybit= ffs(scache_size / c->scache.ways) - 1; 141 c->scache.waybit= __ffs(scache_size / c->scache.ways);
142 c->scache.waysize = scache_size / c->scache.ways; 142 c->scache.waysize = scache_size / c->scache.ways;
143 c->scache.sets = scache_size / (c->scache.linesz * c->scache.ways); 143 c->scache.sets = scache_size / (c->scache.linesz * c->scache.ways);
144 printk(KERN_INFO "Secondary cache size %dK, linesize %d bytes.\n", 144 printk(KERN_INFO "Secondary cache size %dK, linesize %d bytes.\n",
diff --git a/arch/mips/mm/tlb-r4k.c b/arch/mips/mm/tlb-r4k.c
index a865f2394cb0..9dca099ba16b 100644
--- a/arch/mips/mm/tlb-r4k.c
+++ b/arch/mips/mm/tlb-r4k.c
@@ -32,13 +32,35 @@ extern void build_tlb_refill_handler(void);
32 "nop; nop; nop; nop; nop; nop;\n\t" \ 32 "nop; nop; nop; nop; nop; nop;\n\t" \
33 ".set reorder\n\t") 33 ".set reorder\n\t")
34 34
35/* Atomicity and interruptability */
36#ifdef CONFIG_MIPS_MT_SMTC
37
38#include <asm/smtc.h>
39#include <asm/mipsmtregs.h>
40
41#define ENTER_CRITICAL(flags) \
42 { \
43 unsigned int mvpflags; \
44 local_irq_save(flags);\
45 mvpflags = dvpe()
46#define EXIT_CRITICAL(flags) \
47 evpe(mvpflags); \
48 local_irq_restore(flags); \
49 }
50#else
51
52#define ENTER_CRITICAL(flags) local_irq_save(flags)
53#define EXIT_CRITICAL(flags) local_irq_restore(flags)
54
55#endif /* CONFIG_MIPS_MT_SMTC */
56
35void local_flush_tlb_all(void) 57void local_flush_tlb_all(void)
36{ 58{
37 unsigned long flags; 59 unsigned long flags;
38 unsigned long old_ctx; 60 unsigned long old_ctx;
39 int entry; 61 int entry;
40 62
41 local_irq_save(flags); 63 ENTER_CRITICAL(flags);
42 /* Save old context and create impossible VPN2 value */ 64 /* Save old context and create impossible VPN2 value */
43 old_ctx = read_c0_entryhi(); 65 old_ctx = read_c0_entryhi();
44 write_c0_entrylo0(0); 66 write_c0_entrylo0(0);
@@ -57,7 +79,7 @@ void local_flush_tlb_all(void)
57 } 79 }
58 tlbw_use_hazard(); 80 tlbw_use_hazard();
59 write_c0_entryhi(old_ctx); 81 write_c0_entryhi(old_ctx);
60 local_irq_restore(flags); 82 EXIT_CRITICAL(flags);
61} 83}
62 84
63/* All entries common to a mm share an asid. To effectively flush 85/* All entries common to a mm share an asid. To effectively flush
@@ -87,6 +109,7 @@ void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
87 unsigned long flags; 109 unsigned long flags;
88 int size; 110 int size;
89 111
112 ENTER_CRITICAL(flags);
90 size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT; 113 size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
91 size = (size + 1) >> 1; 114 size = (size + 1) >> 1;
92 local_irq_save(flags); 115 local_irq_save(flags);
@@ -120,7 +143,7 @@ void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
120 } else { 143 } else {
121 drop_mmu_context(mm, cpu); 144 drop_mmu_context(mm, cpu);
122 } 145 }
123 local_irq_restore(flags); 146 EXIT_CRITICAL(flags);
124 } 147 }
125} 148}
126 149
@@ -129,9 +152,9 @@ void local_flush_tlb_kernel_range(unsigned long start, unsigned long end)
129 unsigned long flags; 152 unsigned long flags;
130 int size; 153 int size;
131 154
155 ENTER_CRITICAL(flags);
132 size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT; 156 size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
133 size = (size + 1) >> 1; 157 size = (size + 1) >> 1;
134 local_irq_save(flags);
135 if (size <= current_cpu_data.tlbsize / 2) { 158 if (size <= current_cpu_data.tlbsize / 2) {
136 int pid = read_c0_entryhi(); 159 int pid = read_c0_entryhi();
137 160
@@ -162,7 +185,7 @@ void local_flush_tlb_kernel_range(unsigned long start, unsigned long end)
162 } else { 185 } else {
163 local_flush_tlb_all(); 186 local_flush_tlb_all();
164 } 187 }
165 local_irq_restore(flags); 188 EXIT_CRITICAL(flags);
166} 189}
167 190
168void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page) 191void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
@@ -175,7 +198,7 @@ void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
175 198
176 newpid = cpu_asid(cpu, vma->vm_mm); 199 newpid = cpu_asid(cpu, vma->vm_mm);
177 page &= (PAGE_MASK << 1); 200 page &= (PAGE_MASK << 1);
178 local_irq_save(flags); 201 ENTER_CRITICAL(flags);
179 oldpid = read_c0_entryhi(); 202 oldpid = read_c0_entryhi();
180 write_c0_entryhi(page | newpid); 203 write_c0_entryhi(page | newpid);
181 mtc0_tlbw_hazard(); 204 mtc0_tlbw_hazard();
@@ -194,7 +217,7 @@ void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
194 217
195 finish: 218 finish:
196 write_c0_entryhi(oldpid); 219 write_c0_entryhi(oldpid);
197 local_irq_restore(flags); 220 EXIT_CRITICAL(flags);
198 } 221 }
199} 222}
200 223
@@ -207,7 +230,7 @@ void local_flush_tlb_one(unsigned long page)
207 unsigned long flags; 230 unsigned long flags;
208 int oldpid, idx; 231 int oldpid, idx;
209 232
210 local_irq_save(flags); 233 ENTER_CRITICAL(flags);
211 oldpid = read_c0_entryhi(); 234 oldpid = read_c0_entryhi();
212 page &= (PAGE_MASK << 1); 235 page &= (PAGE_MASK << 1);
213 write_c0_entryhi(page); 236 write_c0_entryhi(page);
@@ -226,7 +249,7 @@ void local_flush_tlb_one(unsigned long page)
226 } 249 }
227 write_c0_entryhi(oldpid); 250 write_c0_entryhi(oldpid);
228 251
229 local_irq_restore(flags); 252 EXIT_CRITICAL(flags);
230} 253}
231 254
232/* 255/*
@@ -249,7 +272,7 @@ void __update_tlb(struct vm_area_struct * vma, unsigned long address, pte_t pte)
249 if (current->active_mm != vma->vm_mm) 272 if (current->active_mm != vma->vm_mm)
250 return; 273 return;
251 274
252 local_irq_save(flags); 275 ENTER_CRITICAL(flags);
253 276
254 pid = read_c0_entryhi() & ASID_MASK; 277 pid = read_c0_entryhi() & ASID_MASK;
255 address &= (PAGE_MASK << 1); 278 address &= (PAGE_MASK << 1);
@@ -277,7 +300,7 @@ void __update_tlb(struct vm_area_struct * vma, unsigned long address, pte_t pte)
277 else 300 else
278 tlb_write_indexed(); 301 tlb_write_indexed();
279 tlbw_use_hazard(); 302 tlbw_use_hazard();
280 local_irq_restore(flags); 303 EXIT_CRITICAL(flags);
281} 304}
282 305
283#if 0 306#if 0
@@ -291,7 +314,7 @@ static void r4k_update_mmu_cache_hwbug(struct vm_area_struct * vma,
291 pte_t *ptep; 314 pte_t *ptep;
292 int idx; 315 int idx;
293 316
294 local_irq_save(flags); 317 ENTER_CRITICAL(flags);
295 address &= (PAGE_MASK << 1); 318 address &= (PAGE_MASK << 1);
296 asid = read_c0_entryhi() & ASID_MASK; 319 asid = read_c0_entryhi() & ASID_MASK;
297 write_c0_entryhi(address | asid); 320 write_c0_entryhi(address | asid);
@@ -310,7 +333,7 @@ static void r4k_update_mmu_cache_hwbug(struct vm_area_struct * vma,
310 else 333 else
311 tlb_write_indexed(); 334 tlb_write_indexed();
312 tlbw_use_hazard(); 335 tlbw_use_hazard();
313 local_irq_restore(flags); 336 EXIT_CRITICAL(flags);
314} 337}
315#endif 338#endif
316 339
@@ -322,7 +345,7 @@ void __init add_wired_entry(unsigned long entrylo0, unsigned long entrylo1,
322 unsigned long old_pagemask; 345 unsigned long old_pagemask;
323 unsigned long old_ctx; 346 unsigned long old_ctx;
324 347
325 local_irq_save(flags); 348 ENTER_CRITICAL(flags);
326 /* Save old context and create impossible VPN2 value */ 349 /* Save old context and create impossible VPN2 value */
327 old_ctx = read_c0_entryhi(); 350 old_ctx = read_c0_entryhi();
328 old_pagemask = read_c0_pagemask(); 351 old_pagemask = read_c0_pagemask();
@@ -342,7 +365,7 @@ void __init add_wired_entry(unsigned long entrylo0, unsigned long entrylo1,
342 BARRIER; 365 BARRIER;
343 write_c0_pagemask(old_pagemask); 366 write_c0_pagemask(old_pagemask);
344 local_flush_tlb_all(); 367 local_flush_tlb_all();
345 local_irq_restore(flags); 368 EXIT_CRITICAL(flags);
346} 369}
347 370
348/* 371/*
@@ -362,7 +385,7 @@ __init int add_temporary_entry(unsigned long entrylo0, unsigned long entrylo1,
362 unsigned long old_pagemask; 385 unsigned long old_pagemask;
363 unsigned long old_ctx; 386 unsigned long old_ctx;
364 387
365 local_irq_save(flags); 388 ENTER_CRITICAL(flags);
366 /* Save old context and create impossible VPN2 value */ 389 /* Save old context and create impossible VPN2 value */
367 old_ctx = read_c0_entryhi(); 390 old_ctx = read_c0_entryhi();
368 old_pagemask = read_c0_pagemask(); 391 old_pagemask = read_c0_pagemask();
@@ -386,10 +409,11 @@ __init int add_temporary_entry(unsigned long entrylo0, unsigned long entrylo1,
386 write_c0_entryhi(old_ctx); 409 write_c0_entryhi(old_ctx);
387 write_c0_pagemask(old_pagemask); 410 write_c0_pagemask(old_pagemask);
388out: 411out:
389 local_irq_restore(flags); 412 EXIT_CRITICAL(flags);
390 return ret; 413 return ret;
391} 414}
392 415
416extern void __init sanitize_tlb_entries(void);
393static void __init probe_tlb(unsigned long config) 417static void __init probe_tlb(unsigned long config)
394{ 418{
395 struct cpuinfo_mips *c = &current_cpu_data; 419 struct cpuinfo_mips *c = &current_cpu_data;
@@ -402,6 +426,14 @@ static void __init probe_tlb(unsigned long config)
402 */ 426 */
403 if ((c->processor_id & 0xff0000) == PRID_COMP_LEGACY) 427 if ((c->processor_id & 0xff0000) == PRID_COMP_LEGACY)
404 return; 428 return;
429#ifdef CONFIG_MIPS_MT_SMTC
430 /*
431 * If TLB is shared in SMTC system, total size already
432 * has been calculated and written into cpu_data tlbsize
433 */
434 if((smtc_status & SMTC_TLB_SHARED) == SMTC_TLB_SHARED)
435 return;
436#endif /* CONFIG_MIPS_MT_SMTC */
405 437
406 reg = read_c0_config1(); 438 reg = read_c0_config1();
407 if (!((config >> 7) & 3)) 439 if (!((config >> 7) & 3))
@@ -410,6 +442,15 @@ static void __init probe_tlb(unsigned long config)
410 c->tlbsize = ((reg >> 25) & 0x3f) + 1; 442 c->tlbsize = ((reg >> 25) & 0x3f) + 1;
411} 443}
412 444
445static int __initdata ntlb = 0;
446static int __init set_ntlb(char *str)
447{
448 get_option(&str, &ntlb);
449 return 1;
450}
451
452__setup("ntlb=", set_ntlb);
453
413void __init tlb_init(void) 454void __init tlb_init(void)
414{ 455{
415 unsigned int config = read_c0_config(); 456 unsigned int config = read_c0_config();
@@ -432,5 +473,15 @@ void __init tlb_init(void)
432 473
433 /* Did I tell you that ARC SUCKS? */ 474 /* Did I tell you that ARC SUCKS? */
434 475
476 if (ntlb) {
477 if (ntlb > 1 && ntlb <= current_cpu_data.tlbsize) {
478 int wired = current_cpu_data.tlbsize - ntlb;
479 write_c0_wired(wired);
480 write_c0_index(wired-1);
481 printk ("Restricting TLB to %d entries\n", ntlb);
482 } else
483 printk("Ignoring invalid argument ntlb=%d\n", ntlb);
484 }
485
435 build_tlb_refill_handler(); 486 build_tlb_refill_handler();
436} 487}
diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c
index 599b3c297186..54507be2ab5b 100644
--- a/arch/mips/mm/tlbex.c
+++ b/arch/mips/mm/tlbex.c
@@ -7,6 +7,16 @@
7 * 7 *
8 * Copyright (C) 2004,2005 by Thiemo Seufer 8 * Copyright (C) 2004,2005 by Thiemo Seufer
9 * Copyright (C) 2005 Maciej W. Rozycki 9 * Copyright (C) 2005 Maciej W. Rozycki
10 * Copyright (C) 2006 Ralf Baechle (ralf@linux-mips.org)
11 *
12 * ... and the days got worse and worse and now you see
13 * I've gone completly out of my mind.
14 *
15 * They're coming to take me a away haha
16 * they're coming to take me a away hoho hihi haha
17 * to the funny farm where code is beautiful all the time ...
18 *
19 * (Condolences to Napoleon XIV)
10 */ 20 */
11 21
12#include <stdarg.h> 22#include <stdarg.h>
@@ -68,6 +78,7 @@ enum fields
68 BIMM = 0x040, 78 BIMM = 0x040,
69 JIMM = 0x080, 79 JIMM = 0x080,
70 FUNC = 0x100, 80 FUNC = 0x100,
81 SET = 0x200
71}; 82};
72 83
73#define OP_MASK 0x2f 84#define OP_MASK 0x2f
@@ -86,6 +97,8 @@ enum fields
86#define JIMM_SH 0 97#define JIMM_SH 0
87#define FUNC_MASK 0x2f 98#define FUNC_MASK 0x2f
88#define FUNC_SH 0 99#define FUNC_SH 0
100#define SET_MASK 0x7
101#define SET_SH 0
89 102
90enum opcode { 103enum opcode {
91 insn_invalid, 104 insn_invalid,
@@ -129,8 +142,8 @@ static __initdata struct insn insn_table[] = {
129 { insn_bne, M(bne_op,0,0,0,0,0), RS | RT | BIMM }, 142 { insn_bne, M(bne_op,0,0,0,0,0), RS | RT | BIMM },
130 { insn_daddiu, M(daddiu_op,0,0,0,0,0), RS | RT | SIMM }, 143 { insn_daddiu, M(daddiu_op,0,0,0,0,0), RS | RT | SIMM },
131 { insn_daddu, M(spec_op,0,0,0,0,daddu_op), RS | RT | RD }, 144 { insn_daddu, M(spec_op,0,0,0,0,daddu_op), RS | RT | RD },
132 { insn_dmfc0, M(cop0_op,dmfc_op,0,0,0,0), RT | RD }, 145 { insn_dmfc0, M(cop0_op,dmfc_op,0,0,0,0), RT | RD | SET},
133 { insn_dmtc0, M(cop0_op,dmtc_op,0,0,0,0), RT | RD }, 146 { insn_dmtc0, M(cop0_op,dmtc_op,0,0,0,0), RT | RD | SET},
134 { insn_dsll, M(spec_op,0,0,0,0,dsll_op), RT | RD | RE }, 147 { insn_dsll, M(spec_op,0,0,0,0,dsll_op), RT | RD | RE },
135 { insn_dsll32, M(spec_op,0,0,0,0,dsll32_op), RT | RD | RE }, 148 { insn_dsll32, M(spec_op,0,0,0,0,dsll32_op), RT | RD | RE },
136 { insn_dsra, M(spec_op,0,0,0,0,dsra_op), RT | RD | RE }, 149 { insn_dsra, M(spec_op,0,0,0,0,dsra_op), RT | RD | RE },
@@ -145,8 +158,8 @@ static __initdata struct insn insn_table[] = {
145 { insn_lld, M(lld_op,0,0,0,0,0), RS | RT | SIMM }, 158 { insn_lld, M(lld_op,0,0,0,0,0), RS | RT | SIMM },
146 { insn_lui, M(lui_op,0,0,0,0,0), RT | SIMM }, 159 { insn_lui, M(lui_op,0,0,0,0,0), RT | SIMM },
147 { insn_lw, M(lw_op,0,0,0,0,0), RS | RT | SIMM }, 160 { insn_lw, M(lw_op,0,0,0,0,0), RS | RT | SIMM },
148 { insn_mfc0, M(cop0_op,mfc_op,0,0,0,0), RT | RD }, 161 { insn_mfc0, M(cop0_op,mfc_op,0,0,0,0), RT | RD | SET},
149 { insn_mtc0, M(cop0_op,mtc_op,0,0,0,0), RT | RD }, 162 { insn_mtc0, M(cop0_op,mtc_op,0,0,0,0), RT | RD | SET},
150 { insn_ori, M(ori_op,0,0,0,0,0), RS | RT | UIMM }, 163 { insn_ori, M(ori_op,0,0,0,0,0), RS | RT | UIMM },
151 { insn_rfe, M(cop0_op,cop_op,0,0,0,rfe_op), 0 }, 164 { insn_rfe, M(cop0_op,cop_op,0,0,0,rfe_op), 0 },
152 { insn_sc, M(sc_op,0,0,0,0,0), RS | RT | SIMM }, 165 { insn_sc, M(sc_op,0,0,0,0,0), RS | RT | SIMM },
@@ -242,6 +255,14 @@ static __init u32 build_func(u32 arg)
242 return arg & FUNC_MASK; 255 return arg & FUNC_MASK;
243} 256}
244 257
258static __init u32 build_set(u32 arg)
259{
260 if (arg & ~SET_MASK)
261 printk(KERN_WARNING "TLB synthesizer field overflow\n");
262
263 return arg & SET_MASK;
264}
265
245/* 266/*
246 * The order of opcode arguments is implicitly left to right, 267 * The order of opcode arguments is implicitly left to right,
247 * starting with RS and ending with FUNC or IMM. 268 * starting with RS and ending with FUNC or IMM.
@@ -273,6 +294,7 @@ static void __init build_insn(u32 **buf, enum opcode opc, ...)
273 if (ip->fields & BIMM) op |= build_bimm(va_arg(ap, s32)); 294 if (ip->fields & BIMM) op |= build_bimm(va_arg(ap, s32));
274 if (ip->fields & JIMM) op |= build_jimm(va_arg(ap, u32)); 295 if (ip->fields & JIMM) op |= build_jimm(va_arg(ap, u32));
275 if (ip->fields & FUNC) op |= build_func(va_arg(ap, u32)); 296 if (ip->fields & FUNC) op |= build_func(va_arg(ap, u32));
297 if (ip->fields & SET) op |= build_set(va_arg(ap, u32));
276 va_end(ap); 298 va_end(ap);
277 299
278 **buf = op; 300 **buf = op;
@@ -358,8 +380,8 @@ I_u1s2(_bgezl);
358I_u1s2(_bltz); 380I_u1s2(_bltz);
359I_u1s2(_bltzl); 381I_u1s2(_bltzl);
360I_u1u2s3(_bne); 382I_u1u2s3(_bne);
361I_u1u2(_dmfc0); 383I_u1u2u3(_dmfc0);
362I_u1u2(_dmtc0); 384I_u1u2u3(_dmtc0);
363I_u2u1s3(_daddiu); 385I_u2u1s3(_daddiu);
364I_u3u1u2(_daddu); 386I_u3u1u2(_daddu);
365I_u2u1u3(_dsll); 387I_u2u1u3(_dsll);
@@ -376,8 +398,8 @@ I_u2s3u1(_ll);
376I_u2s3u1(_lld); 398I_u2s3u1(_lld);
377I_u1s2(_lui); 399I_u1s2(_lui);
378I_u2s3u1(_lw); 400I_u2s3u1(_lw);
379I_u1u2(_mfc0); 401I_u1u2u3(_mfc0);
380I_u1u2(_mtc0); 402I_u1u2u3(_mtc0);
381I_u2u1u3(_ori); 403I_u2u1u3(_ori);
382I_0(_rfe); 404I_0(_rfe);
383I_u2s3u1(_sc); 405I_u2s3u1(_sc);
@@ -451,8 +473,8 @@ L_LA(_r3000_write_probe_fail)
451# define i_SLL(buf, rs, rt, sh) i_dsll(buf, rs, rt, sh) 473# define i_SLL(buf, rs, rt, sh) i_dsll(buf, rs, rt, sh)
452# define i_SRA(buf, rs, rt, sh) i_dsra(buf, rs, rt, sh) 474# define i_SRA(buf, rs, rt, sh) i_dsra(buf, rs, rt, sh)
453# define i_SRL(buf, rs, rt, sh) i_dsrl(buf, rs, rt, sh) 475# define i_SRL(buf, rs, rt, sh) i_dsrl(buf, rs, rt, sh)
454# define i_MFC0(buf, rt, rd) i_dmfc0(buf, rt, rd) 476# define i_MFC0(buf, rt, rd...) i_dmfc0(buf, rt, rd)
455# define i_MTC0(buf, rt, rd) i_dmtc0(buf, rt, rd) 477# define i_MTC0(buf, rt, rd...) i_dmtc0(buf, rt, rd)
456# define i_ADDIU(buf, rs, rt, val) i_daddiu(buf, rs, rt, val) 478# define i_ADDIU(buf, rs, rt, val) i_daddiu(buf, rs, rt, val)
457# define i_ADDU(buf, rs, rt, rd) i_daddu(buf, rs, rt, rd) 479# define i_ADDU(buf, rs, rt, rd) i_daddu(buf, rs, rt, rd)
458# define i_SUBU(buf, rs, rt, rd) i_dsubu(buf, rs, rt, rd) 480# define i_SUBU(buf, rs, rt, rd) i_dsubu(buf, rs, rt, rd)
@@ -464,8 +486,8 @@ L_LA(_r3000_write_probe_fail)
464# define i_SLL(buf, rs, rt, sh) i_sll(buf, rs, rt, sh) 486# define i_SLL(buf, rs, rt, sh) i_sll(buf, rs, rt, sh)
465# define i_SRA(buf, rs, rt, sh) i_sra(buf, rs, rt, sh) 487# define i_SRA(buf, rs, rt, sh) i_sra(buf, rs, rt, sh)
466# define i_SRL(buf, rs, rt, sh) i_srl(buf, rs, rt, sh) 488# define i_SRL(buf, rs, rt, sh) i_srl(buf, rs, rt, sh)
467# define i_MFC0(buf, rt, rd) i_mfc0(buf, rt, rd) 489# define i_MFC0(buf, rt, rd...) i_mfc0(buf, rt, rd)
468# define i_MTC0(buf, rt, rd) i_mtc0(buf, rt, rd) 490# define i_MTC0(buf, rt, rd...) i_mtc0(buf, rt, rd)
469# define i_ADDIU(buf, rs, rt, val) i_addiu(buf, rs, rt, val) 491# define i_ADDIU(buf, rs, rt, val) i_addiu(buf, rs, rt, val)
470# define i_ADDU(buf, rs, rt, rd) i_addu(buf, rs, rt, rd) 492# define i_ADDU(buf, rs, rt, rd) i_addu(buf, rs, rt, rd)
471# define i_SUBU(buf, rs, rt, rd) i_subu(buf, rs, rt, rd) 493# define i_SUBU(buf, rs, rt, rd) i_subu(buf, rs, rt, rd)
@@ -670,14 +692,15 @@ static void __init il_bgezl(u32 **p, struct reloc **r, unsigned int reg,
670#define K1 27 692#define K1 27
671 693
672/* Some CP0 registers */ 694/* Some CP0 registers */
673#define C0_INDEX 0 695#define C0_INDEX 0, 0
674#define C0_ENTRYLO0 2 696#define C0_ENTRYLO0 2, 0
675#define C0_ENTRYLO1 3 697#define C0_TCBIND 2, 2
676#define C0_CONTEXT 4 698#define C0_ENTRYLO1 3, 0
677#define C0_BADVADDR 8 699#define C0_CONTEXT 4, 0
678#define C0_ENTRYHI 10 700#define C0_BADVADDR 8, 0
679#define C0_EPC 14 701#define C0_ENTRYHI 10, 0
680#define C0_XCONTEXT 20 702#define C0_EPC 14, 0
703#define C0_XCONTEXT 20, 0
681 704
682#ifdef CONFIG_64BIT 705#ifdef CONFIG_64BIT
683# define GET_CONTEXT(buf, reg) i_MFC0(buf, reg, C0_XCONTEXT) 706# define GET_CONTEXT(buf, reg) i_MFC0(buf, reg, C0_XCONTEXT)
@@ -742,7 +765,7 @@ static void __init build_r3000_tlb_refill_handler(void)
742 } 765 }
743#endif 766#endif
744 767
745 memcpy((void *)CAC_BASE, tlb_handler, 0x80); 768 memcpy((void *)ebase, tlb_handler, 0x80);
746} 769}
747 770
748/* 771/*
@@ -852,6 +875,7 @@ static __init void build_tlb_write_entry(u32 **p, struct label **l,
852 875
853 case CPU_R10000: 876 case CPU_R10000:
854 case CPU_R12000: 877 case CPU_R12000:
878 case CPU_R14000:
855 case CPU_4KC: 879 case CPU_4KC:
856 case CPU_SB1: 880 case CPU_SB1:
857 case CPU_SB1A: 881 case CPU_SB1A:
@@ -883,6 +907,7 @@ static __init void build_tlb_write_entry(u32 **p, struct label **l,
883 case CPU_4KEC: 907 case CPU_4KEC:
884 case CPU_24K: 908 case CPU_24K:
885 case CPU_34K: 909 case CPU_34K:
910 case CPU_74K:
886 i_ehb(p); 911 i_ehb(p);
887 tlbw(p); 912 tlbw(p);
888 break; 913 break;
@@ -951,12 +976,20 @@ build_get_pmde64(u32 **p, struct label **l, struct reloc **r,
951 /* No i_nop needed here, since the next insn doesn't touch TMP. */ 976 /* No i_nop needed here, since the next insn doesn't touch TMP. */
952 977
953#ifdef CONFIG_SMP 978#ifdef CONFIG_SMP
979# ifdef CONFIG_MIPS_MT_SMTC
980 /*
981 * SMTC uses TCBind value as "CPU" index
982 */
983 i_mfc0(p, ptr, C0_TCBIND);
984 i_dsrl(p, ptr, ptr, 19);
985# else
954 /* 986 /*
955 * 64 bit SMP running in XKPHYS has smp_processor_id() << 3 987 * 64 bit SMP running in XKPHYS has smp_processor_id() << 3
956 * stored in CONTEXT. 988 * stored in CONTEXT.
957 */ 989 */
958 i_dmfc0(p, ptr, C0_CONTEXT); 990 i_dmfc0(p, ptr, C0_CONTEXT);
959 i_dsrl(p, ptr, ptr, 23); 991 i_dsrl(p, ptr, ptr, 23);
992#endif
960 i_LA_mostly(p, tmp, pgdc); 993 i_LA_mostly(p, tmp, pgdc);
961 i_daddu(p, ptr, ptr, tmp); 994 i_daddu(p, ptr, ptr, tmp);
962 i_dmfc0(p, tmp, C0_BADVADDR); 995 i_dmfc0(p, tmp, C0_BADVADDR);
@@ -1014,9 +1047,21 @@ build_get_pgde32(u32 **p, unsigned int tmp, unsigned int ptr)
1014 1047
1015 /* 32 bit SMP has smp_processor_id() stored in CONTEXT. */ 1048 /* 32 bit SMP has smp_processor_id() stored in CONTEXT. */
1016#ifdef CONFIG_SMP 1049#ifdef CONFIG_SMP
1050#ifdef CONFIG_MIPS_MT_SMTC
1051 /*
1052 * SMTC uses TCBind value as "CPU" index
1053 */
1054 i_mfc0(p, ptr, C0_TCBIND);
1055 i_LA_mostly(p, tmp, pgdc);
1056 i_srl(p, ptr, ptr, 19);
1057#else
1058 /*
1059 * smp_processor_id() << 3 is stored in CONTEXT.
1060 */
1017 i_mfc0(p, ptr, C0_CONTEXT); 1061 i_mfc0(p, ptr, C0_CONTEXT);
1018 i_LA_mostly(p, tmp, pgdc); 1062 i_LA_mostly(p, tmp, pgdc);
1019 i_srl(p, ptr, ptr, 23); 1063 i_srl(p, ptr, ptr, 23);
1064#endif
1020 i_addu(p, ptr, tmp, ptr); 1065 i_addu(p, ptr, tmp, ptr);
1021#else 1066#else
1022 i_LA_mostly(p, ptr, pgdc); 1067 i_LA_mostly(p, ptr, pgdc);
@@ -1247,7 +1292,7 @@ static void __init build_r4000_tlb_refill_handler(void)
1247 } 1292 }
1248#endif 1293#endif
1249 1294
1250 memcpy((void *)CAC_BASE, final_handler, 0x100); 1295 memcpy((void *)ebase, final_handler, 0x100);
1251} 1296}
1252 1297
1253/* 1298/*