linux-mips
[Top] [All Lists]

[PATCH 4/9] mips: deal with larger physical offsets

To: linux-mips@linux-mips.org, Ralf Baechle <ralf@linux-mips.org>
Subject: [PATCH 4/9] mips: deal with larger physical offsets
From: Florian Fainelli <florian@openwrt.org>
Date: Mon, 1 Jun 2009 13:59:47 +0200
Dkim-signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:received:received:sender:from:date:subject :mime-version:x-uid:x-length:to:content-type :content-transfer-encoding:content-disposition:message-id; bh=3e1lmSTzSVnXkjpU42lXDYthx+baE/MVBgab+7ljVNA=; b=IV8uwDBYeNuTGEOhwnCqs3JRP005atQOCDenx1UuJtXgHUwa3mMVWBxo4gvygapYse XhlWf7FhGVqrPDLcHlOrE8rmgK06aEv4wfgjaLZvpcSr1DQTBRn4DbpDAZ/R4h1H1TOX 3MnyTiN9GtY3sQoYaeku/hgSGWm62NLQfz0rM=
Domainkey-signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=sender:from:date:subject:mime-version:x-uid:x-length:to :content-type:content-transfer-encoding:content-disposition :message-id; b=XmyzMFERWmaGgm4h1ilKn9yM5wU9NUiJT7fjkx6Gmv5OBg8IsNV+UcZt7oWWYmwOaE yCrdaBfwsdKnhgmH5gGuWLJzTGWEk0/stT/KP4bdvw01nur+qbTWMXViS5fKhNAANScZ 3X9DFr6qng5VndFjJDVNyCJpar+85V8f+MPsc=
Original-recipient: rfc822;linux-mips@linux-mips.org
Sender: linux-mips-bounce@linux-mips.org
TI AR7 has larger physical offsets than other MIPS-based
systems. A long jump to the target is required instead of
a short jump like on other systems.

Signed-off-by: Eugene Konev <ejka@imfi.kspu.ru>
Signed-off-by: Florian Fainelli <florian@openwrt.org>
---
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index e83da17..44f7141 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -1256,9 +1256,22 @@ void *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);
+               if ((handler ^ (ebase + 4)) & 0xfc000000) {
+                       /* lui k0, 0x0000 */
+                       *(u32 *)(ebase + 0x200) = 0x3c1a0000 | (handler >> 16);
+                       /* ori k0, 0x0000 */
+                       *(u32 *)(ebase + 0x204) =
+                                       0x375a0000 | (handler & 0xffff);
+                       /* jr k0 */
+                       *(u32 *)(ebase + 0x208) = 0x03400008;
+                       /* nop */
+                       *(u32 *)(ebase + 0x20C) = 0x00000000;
+                       local_flush_icache_range(ebase + 0x200, ebase + 0x210);
+               } else {
+                       *(u32 *)(ebase + 0x200) =
+                               0x08000000 | (0x03ffffff & (handler >> 2));
+                       local_flush_icache_range(ebase + 0x200, ebase + 0x204);
+               }
        }
        return (void *)old_handler;
 }

<Prev in Thread] Current Thread [Next in Thread>