The routine ar_translation() can be reached by both the instruction
intercept path (where the access registers had been loaded with the
guest register contents), and the MEM_OP ioctls (which hadn't).
This latter case means that any ALET the guest expects to be used
would be ignored.

Fix this by swapping the host/guest access registers around the
MEM_OP ioctl, in the same way that the KVM_RUN ioctl does with
sync_regs()/store_regs(). The full register swap isn't needed here,
since only the access registers are used in this interface.

Introduce a boolean in the kvm_vcpu_arch struct to indicate the
guest ARs have been loaded into the registers. This permits a
warning to be emitted if entering this path without a proper
register setup.

Suggested-by: Christian Borntraeger <[email protected]>
Signed-off-by: Eric Farman <[email protected]>
---
 arch/s390/include/asm/kvm_host.h |  1 +
 arch/s390/kvm/gaccess.c          |  2 ++
 arch/s390/kvm/kvm-s390.c         | 11 +++++++++++
 3 files changed, 14 insertions(+)

diff --git a/arch/s390/include/asm/kvm_host.h b/arch/s390/include/asm/kvm_host.h
index 52664105a473..c86215eb4ca7 100644
--- a/arch/s390/include/asm/kvm_host.h
+++ b/arch/s390/include/asm/kvm_host.h
@@ -765,6 +765,7 @@ struct kvm_vcpu_arch {
        __u64 cputm_start;
        bool gs_enabled;
        bool skey_enabled;
+       bool acrs_loaded;
        struct kvm_s390_pv_vcpu pv;
        union diag318_info diag318_info;
 };
diff --git a/arch/s390/kvm/gaccess.c b/arch/s390/kvm/gaccess.c
index 5bfcc50c1a68..33587bb4c9e8 100644
--- a/arch/s390/kvm/gaccess.c
+++ b/arch/s390/kvm/gaccess.c
@@ -391,6 +391,8 @@ static int ar_translation(struct kvm_vcpu *vcpu, union asce 
*asce, u8 ar,
        if (ar >= NUM_ACRS)
                return -EINVAL;
 
+       WARN_ON_ONCE(!vcpu->arch.acrs_loaded);
+
        save_access_regs(vcpu->run->s.regs.acrs);
        alet.val = vcpu->run->s.regs.acrs[ar];
 
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
index ea63ac769889..c60ec561f7f1 100644
--- a/arch/s390/kvm/kvm-s390.c
+++ b/arch/s390/kvm/kvm-s390.c
@@ -3951,6 +3951,7 @@ int kvm_arch_vcpu_create(struct kvm_vcpu *vcpu)
                                    KVM_SYNC_ARCH0 |
                                    KVM_SYNC_PFAULT |
                                    KVM_SYNC_DIAG318;
+       vcpu->arch.acrs_loaded = false;
        kvm_s390_set_prefix(vcpu, 0);
        if (test_kvm_facility(vcpu->kvm, 64))
                vcpu->run->kvm_valid_regs |= KVM_SYNC_RICCB;
@@ -4951,6 +4952,7 @@ static void sync_regs(struct kvm_vcpu *vcpu)
        }
        save_access_regs(vcpu->arch.host_acrs);
        restore_access_regs(vcpu->run->s.regs.acrs);
+       vcpu->arch.acrs_loaded = true;
        /* save host (userspace) fprs/vrs */
        save_fpu_regs();
        vcpu->arch.host_fpregs.fpc = current->thread.fpu.fpc;
@@ -5021,6 +5023,7 @@ static void store_regs(struct kvm_vcpu *vcpu)
        kvm_run->s.regs.pfc = vcpu->arch.pfault_compare;
        save_access_regs(vcpu->run->s.regs.acrs);
        restore_access_regs(vcpu->arch.host_acrs);
+       vcpu->arch.acrs_loaded = false;
        /* Save guest register state */
        save_fpu_regs();
        vcpu->run->s.regs.fpc = current->thread.fpu.fpc;
@@ -5391,6 +5394,11 @@ static long kvm_s390_vcpu_mem_op(struct kvm_vcpu *vcpu,
                        return -ENOMEM;
        }
 
+       /* Swap host/guest access registers */
+       save_access_regs(vcpu->arch.host_acrs);
+       restore_access_regs(vcpu->run->s.regs.acrs);
+       vcpu->arch.acrs_loaded = true;
+
        acc_mode = mop->op == KVM_S390_MEMOP_LOGICAL_READ ? GACC_FETCH : 
GACC_STORE;
        if (mop->flags & KVM_S390_MEMOP_F_CHECK_ONLY) {
                r = check_gva_range(vcpu, mop->gaddr, mop->ar, mop->size,
@@ -5420,6 +5428,9 @@ static long kvm_s390_vcpu_mem_op(struct kvm_vcpu *vcpu,
                kvm_s390_inject_prog_irq(vcpu, &vcpu->arch.pgm);
 
 out_free:
+       save_access_regs(vcpu->run->s.regs.acrs);
+       restore_access_regs(vcpu->arch.host_acrs);
+       vcpu->arch.acrs_loaded = false;
        vfree(tmpbuf);
        return r;
 }
-- 
2.40.1


Reply via email to