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; \ 46 \ 47 if (IS_ERR((void __force *)__uptr)) { \ 48 __ret = PTR_ERR((void __force *)__uptr); \ 49 } else { \ 50 BUG_ON((unsigned long)__uptr & __mask); \ 51 __ret = get_user(x, __uptr); \ 52 } \ 53 __ret; \ 54 }) 55 56 #define put_guest(vcpu, x, gptr) \ 57 ({ \ 58 __typeof__(gptr) __uptr = __gptr_to_uptr(vcpu, gptr, 1);\ 59 int __mask = sizeof(__typeof__(*(gptr))) - 1; \ 60 int __ret; \ 61 \ 62 if (IS_ERR((void __force *)__uptr)) { \ 63 __ret = PTR_ERR((void __force *)__uptr); \ 64 } else { \ 65 BUG_ON((unsigned long)__uptr & __mask); \ 66 __ret = put_user(x, __uptr); \ 67 } \ 68 __ret; \ 69 }) 70 71 static inline int __copy_guest(struct kvm_vcpu *vcpu, unsigned long to, 72 unsigned long from, unsigned long len, 73 int to_guest, int prefixing) 74 { 75 unsigned long _len, rc; 76 void __user *uptr; 77 78 while (len) { 79 uptr = to_guest ? (void __user *)to : (void __user *)from; 80 uptr = __gptr_to_uptr(vcpu, uptr, prefixing); 81 if (IS_ERR((void __force *)uptr)) 82 return -EFAULT; 83 _len = PAGE_SIZE - ((unsigned long)uptr & (PAGE_SIZE - 1)); 84 _len = min(_len, len); 85 if (to_guest) 86 rc = copy_to_user((void __user *) uptr, (void *)from, _len); 87 else 88 rc = copy_from_user((void *)to, (void __user *)uptr, _len); 89 if (rc) 90 return -EFAULT; 91 len -= _len; 92 from += _len; 93 to += _len; 94 } 95 return 0; 96 } 97 98 #define copy_to_guest(vcpu, to, from, size) \ 99 __copy_guest(vcpu, to, (unsigned long)from, size, 1, 1) 100 #define copy_from_guest(vcpu, to, from, size) \ 101 __copy_guest(vcpu, (unsigned long)to, from, size, 0, 1) 102 #define copy_to_guest_absolute(vcpu, to, from, size) \ 103 __copy_guest(vcpu, to, (unsigned long)from, size, 1, 0) 104 #define copy_from_guest_absolute(vcpu, to, from, size) \ 105 __copy_guest(vcpu, (unsigned long)to, from, size, 0, 0) 106 107 #endif /* __KVM_S390_GACCESS_H */ 108