]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - arch/powerpc/kernel/signal_32.c
powerpc: Introduce VSX thread_struct and CONFIG_VSX
[linux-2.6-omap-h63xx.git] / arch / powerpc / kernel / signal_32.c
index b057e6852a7d0a5fd611e76ba66252195b6fffb8..f7fa395b9fb5da1d18446895d6bb111f7a17de73 100644 (file)
@@ -337,14 +337,16 @@ static int save_user_regs(struct pt_regs *regs, struct mcontext __user *frame,
                int sigret)
 {
        unsigned long msr = regs->msr;
+#ifdef CONFIG_VSX
+       double buf[32];
+       int i;
+#endif
 
        /* Make sure floating point registers are stored in regs */
        flush_fp_to_thread(current);
 
-       /* save general and floating-point registers */
-       if (save_general_regs(regs, frame) ||
-           __copy_to_user(&frame->mc_fregs, current->thread.fpr,
-                   ELF_NFPREG * sizeof(double)))
+       /* save general registers */
+       if (save_general_regs(regs, frame))
                return 1;
 
 #ifdef CONFIG_ALTIVEC
@@ -368,7 +370,20 @@ static int save_user_regs(struct pt_regs *regs, struct mcontext __user *frame,
        if (__put_user(current->thread.vrsave, (u32 __user *)&frame->mc_vregs[32]))
                return 1;
 #endif /* CONFIG_ALTIVEC */
-
+#ifdef CONFIG_VSX
+       /* save FPR copy to local buffer then write to the thread_struct */
+       flush_fp_to_thread(current);
+       for (i = 0; i < 32 ; i++)
+               buf[i] = current->thread.TS_FPR(i);
+       memcpy(&buf[i], &current->thread.fpscr, sizeof(double));
+       if (__copy_to_user(&frame->mc_fregs, buf, ELF_NFPREG * sizeof(double)))
+               return 1;
+#else
+       /* save floating-point registers */
+       if (__copy_to_user(&frame->mc_fregs, current->thread.fpr,
+                   ELF_NFPREG * sizeof(double)))
+               return 1;
+#endif /* CONFIG_VSX */
 #ifdef CONFIG_SPE
        /* save spe registers */
        if (current->thread.used_spe) {
@@ -411,6 +426,10 @@ static long restore_user_regs(struct pt_regs *regs,
        long err;
        unsigned int save_r2 = 0;
        unsigned long msr;
+#ifdef CONFIG_VSX
+       double buf[32];
+       int i;
+#endif
 
        /*
         * restore general registers but not including MSR or SOFTE. Also
@@ -438,16 +457,11 @@ static long restore_user_regs(struct pt_regs *regs,
         */
        discard_lazy_cpu_state();
 
-       /* force the process to reload the FP registers from
-          current->thread when it next does FP instructions */
-       regs->msr &= ~(MSR_FP | MSR_FE0 | MSR_FE1);
-       if (__copy_from_user(current->thread.fpr, &sr->mc_fregs,
-                            sizeof(sr->mc_fregs)))
-               return 1;
-
 #ifdef CONFIG_ALTIVEC
-       /* force the process to reload the altivec registers from
-          current->thread when it next does altivec instructions */
+       /*
+        * Force the process to reload the altivec registers from
+        * current->thread when it next does altivec instructions
+        */
        regs->msr &= ~MSR_VEC;
        if (msr & MSR_VEC) {
                /* restore altivec registers from the stack */
@@ -462,6 +476,23 @@ static long restore_user_regs(struct pt_regs *regs,
                return 1;
 #endif /* CONFIG_ALTIVEC */
 
+#ifdef CONFIG_VSX
+       if (__copy_from_user(buf, &sr->mc_fregs,sizeof(sr->mc_fregs)))
+               return 1;
+       for (i = 0; i < 32 ; i++)
+               current->thread.TS_FPR(i) = buf[i];
+       memcpy(&current->thread.fpscr, &buf[i], sizeof(double));
+#else
+       if (__copy_from_user(current->thread.fpr, &sr->mc_fregs,
+                            sizeof(sr->mc_fregs)))
+               return 1;
+#endif /* CONFIG_VSX */
+       /*
+        * force the process to reload the FP registers from
+        * current->thread when it next does FP instructions
+        */
+       regs->msr &= ~(MSR_FP | MSR_FE0 | MSR_FE1);
+
 #ifdef CONFIG_SPE
        /* force the process to reload the spe registers from
           current->thread when it next does spe instructions */