2 * gaccess.h - access guest memory
4 * Copyright IBM Corp. 2008,2009
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.
10 * Author(s): Carsten Otte <cotte@de.ibm.com>
13 #ifndef __KVM_S390_GACCESS_H
14 #define __KVM_S390_GACCESS_H
16 #include <linux/compiler.h>
17 #include <linux/kvm_host.h>
18 #include <asm/uaccess.h>
21 static inline void __user
*__guestaddr_to_user(struct kvm_vcpu
*vcpu
,
22 unsigned long guestaddr
)
24 unsigned long prefix
= vcpu
->arch
.sie_block
->prefix
;
25 unsigned long origin
= vcpu
->arch
.sie_block
->gmsor
;
26 unsigned long memsize
= kvm_s390_vcpu_get_memsize(vcpu
);
28 if (guestaddr
< 2 * PAGE_SIZE
)
30 else if ((guestaddr
>= prefix
) && (guestaddr
< prefix
+ 2 * PAGE_SIZE
))
33 if (guestaddr
> memsize
)
34 return (void __user __force
*) ERR_PTR(-EFAULT
);
38 return (void __user
*) guestaddr
;
41 static inline int get_guest_u64(struct kvm_vcpu
*vcpu
, unsigned long guestaddr
,
44 void __user
*uptr
= __guestaddr_to_user(vcpu
, guestaddr
);
46 BUG_ON(guestaddr
& 7);
48 if (IS_ERR((void __force
*) uptr
))
49 return PTR_ERR((void __force
*) uptr
);
51 return get_user(*result
, (unsigned long __user
*) uptr
);
54 static inline int get_guest_u32(struct kvm_vcpu
*vcpu
, unsigned long guestaddr
,
57 void __user
*uptr
= __guestaddr_to_user(vcpu
, guestaddr
);
59 BUG_ON(guestaddr
& 3);
61 if (IS_ERR((void __force
*) uptr
))
62 return PTR_ERR((void __force
*) uptr
);
64 return get_user(*result
, (u32 __user
*) uptr
);
67 static inline int get_guest_u16(struct kvm_vcpu
*vcpu
, unsigned long guestaddr
,
70 void __user
*uptr
= __guestaddr_to_user(vcpu
, guestaddr
);
72 BUG_ON(guestaddr
& 1);
77 return get_user(*result
, (u16 __user
*) uptr
);
80 static inline int get_guest_u8(struct kvm_vcpu
*vcpu
, unsigned long guestaddr
,
83 void __user
*uptr
= __guestaddr_to_user(vcpu
, guestaddr
);
85 if (IS_ERR((void __force
*) uptr
))
86 return PTR_ERR((void __force
*) uptr
);
88 return get_user(*result
, (u8 __user
*) uptr
);
91 static inline int put_guest_u64(struct kvm_vcpu
*vcpu
, unsigned long guestaddr
,
94 void __user
*uptr
= __guestaddr_to_user(vcpu
, guestaddr
);
96 BUG_ON(guestaddr
& 7);
98 if (IS_ERR((void __force
*) uptr
))
99 return PTR_ERR((void __force
*) uptr
);
101 return put_user(value
, (u64 __user
*) uptr
);
104 static inline int put_guest_u32(struct kvm_vcpu
*vcpu
, unsigned long guestaddr
,
107 void __user
*uptr
= __guestaddr_to_user(vcpu
, guestaddr
);
109 BUG_ON(guestaddr
& 3);
111 if (IS_ERR((void __force
*) uptr
))
112 return PTR_ERR((void __force
*) uptr
);
114 return put_user(value
, (u32 __user
*) uptr
);
117 static inline int put_guest_u16(struct kvm_vcpu
*vcpu
, unsigned long guestaddr
,
120 void __user
*uptr
= __guestaddr_to_user(vcpu
, guestaddr
);
122 BUG_ON(guestaddr
& 1);
124 if (IS_ERR((void __force
*) uptr
))
125 return PTR_ERR((void __force
*) uptr
);
127 return put_user(value
, (u16 __user
*) uptr
);
130 static inline int put_guest_u8(struct kvm_vcpu
*vcpu
, unsigned long guestaddr
,
133 void __user
*uptr
= __guestaddr_to_user(vcpu
, guestaddr
);
135 if (IS_ERR((void __force
*) uptr
))
136 return PTR_ERR((void __force
*) uptr
);
138 return put_user(value
, (u8 __user
*) uptr
);
142 static inline int __copy_to_guest_slow(struct kvm_vcpu
*vcpu
,
143 unsigned long guestdest
,
144 const void *from
, unsigned long n
)
148 const u8
*data
= from
;
150 for (i
= 0; i
< n
; i
++) {
151 rc
= put_guest_u8(vcpu
, guestdest
++, *(data
++));
158 static inline int copy_to_guest(struct kvm_vcpu
*vcpu
, unsigned long guestdest
,
159 const void *from
, unsigned long n
)
161 unsigned long prefix
= vcpu
->arch
.sie_block
->prefix
;
162 unsigned long origin
= vcpu
->arch
.sie_block
->gmsor
;
163 unsigned long memsize
= kvm_s390_vcpu_get_memsize(vcpu
);
165 if ((guestdest
< 2 * PAGE_SIZE
) && (guestdest
+ n
> 2 * PAGE_SIZE
))
168 if ((guestdest
< prefix
) && (guestdest
+ n
> prefix
))
171 if ((guestdest
< prefix
+ 2 * PAGE_SIZE
)
172 && (guestdest
+ n
> prefix
+ 2 * PAGE_SIZE
))
175 if (guestdest
< 2 * PAGE_SIZE
)
177 else if ((guestdest
>= prefix
) && (guestdest
< prefix
+ 2 * PAGE_SIZE
))
180 if (guestdest
+ n
> memsize
)
183 if (guestdest
+ n
< guestdest
)
188 return copy_to_user((void __user
*) guestdest
, from
, n
);
190 return __copy_to_guest_slow(vcpu
, guestdest
, from
, n
);
193 static inline int __copy_from_guest_slow(struct kvm_vcpu
*vcpu
, void *to
,
194 unsigned long guestsrc
,
201 for (i
= 0; i
< n
; i
++) {
202 rc
= get_guest_u8(vcpu
, guestsrc
++, data
++);
209 static inline int copy_from_guest(struct kvm_vcpu
*vcpu
, void *to
,
210 unsigned long guestsrc
, unsigned long n
)
212 unsigned long prefix
= vcpu
->arch
.sie_block
->prefix
;
213 unsigned long origin
= vcpu
->arch
.sie_block
->gmsor
;
214 unsigned long memsize
= kvm_s390_vcpu_get_memsize(vcpu
);
216 if ((guestsrc
< 2 * PAGE_SIZE
) && (guestsrc
+ n
> 2 * PAGE_SIZE
))
219 if ((guestsrc
< prefix
) && (guestsrc
+ n
> prefix
))
222 if ((guestsrc
< prefix
+ 2 * PAGE_SIZE
)
223 && (guestsrc
+ n
> prefix
+ 2 * PAGE_SIZE
))
226 if (guestsrc
< 2 * PAGE_SIZE
)
228 else if ((guestsrc
>= prefix
) && (guestsrc
< prefix
+ 2 * PAGE_SIZE
))
231 if (guestsrc
+ n
> memsize
)
234 if (guestsrc
+ n
< guestsrc
)
239 return copy_from_user(to
, (void __user
*) guestsrc
, n
);
241 return __copy_from_guest_slow(vcpu
, to
, guestsrc
, n
);
244 static inline int copy_to_guest_absolute(struct kvm_vcpu
*vcpu
,
245 unsigned long guestdest
,
246 const void *from
, unsigned long n
)
248 unsigned long origin
= vcpu
->arch
.sie_block
->gmsor
;
249 unsigned long memsize
= kvm_s390_vcpu_get_memsize(vcpu
);
251 if (guestdest
+ n
> memsize
)
254 if (guestdest
+ n
< guestdest
)
259 return copy_to_user((void __user
*) guestdest
, from
, n
);
262 static inline int copy_from_guest_absolute(struct kvm_vcpu
*vcpu
, void *to
,
263 unsigned long guestsrc
,
266 unsigned long origin
= vcpu
->arch
.sie_block
->gmsor
;
267 unsigned long memsize
= kvm_s390_vcpu_get_memsize(vcpu
);
269 if (guestsrc
+ n
> memsize
)
272 if (guestsrc
+ n
< guestsrc
)
277 return copy_from_user(to
, (void __user
*) guestsrc
, n
);