Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit efff1912 authored by Paul Mackerras's avatar Paul Mackerras Committed by Alexander Graf
Browse files

KVM: PPC: Store FP/VSX/VMX state in thread_fp/vr_state structures



This uses struct thread_fp_state and struct thread_vr_state to store
the floating-point, VMX/Altivec and VSX state, rather than flat arrays.
This makes transferring the state to/from the thread_struct simpler
and allows us to unify the get/set_one_reg implementations for the
VSX registers.

Signed-off-by: default avatarPaul Mackerras <paulus@samba.org>
Signed-off-by: default avatarAlexander Graf <agraf@suse.de>
parent 09548fda
Loading
Loading
Loading
Loading
+4 −8
Original line number Diff line number Diff line
@@ -410,8 +410,7 @@ struct kvm_vcpu_arch {

	ulong gpr[32];

	u64 fpr[32];
	u64 fpscr;
	struct thread_fp_state fp;

#ifdef CONFIG_SPE
	ulong evr[32];
@@ -420,12 +419,7 @@ struct kvm_vcpu_arch {
	u64 acc;
#endif
#ifdef CONFIG_ALTIVEC
	vector128 vr[32];
	vector128 vscr;
#endif

#ifdef CONFIG_VSX
	u64 vsr[64];
	struct thread_vr_state vr;
#endif

#ifdef CONFIG_KVM_BOOKE_HV
@@ -619,6 +613,8 @@ struct kvm_vcpu_arch {
#endif
};

#define VCPU_FPR(vcpu, i)	(vcpu)->arch.fp.fpr[i][TS_FPROFFSET]

/* Values for vcpu->arch.state */
#define KVMPPC_VCPU_NOTREADY		0
#define KVMPPC_VCPU_RUNNABLE		1
+4 −7
Original line number Diff line number Diff line
@@ -425,14 +425,11 @@ int main(void)
	DEFINE(VCPU_GUEST_PID, offsetof(struct kvm_vcpu, arch.pid));
	DEFINE(VCPU_GPRS, offsetof(struct kvm_vcpu, arch.gpr));
	DEFINE(VCPU_VRSAVE, offsetof(struct kvm_vcpu, arch.vrsave));
	DEFINE(VCPU_FPRS, offsetof(struct kvm_vcpu, arch.fpr));
	DEFINE(VCPU_FPSCR, offsetof(struct kvm_vcpu, arch.fpscr));
	DEFINE(VCPU_FPRS, offsetof(struct kvm_vcpu, arch.fp.fpr));
	DEFINE(VCPU_FPSCR, offsetof(struct kvm_vcpu, arch.fp.fpscr));
#ifdef CONFIG_ALTIVEC
	DEFINE(VCPU_VRS, offsetof(struct kvm_vcpu, arch.vr));
	DEFINE(VCPU_VSCR, offsetof(struct kvm_vcpu, arch.vscr));
#endif
#ifdef CONFIG_VSX
	DEFINE(VCPU_VSRS, offsetof(struct kvm_vcpu, arch.vsr));
	DEFINE(VCPU_VRS, offsetof(struct kvm_vcpu, arch.vr.vr));
	DEFINE(VCPU_VSCR, offsetof(struct kvm_vcpu, arch.vr.vscr));
#endif
	DEFINE(VCPU_XER, offsetof(struct kvm_vcpu, arch.xer));
	DEFINE(VCPU_CTR, offsetof(struct kvm_vcpu, arch.ctr));
+30 −8
Original line number Diff line number Diff line
@@ -577,10 +577,10 @@ int kvm_vcpu_ioctl_get_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg)
			break;
		case KVM_REG_PPC_FPR0 ... KVM_REG_PPC_FPR31:
			i = reg->id - KVM_REG_PPC_FPR0;
			val = get_reg_val(reg->id, vcpu->arch.fpr[i]);
			val = get_reg_val(reg->id, VCPU_FPR(vcpu, i));
			break;
		case KVM_REG_PPC_FPSCR:
			val = get_reg_val(reg->id, vcpu->arch.fpscr);
			val = get_reg_val(reg->id, vcpu->arch.fp.fpscr);
			break;
#ifdef CONFIG_ALTIVEC
		case KVM_REG_PPC_VR0 ... KVM_REG_PPC_VR31:
@@ -588,19 +588,30 @@ int kvm_vcpu_ioctl_get_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg)
				r = -ENXIO;
				break;
			}
			val.vval = vcpu->arch.vr[reg->id - KVM_REG_PPC_VR0];
			val.vval = vcpu->arch.vr.vr[reg->id - KVM_REG_PPC_VR0];
			break;
		case KVM_REG_PPC_VSCR:
			if (!cpu_has_feature(CPU_FTR_ALTIVEC)) {
				r = -ENXIO;
				break;
			}
			val = get_reg_val(reg->id, vcpu->arch.vscr.u[3]);
			val = get_reg_val(reg->id, vcpu->arch.vr.vscr.u[3]);
			break;
		case KVM_REG_PPC_VRSAVE:
			val = get_reg_val(reg->id, vcpu->arch.vrsave);
			break;
#endif /* CONFIG_ALTIVEC */
#ifdef CONFIG_VSX
		case KVM_REG_PPC_VSR0 ... KVM_REG_PPC_VSR31:
			if (cpu_has_feature(CPU_FTR_VSX)) {
				long int i = reg->id - KVM_REG_PPC_VSR0;
				val.vsxval[0] = vcpu->arch.fp.fpr[i][0];
				val.vsxval[1] = vcpu->arch.fp.fpr[i][1];
			} else {
				r = -ENXIO;
			}
			break;
#endif /* CONFIG_VSX */
		case KVM_REG_PPC_DEBUG_INST: {
			u32 opcode = INS_TW;
			r = copy_to_user((u32 __user *)(long)reg->addr,
@@ -656,10 +667,10 @@ int kvm_vcpu_ioctl_set_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg)
			break;
		case KVM_REG_PPC_FPR0 ... KVM_REG_PPC_FPR31:
			i = reg->id - KVM_REG_PPC_FPR0;
			vcpu->arch.fpr[i] = set_reg_val(reg->id, val);
			VCPU_FPR(vcpu, i) = set_reg_val(reg->id, val);
			break;
		case KVM_REG_PPC_FPSCR:
			vcpu->arch.fpscr = set_reg_val(reg->id, val);
			vcpu->arch.fp.fpscr = set_reg_val(reg->id, val);
			break;
#ifdef CONFIG_ALTIVEC
		case KVM_REG_PPC_VR0 ... KVM_REG_PPC_VR31:
@@ -667,14 +678,14 @@ int kvm_vcpu_ioctl_set_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg)
				r = -ENXIO;
				break;
			}
			vcpu->arch.vr[reg->id - KVM_REG_PPC_VR0] = val.vval;
			vcpu->arch.vr.vr[reg->id - KVM_REG_PPC_VR0] = val.vval;
			break;
		case KVM_REG_PPC_VSCR:
			if (!cpu_has_feature(CPU_FTR_ALTIVEC)) {
				r = -ENXIO;
				break;
			}
			vcpu->arch.vscr.u[3] = set_reg_val(reg->id, val);
			vcpu->arch.vr.vscr.u[3] = set_reg_val(reg->id, val);
			break;
		case KVM_REG_PPC_VRSAVE:
			if (!cpu_has_feature(CPU_FTR_ALTIVEC)) {
@@ -684,6 +695,17 @@ int kvm_vcpu_ioctl_set_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg)
			vcpu->arch.vrsave = set_reg_val(reg->id, val);
			break;
#endif /* CONFIG_ALTIVEC */
#ifdef CONFIG_VSX
		case KVM_REG_PPC_VSR0 ... KVM_REG_PPC_VSR31:
			if (cpu_has_feature(CPU_FTR_VSX)) {
				long int i = reg->id - KVM_REG_PPC_VSR0;
				vcpu->arch.fp.fpr[i][0] = val.vsxval[0];
				vcpu->arch.fp.fpr[i][1] = val.vsxval[1];
			} else {
				r = -ENXIO;
			}
			break;
#endif /* CONFIG_VSX */
#ifdef CONFIG_KVM_XICS
		case KVM_REG_PPC_ICP_STATE:
			if (!vcpu->arch.icp) {
+0 −42
Original line number Diff line number Diff line
@@ -811,27 +811,6 @@ static int kvmppc_get_one_reg_hv(struct kvm_vcpu *vcpu, u64 id,
	case KVM_REG_PPC_SDAR:
		*val = get_reg_val(id, vcpu->arch.sdar);
		break;
#ifdef CONFIG_VSX
	case KVM_REG_PPC_FPR0 ... KVM_REG_PPC_FPR31:
		if (cpu_has_feature(CPU_FTR_VSX)) {
			/* VSX => FP reg i is stored in arch.vsr[2*i] */
			long int i = id - KVM_REG_PPC_FPR0;
			*val = get_reg_val(id, vcpu->arch.vsr[2 * i]);
		} else {
			/* let generic code handle it */
			r = -EINVAL;
		}
		break;
	case KVM_REG_PPC_VSR0 ... KVM_REG_PPC_VSR31:
		if (cpu_has_feature(CPU_FTR_VSX)) {
			long int i = id - KVM_REG_PPC_VSR0;
			val->vsxval[0] = vcpu->arch.vsr[2 * i];
			val->vsxval[1] = vcpu->arch.vsr[2 * i + 1];
		} else {
			r = -ENXIO;
		}
		break;
#endif /* CONFIG_VSX */
	case KVM_REG_PPC_VPA_ADDR:
		spin_lock(&vcpu->arch.vpa_update_lock);
		*val = get_reg_val(id, vcpu->arch.vpa.next_gpa);
@@ -914,27 +893,6 @@ static int kvmppc_set_one_reg_hv(struct kvm_vcpu *vcpu, u64 id,
	case KVM_REG_PPC_SDAR:
		vcpu->arch.sdar = set_reg_val(id, *val);
		break;
#ifdef CONFIG_VSX
	case KVM_REG_PPC_FPR0 ... KVM_REG_PPC_FPR31:
		if (cpu_has_feature(CPU_FTR_VSX)) {
			/* VSX => FP reg i is stored in arch.vsr[2*i] */
			long int i = id - KVM_REG_PPC_FPR0;
			vcpu->arch.vsr[2 * i] = set_reg_val(id, *val);
		} else {
			/* let generic code handle it */
			r = -EINVAL;
		}
		break;
	case KVM_REG_PPC_VSR0 ... KVM_REG_PPC_VSR31:
		if (cpu_has_feature(CPU_FTR_VSX)) {
			long int i = id - KVM_REG_PPC_VSR0;
			vcpu->arch.vsr[2 * i] = val->vsxval[0];
			vcpu->arch.vsr[2 * i + 1] = val->vsxval[1];
		} else {
			r = -ENXIO;
		}
		break;
#endif /* CONFIG_VSX */
	case KVM_REG_PPC_VPA_ADDR:
		addr = set_reg_val(id, *val);
		r = -EINVAL;
+2 −2
Original line number Diff line number Diff line
@@ -1889,7 +1889,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_VSX)
BEGIN_FTR_SECTION
	reg = 0
	.rept	32
	li	r6,reg*16+VCPU_VSRS
	li	r6,reg*16+VCPU_FPRS
	STXVD2X(reg,R6,R3)
	reg = reg + 1
	.endr
@@ -1951,7 +1951,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_VSX)
BEGIN_FTR_SECTION
	reg = 0
	.rept	32
	li	r7,reg*16+VCPU_VSRS
	li	r7,reg*16+VCPU_FPRS
	LXVD2X(reg,R7,R4)
	reg = reg + 1
	.endr
Loading