]> Pileus Git - ~andy/linux/blob - arch/s390/kvm/gaccess.h
Merge tag 'for-linus-3.11-merge-window-part-2' of git://git.kernel.org/pub/scm/linux...
[~andy/linux] / arch / s390 / kvm / gaccess.h
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 */