Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/s390/kvm/gaccess.h
10817 views
1
/*
2
* gaccess.h - 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 <[email protected]>
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 *__guestaddr_to_user(struct kvm_vcpu *vcpu,
22
unsigned long guestaddr)
23
{
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);
27
28
if (guestaddr < 2 * PAGE_SIZE)
29
guestaddr += prefix;
30
else if ((guestaddr >= prefix) && (guestaddr < prefix + 2 * PAGE_SIZE))
31
guestaddr -= prefix;
32
33
if (guestaddr > memsize)
34
return (void __user __force *) ERR_PTR(-EFAULT);
35
36
guestaddr += origin;
37
38
return (void __user *) guestaddr;
39
}
40
41
static inline int get_guest_u64(struct kvm_vcpu *vcpu, unsigned long guestaddr,
42
u64 *result)
43
{
44
void __user *uptr = __guestaddr_to_user(vcpu, guestaddr);
45
46
BUG_ON(guestaddr & 7);
47
48
if (IS_ERR((void __force *) uptr))
49
return PTR_ERR((void __force *) uptr);
50
51
return get_user(*result, (unsigned long __user *) uptr);
52
}
53
54
static inline int get_guest_u32(struct kvm_vcpu *vcpu, unsigned long guestaddr,
55
u32 *result)
56
{
57
void __user *uptr = __guestaddr_to_user(vcpu, guestaddr);
58
59
BUG_ON(guestaddr & 3);
60
61
if (IS_ERR((void __force *) uptr))
62
return PTR_ERR((void __force *) uptr);
63
64
return get_user(*result, (u32 __user *) uptr);
65
}
66
67
static inline int get_guest_u16(struct kvm_vcpu *vcpu, unsigned long guestaddr,
68
u16 *result)
69
{
70
void __user *uptr = __guestaddr_to_user(vcpu, guestaddr);
71
72
BUG_ON(guestaddr & 1);
73
74
if (IS_ERR(uptr))
75
return PTR_ERR(uptr);
76
77
return get_user(*result, (u16 __user *) uptr);
78
}
79
80
static inline int get_guest_u8(struct kvm_vcpu *vcpu, unsigned long guestaddr,
81
u8 *result)
82
{
83
void __user *uptr = __guestaddr_to_user(vcpu, guestaddr);
84
85
if (IS_ERR((void __force *) uptr))
86
return PTR_ERR((void __force *) uptr);
87
88
return get_user(*result, (u8 __user *) uptr);
89
}
90
91
static inline int put_guest_u64(struct kvm_vcpu *vcpu, unsigned long guestaddr,
92
u64 value)
93
{
94
void __user *uptr = __guestaddr_to_user(vcpu, guestaddr);
95
96
BUG_ON(guestaddr & 7);
97
98
if (IS_ERR((void __force *) uptr))
99
return PTR_ERR((void __force *) uptr);
100
101
return put_user(value, (u64 __user *) uptr);
102
}
103
104
static inline int put_guest_u32(struct kvm_vcpu *vcpu, unsigned long guestaddr,
105
u32 value)
106
{
107
void __user *uptr = __guestaddr_to_user(vcpu, guestaddr);
108
109
BUG_ON(guestaddr & 3);
110
111
if (IS_ERR((void __force *) uptr))
112
return PTR_ERR((void __force *) uptr);
113
114
return put_user(value, (u32 __user *) uptr);
115
}
116
117
static inline int put_guest_u16(struct kvm_vcpu *vcpu, unsigned long guestaddr,
118
u16 value)
119
{
120
void __user *uptr = __guestaddr_to_user(vcpu, guestaddr);
121
122
BUG_ON(guestaddr & 1);
123
124
if (IS_ERR((void __force *) uptr))
125
return PTR_ERR((void __force *) uptr);
126
127
return put_user(value, (u16 __user *) uptr);
128
}
129
130
static inline int put_guest_u8(struct kvm_vcpu *vcpu, unsigned long guestaddr,
131
u8 value)
132
{
133
void __user *uptr = __guestaddr_to_user(vcpu, guestaddr);
134
135
if (IS_ERR((void __force *) uptr))
136
return PTR_ERR((void __force *) uptr);
137
138
return put_user(value, (u8 __user *) uptr);
139
}
140
141
142
static inline int __copy_to_guest_slow(struct kvm_vcpu *vcpu,
143
unsigned long guestdest,
144
const void *from, unsigned long n)
145
{
146
int rc;
147
unsigned long i;
148
const u8 *data = from;
149
150
for (i = 0; i < n; i++) {
151
rc = put_guest_u8(vcpu, guestdest++, *(data++));
152
if (rc < 0)
153
return rc;
154
}
155
return 0;
156
}
157
158
static inline int copy_to_guest(struct kvm_vcpu *vcpu, unsigned long guestdest,
159
const void *from, unsigned long n)
160
{
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);
164
165
if ((guestdest < 2 * PAGE_SIZE) && (guestdest + n > 2 * PAGE_SIZE))
166
goto slowpath;
167
168
if ((guestdest < prefix) && (guestdest + n > prefix))
169
goto slowpath;
170
171
if ((guestdest < prefix + 2 * PAGE_SIZE)
172
&& (guestdest + n > prefix + 2 * PAGE_SIZE))
173
goto slowpath;
174
175
if (guestdest < 2 * PAGE_SIZE)
176
guestdest += prefix;
177
else if ((guestdest >= prefix) && (guestdest < prefix + 2 * PAGE_SIZE))
178
guestdest -= prefix;
179
180
if (guestdest + n > memsize)
181
return -EFAULT;
182
183
if (guestdest + n < guestdest)
184
return -EFAULT;
185
186
guestdest += origin;
187
188
return copy_to_user((void __user *) guestdest, from, n);
189
slowpath:
190
return __copy_to_guest_slow(vcpu, guestdest, from, n);
191
}
192
193
static inline int __copy_from_guest_slow(struct kvm_vcpu *vcpu, void *to,
194
unsigned long guestsrc,
195
unsigned long n)
196
{
197
int rc;
198
unsigned long i;
199
u8 *data = to;
200
201
for (i = 0; i < n; i++) {
202
rc = get_guest_u8(vcpu, guestsrc++, data++);
203
if (rc < 0)
204
return rc;
205
}
206
return 0;
207
}
208
209
static inline int copy_from_guest(struct kvm_vcpu *vcpu, void *to,
210
unsigned long guestsrc, unsigned long n)
211
{
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);
215
216
if ((guestsrc < 2 * PAGE_SIZE) && (guestsrc + n > 2 * PAGE_SIZE))
217
goto slowpath;
218
219
if ((guestsrc < prefix) && (guestsrc + n > prefix))
220
goto slowpath;
221
222
if ((guestsrc < prefix + 2 * PAGE_SIZE)
223
&& (guestsrc + n > prefix + 2 * PAGE_SIZE))
224
goto slowpath;
225
226
if (guestsrc < 2 * PAGE_SIZE)
227
guestsrc += prefix;
228
else if ((guestsrc >= prefix) && (guestsrc < prefix + 2 * PAGE_SIZE))
229
guestsrc -= prefix;
230
231
if (guestsrc + n > memsize)
232
return -EFAULT;
233
234
if (guestsrc + n < guestsrc)
235
return -EFAULT;
236
237
guestsrc += origin;
238
239
return copy_from_user(to, (void __user *) guestsrc, n);
240
slowpath:
241
return __copy_from_guest_slow(vcpu, to, guestsrc, n);
242
}
243
244
static inline int copy_to_guest_absolute(struct kvm_vcpu *vcpu,
245
unsigned long guestdest,
246
const void *from, unsigned long n)
247
{
248
unsigned long origin = vcpu->arch.sie_block->gmsor;
249
unsigned long memsize = kvm_s390_vcpu_get_memsize(vcpu);
250
251
if (guestdest + n > memsize)
252
return -EFAULT;
253
254
if (guestdest + n < guestdest)
255
return -EFAULT;
256
257
guestdest += origin;
258
259
return copy_to_user((void __user *) guestdest, from, n);
260
}
261
262
static inline int copy_from_guest_absolute(struct kvm_vcpu *vcpu, void *to,
263
unsigned long guestsrc,
264
unsigned long n)
265
{
266
unsigned long origin = vcpu->arch.sie_block->gmsor;
267
unsigned long memsize = kvm_s390_vcpu_get_memsize(vcpu);
268
269
if (guestsrc + n > memsize)
270
return -EFAULT;
271
272
if (guestsrc + n < guestsrc)
273
return -EFAULT;
274
275
guestsrc += origin;
276
277
return copy_from_user(to, (void __user *) guestsrc, n);
278
}
279
#endif
280
281