2 * gaccess.h - access guest memory
4 * Copyright IBM Corp. 2008
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>
20 static inline void __user
*__guestaddr_to_user(struct kvm_vcpu
*vcpu
,
21 unsigned long guestaddr
)
23 unsigned long prefix
= vcpu
->arch
.sie_block
->prefix
;
24 unsigned long origin
= vcpu
->kvm
->arch
.guest_origin
;
25 unsigned long memsize
= vcpu
->kvm
->arch
.guest_memsize
;
27 if (guestaddr
< 2 * PAGE_SIZE
)
29 else if ((guestaddr
>= prefix
) && (guestaddr
< prefix
+ 2 * PAGE_SIZE
))
32 if (guestaddr
> memsize
)
33 return (void __user __force
*) ERR_PTR(-EFAULT
);
37 return (void __user
*) guestaddr
;
40 static inline int get_guest_u64(struct kvm_vcpu
*vcpu
, unsigned long guestaddr
,
43 void __user
*uptr
= __guestaddr_to_user(vcpu
, guestaddr
);
45 BUG_ON(guestaddr
& 7);
47 if (IS_ERR((void __force
*) uptr
))
48 return PTR_ERR((void __force
*) uptr
);
50 return get_user(*result
, (unsigned long __user
*) uptr
);
53 static inline int get_guest_u32(struct kvm_vcpu
*vcpu
, unsigned long guestaddr
,
56 void __user
*uptr
= __guestaddr_to_user(vcpu
, guestaddr
);
58 BUG_ON(guestaddr
& 3);
60 if (IS_ERR((void __force
*) uptr
))
61 return PTR_ERR((void __force
*) uptr
);
63 return get_user(*result
, (u32 __user
*) uptr
);
66 static inline int get_guest_u16(struct kvm_vcpu
*vcpu
, unsigned long guestaddr
,
69 void __user
*uptr
= __guestaddr_to_user(vcpu
, guestaddr
);
71 BUG_ON(guestaddr
& 1);
76 return get_user(*result
, (u16 __user
*) uptr
);
79 static inline int get_guest_u8(struct kvm_vcpu
*vcpu
, unsigned long guestaddr
,
82 void __user
*uptr
= __guestaddr_to_user(vcpu
, guestaddr
);
84 if (IS_ERR((void __force
*) uptr
))
85 return PTR_ERR((void __force
*) uptr
);
87 return get_user(*result
, (u8 __user
*) uptr
);
90 static inline int put_guest_u64(struct kvm_vcpu
*vcpu
, unsigned long guestaddr
,
93 void __user
*uptr
= __guestaddr_to_user(vcpu
, guestaddr
);
95 BUG_ON(guestaddr
& 7);
97 if (IS_ERR((void __force
*) uptr
))
98 return PTR_ERR((void __force
*) uptr
);
100 return put_user(value
, (u64 __user
*) uptr
);
103 static inline int put_guest_u32(struct kvm_vcpu
*vcpu
, unsigned long guestaddr
,
106 void __user
*uptr
= __guestaddr_to_user(vcpu
, guestaddr
);
108 BUG_ON(guestaddr
& 3);
110 if (IS_ERR((void __force
*) uptr
))
111 return PTR_ERR((void __force
*) uptr
);
113 return put_user(value
, (u32 __user
*) uptr
);
116 static inline int put_guest_u16(struct kvm_vcpu
*vcpu
, unsigned long guestaddr
,
119 void __user
*uptr
= __guestaddr_to_user(vcpu
, guestaddr
);
121 BUG_ON(guestaddr
& 1);
123 if (IS_ERR((void __force
*) uptr
))
124 return PTR_ERR((void __force
*) uptr
);
126 return put_user(value
, (u16 __user
*) uptr
);
129 static inline int put_guest_u8(struct kvm_vcpu
*vcpu
, unsigned long guestaddr
,
132 void __user
*uptr
= __guestaddr_to_user(vcpu
, guestaddr
);
134 if (IS_ERR((void __force
*) uptr
))
135 return PTR_ERR((void __force
*) uptr
);
137 return put_user(value
, (u8 __user
*) uptr
);
141 static inline int __copy_to_guest_slow(struct kvm_vcpu
*vcpu
,
142 unsigned long guestdest
,
143 const void *from
, unsigned long n
)
147 const u8
*data
= from
;
149 for (i
= 0; i
< n
; i
++) {
150 rc
= put_guest_u8(vcpu
, guestdest
++, *(data
++));
157 static inline int copy_to_guest(struct kvm_vcpu
*vcpu
, unsigned long guestdest
,
158 const void *from
, unsigned long n
)
160 unsigned long prefix
= vcpu
->arch
.sie_block
->prefix
;
161 unsigned long origin
= vcpu
->kvm
->arch
.guest_origin
;
162 unsigned long memsize
= vcpu
->kvm
->arch
.guest_memsize
;
164 if ((guestdest
< 2 * PAGE_SIZE
) && (guestdest
+ n
> 2 * PAGE_SIZE
))
167 if ((guestdest
< prefix
) && (guestdest
+ n
> prefix
))
170 if ((guestdest
< prefix
+ 2 * PAGE_SIZE
)
171 && (guestdest
+ n
> prefix
+ 2 * PAGE_SIZE
))
174 if (guestdest
< 2 * PAGE_SIZE
)
176 else if ((guestdest
>= prefix
) && (guestdest
< prefix
+ 2 * PAGE_SIZE
))
179 if (guestdest
+ n
> memsize
)
182 if (guestdest
+ n
< guestdest
)
187 return copy_to_user((void __user
*) guestdest
, from
, n
);
189 return __copy_to_guest_slow(vcpu
, guestdest
, from
, n
);
192 static inline int __copy_from_guest_slow(struct kvm_vcpu
*vcpu
, void *to
,
193 unsigned long guestsrc
,
200 for (i
= 0; i
< n
; i
++) {
201 rc
= get_guest_u8(vcpu
, guestsrc
++, data
++);
208 static inline int copy_from_guest(struct kvm_vcpu
*vcpu
, void *to
,
209 unsigned long guestsrc
, unsigned long n
)
211 unsigned long prefix
= vcpu
->arch
.sie_block
->prefix
;
212 unsigned long origin
= vcpu
->kvm
->arch
.guest_origin
;
213 unsigned long memsize
= vcpu
->kvm
->arch
.guest_memsize
;
215 if ((guestsrc
< 2 * PAGE_SIZE
) && (guestsrc
+ n
> 2 * PAGE_SIZE
))
218 if ((guestsrc
< prefix
) && (guestsrc
+ n
> prefix
))
221 if ((guestsrc
< prefix
+ 2 * PAGE_SIZE
)
222 && (guestsrc
+ n
> prefix
+ 2 * PAGE_SIZE
))
225 if (guestsrc
< 2 * PAGE_SIZE
)
227 else if ((guestsrc
>= prefix
) && (guestsrc
< prefix
+ 2 * PAGE_SIZE
))
230 if (guestsrc
+ n
> memsize
)
233 if (guestsrc
+ n
< guestsrc
)
238 return copy_from_user(to
, (void __user
*) guestsrc
, n
);
240 return __copy_from_guest_slow(vcpu
, to
, guestsrc
, n
);
243 static inline int copy_to_guest_absolute(struct kvm_vcpu
*vcpu
,
244 unsigned long guestdest
,
245 const void *from
, unsigned long n
)
247 unsigned long origin
= vcpu
->kvm
->arch
.guest_origin
;
248 unsigned long memsize
= vcpu
->kvm
->arch
.guest_memsize
;
250 if (guestdest
+ n
> memsize
)
253 if (guestdest
+ n
< guestdest
)
258 return copy_to_user((void __user
*) guestdest
, from
, n
);
261 static inline int copy_from_guest_absolute(struct kvm_vcpu
*vcpu
, void *to
,
262 unsigned long guestsrc
,
265 unsigned long origin
= vcpu
->kvm
->arch
.guest_origin
;
266 unsigned long memsize
= vcpu
->kvm
->arch
.guest_memsize
;
268 if (guestsrc
+ n
> memsize
)
271 if (guestsrc
+ n
< guestsrc
)
276 return copy_from_user(to
, (void __user
*) guestsrc
, n
);