diff options
author | Thomas Huth <thuth@linux.vnet.ibm.com> | 2013-09-09 11:58:38 -0400 |
---|---|---|
committer | Christian Borntraeger <borntraeger@de.ibm.com> | 2014-04-29 09:01:53 -0400 |
commit | fb34c603655fafdd244227cb6b42d006469735fc (patch) | |
tree | 4352670d011b6d87febbdc6515dab93c18f85546 /arch | |
parent | f8232c8cf720074c0eb0804202d424a2b7b4ee76 (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.c | 18 |
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) { |