Commit 01be7f53 authored by Eric Farman's avatar Eric Farman Committed by Heiko Carstens
Browse files

KVM: s390: fix access register usage in ioctls



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).
Since this routine saves the current registers to vcpu->run,
this routine erroneously saves host registers into the guest space.

Introduce a boolean in the kvm_vcpu_arch struct to indicate whether
the registers contain guest contents. If they do (the instruction
intercept path), the save can be performed and the AR translation
is done just as it is today. If they don't (the MEM_OP path), the
AR can be read from vcpu->run without stashing the current contents.

Reviewed-by: default avatarHeiko Carstens <hca@linux.ibm.com>
Reviewed-by: default avatarNina Schoetterl-Glausch <nsg@linux.ibm.com>
Reviewed-by: default avatarChristian Borntraeger <borntraeger@linux.ibm.com>
Signed-off-by: default avatarEric Farman <farman@linux.ibm.com>
Link: https://lore.kernel.org/r/20240220211211.3102609-2-farman@linux.ibm.com


Signed-off-by: default avatarHeiko Carstens <hca@linux.ibm.com>
parent 4a599328
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -764,6 +764,8 @@ struct kvm_vcpu_arch {
	__u64 cputm_start;
	bool gs_enabled;
	bool skey_enabled;
	/* Indicator if the access registers have been loaded from guest */
	bool acrs_loaded;
	struct kvm_s390_pv_vcpu pv;
	union diag318_info diag318_info;
};
+2 −1
Original line number Diff line number Diff line
@@ -391,6 +391,7 @@ static int ar_translation(struct kvm_vcpu *vcpu, union asce *asce, u8 ar,
	if (ar >= NUM_ACRS)
		return -EINVAL;

	if (vcpu->arch.acrs_loaded)
		save_access_regs(vcpu->run->s.regs.acrs);
	alet.val = vcpu->run->s.regs.acrs[ar];

+3 −0
Original line number Diff line number Diff line
@@ -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;
@@ -4949,6 +4950,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;
	kvm_s390_fpu_load(vcpu->run);
	/* Sync fmt2 only data */
	if (likely(!kvm_s390_pv_cpu_is_protected(vcpu))) {
@@ -5010,6 +5012,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;
	kvm_s390_fpu_store(vcpu->run);
	if (likely(!kvm_s390_pv_cpu_is_protected(vcpu)))
		store_regs_fmt2(vcpu);