• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-R7000-V1.0.7.12_1.2.5/components/opensource/linux/linux-2.6.36/arch/s390/kvm/
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 <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
21static 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
41static 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
54static 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
67static 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
80static 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
91static 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
104static 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
117static 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
130static 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
142static 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
158static 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);
189slowpath:
190	return __copy_to_guest_slow(vcpu, guestdest, from, n);
191}
192
193static 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
209static 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);
240slowpath:
241	return __copy_from_guest_slow(vcpu, to, guestsrc, n);
242}
243
244static 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
262static 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