Nicholas Piggin <npig...@gmail.com> writes: > KVM PR does not implement address translation modes on interrupt, so it > must not allow H_SET_MODE to succeed. The behaviour change caused by > this mode is architected and not advisory (interrupts *must* behave > differently). > > QEMU does not deal with differences in AIL support in the host. The > solution to that is a spapr capability and corresponding KVM CAP, but > this patch does not break things more than before (the host behaviour > already differs, this change just disallows some modes that are not > implemented properly). > > By happy coincidence, this allows PR Linux guests that are using the SCV > facility to boot and run, because Linux disables the use of SCV if AIL > can not be set to 3. This does not fix the underlying problem of missing > SCV support (an OS could implement real-mode SCV vectors and try to > enable the facility). The true fix for that is for KVM PR to emulate scv > interrupts from the facility unavailable interrupt. > > Signed-off-by: Nicholas Piggin <npig...@gmail.com>
Reviewed-by: Fabiano Rosas <faro...@linux.ibm.com> > --- > arch/powerpc/kvm/book3s_pr_papr.c | 20 ++++++++++++++++++++ > 1 file changed, 20 insertions(+) > > diff --git a/arch/powerpc/kvm/book3s_pr_papr.c > b/arch/powerpc/kvm/book3s_pr_papr.c > index 1f10e7dfcdd0..dc4f51ac84bc 100644 > --- a/arch/powerpc/kvm/book3s_pr_papr.c > +++ b/arch/powerpc/kvm/book3s_pr_papr.c > @@ -281,6 +281,22 @@ static int kvmppc_h_pr_logical_ci_store(struct kvm_vcpu > *vcpu) > return EMULATE_DONE; > } > > +static int kvmppc_h_pr_set_mode(struct kvm_vcpu *vcpu) > +{ > + unsigned long mflags = kvmppc_get_gpr(vcpu, 4); > + unsigned long resource = kvmppc_get_gpr(vcpu, 5); > + > + if (resource == H_SET_MODE_RESOURCE_ADDR_TRANS_MODE) { > + /* KVM PR does not provide AIL!=0 to guests */ > + if (mflags == 0) > + kvmppc_set_gpr(vcpu, 3, H_SUCCESS); > + else > + kvmppc_set_gpr(vcpu, 3, H_UNSUPPORTED_FLAG_START - 63); > + return EMULATE_DONE; > + } > + return EMULATE_FAIL; > +} > + > #ifdef CONFIG_SPAPR_TCE_IOMMU > static int kvmppc_h_pr_put_tce(struct kvm_vcpu *vcpu) > { > @@ -384,6 +400,8 @@ int kvmppc_h_pr(struct kvm_vcpu *vcpu, unsigned long cmd) > return kvmppc_h_pr_logical_ci_load(vcpu); > case H_LOGICAL_CI_STORE: > return kvmppc_h_pr_logical_ci_store(vcpu); > + case H_SET_MODE: > + return kvmppc_h_pr_set_mode(vcpu); > case H_XIRR: > case H_CPPR: > case H_EOI: > @@ -421,6 +439,7 @@ int kvmppc_hcall_impl_pr(unsigned long cmd) > case H_CEDE: > case H_LOGICAL_CI_LOAD: > case H_LOGICAL_CI_STORE: > + case H_SET_MODE: > #ifdef CONFIG_KVM_XICS > case H_XIRR: > case H_CPPR: > @@ -447,6 +466,7 @@ static unsigned int default_hcall_list[] = { > H_BULK_REMOVE, > H_PUT_TCE, > H_CEDE, > + H_SET_MODE, > #ifdef CONFIG_KVM_XICS > H_XIRR, > H_CPPR,