vserver 1.9.5.x5
[linux-2.6.git] / arch / arm / kernel / fiq.c
index 6f79381..a45c787 100644 (file)
 #include <asm/system.h>
 #include <asm/uaccess.h>
 
-#define FIQ_VECTOR (vectors_base() + 0x1c)
+#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
+#warning This file requires GCC 3.3.x or older to build.  Alternatively,
+#warning please talk to GCC people to resolve the issues with the
+#warning assembly clobber list.
+#endif
 
 static unsigned long no_fiq_insn;
 
-static inline void unprotect_page_0(void)
-{
-       modify_domain(DOMAIN_USER, DOMAIN_MANAGER);
-}
-
-static inline void protect_page_0(void)
-{
-       modify_domain(DOMAIN_USER, DOMAIN_CLIENT);
-}
-
 /* Default reacquire function
  * - we always relinquish FIQ control
  * - we always reacquire FIQ control
  */
 static int fiq_def_op(void *ref, int relinquish)
 {
-       if (!relinquish) {
-               unprotect_page_0();
-               *(unsigned long *)FIQ_VECTOR = no_fiq_insn;
-               protect_page_0();
-               flush_icache_range(FIQ_VECTOR, FIQ_VECTOR + 4);
-       }
+       if (!relinquish)
+               set_fiq_handler(&no_fiq_insn, sizeof(no_fiq_insn));
 
        return 0;
 }
@@ -93,12 +83,10 @@ int show_fiq_list(struct seq_file *p, void *v)
 
 void set_fiq_handler(void *start, unsigned int length)
 {
-       unprotect_page_0();
-
-       memcpy((void *)FIQ_VECTOR, start, length);
-
-       protect_page_0();
-       flush_icache_range(FIQ_VECTOR, FIQ_VECTOR + length);
+       memcpy((void *)0xffff001c, start, length);
+       flush_icache_range(0xffff001c, 0xffff001c + length);
+       if (!vectors_high())
+               flush_icache_range(0x1c, 0x1c + length);
 }
 
 /*
@@ -107,16 +95,15 @@ void set_fiq_handler(void *start, unsigned int length)
  */
 void set_fiq_regs(struct pt_regs *regs)
 {
-       register unsigned long tmp, tmp2;
+       register unsigned long tmp;
        __asm__ volatile (
        "mrs    %0, cpsr\n\
-       mov     %1, %3\n\
-       msr     cpsr_c, %1      @ select FIQ mode\n\
+       msr     cpsr_c, %2      @ select FIQ mode\n\
        mov     r0, r0\n\
-       ldmia   %2, {r8 - r14}\n\
+       ldmia   %1, {r8 - r14}\n\
        msr     cpsr_c, %0      @ return to SVC mode\n\
        mov     r0, r0"
-       : "=&r" (tmp), "=&r" (tmp2)
+       : "=&r" (tmp)
        : "r" (&regs->ARM_r8), "I" (PSR_I_BIT | PSR_F_BIT | FIQ_MODE)
        /* These registers aren't modified by the above code in a way
           visible to the compiler, but we mark them as clobbers anyway
@@ -127,16 +114,15 @@ void set_fiq_regs(struct pt_regs *regs)
 
 void get_fiq_regs(struct pt_regs *regs)
 {
-       register unsigned long tmp, tmp2;
+       register unsigned long tmp;
        __asm__ volatile (
        "mrs    %0, cpsr\n\
-       mov     %1, %3\n\
-       msr     cpsr_c, %1      @ select FIQ mode\n\
+       msr     cpsr_c, %2      @ select FIQ mode\n\
        mov     r0, r0\n\
-       stmia   %2, {r8 - r14}\n\
+       stmia   %1, {r8 - r14}\n\
        msr     cpsr_c, %0      @ return to SVC mode\n\
        mov     r0, r0"
-       : "=&r" (tmp), "=&r" (tmp2)
+       : "=&r" (tmp)
        : "r" (&regs->ARM_r8), "I" (PSR_I_BIT | PSR_F_BIT | FIQ_MODE)
        /* These registers aren't modified by the above code in a way
           visible to the compiler, but we mark them as clobbers anyway
@@ -198,6 +184,5 @@ EXPORT_SYMBOL(disable_fiq);
 
 void __init init_FIQ(void)
 {
-       no_fiq_insn = *(unsigned long *)FIQ_VECTOR;
-       set_fs(get_fs());
+       no_fiq_insn = *(unsigned long *)0xffff001c;
 }