--- /dev/null
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ * Copyright Novell Inc. 2010
+ *
+ * Authors: Alexander Graf <agraf@suse.de>
+ */
+
+#ifndef __ASM_KVM_FPU_H__
+#define __ASM_KVM_FPU_H__
+
+#include <linux/types.h>
+
+extern void fps_fres(struct thread_struct *t, u32 *dst, u32 *src1);
+extern void fps_frsqrte(struct thread_struct *t, u32 *dst, u32 *src1);
+extern void fps_fsqrts(struct thread_struct *t, u32 *dst, u32 *src1);
+
+extern void fps_fadds(struct thread_struct *t, u32 *dst, u32 *src1, u32 *src2);
+extern void fps_fdivs(struct thread_struct *t, u32 *dst, u32 *src1, u32 *src2);
+extern void fps_fmuls(struct thread_struct *t, u32 *dst, u32 *src1, u32 *src2);
+extern void fps_fsubs(struct thread_struct *t, u32 *dst, u32 *src1, u32 *src2);
+
+extern void fps_fmadds(struct thread_struct *t, u32 *dst, u32 *src1, u32 *src2,
+                      u32 *src3);
+extern void fps_fmsubs(struct thread_struct *t, u32 *dst, u32 *src1, u32 *src2,
+                      u32 *src3);
+extern void fps_fnmadds(struct thread_struct *t, u32 *dst, u32 *src1, u32 *src2,
+                       u32 *src3);
+extern void fps_fnmsubs(struct thread_struct *t, u32 *dst, u32 *src1, u32 *src2,
+                       u32 *src3);
+extern void fps_fsel(struct thread_struct *t, u32 *dst, u32 *src1, u32 *src2,
+                    u32 *src3);
+
+#define FPD_ONE_IN(name) extern void fpd_ ## name(u64 *fpscr, u32 *cr, \
+                               u64 *dst, u64 *src1);
+#define FPD_TWO_IN(name) extern void fpd_ ## name(u64 *fpscr, u32 *cr, \
+                               u64 *dst, u64 *src1, u64 *src2);
+#define FPD_THREE_IN(name) extern void fpd_ ## name(u64 *fpscr, u32 *cr, \
+                               u64 *dst, u64 *src1, u64 *src2, u64 *src3);
+
+extern void fpd_fcmpu(u64 *fpscr, u32 *cr, u64 *src1, u64 *src2);
+extern void fpd_fcmpo(u64 *fpscr, u32 *cr, u64 *src1, u64 *src2);
+
+FPD_ONE_IN(fsqrts)
+FPD_ONE_IN(frsqrtes)
+FPD_ONE_IN(fres)
+FPD_ONE_IN(frsp)
+FPD_ONE_IN(fctiw)
+FPD_ONE_IN(fctiwz)
+FPD_ONE_IN(fsqrt)
+FPD_ONE_IN(fre)
+FPD_ONE_IN(frsqrte)
+FPD_ONE_IN(fneg)
+FPD_ONE_IN(fabs)
+FPD_TWO_IN(fadds)
+FPD_TWO_IN(fsubs)
+FPD_TWO_IN(fdivs)
+FPD_TWO_IN(fmuls)
+FPD_TWO_IN(fcpsgn)
+FPD_TWO_IN(fdiv)
+FPD_TWO_IN(fadd)
+FPD_TWO_IN(fmul)
+FPD_TWO_IN(fsub)
+FPD_THREE_IN(fmsubs)
+FPD_THREE_IN(fmadds)
+FPD_THREE_IN(fnmsubs)
+FPD_THREE_IN(fnmadds)
+FPD_THREE_IN(fsel)
+FPD_THREE_IN(fmsub)
+FPD_THREE_IN(fmadd)
+FPD_THREE_IN(fnmsub)
+FPD_THREE_IN(fnmadd)
+
+#endif
 
--- /dev/null
+/*
+ *  FPU helper code to use FPU operations from inside the kernel
+ *
+ *    Copyright (C) 2010 Alexander Graf (agraf@suse.de)
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public License
+ *  as published by the Free Software Foundation; either version
+ *  2 of the License, or (at your option) any later version.
+ *
+ */
+
+#include <asm/reg.h>
+#include <asm/page.h>
+#include <asm/mmu.h>
+#include <asm/pgtable.h>
+#include <asm/cputable.h>
+#include <asm/cache.h>
+#include <asm/thread_info.h>
+#include <asm/ppc_asm.h>
+#include <asm/asm-offsets.h>
+
+/* Instructions operating on single parameters */
+
+/*
+ * Single operation with one input operand
+ *
+ * R3 = (double*)&fpscr
+ * R4 = (short*)&result
+ * R5 = (short*)¶m1
+ */
+#define FPS_ONE_IN(name)                                       \
+_GLOBAL(fps_ ## name);                                                 \
+       lfd     0,0(r3);                /* load up fpscr value */       \
+       MTFSF_L(0);                                                     \
+       lfs     0,0(r5);                                                \
+                                                                       \
+       name    0,0;                                                    \
+                                                                       \
+       stfs    0,0(r4);                                                \
+       mffs    0;                                                      \
+       stfd    0,0(r3);        /* save new fpscr value */      \
+       blr
+
+/*
+ * Single operation with two input operands
+ *
+ * R3 = (double*)&fpscr
+ * R4 = (short*)&result
+ * R5 = (short*)¶m1
+ * R6 = (short*)¶m2
+ */
+#define FPS_TWO_IN(name)                                       \
+_GLOBAL(fps_ ## name);                                                 \
+       lfd     0,0(r3);                /* load up fpscr value */       \
+       MTFSF_L(0);                                                     \
+       lfs     0,0(r5);                                                \
+       lfs     1,0(r6);                                                \
+                                                                       \
+       name    0,0,1;                                                  \
+                                                                       \
+       stfs    0,0(r4);                                                \
+       mffs    0;                                                      \
+       stfd    0,0(r3);                /* save new fpscr value */      \
+       blr
+
+/*
+ * Single operation with three input operands
+ *
+ * R3 = (double*)&fpscr
+ * R4 = (short*)&result
+ * R5 = (short*)¶m1
+ * R6 = (short*)¶m2
+ * R7 = (short*)¶m3
+ */
+#define FPS_THREE_IN(name)                                     \
+_GLOBAL(fps_ ## name);                                                 \
+       lfd     0,0(r3);                /* load up fpscr value */       \
+       MTFSF_L(0);                                                     \
+       lfs     0,0(r5);                                                \
+       lfs     1,0(r6);                                                \
+       lfs     2,0(r7);                                                \
+                                                                       \
+       name    0,0,1,2;                                                \
+                                                                       \
+       stfs    0,0(r4);                                                \
+       mffs    0;                                                      \
+       stfd    0,0(r3);                /* save new fpscr value */      \
+       blr
+
+FPS_ONE_IN(fres)
+FPS_ONE_IN(frsqrte)
+FPS_ONE_IN(fsqrts)
+FPS_TWO_IN(fadds)
+FPS_TWO_IN(fdivs)
+FPS_TWO_IN(fmuls)
+FPS_TWO_IN(fsubs)
+FPS_THREE_IN(fmadds)
+FPS_THREE_IN(fmsubs)
+FPS_THREE_IN(fnmadds)
+FPS_THREE_IN(fnmsubs)
+FPS_THREE_IN(fsel)
+
+
+/* Instructions operating on double parameters */
+
+/*
+ * Beginning of double instruction processing
+ *
+ * R3 = (double*)&fpscr
+ * R4 = (u32*)&cr
+ * R5 = (double*)&result
+ * R6 = (double*)¶m1
+ * R7 = (double*)¶m2 [load_two]
+ * R8 = (double*)¶m3 [load_three]
+ * LR = instruction call function
+ */
+fpd_load_three:
+       lfd     2,0(r8)                 /* load param3 */
+fpd_load_two:
+       lfd     1,0(r7)                 /* load param2 */
+fpd_load_one:
+       lfd     0,0(r6)                 /* load param1 */
+fpd_load_none:
+       lfd     3,0(r3)                 /* load up fpscr value */
+       MTFSF_L(3)
+       lwz     r6, 0(r4)               /* load cr */
+       mtcr    r6
+       blr
+
+/*
+ * End of double instruction processing
+ *
+ * R3 = (double*)&fpscr
+ * R4 = (u32*)&cr
+ * R5 = (double*)&result
+ * LR = caller of instruction call function
+ */
+fpd_return:
+       mfcr    r6
+       stfd    0,0(r5)                 /* save result */
+       mffs    0
+       stfd    0,0(r3)                 /* save new fpscr value */
+       stw     r6,0(r4)                /* save new cr value */
+       blr
+
+/*
+ * Double operation with no input operand
+ *
+ * R3 = (double*)&fpscr
+ * R4 = (u32*)&cr
+ * R5 = (double*)&result
+ */
+#define FPD_NONE_IN(name)                                              \
+_GLOBAL(fpd_ ## name);                                                 \
+       mflr    r12;                                                    \
+       bl      fpd_load_none;                                          \
+       mtlr    r12;                                                    \
+                                                                       \
+       name.   0;                      /* call instruction */          \
+       b       fpd_return
+
+/*
+ * Double operation with one input operand
+ *
+ * R3 = (double*)&fpscr
+ * R4 = (u32*)&cr
+ * R5 = (double*)&result
+ * R6 = (double*)¶m1
+ */
+#define FPD_ONE_IN(name)                                               \
+_GLOBAL(fpd_ ## name);                                                 \
+       mflr    r12;                                                    \
+       bl      fpd_load_one;                                           \
+       mtlr    r12;                                                    \
+                                                                       \
+       name.   0,0;                    /* call instruction */          \
+       b       fpd_return
+
+/*
+ * Double operation with two input operands
+ *
+ * R3 = (double*)&fpscr
+ * R4 = (u32*)&cr
+ * R5 = (double*)&result
+ * R6 = (double*)¶m1
+ * R7 = (double*)¶m2
+ * R8 = (double*)¶m3
+ */
+#define FPD_TWO_IN(name)                                               \
+_GLOBAL(fpd_ ## name);                                                 \
+       mflr    r12;                                                    \
+       bl      fpd_load_two;                                           \
+       mtlr    r12;                                                    \
+                                                                       \
+       name.   0,0,1;                  /* call instruction */          \
+       b       fpd_return
+
+/*
+ * CR Double operation with two input operands
+ *
+ * R3 = (double*)&fpscr
+ * R4 = (u32*)&cr
+ * R5 = (double*)¶m1
+ * R6 = (double*)¶m2
+ * R7 = (double*)¶m3
+ */
+#define FPD_TWO_IN_CR(name)                                            \
+_GLOBAL(fpd_ ## name);                                                 \
+       lfd     1,0(r6);                /* load param2 */               \
+       lfd     0,0(r5);                /* load param1 */               \
+       lfd     3,0(r3);                /* load up fpscr value */       \
+       MTFSF_L(3);                                                     \
+       lwz     r6, 0(r4);              /* load cr */                   \
+       mtcr    r6;                                                     \
+                                                                       \
+       name    0,0,1;                  /* call instruction */          \
+       mfcr    r6;                                                     \
+       mffs    0;                                                      \
+       stfd    0,0(r3);                /* save new fpscr value */      \
+       stw     r6,0(r4);               /* save new cr value */         \
+       blr
+
+/*
+ * Double operation with three input operands
+ *
+ * R3 = (double*)&fpscr
+ * R4 = (u32*)&cr
+ * R5 = (double*)&result
+ * R6 = (double*)¶m1
+ * R7 = (double*)¶m2
+ * R8 = (double*)¶m3
+ */
+#define FPD_THREE_IN(name)                                             \
+_GLOBAL(fpd_ ## name);                                                 \
+       mflr    r12;                                                    \
+       bl      fpd_load_three;                                         \
+       mtlr    r12;                                                    \
+                                                                       \
+       name.   0,0,1,2;                /* call instruction */          \
+       b       fpd_return
+
+FPD_ONE_IN(fsqrts)
+FPD_ONE_IN(frsqrtes)
+FPD_ONE_IN(fres)
+FPD_ONE_IN(frsp)
+FPD_ONE_IN(fctiw)
+FPD_ONE_IN(fctiwz)
+FPD_ONE_IN(fsqrt)
+FPD_ONE_IN(fre)
+FPD_ONE_IN(frsqrte)
+FPD_ONE_IN(fneg)
+FPD_ONE_IN(fabs)
+FPD_TWO_IN(fadds)
+FPD_TWO_IN(fsubs)
+FPD_TWO_IN(fdivs)
+FPD_TWO_IN(fmuls)
+FPD_TWO_IN_CR(fcmpu)
+FPD_TWO_IN(fcpsgn)
+FPD_TWO_IN(fdiv)
+FPD_TWO_IN(fadd)
+FPD_TWO_IN(fmul)
+FPD_TWO_IN_CR(fcmpo)
+FPD_TWO_IN(fsub)
+FPD_THREE_IN(fmsubs)
+FPD_THREE_IN(fmadds)
+FPD_THREE_IN(fnmsubs)
+FPD_THREE_IN(fnmadds)
+FPD_THREE_IN(fsel)
+FPD_THREE_IN(fmsub)
+FPD_THREE_IN(fmadd)
+FPD_THREE_IN(fnmsub)
+FPD_THREE_IN(fnmadd)