All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 2/5] MIPS: Allow kernel to use coprocessor 2
  2013-03-22 16:24 [RFC PATCH 0/5] Cop2 save/restore for XLR/XLP Jayachandran C
@ 2013-03-22 16:24 ` Jayachandran C
  0 siblings, 0 replies; 10+ messages in thread
From: Jayachandran C @ 2013-03-22 16:24 UTC (permalink / raw)
  To: linux-mips, ralf, ddaney.cavm; +Cc: Jayachandran C

Kernel threads should be able to use COP2 if the platform needs it.
Do not call die_if_kernel() for a coprocessor unusable exception if
the exception due to COP2 usage.  Instead, the default notifier for
COP2 exceptions is updated to call die_if_kernel.

Signed-off-by: Jayachandran C <jchandra@broadcom.com>
---
 arch/mips/kernel/traps.c |   15 +++++----------
 1 file changed, 5 insertions(+), 10 deletions(-)

diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index a200b5b..36c242f 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -970,15 +970,9 @@ static int default_cu2_call(struct notifier_block *nfb, unsigned long action,
 {
 	struct pt_regs *regs = data;
 
-	switch (action) {
-	default:
-		die_if_kernel("Unhandled kernel unaligned access or invalid "
+	die_if_kernel("COP2: Unhandled kernel unaligned access or invalid "
 			      "instruction", regs);
-		/* Fall through	 */
-
-	case CU2_EXCEPTION:
-		force_sig(SIGILL, current);
-	}
+	force_sig(SIGILL, current);
 
 	return NOTIFY_OK;
 }
@@ -992,10 +986,11 @@ asmlinkage void do_cpu(struct pt_regs *regs)
 	int status;
 	unsigned long __maybe_unused flags;
 
-	die_if_kernel("do_cpu invoked from kernel context!", regs);
-
 	cpid = (regs->cp0_cause >> CAUSEB_CE) & 3;
 
+	if (cpid != 2)
+		die_if_kernel("do_cpu invoked from kernel context!", regs);
+
 	switch (cpid) {
 	case 0:
 		epc = (unsigned int __user *)exception_epc(regs);
-- 
1.7.9.5

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

* [PATCH 0/5 v2] Cop2 save and restore for Netlogic XLP
@ 2013-06-10  7:29 Jayachandran C
  2013-06-10  7:30 ` [PATCH 1/5] MIPS: Move cop2 save/restore to switch_to() Jayachandran C
                   ` (4 more replies)
  0 siblings, 5 replies; 10+ messages in thread
From: Jayachandran C @ 2013-06-10  7:29 UTC (permalink / raw)
  To: linux-mips, ralf, ddaney.cavm; +Cc: Jayachandran C

This patchset is to generalize the COP2 save/restore implemented for
Octeon and to use it for Netlogic XLP.

Patch 1 and 2 of the series affects the Octeon platform as well, please
let me know if there are any suggestions/comments.

Thanks,
JC.

---

Changes in v2:
 - XLR support dropped, status register is readonly in XLR and cannot
   be restored
 - fix naming of COP2 registers

Jayachandran C (5):
  MIPS: Move cop2 save/restore to switch_to()
  MIPS: Allow kernel to use coprocessor 2
  MIPS: Netlogic: Fix nlm_read_c2_status() definition
  MIPS: Netlogic: rename nlm_cop2_save/restore
  MIPS: Netlogic: COP2 save/restore code

 arch/mips/include/asm/cop2.h             |   29 ++++++++
 arch/mips/include/asm/netlogic/xlr/fmn.h |   12 ++-
 arch/mips/include/asm/processor.h        |   31 +++++---
 arch/mips/include/asm/switch_to.h        |   19 ++++-
 arch/mips/kernel/octeon_switch.S         |   27 -------
 arch/mips/kernel/traps.c                 |   15 ++--
 arch/mips/netlogic/xlp/Makefile          |    2 +-
 arch/mips/netlogic/xlp/cop2-ex.c         |  118 ++++++++++++++++++++++++++++++
 arch/mips/netlogic/xlr/fmn.c             |   18 ++---
 9 files changed, 208 insertions(+), 63 deletions(-)
 create mode 100644 arch/mips/netlogic/xlp/cop2-ex.c

-- 
1.7.9.5

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

* [PATCH 1/5] MIPS: Move cop2 save/restore to switch_to()
  2013-06-10  7:29 [PATCH 0/5 v2] Cop2 save and restore for Netlogic XLP Jayachandran C
@ 2013-06-10  7:30 ` Jayachandran C
  2013-06-10  7:30 ` [PATCH 2/5] MIPS: Allow kernel to use coprocessor 2 Jayachandran C
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 10+ messages in thread
From: Jayachandran C @ 2013-06-10  7:30 UTC (permalink / raw)
  To: linux-mips, ralf, ddaney.cavm; +Cc: Jayachandran C

Move the common code for saving and restoring platform specific COP2
registers to switch_to(). This will make supporting new platforms (like
Netlogic XLP) easier.

The platform specific COP2 definitions are to be specified in
asm/processor.h and in asm/cop2.h.

Signed-off-by: Jayachandran C <jchandra@broadcom.com>
---
 arch/mips/include/asm/cop2.h      |   19 +++++++++++++++++++
 arch/mips/include/asm/processor.h |   18 +++++++-----------
 arch/mips/include/asm/switch_to.h |   19 ++++++++++++++++++-
 arch/mips/kernel/octeon_switch.S  |   27 ---------------------------
 4 files changed, 44 insertions(+), 39 deletions(-)

diff --git a/arch/mips/include/asm/cop2.h b/arch/mips/include/asm/cop2.h
index 3532e2c..b17f38e 100644
--- a/arch/mips/include/asm/cop2.h
+++ b/arch/mips/include/asm/cop2.h
@@ -11,6 +11,25 @@
 
 #include <linux/notifier.h>
 
+#if defined(CONFIG_CPU_CAVIUM_OCTEON)
+
+extern void octeon_cop2_save(struct octeon_cop2_state *);
+extern void octeon_cop2_restore(struct octeon_cop2_state *);
+
+#define cop2_save(r)		octeon_cop2_save(r)
+#define cop2_restore(r)		octeon_cop2_restore(r)
+
+#define cop2_present		1
+#define cop2_lazy_restore	1
+
+#else
+
+#define cop2_present		0
+#define cop2_lazy_restore	0
+#define cop2_save(r)
+#define cop2_restore(r)
+#endif
+
 enum cu2_ops {
 	CU2_EXCEPTION,
 	CU2_LWC2_OP,
diff --git a/arch/mips/include/asm/processor.h b/arch/mips/include/asm/processor.h
index 1470b7b..7c637a4 100644
--- a/arch/mips/include/asm/processor.h
+++ b/arch/mips/include/asm/processor.h
@@ -137,7 +137,7 @@ union mips_watch_reg_state {
 	struct mips3264_watch_reg_state mips3264;
 };
 
-#ifdef CONFIG_CPU_CAVIUM_OCTEON
+#if defined(CONFIG_CPU_CAVIUM_OCTEON)
 
 struct octeon_cop2_state {
 	/* DMFC2 rt, 0x0201 */
@@ -182,13 +182,16 @@ struct octeon_cop2_state {
 	/* DMFC2 rt, 0x025A; DMFC2 rt, 0x025B - Pass2 */
 	unsigned long	cop2_gfm_result[2];
 };
-#define INIT_OCTEON_COP2 {0,}
+#define COP2_INIT						\
+	.cp2			= {0,},
 
 struct octeon_cvmseg_state {
 	unsigned long cvmseg[CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE]
 			    [cpu_dcache_line_size() / sizeof(unsigned long)];
 };
 
+#else
+#define COP2_INIT
 #endif
 
 typedef struct {
@@ -245,13 +248,6 @@ struct thread_struct {
 #define FPAFF_INIT
 #endif /* CONFIG_MIPS_MT_FPAFF */
 
-#ifdef CONFIG_CPU_CAVIUM_OCTEON
-#define OCTEON_INIT						\
-	.cp2			= INIT_OCTEON_COP2,
-#else
-#define OCTEON_INIT
-#endif /* CONFIG_CPU_CAVIUM_OCTEON */
-
 #define INIT_THREAD  {						\
 	/*							\
 	 * Saved main processor registers			\
@@ -300,9 +296,9 @@ struct thread_struct {
 	.cp0_baduaddr		= 0,				\
 	.error_code		= 0,				\
 	/*							\
-	 * Cavium Octeon specifics (null if not Octeon)		\
+	 * Platform specific cop2 registers(null if no COP2)	\
 	 */							\
-	OCTEON_INIT						\
+	COP2_INIT						\
 }
 
 struct task_struct;
diff --git a/arch/mips/include/asm/switch_to.h b/arch/mips/include/asm/switch_to.h
index fd16bcb..eb0af15 100644
--- a/arch/mips/include/asm/switch_to.h
+++ b/arch/mips/include/asm/switch_to.h
@@ -15,6 +15,7 @@
 #include <asm/cpu-features.h>
 #include <asm/watch.h>
 #include <asm/dsp.h>
+#include <asm/cop2.h>
 
 struct task_struct;
 
@@ -66,10 +67,18 @@ do {									\
 
 #define switch_to(prev, next, last)					\
 do {									\
-	u32 __usedfpu;							\
+	u32 __usedfpu, __c0_stat;					\
 	__mips_mt_fpaff_switch_to(prev);				\
 	if (cpu_has_dsp)						\
 		__save_dsp(prev);					\
+	if (cop2_present && (KSTK_STATUS(prev) & ST0_CU2)) {		\
+		if (cop2_lazy_restore)					\
+			KSTK_STATUS(prev) &= ~ST0_CU2;			\
+		__c0_stat = read_c0_status();				\
+		write_c0_status(__c0_stat | ST0_CU2);			\
+		cop2_save(&prev->thread.cp2);				\
+		write_c0_status(__c0_stat & ~ST0_CU2);			\
+	}								\
 	__clear_software_ll_bit();					\
 	__usedfpu = test_and_clear_tsk_thread_flag(prev, TIF_USEDFPU);	\
 	(last) = resume(prev, next, task_thread_info(next), __usedfpu); \
@@ -77,6 +86,14 @@ do {									\
 
 #define finish_arch_switch(prev)					\
 do {									\
+	u32 __c0_stat;							\
+	if (cop2_present && !cop2_lazy_restore &&			\
+			(KSTK_STATUS(current) & ST0_CU2)) {		\
+		__c0_stat = read_c0_status();				\
+		write_c0_status(__c0_stat | ST0_CU2);			\
+		cop2_restore(&current->thread.cp2);			\
+		write_c0_status(__c0_stat & ~ST0_CU2);			\
+	}								\
 	if (cpu_has_dsp)						\
 		__restore_dsp(current);					\
 	if (cpu_has_userlocal)						\
diff --git a/arch/mips/kernel/octeon_switch.S b/arch/mips/kernel/octeon_switch.S
index 0e23343..22e2aa1 100644
--- a/arch/mips/kernel/octeon_switch.S
+++ b/arch/mips/kernel/octeon_switch.S
@@ -40,33 +40,6 @@
 	cpu_save_nonscratch a0
 	LONG_S	ra, THREAD_REG31(a0)
 
-	/* check if we need to save COP2 registers */
-	PTR_L	t2, TASK_THREAD_INFO(a0)
-	LONG_L	t0, ST_OFF(t2)
-	bbit0	t0, 30, 1f
-
-	/* Disable COP2 in the stored process state */
-	li	t1, ST0_CU2
-	xor	t0, t1
-	LONG_S	t0, ST_OFF(t2)
-
-	/* Enable COP2 so we can save it */
-	mfc0	t0, CP0_STATUS
-	or	t0, t1
-	mtc0	t0, CP0_STATUS
-
-	/* Save COP2 */
-	daddu	a0, THREAD_CP2
-	jal octeon_cop2_save
-	dsubu	a0, THREAD_CP2
-
-	/* Disable COP2 now that we are done */
-	mfc0	t0, CP0_STATUS
-	li	t1, ST0_CU2
-	xor	t0, t1
-	mtc0	t0, CP0_STATUS
-
-1:
 #if CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE > 0
 	/* Check if we need to store CVMSEG state */
 	mfc0	t0, $11,7	/* CvmMemCtl */
-- 
1.7.9.5

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

* [PATCH 2/5] MIPS: Allow kernel to use coprocessor 2
  2013-06-10  7:29 [PATCH 0/5 v2] Cop2 save and restore for Netlogic XLP Jayachandran C
  2013-06-10  7:30 ` [PATCH 1/5] MIPS: Move cop2 save/restore to switch_to() Jayachandran C
@ 2013-06-10  7:30 ` Jayachandran C
  2013-06-10 11:31   ` Sergei Shtylyov
  2013-06-10 12:42   ` Ralf Baechle
  2013-06-10  7:30 ` [PATCH 3/5] MIPS: Netlogic: Fix nlm_read_c2_status() definition Jayachandran C
                   ` (2 subsequent siblings)
  4 siblings, 2 replies; 10+ messages in thread
From: Jayachandran C @ 2013-06-10  7:30 UTC (permalink / raw)
  To: linux-mips, ralf, ddaney.cavm; +Cc: Jayachandran C

Kernel threads should be able to use COP2 if the platform needs it.
Do not call die_if_kernel() for a coprocessor unusable exception if
the exception due to COP2 usage.  Instead, the default notifier for
COP2 exceptions is updated to call die_if_kernel.

Signed-off-by: Jayachandran C <jchandra@broadcom.com>
---
 arch/mips/kernel/traps.c |   15 +++++----------
 1 file changed, 5 insertions(+), 10 deletions(-)

diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index beba1e6..142d2be 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -1056,15 +1056,9 @@ static int default_cu2_call(struct notifier_block *nfb, unsigned long action,
 {
 	struct pt_regs *regs = data;
 
-	switch (action) {
-	default:
-		die_if_kernel("Unhandled kernel unaligned access or invalid "
+	die_if_kernel("COP2: Unhandled kernel unaligned access or invalid "
 			      "instruction", regs);
-		/* Fall through	 */
-
-	case CU2_EXCEPTION:
-		force_sig(SIGILL, current);
-	}
+	force_sig(SIGILL, current);
 
 	return NOTIFY_OK;
 }
@@ -1080,10 +1074,11 @@ asmlinkage void do_cpu(struct pt_regs *regs)
 	unsigned long __maybe_unused flags;
 
 	prev_state = exception_enter();
-	die_if_kernel("do_cpu invoked from kernel context!", regs);
-
 	cpid = (regs->cp0_cause >> CAUSEB_CE) & 3;
 
+	if (cpid != 2)
+		die_if_kernel("do_cpu invoked from kernel context!", regs);
+
 	switch (cpid) {
 	case 0:
 		epc = (unsigned int __user *)exception_epc(regs);
-- 
1.7.9.5

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

* [PATCH 3/5] MIPS: Netlogic: Fix nlm_read_c2_status() definition
  2013-06-10  7:29 [PATCH 0/5 v2] Cop2 save and restore for Netlogic XLP Jayachandran C
  2013-06-10  7:30 ` [PATCH 1/5] MIPS: Move cop2 save/restore to switch_to() Jayachandran C
  2013-06-10  7:30 ` [PATCH 2/5] MIPS: Allow kernel to use coprocessor 2 Jayachandran C
@ 2013-06-10  7:30 ` Jayachandran C
  2013-06-10  7:30 ` [PATCH 4/5] MIPS: Netlogic: rename nlm_cop2_save/restore Jayachandran C
  2013-06-10  7:30 ` [PATCH 5/5] MIPS: Netlogic: COP2 save/restore code Jayachandran C
  4 siblings, 0 replies; 10+ messages in thread
From: Jayachandran C @ 2013-06-10  7:30 UTC (permalink / raw)
  To: linux-mips, ralf, ddaney.cavm; +Cc: Jayachandran C

The sel argument os nlm_read_c2_status() was not used and the macro
returned the sel 0 in all cases. Fix this by defining two macros:
nlm_read_c2_status0() and nlm_read_c2_status1() to return the two
status registers.

Add functions to write to the status registers as well.

Signed-off-by: Jayachandran C <jchandra@broadcom.com>
---
 arch/mips/include/asm/netlogic/xlr/fmn.h |    8 ++++++--
 arch/mips/netlogic/xlr/fmn.c             |    2 +-
 2 files changed, 7 insertions(+), 3 deletions(-)

diff --git a/arch/mips/include/asm/netlogic/xlr/fmn.h b/arch/mips/include/asm/netlogic/xlr/fmn.h
index 2a78929..56c7b85 100644
--- a/arch/mips/include/asm/netlogic/xlr/fmn.h
+++ b/arch/mips/include/asm/netlogic/xlr/fmn.h
@@ -175,6 +175,10 @@
 #define nlm_write_c2_cc14(s, v)		__write_32bit_c2_register($30, s, v)
 #define nlm_write_c2_cc15(s, v)		__write_32bit_c2_register($31, s, v)
 
+#define nlm_read_c2_status0()		__read_32bit_c2_register($2, 0)
+#define nlm_write_c2_status0(v)		__write_32bit_c2_register($2, 0, v)
+#define nlm_read_c2_status1()		__read_32bit_c2_register($2, 1)
+#define nlm_write_c2_status1(v)		__write_32bit_c2_register($2, 1, v)
 #define nlm_read_c2_status(sel)		__read_32bit_c2_register($2, 0)
 #define nlm_read_c2_config()		__read_32bit_c2_register($3, 0)
 #define nlm_write_c2_config(v)		__write_32bit_c2_register($3, 0, v)
@@ -296,7 +300,7 @@ static inline int nlm_fmn_send(unsigned int size, unsigned int code,
 	 */
 	for (i = 0; i < 8; i++) {
 		nlm_msgsnd(dest);
-		status = nlm_read_c2_status(0);
+		status = nlm_read_c2_status0();
 		if ((status & 0x2) == 1)
 			pr_info("Send pending fail!\n");
 		if ((status & 0x4) == 0)
@@ -316,7 +320,7 @@ static inline int nlm_fmn_receive(int bucket, int *size, int *code, int *stid,
 
 	/* wait for load pending to clear */
 	do {
-		status = nlm_read_c2_status(1);
+		status = nlm_read_c2_status0();
 	} while ((status & 0x08) != 0);
 
 	/* receive error bits */
diff --git a/arch/mips/netlogic/xlr/fmn.c b/arch/mips/netlogic/xlr/fmn.c
index 4d74f03..0fdce61 100644
--- a/arch/mips/netlogic/xlr/fmn.c
+++ b/arch/mips/netlogic/xlr/fmn.c
@@ -80,7 +80,7 @@ static irqreturn_t fmn_message_handler(int irq, void *data)
 	while (1) {
 		/* 8 bkts per core, [24:31] each bit represents one bucket
 		 * Bit is Zero if bucket is not empty */
-		bkt_status = (nlm_read_c2_status() >> 24) & 0xff;
+		bkt_status = (nlm_read_c2_status0() >> 24) & 0xff;
 		if (bkt_status == 0xff)
 			break;
 		for (bucket = 0; bucket < 8; bucket++) {
-- 
1.7.9.5

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

* [PATCH 4/5] MIPS: Netlogic: rename nlm_cop2_save/restore
  2013-06-10  7:29 [PATCH 0/5 v2] Cop2 save and restore for Netlogic XLP Jayachandran C
                   ` (2 preceding siblings ...)
  2013-06-10  7:30 ` [PATCH 3/5] MIPS: Netlogic: Fix nlm_read_c2_status() definition Jayachandran C
@ 2013-06-10  7:30 ` Jayachandran C
  2013-06-10  7:30 ` [PATCH 5/5] MIPS: Netlogic: COP2 save/restore code Jayachandran C
  4 siblings, 0 replies; 10+ messages in thread
From: Jayachandran C @ 2013-06-10  7:30 UTC (permalink / raw)
  To: linux-mips, ralf, ddaney.cavm; +Cc: Jayachandran C

Rename macro nlm_cop2_enable() to nlm_cop2_enable_irqsave() and the macro
nlm_cop2_restore to nlm_cop2_disable_irqrestore(). The new names will
reflect the functionality better, and will make nlm_cop2_restore()
available to be used later in COP2 save/restore patch.

Signed-off-by: Jayachandran C <jchandra@broadcom.com>
---
 arch/mips/include/asm/netlogic/xlr/fmn.h |    4 ++--
 arch/mips/netlogic/xlr/fmn.c             |   16 ++++++++--------
 2 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/arch/mips/include/asm/netlogic/xlr/fmn.h b/arch/mips/include/asm/netlogic/xlr/fmn.h
index 56c7b85..5604db3 100644
--- a/arch/mips/include/asm/netlogic/xlr/fmn.h
+++ b/arch/mips/include/asm/netlogic/xlr/fmn.h
@@ -241,7 +241,7 @@ static inline void nlm_msgwait(unsigned int mask)
 /*
  * Disable interrupts and enable COP2 access
  */
-static inline uint32_t nlm_cop2_enable(void)
+static inline uint32_t nlm_cop2_enable_irqsave(void)
 {
 	uint32_t sr = read_c0_status();
 
@@ -249,7 +249,7 @@ static inline uint32_t nlm_cop2_enable(void)
 	return sr;
 }
 
-static inline void nlm_cop2_restore(uint32_t sr)
+static inline void nlm_cop2_disable_irqrestore(uint32_t sr)
 {
 	write_c0_status(sr);
 }
diff --git a/arch/mips/netlogic/xlr/fmn.c b/arch/mips/netlogic/xlr/fmn.c
index 0fdce61..d428e84 100644
--- a/arch/mips/netlogic/xlr/fmn.c
+++ b/arch/mips/netlogic/xlr/fmn.c
@@ -74,7 +74,7 @@ static irqreturn_t fmn_message_handler(int irq, void *data)
 	struct nlm_fmn_msg msg;
 	uint32_t mflags, bkt_status;
 
-	mflags = nlm_cop2_enable();
+	mflags = nlm_cop2_enable_irqsave();
 	/* Disable message ring interrupt */
 	nlm_fmn_setup_intr(irq, 0);
 	while (1) {
@@ -97,16 +97,16 @@ static irqreturn_t fmn_message_handler(int irq, void *data)
 				pr_warn("No msgring handler for stnid %d\n",
 						src_stnid);
 			else {
-				nlm_cop2_restore(mflags);
+				nlm_cop2_disable_irqrestore(mflags);
 				hndlr->action(bucket, src_stnid, size, code,
 					&msg, hndlr->arg);
-				mflags = nlm_cop2_enable();
+				mflags = nlm_cop2_enable_irqsave();
 			}
 		}
 	};
 	/* Enable message ring intr, to any thread in core */
 	nlm_fmn_setup_intr(irq, (1 << nlm_threads_per_core) - 1);
-	nlm_cop2_restore(mflags);
+	nlm_cop2_disable_irqrestore(mflags);
 	return IRQ_HANDLED;
 }
 
@@ -128,7 +128,7 @@ void xlr_percpu_fmn_init(void)
 
 	bucket_sizes = xlr_board_fmn_config.bucket_size;
 	cpu_fmn_info = &xlr_board_fmn_config.cpu[id];
-	flags = nlm_cop2_enable();
+	flags = nlm_cop2_enable_irqsave();
 
 	/* Setup bucket sizes for the core. */
 	nlm_write_c2_bucksize(0, bucket_sizes[id * 8 + 0]);
@@ -166,7 +166,7 @@ void xlr_percpu_fmn_init(void)
 
 	/* enable FMN interrupts on this CPU */
 	nlm_fmn_setup_intr(IRQ_FMN, (1 << nlm_threads_per_core) - 1);
-	nlm_cop2_restore(flags);
+	nlm_cop2_disable_irqrestore(flags);
 }
 
 
@@ -198,7 +198,7 @@ void nlm_setup_fmn_irq(void)
 	/* setup irq only once */
 	setup_irq(IRQ_FMN, &fmn_irqaction);
 
-	flags = nlm_cop2_enable();
+	flags = nlm_cop2_enable_irqsave();
 	nlm_fmn_setup_intr(IRQ_FMN, (1 << nlm_threads_per_core) - 1);
-	nlm_cop2_restore(flags);
+	nlm_cop2_disable_irqrestore(flags);
 }
-- 
1.7.9.5

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

* [PATCH 5/5] MIPS: Netlogic: COP2 save/restore code
  2013-06-10  7:29 [PATCH 0/5 v2] Cop2 save and restore for Netlogic XLP Jayachandran C
                   ` (3 preceding siblings ...)
  2013-06-10  7:30 ` [PATCH 4/5] MIPS: Netlogic: rename nlm_cop2_save/restore Jayachandran C
@ 2013-06-10  7:30 ` Jayachandran C
  4 siblings, 0 replies; 10+ messages in thread
From: Jayachandran C @ 2013-06-10  7:30 UTC (permalink / raw)
  To: linux-mips, ralf, ddaney.cavm; +Cc: Jayachandran C

Add COP2 register state structure and functions for Netlogic XLP. The
RX and TX buffers and status registers are to be saved. Since the
registers are 64-bit, do the implementation in inline assembly which
works on both 32-bit and 64-bit kernels.

Signed-off-by: Jayachandran C <jchandra@broadcom.com>
---
 arch/mips/include/asm/cop2.h      |   10 ++++
 arch/mips/include/asm/processor.h |   13 ++++
 arch/mips/netlogic/xlp/Makefile   |    2 +-
 arch/mips/netlogic/xlp/cop2-ex.c  |  118 +++++++++++++++++++++++++++++++++++++
 4 files changed, 142 insertions(+), 1 deletion(-)
 create mode 100644 arch/mips/netlogic/xlp/cop2-ex.c

diff --git a/arch/mips/include/asm/cop2.h b/arch/mips/include/asm/cop2.h
index b17f38e..c1516cc 100644
--- a/arch/mips/include/asm/cop2.h
+++ b/arch/mips/include/asm/cop2.h
@@ -22,6 +22,16 @@ extern void octeon_cop2_restore(struct octeon_cop2_state *);
 #define cop2_present		1
 #define cop2_lazy_restore	1
 
+#elif defined(CONFIG_CPU_XLP)
+
+extern void nlm_cop2_save(struct nlm_cop2_state *);
+extern void nlm_cop2_restore(struct nlm_cop2_state *);
+#define cop2_save(r)		nlm_cop2_save(r)
+#define cop2_restore(r)		nlm_cop2_restore(r)
+
+#define cop2_present		1
+#define cop2_lazy_restore	0
+
 #else
 
 #define cop2_present		0
diff --git a/arch/mips/include/asm/processor.h b/arch/mips/include/asm/processor.h
index 7c637a4..016dc4b 100644
--- a/arch/mips/include/asm/processor.h
+++ b/arch/mips/include/asm/processor.h
@@ -190,6 +190,16 @@ struct octeon_cvmseg_state {
 			    [cpu_dcache_line_size() / sizeof(unsigned long)];
 };
 
+#elif defined(CONFIG_CPU_XLP)
+struct nlm_cop2_state {
+	u64	rx[4];
+	u64	tx[4];
+	u32	tx_msg_status;
+	u32	rx_msg_status;
+};
+
+#define COP2_INIT						\
+	.cp2			= {{0}, {0}, 0, 0},
 #else
 #define COP2_INIT
 #endif
@@ -237,6 +247,9 @@ struct thread_struct {
     struct octeon_cop2_state cp2 __attribute__ ((__aligned__(128)));
     struct octeon_cvmseg_state cvmseg __attribute__ ((__aligned__(128)));
 #endif
+#ifdef CONFIG_CPU_XLP
+	struct nlm_cop2_state cp2;
+#endif
 	struct mips_abi *abi;
 };
 
diff --git a/arch/mips/netlogic/xlp/Makefile b/arch/mips/netlogic/xlp/Makefile
index a84d6ed..e8dd14c 100644
--- a/arch/mips/netlogic/xlp/Makefile
+++ b/arch/mips/netlogic/xlp/Makefile
@@ -1,3 +1,3 @@
-obj-y				+= setup.o nlm_hal.o
+obj-y				+= setup.o nlm_hal.o cop2-ex.o
 obj-$(CONFIG_SMP)		+= wakeup.o
 obj-$(CONFIG_USB)		+= usb-init.o
diff --git a/arch/mips/netlogic/xlp/cop2-ex.c b/arch/mips/netlogic/xlp/cop2-ex.c
new file mode 100644
index 0000000..52bc5de
--- /dev/null
+++ b/arch/mips/netlogic/xlp/cop2-ex.c
@@ -0,0 +1,118 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2013 Broadcom Corporation.
+ *
+ * based on arch/mips/cavium-octeon/cpu.c
+ * Copyright (C) 2009 Wind River Systems,
+ *   written by Ralf Baechle <ralf@linux-mips.org>
+ */
+#include <linux/init.h>
+#include <linux/irqflags.h>
+#include <linux/notifier.h>
+#include <linux/prefetch.h>
+#include <linux/sched.h>
+
+#include <asm/cop2.h>
+#include <asm/current.h>
+#include <asm/mipsregs.h>
+#include <asm/page.h>
+
+#include <asm/netlogic/mips-extns.h>
+
+/*
+ * 64 bit ops are done in inline assembly to support 32 bit
+ * compilation
+ */
+void nlm_cop2_save(struct nlm_cop2_state *r)
+{
+	asm volatile(
+		".set	push\n"
+		".set	noat\n"
+		"dmfc2	$1, $0, 0\n"
+		"sd	$1, 0(%1)\n"
+		"dmfc2	$1, $0, 1\n"
+		"sd	$1, 8(%1)\n"
+		"dmfc2	$1, $0, 2\n"
+		"sd	$1, 16(%1)\n"
+		"dmfc2	$1, $0, 3\n"
+		"sd	$1, 24(%1)\n"
+		"dmfc2	$1, $1, 0\n"
+		"sd	$1, 0(%2)\n"
+		"dmfc2	$1, $1, 1\n"
+		"sd	$1, 8(%2)\n"
+		"dmfc2	$1, $1, 2\n"
+		"sd	$1, 16(%2)\n"
+		"dmfc2	$1, $1, 3\n"
+		"sd	$1, 24(%2)\n"
+		".set	pop\n"
+		: "=m"(*r)
+		: "r"(r->tx), "r"(r->rx));
+
+	r->tx_msg_status = __read_32bit_c2_register($2, 0);
+	r->rx_msg_status = __read_32bit_c2_register($3, 0) & 0x0fffffff;
+}
+
+void nlm_cop2_restore(struct nlm_cop2_state *r)
+{
+	u32 rstat;
+
+	asm volatile(
+		".set	push\n"
+		".set	noat\n"
+		"ld	$1, 0(%1)\n"
+		"dmtc2	$1, $0, 0\n"
+		"ld	$1, 8(%1)\n"
+		"dmtc2	$1, $0, 1\n"
+		"ld	$1, 16(%1)\n"
+		"dmtc2	$1, $0, 2\n"
+		"ld	$1, 24(%1)\n"
+		"dmtc2	$1, $0, 3\n"
+		"ld	$1, 0(%2)\n"
+		"dmtc2	$1, $1, 0\n"
+		"ld	$1, 8(%2)\n"
+		"dmtc2	$1, $1, 1\n"
+		"ld	$1, 16(%2)\n"
+		"dmtc2	$1, $1, 2\n"
+		"ld	$1, 24(%2)\n"
+		"dmtc2	$1, $1, 3\n"
+		".set	pop\n"
+		: : "m"(*r), "r"(r->tx), "r"(r->rx));
+
+	__write_32bit_c2_register($2, 0, r->tx_msg_status);
+	rstat = __read_32bit_c2_register($3, 0) & 0xf0000000u;
+	__write_32bit_c2_register($3, 0, r->rx_msg_status | rstat);
+}
+
+static int nlm_cu2_call(struct notifier_block *nfb, unsigned long action,
+	void *data)
+{
+	unsigned long flags;
+	unsigned int status;
+
+	switch (action) {
+	case CU2_EXCEPTION:
+		if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO))
+			break;
+		local_irq_save(flags);
+		KSTK_STATUS(current) |= ST0_CU2;
+		status = read_c0_status();
+		write_c0_status(status | ST0_CU2);
+		nlm_cop2_restore(&(current->thread.cp2));
+		write_c0_status(status & ~ST0_CU2);
+		local_irq_restore(flags);
+		pr_info("COP2 access enabled for pid %d (%s)\n",
+					current->pid, current->comm);
+		return NOTIFY_BAD;	/* Don't call default notifier */
+	}
+
+	return NOTIFY_OK;		/* Let default notifier send signals */
+}
+
+static int __init nlm_cu2_setup(void)
+{
+	return cu2_notifier(nlm_cu2_call, 0);
+}
+early_initcall(nlm_cu2_setup);
-- 
1.7.9.5

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

* Re: [PATCH 2/5] MIPS: Allow kernel to use coprocessor 2
  2013-06-10  7:30 ` [PATCH 2/5] MIPS: Allow kernel to use coprocessor 2 Jayachandran C
@ 2013-06-10 11:31   ` Sergei Shtylyov
  2013-06-10 12:42   ` Ralf Baechle
  1 sibling, 0 replies; 10+ messages in thread
From: Sergei Shtylyov @ 2013-06-10 11:31 UTC (permalink / raw)
  To: Jayachandran C; +Cc: linux-mips, ralf, ddaney.cavm

On 10.06.2013 11:30, Jayachandran C wrote:

> Kernel threads should be able to use COP2 if the platform needs it.
> Do not call die_if_kernel() for a coprocessor unusable exception if
> the exception due to COP2 usage.  Instead, the default notifier for
> COP2 exceptions is updated to call die_if_kernel.

> Signed-off-by: Jayachandran C <jchandra@broadcom.com>
> ---
>   arch/mips/kernel/traps.c |   15 +++++----------
>   1 file changed, 5 insertions(+), 10 deletions(-)

> diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
> index beba1e6..142d2be 100644
> --- a/arch/mips/kernel/traps.c
> +++ b/arch/mips/kernel/traps.c
> @@ -1056,15 +1056,9 @@ static int default_cu2_call(struct notifier_block *nfb, unsigned long action,
>   {
>   	struct pt_regs *regs = data;
>
> -	switch (action) {
> -	default:
> -		die_if_kernel("Unhandled kernel unaligned access or invalid "
> +	die_if_kernel("COP2: Unhandled kernel unaligned access or invalid "
>   			      "instruction", regs);

    Do not wrap the message please -- it's useful for grepping. 
checkpatch.pl shouldn't complain about the line length.

WBR, Sergei

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

* Re: [PATCH 2/5] MIPS: Allow kernel to use coprocessor 2
  2013-06-10  7:30 ` [PATCH 2/5] MIPS: Allow kernel to use coprocessor 2 Jayachandran C
  2013-06-10 11:31   ` Sergei Shtylyov
@ 2013-06-10 12:42   ` Ralf Baechle
  2013-06-11  4:12     ` Jayachandran C.
  1 sibling, 1 reply; 10+ messages in thread
From: Ralf Baechle @ 2013-06-10 12:42 UTC (permalink / raw)
  To: Jayachandran C; +Cc: linux-mips, ddaney.cavm

On Mon, Jun 10, 2013 at 01:00:01PM +0530, Jayachandran C wrote:

> Kernel threads should be able to use COP2 if the platform needs it.
> Do not call die_if_kernel() for a coprocessor unusable exception if
> the exception due to COP2 usage.  Instead, the default notifier for
> COP2 exceptions is updated to call die_if_kernel.
> 
> Signed-off-by: Jayachandran C <jchandra@broadcom.com>
> ---
>  arch/mips/kernel/traps.c |   15 +++++----------
>  1 file changed, 5 insertions(+), 10 deletions(-)
> 
> diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
> index beba1e6..142d2be 100644
> --- a/arch/mips/kernel/traps.c
> +++ b/arch/mips/kernel/traps.c
> @@ -1056,15 +1056,9 @@ static int default_cu2_call(struct notifier_block *nfb, unsigned long action,
>  {
>  	struct pt_regs *regs = data;
>  
> -	switch (action) {
> -	default:
> -		die_if_kernel("Unhandled kernel unaligned access or invalid "
> +	die_if_kernel("COP2: Unhandled kernel unaligned access or invalid "
>  			      "instruction", regs);
> -		/* Fall through	 */
> -
> -	case CU2_EXCEPTION:
> -		force_sig(SIGILL, current);
> -	}
> +	force_sig(SIGILL, current);
>  
>  	return NOTIFY_OK;
>  }

The idea for cu2_chain notifiers is that they should return a value with
NOTIFY_STOP_MASK set.  That would prevent further calls to other notifiers.
The default_cu2_call() notifier is installed with the lowest possible
priority and is meant to only be called if there is no other notifier was
installed, that is on a bog standard MIPS core with no CP2.

> @@ -1080,10 +1074,11 @@ asmlinkage void do_cpu(struct pt_regs *regs)
>  	unsigned long __maybe_unused flags;
>  
>  	prev_state = exception_enter();
> -	die_if_kernel("do_cpu invoked from kernel context!", regs);
> -
>  	cpid = (regs->cp0_cause >> CAUSEB_CE) & 3;
>  
> +	if (cpid != 2)
> +		die_if_kernel("do_cpu invoked from kernel context!", regs);
> +
>  	switch (cpid) {
>  	case 0:
>  		epc = (unsigned int __user *)exception_epc(regs);

I'm ok with this segment.

  Ralf

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

* Re: [PATCH 2/5] MIPS: Allow kernel to use coprocessor 2
  2013-06-10 12:42   ` Ralf Baechle
@ 2013-06-11  4:12     ` Jayachandran C.
  0 siblings, 0 replies; 10+ messages in thread
From: Jayachandran C. @ 2013-06-11  4:12 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips, ddaney.cavm

On Mon, Jun 10, 2013 at 02:42:29PM +0200, Ralf Baechle wrote:
> On Mon, Jun 10, 2013 at 01:00:01PM +0530, Jayachandran C wrote:
> 
> > Kernel threads should be able to use COP2 if the platform needs it.
> > Do not call die_if_kernel() for a coprocessor unusable exception if
> > the exception due to COP2 usage.  Instead, the default notifier for
> > COP2 exceptions is updated to call die_if_kernel.
> > 
> > Signed-off-by: Jayachandran C <jchandra@broadcom.com>
> > ---
> >  arch/mips/kernel/traps.c |   15 +++++----------
> >  1 file changed, 5 insertions(+), 10 deletions(-)
> > 
> > diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
> > index beba1e6..142d2be 100644
> > --- a/arch/mips/kernel/traps.c
> > +++ b/arch/mips/kernel/traps.c
> > @@ -1056,15 +1056,9 @@ static int default_cu2_call(struct notifier_block *nfb, unsigned long action,
> >  {
> >  	struct pt_regs *regs = data;
> >  
> > -	switch (action) {
> > -	default:
> > -		die_if_kernel("Unhandled kernel unaligned access or invalid "
> > +	die_if_kernel("COP2: Unhandled kernel unaligned access or invalid "
> >  			      "instruction", regs);
> > -		/* Fall through	 */
> > -
> > -	case CU2_EXCEPTION:
> > -		force_sig(SIGILL, current);
> > -	}
> > +	force_sig(SIGILL, current);
> >  
> >  	return NOTIFY_OK;
> >  }
> 
> The idea for cu2_chain notifiers is that they should return a value with
> NOTIFY_STOP_MASK set.  That would prevent further calls to other notifiers.
> The default_cu2_call() notifier is installed with the lowest possible
> priority and is meant to only be called if there is no other notifier was
> installed, that is on a bog standard MIPS core with no CP2.

I am trying to move the die_if_kernel from do_cpu() to here for COP2
exceptions. In the existing code, COP2 unusable exception calls
die_if_kernel in do_cpu() itself, so COP2 unusable generated by kernel
threads will not make it to the notifiers.  With this change (and the
one below), die_if_kernel() is called only if the all the notifiers
pass it thru.

> 
> > @@ -1080,10 +1074,11 @@ asmlinkage void do_cpu(struct pt_regs *regs)
> >  	unsigned long __maybe_unused flags;
> >  
> >  	prev_state = exception_enter();
> > -	die_if_kernel("do_cpu invoked from kernel context!", regs);
> > -
> >  	cpid = (regs->cp0_cause >> CAUSEB_CE) & 3;
> >  
> > +	if (cpid != 2)
> > +		die_if_kernel("do_cpu invoked from kernel context!", regs);
> > +
> >  	switch (cpid) {
> >  	case 0:
> >  		epc = (unsigned int __user *)exception_epc(regs);
> 
> I'm ok with this segment.
> 
>   Ralf

JC.

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

end of thread, other threads:[~2013-06-11  4:12 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-06-10  7:29 [PATCH 0/5 v2] Cop2 save and restore for Netlogic XLP Jayachandran C
2013-06-10  7:30 ` [PATCH 1/5] MIPS: Move cop2 save/restore to switch_to() Jayachandran C
2013-06-10  7:30 ` [PATCH 2/5] MIPS: Allow kernel to use coprocessor 2 Jayachandran C
2013-06-10 11:31   ` Sergei Shtylyov
2013-06-10 12:42   ` Ralf Baechle
2013-06-11  4:12     ` Jayachandran C.
2013-06-10  7:30 ` [PATCH 3/5] MIPS: Netlogic: Fix nlm_read_c2_status() definition Jayachandran C
2013-06-10  7:30 ` [PATCH 4/5] MIPS: Netlogic: rename nlm_cop2_save/restore Jayachandran C
2013-06-10  7:30 ` [PATCH 5/5] MIPS: Netlogic: COP2 save/restore code Jayachandran C
  -- strict thread matches above, loose matches on Subject: below --
2013-03-22 16:24 [RFC PATCH 0/5] Cop2 save/restore for XLR/XLP Jayachandran C
2013-03-22 16:24 ` [PATCH 2/5] MIPS: Allow kernel to use coprocessor 2 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.