diff options
author | Jayachandran C <jchandra@broadcom.com> | 2013-06-11 10:41:35 -0400 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2013-06-13 11:46:43 -0400 |
commit | 7777b9395b77664cb736b941f95fb8f656edd111 (patch) | |
tree | ab4cf1c71a9c8bf41bca5b289e9854a91a2909b6 | |
parent | 8ecd08378c132536c7d47af225e09bd6f3a16779 (diff) |
MIPS: Allow platform specific scratch registers
XLR/XLP COP0 scratch is register 22, sel 0-7. Add a function
c0_kscratch() which returns the scratch register for the platform,
and use the return value while generating TLB handlers.
Setup kscratch_mask to 0xf for XLR/XLP since the config4 register
does not exist. This allows the kernel to allocate scratch registers
0-3 if needed.
Signed-off-by: Jayachandran C <jchandra@broadcom.com>
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/5445/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
-rw-r--r-- | arch/mips/kernel/cpu-probe.c | 1 | ||||
-rw-r--r-- | arch/mips/mm/tlbex.c | 41 |
2 files changed, 27 insertions, 15 deletions
diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c index c6568bf4b1b0..265c97da6619 100644 --- a/arch/mips/kernel/cpu-probe.c +++ b/arch/mips/kernel/cpu-probe.c | |||
@@ -959,6 +959,7 @@ static inline void cpu_probe_netlogic(struct cpuinfo_mips *c, int cpu) | |||
959 | set_isa(c, MIPS_CPU_ISA_M64R1); | 959 | set_isa(c, MIPS_CPU_ISA_M64R1); |
960 | c->tlbsize = ((read_c0_config1() >> 25) & 0x3f) + 1; | 960 | c->tlbsize = ((read_c0_config1() >> 25) & 0x3f) + 1; |
961 | } | 961 | } |
962 | c->kscratch_mask = 0xf; | ||
962 | } | 963 | } |
963 | 964 | ||
964 | #ifdef CONFIG_64BIT | 965 | #ifdef CONFIG_64BIT |
diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c index afeef93f81a7..c052df8ae7d7 100644 --- a/arch/mips/mm/tlbex.c +++ b/arch/mips/mm/tlbex.c | |||
@@ -305,6 +305,17 @@ static int check_for_high_segbits __cpuinitdata; | |||
305 | 305 | ||
306 | static unsigned int kscratch_used_mask __cpuinitdata; | 306 | static unsigned int kscratch_used_mask __cpuinitdata; |
307 | 307 | ||
308 | static inline int __maybe_unused c0_kscratch(void) | ||
309 | { | ||
310 | switch (current_cpu_type()) { | ||
311 | case CPU_XLP: | ||
312 | case CPU_XLR: | ||
313 | return 22; | ||
314 | default: | ||
315 | return 31; | ||
316 | } | ||
317 | } | ||
318 | |||
308 | static int __cpuinit allocate_kscratch(void) | 319 | static int __cpuinit allocate_kscratch(void) |
309 | { | 320 | { |
310 | int r; | 321 | int r; |
@@ -336,7 +347,7 @@ static struct work_registers __cpuinit build_get_work_registers(u32 **p) | |||
336 | 347 | ||
337 | if (scratch_reg > 0) { | 348 | if (scratch_reg > 0) { |
338 | /* Save in CPU local C0_KScratch? */ | 349 | /* Save in CPU local C0_KScratch? */ |
339 | UASM_i_MTC0(p, 1, 31, scratch_reg); | 350 | UASM_i_MTC0(p, 1, c0_kscratch(), scratch_reg); |
340 | r.r1 = K0; | 351 | r.r1 = K0; |
341 | r.r2 = K1; | 352 | r.r2 = K1; |
342 | r.r3 = 1; | 353 | r.r3 = 1; |
@@ -385,7 +396,7 @@ static struct work_registers __cpuinit build_get_work_registers(u32 **p) | |||
385 | static void __cpuinit build_restore_work_registers(u32 **p) | 396 | static void __cpuinit build_restore_work_registers(u32 **p) |
386 | { | 397 | { |
387 | if (scratch_reg > 0) { | 398 | if (scratch_reg > 0) { |
388 | UASM_i_MFC0(p, 1, 31, scratch_reg); | 399 | UASM_i_MFC0(p, 1, c0_kscratch(), scratch_reg); |
389 | return; | 400 | return; |
390 | } | 401 | } |
391 | /* K0 already points to save area, restore $1 and $2 */ | 402 | /* K0 already points to save area, restore $1 and $2 */ |
@@ -674,7 +685,7 @@ static __cpuinit void build_restore_pagemask(u32 **p, | |||
674 | uasm_il_b(p, r, lid); | 685 | uasm_il_b(p, r, lid); |
675 | } | 686 | } |
676 | if (scratch_reg > 0) | 687 | if (scratch_reg > 0) |
677 | UASM_i_MFC0(p, 1, 31, scratch_reg); | 688 | UASM_i_MFC0(p, 1, c0_kscratch(), scratch_reg); |
678 | else | 689 | else |
679 | UASM_i_LW(p, 1, scratchpad_offset(0), 0); | 690 | UASM_i_LW(p, 1, scratchpad_offset(0), 0); |
680 | } else { | 691 | } else { |
@@ -817,7 +828,7 @@ build_get_pmde64(u32 **p, struct uasm_label **l, struct uasm_reloc **r, | |||
817 | #ifdef CONFIG_MIPS_PGD_C0_CONTEXT | 828 | #ifdef CONFIG_MIPS_PGD_C0_CONTEXT |
818 | if (pgd_reg != -1) { | 829 | if (pgd_reg != -1) { |
819 | /* pgd is in pgd_reg */ | 830 | /* pgd is in pgd_reg */ |
820 | UASM_i_MFC0(p, ptr, 31, pgd_reg); | 831 | UASM_i_MFC0(p, ptr, c0_kscratch(), pgd_reg); |
821 | } else { | 832 | } else { |
822 | /* | 833 | /* |
823 | * &pgd << 11 stored in CONTEXT [23..63]. | 834 | * &pgd << 11 stored in CONTEXT [23..63]. |
@@ -930,7 +941,7 @@ build_get_pgd_vmalloc64(u32 **p, struct uasm_label **l, struct uasm_reloc **r, | |||
930 | 941 | ||
931 | if (mode == refill_scratch) { | 942 | if (mode == refill_scratch) { |
932 | if (scratch_reg > 0) | 943 | if (scratch_reg > 0) |
933 | UASM_i_MFC0(p, 1, 31, scratch_reg); | 944 | UASM_i_MFC0(p, 1, c0_kscratch(), scratch_reg); |
934 | else | 945 | else |
935 | UASM_i_LW(p, 1, scratchpad_offset(0), 0); | 946 | UASM_i_LW(p, 1, scratchpad_offset(0), 0); |
936 | } else { | 947 | } else { |
@@ -1096,7 +1107,7 @@ struct mips_huge_tlb_info { | |||
1096 | static struct mips_huge_tlb_info __cpuinit | 1107 | static struct mips_huge_tlb_info __cpuinit |
1097 | build_fast_tlb_refill_handler (u32 **p, struct uasm_label **l, | 1108 | build_fast_tlb_refill_handler (u32 **p, struct uasm_label **l, |
1098 | struct uasm_reloc **r, unsigned int tmp, | 1109 | struct uasm_reloc **r, unsigned int tmp, |
1099 | unsigned int ptr, int c0_scratch) | 1110 | unsigned int ptr, int c0_scratch_reg) |
1100 | { | 1111 | { |
1101 | struct mips_huge_tlb_info rv; | 1112 | struct mips_huge_tlb_info rv; |
1102 | unsigned int even, odd; | 1113 | unsigned int even, odd; |
@@ -1110,12 +1121,12 @@ build_fast_tlb_refill_handler (u32 **p, struct uasm_label **l, | |||
1110 | UASM_i_MFC0(p, tmp, C0_BADVADDR); | 1121 | UASM_i_MFC0(p, tmp, C0_BADVADDR); |
1111 | 1122 | ||
1112 | if (pgd_reg != -1) | 1123 | if (pgd_reg != -1) |
1113 | UASM_i_MFC0(p, ptr, 31, pgd_reg); | 1124 | UASM_i_MFC0(p, ptr, c0_kscratch(), pgd_reg); |
1114 | else | 1125 | else |
1115 | UASM_i_MFC0(p, ptr, C0_CONTEXT); | 1126 | UASM_i_MFC0(p, ptr, C0_CONTEXT); |
1116 | 1127 | ||
1117 | if (c0_scratch >= 0) | 1128 | if (c0_scratch_reg >= 0) |
1118 | UASM_i_MTC0(p, scratch, 31, c0_scratch); | 1129 | UASM_i_MTC0(p, scratch, c0_kscratch(), c0_scratch_reg); |
1119 | else | 1130 | else |
1120 | UASM_i_SW(p, scratch, scratchpad_offset(0), 0); | 1131 | UASM_i_SW(p, scratch, scratchpad_offset(0), 0); |
1121 | 1132 | ||
@@ -1130,14 +1141,14 @@ build_fast_tlb_refill_handler (u32 **p, struct uasm_label **l, | |||
1130 | } | 1141 | } |
1131 | } else { | 1142 | } else { |
1132 | if (pgd_reg != -1) | 1143 | if (pgd_reg != -1) |
1133 | UASM_i_MFC0(p, ptr, 31, pgd_reg); | 1144 | UASM_i_MFC0(p, ptr, c0_kscratch(), pgd_reg); |
1134 | else | 1145 | else |
1135 | UASM_i_MFC0(p, ptr, C0_CONTEXT); | 1146 | UASM_i_MFC0(p, ptr, C0_CONTEXT); |
1136 | 1147 | ||
1137 | UASM_i_MFC0(p, tmp, C0_BADVADDR); | 1148 | UASM_i_MFC0(p, tmp, C0_BADVADDR); |
1138 | 1149 | ||
1139 | if (c0_scratch >= 0) | 1150 | if (c0_scratch_reg >= 0) |
1140 | UASM_i_MTC0(p, scratch, 31, c0_scratch); | 1151 | UASM_i_MTC0(p, scratch, c0_kscratch(), c0_scratch_reg); |
1141 | else | 1152 | else |
1142 | UASM_i_SW(p, scratch, scratchpad_offset(0), 0); | 1153 | UASM_i_SW(p, scratch, scratchpad_offset(0), 0); |
1143 | 1154 | ||
@@ -1242,8 +1253,8 @@ build_fast_tlb_refill_handler (u32 **p, struct uasm_label **l, | |||
1242 | } | 1253 | } |
1243 | UASM_i_MTC0(p, odd, C0_ENTRYLO1); /* load it */ | 1254 | UASM_i_MTC0(p, odd, C0_ENTRYLO1); /* load it */ |
1244 | 1255 | ||
1245 | if (c0_scratch >= 0) { | 1256 | if (c0_scratch_reg >= 0) { |
1246 | UASM_i_MFC0(p, scratch, 31, c0_scratch); | 1257 | UASM_i_MFC0(p, scratch, c0_kscratch(), c0_scratch_reg); |
1247 | build_tlb_write_entry(p, l, r, tlb_random); | 1258 | build_tlb_write_entry(p, l, r, tlb_random); |
1248 | uasm_l_leave(l, *p); | 1259 | uasm_l_leave(l, *p); |
1249 | rv.restore_scratch = 1; | 1260 | rv.restore_scratch = 1; |
@@ -1490,7 +1501,7 @@ static void __cpuinit build_r4000_setup_pgd(void) | |||
1490 | } else { | 1501 | } else { |
1491 | /* PGD in c0_KScratch */ | 1502 | /* PGD in c0_KScratch */ |
1492 | uasm_i_jr(&p, 31); | 1503 | uasm_i_jr(&p, 31); |
1493 | UASM_i_MTC0(&p, a0, 31, pgd_reg); | 1504 | UASM_i_MTC0(&p, a0, c0_kscratch(), pgd_reg); |
1494 | } | 1505 | } |
1495 | if (p - tlbmiss_handler_setup_pgd_array > ARRAY_SIZE(tlbmiss_handler_setup_pgd_array)) | 1506 | if (p - tlbmiss_handler_setup_pgd_array > ARRAY_SIZE(tlbmiss_handler_setup_pgd_array)) |
1496 | panic("tlbmiss_handler_setup_pgd_array space exceeded"); | 1507 | panic("tlbmiss_handler_setup_pgd_array space exceeded"); |