int kvmppc_core_emulate_mfspr_pr()

in kvm/book3s_emulate.c [864:1032]


int kvmppc_core_emulate_mfspr_pr(struct kvm_vcpu *vcpu, int sprn, ulong *spr_val)
{
	int emulated = EMULATE_DONE;

	switch (sprn) {
	case SPRN_IBAT0U ... SPRN_IBAT3L:
	case SPRN_IBAT4U ... SPRN_IBAT7L:
	case SPRN_DBAT0U ... SPRN_DBAT3L:
	case SPRN_DBAT4U ... SPRN_DBAT7L:
	{
		struct kvmppc_bat *bat = kvmppc_find_bat(vcpu, sprn);

		if (sprn % 2)
			*spr_val = bat->raw >> 32;
		else
			*spr_val = bat->raw;

		break;
	}
	case SPRN_SDR1:
		if (!spr_allowed(vcpu, PRIV_HYPER))
			goto unprivileged;
		*spr_val = to_book3s(vcpu)->sdr1;
		break;
	case SPRN_DSISR:
		*spr_val = kvmppc_get_dsisr(vcpu);
		break;
	case SPRN_DAR:
		*spr_val = kvmppc_get_dar(vcpu);
		break;
	case SPRN_HIOR:
		*spr_val = to_book3s(vcpu)->hior;
		break;
	case SPRN_HID0:
		*spr_val = to_book3s(vcpu)->hid[0];
		break;
	case SPRN_HID1:
		*spr_val = to_book3s(vcpu)->hid[1];
		break;
	case SPRN_HID2:
	case SPRN_HID2_GEKKO:
		*spr_val = to_book3s(vcpu)->hid[2];
		break;
	case SPRN_HID4:
	case SPRN_HID4_GEKKO:
		*spr_val = to_book3s(vcpu)->hid[4];
		break;
	case SPRN_HID5:
		*spr_val = to_book3s(vcpu)->hid[5];
		break;
	case SPRN_CFAR:
	case SPRN_DSCR:
		*spr_val = 0;
		break;
	case SPRN_PURR:
		/*
		 * On exit we would have updated purr
		 */
		*spr_val = vcpu->arch.purr;
		break;
	case SPRN_SPURR:
		/*
		 * On exit we would have updated spurr
		 */
		*spr_val = vcpu->arch.spurr;
		break;
	case SPRN_VTB:
		*spr_val = to_book3s(vcpu)->vtb;
		break;
	case SPRN_IC:
		*spr_val = vcpu->arch.ic;
		break;
	case SPRN_GQR0:
	case SPRN_GQR1:
	case SPRN_GQR2:
	case SPRN_GQR3:
	case SPRN_GQR4:
	case SPRN_GQR5:
	case SPRN_GQR6:
	case SPRN_GQR7:
		*spr_val = to_book3s(vcpu)->gqr[sprn - SPRN_GQR0];
		break;
#ifdef CONFIG_PPC_BOOK3S_64
	case SPRN_FSCR:
		*spr_val = vcpu->arch.fscr;
		break;
	case SPRN_BESCR:
		*spr_val = vcpu->arch.bescr;
		break;
	case SPRN_EBBHR:
		*spr_val = vcpu->arch.ebbhr;
		break;
	case SPRN_EBBRR:
		*spr_val = vcpu->arch.ebbrr;
		break;
#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
	case SPRN_TFHAR:
	case SPRN_TEXASR:
	case SPRN_TFIAR:
		if (!cpu_has_feature(CPU_FTR_TM))
			break;

		if (!(kvmppc_get_msr(vcpu) & MSR_TM)) {
			kvmppc_trigger_fac_interrupt(vcpu, FSCR_TM_LG);
			emulated = EMULATE_AGAIN;
			break;
		}

		tm_enable();
		if (sprn == SPRN_TFHAR)
			*spr_val = mfspr(SPRN_TFHAR);
		else if (sprn == SPRN_TEXASR)
			*spr_val = mfspr(SPRN_TEXASR);
		else if (sprn == SPRN_TFIAR)
			*spr_val = mfspr(SPRN_TFIAR);
		tm_disable();
		break;
#endif
#endif
	case SPRN_THRM1:
	case SPRN_THRM2:
	case SPRN_THRM3:
	case SPRN_CTRLF:
	case SPRN_CTRLT:
	case SPRN_L2CR:
	case SPRN_MMCR0_GEKKO:
	case SPRN_MMCR1_GEKKO:
	case SPRN_PMC1_GEKKO:
	case SPRN_PMC2_GEKKO:
	case SPRN_PMC3_GEKKO:
	case SPRN_PMC4_GEKKO:
	case SPRN_WPAR_GEKKO:
	case SPRN_MSSSR0:
	case SPRN_DABR:
#ifdef CONFIG_PPC_BOOK3S_64
	case SPRN_MMCRS:
	case SPRN_MMCRA:
	case SPRN_MMCR0:
	case SPRN_MMCR1:
	case SPRN_MMCR2:
	case SPRN_UMMCR2:
	case SPRN_TIR:
	case SPRN_UAMOR:
	case SPRN_IAMR:
	case SPRN_AMR:
#endif
		*spr_val = 0;
		break;
	default:
unprivileged:
		pr_info_ratelimited("KVM: invalid SPR read: %d\n", sprn);
		if (sprn & 0x10) {
			if (kvmppc_get_msr(vcpu) & MSR_PR) {
				kvmppc_core_queue_program(vcpu, SRR1_PROGPRIV);
				emulated = EMULATE_AGAIN;
			}
		} else {
			if ((kvmppc_get_msr(vcpu) & MSR_PR) || sprn == 0 ||
			    sprn == 4 || sprn == 5 || sprn == 6) {
				kvmppc_core_queue_program(vcpu, SRR1_PROGILL);
				emulated = EMULATE_AGAIN;
			}
		}

		break;
	}

	return emulated;
}