diff options
Diffstat (limited to 'arch/mips/mm')
| -rw-r--r-- | arch/mips/mm/cerr-sb1.c | 7 | ||||
| -rw-r--r-- | arch/mips/mm/init.c | 2 | ||||
| -rw-r--r-- | arch/mips/mm/tlbex.c | 28 | ||||
| -rw-r--r-- | arch/mips/mm/uasm.c | 16 | ||||
| -rw-r--r-- | arch/mips/mm/uasm.h | 7 |
5 files changed, 49 insertions, 11 deletions
diff --git a/arch/mips/mm/cerr-sb1.c b/arch/mips/mm/cerr-sb1.c index 1bd1f18ac23c..3571090ba178 100644 --- a/arch/mips/mm/cerr-sb1.c +++ b/arch/mips/mm/cerr-sb1.c | |||
| @@ -567,13 +567,10 @@ static uint32_t extract_dc(unsigned short addr, int data) | |||
| 567 | datalo = ((unsigned long long)datalohi << 32) | datalolo; | 567 | datalo = ((unsigned long long)datalohi << 32) | datalolo; |
| 568 | ecc = dc_ecc(datalo); | 568 | ecc = dc_ecc(datalo); |
| 569 | if (ecc != datahi) { | 569 | if (ecc != datahi) { |
| 570 | int bits = 0; | 570 | int bits; |
| 571 | bad_ecc |= 1 << (3-offset); | 571 | bad_ecc |= 1 << (3-offset); |
| 572 | ecc ^= datahi; | 572 | ecc ^= datahi; |
| 573 | while (ecc) { | 573 | bits = hweight8(ecc); |
| 574 | if (ecc & 1) bits++; | ||
| 575 | ecc >>= 1; | ||
| 576 | } | ||
| 577 | res |= (bits == 1) ? CP0_CERRD_DATA_SBE : CP0_CERRD_DATA_DBE; | 574 | res |= (bits == 1) ? CP0_CERRD_DATA_SBE : CP0_CERRD_DATA_DBE; |
| 578 | } | 575 | } |
| 579 | printk(" %02X-%016llX", datahi, datalo); | 576 | printk(" %02X-%016llX", datahi, datalo); |
diff --git a/arch/mips/mm/init.c b/arch/mips/mm/init.c index 8d1f4f363049..9e8d00389eef 100644 --- a/arch/mips/mm/init.c +++ b/arch/mips/mm/init.c | |||
| @@ -462,7 +462,9 @@ void __init_refok free_initmem(void) | |||
| 462 | __pa_symbol(&__init_end)); | 462 | __pa_symbol(&__init_end)); |
| 463 | } | 463 | } |
| 464 | 464 | ||
| 465 | #ifndef CONFIG_MIPS_PGD_C0_CONTEXT | ||
| 465 | unsigned long pgd_current[NR_CPUS]; | 466 | unsigned long pgd_current[NR_CPUS]; |
| 467 | #endif | ||
| 466 | /* | 468 | /* |
| 467 | * On 64-bit we've got three-level pagetables with a slightly | 469 | * On 64-bit we've got three-level pagetables with a slightly |
| 468 | * different layout ... | 470 | * different layout ... |
diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c index bb1719a55d22..3d0baa4a842d 100644 --- a/arch/mips/mm/tlbex.c +++ b/arch/mips/mm/tlbex.c | |||
| @@ -160,6 +160,12 @@ static u32 tlb_handler[128] __cpuinitdata; | |||
| 160 | static struct uasm_label labels[128] __cpuinitdata; | 160 | static struct uasm_label labels[128] __cpuinitdata; |
| 161 | static struct uasm_reloc relocs[128] __cpuinitdata; | 161 | static struct uasm_reloc relocs[128] __cpuinitdata; |
| 162 | 162 | ||
| 163 | #ifndef CONFIG_MIPS_PGD_C0_CONTEXT | ||
| 164 | /* | ||
| 165 | * CONFIG_MIPS_PGD_C0_CONTEXT implies 64 bit and lack of pgd_current, | ||
| 166 | * we cannot do r3000 under these circumstances. | ||
| 167 | */ | ||
| 168 | |||
| 163 | /* | 169 | /* |
| 164 | * The R3000 TLB handler is simple. | 170 | * The R3000 TLB handler is simple. |
| 165 | */ | 171 | */ |
| @@ -199,6 +205,7 @@ static void __cpuinit build_r3000_tlb_refill_handler(void) | |||
| 199 | 205 | ||
| 200 | dump_handler((u32 *)ebase, 32); | 206 | dump_handler((u32 *)ebase, 32); |
| 201 | } | 207 | } |
| 208 | #endif /* CONFIG_MIPS_PGD_C0_CONTEXT */ | ||
| 202 | 209 | ||
| 203 | /* | 210 | /* |
| 204 | * The R4000 TLB handler is much more complicated. We have two | 211 | * The R4000 TLB handler is much more complicated. We have two |
| @@ -497,8 +504,9 @@ static void __cpuinit | |||
| 497 | build_get_pmde64(u32 **p, struct uasm_label **l, struct uasm_reloc **r, | 504 | build_get_pmde64(u32 **p, struct uasm_label **l, struct uasm_reloc **r, |
| 498 | unsigned int tmp, unsigned int ptr) | 505 | unsigned int tmp, unsigned int ptr) |
| 499 | { | 506 | { |
| 507 | #ifndef CONFIG_MIPS_PGD_C0_CONTEXT | ||
| 500 | long pgdc = (long)pgd_current; | 508 | long pgdc = (long)pgd_current; |
| 501 | 509 | #endif | |
| 502 | /* | 510 | /* |
| 503 | * The vmalloc handling is not in the hotpath. | 511 | * The vmalloc handling is not in the hotpath. |
| 504 | */ | 512 | */ |
| @@ -506,7 +514,15 @@ build_get_pmde64(u32 **p, struct uasm_label **l, struct uasm_reloc **r, | |||
| 506 | uasm_il_bltz(p, r, tmp, label_vmalloc); | 514 | uasm_il_bltz(p, r, tmp, label_vmalloc); |
| 507 | /* No uasm_i_nop needed here, since the next insn doesn't touch TMP. */ | 515 | /* No uasm_i_nop needed here, since the next insn doesn't touch TMP. */ |
| 508 | 516 | ||
| 509 | #ifdef CONFIG_SMP | 517 | #ifdef CONFIG_MIPS_PGD_C0_CONTEXT |
| 518 | /* | ||
| 519 | * &pgd << 11 stored in CONTEXT [23..63]. | ||
| 520 | */ | ||
| 521 | UASM_i_MFC0(p, ptr, C0_CONTEXT); | ||
| 522 | uasm_i_dins(p, ptr, 0, 0, 23); /* Clear lower 23 bits of context. */ | ||
| 523 | uasm_i_ori(p, ptr, ptr, 0x540); /* 1 0 1 0 1 << 6 xkphys cached */ | ||
| 524 | uasm_i_drotr(p, ptr, ptr, 11); | ||
| 525 | #elif defined(CONFIG_SMP) | ||
| 510 | # ifdef CONFIG_MIPS_MT_SMTC | 526 | # ifdef CONFIG_MIPS_MT_SMTC |
| 511 | /* | 527 | /* |
| 512 | * SMTC uses TCBind value as "CPU" index | 528 | * SMTC uses TCBind value as "CPU" index |
| @@ -520,7 +536,7 @@ build_get_pmde64(u32 **p, struct uasm_label **l, struct uasm_reloc **r, | |||
| 520 | */ | 536 | */ |
| 521 | uasm_i_dmfc0(p, ptr, C0_CONTEXT); | 537 | uasm_i_dmfc0(p, ptr, C0_CONTEXT); |
| 522 | uasm_i_dsrl(p, ptr, ptr, 23); | 538 | uasm_i_dsrl(p, ptr, ptr, 23); |
| 523 | #endif | 539 | # endif |
| 524 | UASM_i_LA_mostly(p, tmp, pgdc); | 540 | UASM_i_LA_mostly(p, tmp, pgdc); |
| 525 | uasm_i_daddu(p, ptr, ptr, tmp); | 541 | uasm_i_daddu(p, ptr, ptr, tmp); |
| 526 | uasm_i_dmfc0(p, tmp, C0_BADVADDR); | 542 | uasm_i_dmfc0(p, tmp, C0_BADVADDR); |
| @@ -1033,6 +1049,7 @@ build_pte_modifiable(u32 **p, struct uasm_reloc **r, | |||
| 1033 | iPTE_LW(p, pte, ptr); | 1049 | iPTE_LW(p, pte, ptr); |
| 1034 | } | 1050 | } |
| 1035 | 1051 | ||
| 1052 | #ifndef CONFIG_MIPS_PGD_C0_CONTEXT | ||
| 1036 | /* | 1053 | /* |
| 1037 | * R3000 style TLB load/store/modify handlers. | 1054 | * R3000 style TLB load/store/modify handlers. |
| 1038 | */ | 1055 | */ |
| @@ -1184,6 +1201,7 @@ static void __cpuinit build_r3000_tlb_modify_handler(void) | |||
| 1184 | 1201 | ||
| 1185 | dump_handler(handle_tlbm, ARRAY_SIZE(handle_tlbm)); | 1202 | dump_handler(handle_tlbm, ARRAY_SIZE(handle_tlbm)); |
| 1186 | } | 1203 | } |
| 1204 | #endif /* CONFIG_MIPS_PGD_C0_CONTEXT */ | ||
| 1187 | 1205 | ||
| 1188 | /* | 1206 | /* |
| 1189 | * R4000 style TLB load/store/modify handlers. | 1207 | * R4000 style TLB load/store/modify handlers. |
| @@ -1400,6 +1418,7 @@ void __cpuinit build_tlb_refill_handler(void) | |||
| 1400 | case CPU_TX3912: | 1418 | case CPU_TX3912: |
| 1401 | case CPU_TX3922: | 1419 | case CPU_TX3922: |
| 1402 | case CPU_TX3927: | 1420 | case CPU_TX3927: |
| 1421 | #ifndef CONFIG_MIPS_PGD_C0_CONTEXT | ||
| 1403 | build_r3000_tlb_refill_handler(); | 1422 | build_r3000_tlb_refill_handler(); |
| 1404 | if (!run_once) { | 1423 | if (!run_once) { |
| 1405 | build_r3000_tlb_load_handler(); | 1424 | build_r3000_tlb_load_handler(); |
| @@ -1407,6 +1426,9 @@ void __cpuinit build_tlb_refill_handler(void) | |||
| 1407 | build_r3000_tlb_modify_handler(); | 1426 | build_r3000_tlb_modify_handler(); |
| 1408 | run_once++; | 1427 | run_once++; |
| 1409 | } | 1428 | } |
| 1429 | #else | ||
| 1430 | panic("No R3000 TLB refill handler"); | ||
| 1431 | #endif | ||
| 1410 | break; | 1432 | break; |
| 1411 | 1433 | ||
| 1412 | case CPU_R6000: | 1434 | case CPU_R6000: |
diff --git a/arch/mips/mm/uasm.c b/arch/mips/mm/uasm.c index f467199676a8..0a165c5179a1 100644 --- a/arch/mips/mm/uasm.c +++ b/arch/mips/mm/uasm.c | |||
| @@ -60,11 +60,11 @@ enum opcode { | |||
| 60 | insn_beql, insn_bgez, insn_bgezl, insn_bltz, insn_bltzl, | 60 | insn_beql, insn_bgez, insn_bgezl, insn_bltz, insn_bltzl, |
| 61 | insn_bne, insn_cache, insn_daddu, insn_daddiu, insn_dmfc0, | 61 | insn_bne, insn_cache, insn_daddu, insn_daddiu, insn_dmfc0, |
| 62 | insn_dmtc0, insn_dsll, insn_dsll32, insn_dsra, insn_dsrl, | 62 | insn_dmtc0, insn_dsll, insn_dsll32, insn_dsra, insn_dsrl, |
| 63 | insn_dsrl32, insn_dsubu, insn_eret, insn_j, insn_jal, insn_jr, | 63 | insn_dsrl32, insn_drotr, insn_dsubu, insn_eret, insn_j, insn_jal, |
| 64 | insn_ld, insn_ll, insn_lld, insn_lui, insn_lw, insn_mfc0, | 64 | insn_jr, insn_ld, insn_ll, insn_lld, insn_lui, insn_lw, insn_mfc0, |
| 65 | insn_mtc0, insn_ori, insn_pref, insn_rfe, insn_sc, insn_scd, | 65 | insn_mtc0, insn_ori, insn_pref, insn_rfe, insn_sc, insn_scd, |
| 66 | insn_sd, insn_sll, insn_sra, insn_srl, insn_subu, insn_sw, | 66 | insn_sd, insn_sll, insn_sra, insn_srl, insn_subu, insn_sw, |
| 67 | insn_tlbp, insn_tlbwi, insn_tlbwr, insn_xor, insn_xori | 67 | insn_tlbp, insn_tlbwi, insn_tlbwr, insn_xor, insn_xori, insn_dins |
| 68 | }; | 68 | }; |
| 69 | 69 | ||
| 70 | struct insn { | 70 | struct insn { |
| @@ -104,6 +104,7 @@ static struct insn insn_table[] __cpuinitdata = { | |||
| 104 | { insn_dsra, M(spec_op, 0, 0, 0, 0, dsra_op), RT | RD | RE }, | 104 | { insn_dsra, M(spec_op, 0, 0, 0, 0, dsra_op), RT | RD | RE }, |
| 105 | { insn_dsrl, M(spec_op, 0, 0, 0, 0, dsrl_op), RT | RD | RE }, | 105 | { insn_dsrl, M(spec_op, 0, 0, 0, 0, dsrl_op), RT | RD | RE }, |
| 106 | { insn_dsrl32, M(spec_op, 0, 0, 0, 0, dsrl32_op), RT | RD | RE }, | 106 | { insn_dsrl32, M(spec_op, 0, 0, 0, 0, dsrl32_op), RT | RD | RE }, |
| 107 | { insn_drotr, M(spec_op, 1, 0, 0, 0, dsrl_op), RT | RD | RE }, | ||
| 107 | { insn_dsubu, M(spec_op, 0, 0, 0, 0, dsubu_op), RS | RT | RD }, | 108 | { insn_dsubu, M(spec_op, 0, 0, 0, 0, dsubu_op), RS | RT | RD }, |
| 108 | { insn_eret, M(cop0_op, cop_op, 0, 0, 0, eret_op), 0 }, | 109 | { insn_eret, M(cop0_op, cop_op, 0, 0, 0, eret_op), 0 }, |
| 109 | { insn_j, M(j_op, 0, 0, 0, 0, 0), JIMM }, | 110 | { insn_j, M(j_op, 0, 0, 0, 0, 0), JIMM }, |
| @@ -132,6 +133,7 @@ static struct insn insn_table[] __cpuinitdata = { | |||
| 132 | { insn_tlbwr, M(cop0_op, cop_op, 0, 0, 0, tlbwr_op), 0 }, | 133 | { insn_tlbwr, M(cop0_op, cop_op, 0, 0, 0, tlbwr_op), 0 }, |
| 133 | { insn_xor, M(spec_op, 0, 0, 0, 0, xor_op), RS | RT | RD }, | 134 | { insn_xor, M(spec_op, 0, 0, 0, 0, xor_op), RS | RT | RD }, |
| 134 | { insn_xori, M(xori_op, 0, 0, 0, 0, 0), RS | RT | UIMM }, | 135 | { insn_xori, M(xori_op, 0, 0, 0, 0, 0), RS | RT | UIMM }, |
| 136 | { insn_dins, M(spec3_op, 0, 0, 0, 0, dins_op), RS | RT | RD | RE }, | ||
| 135 | { insn_invalid, 0, 0 } | 137 | { insn_invalid, 0, 0 } |
| 136 | }; | 138 | }; |
| 137 | 139 | ||
| @@ -304,6 +306,12 @@ Ip_u2u1s3(op) \ | |||
| 304 | build_insn(buf, insn##op, b, a, c); \ | 306 | build_insn(buf, insn##op, b, a, c); \ |
| 305 | } | 307 | } |
| 306 | 308 | ||
| 309 | #define I_u2u1msbu3(op) \ | ||
| 310 | Ip_u2u1msbu3(op) \ | ||
| 311 | { \ | ||
| 312 | build_insn(buf, insn##op, b, a, c+d-1, c); \ | ||
| 313 | } | ||
| 314 | |||
| 307 | #define I_u1u2(op) \ | 315 | #define I_u1u2(op) \ |
| 308 | Ip_u1u2(op) \ | 316 | Ip_u1u2(op) \ |
| 309 | { \ | 317 | { \ |
| @@ -349,6 +357,7 @@ I_u2u1u3(_dsll32) | |||
| 349 | I_u2u1u3(_dsra) | 357 | I_u2u1u3(_dsra) |
| 350 | I_u2u1u3(_dsrl) | 358 | I_u2u1u3(_dsrl) |
| 351 | I_u2u1u3(_dsrl32) | 359 | I_u2u1u3(_dsrl32) |
| 360 | I_u2u1u3(_drotr) | ||
| 352 | I_u3u1u2(_dsubu) | 361 | I_u3u1u2(_dsubu) |
| 353 | I_0(_eret) | 362 | I_0(_eret) |
| 354 | I_u1(_j) | 363 | I_u1(_j) |
| @@ -377,6 +386,7 @@ I_0(_tlbwi) | |||
| 377 | I_0(_tlbwr) | 386 | I_0(_tlbwr) |
| 378 | I_u3u1u2(_xor) | 387 | I_u3u1u2(_xor) |
| 379 | I_u2u1u3(_xori) | 388 | I_u2u1u3(_xori) |
| 389 | I_u2u1msbu3(_dins); | ||
| 380 | 390 | ||
| 381 | /* Handle labels. */ | 391 | /* Handle labels. */ |
| 382 | void __cpuinit uasm_build_label(struct uasm_label **lab, u32 *addr, int lid) | 392 | void __cpuinit uasm_build_label(struct uasm_label **lab, u32 *addr, int lid) |
diff --git a/arch/mips/mm/uasm.h b/arch/mips/mm/uasm.h index c6d1e3dd82d4..3d153edaa51e 100644 --- a/arch/mips/mm/uasm.h +++ b/arch/mips/mm/uasm.h | |||
| @@ -34,6 +34,11 @@ uasm_i##op(u32 **buf, unsigned int a, signed int b, unsigned int c) | |||
| 34 | void __cpuinit \ | 34 | void __cpuinit \ |
| 35 | uasm_i##op(u32 **buf, unsigned int a, unsigned int b, signed int c) | 35 | uasm_i##op(u32 **buf, unsigned int a, unsigned int b, signed int c) |
| 36 | 36 | ||
| 37 | #define Ip_u2u1msbu3(op) \ | ||
| 38 | void __cpuinit \ | ||
| 39 | uasm_i##op(u32 **buf, unsigned int a, unsigned int b, unsigned int c, \ | ||
| 40 | unsigned int d) | ||
| 41 | |||
| 37 | #define Ip_u1u2(op) \ | 42 | #define Ip_u1u2(op) \ |
| 38 | void __cpuinit uasm_i##op(u32 **buf, unsigned int a, unsigned int b) | 43 | void __cpuinit uasm_i##op(u32 **buf, unsigned int a, unsigned int b) |
| 39 | 44 | ||
| @@ -65,6 +70,7 @@ Ip_u2u1u3(_dsll32); | |||
| 65 | Ip_u2u1u3(_dsra); | 70 | Ip_u2u1u3(_dsra); |
| 66 | Ip_u2u1u3(_dsrl); | 71 | Ip_u2u1u3(_dsrl); |
| 67 | Ip_u2u1u3(_dsrl32); | 72 | Ip_u2u1u3(_dsrl32); |
| 73 | Ip_u2u1u3(_drotr); | ||
| 68 | Ip_u3u1u2(_dsubu); | 74 | Ip_u3u1u2(_dsubu); |
| 69 | Ip_0(_eret); | 75 | Ip_0(_eret); |
| 70 | Ip_u1(_j); | 76 | Ip_u1(_j); |
| @@ -93,6 +99,7 @@ Ip_0(_tlbwi); | |||
| 93 | Ip_0(_tlbwr); | 99 | Ip_0(_tlbwr); |
| 94 | Ip_u3u1u2(_xor); | 100 | Ip_u3u1u2(_xor); |
| 95 | Ip_u2u1u3(_xori); | 101 | Ip_u2u1u3(_xori); |
| 102 | Ip_u2u1msbu3(_dins); | ||
| 96 | 103 | ||
| 97 | /* Handle labels. */ | 104 | /* Handle labels. */ |
| 98 | struct uasm_label { | 105 | struct uasm_label { |
