aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJayachandran C <jchandra@broadcom.com>2013-06-11 10:41:35 -0400
committerRalf Baechle <ralf@linux-mips.org>2013-06-13 11:46:43 -0400
commit7777b9395b77664cb736b941f95fb8f656edd111 (patch)
treeab4cf1c71a9c8bf41bca5b289e9854a91a2909b6
parent8ecd08378c132536c7d47af225e09bd6f3a16779 (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.c1
-rw-r--r--arch/mips/mm/tlbex.c41
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
306static unsigned int kscratch_used_mask __cpuinitdata; 306static unsigned int kscratch_used_mask __cpuinitdata;
307 307
308static 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
308static int __cpuinit allocate_kscratch(void) 319static 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)
385static void __cpuinit build_restore_work_registers(u32 **p) 396static 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 {
1096static struct mips_huge_tlb_info __cpuinit 1107static struct mips_huge_tlb_info __cpuinit
1097build_fast_tlb_refill_handler (u32 **p, struct uasm_label **l, 1108build_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");