All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 0/3] Use scratch registers on XLR/XLS/XLP
@ 2013-03-20 16:27 Jayachandran C
  2013-03-20 16:27 ` [PATCH 1/3] MIPS: Allow platform specific scratch registers Jayachandran C
                   ` (2 more replies)
  0 siblings, 3 replies; 8+ messages in thread
From: Jayachandran C @ 2013-03-20 16:27 UTC (permalink / raw)
  To: linux-mips, ralf; +Cc: Jayachandran C

This set of patches enable the use of scratch registers on XLR/XLS and XLP
(cop0 reg 22, sel 0-7) to optimize the generated TLB handlers.

The current code assumes scratch is 31, which is fixed by the first patch.
The second patch enables use of a scratch register when it is available
even on a 32-bit or non-r2 platform. The third patch is a cleanup to 
consolidate all the defines needed into one file, this patch does not
have any change in logic.

In the earlier scheme, if MIPS_PGD_C0_CONTEXT was defined, the Context
register or a scratch register would contain the current PGD, and the
Xcontext would contain the smp_processor_id shifted to index pointers.

In the new scheme, the behavior when MIPS_PGD_C0_CONTEXT is defined
remains the same.  But when it is not defined, we still try to allocate
a scratch register for the current pgd. and the smp processor id remains
in Context.

There is also an additional change is to generate the
tlbmiss_handler_setup_pgd() function even when MIPS_PGD_C0_CONTEXT is not
defined.  This function will save the PGD in pgd_current[] and also in
the scratch register if one has been allocated.

Comments/testing welcome.

Thanks,
JC.

Changes in v2:
* Update macros in thread-info.h, remove __ASSEMBLY__ part
* add ASM_CPUID_MFC0 and UASM_i_CPUID_MFC0 which allows us to remove
  a lot of conditional compilation.
* make c0_kscratch a inline function and remove global variable


Jayachandran C (3):
  MIPS: Allow platform specific scratch registers
  MIPS: mm: Use scratch for PGD when !CONFIG_MIPS_PGD_C0_CONTEXT
  MIPS: Move definition of SMP processor id register to header file

 arch/mips/include/asm/mmu_context.h |   26 ++----
 arch/mips/include/asm/stackframe.h  |   26 ++----
 arch/mips/include/asm/thread_info.h |   30 +++++-
 arch/mips/kernel/cpu-probe.c        |    1 +
 arch/mips/mm/tlbex.c                |  176 +++++++++++++++++------------------
 5 files changed, 130 insertions(+), 129 deletions(-)

-- 
1.7.9.5

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH 1/3] MIPS: Allow platform specific scratch registers
  2013-03-20 16:27 [PATCH v2 0/3] Use scratch registers on XLR/XLS/XLP Jayachandran C
@ 2013-03-20 16:27 ` Jayachandran C
  2013-03-20 16:27 ` [PATCH 2/3] MIPS: mm: Use scratch for PGD when !CONFIG_MIPS_PGD_C0_CONTEXT Jayachandran C
  2013-03-20 16:27 ` [PATCH 3/3] MIPS: Move definition of SMP processor id register to header file Jayachandran C
  2 siblings, 0 replies; 8+ messages in thread
From: Jayachandran C @ 2013-03-20 16:27 UTC (permalink / raw)
  To: linux-mips, ralf; +Cc: Jayachandran C

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>
---
 arch/mips/kernel/cpu-probe.c |    1 +
 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 d069a19..1d7bfb3 100644
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -1154,6 +1154,7 @@ static inline void cpu_probe_netlogic(struct cpuinfo_mips *c, int cpu)
 		set_isa(c, MIPS_CPU_ISA_M64R1);
 		c->tlbsize = ((read_c0_config1() >> 25) & 0x3f) + 1;
 	}
+	c->kscratch_mask = 0xf;
 }
 
 #ifdef CONFIG_64BIT
diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c
index 820e661..ca470c6 100644
--- a/arch/mips/mm/tlbex.c
+++ b/arch/mips/mm/tlbex.c
@@ -309,6 +309,17 @@ static int check_for_high_segbits __cpuinitdata;
 
 static unsigned int kscratch_used_mask __cpuinitdata;
 
+static inline int __maybe_unused c0_kscratch(void)
+{
+	switch (current_cpu_type()) {
+	case CPU_XLP:
+	case CPU_XLR:
+		return 22;
+	default:
+		return 31;
+	}
+}
+
 static int __cpuinit allocate_kscratch(void)
 {
 	int r;
@@ -340,7 +351,7 @@ static struct work_registers __cpuinit build_get_work_registers(u32 **p)
 
 	if (scratch_reg > 0) {
 		/* Save in CPU local C0_KScratch? */
-		UASM_i_MTC0(p, 1, 31, scratch_reg);
+		UASM_i_MTC0(p, 1, c0_kscratch(), scratch_reg);
 		r.r1 = K0;
 		r.r2 = K1;
 		r.r3 = 1;
@@ -389,7 +400,7 @@ static struct work_registers __cpuinit build_get_work_registers(u32 **p)
 static void __cpuinit build_restore_work_registers(u32 **p)
 {
 	if (scratch_reg > 0) {
-		UASM_i_MFC0(p, 1, 31, scratch_reg);
+		UASM_i_MFC0(p, 1, c0_kscratch(), scratch_reg);
 		return;
 	}
 	/* K0 already points to save area, restore $1 and $2  */
@@ -678,7 +689,7 @@ static __cpuinit void build_restore_pagemask(u32 **p,
 			uasm_il_b(p, r, lid);
 		}
 		if (scratch_reg > 0)
-			UASM_i_MFC0(p, 1, 31, scratch_reg);
+			UASM_i_MFC0(p, 1, c0_kscratch(), scratch_reg);
 		else
 			UASM_i_LW(p, 1, scratchpad_offset(0), 0);
 	} else {
@@ -821,7 +832,7 @@ build_get_pmde64(u32 **p, struct uasm_label **l, struct uasm_reloc **r,
 #ifdef CONFIG_MIPS_PGD_C0_CONTEXT
 	if (pgd_reg != -1) {
 		/* pgd is in pgd_reg */
-		UASM_i_MFC0(p, ptr, 31, pgd_reg);
+		UASM_i_MFC0(p, ptr, c0_kscratch(), pgd_reg);
 	} else {
 		/*
 		 * &pgd << 11 stored in CONTEXT [23..63].
@@ -934,7 +945,7 @@ build_get_pgd_vmalloc64(u32 **p, struct uasm_label **l, struct uasm_reloc **r,
 
 		if (mode == refill_scratch) {
 			if (scratch_reg > 0)
-				UASM_i_MFC0(p, 1, 31, scratch_reg);
+				UASM_i_MFC0(p, 1, c0_kscratch(), scratch_reg);
 			else
 				UASM_i_LW(p, 1, scratchpad_offset(0), 0);
 		} else {
@@ -1100,7 +1111,7 @@ struct mips_huge_tlb_info {
 static struct mips_huge_tlb_info __cpuinit
 build_fast_tlb_refill_handler (u32 **p, struct uasm_label **l,
 			       struct uasm_reloc **r, unsigned int tmp,
-			       unsigned int ptr, int c0_scratch)
+			       unsigned int ptr, int c0_scratch_reg)
 {
 	struct mips_huge_tlb_info rv;
 	unsigned int even, odd;
@@ -1114,12 +1125,12 @@ build_fast_tlb_refill_handler (u32 **p, struct uasm_label **l,
 		UASM_i_MFC0(p, tmp, C0_BADVADDR);
 
 		if (pgd_reg != -1)
-			UASM_i_MFC0(p, ptr, 31, pgd_reg);
+			UASM_i_MFC0(p, ptr, c0_kscratch(), pgd_reg);
 		else
 			UASM_i_MFC0(p, ptr, C0_CONTEXT);
 
-		if (c0_scratch >= 0)
-			UASM_i_MTC0(p, scratch, 31, c0_scratch);
+		if (c0_scratch_reg >= 0)
+			UASM_i_MTC0(p, scratch, c0_kscratch(), c0_scratch_reg);
 		else
 			UASM_i_SW(p, scratch, scratchpad_offset(0), 0);
 
@@ -1134,14 +1145,14 @@ build_fast_tlb_refill_handler (u32 **p, struct uasm_label **l,
 		}
 	} else {
 		if (pgd_reg != -1)
-			UASM_i_MFC0(p, ptr, 31, pgd_reg);
+			UASM_i_MFC0(p, ptr, c0_kscratch(), pgd_reg);
 		else
 			UASM_i_MFC0(p, ptr, C0_CONTEXT);
 
 		UASM_i_MFC0(p, tmp, C0_BADVADDR);
 
-		if (c0_scratch >= 0)
-			UASM_i_MTC0(p, scratch, 31, c0_scratch);
+		if (c0_scratch_reg >= 0)
+			UASM_i_MTC0(p, scratch, c0_kscratch(), c0_scratch_reg);
 		else
 			UASM_i_SW(p, scratch, scratchpad_offset(0), 0);
 
@@ -1246,8 +1257,8 @@ build_fast_tlb_refill_handler (u32 **p, struct uasm_label **l,
 	}
 	UASM_i_MTC0(p, odd, C0_ENTRYLO1); /* load it */
 
-	if (c0_scratch >= 0) {
-		UASM_i_MFC0(p, scratch, 31, c0_scratch);
+	if (c0_scratch_reg >= 0) {
+		UASM_i_MFC0(p, scratch, c0_kscratch(), c0_scratch_reg);
 		build_tlb_write_entry(p, l, r, tlb_random);
 		uasm_l_leave(l, *p);
 		rv.restore_scratch = 1;
@@ -1494,7 +1505,7 @@ static void __cpuinit build_r4000_setup_pgd(void)
 	} else {
 		/* PGD in c0_KScratch */
 		uasm_i_jr(&p, 31);
-		UASM_i_MTC0(&p, a0, 31, pgd_reg);
+		UASM_i_MTC0(&p, a0, c0_kscratch(), pgd_reg);
 	}
 	if (p - tlbmiss_handler_setup_pgd > ARRAY_SIZE(tlbmiss_handler_setup_pgd))
 		panic("tlbmiss_handler_setup_pgd space exceeded");
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 2/3] MIPS: mm: Use scratch for PGD when !CONFIG_MIPS_PGD_C0_CONTEXT
  2013-03-20 16:27 [PATCH v2 0/3] Use scratch registers on XLR/XLS/XLP Jayachandran C
  2013-03-20 16:27 ` [PATCH 1/3] MIPS: Allow platform specific scratch registers Jayachandran C
@ 2013-03-20 16:27 ` Jayachandran C
  2013-03-20 16:45   ` David Daney
  2013-03-20 16:27 ` [PATCH 3/3] MIPS: Move definition of SMP processor id register to header file Jayachandran C
  2 siblings, 1 reply; 8+ messages in thread
From: Jayachandran C @ 2013-03-20 16:27 UTC (permalink / raw)
  To: linux-mips, ralf; +Cc: Jayachandran C

Allow usage of scratch register for current pgd even when
MIPS_PGD_C0_CONTEXT is not configured.  MIPS_PGD_C0_CONTEXT is set
for 64r2 platforms to indicate availability of Xcontext for saving
cpuid, thus freeing Context which was used for cpuid to be used for
saving PGD. This option was also tied to using a scratch register for
storing PGD.

This commit will allow usage of scratch register to store the current
pgd if one can be allocated for the platform, even when
MIPS_PGD_C0_CONTEXT is not set. The cpu id will be kept in the CP0
Context register in this case.

The code to store the current pgd for the TLB miss handler is now
generated in all cases. When scratch register is available, the PGD
is also stored in the scratch register.

Signed-off-by: Jayachandran C <jchandra@broadcom.com>
---
 arch/mips/include/asm/mmu_context.h |    8 +-
 arch/mips/mm/tlbex.c                |  142 ++++++++++++++++++++++-------------
 2 files changed, 92 insertions(+), 58 deletions(-)

diff --git a/arch/mips/include/asm/mmu_context.h b/arch/mips/include/asm/mmu_context.h
index e81d719..39e87ee 100644
--- a/arch/mips/include/asm/mmu_context.h
+++ b/arch/mips/include/asm/mmu_context.h
@@ -24,13 +24,12 @@
 #endif /* SMTC */
 #include <asm-generic/mm_hooks.h>
 
-#ifdef CONFIG_MIPS_PGD_C0_CONTEXT
+extern void tlbmiss_handler_setup_pgd(unsigned long pgd);
 
 #define TLBMISS_HANDLER_SETUP_PGD(pgd)				\
 	tlbmiss_handler_setup_pgd((unsigned long)(pgd))
 
-extern void tlbmiss_handler_setup_pgd(unsigned long pgd);
-
+#ifdef CONFIG_MIPS_PGD_C0_CONTEXT
 #define TLBMISS_HANDLER_SETUP()						\
 	do {								\
 		TLBMISS_HANDLER_SETUP_PGD(swapper_pg_dir);		\
@@ -46,9 +45,6 @@ extern void tlbmiss_handler_setup_pgd(unsigned long pgd);
  */
 extern unsigned long pgd_current[];
 
-#define TLBMISS_HANDLER_SETUP_PGD(pgd) \
-	pgd_current[smp_processor_id()] = (unsigned long)(pgd)
-
 #ifdef CONFIG_32BIT
 #define TLBMISS_HANDLER_SETUP()						\
 	write_c0_context((unsigned long) smp_processor_id() << 25);	\
diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c
index ca470c6..ede46d7 100644
--- a/arch/mips/mm/tlbex.c
+++ b/arch/mips/mm/tlbex.c
@@ -829,11 +829,11 @@ build_get_pmde64(u32 **p, struct uasm_label **l, struct uasm_reloc **r,
 	}
 	/* No uasm_i_nop needed here, since the next insn doesn't touch TMP. */
 
-#ifdef CONFIG_MIPS_PGD_C0_CONTEXT
 	if (pgd_reg != -1) {
 		/* pgd is in pgd_reg */
 		UASM_i_MFC0(p, ptr, c0_kscratch(), pgd_reg);
 	} else {
+#ifdef CONFIG_MIPS_PGD_C0_CONTEXT
 		/*
 		 * &pgd << 11 stored in CONTEXT [23..63].
 		 */
@@ -845,30 +845,30 @@ build_get_pmde64(u32 **p, struct uasm_label **l, struct uasm_reloc **r,
 		/* 1 0	1 0 1  << 6  xkphys cached */
 		uasm_i_ori(p, ptr, ptr, 0x540);
 		uasm_i_drotr(p, ptr, ptr, 11);
-	}
 #elif defined(CONFIG_SMP)
-# ifdef	 CONFIG_MIPS_MT_SMTC
-	/*
-	 * SMTC uses TCBind value as "CPU" index
-	 */
-	uasm_i_mfc0(p, ptr, C0_TCBIND);
-	uasm_i_dsrl_safe(p, ptr, ptr, 19);
+# ifdef CONFIG_MIPS_MT_SMTC
+		/*
+		 * SMTC uses TCBind value as "CPU" index
+		 */
+		uasm_i_mfc0(p, ptr, C0_TCBIND);
+		uasm_i_dsrl_safe(p, ptr, ptr, 19);
 # else
-	/*
-	 * 64 bit SMP running in XKPHYS has smp_processor_id() << 3
-	 * stored in CONTEXT.
-	 */
-	uasm_i_dmfc0(p, ptr, C0_CONTEXT);
-	uasm_i_dsrl_safe(p, ptr, ptr, 23);
+		/*
+		 * 64 bit SMP running in XKPHYS has smp_processor_id() << 3
+		 * stored in CONTEXT.
+		 */
+		uasm_i_dmfc0(p, ptr, C0_CONTEXT);
+		uasm_i_dsrl_safe(p, ptr, ptr, 23);
 # endif
-	UASM_i_LA_mostly(p, tmp, pgdc);
-	uasm_i_daddu(p, ptr, ptr, tmp);
-	uasm_i_dmfc0(p, tmp, C0_BADVADDR);
-	uasm_i_ld(p, ptr, uasm_rel_lo(pgdc), ptr);
+		UASM_i_LA_mostly(p, tmp, pgdc);
+		uasm_i_daddu(p, ptr, ptr, tmp);
+		uasm_i_dmfc0(p, tmp, C0_BADVADDR);
+		uasm_i_ld(p, ptr, uasm_rel_lo(pgdc), ptr);
 #else
-	UASM_i_LA_mostly(p, ptr, pgdc);
-	uasm_i_ld(p, ptr, uasm_rel_lo(pgdc), ptr);
+		UASM_i_LA_mostly(p, ptr, pgdc);
+		uasm_i_ld(p, ptr, uasm_rel_lo(pgdc), ptr);
 #endif
+	}
 
 	uasm_l_vmalloc_done(l, *p);
 
@@ -963,31 +963,37 @@ build_get_pgd_vmalloc64(u32 **p, struct uasm_label **l, struct uasm_reloc **r,
 static void __cpuinit __maybe_unused
 build_get_pgde32(u32 **p, unsigned int tmp, unsigned int ptr)
 {
-	long pgdc = (long)pgd_current;
+	if (pgd_reg != -1) {
+		/* pgd is in pgd_reg */
+		uasm_i_mfc0(p, ptr, c0_kscratch(), pgd_reg);
+		uasm_i_mfc0(p, tmp, C0_BADVADDR); /* get faulting address */
+	} else {
+		long pgdc = (long)pgd_current;
 
-	/* 32 bit SMP has smp_processor_id() stored in CONTEXT. */
+		/* 32 bit SMP has smp_processor_id() stored in CONTEXT. */
 #ifdef CONFIG_SMP
-#ifdef	CONFIG_MIPS_MT_SMTC
-	/*
-	 * SMTC uses TCBind value as "CPU" index
-	 */
-	uasm_i_mfc0(p, ptr, C0_TCBIND);
-	UASM_i_LA_mostly(p, tmp, pgdc);
-	uasm_i_srl(p, ptr, ptr, 19);
-#else
-	/*
-	 * smp_processor_id() << 3 is stored in CONTEXT.
-	 */
-	uasm_i_mfc0(p, ptr, C0_CONTEXT);
-	UASM_i_LA_mostly(p, tmp, pgdc);
-	uasm_i_srl(p, ptr, ptr, 23);
-#endif
-	uasm_i_addu(p, ptr, tmp, ptr);
+# ifdef CONFIG_MIPS_MT_SMTC
+		/*
+		 * SMTC uses TCBind value as "CPU" index
+		 */
+		uasm_i_mfc0(p, ptr, C0_TCBIND);
+		UASM_i_LA_mostly(p, tmp, pgdc);
+		uasm_i_srl(p, ptr, ptr, 19);
+# else
+		/*
+		 * smp_processor_id() << 3 is stored in CONTEXT.
+		 */
+		uasm_i_mfc0(p, ptr, C0_CONTEXT);
+		UASM_i_LA_mostly(p, tmp, pgdc);
+		uasm_i_srl(p, ptr, ptr, 23);
+# endif
+		uasm_i_addu(p, ptr, tmp, ptr);
 #else
-	UASM_i_LA_mostly(p, ptr, pgdc);
+		UASM_i_LA_mostly(p, ptr, pgdc);
 #endif
-	uasm_i_mfc0(p, tmp, C0_BADVADDR); /* get faulting address */
-	uasm_i_lw(p, ptr, uasm_rel_lo(pgdc), ptr);
+		uasm_i_mfc0(p, tmp, C0_BADVADDR); /* get faulting address */
+		uasm_i_lw(p, ptr, uasm_rel_lo(pgdc), ptr);
+	}
 	uasm_i_srl(p, tmp, tmp, PGDIR_SHIFT); /* get pgd only bits */
 	uasm_i_sll(p, tmp, tmp, PGD_T_LOG2);
 	uasm_i_addu(p, ptr, ptr, tmp); /* add in pgd offset */
@@ -1468,16 +1474,17 @@ static void __cpuinit build_r4000_tlb_refill_handler(void)
 u32 handle_tlbl[FASTPATH_SIZE] __cacheline_aligned;
 u32 handle_tlbs[FASTPATH_SIZE] __cacheline_aligned;
 u32 handle_tlbm[FASTPATH_SIZE] __cacheline_aligned;
-#ifdef CONFIG_MIPS_PGD_C0_CONTEXT
 u32 tlbmiss_handler_setup_pgd[16] __cacheline_aligned;
 
-static void __cpuinit build_r4000_setup_pgd(void)
+static void __cpuinit build_setup_pgd(void)
 {
 	const int a0 = 4;
-	const int a1 = 5;
+	const int __maybe_unused a1 = 5;
+	const int __maybe_unused a2 = 6;
 	u32 *p = tlbmiss_handler_setup_pgd;
-	struct uasm_label *l = labels;
-	struct uasm_reloc *r = relocs;
+#ifndef CONFIG_MIPS_PGD_C0_CONTEXT
+	long pgdc = (long)pgd_current;
+#endif
 
 	memset(tlbmiss_handler_setup_pgd, 0, sizeof(tlbmiss_handler_setup_pgd));
 	memset(labels, 0, sizeof(labels));
@@ -1485,7 +1492,11 @@ static void __cpuinit build_r4000_setup_pgd(void)
 
 	pgd_reg = allocate_kscratch();
 
+#ifdef CONFIG_MIPS_PGD_C0_CONTEXT
 	if (pgd_reg == -1) {
+		struct uasm_label *l = labels;
+		struct uasm_reloc *r = relocs;
+
 		/* PGD << 11 in c0_Context */
 		/*
 		 * If it is a ckseg0 address, convert to a physical
@@ -1507,6 +1518,37 @@ static void __cpuinit build_r4000_setup_pgd(void)
 		uasm_i_jr(&p, 31);
 		UASM_i_MTC0(&p, a0, c0_kscratch(), pgd_reg);
 	}
+#else
+	/* Save PGD to pgd_current[smp_processor_id()] */
+#if defined(CONFIG_SMP)
+# ifdef CONFIG_MIPS_MT_SMTC
+	/*
+	 * SMTC uses TCBind value as "CPU" index
+	 */
+	uasm_i_mfc0(&p, a1, C0_TCBIND);
+	uasm_i_dsrl_safe(&p, a1, a1, 19);
+# else
+	/*
+	 * smp_processor_id() is in CONTEXT
+	 */
+	UASM_i_MFC0(&p, a1, C0_CONTEXT);
+	uasm_i_dsrl_safe(&p, a1, a1, 23);
+# endif
+	UASM_i_LA_mostly(&p, a2, pgdc);
+	UASM_i_ADDU(&p, a2, a2, a1);
+	UASM_i_SW(&p, a0, uasm_rel_lo(pgdc), a2);
+#else
+	UASM_i_LA_mostly(&p, a2, pgdc);
+	UASM_i_SW(&p, a0, uasm_rel_lo(pgdc), a2);
+#endif /* SMP */
+	uasm_i_jr(&p, 31);
+
+	/* if pgd_reg is allocated, save PGD also to scratch register */
+	if (pgd_reg != -1)
+		UASM_i_MTC0(&p, a0, c0_kscratch(), pgd_reg);
+	else
+		uasm_i_nop(&p);
+#endif
 	if (p - tlbmiss_handler_setup_pgd > ARRAY_SIZE(tlbmiss_handler_setup_pgd))
 		panic("tlbmiss_handler_setup_pgd space exceeded");
 	uasm_resolve_relocs(relocs, labels);
@@ -1517,7 +1559,6 @@ static void __cpuinit build_r4000_setup_pgd(void)
 		     tlbmiss_handler_setup_pgd,
 		     ARRAY_SIZE(tlbmiss_handler_setup_pgd));
 }
-#endif
 
 static void __cpuinit
 iPTE_LW(u32 **p, unsigned int pte, unsigned int ptr)
@@ -2175,6 +2216,7 @@ void __cpuinit build_tlb_refill_handler(void)
 #ifndef CONFIG_MIPS_PGD_C0_CONTEXT
 		build_r3000_tlb_refill_handler();
 		if (!run_once) {
+			build_setup_pgd();
 			build_r3000_tlb_load_handler();
 			build_r3000_tlb_store_handler();
 			build_r3000_tlb_modify_handler();
@@ -2197,9 +2239,7 @@ void __cpuinit build_tlb_refill_handler(void)
 	default:
 		if (!run_once) {
 			scratch_reg = allocate_kscratch();
-#ifdef CONFIG_MIPS_PGD_C0_CONTEXT
-			build_r4000_setup_pgd();
-#endif
+			build_setup_pgd();
 			build_r4000_tlb_load_handler();
 			build_r4000_tlb_store_handler();
 			build_r4000_tlb_modify_handler();
@@ -2217,8 +2257,6 @@ void __cpuinit flush_tlb_handlers(void)
 			   (unsigned long)handle_tlbs + sizeof(handle_tlbs));
 	local_flush_icache_range((unsigned long)handle_tlbm,
 			   (unsigned long)handle_tlbm + sizeof(handle_tlbm));
-#ifdef CONFIG_MIPS_PGD_C0_CONTEXT
 	local_flush_icache_range((unsigned long)tlbmiss_handler_setup_pgd,
 			   (unsigned long)tlbmiss_handler_setup_pgd + sizeof(handle_tlbm));
-#endif
 }
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 3/3] MIPS: Move definition of SMP processor id register to header file
  2013-03-20 16:27 [PATCH v2 0/3] Use scratch registers on XLR/XLS/XLP Jayachandran C
  2013-03-20 16:27 ` [PATCH 1/3] MIPS: Allow platform specific scratch registers Jayachandran C
  2013-03-20 16:27 ` [PATCH 2/3] MIPS: mm: Use scratch for PGD when !CONFIG_MIPS_PGD_C0_CONTEXT Jayachandran C
@ 2013-03-20 16:27 ` Jayachandran C
  2 siblings, 0 replies; 8+ messages in thread
From: Jayachandran C @ 2013-03-20 16:27 UTC (permalink / raw)
  To: linux-mips, ralf; +Cc: Jayachandran C

The definition of the CP0 register used to save the smp processor
id is repicated in many files, move them all to thread_info.h.

Signed-off-by: Jayachandran C <jchandra@broadcom.com>
---
 arch/mips/include/asm/mmu_context.h |   18 +++------
 arch/mips/include/asm/stackframe.h  |   26 ++++--------
 arch/mips/include/asm/thread_info.h |   30 +++++++++++++-
 arch/mips/mm/tlbex.c                |   75 +++++------------------------------
 4 files changed, 52 insertions(+), 97 deletions(-)

diff --git a/arch/mips/include/asm/mmu_context.h b/arch/mips/include/asm/mmu_context.h
index 39e87ee..514a7fd 100644
--- a/arch/mips/include/asm/mmu_context.h
+++ b/arch/mips/include/asm/mmu_context.h
@@ -26,17 +26,18 @@
 
 extern void tlbmiss_handler_setup_pgd(unsigned long pgd);
 
-#define TLBMISS_HANDLER_SETUP_PGD(pgd)				\
+#define TLBMISS_HANDLER_SETUP_PGD(pgd)					\
 	tlbmiss_handler_setup_pgd((unsigned long)(pgd))
 
 #ifdef CONFIG_MIPS_PGD_C0_CONTEXT
 #define TLBMISS_HANDLER_SETUP()						\
 	do {								\
 		TLBMISS_HANDLER_SETUP_PGD(swapper_pg_dir);		\
-		write_c0_xcontext((unsigned long) smp_processor_id() << 51); \
+		write_c0_xcontext((unsigned long) smp_processor_id() <<	\
+						SMP_CPUID_REGSHIFT);	\
 	} while (0)
 
-#else /* CONFIG_MIPS_PGD_C0_CONTEXT: using  pgd_current*/
+#else /* !CONFIG_MIPS_PGD_C0_CONTEXT: using  pgd_current*/
 
 /*
  * For the fast tlb miss handlers, we keep a per cpu array of pointers
@@ -45,18 +46,11 @@ extern void tlbmiss_handler_setup_pgd(unsigned long pgd);
  */
 extern unsigned long pgd_current[];
 
-#ifdef CONFIG_32BIT
 #define TLBMISS_HANDLER_SETUP()						\
-	write_c0_context((unsigned long) smp_processor_id() << 25);	\
+	write_c0_context((unsigned long) smp_processor_id() <<		\
+						SMP_CPUID_REGSHIFT);	\
 	back_to_back_c0_hazard();					\
 	TLBMISS_HANDLER_SETUP_PGD(swapper_pg_dir)
-#endif
-#ifdef CONFIG_64BIT
-#define TLBMISS_HANDLER_SETUP()						\
-	write_c0_context((unsigned long) smp_processor_id() << 26);	\
-	back_to_back_c0_hazard();					\
-	TLBMISS_HANDLER_SETUP_PGD(swapper_pg_dir)
-#endif
 #endif /* CONFIG_MIPS_PGD_C0_CONTEXT*/
 #if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX)
 
diff --git a/arch/mips/include/asm/stackframe.h b/arch/mips/include/asm/stackframe.h
index c993840..690a71c 100644
--- a/arch/mips/include/asm/stackframe.h
+++ b/arch/mips/include/asm/stackframe.h
@@ -17,6 +17,7 @@
 #include <asm/asmmacro.h>
 #include <asm/mipsregs.h>
 #include <asm/asm-offsets.h>
+#include <asm/thread_info.h>
 
 /*
  * For SMTC kernel, global IE should be left set, and interrupts
@@ -85,21 +86,8 @@
 		.endm
 
 #ifdef CONFIG_SMP
-#ifdef CONFIG_MIPS_MT_SMTC
-#define PTEBASE_SHIFT	19	/* TCBIND */
-#define CPU_ID_REG CP0_TCBIND
-#define CPU_ID_MFC0 mfc0
-#elif defined(CONFIG_MIPS_PGD_C0_CONTEXT)
-#define PTEBASE_SHIFT	48	/* XCONTEXT */
-#define CPU_ID_REG CP0_XCONTEXT
-#define CPU_ID_MFC0 MFC0
-#else
-#define PTEBASE_SHIFT	23	/* CONTEXT */
-#define CPU_ID_REG CP0_CONTEXT
-#define CPU_ID_MFC0 MFC0
-#endif
 		.macro	get_saved_sp	/* SMP variation */
-		CPU_ID_MFC0	k0, CPU_ID_REG
+		ASM_CPUID_MFC0	k0, $SMP_CPUID_REG
 #if defined(CONFIG_32BIT) || defined(KBUILD_64BIT_SYM32)
 		lui	k1, %hi(kernelsp)
 #else
@@ -109,17 +97,17 @@
 		daddiu	k1, %hi(kernelsp)
 		dsll	k1, 16
 #endif
-		LONG_SRL	k0, PTEBASE_SHIFT
+		LONG_SRL	k0, SMP_CPUID_PTRSHIFT
 		LONG_ADDU	k1, k0
 		LONG_L	k1, %lo(kernelsp)(k1)
 		.endm
 
 		.macro	set_saved_sp stackp temp temp2
-		CPU_ID_MFC0	\temp, CPU_ID_REG
-		LONG_SRL	\temp, PTEBASE_SHIFT
+		ASM_CPUID_MFC0	\temp, $SMP_CPUID_REG
+		LONG_SRL	\temp, SMP_CPUID_PTRSHIFT
 		LONG_S	\stackp, kernelsp(\temp)
 		.endm
-#else
+#else /* !CONFIG_SMP */
 		.macro	get_saved_sp	/* Uniprocessor variation */
 #ifdef CONFIG_CPU_JUMP_WORKAROUNDS
 		/*
@@ -139,7 +127,7 @@
 1:		move	ra, k0
 		li	k0, 3
 		mtc0	k0, $22
-#endif /* CONFIG_CPU_LOONGSON2F */
+#endif /* CONFIG_CPU_JUMP_WORKAROUNDS */
 #if defined(CONFIG_32BIT) || defined(KBUILD_64BIT_SYM32)
 		lui	k1, %hi(kernelsp)
 #else
diff --git a/arch/mips/include/asm/thread_info.h b/arch/mips/include/asm/thread_info.h
index 178f792..e373626 100644
--- a/arch/mips/include/asm/thread_info.h
+++ b/arch/mips/include/asm/thread_info.h
@@ -136,6 +136,34 @@ register struct thread_info *__current_thread_info __asm__("$28");
 /* work to do on any return to u-space */
 #define _TIF_ALLWORK_MASK	(_TIF_WORK_MASK | _TIF_WORK_SYSCALL_EXIT)
 
-#endif /* __KERNEL__ */
+/*
+ * We stash processor id into a COP0 register to retrieve it fast
+ * at kernel exception entry. The register and shift used for this.
+ */
+#if defined(CONFIG_MIPS_MT_SMTC)
+#define SMP_CPUID_REG		2, 2	/* TCBIND */
+#define SMP_CPUID_PTRSHIFT	19
+#elif defined(CONFIG_MIPS_PGD_C0_CONTEXT)
+#define SMP_CPUID_REG		20, 0	/* XCONTEXT */
+#define SMP_CPUID_PTRSHIFT	48
+#else
+#define SMP_CPUID_REG		4, 0	/* CONTEXT */
+#define SMP_CPUID_PTRSHIFT	23
+#endif
 
+#ifdef CONFIG_64BIT
+#define SMP_CPUID_REGSHIFT	(SMP_CPUID_PTRSHIFT + 3)
+#else
+#define SMP_CPUID_REGSHIFT	(SMP_CPUID_PTRSHIFT + 2)
+#endif
+
+#ifdef CONFIG_MIPS_MT_SMTC
+#define ASM_CPUID_MFC0		mfc0
+#define UASM_i_CPUID_MFC0	uasm_i_mfc0
+#else
+#define ASM_CPUID_MFC0		MFC0
+#define UASM_i_CPUID_MFC0	UASM_i_MFC0
+#endif
+
+#endif /* __KERNEL__ */
 #endif /* _ASM_THREAD_INFO_H */
diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c
index ede46d7..432328b 100644
--- a/arch/mips/mm/tlbex.c
+++ b/arch/mips/mm/tlbex.c
@@ -345,10 +345,6 @@ static struct work_registers __cpuinit build_get_work_registers(u32 **p)
 {
 	struct work_registers r;
 
-	int smp_processor_id_reg;
-	int smp_processor_id_sel;
-	int smp_processor_id_shift;
-
 	if (scratch_reg > 0) {
 		/* Save in CPU local C0_KScratch? */
 		UASM_i_MTC0(p, 1, c0_kscratch(), scratch_reg);
@@ -359,25 +355,9 @@ static struct work_registers __cpuinit build_get_work_registers(u32 **p)
 	}
 
 	if (num_possible_cpus() > 1) {
-#ifdef CONFIG_MIPS_PGD_C0_CONTEXT
-		smp_processor_id_shift = 51;
-		smp_processor_id_reg = 20; /* XContext */
-		smp_processor_id_sel = 0;
-#else
-# ifdef CONFIG_32BIT
-		smp_processor_id_shift = 25;
-		smp_processor_id_reg = 4; /* Context */
-		smp_processor_id_sel = 0;
-# endif
-# ifdef CONFIG_64BIT
-		smp_processor_id_shift = 26;
-		smp_processor_id_reg = 4; /* Context */
-		smp_processor_id_sel = 0;
-# endif
-#endif
 		/* Get smp_processor_id */
-		UASM_i_MFC0(p, K0, smp_processor_id_reg, smp_processor_id_sel);
-		UASM_i_SRL_SAFE(p, K0, K0, smp_processor_id_shift);
+		UASM_i_CPUID_MFC0(p, K0, SMP_CPUID_REG);
+		UASM_i_SRL_SAFE(p, K0, K0, SMP_CPUID_REGSHIFT);
 
 		/* handler_reg_save index in K0 */
 		UASM_i_SLL(p, K0, K0, ilog2(sizeof(struct tlb_reg_save)));
@@ -833,7 +813,7 @@ build_get_pmde64(u32 **p, struct uasm_label **l, struct uasm_reloc **r,
 		/* pgd is in pgd_reg */
 		UASM_i_MFC0(p, ptr, c0_kscratch(), pgd_reg);
 	} else {
-#ifdef CONFIG_MIPS_PGD_C0_CONTEXT
+#if defined(CONFIG_MIPS_PGD_C0_CONTEXT)
 		/*
 		 * &pgd << 11 stored in CONTEXT [23..63].
 		 */
@@ -846,20 +826,8 @@ build_get_pmde64(u32 **p, struct uasm_label **l, struct uasm_reloc **r,
 		uasm_i_ori(p, ptr, ptr, 0x540);
 		uasm_i_drotr(p, ptr, ptr, 11);
 #elif defined(CONFIG_SMP)
-# ifdef CONFIG_MIPS_MT_SMTC
-		/*
-		 * SMTC uses TCBind value as "CPU" index
-		 */
-		uasm_i_mfc0(p, ptr, C0_TCBIND);
-		uasm_i_dsrl_safe(p, ptr, ptr, 19);
-# else
-		/*
-		 * 64 bit SMP running in XKPHYS has smp_processor_id() << 3
-		 * stored in CONTEXT.
-		 */
-		uasm_i_dmfc0(p, ptr, C0_CONTEXT);
-		uasm_i_dsrl_safe(p, ptr, ptr, 23);
-# endif
+		UASM_i_CPUID_MFC0(p, ptr, SMP_CPUID_REG);
+		uasm_i_dsrl_safe(p, ptr, ptr, SMP_CPUID_PTRSHIFT);
 		UASM_i_LA_mostly(p, tmp, pgdc);
 		uasm_i_daddu(p, ptr, ptr, tmp);
 		uasm_i_dmfc0(p, tmp, C0_BADVADDR);
@@ -972,21 +940,9 @@ build_get_pgde32(u32 **p, unsigned int tmp, unsigned int ptr)
 
 		/* 32 bit SMP has smp_processor_id() stored in CONTEXT. */
 #ifdef CONFIG_SMP
-# ifdef CONFIG_MIPS_MT_SMTC
-		/*
-		 * SMTC uses TCBind value as "CPU" index
-		 */
-		uasm_i_mfc0(p, ptr, C0_TCBIND);
+		uasm_i_mfc0(p, ptr, SMP_CPUID_REG);
 		UASM_i_LA_mostly(p, tmp, pgdc);
-		uasm_i_srl(p, ptr, ptr, 19);
-# else
-		/*
-		 * smp_processor_id() << 3 is stored in CONTEXT.
-		 */
-		uasm_i_mfc0(p, ptr, C0_CONTEXT);
-		UASM_i_LA_mostly(p, tmp, pgdc);
-		uasm_i_srl(p, ptr, ptr, 23);
-# endif
+		uasm_i_srl(p, ptr, ptr, SMP_CPUID_PTRSHIFT);
 		uasm_i_addu(p, ptr, tmp, ptr);
 #else
 		UASM_i_LA_mostly(p, ptr, pgdc);
@@ -1519,21 +1475,10 @@ static void __cpuinit build_setup_pgd(void)
 		UASM_i_MTC0(&p, a0, c0_kscratch(), pgd_reg);
 	}
 #else
+#ifdef CONFIG_SMP
 	/* Save PGD to pgd_current[smp_processor_id()] */
-#if defined(CONFIG_SMP)
-# ifdef CONFIG_MIPS_MT_SMTC
-	/*
-	 * SMTC uses TCBind value as "CPU" index
-	 */
-	uasm_i_mfc0(&p, a1, C0_TCBIND);
-	uasm_i_dsrl_safe(&p, a1, a1, 19);
-# else
-	/*
-	 * smp_processor_id() is in CONTEXT
-	 */
-	UASM_i_MFC0(&p, a1, C0_CONTEXT);
-	uasm_i_dsrl_safe(&p, a1, a1, 23);
-# endif
+	UASM_i_CPUID_MFC0(&p, a1, SMP_CPUID_REG);
+	uasm_i_dsrl_safe(&p, a1, a1, SMP_CPUID_PTRSHIFT);
 	UASM_i_LA_mostly(&p, a2, pgdc);
 	UASM_i_ADDU(&p, a2, a2, a1);
 	UASM_i_SW(&p, a0, uasm_rel_lo(pgdc), a2);
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [PATCH 2/3] MIPS: mm: Use scratch for PGD when !CONFIG_MIPS_PGD_C0_CONTEXT
  2013-03-20 16:27 ` [PATCH 2/3] MIPS: mm: Use scratch for PGD when !CONFIG_MIPS_PGD_C0_CONTEXT Jayachandran C
@ 2013-03-20 16:45   ` David Daney
  2013-03-20 18:01     ` Jayachandran C.
  0 siblings, 1 reply; 8+ messages in thread
From: David Daney @ 2013-03-20 16:45 UTC (permalink / raw)
  To: Jayachandran C; +Cc: linux-mips, ralf

On 03/20/2013 09:27 AM, Jayachandran C wrote:
> Allow usage of scratch register for current pgd even when
> MIPS_PGD_C0_CONTEXT is not configured.  MIPS_PGD_C0_CONTEXT is set
> for 64r2 platforms to indicate availability of Xcontext for saving
> cpuid, thus freeing Context which was used for cpuid to be used for
> saving PGD. This option was also tied to using a scratch register for
> storing PGD.
>
> This commit will allow usage of scratch register to store the current
> pgd if one can be allocated for the platform, even when
> MIPS_PGD_C0_CONTEXT is not set. The cpu id will be kept in the CP0
> Context register in this case.


The point of MIPS_PGD_C0_CONTEXT is really to indicate that the PGD 
pointer is stored in a register (or portion thereof) and that setting 
the PGD is done by calling into uasm generated code.

Perhaps we should rename this Kconfig vairable so that its name 
indicates its function, or remove it altogether if possible, and machine 
generate the setting of the PGD pointer even when it is stored in the 
array in memory.


>
> The code to store the current pgd for the TLB miss handler is now
> generated in all cases. When scratch register is available, the PGD
> is also stored in the scratch register.
>
> Signed-off-by: Jayachandran C <jchandra@broadcom.com>
> ---
>   arch/mips/include/asm/mmu_context.h |    8 +-
>   arch/mips/mm/tlbex.c                |  142 ++++++++++++++++++++++-------------
>   2 files changed, 92 insertions(+), 58 deletions(-)
>
> diff --git a/arch/mips/include/asm/mmu_context.h b/arch/mips/include/asm/mmu_context.h
> index e81d719..39e87ee 100644
> --- a/arch/mips/include/asm/mmu_context.h
> +++ b/arch/mips/include/asm/mmu_context.h
> @@ -24,13 +24,12 @@
>   #endif /* SMTC */
>   #include <asm-generic/mm_hooks.h>
>
> -#ifdef CONFIG_MIPS_PGD_C0_CONTEXT
> +extern void tlbmiss_handler_setup_pgd(unsigned long pgd);
>
>   #define TLBMISS_HANDLER_SETUP_PGD(pgd)				\
>   	tlbmiss_handler_setup_pgd((unsigned long)(pgd))
>
> -extern void tlbmiss_handler_setup_pgd(unsigned long pgd);
> -
> +#ifdef CONFIG_MIPS_PGD_C0_CONTEXT
>   #define TLBMISS_HANDLER_SETUP()						\
>   	do {								\
>   		TLBMISS_HANDLER_SETUP_PGD(swapper_pg_dir);		\
> @@ -46,9 +45,6 @@ extern void tlbmiss_handler_setup_pgd(unsigned long pgd);
>    */
>   extern unsigned long pgd_current[];
>
> -#define TLBMISS_HANDLER_SETUP_PGD(pgd) \
> -	pgd_current[smp_processor_id()] = (unsigned long)(pgd)
> -
>   #ifdef CONFIG_32BIT
>   #define TLBMISS_HANDLER_SETUP()						\
>   	write_c0_context((unsigned long) smp_processor_id() << 25);	\
> diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c
> index ca470c6..ede46d7 100644
> --- a/arch/mips/mm/tlbex.c
> +++ b/arch/mips/mm/tlbex.c
> @@ -829,11 +829,11 @@ build_get_pmde64(u32 **p, struct uasm_label **l, struct uasm_reloc **r,
>   	}
>   	/* No uasm_i_nop needed here, since the next insn doesn't touch TMP. */
>
> -#ifdef CONFIG_MIPS_PGD_C0_CONTEXT
>   	if (pgd_reg != -1) {
>   		/* pgd is in pgd_reg */
>   		UASM_i_MFC0(p, ptr, c0_kscratch(), pgd_reg);
>   	} else {
> +#ifdef CONFIG_MIPS_PGD_C0_CONTEXT
>   		/*
>   		 * &pgd << 11 stored in CONTEXT [23..63].
>   		 */
> @@ -845,30 +845,30 @@ build_get_pmde64(u32 **p, struct uasm_label **l, struct uasm_reloc **r,
>   		/* 1 0	1 0 1  << 6  xkphys cached */
>   		uasm_i_ori(p, ptr, ptr, 0x540);
>   		uasm_i_drotr(p, ptr, ptr, 11);
> -	}
>   #elif defined(CONFIG_SMP)
> -# ifdef	 CONFIG_MIPS_MT_SMTC
> -	/*
> -	 * SMTC uses TCBind value as "CPU" index
> -	 */
> -	uasm_i_mfc0(p, ptr, C0_TCBIND);
> -	uasm_i_dsrl_safe(p, ptr, ptr, 19);
> +# ifdef CONFIG_MIPS_MT_SMTC
> +		/*
> +		 * SMTC uses TCBind value as "CPU" index
> +		 */
> +		uasm_i_mfc0(p, ptr, C0_TCBIND);
> +		uasm_i_dsrl_safe(p, ptr, ptr, 19);
>   # else
> -	/*
> -	 * 64 bit SMP running in XKPHYS has smp_processor_id() << 3
> -	 * stored in CONTEXT.
> -	 */
> -	uasm_i_dmfc0(p, ptr, C0_CONTEXT);
> -	uasm_i_dsrl_safe(p, ptr, ptr, 23);
> +		/*
> +		 * 64 bit SMP running in XKPHYS has smp_processor_id() << 3
> +		 * stored in CONTEXT.
> +		 */
> +		uasm_i_dmfc0(p, ptr, C0_CONTEXT);
> +		uasm_i_dsrl_safe(p, ptr, ptr, 23);
>   # endif
> -	UASM_i_LA_mostly(p, tmp, pgdc);
> -	uasm_i_daddu(p, ptr, ptr, tmp);
> -	uasm_i_dmfc0(p, tmp, C0_BADVADDR);
> -	uasm_i_ld(p, ptr, uasm_rel_lo(pgdc), ptr);
> +		UASM_i_LA_mostly(p, tmp, pgdc);
> +		uasm_i_daddu(p, ptr, ptr, tmp);
> +		uasm_i_dmfc0(p, tmp, C0_BADVADDR);
> +		uasm_i_ld(p, ptr, uasm_rel_lo(pgdc), ptr);
>   #else
> -	UASM_i_LA_mostly(p, ptr, pgdc);
> -	uasm_i_ld(p, ptr, uasm_rel_lo(pgdc), ptr);
> +		UASM_i_LA_mostly(p, ptr, pgdc);
> +		uasm_i_ld(p, ptr, uasm_rel_lo(pgdc), ptr);
>   #endif
> +	}
>
>   	uasm_l_vmalloc_done(l, *p);
>
> @@ -963,31 +963,37 @@ build_get_pgd_vmalloc64(u32 **p, struct uasm_label **l, struct uasm_reloc **r,
>   static void __cpuinit __maybe_unused
>   build_get_pgde32(u32 **p, unsigned int tmp, unsigned int ptr)
>   {
> -	long pgdc = (long)pgd_current;
> +	if (pgd_reg != -1) {
> +		/* pgd is in pgd_reg */
> +		uasm_i_mfc0(p, ptr, c0_kscratch(), pgd_reg);
> +		uasm_i_mfc0(p, tmp, C0_BADVADDR); /* get faulting address */
> +	} else {
> +		long pgdc = (long)pgd_current;
>
> -	/* 32 bit SMP has smp_processor_id() stored in CONTEXT. */
> +		/* 32 bit SMP has smp_processor_id() stored in CONTEXT. */
>   #ifdef CONFIG_SMP
> -#ifdef	CONFIG_MIPS_MT_SMTC
> -	/*
> -	 * SMTC uses TCBind value as "CPU" index
> -	 */
> -	uasm_i_mfc0(p, ptr, C0_TCBIND);
> -	UASM_i_LA_mostly(p, tmp, pgdc);
> -	uasm_i_srl(p, ptr, ptr, 19);
> -#else
> -	/*
> -	 * smp_processor_id() << 3 is stored in CONTEXT.
> -	 */
> -	uasm_i_mfc0(p, ptr, C0_CONTEXT);
> -	UASM_i_LA_mostly(p, tmp, pgdc);
> -	uasm_i_srl(p, ptr, ptr, 23);
> -#endif
> -	uasm_i_addu(p, ptr, tmp, ptr);
> +# ifdef CONFIG_MIPS_MT_SMTC
> +		/*
> +		 * SMTC uses TCBind value as "CPU" index
> +		 */
> +		uasm_i_mfc0(p, ptr, C0_TCBIND);
> +		UASM_i_LA_mostly(p, tmp, pgdc);
> +		uasm_i_srl(p, ptr, ptr, 19);
> +# else
> +		/*
> +		 * smp_processor_id() << 3 is stored in CONTEXT.
> +		 */
> +		uasm_i_mfc0(p, ptr, C0_CONTEXT);
> +		UASM_i_LA_mostly(p, tmp, pgdc);
> +		uasm_i_srl(p, ptr, ptr, 23);
> +# endif
> +		uasm_i_addu(p, ptr, tmp, ptr);
>   #else
> -	UASM_i_LA_mostly(p, ptr, pgdc);
> +		UASM_i_LA_mostly(p, ptr, pgdc);
>   #endif
> -	uasm_i_mfc0(p, tmp, C0_BADVADDR); /* get faulting address */
> -	uasm_i_lw(p, ptr, uasm_rel_lo(pgdc), ptr);
> +		uasm_i_mfc0(p, tmp, C0_BADVADDR); /* get faulting address */
> +		uasm_i_lw(p, ptr, uasm_rel_lo(pgdc), ptr);
> +	}
>   	uasm_i_srl(p, tmp, tmp, PGDIR_SHIFT); /* get pgd only bits */
>   	uasm_i_sll(p, tmp, tmp, PGD_T_LOG2);
>   	uasm_i_addu(p, ptr, ptr, tmp); /* add in pgd offset */
> @@ -1468,16 +1474,17 @@ static void __cpuinit build_r4000_tlb_refill_handler(void)
>   u32 handle_tlbl[FASTPATH_SIZE] __cacheline_aligned;
>   u32 handle_tlbs[FASTPATH_SIZE] __cacheline_aligned;
>   u32 handle_tlbm[FASTPATH_SIZE] __cacheline_aligned;
> -#ifdef CONFIG_MIPS_PGD_C0_CONTEXT
>   u32 tlbmiss_handler_setup_pgd[16] __cacheline_aligned;
>
> -static void __cpuinit build_r4000_setup_pgd(void)
> +static void __cpuinit build_setup_pgd(void)
>   {
>   	const int a0 = 4;
> -	const int a1 = 5;
> +	const int __maybe_unused a1 = 5;
> +	const int __maybe_unused a2 = 6;
>   	u32 *p = tlbmiss_handler_setup_pgd;
> -	struct uasm_label *l = labels;
> -	struct uasm_reloc *r = relocs;
> +#ifndef CONFIG_MIPS_PGD_C0_CONTEXT
> +	long pgdc = (long)pgd_current;
> +#endif
>
>   	memset(tlbmiss_handler_setup_pgd, 0, sizeof(tlbmiss_handler_setup_pgd));
>   	memset(labels, 0, sizeof(labels));
> @@ -1485,7 +1492,11 @@ static void __cpuinit build_r4000_setup_pgd(void)
>
>   	pgd_reg = allocate_kscratch();
>
> +#ifdef CONFIG_MIPS_PGD_C0_CONTEXT
>   	if (pgd_reg == -1) {
> +		struct uasm_label *l = labels;
> +		struct uasm_reloc *r = relocs;
> +
>   		/* PGD << 11 in c0_Context */
>   		/*
>   		 * If it is a ckseg0 address, convert to a physical
> @@ -1507,6 +1518,37 @@ static void __cpuinit build_r4000_setup_pgd(void)
>   		uasm_i_jr(&p, 31);
>   		UASM_i_MTC0(&p, a0, c0_kscratch(), pgd_reg);
>   	}
> +#else
> +	/* Save PGD to pgd_current[smp_processor_id()] */
> +#if defined(CONFIG_SMP)
> +# ifdef CONFIG_MIPS_MT_SMTC
> +	/*
> +	 * SMTC uses TCBind value as "CPU" index
> +	 */
> +	uasm_i_mfc0(&p, a1, C0_TCBIND);
> +	uasm_i_dsrl_safe(&p, a1, a1, 19);
> +# else
> +	/*
> +	 * smp_processor_id() is in CONTEXT
> +	 */
> +	UASM_i_MFC0(&p, a1, C0_CONTEXT);
> +	uasm_i_dsrl_safe(&p, a1, a1, 23);
> +# endif
> +	UASM_i_LA_mostly(&p, a2, pgdc);
> +	UASM_i_ADDU(&p, a2, a2, a1);
> +	UASM_i_SW(&p, a0, uasm_rel_lo(pgdc), a2);
> +#else
> +	UASM_i_LA_mostly(&p, a2, pgdc);
> +	UASM_i_SW(&p, a0, uasm_rel_lo(pgdc), a2);
> +#endif /* SMP */
> +	uasm_i_jr(&p, 31);
> +
> +	/* if pgd_reg is allocated, save PGD also to scratch register */
> +	if (pgd_reg != -1)
> +		UASM_i_MTC0(&p, a0, c0_kscratch(), pgd_reg);
> +	else
> +		uasm_i_nop(&p);
> +#endif
>   	if (p - tlbmiss_handler_setup_pgd > ARRAY_SIZE(tlbmiss_handler_setup_pgd))
>   		panic("tlbmiss_handler_setup_pgd space exceeded");
>   	uasm_resolve_relocs(relocs, labels);
> @@ -1517,7 +1559,6 @@ static void __cpuinit build_r4000_setup_pgd(void)
>   		     tlbmiss_handler_setup_pgd,
>   		     ARRAY_SIZE(tlbmiss_handler_setup_pgd));
>   }
> -#endif
>
>   static void __cpuinit
>   iPTE_LW(u32 **p, unsigned int pte, unsigned int ptr)
> @@ -2175,6 +2216,7 @@ void __cpuinit build_tlb_refill_handler(void)
>   #ifndef CONFIG_MIPS_PGD_C0_CONTEXT
>   		build_r3000_tlb_refill_handler();
>   		if (!run_once) {
> +			build_setup_pgd();
>   			build_r3000_tlb_load_handler();
>   			build_r3000_tlb_store_handler();
>   			build_r3000_tlb_modify_handler();
> @@ -2197,9 +2239,7 @@ void __cpuinit build_tlb_refill_handler(void)
>   	default:
>   		if (!run_once) {
>   			scratch_reg = allocate_kscratch();
> -#ifdef CONFIG_MIPS_PGD_C0_CONTEXT
> -			build_r4000_setup_pgd();
> -#endif
> +			build_setup_pgd();
>   			build_r4000_tlb_load_handler();
>   			build_r4000_tlb_store_handler();
>   			build_r4000_tlb_modify_handler();
> @@ -2217,8 +2257,6 @@ void __cpuinit flush_tlb_handlers(void)
>   			   (unsigned long)handle_tlbs + sizeof(handle_tlbs));
>   	local_flush_icache_range((unsigned long)handle_tlbm,
>   			   (unsigned long)handle_tlbm + sizeof(handle_tlbm));
> -#ifdef CONFIG_MIPS_PGD_C0_CONTEXT
>   	local_flush_icache_range((unsigned long)tlbmiss_handler_setup_pgd,
>   			   (unsigned long)tlbmiss_handler_setup_pgd + sizeof(handle_tlbm));
> -#endif
>   }
>

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH 2/3] MIPS: mm: Use scratch for PGD when !CONFIG_MIPS_PGD_C0_CONTEXT
  2013-03-20 16:45   ` David Daney
@ 2013-03-20 18:01     ` Jayachandran C.
  0 siblings, 0 replies; 8+ messages in thread
From: Jayachandran C. @ 2013-03-20 18:01 UTC (permalink / raw)
  To: David Daney; +Cc: linux-mips, ralf

On Wed, Mar 20, 2013 at 09:45:24AM -0700, David Daney wrote:
> On 03/20/2013 09:27 AM, Jayachandran C wrote:
> >Allow usage of scratch register for current pgd even when
> >MIPS_PGD_C0_CONTEXT is not configured.  MIPS_PGD_C0_CONTEXT is set
> >for 64r2 platforms to indicate availability of Xcontext for saving
> >cpuid, thus freeing Context which was used for cpuid to be used for
> >saving PGD. This option was also tied to using a scratch register for
> >storing PGD.
> >
> >This commit will allow usage of scratch register to store the current
> >pgd if one can be allocated for the platform, even when
> >MIPS_PGD_C0_CONTEXT is not set. The cpu id will be kept in the CP0
> >Context register in this case.
> 
> 
> The point of MIPS_PGD_C0_CONTEXT is really to indicate that the PGD
> pointer is stored in a register (or portion thereof) and that
> setting the PGD is done by calling into uasm generated code.
> 
> Perhaps we should rename this Kconfig vairable so that its name
> indicates its function, or remove it altogether if possible, and
> machine generate the setting of the PGD pointer even when it is
> stored in the array in memory.

Removing the MIPS_PGD_C0_CONTEXT Kconfig variable does not look feasible.
The processor id is used by get_saved_sp macro and it needs to know at
compile time whether the processor id is in Context or Xcontext. We could
call it something like MIPS_PROCESSOR_ID_IN_XCONTEXT (if it would not
affect too many config files).

The second part (generating code for setting PGD pointer in pgd_current) is
already in the patch. This generated code also saves PGD to the scratch
register if one was allocated.

JC.

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH 2/3] MIPS: mm: Use scratch for PGD when !CONFIG_MIPS_PGD_C0_CONTEXT
  2013-06-23 18:16 [PATCH 0/3] Use scratch registers when MIPS_PGD_C0_CONTEXT is not set Jayachandran C
@ 2013-06-23 18:16 ` Jayachandran C
  0 siblings, 0 replies; 8+ messages in thread
From: Jayachandran C @ 2013-06-23 18:16 UTC (permalink / raw)
  To: ralf, linux-mips; +Cc: Jayachandran C

Allow usage of scratch register for current pgd even when
MIPS_PGD_C0_CONTEXT is not configured. MIPS_PGD_C0_CONTEXT is set
for 64r2 platforms to indicate availability of Xcontext for saving
cpuid, thus freeing Context to be used for saving PGD. This option
was also tied to using a scratch register for storing PGD.

This commit will allow usage of scratch register to store the current
pgd if one can be allocated for the platform, even when
MIPS_PGD_C0_CONTEXT is not set. The cpuid will be kept in the CP0
Context register in this case.

The code to store the current pgd for the TLB miss handler is now
generated in all cases. When scratch register is available, the PGD
is also stored in the scratch register.

Signed-off-by: Jayachandran C <jchandra@broadcom.com>
---
 arch/mips/include/asm/mmu_context.h |    6 +-
 arch/mips/mm/tlbex.c                |  147 ++++++++++++++++++++++-------------
 2 files changed, 92 insertions(+), 61 deletions(-)

diff --git a/arch/mips/include/asm/mmu_context.h b/arch/mips/include/asm/mmu_context.h
index 3b29079..c846d45 100644
--- a/arch/mips/include/asm/mmu_context.h
+++ b/arch/mips/include/asm/mmu_context.h
@@ -24,14 +24,13 @@
 #endif /* SMTC */
 #include <asm-generic/mm_hooks.h>
 
-#ifdef CONFIG_MIPS_PGD_C0_CONTEXT
-
 #define TLBMISS_HANDLER_SETUP_PGD(pgd)					\
 do {									\
 	extern void tlbmiss_handler_setup_pgd(unsigned long);		\
 	tlbmiss_handler_setup_pgd((unsigned long)(pgd));		\
 } while (0)
 
+#ifdef CONFIG_MIPS_PGD_C0_CONTEXT
 #define TLBMISS_HANDLER_SETUP()						\
 	do {								\
 		TLBMISS_HANDLER_SETUP_PGD(swapper_pg_dir);		\
@@ -47,9 +46,6 @@ do {									\
  */
 extern unsigned long pgd_current[];
 
-#define TLBMISS_HANDLER_SETUP_PGD(pgd) \
-	pgd_current[smp_processor_id()] = (unsigned long)(pgd)
-
 #ifdef CONFIG_32BIT
 #define TLBMISS_HANDLER_SETUP()						\
 	write_c0_context((unsigned long) smp_processor_id() << 25);	\
diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c
index b5e9363..dcec1c0 100644
--- a/arch/mips/mm/tlbex.c
+++ b/arch/mips/mm/tlbex.c
@@ -825,11 +825,11 @@ build_get_pmde64(u32 **p, struct uasm_label **l, struct uasm_reloc **r,
 	}
 	/* No uasm_i_nop needed here, since the next insn doesn't touch TMP. */
 
-#ifdef CONFIG_MIPS_PGD_C0_CONTEXT
 	if (pgd_reg != -1) {
 		/* pgd is in pgd_reg */
 		UASM_i_MFC0(p, ptr, c0_kscratch(), pgd_reg);
 	} else {
+#ifdef CONFIG_MIPS_PGD_C0_CONTEXT
 		/*
 		 * &pgd << 11 stored in CONTEXT [23..63].
 		 */
@@ -841,30 +841,30 @@ build_get_pmde64(u32 **p, struct uasm_label **l, struct uasm_reloc **r,
 		/* 1 0	1 0 1  << 6  xkphys cached */
 		uasm_i_ori(p, ptr, ptr, 0x540);
 		uasm_i_drotr(p, ptr, ptr, 11);
-	}
 #elif defined(CONFIG_SMP)
-# ifdef	 CONFIG_MIPS_MT_SMTC
-	/*
-	 * SMTC uses TCBind value as "CPU" index
-	 */
-	uasm_i_mfc0(p, ptr, C0_TCBIND);
-	uasm_i_dsrl_safe(p, ptr, ptr, 19);
+# ifdef CONFIG_MIPS_MT_SMTC
+		/*
+		 * SMTC uses TCBind value as "CPU" index
+		 */
+		uasm_i_mfc0(p, ptr, C0_TCBIND);
+		uasm_i_dsrl_safe(p, ptr, ptr, 19);
 # else
-	/*
-	 * 64 bit SMP running in XKPHYS has smp_processor_id() << 3
-	 * stored in CONTEXT.
-	 */
-	uasm_i_dmfc0(p, ptr, C0_CONTEXT);
-	uasm_i_dsrl_safe(p, ptr, ptr, 23);
+		/*
+		 * 64 bit SMP running in XKPHYS has smp_processor_id() << 3
+		 * stored in CONTEXT.
+		 */
+		uasm_i_dmfc0(p, ptr, C0_CONTEXT);
+		uasm_i_dsrl_safe(p, ptr, ptr, 23);
 # endif
-	UASM_i_LA_mostly(p, tmp, pgdc);
-	uasm_i_daddu(p, ptr, ptr, tmp);
-	uasm_i_dmfc0(p, tmp, C0_BADVADDR);
-	uasm_i_ld(p, ptr, uasm_rel_lo(pgdc), ptr);
+		UASM_i_LA_mostly(p, tmp, pgdc);
+		uasm_i_daddu(p, ptr, ptr, tmp);
+		uasm_i_dmfc0(p, tmp, C0_BADVADDR);
+		uasm_i_ld(p, ptr, uasm_rel_lo(pgdc), ptr);
 #else
-	UASM_i_LA_mostly(p, ptr, pgdc);
-	uasm_i_ld(p, ptr, uasm_rel_lo(pgdc), ptr);
+		UASM_i_LA_mostly(p, ptr, pgdc);
+		uasm_i_ld(p, ptr, uasm_rel_lo(pgdc), ptr);
 #endif
+	}
 
 	uasm_l_vmalloc_done(l, *p);
 
@@ -959,31 +959,37 @@ build_get_pgd_vmalloc64(u32 **p, struct uasm_label **l, struct uasm_reloc **r,
 static void __cpuinit __maybe_unused
 build_get_pgde32(u32 **p, unsigned int tmp, unsigned int ptr)
 {
-	long pgdc = (long)pgd_current;
+	if (pgd_reg != -1) {
+		/* pgd is in pgd_reg */
+		uasm_i_mfc0(p, ptr, c0_kscratch(), pgd_reg);
+		uasm_i_mfc0(p, tmp, C0_BADVADDR); /* get faulting address */
+	} else {
+		long pgdc = (long)pgd_current;
 
-	/* 32 bit SMP has smp_processor_id() stored in CONTEXT. */
+		/* 32 bit SMP has smp_processor_id() stored in CONTEXT. */
 #ifdef CONFIG_SMP
-#ifdef	CONFIG_MIPS_MT_SMTC
-	/*
-	 * SMTC uses TCBind value as "CPU" index
-	 */
-	uasm_i_mfc0(p, ptr, C0_TCBIND);
-	UASM_i_LA_mostly(p, tmp, pgdc);
-	uasm_i_srl(p, ptr, ptr, 19);
-#else
-	/*
-	 * smp_processor_id() << 3 is stored in CONTEXT.
-	 */
-	uasm_i_mfc0(p, ptr, C0_CONTEXT);
-	UASM_i_LA_mostly(p, tmp, pgdc);
-	uasm_i_srl(p, ptr, ptr, 23);
-#endif
-	uasm_i_addu(p, ptr, tmp, ptr);
+# ifdef CONFIG_MIPS_MT_SMTC
+		/*
+		 * SMTC uses TCBind value as "CPU" index
+		 */
+		uasm_i_mfc0(p, ptr, C0_TCBIND);
+		UASM_i_LA_mostly(p, tmp, pgdc);
+		uasm_i_srl(p, ptr, ptr, 19);
+# else
+		/*
+		 * smp_processor_id() << 3 is stored in CONTEXT.
+		 */
+		uasm_i_mfc0(p, ptr, C0_CONTEXT);
+		UASM_i_LA_mostly(p, tmp, pgdc);
+		uasm_i_srl(p, ptr, ptr, 23);
+# endif
+		uasm_i_addu(p, ptr, tmp, ptr);
 #else
-	UASM_i_LA_mostly(p, ptr, pgdc);
+		UASM_i_LA_mostly(p, ptr, pgdc);
 #endif
-	uasm_i_mfc0(p, tmp, C0_BADVADDR); /* get faulting address */
-	uasm_i_lw(p, ptr, uasm_rel_lo(pgdc), ptr);
+		uasm_i_mfc0(p, tmp, C0_BADVADDR); /* get faulting address */
+		uasm_i_lw(p, ptr, uasm_rel_lo(pgdc), ptr);
+	}
 	uasm_i_srl(p, tmp, tmp, PGDIR_SHIFT); /* get pgd only bits */
 	uasm_i_sll(p, tmp, tmp, PGD_T_LOG2);
 	uasm_i_addu(p, ptr, ptr, tmp); /* add in pgd offset */
@@ -1458,28 +1464,30 @@ static void __cpuinit build_r4000_tlb_refill_handler(void)
 extern u32 handle_tlbl[], handle_tlbl_end[];
 extern u32 handle_tlbs[], handle_tlbs_end[];
 extern u32 handle_tlbm[], handle_tlbm_end[];
-
-#ifdef CONFIG_MIPS_PGD_C0_CONTEXT
 extern u32 tlbmiss_handler_setup_pgd[], tlbmiss_handler_setup_pgd_end[];
 
-static void __cpuinit build_r4000_setup_pgd(void)
+static void __cpuinit build_setup_pgd(void)
 {
 	const int a0 = 4;
-	const int a1 = 5;
-	u32 *p = tlbmiss_handler_setup_pgd_array;
+	const int __maybe_unused a1 = 5;
+	const int __maybe_unused a2 = 6;
+	u32 *p = tlbmiss_handler_setup_pgd;
 	const int tlbmiss_handler_setup_pgd_size =
 		tlbmiss_handler_setup_pgd_end - tlbmiss_handler_setup_pgd;
-	struct uasm_label *l = labels;
-	struct uasm_reloc *r = relocs;
+#ifndef CONFIG_MIPS_PGD_C0_CONTEXT
+	long pgdc = (long)pgd_current;
+#endif
 
 	memset(tlbmiss_handler_setup_pgd, 0, tlbmiss_handler_setup_pgd_size *
 					sizeof(tlbmiss_handler_setup_pgd[0]));
 	memset(labels, 0, sizeof(labels));
 	memset(relocs, 0, sizeof(relocs));
-
 	pgd_reg = allocate_kscratch();
-
+#ifdef CONFIG_MIPS_PGD_C0_CONTEXT
 	if (pgd_reg == -1) {
+		struct uasm_label *l = labels;
+		struct uasm_reloc *r = relocs;
+
 		/* PGD << 11 in c0_Context */
 		/*
 		 * If it is a ckseg0 address, convert to a physical
@@ -1501,6 +1509,37 @@ static void __cpuinit build_r4000_setup_pgd(void)
 		uasm_i_jr(&p, 31);
 		UASM_i_MTC0(&p, a0, c0_kscratch(), pgd_reg);
 	}
+#else
+	/* Save PGD to pgd_current[smp_processor_id()] */
+#if defined(CONFIG_SMP)
+# ifdef CONFIG_MIPS_MT_SMTC
+	/*
+	 * SMTC uses TCBind value as "CPU" index
+	 */
+	uasm_i_mfc0(&p, a1, C0_TCBIND);
+	UASM_i_SRL_SAFE(&p, a1, a1, 19);
+# else
+	/*
+	 * smp_processor_id() is in CONTEXT
+	 */
+	UASM_i_MFC0(&p, a1, C0_CONTEXT);
+	UASM_i_SRL_SAFE(&p, a1, a1, 23);
+# endif
+	UASM_i_LA_mostly(&p, a2, pgdc);
+	UASM_i_ADDU(&p, a2, a2, a1);
+	UASM_i_SW(&p, a0, uasm_rel_lo(pgdc), a2);
+#else
+	UASM_i_LA_mostly(&p, a2, pgdc);
+	UASM_i_SW(&p, a0, uasm_rel_lo(pgdc), a2);
+#endif /* SMP */
+	uasm_i_jr(&p, 31);
+
+	/* if pgd_reg is allocated, save PGD also to scratch register */
+	if (pgd_reg != -1)
+		UASM_i_MTC0(&p, a0, c0_kscratch(), pgd_reg);
+	else
+		uasm_i_nop(&p);
+#endif
 	if (p >= tlbmiss_handler_setup_pgd_end)
 		panic("tlbmiss_handler_setup_pgd space exceeded");
 
@@ -1511,7 +1550,6 @@ static void __cpuinit build_r4000_setup_pgd(void)
 	dump_handler("tlbmiss_handler", tlbmiss_handler_setup_pgd,
 					tlbmiss_handler_setup_pgd_size);
 }
-#endif
 
 static void __cpuinit
 iPTE_LW(u32 **p, unsigned int pte, unsigned int ptr)
@@ -2225,6 +2263,7 @@ void __cpuinit build_tlb_refill_handler(void)
 		if (!run_once) {
 			if (!cpu_has_local_ebase)
 				build_r3000_tlb_refill_handler();
+			build_setup_pgd();
 			build_r3000_tlb_load_handler();
 			build_r3000_tlb_store_handler();
 			build_r3000_tlb_modify_handler();
@@ -2247,9 +2286,7 @@ void __cpuinit build_tlb_refill_handler(void)
 	default:
 		if (!run_once) {
 			scratch_reg = allocate_kscratch();
-#ifdef CONFIG_MIPS_PGD_C0_CONTEXT
-			build_r4000_setup_pgd();
-#endif
+			build_setup_pgd();
 			build_r4000_tlb_load_handler();
 			build_r4000_tlb_store_handler();
 			build_r4000_tlb_modify_handler();
@@ -2270,8 +2307,6 @@ void __cpuinit flush_tlb_handlers(void)
 			   (unsigned long)handle_tlbs_end);
 	local_flush_icache_range((unsigned long)handle_tlbm,
 			   (unsigned long)handle_tlbm_end);
-#ifdef CONFIG_MIPS_PGD_C0_CONTEXT
 	local_flush_icache_range((unsigned long)tlbmiss_handler_setup_pgd,
 			   (unsigned long)tlbmiss_handler_setup_pgd_end);
-#endif
 }
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 2/3] MIPS: mm: Use scratch for PGD when !CONFIG_MIPS_PGD_C0_CONTEXT
  2013-01-08 12:56 [RFC PATCH 0/3] Use scratch registers on XLR/XLS/XLP Jayachandran C
@ 2013-01-08 12:56 ` Jayachandran C
  0 siblings, 0 replies; 8+ messages in thread
From: Jayachandran C @ 2013-01-08 12:56 UTC (permalink / raw)
  To: linux-mips, ralf; +Cc: Jayachandran C

Allow usage of scratch register for current pgd even when
MIPS_PGD_C0_CONTEXT is not configured.  MIPS_PGD_C0_CONTEXT is set
for 64r2 platforms to indicate availability of Xcontext for saving
cpuid, and this was also tied to using scratch registers for PGD.

This commit will allow usage of scratch register to store the current
pgd, if one can be allocated for the platform, even in other cases
(i.e when MIPS_PGD_C0_CONTEXT is not set). The processor id will be
kept in the CP0 Context register in this case.

The code to store the current pgd for the TLB miss handler is now
generated in all cases, and if scratch register is available, the
pgd is also stored in the scratch register.

Signed-off-by: Jayachandran C <jchandra@broadcom.com>
---
 arch/mips/include/asm/mmu_context.h |    8 +-
 arch/mips/mm/tlbex.c                |  139 ++++++++++++++++++++++-------------
 2 files changed, 91 insertions(+), 56 deletions(-)

diff --git a/arch/mips/include/asm/mmu_context.h b/arch/mips/include/asm/mmu_context.h
index 9b02cfb..9d06a96 100644
--- a/arch/mips/include/asm/mmu_context.h
+++ b/arch/mips/include/asm/mmu_context.h
@@ -24,13 +24,12 @@
 #endif /* SMTC */
 #include <asm-generic/mm_hooks.h>
 
-#ifdef CONFIG_MIPS_PGD_C0_CONTEXT
+extern void tlbmiss_handler_setup_pgd(unsigned long pgd);
 
 #define TLBMISS_HANDLER_SETUP_PGD(pgd)				\
 	tlbmiss_handler_setup_pgd((unsigned long)(pgd))
 
-extern void tlbmiss_handler_setup_pgd(unsigned long pgd);
-
+#ifdef CONFIG_MIPS_PGD_C0_CONTEXT
 #define TLBMISS_HANDLER_SETUP()						\
 	do {								\
 		TLBMISS_HANDLER_SETUP_PGD(swapper_pg_dir);		\
@@ -46,9 +45,6 @@ extern void tlbmiss_handler_setup_pgd(unsigned long pgd);
  */
 extern unsigned long pgd_current[];
 
-#define TLBMISS_HANDLER_SETUP_PGD(pgd) \
-	pgd_current[smp_processor_id()] = (unsigned long)(pgd)
-
 #ifdef CONFIG_32BIT
 #define TLBMISS_HANDLER_SETUP()						\
 	write_c0_context((unsigned long) smp_processor_id() << 25);	\
diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c
index c14f63f..ffbdedf 100644
--- a/arch/mips/mm/tlbex.c
+++ b/arch/mips/mm/tlbex.c
@@ -805,11 +805,11 @@ build_get_pmde64(u32 **p, struct uasm_label **l, struct uasm_reloc **r,
 	}
 	/* No uasm_i_nop needed here, since the next insn doesn't touch TMP. */
 
-#ifdef CONFIG_MIPS_PGD_C0_CONTEXT
 	if (pgd_reg != -1) {
 		/* pgd is in pgd_reg */
 		UASM_i_MFC0(p, ptr, c0_kscratch, pgd_reg);
 	} else {
+#ifdef CONFIG_MIPS_PGD_C0_CONTEXT
 		/*
 		 * &pgd << 11 stored in CONTEXT [23..63].
 		 */
@@ -821,30 +821,32 @@ build_get_pmde64(u32 **p, struct uasm_label **l, struct uasm_reloc **r,
 		/* 1 0  1 0 1  << 6  xkphys cached */
 		uasm_i_ori(p, ptr, ptr, 0x540);
 		uasm_i_drotr(p, ptr, ptr, 11);
-	}
-#elif defined(CONFIG_SMP)
+#else
+#if defined(CONFIG_SMP)
 # ifdef  CONFIG_MIPS_MT_SMTC
-	/*
-	 * SMTC uses TCBind value as "CPU" index
-	 */
-	uasm_i_mfc0(p, ptr, C0_TCBIND);
-	uasm_i_dsrl_safe(p, ptr, ptr, 19);
+		/*
+		 * SMTC uses TCBind value as "CPU" index
+		 */
+		uasm_i_mfc0(p, ptr, C0_TCBIND);
+		uasm_i_dsrl_safe(p, ptr, ptr, 19);
 # else
-	/*
-	 * 64 bit SMP running in XKPHYS has smp_processor_id() << 3
-	 * stored in CONTEXT.
-	 */
-	uasm_i_dmfc0(p, ptr, C0_CONTEXT);
-	uasm_i_dsrl_safe(p, ptr, ptr, 23);
+		/*
+		 * 64 bit SMP running in XKPHYS has smp_processor_id() << 3
+		 * stored in CONTEXT.
+		 */
+		uasm_i_dmfc0(p, ptr, C0_CONTEXT);
+		uasm_i_dsrl_safe(p, ptr, ptr, 23);
 # endif
-	UASM_i_LA_mostly(p, tmp, pgdc);
-	uasm_i_daddu(p, ptr, ptr, tmp);
-	uasm_i_dmfc0(p, tmp, C0_BADVADDR);
-	uasm_i_ld(p, ptr, uasm_rel_lo(pgdc), ptr);
+		UASM_i_LA_mostly(p, tmp, pgdc);
+		uasm_i_daddu(p, ptr, ptr, tmp);
+		uasm_i_dmfc0(p, tmp, C0_BADVADDR);
+		uasm_i_ld(p, ptr, uasm_rel_lo(pgdc), ptr);
 #else
-	UASM_i_LA_mostly(p, ptr, pgdc);
-	uasm_i_ld(p, ptr, uasm_rel_lo(pgdc), ptr);
-#endif
+		UASM_i_LA_mostly(p, ptr, pgdc);
+		uasm_i_ld(p, ptr, uasm_rel_lo(pgdc), ptr);
+#endif /* SMP */
+#endif  /* CONFIG_MIPS_PGD_C0_CONTEXT */
+	}
 
 	uasm_l_vmalloc_done(l, *p);
 
@@ -939,31 +941,37 @@ build_get_pgd_vmalloc64(u32 **p, struct uasm_label **l, struct uasm_reloc **r,
 static void __cpuinit __maybe_unused
 build_get_pgde32(u32 **p, unsigned int tmp, unsigned int ptr)
 {
-	long pgdc = (long)pgd_current;
+	if (pgd_reg != -1) {
+		/* pgd is in pgd_reg */
+		uasm_i_mfc0(p, ptr, c0_kscratch, pgd_reg);
+		uasm_i_mfc0(p, tmp, C0_BADVADDR); /* get faulting address */
+	} else {
+		long pgdc = (long)pgd_current;
 
-	/* 32 bit SMP has smp_processor_id() stored in CONTEXT. */
+		/* 32 bit SMP has smp_processor_id() stored in CONTEXT. */
 #ifdef CONFIG_SMP
 #ifdef  CONFIG_MIPS_MT_SMTC
-	/*
-	 * SMTC uses TCBind value as "CPU" index
-	 */
-	uasm_i_mfc0(p, ptr, C0_TCBIND);
-	UASM_i_LA_mostly(p, tmp, pgdc);
-	uasm_i_srl(p, ptr, ptr, 19);
+		/*
+		 * SMTC uses TCBind value as "CPU" index
+		 */
+		uasm_i_mfc0(p, ptr, C0_TCBIND);
+		UASM_i_LA_mostly(p, tmp, pgdc);
+		uasm_i_srl(p, ptr, ptr, 19);
 #else
-	/*
-	 * smp_processor_id() << 3 is stored in CONTEXT.
-         */
-	uasm_i_mfc0(p, ptr, C0_CONTEXT);
-	UASM_i_LA_mostly(p, tmp, pgdc);
-	uasm_i_srl(p, ptr, ptr, 23);
+		/*
+		 * smp_processor_id() << 3 is stored in CONTEXT.
+		 */
+		uasm_i_mfc0(p, ptr, C0_CONTEXT);
+		UASM_i_LA_mostly(p, tmp, pgdc);
+		uasm_i_srl(p, ptr, ptr, 23);
 #endif
-	uasm_i_addu(p, ptr, tmp, ptr);
+		uasm_i_addu(p, ptr, tmp, ptr);
 #else
-	UASM_i_LA_mostly(p, ptr, pgdc);
+		UASM_i_LA_mostly(p, ptr, pgdc);
 #endif
-	uasm_i_mfc0(p, tmp, C0_BADVADDR); /* get faulting address */
-	uasm_i_lw(p, ptr, uasm_rel_lo(pgdc), ptr);
+		uasm_i_mfc0(p, tmp, C0_BADVADDR); /* get faulting address */
+		uasm_i_lw(p, ptr, uasm_rel_lo(pgdc), ptr);
+	}
 	uasm_i_srl(p, tmp, tmp, PGDIR_SHIFT); /* get pgd only bits */
 	uasm_i_sll(p, tmp, tmp, PGD_T_LOG2);
 	uasm_i_addu(p, ptr, ptr, tmp); /* add in pgd offset */
@@ -1446,16 +1454,17 @@ static void __cpuinit build_r4000_tlb_refill_handler(void)
 u32 handle_tlbl[FASTPATH_SIZE] __cacheline_aligned;
 u32 handle_tlbs[FASTPATH_SIZE] __cacheline_aligned;
 u32 handle_tlbm[FASTPATH_SIZE] __cacheline_aligned;
-#ifdef CONFIG_MIPS_PGD_C0_CONTEXT
 u32 tlbmiss_handler_setup_pgd[16] __cacheline_aligned;
 
-static void __cpuinit build_r4000_setup_pgd(void)
+static void __cpuinit build_setup_pgd(void)
 {
 	const int a0 = 4;
-	const int a1 = 5;
+	const int __maybe_unused a1 = 5;
+	const int a2 = 6;
 	u32 *p = tlbmiss_handler_setup_pgd;
-	struct uasm_label *l = labels;
-	struct uasm_reloc *r = relocs;
+#ifndef CONFIG_MIPS_PGD_C0_CONTEXT
+	long pgdc = (long)pgd_current;
+#endif
 
 	memset(tlbmiss_handler_setup_pgd, 0, sizeof(tlbmiss_handler_setup_pgd));
 	memset(labels, 0, sizeof(labels));
@@ -1463,7 +1472,11 @@ static void __cpuinit build_r4000_setup_pgd(void)
 
 	pgd_reg = allocate_kscratch();
 
+#ifdef CONFIG_MIPS_PGD_C0_CONTEXT
 	if (pgd_reg == -1) {
+		struct uasm_label *l = labels;
+		struct uasm_reloc *r = relocs;
+
 		/* PGD << 11 in c0_Context */
 		/*
 		 * If it is a ckseg0 address, convert to a physical
@@ -1485,6 +1498,36 @@ static void __cpuinit build_r4000_setup_pgd(void)
 		uasm_i_jr(&p, 31);
 		UASM_i_MTC0(&p, a0, c0_kscratch, pgd_reg);
 	}
+#else
+#if defined(CONFIG_SMP)
+# ifdef CONFIG_MIPS_MT_SMTC
+	/*
+	 * SMTC uses TCBind value as "CPU" index
+	 */
+	uasm_i_mfc0(&p, a1, C0_TCBIND);
+	uasm_i_dsrl_safe(&p, a1, a1, 19);
+# else
+	/*
+	 * 64 bit SMP running in XKPHYS has smp_processor_id() << 3
+	 * stored in CONTEXT.
+	 */
+	UASM_i_MFC0(&p, a1, C0_CONTEXT);
+	uasm_i_dsrl_safe(&p, a1, a1, 23);
+# endif
+	UASM_i_LA_mostly(&p, a2, pgdc);
+	UASM_i_ADDU(&p, a2, a2, a1);
+	UASM_i_SW(&p, a0, uasm_rel_lo(pgdc), a2);
+#else
+	UASM_i_LA_mostly(&p, a2, pgdc);
+	UASM_i_SW(&p, a0, uasm_rel_lo(pgdc), a2);
+#endif /* SMP */
+	uasm_i_jr(&p, 31);
+	if (pgd_reg != -1) {
+		/* PGD also in c0_KScratch */
+		UASM_i_MTC0(&p, a0, c0_kscratch, pgd_reg);
+	} else
+		uasm_i_nop(&p);
+#endif
 	if (p - tlbmiss_handler_setup_pgd > ARRAY_SIZE(tlbmiss_handler_setup_pgd))
 		panic("tlbmiss_handler_setup_pgd space exceeded");
 	uasm_resolve_relocs(relocs, labels);
@@ -1494,7 +1537,6 @@ static void __cpuinit build_r4000_setup_pgd(void)
 	dump_handler(tlbmiss_handler_setup_pgd,
 		     ARRAY_SIZE(tlbmiss_handler_setup_pgd));
 }
-#endif
 
 static void __cpuinit
 iPTE_LW(u32 **p, unsigned int pte, unsigned int ptr)
@@ -2150,6 +2192,7 @@ void __cpuinit build_tlb_refill_handler(void)
 #ifndef CONFIG_MIPS_PGD_C0_CONTEXT
 		build_r3000_tlb_refill_handler();
 		if (!run_once) {
+			build_setup_pgd();
 			build_r3000_tlb_load_handler();
 			build_r3000_tlb_store_handler();
 			build_r3000_tlb_modify_handler();
@@ -2173,9 +2216,7 @@ void __cpuinit build_tlb_refill_handler(void)
 		if (!run_once) {
 			c0_kscratch = kscratch_reg();
 			scratch_reg = allocate_kscratch();
-#ifdef CONFIG_MIPS_PGD_C0_CONTEXT
-			build_r4000_setup_pgd();
-#endif
+			build_setup_pgd();
 			build_r4000_tlb_load_handler();
 			build_r4000_tlb_store_handler();
 			build_r4000_tlb_modify_handler();
@@ -2193,8 +2234,6 @@ void __cpuinit flush_tlb_handlers(void)
 			   (unsigned long)handle_tlbs + sizeof(handle_tlbs));
 	local_flush_icache_range((unsigned long)handle_tlbm,
 			   (unsigned long)handle_tlbm + sizeof(handle_tlbm));
-#ifdef CONFIG_MIPS_PGD_C0_CONTEXT
 	local_flush_icache_range((unsigned long)tlbmiss_handler_setup_pgd,
 			   (unsigned long)tlbmiss_handler_setup_pgd + sizeof(handle_tlbm));
-#endif
 }
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2013-06-23 18:18 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-03-20 16:27 [PATCH v2 0/3] Use scratch registers on XLR/XLS/XLP Jayachandran C
2013-03-20 16:27 ` [PATCH 1/3] MIPS: Allow platform specific scratch registers Jayachandran C
2013-03-20 16:27 ` [PATCH 2/3] MIPS: mm: Use scratch for PGD when !CONFIG_MIPS_PGD_C0_CONTEXT Jayachandran C
2013-03-20 16:45   ` David Daney
2013-03-20 18:01     ` Jayachandran C.
2013-03-20 16:27 ` [PATCH 3/3] MIPS: Move definition of SMP processor id register to header file Jayachandran C
  -- strict thread matches above, loose matches on Subject: below --
2013-06-23 18:16 [PATCH 0/3] Use scratch registers when MIPS_PGD_C0_CONTEXT is not set Jayachandran C
2013-06-23 18:16 ` [PATCH 2/3] MIPS: mm: Use scratch for PGD when !CONFIG_MIPS_PGD_C0_CONTEXT Jayachandran C
2013-01-08 12:56 [RFC PATCH 0/3] Use scratch registers on XLR/XLS/XLP Jayachandran C
2013-01-08 12:56 ` [PATCH 2/3] MIPS: mm: Use scratch for PGD when !CONFIG_MIPS_PGD_C0_CONTEXT Jayachandran C

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.