ARM: update FIQ support for relocation of vectors
authorRussell King <rmk+kernel@arm.linux.org.uk>
Tue, 9 Jul 2013 00:03:17 +0000 (01:03 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 12 Aug 2013 01:35:20 +0000 (18:35 -0700)
commit e39e3f3ebfef03450cf7bfa7a974a8c61f7980c8 upstream.

FIQ should no longer copy the FIQ code into the user visible vector
page.  Instead, it should use the hidden page.  This change makes
that happen.

Acked-by: Nicolas Pitre <nico@linaro.org>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
arch/arm/kernel/entry-armv.S
arch/arm/kernel/fiq.c

index 12ac1e3366452c6e7653c077b0360ebed859c5ef..4d938421bb9abead12df9f96b750e209cd7f9ed9 100644 (file)
@@ -1119,6 +1119,9 @@ vector_addrexcptn:
 vector_fiq:
        subs    pc, lr, #4
 
+       .globl  vector_fiq_offset
+       .equ    vector_fiq_offset, vector_fiq
+
        .section .vectors, "ax", %progbits
 __vectors_start:
        W(b)    vector_rst
index 2adda11f712fe02fa2fdaa63e944e17199bd3748..25442f451148ee107ad8db89de891c8ff42b3bc0 100644 (file)
 #include <asm/irq.h>
 #include <asm/traps.h>
 
+#define FIQ_OFFSET ({                                  \
+               extern void *vector_fiq_offset;         \
+               (unsigned)&vector_fiq_offset;           \
+       })
+
 static unsigned long no_fiq_insn;
 
 /* Default reacquire function
@@ -80,13 +85,16 @@ int show_fiq_list(struct seq_file *p, int prec)
 void set_fiq_handler(void *start, unsigned int length)
 {
 #if defined(CONFIG_CPU_USE_DOMAINS)
-       memcpy((void *)0xffff001c, start, length);
+       void *base = (void *)0xffff0000;
 #else
-       memcpy(vectors_page + 0x1c, start, length);
+       void *base = vectors_page;
 #endif
-       flush_icache_range(0xffff001c, 0xffff001c + length);
+       unsigned offset = FIQ_OFFSET;
+
+       memcpy(base + offset, start, length);
+       flush_icache_range(0xffff0000 + offset, 0xffff0000 + offset + length);
        if (!vectors_high())
-               flush_icache_range(0x1c, 0x1c + length);
+               flush_icache_range(offset, offset + length);
 }
 
 int claim_fiq(struct fiq_handler *f)
@@ -144,6 +152,7 @@ EXPORT_SYMBOL(disable_fiq);
 
 void __init init_FIQ(int start)
 {
-       no_fiq_insn = *(unsigned long *)0xffff001c;
+       unsigned offset = FIQ_OFFSET;
+       no_fiq_insn = *(unsigned long *)(0xffff0000 + offset);
        fiq_start = start;
 }