diff --git a/arch/powerpc/include/asm/kvm_fpu.h b/arch/powerpc/include/asm/kvm_fpu.h
new file mode 100644
index 0000000..2e42eb7
--- /dev/null
+++ b/arch/powerpc/include/asm/kvm_fpu.h
@@ -0,0 +1,45 @@
+/*
+ * 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 fp_fres(struct thread_struct *t, u32 *dst, u32 *src1);
+extern void fp_frsqrte(struct thread_struct *t, u32 *dst, u32 *src1);
+extern void fp_fsqrts(struct thread_struct *t, u32 *dst, u32 *src1);
+
+extern void fp_fadds(struct thread_struct *t, u32 *dst, u32 *src1, u32 *src2);
+extern void fp_fdivs(struct thread_struct *t, u32 *dst, u32 *src1, u32 *src2);
+extern void fp_fmuls(struct thread_struct *t, u32 *dst, u32 *src1, u32 *src2);
+extern void fp_fsubs(struct thread_struct *t, u32 *dst, u32 *src1, u32 *src2);
+
+extern void fp_fmadds(struct thread_struct *t, u32 *dst, u32 *src1, u32 *src2,
+		      u32 *src3);
+extern void fp_fmsubs(struct thread_struct *t, u32 *dst, u32 *src1, u32 *src2,
+		      u32 *src3);
+extern void fp_fnmadds(struct thread_struct *t, u32 *dst, u32 *src1, u32 *src2,
+		       u32 *src3);
+extern void fp_fnmsubs(struct thread_struct *t, u32 *dst, u32 *src1, u32 *src2,
+		       u32 *src3);
+extern void fp_fsel(struct thread_struct *t, u32 *dst, u32 *src1, u32 *src2,
+		    u32 *src3);
+
+#endif
diff --git a/arch/powerpc/kernel/ppc_ksyms.c b/arch/powerpc/kernel/ppc_ksyms.c
index ab3e392..58fdb3a 100644
--- a/arch/powerpc/kernel/ppc_ksyms.c
+++ b/arch/powerpc/kernel/ppc_ksyms.c
@@ -101,6 +101,8 @@ EXPORT_SYMBOL(pci_dram_offset);
 EXPORT_SYMBOL(start_thread);
 EXPORT_SYMBOL(kernel_thread);
 
+EXPORT_SYMBOL_GPL(cvt_df);
+EXPORT_SYMBOL_GPL(cvt_fd);
 EXPORT_SYMBOL(giveup_fpu);
 #ifdef CONFIG_ALTIVEC
 EXPORT_SYMBOL(giveup_altivec);
diff --git a/arch/powerpc/kvm/Makefile b/arch/powerpc/kvm/Makefile
index 56484d6..e575cfd 100644
--- a/arch/powerpc/kvm/Makefile
+++ b/arch/powerpc/kvm/Makefile
@@ -40,6 +40,7 @@ kvm-objs-$(CONFIG_KVM_E500) := $(kvm-e500-objs)
 
 kvm-book3s_64-objs := \
 	$(common-objs-y) \
+	fpu.o \
 	book3s.o \
 	book3s_64_emulate.o \
 	book3s_64_interrupts.o \
diff --git a/arch/powerpc/kvm/fpu.S b/arch/powerpc/kvm/fpu.S
new file mode 100644
index 0000000..50575ac
--- /dev/null
+++ b/arch/powerpc/kvm/fpu.S
@@ -0,0 +1,77 @@
+/*
+ *  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>
+
+#define FPS_ONE_IN(name) 					\
+_GLOBAL(fp_ ## name);							\
+	lfd	0,THREAD_FPSCR(r3);	/* load up fpscr value */	\
+	MTFSF_L(0);							\
+	lfs	0,0(r5);						\
+									\
+	name	0,0;							\
+									\
+	stfs	0,0(r4);						\
+	mffs	0;							\
+	stfd	0,THREAD_FPSCR(r3);	/* save new fpscr value */	\
+	blr
+
+#define FPS_TWO_IN(name) 					\
+_GLOBAL(fp_ ## name);							\
+	lfd	0,THREAD_FPSCR(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,THREAD_FPSCR(r3);	/* save new fpscr value */	\
+	blr
+
+#define FPS_THREE_IN(name) 					\
+_GLOBAL(fp_ ## name);							\
+	lfd	0,THREAD_FPSCR(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,THREAD_FPSCR(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)
+
