Skip to contentSkip to conversation

MIPS: deal with larger physical offsets

PATCH In review Florian Fainelli 4 participants 5 messages Jan 28, 2010 – Jan 30, 2010 MIPS

lore
Share & tools
lore
#0 lore raw

PATCH 3/3 MIPS: deal with larger physical offsets

AR7 has a larger physical offset than other MIPS based systems and therefore needs to setup its handlers beyond the usual KSEG0 range. When running the kernel in mapped mode this modification is also required. Remove function comment which is now incorrect.

---

arch/mips/kernel/traps.c +13 -8
index 574608e..14d515f 100644
@@ -50,6 +50,7 @@
 #include <asm/types.h>
 #include <asm/stacktrace.h>
 #include <asm/irq.h>
+#include <asm/uasm.h>
 
 extern void check_wait(void);
 extern asmlinkage void r4k_wait(void);
@@ -1271,11 +1272,6 @@ unsigned long ebase;
 unsigned long exception_handlers[32];
 unsigned long vi_handlers[64];
 
-/*
- * As a side effect of the way this is implemented we're limited
- * to interrupt handlers in the address range from
- * KSEG0 <= x < KSEG0 + 256mb on the Nevada.  Oh well ...
- */
 void __init *set_except_vector(int n, void *addr)
 {
 	unsigned long handler = (unsigned long) addr;
@@ -1283,9 +1279,18 @@ void __init *set_except_vector(int n, void *addr)
 
 	exception_handlers[n] = handler;
 	if (n == 0 && cpu_has_divec) {
-		*(u32 *)(ebase + 0x200) = 0x08000000 |
-					  (0x03ffffff & (handler >> 2));
-		local_flush_icache_range(ebase + 0x200, ebase + 0x204);
+		unsigned long jump_mask = ~((1 << 28) - 1);
+		u32 *buf = (u32 *)(ebase + 0x200);
+		unsigned int k0 = 26;
+		if((handler & jump_mask) == ((ebase + 0x200) & jump_mask)) {
+			uasm_i_j(&buf, handler & jump_mask);
+			uasm_i_nop(&buf);
+		} else {
+			UASM_i_LA(&buf, k0, handler);
+			uasm_i_jr(&buf, k0);
+			uasm_i_nop(&buf);
+		}
+		local_flush_icache_range(ebase + 0x200, (unsigned long)buf);
 	}
 	return (void *)old_handler;
 }
#1 lore raw

On Thu, Jan 28, 2010 at 03:22:37PM +0100, Florian Fainelli wrote:

Thanks, queued for 2.6.34.

Ral

#2 lore raw
In reply to Florian Fainelli

arch/mips/kernel/traps.c

Quoted 14 lines · Florian Fainelli

AR7 has a larger physical offset than other MIPS based systems and therefore needs to setup its handlers beyond the usual KSEG0 range. When running the kernel in mapped mode this modification is also required. Remove function comment which is now incorrect.

---

arch/mips/kernel/traps.c +0 -0
index 574608e..14d515f 100644

...]

arch/mips/kernel/traps.c void __init *set_except_vector(int n, void *addr) · line 1286

Quoted 12 lines
arch/mips/kernel/traps.c +4 -3
@@ -1283,9 +1279,18 @@ void __init *set_except_vector(int n, void *addr)
 
 	exception_handlers[n] = handler;
 	if (n == 0 && cpu_has_divec) {
-		*(u32 *)(ebase + 0x200) = 0x08000000 |
-					  (0x03ffffff & (handler >> 2));
-		local_flush_icache_range(ebase + 0x200, ebase + 0x204);
+		unsigned long jump_mask = ~((1 << 28) - 1);
+		u32 *buf = (u32 *)(ebase + 0x200);
+		unsigned int k0 = 26;
+		if((handler & jump_mask) == ((ebase + 0x200) & jump_mask)) {
 

Missing space after *if* (should be easy for Ralf to fix manually
though). You should run the patch thru scripts/checkpatch.pl first.

WBR, Sergei

#3 lore raw
Quoted 16 lines · Sergei Shtylyov

arch/mips/kernel/traps.c

Quoted 14 lines · Florian Fainelli

AR7 has a larger physical offset than other MIPS based systems and therefore needs to setup its handlers beyond the usual KSEG0 range. When running the kernel in mapped mode this modification is also required. Remove function comment which is now incorrect.

---

arch/mips/kernel/traps.c +0 -0
index 574608e..14d515f 100644

...]

Quoted 13 lines

arch/mips/kernel/traps.c void __init *set_except_vector(int n, void *addr) · line 1284

Quoted 10 lines
arch/mips/kernel/traps.c +4 -3
@@ -1283,9 +1279,18 @@ void __init *set_except_vector(int n, void *addr)
 	exception_handlers[n] = handler;
 	if (n == 0 && cpu_has_divec) {
-		*(u32 *)(ebase + 0x200) = 0x08000000 |
-					  (0x03ffffff & (handler >> 2));
-		local_flush_icache_range(ebase + 0x200, ebase + 0x204);
+		unsigned long jump_mask = ~((1 << 28) - 1);
+		u32 *buf = (u32 *)(ebase + 0x200);
+		unsigned int k0 = 26;
+		if((handler & jump_mask) == ((ebase + 0x200) & jump_mask)) {

Missing space after *if* (should be easy for Ralf to fix manually
though). You should run the patch thru scripts/checkpatch.pl first.

Just did that. Thanks for nitpicking :-)

Ralf

#4 lore raw
In reply to Florian Fainelli

On Thu, 2010-01-28 at 15:22 +0100, Florian Fainelli wrote:

Hi,

arch/mips/kernel/traps.c void __init *set_except_vector(int n, void *addr) · line 1287

Quoted 10 lines
arch/mips/kernel/traps.c +6 -3
 	if (n == 0 && cpu_has_divec) {
-		*(u32 *)(ebase + 0x200) = 0x08000000 |
-					  (0x03ffffff & (handler >> 2));
-		local_flush_icache_range(ebase + 0x200, ebase + 0x204);
+		unsigned long jump_mask = ~((1 << 28) - 1);
+		u32 *buf = (u32 *)(ebase + 0x200);
+		unsigned int k0 = 26;
+		if((handler & jump_mask) == ((ebase + 0x200) & jump_mask)) {
+			uasm_i_j(&buf, handler & jump_mask);
+			uasm_i_nop(&buf);

This results in "Micro-assembler field overflow" on my board.

jump_mask is 0xf0000000, so I guess you meant:

- uasm_i_j(&buf, handler & jump_mask);
+ uasm_i_j(&buf, handler & ~jump_mask);

And by the way, shouldn't jump_mask be 0xfc000000 ?

Signature · 1 line
Maxime