Commit 65acb891 authored by Radim Krčmář's avatar Radim Krčmář

Merge branch 'kvm-ppc-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc

- fix build failures with PR KVM configurations
- fix a host crash that can occur on POWER9 with radix guests
parents 2ea659a9 76d837a4
...@@ -67,7 +67,7 @@ config KVM_BOOK3S_64 ...@@ -67,7 +67,7 @@ config KVM_BOOK3S_64
select KVM_BOOK3S_64_HANDLER select KVM_BOOK3S_64_HANDLER
select KVM select KVM
select KVM_BOOK3S_PR_POSSIBLE if !KVM_BOOK3S_HV_POSSIBLE 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--- ---help---
Support running unmodified book3s_64 and book3s_32 guest kernels Support running unmodified book3s_64 and book3s_32 guest kernels
in virtual machines on book3s_64 host processors. in virtual machines on book3s_64 host processors.
......
...@@ -46,7 +46,7 @@ kvm-e500mc-objs := \ ...@@ -46,7 +46,7 @@ kvm-e500mc-objs := \
e500_emulate.o e500_emulate.o
kvm-objs-$(CONFIG_KVM_E500MC) := $(kvm-e500mc-objs) 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 book3s_64_vio_hv.o
kvm-pr-y := \ kvm-pr-y := \
...@@ -90,11 +90,11 @@ kvm-book3s_64-objs-$(CONFIG_KVM_XICS) += \ ...@@ -90,11 +90,11 @@ kvm-book3s_64-objs-$(CONFIG_KVM_XICS) += \
book3s_xics.o book3s_xics.o
kvm-book3s_64-objs-$(CONFIG_KVM_XIVE) += book3s_xive.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 := \ kvm-book3s_64-module-objs := \
$(common-objs-y) \ $(common-objs-y) \
book3s.o \ book3s.o \
book3s_64_vio.o \
book3s_rtas.o \ book3s_rtas.o \
$(kvm-book3s_64-objs-y) $(kvm-book3s_64-objs-y)
......
...@@ -301,6 +301,10 @@ long kvmppc_rm_h_put_tce(struct kvm_vcpu *vcpu, unsigned long liobn, ...@@ -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", */ /* udbg_printf("H_PUT_TCE(): liobn=0x%lx ioba=0x%lx, tce=0x%lx\n", */
/* liobn, ioba, tce); */ /* 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); stt = kvmppc_find_table(vcpu->kvm, liobn);
if (!stt) if (!stt)
return H_TOO_HARD; return H_TOO_HARD;
...@@ -381,6 +385,10 @@ long kvmppc_rm_h_put_tce_indirect(struct kvm_vcpu *vcpu, ...@@ -381,6 +385,10 @@ long kvmppc_rm_h_put_tce_indirect(struct kvm_vcpu *vcpu,
bool prereg = false; bool prereg = false;
struct kvmppc_spapr_tce_iommu_table *stit; 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); stt = kvmppc_find_table(vcpu->kvm, liobn);
if (!stt) if (!stt)
return H_TOO_HARD; return H_TOO_HARD;
...@@ -491,6 +499,10 @@ long kvmppc_rm_h_stuff_tce(struct kvm_vcpu *vcpu, ...@@ -491,6 +499,10 @@ long kvmppc_rm_h_stuff_tce(struct kvm_vcpu *vcpu,
long i, ret; long i, ret;
struct kvmppc_spapr_tce_iommu_table *stit; 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); stt = kvmppc_find_table(vcpu->kvm, liobn);
if (!stt) if (!stt)
return H_TOO_HARD; return H_TOO_HARD;
...@@ -527,6 +539,7 @@ long kvmppc_rm_h_stuff_tce(struct kvm_vcpu *vcpu, ...@@ -527,6 +539,7 @@ long kvmppc_rm_h_stuff_tce(struct kvm_vcpu *vcpu,
return H_SUCCESS; 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, long kvmppc_h_get_tce(struct kvm_vcpu *vcpu, unsigned long liobn,
unsigned long ioba) unsigned long ioba)
{ {
......
...@@ -207,7 +207,14 @@ EXPORT_SYMBOL_GPL(kvmppc_hwrng_present); ...@@ -207,7 +207,14 @@ EXPORT_SYMBOL_GPL(kvmppc_hwrng_present);
long kvmppc_h_random(struct kvm_vcpu *vcpu) 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_SUCCESS;
return H_HARDWARE; return H_HARDWARE;
......
...@@ -50,7 +50,9 @@ static int kvmppc_h_pr_enter(struct kvm_vcpu *vcpu) ...@@ -50,7 +50,9 @@ static int kvmppc_h_pr_enter(struct kvm_vcpu *vcpu)
pteg_addr = get_pteg_addr(vcpu, pte_index); pteg_addr = get_pteg_addr(vcpu, pte_index);
mutex_lock(&vcpu->kvm->arch.hpt_mutex); 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; hpte = pteg;
ret = H_PTEG_FULL; ret = H_PTEG_FULL;
...@@ -71,7 +73,9 @@ static int kvmppc_h_pr_enter(struct kvm_vcpu *vcpu) ...@@ -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[0] = cpu_to_be64(kvmppc_get_gpr(vcpu, 6));
hpte[1] = cpu_to_be64(kvmppc_get_gpr(vcpu, 7)); hpte[1] = cpu_to_be64(kvmppc_get_gpr(vcpu, 7));
pteg_addr += i * HPTE_SIZE; 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); kvmppc_set_gpr(vcpu, 4, pte_index | i);
ret = H_SUCCESS; ret = H_SUCCESS;
...@@ -93,7 +97,9 @@ static int kvmppc_h_pr_remove(struct kvm_vcpu *vcpu) ...@@ -93,7 +97,9 @@ static int kvmppc_h_pr_remove(struct kvm_vcpu *vcpu)
pteg = get_pteg_addr(vcpu, pte_index); pteg = get_pteg_addr(vcpu, pte_index);
mutex_lock(&vcpu->kvm->arch.hpt_mutex); 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[0] = be64_to_cpu((__force __be64)pte[0]);
pte[1] = be64_to_cpu((__force __be64)pte[1]); pte[1] = be64_to_cpu((__force __be64)pte[1]);
...@@ -103,7 +109,9 @@ static int kvmppc_h_pr_remove(struct kvm_vcpu *vcpu) ...@@ -103,7 +109,9 @@ static int kvmppc_h_pr_remove(struct kvm_vcpu *vcpu)
((flags & H_ANDCOND) && (pte[0] & avpn) != 0)) ((flags & H_ANDCOND) && (pte[0] & avpn) != 0))
goto done; 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); rb = compute_tlbie_rb(pte[0], pte[1], pte_index);
vcpu->arch.mmu.tlbie(vcpu, rb, rb & 1 ? true : false); 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) ...@@ -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); 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[0] = be64_to_cpu((__force __be64)pte[0]);
pte[1] = be64_to_cpu((__force __be64)pte[1]); pte[1] = be64_to_cpu((__force __be64)pte[1]);
...@@ -184,7 +195,10 @@ static int kvmppc_h_pr_bulk_remove(struct kvm_vcpu *vcpu) ...@@ -184,7 +195,10 @@ static int kvmppc_h_pr_bulk_remove(struct kvm_vcpu *vcpu)
tsh |= H_BULK_REMOVE_NOT_FOUND; tsh |= H_BULK_REMOVE_NOT_FOUND;
} else { } else {
/* Splat the pteg in (userland) hpt */ /* 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], rb = compute_tlbie_rb(pte[0], pte[1],
tsh & H_BULK_REMOVE_PTEX); tsh & H_BULK_REMOVE_PTEX);
...@@ -211,7 +225,9 @@ static int kvmppc_h_pr_protect(struct kvm_vcpu *vcpu) ...@@ -211,7 +225,9 @@ static int kvmppc_h_pr_protect(struct kvm_vcpu *vcpu)
pteg = get_pteg_addr(vcpu, pte_index); pteg = get_pteg_addr(vcpu, pte_index);
mutex_lock(&vcpu->kvm->arch.hpt_mutex); 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[0] = be64_to_cpu((__force __be64)pte[0]);
pte[1] = be64_to_cpu((__force __be64)pte[1]); pte[1] = be64_to_cpu((__force __be64)pte[1]);
...@@ -234,7 +250,9 @@ static int kvmppc_h_pr_protect(struct kvm_vcpu *vcpu) ...@@ -234,7 +250,9 @@ static int kvmppc_h_pr_protect(struct kvm_vcpu *vcpu)
vcpu->arch.mmu.tlbie(vcpu, rb, rb & 1 ? true : false); vcpu->arch.mmu.tlbie(vcpu, rb, rb & 1 ? true : false);
pte[0] = (__force u64)cpu_to_be64(pte[0]); pte[0] = (__force u64)cpu_to_be64(pte[0]);
pte[1] = (__force u64)cpu_to_be64(pte[1]); 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; ret = H_SUCCESS;
done: done:
...@@ -244,36 +262,37 @@ static int kvmppc_h_pr_protect(struct kvm_vcpu *vcpu) ...@@ -244,36 +262,37 @@ static int kvmppc_h_pr_protect(struct kvm_vcpu *vcpu)
return EMULATE_DONE; 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; long rc;
rc = kvmppc_h_put_tce(vcpu, liobn, ioba, tce); rc = kvmppc_h_logical_ci_load(vcpu);
if (rc == H_TOO_HARD) if (rc == H_TOO_HARD)
return EMULATE_FAIL; return EMULATE_FAIL;
kvmppc_set_gpr(vcpu, 3, rc); kvmppc_set_gpr(vcpu, 3, rc);
return EMULATE_DONE; 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; long rc;
rc = kvmppc_h_logical_ci_load(vcpu); rc = kvmppc_h_logical_ci_store(vcpu);
if (rc == H_TOO_HARD) if (rc == H_TOO_HARD)
return EMULATE_FAIL; return EMULATE_FAIL;
kvmppc_set_gpr(vcpu, 3, rc); kvmppc_set_gpr(vcpu, 3, rc);
return EMULATE_DONE; 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; long rc;
rc = kvmppc_h_logical_ci_store(vcpu); rc = kvmppc_h_put_tce(vcpu, liobn, ioba, tce);
if (rc == H_TOO_HARD) if (rc == H_TOO_HARD)
return EMULATE_FAIL; return EMULATE_FAIL;
kvmppc_set_gpr(vcpu, 3, rc); kvmppc_set_gpr(vcpu, 3, rc);
...@@ -311,6 +330,23 @@ static int kvmppc_h_pr_stuff_tce(struct kvm_vcpu *vcpu) ...@@ -311,6 +330,23 @@ static int kvmppc_h_pr_stuff_tce(struct kvm_vcpu *vcpu)
return EMULATE_DONE; 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) static int kvmppc_h_pr_xics_hcall(struct kvm_vcpu *vcpu, u32 cmd)
{ {
long rc = kvmppc_xics_hcall(vcpu, cmd); long rc = kvmppc_xics_hcall(vcpu, cmd);
......
...@@ -1749,7 +1749,7 @@ long kvm_arch_vm_ioctl(struct file *filp, ...@@ -1749,7 +1749,7 @@ long kvm_arch_vm_ioctl(struct file *filp,
r = kvm_vm_ioctl_enable_cap(kvm, &cap); r = kvm_vm_ioctl_enable_cap(kvm, &cap);
break; break;
} }
#ifdef CONFIG_PPC_BOOK3S_64 #ifdef CONFIG_SPAPR_TCE_IOMMU
case KVM_CREATE_SPAPR_TCE_64: { case KVM_CREATE_SPAPR_TCE_64: {
struct kvm_create_spapr_tce_64 create_tce_64; struct kvm_create_spapr_tce_64 create_tce_64;
...@@ -1780,6 +1780,8 @@ long kvm_arch_vm_ioctl(struct file *filp, ...@@ -1780,6 +1780,8 @@ long kvm_arch_vm_ioctl(struct file *filp,
r = kvm_vm_ioctl_create_spapr_tce(kvm, &create_tce_64); r = kvm_vm_ioctl_create_spapr_tce(kvm, &create_tce_64);
goto out; goto out;
} }
#endif
#ifdef CONFIG_PPC_BOOK3S_64
case KVM_PPC_GET_SMMU_INFO: { case KVM_PPC_GET_SMMU_INFO: {
struct kvm_ppc_smmu_info info; struct kvm_ppc_smmu_info info;
struct kvm *kvm = filp->private_data; struct kvm *kvm = filp->private_data;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment