aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Hildenbrand <dahi@linux.vnet.ibm.com>2015-06-23 16:49:36 -0400
committerChristian Borntraeger <borntraeger@de.ibm.com>2015-07-29 04:36:22 -0400
commit0df30abcd69b61d8163282c157f15ed3b0f1ac85 (patch)
treebfc085b7899b38fc8ee70b1a72607fbc0ea62bb6
parent14d4a425e7df6aaaa3287108ce191ccb6644c264 (diff)
KVM: s390: filter space-switch events when PER is enforced
When guest debugging is active, space-switch events might be enforced by PER. While the PER events are correctly filtered out, space-switch-events could be forwarded to the guest, although from a guest point of view, they should not have been reported. Therefore we have to filter out space-switch events being concurrently reported with a PER event, if the PER event got filtered out. To do so, we theoretically have to know which instruction was responsible for the event. As the applicable instructions modify the PSW address, the address space set in the PSW and even the address space in cr1, we can't figure out the instruction that way. For this reason, we have to rely on the information about the old and new address space, in order to guess the responsible instruction type and do appropriate checks for space-switch events. Signed-off-by: David Hildenbrand <dahi@linux.vnet.ibm.com> Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
-rw-r--r--arch/s390/kvm/guestdbg.c35
1 files changed, 35 insertions, 0 deletions
diff --git a/arch/s390/kvm/guestdbg.c b/arch/s390/kvm/guestdbg.c
index e97b3455d7e6..47518a324d75 100644
--- a/arch/s390/kvm/guestdbg.c
+++ b/arch/s390/kvm/guestdbg.c
@@ -473,10 +473,45 @@ static void filter_guest_per_event(struct kvm_vcpu *vcpu)
473 vcpu->arch.sie_block->iprcc &= ~PGM_PER; 473 vcpu->arch.sie_block->iprcc &= ~PGM_PER;
474} 474}
475 475
476#define pssec(vcpu) (vcpu->arch.sie_block->gcr[1] & _ASCE_SPACE_SWITCH)
477#define hssec(vcpu) (vcpu->arch.sie_block->gcr[13] & _ASCE_SPACE_SWITCH)
478#define old_ssec(vcpu) ((vcpu->arch.sie_block->tecmc >> 31) & 0x1)
479#define old_as_is_home(vcpu) !(vcpu->arch.sie_block->tecmc & 0xffff)
480
476void kvm_s390_handle_per_event(struct kvm_vcpu *vcpu) 481void kvm_s390_handle_per_event(struct kvm_vcpu *vcpu)
477{ 482{
483 int new_as;
484
478 if (debug_exit_required(vcpu)) 485 if (debug_exit_required(vcpu))
479 vcpu->guest_debug |= KVM_GUESTDBG_EXIT_PENDING; 486 vcpu->guest_debug |= KVM_GUESTDBG_EXIT_PENDING;
480 487
481 filter_guest_per_event(vcpu); 488 filter_guest_per_event(vcpu);
489
490 /*
491 * Only RP, SAC, SACF, PT, PTI, PR, PC instructions can trigger
492 * a space-switch event. PER events enforce space-switch events
493 * for these instructions. So if no PER event for the guest is left,
494 * we might have to filter the space-switch element out, too.
495 */
496 if (vcpu->arch.sie_block->iprcc == PGM_SPACE_SWITCH) {
497 vcpu->arch.sie_block->iprcc = 0;
498 new_as = psw_bits(vcpu->arch.sie_block->gpsw).as;
499
500 /*
501 * If the AS changed from / to home, we had RP, SAC or SACF
502 * instruction. Check primary and home space-switch-event
503 * controls. (theoretically home -> home produced no event)
504 */
505 if (((new_as == PSW_AS_HOME) ^ old_as_is_home(vcpu)) &&
506 (pssec(vcpu) || hssec(vcpu)))
507 vcpu->arch.sie_block->iprcc = PGM_SPACE_SWITCH;
508
509 /*
510 * PT, PTI, PR, PC instruction operate on primary AS only. Check
511 * if the primary-space-switch-event control was or got set.
512 */
513 if (new_as == PSW_AS_PRIMARY && !old_as_is_home(vcpu) &&
514 (pssec(vcpu) || old_ssec(vcpu)))
515 vcpu->arch.sie_block->iprcc = PGM_SPACE_SWITCH;
516 }
482} 517}