aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/kvm
diff options
context:
space:
mode:
authorThomas Huth <thuth@linux.vnet.ibm.com>2015-02-05 03:06:56 -0500
committerChristian Borntraeger <borntraeger@de.ibm.com>2015-03-06 07:40:40 -0500
commita9a846fd5c1723820c97cef56989ea14eea4b30e (patch)
tree85515a198cd4fcb66104bce1fbd73d7cee86b91d /arch/s390/kvm
parent15462e37ca848abac7477dece65f8af25febd744 (diff)
KVM: s390: Nullify instruction for certain program exceptions
When certain program exceptions (e.g. DAT access exceptions) occur, the current instruction has to be nullified, i.e. the old PSW that gets written into the low-core has to point to the beginning of the instruction again, and not to the beginning of the next instruction. Thus we have to rewind the PSW before writing it into the low-core. The list of nullifying exceptions can be found in the POP, chapter 6, figure 6-1 ("Interruption Action"). Signed-off-by: Thomas Huth <thuth@linux.vnet.ibm.com> Reviewed-by: Jens Freimann <jfrei@linux.vnet.ibm.com> Reviewed-by: David Hildenbrand <dahi@linux.vnet.ibm.com> Acked-by: Christian Borntraeger <borntraeger@de.ibm.com> Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
Diffstat (limited to 'arch/s390/kvm')
-rw-r--r--arch/s390/kvm/interrupt.c18
1 files changed, 17 insertions, 1 deletions
diff --git a/arch/s390/kvm/interrupt.c b/arch/s390/kvm/interrupt.c
index e7a46e817874..98a313138f83 100644
--- a/arch/s390/kvm/interrupt.c
+++ b/arch/s390/kvm/interrupt.c
@@ -484,7 +484,7 @@ static int __must_check __deliver_prog(struct kvm_vcpu *vcpu)
484{ 484{
485 struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int; 485 struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int;
486 struct kvm_s390_pgm_info pgm_info; 486 struct kvm_s390_pgm_info pgm_info;
487 int rc = 0; 487 int rc = 0, nullifying = false;
488 u16 ilc = get_ilc(vcpu); 488 u16 ilc = get_ilc(vcpu);
489 489
490 spin_lock(&li->lock); 490 spin_lock(&li->lock);
@@ -509,6 +509,8 @@ static int __must_check __deliver_prog(struct kvm_vcpu *vcpu)
509 case PGM_LX_TRANSLATION: 509 case PGM_LX_TRANSLATION:
510 case PGM_PRIMARY_AUTHORITY: 510 case PGM_PRIMARY_AUTHORITY:
511 case PGM_SECONDARY_AUTHORITY: 511 case PGM_SECONDARY_AUTHORITY:
512 nullifying = true;
513 /* fall through */
512 case PGM_SPACE_SWITCH: 514 case PGM_SPACE_SWITCH:
513 rc = put_guest_lc(vcpu, pgm_info.trans_exc_code, 515 rc = put_guest_lc(vcpu, pgm_info.trans_exc_code,
514 (u64 *)__LC_TRANS_EXC_CODE); 516 (u64 *)__LC_TRANS_EXC_CODE);
@@ -521,6 +523,7 @@ static int __must_check __deliver_prog(struct kvm_vcpu *vcpu)
521 case PGM_EXTENDED_AUTHORITY: 523 case PGM_EXTENDED_AUTHORITY:
522 rc = put_guest_lc(vcpu, pgm_info.exc_access_id, 524 rc = put_guest_lc(vcpu, pgm_info.exc_access_id,
523 (u8 *)__LC_EXC_ACCESS_ID); 525 (u8 *)__LC_EXC_ACCESS_ID);
526 nullifying = true;
524 break; 527 break;
525 case PGM_ASCE_TYPE: 528 case PGM_ASCE_TYPE:
526 case PGM_PAGE_TRANSLATION: 529 case PGM_PAGE_TRANSLATION:
@@ -534,6 +537,7 @@ static int __must_check __deliver_prog(struct kvm_vcpu *vcpu)
534 (u8 *)__LC_EXC_ACCESS_ID); 537 (u8 *)__LC_EXC_ACCESS_ID);
535 rc |= put_guest_lc(vcpu, pgm_info.op_access_id, 538 rc |= put_guest_lc(vcpu, pgm_info.op_access_id,
536 (u8 *)__LC_OP_ACCESS_ID); 539 (u8 *)__LC_OP_ACCESS_ID);
540 nullifying = true;
537 break; 541 break;
538 case PGM_MONITOR: 542 case PGM_MONITOR:
539 rc = put_guest_lc(vcpu, pgm_info.mon_class_nr, 543 rc = put_guest_lc(vcpu, pgm_info.mon_class_nr,
@@ -551,6 +555,15 @@ static int __must_check __deliver_prog(struct kvm_vcpu *vcpu)
551 rc |= put_guest_lc(vcpu, pgm_info.exc_access_id, 555 rc |= put_guest_lc(vcpu, pgm_info.exc_access_id,
552 (u8 *)__LC_EXC_ACCESS_ID); 556 (u8 *)__LC_EXC_ACCESS_ID);
553 break; 557 break;
558 case PGM_STACK_FULL:
559 case PGM_STACK_EMPTY:
560 case PGM_STACK_SPECIFICATION:
561 case PGM_STACK_TYPE:
562 case PGM_STACK_OPERATION:
563 case PGM_TRACE_TABEL:
564 case PGM_CRYPTO_OPERATION:
565 nullifying = true;
566 break;
554 } 567 }
555 568
556 if (pgm_info.code & PGM_PER) { 569 if (pgm_info.code & PGM_PER) {
@@ -564,6 +577,9 @@ static int __must_check __deliver_prog(struct kvm_vcpu *vcpu)
564 (u8 *) __LC_PER_ACCESS_ID); 577 (u8 *) __LC_PER_ACCESS_ID);
565 } 578 }
566 579
580 if (nullifying && vcpu->arch.sie_block->icptcode == ICPT_INST)
581 kvm_s390_rewind_psw(vcpu, ilc);
582
567 rc |= put_guest_lc(vcpu, ilc, (u16 *) __LC_PGM_ILC); 583 rc |= put_guest_lc(vcpu, ilc, (u16 *) __LC_PGM_ILC);
568 rc |= put_guest_lc(vcpu, pgm_info.code, 584 rc |= put_guest_lc(vcpu, pgm_info.code,
569 (u16 *)__LC_PGM_INT_CODE); 585 (u16 *)__LC_PGM_INT_CODE);