diff --git a/arch/powerpc/include/asm/kvm.h b/arch/powerpc/include/asm/kvm.h
index 9557576..5792024 100644
--- a/arch/powerpc/include/asm/kvm.h
+++ b/arch/powerpc/include/asm/kvm.h
@@ -261,9 +261,20 @@ struct kvm_sregs {
 };
 
 struct kvm_fpu {
+	__u64 valid;
+	__u64 fpscr;
 	__u64 fpr[32];
+	__vector128 vr[32];
+	__u32 _pad[3];
+	__u32 vscr;
+	__u64 vsr[32];
 };
 
+/* Values for kvm_fpu valid field */
+#define KVM_FPU_FPREGS	1	/* standard floating-point regs & FPSCR */
+#define KVM_FPU_VREGS	2	/* VMX/Altivec vector regs & VSCR */
+#define KVM_FPU_VSREGS	4	/* POWER7 vector/scalar additional regs */
+
 struct kvm_debug_exit_arch {
 };
 
diff --git a/arch/powerpc/include/asm/kvm_ppc.h b/arch/powerpc/include/asm/kvm_ppc.h
index c06a64b..5dccdc5 100644
--- a/arch/powerpc/include/asm/kvm_ppc.h
+++ b/arch/powerpc/include/asm/kvm_ppc.h
@@ -96,6 +96,8 @@ extern int kvmppc_core_vcpu_translate(struct kvm_vcpu *vcpu,
 
 extern void kvmppc_core_vcpu_load(struct kvm_vcpu *vcpu, int cpu);
 extern void kvmppc_core_vcpu_put(struct kvm_vcpu *vcpu);
+extern u64 kvmppc_core_get_fpu_valid(struct kvm_vcpu *vcpu);
+extern void kvmppc_core_set_fpu_valid(struct kvm_vcpu *vcpu, u64 valid);
 
 extern int kvmppc_core_prepare_to_enter(struct kvm_vcpu *vcpu);
 extern int kvmppc_core_pending_dec(struct kvm_vcpu *vcpu);
diff --git a/arch/powerpc/kvm/book3s.c b/arch/powerpc/kvm/book3s.c
index e946665..c2278f6 100644
--- a/arch/powerpc/kvm/book3s.c
+++ b/arch/powerpc/kvm/book3s.c
@@ -477,12 +477,57 @@ int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
 
 int kvm_arch_vcpu_ioctl_get_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu)
 {
-	return -ENOTSUPP;
+	u64 valid = kvmppc_core_get_fpu_valid(vcpu);
+
+	/* avoid leaking information to userspace */
+	memset(fpu, 0, sizeof(*fpu));
+
+	if (valid & KVM_FPU_FPREGS) {
+		memcpy(fpu->fpr, vcpu->arch.fpr, sizeof(fpu->fpr));
+		fpu->fpscr = vcpu->arch.fpscr;
+	}
+#ifdef CONFIG_ALTIVEC
+	if (valid & KVM_FPU_VREGS) {
+		memcpy(fpu->vr, vcpu->arch.vr, sizeof(fpu->vr));
+		fpu->vscr = vcpu->arch.vscr.u[3];
+	}
+#endif
+#ifdef CONFIG_VSX
+	if (valid & KVM_FPU_VSREGS) {
+		long i;
+
+		for (i = 0; i < ARRAY_SIZE(fpu->vsr); ++i)
+			fpu->vsr[i] = vcpu->arch.vsr[2*i + 1];
+	}
+#endif
+	fpu->valid = valid;
+	return 0;
 }
 
 int kvm_arch_vcpu_ioctl_set_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu)
 {
-	return -ENOTSUPP;
+	u64 valid = fpu->valid;
+
+	if (valid & KVM_FPU_FPREGS) {
+		memcpy(vcpu->arch.fpr, fpu->fpr, sizeof(vcpu->arch.fpr));
+		vcpu->arch.fpscr = fpu->fpscr;
+	}
+#ifdef CONFIG_ALTIVEC
+	if (valid & KVM_FPU_VREGS) {
+		memcpy(vcpu->arch.vr, fpu->vr, sizeof(vcpu->arch.vr));
+		vcpu->arch.vscr.u[3] = fpu->vscr;
+	}
+#endif
+#ifdef CONFIG_VSX
+	if (valid & KVM_FPU_VSREGS) {
+		long i;
+
+		for (i = 0; i < ARRAY_SIZE(fpu->vsr); ++i)
+			vcpu->arch.vsr[2*i + 1] = fpu->vsr[i];
+	}
+#endif
+	kvmppc_core_set_fpu_valid(vcpu, valid);
+	return 0;
 }
 
 int kvm_arch_vcpu_ioctl_translate(struct kvm_vcpu *vcpu,
diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c
index 7fe5c9a..2c2b6b9 100644
--- a/arch/powerpc/kvm/book3s_hv.c
+++ b/arch/powerpc/kvm/book3s_hv.c
@@ -677,6 +677,38 @@ int kvm_vcpu_ioctl_set_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg)
 	return r;
 }
 
+u64 kvmppc_core_get_fpu_valid(struct kvm_vcpu *vcpu)
+{
+	u64 valid = KVM_FPU_FPREGS;
+
+#ifdef CONFIG_ALTIVEC
+	if (cpu_has_feature(CPU_FTR_ALTIVEC))
+		valid |= KVM_FPU_VREGS;
+#endif
+#ifdef CONFIG_VSX
+	if (cpu_has_feature(CPU_FTR_VSX)) {
+		long i;
+
+		for (i = 0; i < ARRAY_SIZE(vcpu->arch.fpr); ++i)
+			vcpu->arch.fpr[i] = vcpu->arch.vsr[2*i];
+		valid |= KVM_FPU_VSREGS;
+	}
+#endif
+	return valid;
+}
+
+void kvmppc_core_set_fpu_valid(struct kvm_vcpu *vcpu, u64 valid)
+{
+#ifdef CONFIG_VSX
+	if ((valid & KVM_FPU_FPREGS) && cpu_has_feature(CPU_FTR_VSX)) {
+		long i;
+
+		for (i = 0; i < ARRAY_SIZE(vcpu->arch.fpr); ++i)
+			vcpu->arch.vsr[2*i] = vcpu->arch.fpr[i];
+	}
+#endif
+}
+
 int kvmppc_core_check_processor_compat(void)
 {
 	if (cpu_has_feature(CPU_FTR_HVMODE))
diff --git a/arch/powerpc/kvm/book3s_pr.c b/arch/powerpc/kvm/book3s_pr.c
index b3c584f..e3b81a2 100644
--- a/arch/powerpc/kvm/book3s_pr.c
+++ b/arch/powerpc/kvm/book3s_pr.c
@@ -978,6 +978,25 @@ int kvm_vcpu_ioctl_set_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg)
 	return r;
 }
 
+u64 kvmppc_core_get_fpu_valid(struct kvm_vcpu *vcpu)
+{
+	u64 valid = KVM_FPU_FPREGS;
+
+#ifdef CONFIG_ALTIVEC
+	if (cpu_has_feature(CPU_FTR_ALTIVEC))
+		valid |= KVM_FPU_VREGS;
+#endif
+#ifdef CONFIG_VSX
+	if (cpu_has_feature(CPU_FTR_VSX))
+		valid |= KVM_FPU_VSREGS;
+#endif
+	return valid;
+}
+
+void kvmppc_core_set_fpu_valid(struct kvm_vcpu *vcpu, u64 valid)
+{
+}
+
 int kvmppc_core_check_processor_compat(void)
 {
 	return 0;
