diff options
author | Thomas Huth <thuth@linux.vnet.ibm.com> | 2014-02-04 08:43:25 -0500 |
---|---|---|
committer | Christian Borntraeger <borntraeger@de.ibm.com> | 2014-05-30 03:39:35 -0400 |
commit | 9fbc02760d61fddc7716f9e6aa6ed1ff33e65405 (patch) | |
tree | 4aa1295e469db401198a93692301ef61173f5765 | |
parent | 1f854112553a1d65363ab27d4ee3dfb4b27075fb (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.c | 53 | ||||
-rw-r--r-- | arch/s390/kvm/gaccess.h | 3 |
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 | */ | ||
656 | int 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 | ||
158 | int guest_translate_address(struct kvm_vcpu *vcpu, unsigned long gva, | ||
159 | unsigned long *gpa, int write); | ||
160 | |||
158 | int access_guest(struct kvm_vcpu *vcpu, unsigned long ga, void *data, | 161 | int 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 | ||