aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/kernel/traps.c
diff options
context:
space:
mode:
authorFlorian Fainelli <florian@openwrt.org>2010-01-28 09:22:37 -0500
committerRalf Baechle <ralf@linux-mips.org>2010-02-27 06:53:19 -0500
commit92bbe1b988d3d6fa6348e3e376ff6d27e0712147 (patch)
tree71ab0d2cad91210a98b4c4b1a72598125ec0d100 /arch/mips/kernel/traps.c
parent2d1b6e95515d63030b6e002125799f2aa52a9d27 (diff)
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. Signed-off-by: David Daney <ddaney@caviumnetworks.com> Signed-off-by: Eugene Konev <ejka@imfi.kspu.ru> Signed-off-by: Florian Fainelli <florian@openwrt.org> To: linux-mips@linux-mips.org To: Thomas Bogendoerfer <tsbogend@alpha.franken.de> Cc: linux-mips@linux-mips.org Patchwork: http://patchwork.linux-mips.org/patch/889/ Patchwork: http://patchwork.linux-mips.org/patch/932/ Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch/mips/kernel/traps.c')
-rw-r--r--arch/mips/kernel/traps.c21
1 files changed, 13 insertions, 8 deletions
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index b417e2727050..4e00f9bc23ee 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -50,6 +50,7 @@
50#include <asm/types.h> 50#include <asm/types.h>
51#include <asm/stacktrace.h> 51#include <asm/stacktrace.h>
52#include <asm/irq.h> 52#include <asm/irq.h>
53#include <asm/uasm.h>
53 54
54extern void check_wait(void); 55extern void check_wait(void);
55extern asmlinkage void r4k_wait(void); 56extern asmlinkage void r4k_wait(void);
@@ -1271,11 +1272,6 @@ unsigned long ebase;
1271unsigned long exception_handlers[32]; 1272unsigned long exception_handlers[32];
1272unsigned long vi_handlers[64]; 1273unsigned long vi_handlers[64];
1273 1274
1274/*
1275 * As a side effect of the way this is implemented we're limited
1276 * to interrupt handlers in the address range from
1277 * KSEG0 <= x < KSEG0 + 256mb on the Nevada. Oh well ...
1278 */
1279void __init *set_except_vector(int n, void *addr) 1275void __init *set_except_vector(int n, void *addr)
1280{ 1276{
1281 unsigned long handler = (unsigned long) addr; 1277 unsigned long handler = (unsigned long) addr;
@@ -1283,9 +1279,18 @@ void __init *set_except_vector(int n, void *addr)
1283 1279
1284 exception_handlers[n] = handler; 1280 exception_handlers[n] = handler;
1285 if (n == 0 && cpu_has_divec) { 1281 if (n == 0 && cpu_has_divec) {
1286 *(u32 *)(ebase + 0x200) = 0x08000000 | 1282 unsigned long jump_mask = ~((1 << 28) - 1);
1287 (0x03ffffff & (handler >> 2)); 1283 u32 *buf = (u32 *)(ebase + 0x200);
1288 local_flush_icache_range(ebase + 0x200, ebase + 0x204); 1284 unsigned int k0 = 26;
1285 if ((handler & jump_mask) == ((ebase + 0x200) & jump_mask)) {
1286 uasm_i_j(&buf, handler & ~jump_mask);
1287 uasm_i_nop(&buf);
1288 } else {
1289 UASM_i_LA(&buf, k0, handler);
1290 uasm_i_jr(&buf, k0);
1291 uasm_i_nop(&buf);
1292 }
1293 local_flush_icache_range(ebase + 0x200, (unsigned long)buf);
1289 } 1294 }
1290 return (void *)old_handler; 1295 return (void *)old_handler;
1291} 1296}