aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorThomas Huth <thuth@linux.vnet.ibm.com>2013-09-09 11:58:38 -0400
committerChristian Borntraeger <borntraeger@de.ibm.com>2014-04-29 09:01:53 -0400
commitfb34c603655fafdd244227cb6b42d006469735fc (patch)
tree4352670d011b6d87febbdc6515dab93c18f85546 /arch
parentf8232c8cf720074c0eb0804202d424a2b7b4ee76 (diff)
KVM: s390: Fixes for PFMF
Add a check for low-address protection to the PFMF handler and convert real-addresses to absolute if necessary, as it is defined in the Principles of Operations specification. Signed-off-by: Thomas Huth <thuth@linux.vnet.ibm.com> Reviewed-by: Cornelia Huck <cornelia.huck@de.ibm.com> Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
Diffstat (limited to 'arch')
-rw-r--r--arch/s390/kvm/priv.c18
1 files changed, 14 insertions, 4 deletions
diff --git a/arch/s390/kvm/priv.c b/arch/s390/kvm/priv.c
index 27f9051a78f8..a47157bca8a6 100644
--- a/arch/s390/kvm/priv.c
+++ b/arch/s390/kvm/priv.c
@@ -650,6 +650,11 @@ static int handle_pfmf(struct kvm_vcpu *vcpu)
650 return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION); 650 return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
651 651
652 start = vcpu->run->s.regs.gprs[reg2] & PAGE_MASK; 652 start = vcpu->run->s.regs.gprs[reg2] & PAGE_MASK;
653 if (vcpu->run->s.regs.gprs[reg1] & PFMF_CF) {
654 if (kvm_s390_check_low_addr_protection(vcpu, start))
655 return kvm_s390_inject_prog_irq(vcpu, &vcpu->arch.pgm);
656 }
657
653 switch (vcpu->run->s.regs.gprs[reg1] & PFMF_FSC) { 658 switch (vcpu->run->s.regs.gprs[reg1] & PFMF_FSC) {
654 case 0x00000000: 659 case 0x00000000:
655 end = (start + (1UL << 12)) & ~((1UL << 12) - 1); 660 end = (start + (1UL << 12)) & ~((1UL << 12) - 1);
@@ -665,10 +670,15 @@ static int handle_pfmf(struct kvm_vcpu *vcpu)
665 return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION); 670 return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
666 } 671 }
667 while (start < end) { 672 while (start < end) {
668 unsigned long useraddr; 673 unsigned long useraddr, abs_addr;
669 674
670 useraddr = gmap_translate(start, vcpu->arch.gmap); 675 /* Translate guest address to host address */
671 if (IS_ERR((void *)useraddr)) 676 if ((vcpu->run->s.regs.gprs[reg1] & PFMF_FSC) == 0)
677 abs_addr = kvm_s390_real_to_abs(vcpu, start);
678 else
679 abs_addr = start;
680 useraddr = gfn_to_hva(vcpu->kvm, gpa_to_gfn(abs_addr));
681 if (kvm_is_error_hva(useraddr))
672 return kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING); 682 return kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
673 683
674 if (vcpu->run->s.regs.gprs[reg1] & PFMF_CF) { 684 if (vcpu->run->s.regs.gprs[reg1] & PFMF_CF) {