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

Commit 388cf9ee authored by Alexander Graf's avatar Alexander Graf
Browse files

KVM: PPC: Move mtspr/mfspr emulation into own functions



The mtspr/mfspr emulation code became quite big over time. Move it
into its own function so things stay more readable.

Signed-off-by: default avatarAlexander Graf <agraf@suse.de>
parent 686de182
Loading
Loading
Loading
Loading
+121 −100
Original line number Diff line number Diff line
@@ -131,6 +131,125 @@ u32 kvmppc_get_dec(struct kvm_vcpu *vcpu, u64 tb)
	return vcpu->arch.dec - jd;
}

static int kvmppc_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, int rs)
{
	enum emulation_result emulated = EMULATE_DONE;
	ulong spr_val = kvmppc_get_gpr(vcpu, rs);

	switch (sprn) {
	case SPRN_SRR0:
		vcpu->arch.shared->srr0 = spr_val;
		break;
	case SPRN_SRR1:
		vcpu->arch.shared->srr1 = spr_val;
		break;

	/* XXX We need to context-switch the timebase for
	 * watchdog and FIT. */
	case SPRN_TBWL: break;
	case SPRN_TBWU: break;

	case SPRN_MSSSR0: break;

	case SPRN_DEC:
		vcpu->arch.dec = spr_val;
		kvmppc_emulate_dec(vcpu);
		break;

	case SPRN_SPRG0:
		vcpu->arch.shared->sprg0 = spr_val;
		break;
	case SPRN_SPRG1:
		vcpu->arch.shared->sprg1 = spr_val;
		break;
	case SPRN_SPRG2:
		vcpu->arch.shared->sprg2 = spr_val;
		break;
	case SPRN_SPRG3:
		vcpu->arch.shared->sprg3 = spr_val;
		break;

	default:
		emulated = kvmppc_core_emulate_mtspr(vcpu, sprn,
						     spr_val);
		if (emulated == EMULATE_FAIL)
			printk(KERN_INFO "mtspr: unknown spr "
				"0x%x\n", sprn);
		break;
	}

	kvmppc_set_exit_type(vcpu, EMULATED_MTSPR_EXITS);

	return emulated;
}

static int kvmppc_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn, int rt)
{
	enum emulation_result emulated = EMULATE_DONE;
	ulong spr_val = 0;

	switch (sprn) {
	case SPRN_SRR0:
		spr_val = vcpu->arch.shared->srr0;
		break;
	case SPRN_SRR1:
		spr_val = vcpu->arch.shared->srr1;
		break;
	case SPRN_PVR:
		spr_val = vcpu->arch.pvr;
		break;
	case SPRN_PIR:
		spr_val = vcpu->vcpu_id;
		break;
	case SPRN_MSSSR0:
		spr_val = 0;
		break;

	/* Note: mftb and TBRL/TBWL are user-accessible, so
	 * the guest can always access the real TB anyways.
	 * In fact, we probably will never see these traps. */
	case SPRN_TBWL:
		spr_val = get_tb() >> 32;
		break;
	case SPRN_TBWU:
		spr_val = get_tb();
		break;

	case SPRN_SPRG0:
		spr_val = vcpu->arch.shared->sprg0;
		break;
	case SPRN_SPRG1:
		spr_val = vcpu->arch.shared->sprg1;
		break;
	case SPRN_SPRG2:
		spr_val = vcpu->arch.shared->sprg2;
		break;
	case SPRN_SPRG3:
		spr_val = vcpu->arch.shared->sprg3;
		break;
	/* Note: SPRG4-7 are user-readable, so we don't get
	 * a trap. */

	case SPRN_DEC:
		spr_val = kvmppc_get_dec(vcpu, get_tb());
		break;
	default:
		emulated = kvmppc_core_emulate_mfspr(vcpu, sprn,
						     &spr_val);
		if (unlikely(emulated == EMULATE_FAIL)) {
			printk(KERN_INFO "mfspr: unknown spr "
				"0x%x\n", sprn);
		}
		break;
	}

	if (emulated == EMULATE_DONE)
		kvmppc_set_gpr(vcpu, rt, spr_val);
	kvmppc_set_exit_type(vcpu, EMULATED_MFSPR_EXITS);

	return emulated;
}

/* XXX to do:
 * lhax
 * lhaux
@@ -156,7 +275,6 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu)
	int sprn = get_sprn(inst);
	enum emulation_result emulated = EMULATE_DONE;
	int advance = 1;
	ulong spr_val = 0;

	/* this default type might be overwritten by subcategories */
	kvmppc_set_exit_type(vcpu, EMULATED_INST_EXITS);
@@ -236,62 +354,7 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu)
			break;

		case OP_31_XOP_MFSPR:
			switch (sprn) {
			case SPRN_SRR0:
				spr_val = vcpu->arch.shared->srr0;
				break;
			case SPRN_SRR1:
				spr_val = vcpu->arch.shared->srr1;
				break;
			case SPRN_PVR:
				spr_val = vcpu->arch.pvr;
				break;
			case SPRN_PIR:
				spr_val = vcpu->vcpu_id;
				break;
			case SPRN_MSSSR0:
				spr_val = 0;
				break;

			/* Note: mftb and TBRL/TBWL are user-accessible, so
			 * the guest can always access the real TB anyways.
			 * In fact, we probably will never see these traps. */
			case SPRN_TBWL:
				spr_val = get_tb() >> 32;
				break;
			case SPRN_TBWU:
				spr_val = get_tb();
				break;

			case SPRN_SPRG0:
				spr_val = vcpu->arch.shared->sprg0;
				break;
			case SPRN_SPRG1:
				spr_val = vcpu->arch.shared->sprg1;
				break;
			case SPRN_SPRG2:
				spr_val = vcpu->arch.shared->sprg2;
				break;
			case SPRN_SPRG3:
				spr_val = vcpu->arch.shared->sprg3;
				break;
			/* Note: SPRG4-7 are user-readable, so we don't get
			 * a trap. */

			case SPRN_DEC:
				spr_val = kvmppc_get_dec(vcpu, get_tb());
				break;
			default:
				emulated = kvmppc_core_emulate_mfspr(vcpu, sprn,
								     &spr_val);
				if (unlikely(emulated == EMULATE_FAIL)) {
					printk(KERN_INFO "mfspr: unknown spr "
						"0x%x\n", sprn);
				}
				break;
			}
			kvmppc_set_gpr(vcpu, rt, spr_val);
			kvmppc_set_exit_type(vcpu, EMULATED_MFSPR_EXITS);
			emulated = kvmppc_emulate_mfspr(vcpu, sprn, rt);
			break;

		case OP_31_XOP_STHX:
@@ -308,49 +371,7 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu)
			break;

		case OP_31_XOP_MTSPR:
			spr_val = kvmppc_get_gpr(vcpu, rs);
			switch (sprn) {
			case SPRN_SRR0:
				vcpu->arch.shared->srr0 = spr_val;
				break;
			case SPRN_SRR1:
				vcpu->arch.shared->srr1 = spr_val;
				break;

			/* XXX We need to context-switch the timebase for
			 * watchdog and FIT. */
			case SPRN_TBWL: break;
			case SPRN_TBWU: break;

			case SPRN_MSSSR0: break;

			case SPRN_DEC:
				vcpu->arch.dec = spr_val;
				kvmppc_emulate_dec(vcpu);
				break;

			case SPRN_SPRG0:
				vcpu->arch.shared->sprg0 = spr_val;
				break;
			case SPRN_SPRG1:
				vcpu->arch.shared->sprg1 = spr_val;
				break;
			case SPRN_SPRG2:
				vcpu->arch.shared->sprg2 = spr_val;
				break;
			case SPRN_SPRG3:
				vcpu->arch.shared->sprg3 = spr_val;
				break;

			default:
				emulated = kvmppc_core_emulate_mtspr(vcpu, sprn,
								     spr_val);
				if (emulated == EMULATE_FAIL)
					printk(KERN_INFO "mtspr: unknown spr "
						"0x%x\n", sprn);
				break;
			}
			kvmppc_set_exit_type(vcpu, EMULATED_MTSPR_EXITS);
			emulated = kvmppc_emulate_mtspr(vcpu, sprn, rs);
			break;

		case OP_31_XOP_DCBI: