Commit 65acb891 authored by Radim Krčmář's avatar Radim Krčmář
Browse files
- fix build failures with PR KVM configurations
- fix a host crash that can occur on POWER9 with radix guests
parents 2ea659a9 76d837a4
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -67,7 +67,7 @@ config KVM_BOOK3S_64
	select KVM_BOOK3S_64_HANDLER
	select KVM
	select KVM_BOOK3S_PR_POSSIBLE if !KVM_BOOK3S_HV_POSSIBLE
	select SPAPR_TCE_IOMMU if IOMMU_SUPPORT
	select SPAPR_TCE_IOMMU if IOMMU_SUPPORT && (PPC_SERIES || PPC_POWERNV)
	---help---
	  Support running unmodified book3s_64 and book3s_32 guest kernels
	  in virtual machines on book3s_64 host processors.
+2 −2
Original line number Diff line number Diff line
@@ -46,7 +46,7 @@ kvm-e500mc-objs := \
	e500_emulate.o
kvm-objs-$(CONFIG_KVM_E500MC) := $(kvm-e500mc-objs)

kvm-book3s_64-builtin-objs-$(CONFIG_KVM_BOOK3S_64_HANDLER) := \
kvm-book3s_64-builtin-objs-$(CONFIG_SPAPR_TCE_IOMMU) := \
	book3s_64_vio_hv.o

kvm-pr-y := \
@@ -90,11 +90,11 @@ kvm-book3s_64-objs-$(CONFIG_KVM_XICS) += \
	book3s_xics.o

kvm-book3s_64-objs-$(CONFIG_KVM_XIVE) += book3s_xive.o
kvm-book3s_64-objs-$(CONFIG_SPAPR_TCE_IOMMU) += book3s_64_vio.o

kvm-book3s_64-module-objs := \
	$(common-objs-y) \
	book3s.o \
	book3s_64_vio.o \
	book3s_rtas.o \
	$(kvm-book3s_64-objs-y)

+13 −0
Original line number Diff line number Diff line
@@ -301,6 +301,10 @@ long kvmppc_rm_h_put_tce(struct kvm_vcpu *vcpu, unsigned long liobn,
	/* udbg_printf("H_PUT_TCE(): liobn=0x%lx ioba=0x%lx, tce=0x%lx\n", */
	/* 	    liobn, ioba, tce); */

	/* For radix, we might be in virtual mode, so punt */
	if (kvm_is_radix(vcpu->kvm))
		return H_TOO_HARD;

	stt = kvmppc_find_table(vcpu->kvm, liobn);
	if (!stt)
		return H_TOO_HARD;
@@ -381,6 +385,10 @@ long kvmppc_rm_h_put_tce_indirect(struct kvm_vcpu *vcpu,
	bool prereg = false;
	struct kvmppc_spapr_tce_iommu_table *stit;

	/* For radix, we might be in virtual mode, so punt */
	if (kvm_is_radix(vcpu->kvm))
		return H_TOO_HARD;

	stt = kvmppc_find_table(vcpu->kvm, liobn);
	if (!stt)
		return H_TOO_HARD;
@@ -491,6 +499,10 @@ long kvmppc_rm_h_stuff_tce(struct kvm_vcpu *vcpu,
	long i, ret;
	struct kvmppc_spapr_tce_iommu_table *stit;

	/* For radix, we might be in virtual mode, so punt */
	if (kvm_is_radix(vcpu->kvm))
		return H_TOO_HARD;

	stt = kvmppc_find_table(vcpu->kvm, liobn);
	if (!stt)
		return H_TOO_HARD;
@@ -527,6 +539,7 @@ long kvmppc_rm_h_stuff_tce(struct kvm_vcpu *vcpu,
	return H_SUCCESS;
}

/* This can be called in either virtual mode or real mode */
long kvmppc_h_get_tce(struct kvm_vcpu *vcpu, unsigned long liobn,
		      unsigned long ioba)
{
+8 −1
Original line number Diff line number Diff line
@@ -207,7 +207,14 @@ EXPORT_SYMBOL_GPL(kvmppc_hwrng_present);

long kvmppc_h_random(struct kvm_vcpu *vcpu)
{
	if (powernv_get_random_real_mode(&vcpu->arch.gpr[4]))
	int r;

	/* Only need to do the expensive mfmsr() on radix */
	if (kvm_is_radix(vcpu->kvm) && (mfmsr() & MSR_IR))
		r = powernv_get_random_long(&vcpu->arch.gpr[4]);
	else
		r = powernv_get_random_real_mode(&vcpu->arch.gpr[4]);
	if (r)
		return H_SUCCESS;

	return H_HARDWARE;
+53 −17
Original line number Diff line number Diff line
@@ -50,7 +50,9 @@ static int kvmppc_h_pr_enter(struct kvm_vcpu *vcpu)
	pteg_addr = get_pteg_addr(vcpu, pte_index);

	mutex_lock(&vcpu->kvm->arch.hpt_mutex);
	copy_from_user(pteg, (void __user *)pteg_addr, sizeof(pteg));
	ret = H_FUNCTION;
	if (copy_from_user(pteg, (void __user *)pteg_addr, sizeof(pteg)))
		goto done;
	hpte = pteg;

	ret = H_PTEG_FULL;
@@ -71,7 +73,9 @@ static int kvmppc_h_pr_enter(struct kvm_vcpu *vcpu)
	hpte[0] = cpu_to_be64(kvmppc_get_gpr(vcpu, 6));
	hpte[1] = cpu_to_be64(kvmppc_get_gpr(vcpu, 7));
	pteg_addr += i * HPTE_SIZE;
	copy_to_user((void __user *)pteg_addr, hpte, HPTE_SIZE);
	ret = H_FUNCTION;
	if (copy_to_user((void __user *)pteg_addr, hpte, HPTE_SIZE))
		goto done;
	kvmppc_set_gpr(vcpu, 4, pte_index | i);
	ret = H_SUCCESS;

@@ -93,7 +97,9 @@ static int kvmppc_h_pr_remove(struct kvm_vcpu *vcpu)

	pteg = get_pteg_addr(vcpu, pte_index);
	mutex_lock(&vcpu->kvm->arch.hpt_mutex);
	copy_from_user(pte, (void __user *)pteg, sizeof(pte));
	ret = H_FUNCTION;
	if (copy_from_user(pte, (void __user *)pteg, sizeof(pte)))
		goto done;
	pte[0] = be64_to_cpu((__force __be64)pte[0]);
	pte[1] = be64_to_cpu((__force __be64)pte[1]);

@@ -103,7 +109,9 @@ static int kvmppc_h_pr_remove(struct kvm_vcpu *vcpu)
	    ((flags & H_ANDCOND) && (pte[0] & avpn) != 0))
		goto done;

	copy_to_user((void __user *)pteg, &v, sizeof(v));
	ret = H_FUNCTION;
	if (copy_to_user((void __user *)pteg, &v, sizeof(v)))
		goto done;

	rb = compute_tlbie_rb(pte[0], pte[1], pte_index);
	vcpu->arch.mmu.tlbie(vcpu, rb, rb & 1 ? true : false);
@@ -171,7 +179,10 @@ static int kvmppc_h_pr_bulk_remove(struct kvm_vcpu *vcpu)
		}

		pteg = get_pteg_addr(vcpu, tsh & H_BULK_REMOVE_PTEX);
		copy_from_user(pte, (void __user *)pteg, sizeof(pte));
		if (copy_from_user(pte, (void __user *)pteg, sizeof(pte))) {
			ret = H_FUNCTION;
			break;
		}
		pte[0] = be64_to_cpu((__force __be64)pte[0]);
		pte[1] = be64_to_cpu((__force __be64)pte[1]);

@@ -184,7 +195,10 @@ static int kvmppc_h_pr_bulk_remove(struct kvm_vcpu *vcpu)
			tsh |= H_BULK_REMOVE_NOT_FOUND;
		} else {
			/* Splat the pteg in (userland) hpt */
			copy_to_user((void __user *)pteg, &v, sizeof(v));
			if (copy_to_user((void __user *)pteg, &v, sizeof(v))) {
				ret = H_FUNCTION;
				break;
			}

			rb = compute_tlbie_rb(pte[0], pte[1],
					      tsh & H_BULK_REMOVE_PTEX);
@@ -211,7 +225,9 @@ static int kvmppc_h_pr_protect(struct kvm_vcpu *vcpu)

	pteg = get_pteg_addr(vcpu, pte_index);
	mutex_lock(&vcpu->kvm->arch.hpt_mutex);
	copy_from_user(pte, (void __user *)pteg, sizeof(pte));
	ret = H_FUNCTION;
	if (copy_from_user(pte, (void __user *)pteg, sizeof(pte)))
		goto done;
	pte[0] = be64_to_cpu((__force __be64)pte[0]);
	pte[1] = be64_to_cpu((__force __be64)pte[1]);

@@ -234,7 +250,9 @@ static int kvmppc_h_pr_protect(struct kvm_vcpu *vcpu)
	vcpu->arch.mmu.tlbie(vcpu, rb, rb & 1 ? true : false);
	pte[0] = (__force u64)cpu_to_be64(pte[0]);
	pte[1] = (__force u64)cpu_to_be64(pte[1]);
	copy_to_user((void __user *)pteg, pte, sizeof(pte));
	ret = H_FUNCTION;
	if (copy_to_user((void __user *)pteg, pte, sizeof(pte)))
		goto done;
	ret = H_SUCCESS;

 done:
@@ -244,36 +262,37 @@ static int kvmppc_h_pr_protect(struct kvm_vcpu *vcpu)
	return EMULATE_DONE;
}

static int kvmppc_h_pr_put_tce(struct kvm_vcpu *vcpu)
static int kvmppc_h_pr_logical_ci_load(struct kvm_vcpu *vcpu)
{
	unsigned long liobn = kvmppc_get_gpr(vcpu, 4);
	unsigned long ioba = kvmppc_get_gpr(vcpu, 5);
	unsigned long tce = kvmppc_get_gpr(vcpu, 6);
	long rc;

	rc = kvmppc_h_put_tce(vcpu, liobn, ioba, tce);
	rc = kvmppc_h_logical_ci_load(vcpu);
	if (rc == H_TOO_HARD)
		return EMULATE_FAIL;
	kvmppc_set_gpr(vcpu, 3, rc);
	return EMULATE_DONE;
}

static int kvmppc_h_pr_logical_ci_load(struct kvm_vcpu *vcpu)
static int kvmppc_h_pr_logical_ci_store(struct kvm_vcpu *vcpu)
{
	long rc;

	rc = kvmppc_h_logical_ci_load(vcpu);
	rc = kvmppc_h_logical_ci_store(vcpu);
	if (rc == H_TOO_HARD)
		return EMULATE_FAIL;
	kvmppc_set_gpr(vcpu, 3, rc);
	return EMULATE_DONE;
}

static int kvmppc_h_pr_logical_ci_store(struct kvm_vcpu *vcpu)
#ifdef CONFIG_SPAPR_TCE_IOMMU
static int kvmppc_h_pr_put_tce(struct kvm_vcpu *vcpu)
{
	unsigned long liobn = kvmppc_get_gpr(vcpu, 4);
	unsigned long ioba = kvmppc_get_gpr(vcpu, 5);
	unsigned long tce = kvmppc_get_gpr(vcpu, 6);
	long rc;

	rc = kvmppc_h_logical_ci_store(vcpu);
	rc = kvmppc_h_put_tce(vcpu, liobn, ioba, tce);
	if (rc == H_TOO_HARD)
		return EMULATE_FAIL;
	kvmppc_set_gpr(vcpu, 3, rc);
@@ -311,6 +330,23 @@ static int kvmppc_h_pr_stuff_tce(struct kvm_vcpu *vcpu)
	return EMULATE_DONE;
}

#else /* CONFIG_SPAPR_TCE_IOMMU */
static int kvmppc_h_pr_put_tce(struct kvm_vcpu *vcpu)
{
	return EMULATE_FAIL;
}

static int kvmppc_h_pr_put_tce_indirect(struct kvm_vcpu *vcpu)
{
	return EMULATE_FAIL;
}

static int kvmppc_h_pr_stuff_tce(struct kvm_vcpu *vcpu)
{
	return EMULATE_FAIL;
}
#endif /* CONFIG_SPAPR_TCE_IOMMU */

static int kvmppc_h_pr_xics_hcall(struct kvm_vcpu *vcpu, u32 cmd)
{
	long rc = kvmppc_xics_hcall(vcpu, cmd);
Loading