Commit 92bbe1b9 authored by Florian Fainelli's avatar Florian Fainelli Committed by Ralf Baechle

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: default avatarDavid Daney <ddaney@caviumnetworks.com>
Signed-off-by: default avatarEugene Konev <ejka@imfi.kspu.ru>
Signed-off-by: default avatarFlorian 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: default avatarRalf Baechle <ralf@linux-mips.org>
parent 2d1b6e95
...@@ -50,6 +50,7 @@ ...@@ -50,6 +50,7 @@
#include <asm/types.h> #include <asm/types.h>
#include <asm/stacktrace.h> #include <asm/stacktrace.h>
#include <asm/irq.h> #include <asm/irq.h>
#include <asm/uasm.h>
extern void check_wait(void); extern void check_wait(void);
extern asmlinkage void r4k_wait(void); extern asmlinkage void r4k_wait(void);
...@@ -1271,11 +1272,6 @@ unsigned long ebase; ...@@ -1271,11 +1272,6 @@ unsigned long ebase;
unsigned long exception_handlers[32]; unsigned long exception_handlers[32];
unsigned long vi_handlers[64]; 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) void __init *set_except_vector(int n, void *addr)
{ {
unsigned long handler = (unsigned long) addr; unsigned long handler = (unsigned long) addr;
...@@ -1283,9 +1279,18 @@ void __init *set_except_vector(int n, void *addr) ...@@ -1283,9 +1279,18 @@ void __init *set_except_vector(int n, void *addr)
exception_handlers[n] = handler; exception_handlers[n] = handler;
if (n == 0 && cpu_has_divec) { if (n == 0 && cpu_has_divec) {
*(u32 *)(ebase + 0x200) = 0x08000000 | unsigned long jump_mask = ~((1 << 28) - 1);
(0x03ffffff & (handler >> 2)); u32 *buf = (u32 *)(ebase + 0x200);
local_flush_icache_range(ebase + 0x200, ebase + 0x204); 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; return (void *)old_handler;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment