diff options
Diffstat (limited to 'arch/s390/kvm/gaccess.h')
-rw-r--r-- | arch/s390/kvm/gaccess.h | 21 |
1 files changed, 14 insertions, 7 deletions
diff --git a/arch/s390/kvm/gaccess.h b/arch/s390/kvm/gaccess.h index 99d789e8a018..374a439ccc60 100644 --- a/arch/s390/kvm/gaccess.h +++ b/arch/s390/kvm/gaccess.h | |||
@@ -18,20 +18,27 @@ | |||
18 | #include <asm/uaccess.h> | 18 | #include <asm/uaccess.h> |
19 | #include "kvm-s390.h" | 19 | #include "kvm-s390.h" |
20 | 20 | ||
21 | /* Convert real to absolute address by applying the prefix of the CPU */ | ||
22 | static inline unsigned long kvm_s390_real_to_abs(struct kvm_vcpu *vcpu, | ||
23 | unsigned long gaddr) | ||
24 | { | ||
25 | unsigned long prefix = vcpu->arch.sie_block->prefix; | ||
26 | if (gaddr < 2 * PAGE_SIZE) | ||
27 | gaddr += prefix; | ||
28 | else if (gaddr >= prefix && gaddr < prefix + 2 * PAGE_SIZE) | ||
29 | gaddr -= prefix; | ||
30 | return gaddr; | ||
31 | } | ||
32 | |||
21 | static inline void __user *__gptr_to_uptr(struct kvm_vcpu *vcpu, | 33 | static inline void __user *__gptr_to_uptr(struct kvm_vcpu *vcpu, |
22 | void __user *gptr, | 34 | void __user *gptr, |
23 | int prefixing) | 35 | int prefixing) |
24 | { | 36 | { |
25 | unsigned long prefix = vcpu->arch.sie_block->prefix; | ||
26 | unsigned long gaddr = (unsigned long) gptr; | 37 | unsigned long gaddr = (unsigned long) gptr; |
27 | unsigned long uaddr; | 38 | unsigned long uaddr; |
28 | 39 | ||
29 | if (prefixing) { | 40 | if (prefixing) |
30 | if (gaddr < 2 * PAGE_SIZE) | 41 | gaddr = kvm_s390_real_to_abs(vcpu, gaddr); |
31 | gaddr += prefix; | ||
32 | else if ((gaddr >= prefix) && (gaddr < prefix + 2 * PAGE_SIZE)) | ||
33 | gaddr -= prefix; | ||
34 | } | ||
35 | uaddr = gmap_fault(gaddr, vcpu->arch.gmap); | 42 | uaddr = gmap_fault(gaddr, vcpu->arch.gmap); |
36 | if (IS_ERR_VALUE(uaddr)) | 43 | if (IS_ERR_VALUE(uaddr)) |
37 | uaddr = -EFAULT; | 44 | uaddr = -EFAULT; |