1 /* 2 * access guest memory 3 * 4 * Copyright IBM Corp. 2008, 2009 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License (version 2 only) 8 * as published by the Free Software Foundation. 9 * 10 * Author(s): Carsten Otte <cotte@de.ibm.com> 11 */ 12 13 #ifndef __KVM_S390_GACCESS_H 14 #define __KVM_S390_GACCESS_H 15 16 #include <linux/compiler.h> 17 #include <linux/kvm_host.h> 18 #include <asm/uaccess.h> 19 #include "kvm-s390.h" 20 21 static inline void __user *__gptr_to_uptr(struct kvm_vcpu *vcpu, 22 void __user *gptr, 23 int prefixing) 24 { 25 unsigned long prefix = vcpu->arch.sie_block->prefix; 26 unsigned long gaddr = (unsigned long) gptr; 27 unsigned long uaddr; 28 29 if (prefixing) { 30 if (gaddr < 2 * PAGE_SIZE) 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); 36 if (IS_ERR_VALUE(uaddr)) 37 uaddr = -EFAULT; 38 return (void __user *)uaddr; 39 } 40 41 #define get_guest(vcpu, x, gptr) \ 42 ({ \ 43 __typeof__(gptr) __uptr = __gptr_to_uptr(vcpu, gptr, 1);\ 44 int __mask = sizeof(__typeof__(*(gptr))) - 1; \ 45 int __ret = PTR_RET((void __force *)__uptr); \ 46 \ 47 if (!__ret) { \ 48 BUG_ON((unsigned long)__uptr & __mask); \ 49 __ret = get_user(x, __uptr); \ 50 } \ 51 __ret; \ 52 }) 53 54 #define put_guest(vcpu, x, gptr) \ 55 ({ \ 56 __typeof__(gptr) __uptr = __gptr_to_uptr(vcpu, gptr, 1);\ 57 int __mask = sizeof(__typeof__(*(gptr))) - 1; \ 58 int __ret = PTR_RET((void __force *)__uptr); \ 59 \ 60 if (!__ret) { \ 61 BUG_ON((unsigned long)__uptr & __mask); \ 62 __ret = put_user(x, __uptr); \ 63 } \ 64 __ret; \ 65 }) 66 67 static inline int __copy_guest(struct kvm_vcpu *vcpu, unsigned long to, 68 unsigned long from, unsigned long len, 69 int to_guest, int prefixing) 70 { 71 unsigned long _len, rc; 72 void __user *uptr; 73 74 while (len) { 75 uptr = to_guest ? (void __user *)to : (void __user *)from; 76 uptr = __gptr_to_uptr(vcpu, uptr, prefixing); 77 if (IS_ERR((void __force *)uptr)) 78 return -EFAULT; 79 _len = PAGE_SIZE - ((unsigned long)uptr & (PAGE_SIZE - 1)); 80 _len = min(_len, len); 81 if (to_guest) 82 rc = copy_to_user((void __user *) uptr, (void *)from, _len); 83 else 84 rc = copy_from_user((void *)to, (void __user *)uptr, _len); 85 if (rc) 86 return -EFAULT; 87 len -= _len; 88 from += _len; 89 to += _len; 90 } 91 return 0; 92 } 93 94 #define copy_to_guest(vcpu, to, from, size) \ 95 __copy_guest(vcpu, to, (unsigned long)from, size, 1, 1) 96 #define copy_from_guest(vcpu, to, from, size) \ 97 __copy_guest(vcpu, (unsigned long)to, from, size, 0, 1) 98 #define copy_to_guest_absolute(vcpu, to, from, size) \ 99 __copy_guest(vcpu, to, (unsigned long)from, size, 1, 0) 100 #define copy_from_guest_absolute(vcpu, to, from, size) \ 101 __copy_guest(vcpu, (unsigned long)to, from, size, 0, 0) 102 103 #endif /* __KVM_S390_GACCESS_H */ 104