aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Huth <thuth@linux.vnet.ibm.com>2014-02-04 08:43:25 -0500
committerChristian Borntraeger <borntraeger@de.ibm.com>2014-05-30 03:39:35 -0400
commit9fbc02760d61fddc7716f9e6aa6ed1ff33e65405 (patch)
tree4aa1295e469db401198a93692301ef61173f5765
parent1f854112553a1d65363ab27d4ee3dfb4b27075fb (diff)
KVM: s390: Add a generic function for translating guest addresses
This patch adds a function for translating logical guest addresses into physical guest addresses without touching the memory at the given location. Signed-off-by: Thomas Huth <thuth@linux.vnet.ibm.com> Reviewed-by: Cornelia Huck <cornelia.huck@de.ibm.com>
-rw-r--r--arch/s390/kvm/gaccess.c53
-rw-r--r--arch/s390/kvm/gaccess.h3
2 files changed, 56 insertions, 0 deletions
diff --git a/arch/s390/kvm/gaccess.c b/arch/s390/kvm/gaccess.c
index db608c3f9303..5f73826992f2 100644
--- a/arch/s390/kvm/gaccess.c
+++ b/arch/s390/kvm/gaccess.c
@@ -645,6 +645,59 @@ int access_guest_real(struct kvm_vcpu *vcpu, unsigned long gra,
645} 645}
646 646
647/** 647/**
648 * guest_translate_address - translate guest logical into guest absolute address
649 *
650 * Parameter semantics are the same as the ones from guest_translate.
651 * The memory contents at the guest address are not changed.
652 *
653 * Note: The IPTE lock is not taken during this function, so the caller
654 * has to take care of this.
655 */
656int guest_translate_address(struct kvm_vcpu *vcpu, unsigned long gva,
657 unsigned long *gpa, int write)
658{
659 struct kvm_s390_pgm_info *pgm = &vcpu->arch.pgm;
660 psw_t *psw = &vcpu->arch.sie_block->gpsw;
661 struct trans_exc_code_bits *tec;
662 union asce asce;
663 int rc;
664
665 /* Access register mode is not supported yet. */
666 if (psw_bits(*psw).t && psw_bits(*psw).as == PSW_AS_ACCREG)
667 return -EOPNOTSUPP;
668
669 gva = kvm_s390_logical_to_effective(vcpu, gva);
670 memset(pgm, 0, sizeof(*pgm));
671 tec = (struct trans_exc_code_bits *)&pgm->trans_exc_code;
672 tec->as = psw_bits(*psw).as;
673 tec->fsi = write ? FSI_STORE : FSI_FETCH;
674 tec->addr = gva >> PAGE_SHIFT;
675 if (is_low_address(gva) && low_address_protection_enabled(vcpu)) {
676 if (write) {
677 rc = pgm->code = PGM_PROTECTION;
678 return rc;
679 }
680 }
681
682 asce.val = get_vcpu_asce(vcpu);
683 if (psw_bits(*psw).t && !asce.r) { /* Use DAT? */
684 rc = guest_translate(vcpu, gva, gpa, write);
685 if (rc > 0) {
686 if (rc == PGM_PROTECTION)
687 tec->b61 = 1;
688 pgm->code = rc;
689 }
690 } else {
691 rc = 0;
692 *gpa = kvm_s390_real_to_abs(vcpu, gva);
693 if (kvm_is_error_gpa(vcpu->kvm, *gpa))
694 rc = pgm->code = PGM_ADDRESSING;
695 }
696
697 return rc;
698}
699
700/**
648 * kvm_s390_check_low_addr_protection - check for low-address protection 701 * kvm_s390_check_low_addr_protection - check for low-address protection
649 * @ga: Guest address 702 * @ga: Guest address
650 * 703 *
diff --git a/arch/s390/kvm/gaccess.h b/arch/s390/kvm/gaccess.h
index a07ee08ac478..2d37a46195e2 100644
--- a/arch/s390/kvm/gaccess.h
+++ b/arch/s390/kvm/gaccess.h
@@ -155,6 +155,9 @@ int read_guest_lc(struct kvm_vcpu *vcpu, unsigned long gra, void *data,
155 return kvm_read_guest(vcpu->kvm, gpa, data, len); 155 return kvm_read_guest(vcpu->kvm, gpa, data, len);
156} 156}
157 157
158int guest_translate_address(struct kvm_vcpu *vcpu, unsigned long gva,
159 unsigned long *gpa, int write);
160
158int access_guest(struct kvm_vcpu *vcpu, unsigned long ga, void *data, 161int access_guest(struct kvm_vcpu *vcpu, unsigned long ga, void *data,
159 unsigned long len, int write); 162 unsigned long len, int write);
160 163