aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/mm
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2006-10-23 21:29:01 -0400
committerRalf Baechle <ralf@linux-mips.org>2006-11-01 12:46:09 -0500
commit242954b5aa8e5ec84f46a84637daf08ee4247c6e (patch)
tree7fb896349b377f5f819d4050bb92eeee05598571 /arch/mips/mm
parent4b1c46a383aafc137bc91a0f9698bfc11e062d1b (diff)
[MIPS] 16K & 64K page size fixes
Derived from Peter Watkins <treestem@gmail.com>'s work. Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch/mips/mm')
-rw-r--r--arch/mips/mm/pg-r4k.c30
-rw-r--r--arch/mips/mm/tlbex.c13
2 files changed, 38 insertions, 5 deletions
diff --git a/arch/mips/mm/pg-r4k.c b/arch/mips/mm/pg-r4k.c
index b7c749232ffe..d41fc5885e87 100644
--- a/arch/mips/mm/pg-r4k.c
+++ b/arch/mips/mm/pg-r4k.c
@@ -270,6 +270,20 @@ static inline void build_addiu_a2_a0(unsigned long offset)
270 emit_instruction(mi); 270 emit_instruction(mi);
271} 271}
272 272
273static inline void build_addiu_a2(unsigned long offset)
274{
275 union mips_instruction mi;
276
277 BUG_ON(offset > 0x7fff);
278
279 mi.i_format.opcode = cpu_has_64bit_gp_regs ? daddiu_op : addiu_op;
280 mi.i_format.rs = 6; /* $a2 */
281 mi.i_format.rt = 6; /* $a2 */
282 mi.i_format.simmediate = offset;
283
284 emit_instruction(mi);
285}
286
273static inline void build_addiu_a1(unsigned long offset) 287static inline void build_addiu_a1(unsigned long offset)
274{ 288{
275 union mips_instruction mi; 289 union mips_instruction mi;
@@ -333,6 +347,7 @@ static inline void build_jr_ra(void)
333void __init build_clear_page(void) 347void __init build_clear_page(void)
334{ 348{
335 unsigned int loop_start; 349 unsigned int loop_start;
350 unsigned long off;
336 351
337 epc = (unsigned int *) &clear_page_array; 352 epc = (unsigned int *) &clear_page_array;
338 instruction_pending = 0; 353 instruction_pending = 0;
@@ -369,7 +384,12 @@ void __init build_clear_page(void)
369 } 384 }
370 } 385 }
371 386
372 build_addiu_a2_a0(PAGE_SIZE - (cpu_has_prefetch ? pref_offset_clear : 0)); 387 off = PAGE_SIZE - (cpu_has_prefetch ? pref_offset_clear : 0);
388 if (off > 0x7fff) {
389 build_addiu_a2_a0(off >> 1);
390 build_addiu_a2(off >> 1);
391 } else
392 build_addiu_a2_a0(off);
373 393
374 if (R4600_V2_HIT_CACHEOP_WAR && cpu_is_r4600_v2_x()) 394 if (R4600_V2_HIT_CACHEOP_WAR && cpu_is_r4600_v2_x())
375 build_insn_word(0x3c01a000); /* lui $at, 0xa000 */ 395 build_insn_word(0x3c01a000); /* lui $at, 0xa000 */
@@ -420,12 +440,18 @@ dest = label();
420void __init build_copy_page(void) 440void __init build_copy_page(void)
421{ 441{
422 unsigned int loop_start; 442 unsigned int loop_start;
443 unsigned long off;
423 444
424 epc = (unsigned int *) &copy_page_array; 445 epc = (unsigned int *) &copy_page_array;
425 store_offset = load_offset = 0; 446 store_offset = load_offset = 0;
426 instruction_pending = 0; 447 instruction_pending = 0;
427 448
428 build_addiu_a2_a0(PAGE_SIZE - (cpu_has_prefetch ? pref_offset_copy : 0)); 449 off = PAGE_SIZE - (cpu_has_prefetch ? pref_offset_copy : 0);
450 if (off > 0x7fff) {
451 build_addiu_a2_a0(off >> 1);
452 build_addiu_a2(off >> 1);
453 } else
454 build_addiu_a2_a0(off);
429 455
430 if (R4600_V2_HIT_CACHEOP_WAR && cpu_is_r4600_v2_x()) 456 if (R4600_V2_HIT_CACHEOP_WAR && cpu_is_r4600_v2_x())
431 build_insn_word(0x3c01a000); /* lui $at, 0xa000 */ 457 build_insn_word(0x3c01a000); /* lui $at, 0xa000 */
diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c
index 6f8b25cfa6f0..fec318a1c8c5 100644
--- a/arch/mips/mm/tlbex.c
+++ b/arch/mips/mm/tlbex.c
@@ -102,7 +102,7 @@ enum opcode {
102 insn_addu, insn_addiu, insn_and, insn_andi, insn_beq, 102 insn_addu, insn_addiu, insn_and, insn_andi, insn_beq,
103 insn_beql, insn_bgez, insn_bgezl, insn_bltz, insn_bltzl, 103 insn_beql, insn_bgez, insn_bgezl, insn_bltz, insn_bltzl,
104 insn_bne, insn_daddu, insn_daddiu, insn_dmfc0, insn_dmtc0, 104 insn_bne, insn_daddu, insn_daddiu, insn_dmfc0, insn_dmtc0,
105 insn_dsll, insn_dsll32, insn_dsra, insn_dsrl, 105 insn_dsll, insn_dsll32, insn_dsra, insn_dsrl, insn_dsrl32,
106 insn_dsubu, insn_eret, insn_j, insn_jal, insn_jr, insn_ld, 106 insn_dsubu, insn_eret, insn_j, insn_jal, insn_jr, insn_ld,
107 insn_ll, insn_lld, insn_lui, insn_lw, insn_mfc0, insn_mtc0, 107 insn_ll, insn_lld, insn_lui, insn_lw, insn_mfc0, insn_mtc0,
108 insn_ori, insn_rfe, insn_sc, insn_scd, insn_sd, insn_sll, 108 insn_ori, insn_rfe, insn_sc, insn_scd, insn_sd, insn_sll,
@@ -145,6 +145,7 @@ static __initdata struct insn insn_table[] = {
145 { insn_dsll32, M(spec_op,0,0,0,0,dsll32_op), RT | RD | RE }, 145 { insn_dsll32, M(spec_op,0,0,0,0,dsll32_op), RT | RD | RE },
146 { insn_dsra, M(spec_op,0,0,0,0,dsra_op), RT | RD | RE }, 146 { insn_dsra, M(spec_op,0,0,0,0,dsra_op), RT | RD | RE },
147 { insn_dsrl, M(spec_op,0,0,0,0,dsrl_op), RT | RD | RE }, 147 { insn_dsrl, M(spec_op,0,0,0,0,dsrl_op), RT | RD | RE },
148 { insn_dsrl32, M(spec_op,0,0,0,0,dsrl32_op), RT | RD | RE },
148 { insn_dsubu, M(spec_op,0,0,0,0,dsubu_op), RS | RT | RD }, 149 { insn_dsubu, M(spec_op,0,0,0,0,dsubu_op), RS | RT | RD },
149 { insn_eret, M(cop0_op,cop_op,0,0,0,eret_op), 0 }, 150 { insn_eret, M(cop0_op,cop_op,0,0,0,eret_op), 0 },
150 { insn_j, M(j_op,0,0,0,0,0), JIMM }, 151 { insn_j, M(j_op,0,0,0,0,0), JIMM },
@@ -385,6 +386,7 @@ I_u2u1u3(_dsll);
385I_u2u1u3(_dsll32); 386I_u2u1u3(_dsll32);
386I_u2u1u3(_dsra); 387I_u2u1u3(_dsra);
387I_u2u1u3(_dsrl); 388I_u2u1u3(_dsrl);
389I_u2u1u3(_dsrl32);
388I_u3u1u2(_dsubu); 390I_u3u1u2(_dsubu);
389I_0(_eret); 391I_0(_eret);
390I_u1(_j); 392I_u1(_j);
@@ -996,7 +998,12 @@ build_get_pmde64(u32 **p, struct label **l, struct reloc **r,
996#endif 998#endif
997 999
998 l_vmalloc_done(l, *p); 1000 l_vmalloc_done(l, *p);
999 i_dsrl(p, tmp, tmp, PGDIR_SHIFT-3); /* get pgd offset in bytes */ 1001
1002 if (PGDIR_SHIFT - 3 < 32) /* get pgd offset in bytes */
1003 i_dsrl(p, tmp, tmp, PGDIR_SHIFT-3);
1004 else
1005 i_dsrl32(p, tmp, tmp, PGDIR_SHIFT - 3 - 32);
1006
1000 i_andi(p, tmp, tmp, (PTRS_PER_PGD - 1)<<3); 1007 i_andi(p, tmp, tmp, (PTRS_PER_PGD - 1)<<3);
1001 i_daddu(p, ptr, ptr, tmp); /* add in pgd offset */ 1008 i_daddu(p, ptr, ptr, tmp); /* add in pgd offset */
1002 i_dmfc0(p, tmp, C0_BADVADDR); /* get faulting address */ 1009 i_dmfc0(p, tmp, C0_BADVADDR); /* get faulting address */
@@ -1073,7 +1080,7 @@ build_get_pgde32(u32 **p, unsigned int tmp, unsigned int ptr)
1073 1080
1074static __init void build_adjust_context(u32 **p, unsigned int ctx) 1081static __init void build_adjust_context(u32 **p, unsigned int ctx)
1075{ 1082{
1076 unsigned int shift = 4 - (PTE_T_LOG2 + 1); 1083 unsigned int shift = 4 - (PTE_T_LOG2 + 1) + PAGE_SHIFT - 12;
1077 unsigned int mask = (PTRS_PER_PTE / 2 - 1) << (PTE_T_LOG2 + 1); 1084 unsigned int mask = (PTRS_PER_PTE / 2 - 1) << (PTE_T_LOG2 + 1);
1078 1085
1079 switch (current_cpu_data.cputype) { 1086 switch (current_cpu_data.cputype) {