Skip to content

Commit ff5dc14

Browse files
David Hildenbrandborntraeger
authored andcommitted
KVM: s390: fix delivery of vector regs during machine checks
Vector registers are only to be stored if the facility is available and if the guest has set up the machine check extended save area. If anything goes wrong while writing the vector registers, the vector registers are to be marked as invalid. Please note that we are allowed to write the registers although they are marked as invalid. Machine checks and "store status" SIGP orders are two different concepts, let's correctly separate these. As the SIGP part is completely handled in user space, we can drop it. This patch is based on a patch from Cornelia Huck. Reviewed-by: Cornelia Huck <cornelia.huck@de.ibm.com> Signed-off-by: David Hildenbrand <dahi@linux.vnet.ibm.com> Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
1 parent 0319dae commit ff5dc14

File tree

3 files changed

+13
-37
lines changed

3 files changed

+13
-37
lines changed

arch/s390/kvm/interrupt.c

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include <asm/isc.h>
2626
#include <asm/gmap.h>
2727
#include <asm/switch_to.h>
28+
#include <asm/nmi.h>
2829
#include "kvm-s390.h"
2930
#include "gaccess.h"
3031
#include "trace-s390.h"
@@ -406,24 +407,34 @@ static int __write_machine_check(struct kvm_vcpu *vcpu,
406407
{
407408
unsigned long ext_sa_addr;
408409
freg_t fprs[NUM_FPRS];
410+
union mci mci;
409411
int rc;
410412

413+
mci.val = mchk->mcic;
411414
/* take care of lazy register loading via vcpu load/put */
412415
save_fpu_regs();
413416
save_access_regs(vcpu->run->s.regs.acrs);
414417

415418
/* Extended save area */
416419
rc = read_guest_lc(vcpu, __LC_VX_SAVE_AREA_ADDR, &ext_sa_addr,
417420
sizeof(unsigned long));
418-
rc |= kvm_s390_vcpu_store_adtl_status(vcpu, ext_sa_addr);
421+
/* Only bits 0-53 are used for address formation */
422+
ext_sa_addr &= ~0x3ffUL;
423+
if (!rc && mci.vr && ext_sa_addr && test_kvm_facility(vcpu->kvm, 129)) {
424+
if (write_guest_abs(vcpu, ext_sa_addr, vcpu->run->s.regs.vrs,
425+
512))
426+
mci.vr = 0;
427+
} else {
428+
mci.vr = 0;
429+
}
419430

420431
/* General interruption information */
421432
rc |= put_guest_lc(vcpu, 1, (u8 __user *) __LC_AR_MODE_ID);
422433
rc |= write_guest_lc(vcpu, __LC_MCK_OLD_PSW,
423434
&vcpu->arch.sie_block->gpsw, sizeof(psw_t));
424435
rc |= read_guest_lc(vcpu, __LC_MCK_NEW_PSW,
425436
&vcpu->arch.sie_block->gpsw, sizeof(psw_t));
426-
rc |= put_guest_lc(vcpu, mchk->mcic, (u64 __user *) __LC_MCCK_CODE);
437+
rc |= put_guest_lc(vcpu, mci.val, (u64 __user *) __LC_MCCK_CODE);
427438

428439
/* Register-save areas */
429440
if (MACHINE_HAS_VX) {

arch/s390/kvm/kvm-s390.c

Lines changed: 0 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -2837,38 +2837,6 @@ int kvm_s390_vcpu_store_status(struct kvm_vcpu *vcpu, unsigned long addr)
28372837
return kvm_s390_store_status_unloaded(vcpu, addr);
28382838
}
28392839

2840-
/*
2841-
* store additional status at address
2842-
*/
2843-
int kvm_s390_store_adtl_status_unloaded(struct kvm_vcpu *vcpu,
2844-
unsigned long gpa)
2845-
{
2846-
/* Only bits 0-53 are used for address formation */
2847-
if (!(gpa & ~0x3ff))
2848-
return 0;
2849-
2850-
return write_guest_abs(vcpu, gpa & ~0x3ff,
2851-
(void *)&vcpu->run->s.regs.vrs, 512);
2852-
}
2853-
2854-
int kvm_s390_vcpu_store_adtl_status(struct kvm_vcpu *vcpu, unsigned long addr)
2855-
{
2856-
if (!test_kvm_facility(vcpu->kvm, 129))
2857-
return 0;
2858-
2859-
/*
2860-
* The guest VXRS are in the host VXRs due to the lazy
2861-
* copying in vcpu load/put. We can simply call save_fpu_regs()
2862-
* to save the current register state because we are in the
2863-
* middle of a load/put cycle.
2864-
*
2865-
* Let's update our copies before we save it into the save area.
2866-
*/
2867-
save_fpu_regs();
2868-
2869-
return kvm_s390_store_adtl_status_unloaded(vcpu, addr);
2870-
}
2871-
28722840
static void __disable_ibs_on_vcpu(struct kvm_vcpu *vcpu)
28732841
{
28742842
kvm_check_request(KVM_REQ_ENABLE_IBS, vcpu);

arch/s390/kvm/kvm-s390.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -273,10 +273,7 @@ int handle_sthyi(struct kvm_vcpu *vcpu);
273273
void kvm_s390_set_tod_clock(struct kvm *kvm, u64 tod);
274274
long kvm_arch_fault_in_page(struct kvm_vcpu *vcpu, gpa_t gpa, int writable);
275275
int kvm_s390_store_status_unloaded(struct kvm_vcpu *vcpu, unsigned long addr);
276-
int kvm_s390_store_adtl_status_unloaded(struct kvm_vcpu *vcpu,
277-
unsigned long addr);
278276
int kvm_s390_vcpu_store_status(struct kvm_vcpu *vcpu, unsigned long addr);
279-
int kvm_s390_vcpu_store_adtl_status(struct kvm_vcpu *vcpu, unsigned long addr);
280277
void kvm_s390_vcpu_start(struct kvm_vcpu *vcpu);
281278
void kvm_s390_vcpu_stop(struct kvm_vcpu *vcpu);
282279
void kvm_s390_vcpu_block(struct kvm_vcpu *vcpu);

0 commit comments

Comments
 (0)