瀏覽代碼

KVM: PPC: Book3S PR: Expose TAR facility to guest

POWER8 implements a new register called TAR. This register has to be
enabled in FSCR and then from KVM's point of view is mere storage.

This patch enables the guest to use TAR.

Signed-off-by: Alexander Graf <agraf@suse.de>
Alexander Graf 11 年之前
父節點
當前提交
e14e7a1e53

+ 2 - 0
arch/powerpc/include/asm/kvm_host.h

@@ -449,7 +449,9 @@ struct kvm_vcpu_arch {
 	ulong pc;
 	ulong pc;
 	ulong ctr;
 	ulong ctr;
 	ulong lr;
 	ulong lr;
+#ifdef CONFIG_PPC_BOOK3S
 	ulong tar;
 	ulong tar;
+#endif
 
 
 	ulong xer;
 	ulong xer;
 	u32 cr;
 	u32 cr;

+ 2 - 0
arch/powerpc/kernel/asm-offsets.c

@@ -446,7 +446,9 @@ int main(void)
 	DEFINE(VCPU_XER, offsetof(struct kvm_vcpu, arch.xer));
 	DEFINE(VCPU_XER, offsetof(struct kvm_vcpu, arch.xer));
 	DEFINE(VCPU_CTR, offsetof(struct kvm_vcpu, arch.ctr));
 	DEFINE(VCPU_CTR, offsetof(struct kvm_vcpu, arch.ctr));
 	DEFINE(VCPU_LR, offsetof(struct kvm_vcpu, arch.lr));
 	DEFINE(VCPU_LR, offsetof(struct kvm_vcpu, arch.lr));
+#ifdef CONFIG_PPC_BOOK3S
 	DEFINE(VCPU_TAR, offsetof(struct kvm_vcpu, arch.tar));
 	DEFINE(VCPU_TAR, offsetof(struct kvm_vcpu, arch.tar));
+#endif
 	DEFINE(VCPU_CR, offsetof(struct kvm_vcpu, arch.cr));
 	DEFINE(VCPU_CR, offsetof(struct kvm_vcpu, arch.cr));
 	DEFINE(VCPU_PC, offsetof(struct kvm_vcpu, arch.pc));
 	DEFINE(VCPU_PC, offsetof(struct kvm_vcpu, arch.pc));
 #ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
 #ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE

+ 6 - 0
arch/powerpc/kvm/book3s.c

@@ -634,6 +634,9 @@ int kvm_vcpu_ioctl_get_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg)
 		case KVM_REG_PPC_FSCR:
 		case KVM_REG_PPC_FSCR:
 			val = get_reg_val(reg->id, vcpu->arch.fscr);
 			val = get_reg_val(reg->id, vcpu->arch.fscr);
 			break;
 			break;
+		case KVM_REG_PPC_TAR:
+			val = get_reg_val(reg->id, vcpu->arch.tar);
+			break;
 		default:
 		default:
 			r = -EINVAL;
 			r = -EINVAL;
 			break;
 			break;
@@ -726,6 +729,9 @@ int kvm_vcpu_ioctl_set_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg)
 		case KVM_REG_PPC_FSCR:
 		case KVM_REG_PPC_FSCR:
 			vcpu->arch.fscr = set_reg_val(reg->id, val);
 			vcpu->arch.fscr = set_reg_val(reg->id, val);
 			break;
 			break;
+		case KVM_REG_PPC_TAR:
+			vcpu->arch.tar = set_reg_val(reg->id, val);
+			break;
 		default:
 		default:
 			r = -EINVAL;
 			r = -EINVAL;
 			break;
 			break;

+ 0 - 6
arch/powerpc/kvm/book3s_hv.c

@@ -891,9 +891,6 @@ static int kvmppc_get_one_reg_hv(struct kvm_vcpu *vcpu, u64 id,
 	case KVM_REG_PPC_BESCR:
 	case KVM_REG_PPC_BESCR:
 		*val = get_reg_val(id, vcpu->arch.bescr);
 		*val = get_reg_val(id, vcpu->arch.bescr);
 		break;
 		break;
-	case KVM_REG_PPC_TAR:
-		*val = get_reg_val(id, vcpu->arch.tar);
-		break;
 	case KVM_REG_PPC_DPDES:
 	case KVM_REG_PPC_DPDES:
 		*val = get_reg_val(id, vcpu->arch.vcore->dpdes);
 		*val = get_reg_val(id, vcpu->arch.vcore->dpdes);
 		break;
 		break;
@@ -1100,9 +1097,6 @@ static int kvmppc_set_one_reg_hv(struct kvm_vcpu *vcpu, u64 id,
 	case KVM_REG_PPC_BESCR:
 	case KVM_REG_PPC_BESCR:
 		vcpu->arch.bescr = set_reg_val(id, *val);
 		vcpu->arch.bescr = set_reg_val(id, *val);
 		break;
 		break;
-	case KVM_REG_PPC_TAR:
-		vcpu->arch.tar = set_reg_val(id, *val);
-		break;
 	case KVM_REG_PPC_DPDES:
 	case KVM_REG_PPC_DPDES:
 		vcpu->arch.vcore->dpdes = set_reg_val(id, *val);
 		vcpu->arch.vcore->dpdes = set_reg_val(id, *val);
 		break;
 		break;

+ 18 - 0
arch/powerpc/kvm/book3s_pr.c

@@ -90,6 +90,7 @@ static void kvmppc_core_vcpu_put_pr(struct kvm_vcpu *vcpu)
 #endif
 #endif
 
 
 	kvmppc_giveup_ext(vcpu, MSR_FP | MSR_VEC | MSR_VSX);
 	kvmppc_giveup_ext(vcpu, MSR_FP | MSR_VEC | MSR_VSX);
+	kvmppc_giveup_fac(vcpu, FSCR_TAR_LG);
 	vcpu->cpu = -1;
 	vcpu->cpu = -1;
 }
 }
 
 
@@ -625,6 +626,14 @@ static void kvmppc_giveup_fac(struct kvm_vcpu *vcpu, ulong fac)
 		/* Facility not available to the guest, ignore giveup request*/
 		/* Facility not available to the guest, ignore giveup request*/
 		return;
 		return;
 	}
 	}
+
+	switch (fac) {
+	case FSCR_TAR_LG:
+		vcpu->arch.tar = mfspr(SPRN_TAR);
+		mtspr(SPRN_TAR, current->thread.tar);
+		vcpu->arch.shadow_fscr &= ~FSCR_TAR;
+		break;
+	}
 #endif
 #endif
 }
 }
 
 
@@ -794,6 +803,12 @@ static int kvmppc_handle_fac(struct kvm_vcpu *vcpu, ulong fac)
 	}
 	}
 
 
 	switch (fac) {
 	switch (fac) {
+	case FSCR_TAR_LG:
+		/* TAR switching isn't lazy in Linux yet */
+		current->thread.tar = mfspr(SPRN_TAR);
+		mtspr(SPRN_TAR, vcpu->arch.tar);
+		vcpu->arch.shadow_fscr |= FSCR_TAR;
+		break;
 	default:
 	default:
 		kvmppc_emulate_fac(vcpu, fac);
 		kvmppc_emulate_fac(vcpu, fac);
 		break;
 		break;
@@ -1393,6 +1408,9 @@ static int kvmppc_vcpu_run_pr(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
 	/* Make sure we save the guest FPU/Altivec/VSX state */
 	/* Make sure we save the guest FPU/Altivec/VSX state */
 	kvmppc_giveup_ext(vcpu, MSR_FP | MSR_VEC | MSR_VSX);
 	kvmppc_giveup_ext(vcpu, MSR_FP | MSR_VEC | MSR_VSX);
 
 
+	/* Make sure we save the guest TAR/EBB/DSCR state */
+	kvmppc_giveup_fac(vcpu, FSCR_TAR_LG);
+
 out:
 out:
 	vcpu->mode = OUTSIDE_GUEST_MODE;
 	vcpu->mode = OUTSIDE_GUEST_MODE;
 	return ret;
 	return ret;