[OpenWrt-Devel] [PATCH 4/9] ramips: backport series of patches that ensure GCRs of other CPUs are accessed properly

Nikolay Martynov mar.kolya at gmail.com
Thu Dec 10 23:01:35 EST 2015


Signed-off-by: Nikolay Martynov <mar.kolya at gmail.com>
---
 ...-cm-intoruce-core-other-locking-functions.patch | 140 +++++++++++++++++++++
 .../0057-cm-use-core-other-locking-function.patch  |  80 ++++++++++++
 ...nsure-core-other-GCR-reflect-correct-core.patch |  49 ++++++++
 3 files changed, 269 insertions(+)
 create mode 100644 target/linux/ramips/patches-4.3/0056-cm-intoruce-core-other-locking-functions.patch
 create mode 100644 target/linux/ramips/patches-4.3/0057-cm-use-core-other-locking-function.patch
 create mode 100644 target/linux/ramips/patches-4.3/0058-backport-ensure-core-other-GCR-reflect-correct-core.patch

diff --git a/target/linux/ramips/patches-4.3/0056-cm-intoruce-core-other-locking-functions.patch b/target/linux/ramips/patches-4.3/0056-cm-intoruce-core-other-locking-functions.patch
new file mode 100644
index 0000000..e7c5a0b
--- /dev/null
+++ b/target/linux/ramips/patches-4.3/0056-cm-intoruce-core-other-locking-functions.patch
@@ -0,0 +1,140 @@
+commit 23d5de8efb9aed48074a72bf3d43841e1556ca42
+Author: Paul Burton <paul.burton at imgtec.com>
+Date:   Tue Sep 22 11:12:16 2015 -0700
+
+    MIPS: CM: Introduce core-other locking functions
+    
+    Introduce mips_cm_lock_other & mips_cm_unlock_other, mirroring the
+    existing CPC equivalents, in order to lock access from the current core
+    to another via the core-other GCR region. This hasn't been required in
+    the past but with CM3 the CPC starts using GCR_CL_OTHER rather than
+    CPC_CL_OTHER and this will be required for safety.
+    
+    [ralf at linux-mips.org: Fix merge conflict.]
+    
+    Signed-off-by: Paul Burton <paul.burton at imgtec.com>
+    Cc: linux-mips at linux-mips.org
+    Cc: linux-kernel at vger.kernel.org
+    Cc: James Hogan <james.hogan at imgtec.com>
+    Cc: Markos Chandras <markos.chandras at imgtec.com>
+    Patchwork: https://patchwork.linux-mips.org/patch/11207/
+    Signed-off-by: Ralf Baechle <ralf at linux-mips.org>
+
+--- a/arch/mips/include/asm/mips-cm.h
++++ b/arch/mips/include/asm/mips-cm.h
+@@ -334,6 +334,10 @@ BUILD_CM_Cx_R_(tcid_8_priority,	0x80)
+ /* GCR_Cx_OTHER register fields */
+ #define CM_GCR_Cx_OTHER_CORENUM_SHF		16
+ #define CM_GCR_Cx_OTHER_CORENUM_MSK		(_ULCAST_(0xffff) << 16)
++#define CM3_GCR_Cx_OTHER_CORE_SHF		8
++#define CM3_GCR_Cx_OTHER_CORE_MSK		(_ULCAST_(0x3f) << 8)
++#define CM3_GCR_Cx_OTHER_VP_SHF			0
++#define CM3_GCR_Cx_OTHER_VP_MSK			(_ULCAST_(0x7) << 0)
+ 
+ /* GCR_Cx_RESET_BASE register fields */
+ #define CM_GCR_Cx_RESET_BASE_BEVEXCBASE_SHF	12
+@@ -444,4 +448,32 @@ static inline unsigned int mips_cm_vp_id
+ 	return (core * mips_cm_max_vp_width()) + vp;
+ }
+ 
++#ifdef CONFIG_MIPS_CM
++
++/**
++ * mips_cm_lock_other - lock access to another core
++ * @core: the other core to be accessed
++ * @vp: the VP within the other core to be accessed
++ *
++ * Call before operating upon a core via the 'other' register region in
++ * order to prevent the region being moved during access. Must be followed
++ * by a call to mips_cm_unlock_other.
++ */
++extern void mips_cm_lock_other(unsigned int core, unsigned int vp);
++
++/**
++ * mips_cm_unlock_other - unlock access to another core
++ *
++ * Call after operating upon another core via the 'other' register region.
++ * Must be called after mips_cm_lock_other.
++ */
++extern void mips_cm_unlock_other(void);
++
++#else /* !CONFIG_MIPS_CM */
++
++static inline void mips_cm_lock_other(unsigned int core) { }
++static inline void mips_cm_unlock_other(void) { }
++
++#endif /* !CONFIG_MIPS_CM */
++
+ #endif /* __MIPS_ASM_MIPS_CM_H__ */
+--- a/arch/mips/kernel/mips-cm.c
++++ b/arch/mips/kernel/mips-cm.c
+@@ -9,6 +9,8 @@
+  */
+ 
+ #include <linux/errno.h>
++#include <linux/percpu.h>
++#include <linux/spinlock.h>
+ 
+ #include <asm/mips-cm.h>
+ #include <asm/mipsregs.h>
+@@ -136,6 +138,9 @@ static char *cm3_causes[32] = {
+ 	"0x19", "0x1a", "0x1b", "0x1c", "0x1d", "0x1e", "0x1f"
+ };
+ 
++static DEFINE_PER_CPU_ALIGNED(spinlock_t, cm_core_lock);
++static DEFINE_PER_CPU_ALIGNED(unsigned long, cm_core_lock_flags);
++
+ phys_addr_t __mips_cm_phys_base(void)
+ {
+ 	u32 config3 = read_c0_config3();
+@@ -200,6 +205,7 @@ int mips_cm_probe(void)
+ {
+ 	phys_addr_t addr;
+ 	u32 base_reg;
++	unsigned cpu;
+ 
+ 	/*
+ 	 * No need to probe again if we have already been
+@@ -247,9 +253,42 @@ int mips_cm_probe(void)
+ 	/* determine register width for this CM */
+ 	mips_cm_is64 = config_enabled(CONFIG_64BIT) && (mips_cm_revision() >= CM_REV_CM3);
+ 
++	for_each_possible_cpu(cpu)
++		spin_lock_init(&per_cpu(cm_core_lock, cpu));
++
+ 	return 0;
+ }
+ 
++void mips_cm_lock_other(unsigned int core, unsigned int vp)
++{
++	unsigned curr_core;
++	u32 val;
++
++	preempt_disable();
++	curr_core = current_cpu_data.core;
++	spin_lock_irqsave(&per_cpu(cm_core_lock, curr_core),
++			  per_cpu(cm_core_lock_flags, curr_core));
++
++	if (mips_cm_revision() >= CM_REV_CM3) {
++		val = core << CM3_GCR_Cx_OTHER_CORE_SHF;
++		val |= vp << CM3_GCR_Cx_OTHER_VP_SHF;
++	} else {
++		BUG_ON(vp != 0);
++		val = core << CM_GCR_Cx_OTHER_CORENUM_SHF;
++	}
++
++	write_gcr_cl_other(val);
++}
++
++void mips_cm_unlock_other(void)
++{
++	unsigned curr_core = current_cpu_data.core;
++
++	spin_unlock_irqrestore(&per_cpu(cm_core_lock, curr_core),
++			       per_cpu(cm_core_lock_flags, curr_core));
++	preempt_enable();
++}
++
+ void mips_cm_error_report(void)
+ {
+ 	unsigned long revision = mips_cm_revision();
diff --git a/target/linux/ramips/patches-4.3/0057-cm-use-core-other-locking-function.patch b/target/linux/ramips/patches-4.3/0057-cm-use-core-other-locking-function.patch
new file mode 100644
index 0000000..2ac52f7
--- /dev/null
+++ b/target/linux/ramips/patches-4.3/0057-cm-use-core-other-locking-function.patch
@@ -0,0 +1,80 @@
+commit 4ede31617056b7424eef28dce59dd6dbe81729c3
+Author: Paul Burton <paul.burton at imgtec.com>
+Date:   Tue Sep 22 11:12:17 2015 -0700
+
+    MIPS: CM: make use of mips_cm_{lock,unlock}_other
+    
+    Document that CPC core-other accesses must take place within the bounds
+    of the CM lock, and begin using the CM lock functions where we access
+    the GCRs of other cores. This is required because with CM3 the CPC began
+    using GCR_CL_OTHER instead of CPC_CL_OTHER.
+    
+    Signed-off-by: Paul Burton <paul.burton at imgtec.com>
+    Cc: linux-mips at linux-mips.org
+    Cc: Rusty Russell <rusty at rustcorp.com.au>
+    Cc: Andrew Bresticker <abrestic at chromium.org>
+    Cc: Bjorn Helgaas <bhelgaas at google.com>
+    Cc: linux-kernel at vger.kernel.org
+    Cc: Niklas Cassel <niklas.cassel at axis.com>
+    Cc: Ezequiel Garcia <ezequiel.garcia at imgtec.com>
+    Cc: Markos Chandras <markos.chandras at imgtec.com>
+    Patchwork: https://patchwork.linux-mips.org/patch/11208/
+    Signed-off-by: Ralf Baechle <ralf at linux-mips.org>
+
+--- a/arch/mips/include/asm/mips-cpc.h
++++ b/arch/mips/include/asm/mips-cpc.h
+@@ -149,7 +149,8 @@ BUILD_CPC_Cx_RW(other,		0x10)
+  * core: the other core to be accessed
+  *
+  * Call before operating upon a core via the 'other' register region in
+- * order to prevent the region being moved during access. Must be followed
++ * order to prevent the region being moved during access. Must be called
++ * within the bounds of a mips_cm_{lock,unlock}_other pair, and followed
+  * by a call to mips_cpc_unlock_other.
+  */
+ extern void mips_cpc_lock_other(unsigned int core);
+--- a/arch/mips/kernel/smp-cps.c
++++ b/arch/mips/kernel/smp-cps.c
+@@ -37,8 +37,9 @@ static unsigned core_vpe_count(unsigned
+ 	if (!config_enabled(CONFIG_MIPS_MT_SMP) || !cpu_has_mipsmt)
+ 		return 1;
+ 
+-	write_gcr_cl_other(core << CM_GCR_Cx_OTHER_CORENUM_SHF);
++	mips_cm_lock_other(core, 0);
+ 	cfg = read_gcr_co_config() & CM_GCR_Cx_CONFIG_PVPE_MSK;
++	mips_cm_unlock_other();
+ 	return (cfg >> CM_GCR_Cx_CONFIG_PVPE_SHF) + 1;
+ }
+ 
+@@ -193,7 +194,7 @@ static void boot_core(unsigned core)
+ 	u32 access;
+ 
+ 	/* Select the appropriate core */
+-	write_gcr_cl_other(core << CM_GCR_Cx_OTHER_CORENUM_SHF);
++	mips_cm_lock_other(core, 0);
+ 
+ 	/* Set its reset vector */
+ 	write_gcr_co_reset_base(CKSEG1ADDR((unsigned long)mips_cps_core_entry));
+@@ -216,6 +217,8 @@ static void boot_core(unsigned core)
+ 		write_gcr_co_reset_release(0);
+ 	}
+ 
++	mips_cm_unlock_other();
++
+ 	/* The core is now powered up */
+ 	bitmap_set(core_power, core, 1);
+ }
+--- a/arch/mips/kernel/smp-gic.c
++++ b/arch/mips/kernel/smp-gic.c
+@@ -46,9 +46,11 @@ void gic_send_ipi_single(int cpu, unsign
+ 
+ 	if (mips_cpc_present() && (core != current_cpu_data.core)) {
+ 		while (!cpumask_test_cpu(cpu, &cpu_coherent_mask)) {
++			mips_cm_lock_other(core, 0);
+ 			mips_cpc_lock_other(core);
+ 			write_cpc_co_cmd(CPC_Cx_CMD_PWRUP);
+ 			mips_cpc_unlock_other();
++			mips_cm_unlock_other();
+ 		}
+ 	}
+ 
diff --git a/target/linux/ramips/patches-4.3/0058-backport-ensure-core-other-GCR-reflect-correct-core.patch b/target/linux/ramips/patches-4.3/0058-backport-ensure-core-other-GCR-reflect-correct-core.patch
new file mode 100644
index 0000000..e8ed6ab
--- /dev/null
+++ b/target/linux/ramips/patches-4.3/0058-backport-ensure-core-other-GCR-reflect-correct-core.patch
@@ -0,0 +1,49 @@
+commit 78a54c4d8e5a7915a4ec2ba0eb461fae50590683
+Author: Paul Burton <paul.burton at imgtec.com>
+Date:   Tue Sep 22 11:12:18 2015 -0700
+
+    MIPS: CM, CPC: Ensure core-other GCRs reflect the correct core
+    
+    Ensure the update to which core the core-other GCR regions reflect has
+    taken place before any core-other GCRs are accessed by placing a memory
+    barrier (sync instruction) between the write to the core-other registers
+    and any such GCR accesses.
+    
+    Signed-off-by: Paul Burton <paul.burton at imgtec.com>
+    Cc: linux-mips at linux-mips.org
+    Cc: Bjorn Helgaas <bhelgaas at google.com>
+    Cc: linux-kernel at vger.kernel.org
+    Cc: Markos Chandras <markos.chandras at imgtec.com>
+    Patchwork: https://patchwork.linux-mips.org/patch/11209/
+    Signed-off-by: Ralf Baechle <ralf at linux-mips.org>
+
+--- a/arch/mips/kernel/mips-cm.c
++++ b/arch/mips/kernel/mips-cm.c
+@@ -278,6 +278,12 @@ void mips_cm_lock_other(unsigned int cor
+ 	}
+ 
+ 	write_gcr_cl_other(val);
++
++	/*
++	 * Ensure the core-other region reflects the appropriate core &
++	 * VP before any accesses to it occur.
++	 */
++	mb();
+ }
+ 
+ void mips_cm_unlock_other(void)
+--- a/arch/mips/kernel/mips-cpc.c
++++ b/arch/mips/kernel/mips-cpc.c
+@@ -76,6 +76,12 @@ void mips_cpc_lock_other(unsigned int co
+ 	spin_lock_irqsave(&per_cpu(cpc_core_lock, curr_core),
+ 			  per_cpu(cpc_core_lock_flags, curr_core));
+ 	write_cpc_cl_other(core << CPC_Cx_OTHER_CORENUM_SHF);
++
++	/*
++	 * Ensure the core-other region reflects the appropriate core &
++	 * VP before any accesses to it occur.
++	 */
++	mb();
+ }
+ 
+ void mips_cpc_unlock_other(void)
-- 
2.6.4
_______________________________________________
openwrt-devel mailing list
openwrt-devel at lists.openwrt.org
https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel



More information about the openwrt-devel mailing list