Skip to content

Commit acde257

Browse files
committed
KVM: PPC: Book3S HV: Add radix checks in real-mode hypercall handlers
POWER9 running a radix guest will take some hypervisor interrupts without going to real mode (turning off the MMU). This means that early hypercall handlers may now be called in virtual mode. Most of the handlers work just fine in both modes, but there are some that can crash the host if called in virtual mode, notably the TCE (IOMMU) hypercalls H_PUT_TCE, H_STUFF_TCE and H_PUT_TCE_INDIRECT. These already have both a real-mode and a virtual-mode version, so we arrange for the real-mode version to return H_TOO_HARD for radix guests, which will result in the virtual-mode version being called. The other hypercall which is sensitive to the MMU mode is H_RANDOM. It doesn't have a virtual-mode version, so this adds code to enable it to be called in either mode. An alternative solution was considered which would refuse to call any of the early hypercall handlers when doing a virtual-mode exit from a radix guest. However, the XICS-on-XIVE code depends on the XICS hypercalls being handled early even for virtual-mode exits, because the handlers need to be called before the XIVE vCPU state has been pulled off the hardware. Therefore that solution would have become quite invasive and complicated, and was rejected in favour of the simpler, though less elegant, solution presented here. Reviewed-by: David Gibson <[email protected]> Tested-by: David Gibson <[email protected]> Signed-off-by: Paul Mackerras <[email protected]>
1 parent 36c344f commit acde257

File tree

2 files changed

+21
-1
lines changed

2 files changed

+21
-1
lines changed

arch/powerpc/kvm/book3s_64_vio_hv.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -301,6 +301,10 @@ long kvmppc_rm_h_put_tce(struct kvm_vcpu *vcpu, unsigned long liobn,
301301
/* udbg_printf("H_PUT_TCE(): liobn=0x%lx ioba=0x%lx, tce=0x%lx\n", */
302302
/* liobn, ioba, tce); */
303303

304+
/* For radix, we might be in virtual mode, so punt */
305+
if (kvm_is_radix(vcpu->kvm))
306+
return H_TOO_HARD;
307+
304308
stt = kvmppc_find_table(vcpu->kvm, liobn);
305309
if (!stt)
306310
return H_TOO_HARD;
@@ -381,6 +385,10 @@ long kvmppc_rm_h_put_tce_indirect(struct kvm_vcpu *vcpu,
381385
bool prereg = false;
382386
struct kvmppc_spapr_tce_iommu_table *stit;
383387

388+
/* For radix, we might be in virtual mode, so punt */
389+
if (kvm_is_radix(vcpu->kvm))
390+
return H_TOO_HARD;
391+
384392
stt = kvmppc_find_table(vcpu->kvm, liobn);
385393
if (!stt)
386394
return H_TOO_HARD;
@@ -491,6 +499,10 @@ long kvmppc_rm_h_stuff_tce(struct kvm_vcpu *vcpu,
491499
long i, ret;
492500
struct kvmppc_spapr_tce_iommu_table *stit;
493501

502+
/* For radix, we might be in virtual mode, so punt */
503+
if (kvm_is_radix(vcpu->kvm))
504+
return H_TOO_HARD;
505+
494506
stt = kvmppc_find_table(vcpu->kvm, liobn);
495507
if (!stt)
496508
return H_TOO_HARD;
@@ -527,6 +539,7 @@ long kvmppc_rm_h_stuff_tce(struct kvm_vcpu *vcpu,
527539
return H_SUCCESS;
528540
}
529541

542+
/* This can be called in either virtual mode or real mode */
530543
long kvmppc_h_get_tce(struct kvm_vcpu *vcpu, unsigned long liobn,
531544
unsigned long ioba)
532545
{

arch/powerpc/kvm/book3s_hv_builtin.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,14 @@ EXPORT_SYMBOL_GPL(kvmppc_hwrng_present);
207207

208208
long kvmppc_h_random(struct kvm_vcpu *vcpu)
209209
{
210-
if (powernv_get_random_real_mode(&vcpu->arch.gpr[4]))
210+
int r;
211+
212+
/* Only need to do the expensive mfmsr() on radix */
213+
if (kvm_is_radix(vcpu->kvm) && (mfmsr() & MSR_IR))
214+
r = powernv_get_random_long(&vcpu->arch.gpr[4]);
215+
else
216+
r = powernv_get_random_real_mode(&vcpu->arch.gpr[4]);
217+
if (r)
211218
return H_SUCCESS;
212219

213220
return H_HARDWARE;

0 commit comments

Comments
 (0)