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,

Reply via email to