]> Pileus Git - ~andy/linux/blob - arch/s390/kvm/gaccess.h
Merge tag 'microblaze-3.12-rc1' of git://git.monstr.eu/linux-2.6-microblaze
[~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;                                              \
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 */