All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/3] A bunch of RDHWR emulation bug fixes
@ 2016-01-30  9:08 ` Maciej W. Rozycki
  0 siblings, 0 replies; 8+ messages in thread
From: Maciej W. Rozycki @ 2016-01-30  9:08 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips

Ralf,

 As I investigated legacy SYNC support I came across a number of issues 
with RDHWR emulation, located nearby.  This mini patch set addresses these 
problems, please apply.  As these are bug fixes I think there is no need 
to wait for the next rc1 stage.

  Maciej

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

* [PATCH 0/3] A bunch of RDHWR emulation bug fixes
@ 2016-01-30  9:08 ` Maciej W. Rozycki
  0 siblings, 0 replies; 8+ messages in thread
From: Maciej W. Rozycki @ 2016-01-30  9:08 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips

Ralf,

 As I investigated legacy SYNC support I came across a number of issues 
with RDHWR emulation, located nearby.  This mini patch set addresses these 
problems, please apply.  As these are bug fixes I think there is no need 
to wait for the next rc1 stage.

  Maciej

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

* [PATCH 1/3] MIPS: traps.c: Don't emulate RDHWR in the CpU #0 exception handler
@ 2016-01-30  9:08   ` Maciej W. Rozycki
  0 siblings, 0 replies; 8+ messages in thread
From: Maciej W. Rozycki @ 2016-01-30  9:08 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips

In the regular MIPS instruction set RDHWR is encoded with the SPECIAL3 
(011111) major opcode.  Therefore it cannot trigger the CpU (Coprocessor 
Unusable) exception, and certainly not for coprocessor 0, as the opcode 
does not overlap with any of the older ISA reservations, i.e. LWC0 
(110000), SWC0 (111000), LDC0 (110100) or SDC0 (111100).  The closest 
match might be SDC3 (111111), possibly causing a CpU #3 exception, 
however our code does not handle it anyway.  A quick check with a MIPS I 
and a MIPS III processor:

CPU0 revision is: 00000220 (R3000)
CPU0 revision is: 00000440 (R4400SC)

indeed indicates that the RI (Reserved Instruction) exception is 
triggered.  It's only LL and SC that require emulation in the CpU #0 
exception handler as they reuse the LWC0 and SWC0 opcodes respectively.

In the microMIPS instruction set RDHWR is mandatory and triggering the 
RI exception is required on unimplemented or disabled register accesses.  
Therefore emulating the microMIPS instruction in the CpU #0 exception 
handler is not required either.

Signed-off-by: Maciej W. Rozycki <macro@imgtec.com>
---
linux-mips-rdhwr-do-cpu.diff
Index: linux-sfr-test/arch/mips/kernel/traps.c
===================================================================
--- linux-sfr-test.orig/arch/mips/kernel/traps.c	2016-01-30 03:44:50.567566000 +0000
+++ linux-sfr-test/arch/mips/kernel/traps.c	2016-01-30 03:48:33.611317000 +0000
@@ -1369,26 +1369,12 @@ asmlinkage void do_cpu(struct pt_regs *r
 		if (unlikely(compute_return_epc(regs) < 0))
 			break;
 
-		if (get_isa16_mode(regs->cp0_epc)) {
-			unsigned short mmop[2] = { 0 };
-
-			if (unlikely(get_user(mmop[0], epc) < 0))
-				status = SIGSEGV;
-			if (unlikely(get_user(mmop[1], epc) < 0))
-				status = SIGSEGV;
-			opcode = (mmop[0] << 16) | mmop[1];
-
-			if (status < 0)
-				status = simulate_rdhwr_mm(regs, opcode);
-		} else {
+		if (!get_isa16_mode(regs->cp0_epc)) {
 			if (unlikely(get_user(opcode, epc) < 0))
 				status = SIGSEGV;
 
 			if (!cpu_has_llsc && status < 0)
 				status = simulate_llsc(regs, opcode);
-
-			if (status < 0)
-				status = simulate_rdhwr_normal(regs, opcode);
 		}
 
 		if (status < 0)

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

* [PATCH 1/3] MIPS: traps.c: Don't emulate RDHWR in the CpU #0 exception handler
@ 2016-01-30  9:08   ` Maciej W. Rozycki
  0 siblings, 0 replies; 8+ messages in thread
From: Maciej W. Rozycki @ 2016-01-30  9:08 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips

In the regular MIPS instruction set RDHWR is encoded with the SPECIAL3 
(011111) major opcode.  Therefore it cannot trigger the CpU (Coprocessor 
Unusable) exception, and certainly not for coprocessor 0, as the opcode 
does not overlap with any of the older ISA reservations, i.e. LWC0 
(110000), SWC0 (111000), LDC0 (110100) or SDC0 (111100).  The closest 
match might be SDC3 (111111), possibly causing a CpU #3 exception, 
however our code does not handle it anyway.  A quick check with a MIPS I 
and a MIPS III processor:

CPU0 revision is: 00000220 (R3000)
CPU0 revision is: 00000440 (R4400SC)

indeed indicates that the RI (Reserved Instruction) exception is 
triggered.  It's only LL and SC that require emulation in the CpU #0 
exception handler as they reuse the LWC0 and SWC0 opcodes respectively.

In the microMIPS instruction set RDHWR is mandatory and triggering the 
RI exception is required on unimplemented or disabled register accesses.  
Therefore emulating the microMIPS instruction in the CpU #0 exception 
handler is not required either.

Signed-off-by: Maciej W. Rozycki <macro@imgtec.com>
---
linux-mips-rdhwr-do-cpu.diff
Index: linux-sfr-test/arch/mips/kernel/traps.c
===================================================================
--- linux-sfr-test.orig/arch/mips/kernel/traps.c	2016-01-30 03:44:50.567566000 +0000
+++ linux-sfr-test/arch/mips/kernel/traps.c	2016-01-30 03:48:33.611317000 +0000
@@ -1369,26 +1369,12 @@ asmlinkage void do_cpu(struct pt_regs *r
 		if (unlikely(compute_return_epc(regs) < 0))
 			break;
 
-		if (get_isa16_mode(regs->cp0_epc)) {
-			unsigned short mmop[2] = { 0 };
-
-			if (unlikely(get_user(mmop[0], epc) < 0))
-				status = SIGSEGV;
-			if (unlikely(get_user(mmop[1], epc) < 0))
-				status = SIGSEGV;
-			opcode = (mmop[0] << 16) | mmop[1];
-
-			if (status < 0)
-				status = simulate_rdhwr_mm(regs, opcode);
-		} else {
+		if (!get_isa16_mode(regs->cp0_epc)) {
 			if (unlikely(get_user(opcode, epc) < 0))
 				status = SIGSEGV;
 
 			if (!cpu_has_llsc && status < 0)
 				status = simulate_llsc(regs, opcode);
-
-			if (status < 0)
-				status = simulate_rdhwr_normal(regs, opcode);
 		}
 
 		if (status < 0)

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

* [PATCH 2/3] MIPS: traps.c: Correct microMIPS RDHWR emulation
@ 2016-01-30  9:08   ` Maciej W. Rozycki
  0 siblings, 0 replies; 8+ messages in thread
From: Maciej W. Rozycki @ 2016-01-30  9:08 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips

Fix the code to fetch and decode the whole 32-bit instruction.  This 
only really matters with the `noulri' kernel parameter as all microMIPS 
processors are supposed to have all the hardware registers we support.

Signed-off-by: Maciej W. Rozycki <macro@imgtec.com>
---
linux-umips-rdhwr-opcode.diff
Index: linux-sfr-test/arch/mips/kernel/traps.c
===================================================================
--- linux-sfr-test.orig/arch/mips/kernel/traps.c	2016-01-30 03:39:20.000000000 +0000
+++ linux-sfr-test/arch/mips/kernel/traps.c	2016-01-30 03:40:58.944753000 +0000
@@ -663,7 +663,7 @@ static int simulate_rdhwr_normal(struct 
 	return -1;
 }
 
-static int simulate_rdhwr_mm(struct pt_regs *regs, unsigned short opcode)
+static int simulate_rdhwr_mm(struct pt_regs *regs, unsigned int opcode)
 {
 	if ((opcode & MM_POOL32A_FUNC) == MM_RDHWR) {
 		int rd = (opcode & MM_RS) >> 16;
@@ -1119,11 +1119,12 @@ asmlinkage void do_ri(struct pt_regs *re
 	if (get_isa16_mode(regs->cp0_epc)) {
 		unsigned short mmop[2] = { 0 };
 
-		if (unlikely(get_user(mmop[0], epc) < 0))
+		if (unlikely(get_user(mmop[0], (u16 __user *)epc + 0) < 0))
 			status = SIGSEGV;
-		if (unlikely(get_user(mmop[1], epc) < 0))
+		if (unlikely(get_user(mmop[1], (u16 __user *)epc + 1) < 0))
 			status = SIGSEGV;
-		opcode = (mmop[0] << 16) | mmop[1];
+		opcode = mmop[0];
+		opcode = (opcode << 16) | mmop[1];
 
 		if (status < 0)
 			status = simulate_rdhwr_mm(regs, opcode);

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

* [PATCH 2/3] MIPS: traps.c: Correct microMIPS RDHWR emulation
@ 2016-01-30  9:08   ` Maciej W. Rozycki
  0 siblings, 0 replies; 8+ messages in thread
From: Maciej W. Rozycki @ 2016-01-30  9:08 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips

Fix the code to fetch and decode the whole 32-bit instruction.  This 
only really matters with the `noulri' kernel parameter as all microMIPS 
processors are supposed to have all the hardware registers we support.

Signed-off-by: Maciej W. Rozycki <macro@imgtec.com>
---
linux-umips-rdhwr-opcode.diff
Index: linux-sfr-test/arch/mips/kernel/traps.c
===================================================================
--- linux-sfr-test.orig/arch/mips/kernel/traps.c	2016-01-30 03:39:20.000000000 +0000
+++ linux-sfr-test/arch/mips/kernel/traps.c	2016-01-30 03:40:58.944753000 +0000
@@ -663,7 +663,7 @@ static int simulate_rdhwr_normal(struct 
 	return -1;
 }
 
-static int simulate_rdhwr_mm(struct pt_regs *regs, unsigned short opcode)
+static int simulate_rdhwr_mm(struct pt_regs *regs, unsigned int opcode)
 {
 	if ((opcode & MM_POOL32A_FUNC) == MM_RDHWR) {
 		int rd = (opcode & MM_RS) >> 16;
@@ -1119,11 +1119,12 @@ asmlinkage void do_ri(struct pt_regs *re
 	if (get_isa16_mode(regs->cp0_epc)) {
 		unsigned short mmop[2] = { 0 };
 
-		if (unlikely(get_user(mmop[0], epc) < 0))
+		if (unlikely(get_user(mmop[0], (u16 __user *)epc + 0) < 0))
 			status = SIGSEGV;
-		if (unlikely(get_user(mmop[1], epc) < 0))
+		if (unlikely(get_user(mmop[1], (u16 __user *)epc + 1) < 0))
 			status = SIGSEGV;
-		opcode = (mmop[0] << 16) | mmop[1];
+		opcode = mmop[0];
+		opcode = (opcode << 16) | mmop[1];
 
 		if (status < 0)
 			status = simulate_rdhwr_mm(regs, opcode);

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

* [PATCH 3/3] MIPS: traps.c: Verify the ISA for microMIPS RDHWR emulation
@ 2016-01-30  9:08   ` Maciej W. Rozycki
  0 siblings, 0 replies; 8+ messages in thread
From: Maciej W. Rozycki @ 2016-01-30  9:08 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips

Make sure it's the microMIPS rather than MIPS16 ISA before emulating 
microMIPS RDHWR.  Mostly needed as an optimisation for configurations 
where `cpu_has_mmips' is hardcoded to 0 and also a good measure in case 
we add further microMIPS instructions to emulate in the future, as the 
corresponding MIPS16 encoding is ADDIUSP, not supposed to trap.

Signed-off-by: Maciej W. Rozycki <macro@imgtec.com>
---
linux-umips-rdhwr-isa.diff
Index: linux-sfr-test/arch/mips/kernel/traps.c
===================================================================
--- linux-sfr-test.orig/arch/mips/kernel/traps.c	2016-01-30 03:42:36.000000000 +0000
+++ linux-sfr-test/arch/mips/kernel/traps.c	2016-01-30 03:42:14.980343000 +0000
@@ -1116,19 +1116,7 @@ asmlinkage void do_ri(struct pt_regs *re
 	if (unlikely(compute_return_epc(regs) < 0))
 		goto out;
 
-	if (get_isa16_mode(regs->cp0_epc)) {
-		unsigned short mmop[2] = { 0 };
-
-		if (unlikely(get_user(mmop[0], (u16 __user *)epc + 0) < 0))
-			status = SIGSEGV;
-		if (unlikely(get_user(mmop[1], (u16 __user *)epc + 1) < 0))
-			status = SIGSEGV;
-		opcode = mmop[0];
-		opcode = (opcode << 16) | mmop[1];
-
-		if (status < 0)
-			status = simulate_rdhwr_mm(regs, opcode);
-	} else {
+	if (!get_isa16_mode(regs->cp0_epc)) {
 		if (unlikely(get_user(opcode, epc) < 0))
 			status = SIGSEGV;
 
@@ -1143,6 +1131,18 @@ asmlinkage void do_ri(struct pt_regs *re
 
 		if (status < 0)
 			status = simulate_fp(regs, opcode, old_epc, old31);
+	} else if (cpu_has_mmips) {
+		unsigned short mmop[2] = { 0 };
+
+		if (unlikely(get_user(mmop[0], (u16 __user *)epc + 0) < 0))
+			status = SIGSEGV;
+		if (unlikely(get_user(mmop[1], (u16 __user *)epc + 1) < 0))
+			status = SIGSEGV;
+		opcode = mmop[0];
+		opcode = (opcode << 16) | mmop[1];
+
+		if (status < 0)
+			status = simulate_rdhwr_mm(regs, opcode);
 	}
 
 	if (status < 0)

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

* [PATCH 3/3] MIPS: traps.c: Verify the ISA for microMIPS RDHWR emulation
@ 2016-01-30  9:08   ` Maciej W. Rozycki
  0 siblings, 0 replies; 8+ messages in thread
From: Maciej W. Rozycki @ 2016-01-30  9:08 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips

Make sure it's the microMIPS rather than MIPS16 ISA before emulating 
microMIPS RDHWR.  Mostly needed as an optimisation for configurations 
where `cpu_has_mmips' is hardcoded to 0 and also a good measure in case 
we add further microMIPS instructions to emulate in the future, as the 
corresponding MIPS16 encoding is ADDIUSP, not supposed to trap.

Signed-off-by: Maciej W. Rozycki <macro@imgtec.com>
---
linux-umips-rdhwr-isa.diff
Index: linux-sfr-test/arch/mips/kernel/traps.c
===================================================================
--- linux-sfr-test.orig/arch/mips/kernel/traps.c	2016-01-30 03:42:36.000000000 +0000
+++ linux-sfr-test/arch/mips/kernel/traps.c	2016-01-30 03:42:14.980343000 +0000
@@ -1116,19 +1116,7 @@ asmlinkage void do_ri(struct pt_regs *re
 	if (unlikely(compute_return_epc(regs) < 0))
 		goto out;
 
-	if (get_isa16_mode(regs->cp0_epc)) {
-		unsigned short mmop[2] = { 0 };
-
-		if (unlikely(get_user(mmop[0], (u16 __user *)epc + 0) < 0))
-			status = SIGSEGV;
-		if (unlikely(get_user(mmop[1], (u16 __user *)epc + 1) < 0))
-			status = SIGSEGV;
-		opcode = mmop[0];
-		opcode = (opcode << 16) | mmop[1];
-
-		if (status < 0)
-			status = simulate_rdhwr_mm(regs, opcode);
-	} else {
+	if (!get_isa16_mode(regs->cp0_epc)) {
 		if (unlikely(get_user(opcode, epc) < 0))
 			status = SIGSEGV;
 
@@ -1143,6 +1131,18 @@ asmlinkage void do_ri(struct pt_regs *re
 
 		if (status < 0)
 			status = simulate_fp(regs, opcode, old_epc, old31);
+	} else if (cpu_has_mmips) {
+		unsigned short mmop[2] = { 0 };
+
+		if (unlikely(get_user(mmop[0], (u16 __user *)epc + 0) < 0))
+			status = SIGSEGV;
+		if (unlikely(get_user(mmop[1], (u16 __user *)epc + 1) < 0))
+			status = SIGSEGV;
+		opcode = mmop[0];
+		opcode = (opcode << 16) | mmop[1];
+
+		if (status < 0)
+			status = simulate_rdhwr_mm(regs, opcode);
 	}
 
 	if (status < 0)

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

end of thread, other threads:[~2016-01-30  9:09 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-01-30  9:08 [PATCH 0/3] A bunch of RDHWR emulation bug fixes Maciej W. Rozycki
2016-01-30  9:08 ` Maciej W. Rozycki
2016-01-30  9:08 ` [PATCH 1/3] MIPS: traps.c: Don't emulate RDHWR in the CpU #0 exception handler Maciej W. Rozycki
2016-01-30  9:08   ` Maciej W. Rozycki
2016-01-30  9:08 ` [PATCH 2/3] MIPS: traps.c: Correct microMIPS RDHWR emulation Maciej W. Rozycki
2016-01-30  9:08   ` Maciej W. Rozycki
2016-01-30  9:08 ` [PATCH 3/3] MIPS: traps.c: Verify the ISA for " Maciej W. Rozycki
2016-01-30  9:08   ` Maciej W. Rozycki

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.