]>
Commit | Line | Data |
---|---|---|
d809aa23 | 1 | /* SPDX-License-Identifier: GPL-2.0 */ |
b0c632db | 2 | /* |
a53c8fab | 3 | * access guest memory |
b0c632db | 4 | * |
d95fb12f | 5 | * Copyright IBM Corp. 2008, 2014 |
b0c632db | 6 | * |
b0c632db HC |
7 | * Author(s): Carsten Otte <cotte@de.ibm.com> |
8 | */ | |
9 | ||
10 | #ifndef __KVM_S390_GACCESS_H | |
11 | #define __KVM_S390_GACCESS_H | |
12 | ||
13 | #include <linux/compiler.h> | |
14 | #include <linux/kvm_host.h> | |
d95fb12f HC |
15 | #include <linux/uaccess.h> |
16 | #include <linux/ptrace.h> | |
628eb9b8 | 17 | #include "kvm-s390.h" |
b0c632db | 18 | |
e497a96a HC |
19 | /** |
20 | * kvm_s390_real_to_abs - convert guest real address to guest absolute address | |
21 | * @vcpu - guest virtual cpu | |
22 | * @gra - guest real address | |
23 | * | |
24 | * Returns the guest absolute address that corresponds to the passed guest real | |
25 | * address @gra of a virtual guest cpu by applying its prefix. | |
26 | */ | |
732e5633 | 27 | static inline unsigned long kvm_s390_real_to_abs(struct kvm_vcpu *vcpu, |
e497a96a | 28 | unsigned long gra) |
732e5633 | 29 | { |
fda902cb | 30 | unsigned long prefix = kvm_s390_get_prefix(vcpu); |
e497a96a HC |
31 | |
32 | if (gra < 2 * PAGE_SIZE) | |
33 | gra += prefix; | |
34 | else if (gra >= prefix && gra < prefix + 2 * PAGE_SIZE) | |
35 | gra -= prefix; | |
36 | return gra; | |
732e5633 TH |
37 | } |
38 | ||
072c9878 HC |
39 | /** |
40 | * kvm_s390_logical_to_effective - convert guest logical to effective address | |
41 | * @vcpu: guest virtual cpu | |
42 | * @ga: guest logical address | |
43 | * | |
44 | * Convert a guest vcpu logical address to a guest vcpu effective address by | |
45 | * applying the rules of the vcpu's addressing mode defined by PSW bits 31 | |
46 | * and 32 (extendended/basic addressing mode). | |
47 | * | |
48 | * Depending on the vcpu's addressing mode the upper 40 bits (24 bit addressing | |
49 | * mode), 33 bits (31 bit addressing mode) or no bits (64 bit addressing mode) | |
50 | * of @ga will be zeroed and the remaining bits will be returned. | |
51 | */ | |
52 | static inline unsigned long kvm_s390_logical_to_effective(struct kvm_vcpu *vcpu, | |
53 | unsigned long ga) | |
54 | { | |
55 | psw_t *psw = &vcpu->arch.sie_block->gpsw; | |
56 | ||
8bb3fdd6 | 57 | if (psw_bits(*psw).eaba == PSW_BITS_AMODE_64BIT) |
072c9878 | 58 | return ga; |
8bb3fdd6 | 59 | if (psw_bits(*psw).eaba == PSW_BITS_AMODE_31BIT) |
072c9878 HC |
60 | return ga & ((1UL << 31) - 1); |
61 | return ga & ((1UL << 24) - 1); | |
62 | } | |
63 | ||
d95fb12f HC |
64 | /* |
65 | * put_guest_lc, read_guest_lc and write_guest_lc are guest access functions | |
66 | * which shall only be used to access the lowcore of a vcpu. | |
67 | * These functions should be used for e.g. interrupt handlers where no | |
68 | * guest memory access protection facilities, like key or low address | |
69 | * protection, are applicable. | |
70 | * At a later point guest vcpu lowcore access should happen via pinned | |
71 | * prefix pages, so that these pages can be accessed directly via the | |
72 | * kernel mapping. All of these *_lc functions can be removed then. | |
73 | */ | |
74 | ||
75 | /** | |
76 | * put_guest_lc - write a simple variable to a guest vcpu's lowcore | |
77 | * @vcpu: virtual cpu | |
78 | * @x: value to copy to guest | |
79 | * @gra: vcpu's destination guest real address | |
80 | * | |
81 | * Copies a simple value from kernel space to a guest vcpu's lowcore. | |
82 | * The size of the variable may be 1, 2, 4 or 8 bytes. The destination | |
83 | * must be located in the vcpu's lowcore. Otherwise the result is undefined. | |
84 | * | |
85 | * Returns zero on success or -EFAULT on error. | |
86 | * | |
87 | * Note: an error indicates that either the kernel is out of memory or | |
88 | * the guest memory mapping is broken. In any case the best solution | |
89 | * would be to terminate the guest. | |
90 | * It is wrong to inject a guest exception. | |
91 | */ | |
92 | #define put_guest_lc(vcpu, x, gra) \ | |
93 | ({ \ | |
94 | struct kvm_vcpu *__vcpu = (vcpu); \ | |
95 | __typeof__(*(gra)) __x = (x); \ | |
96 | unsigned long __gpa; \ | |
97 | \ | |
98 | __gpa = (unsigned long)(gra); \ | |
fda902cb | 99 | __gpa += kvm_s390_get_prefix(__vcpu); \ |
d95fb12f HC |
100 | kvm_write_guest(__vcpu->kvm, __gpa, &__x, sizeof(__x)); \ |
101 | }) | |
102 | ||
103 | /** | |
104 | * write_guest_lc - copy data from kernel space to guest vcpu's lowcore | |
105 | * @vcpu: virtual cpu | |
106 | * @gra: vcpu's source guest real address | |
107 | * @data: source address in kernel space | |
108 | * @len: number of bytes to copy | |
109 | * | |
110 | * Copy data from kernel space to guest vcpu's lowcore. The entire range must | |
111 | * be located within the vcpu's lowcore, otherwise the result is undefined. | |
112 | * | |
113 | * Returns zero on success or -EFAULT on error. | |
114 | * | |
115 | * Note: an error indicates that either the kernel is out of memory or | |
116 | * the guest memory mapping is broken. In any case the best solution | |
117 | * would be to terminate the guest. | |
118 | * It is wrong to inject a guest exception. | |
119 | */ | |
120 | static inline __must_check | |
121 | int write_guest_lc(struct kvm_vcpu *vcpu, unsigned long gra, void *data, | |
122 | unsigned long len) | |
123 | { | |
fda902cb | 124 | unsigned long gpa = gra + kvm_s390_get_prefix(vcpu); |
d95fb12f HC |
125 | |
126 | return kvm_write_guest(vcpu->kvm, gpa, data, len); | |
127 | } | |
128 | ||
129 | /** | |
130 | * read_guest_lc - copy data from guest vcpu's lowcore to kernel space | |
131 | * @vcpu: virtual cpu | |
132 | * @gra: vcpu's source guest real address | |
133 | * @data: destination address in kernel space | |
134 | * @len: number of bytes to copy | |
135 | * | |
136 | * Copy data from guest vcpu's lowcore to kernel space. The entire range must | |
137 | * be located within the vcpu's lowcore, otherwise the result is undefined. | |
138 | * | |
139 | * Returns zero on success or -EFAULT on error. | |
140 | * | |
141 | * Note: an error indicates that either the kernel is out of memory or | |
142 | * the guest memory mapping is broken. In any case the best solution | |
143 | * would be to terminate the guest. | |
144 | * It is wrong to inject a guest exception. | |
145 | */ | |
146 | static inline __must_check | |
147 | int read_guest_lc(struct kvm_vcpu *vcpu, unsigned long gra, void *data, | |
148 | unsigned long len) | |
149 | { | |
fda902cb | 150 | unsigned long gpa = gra + kvm_s390_get_prefix(vcpu); |
d95fb12f HC |
151 | |
152 | return kvm_read_guest(vcpu->kvm, gpa, data, len); | |
153 | } | |
22938978 | 154 | |
92c96321 DH |
155 | enum gacc_mode { |
156 | GACC_FETCH, | |
157 | GACC_STORE, | |
34346b9a | 158 | GACC_IFETCH, |
92c96321 DH |
159 | }; |
160 | ||
9fbc0276 | 161 | int guest_translate_address(struct kvm_vcpu *vcpu, unsigned long gva, |
27f67f87 CB |
162 | u8 ar, unsigned long *gpa, enum gacc_mode mode); |
163 | int check_gva_range(struct kvm_vcpu *vcpu, unsigned long gva, u8 ar, | |
92c96321 | 164 | unsigned long length, enum gacc_mode mode); |
9fbc0276 | 165 | |
27f67f87 | 166 | int access_guest(struct kvm_vcpu *vcpu, unsigned long ga, u8 ar, void *data, |
92c96321 | 167 | unsigned long len, enum gacc_mode mode); |
22938978 HC |
168 | |
169 | int access_guest_real(struct kvm_vcpu *vcpu, unsigned long gra, | |
92c96321 | 170 | void *data, unsigned long len, enum gacc_mode mode); |
22938978 HC |
171 | |
172 | /** | |
173 | * write_guest - copy data from kernel space to guest space | |
174 | * @vcpu: virtual cpu | |
175 | * @ga: guest address | |
8ae04b8f | 176 | * @ar: access register |
22938978 HC |
177 | * @data: source address in kernel space |
178 | * @len: number of bytes to copy | |
179 | * | |
180 | * Copy @len bytes from @data (kernel space) to @ga (guest address). | |
181 | * In order to copy data to guest space the PSW of the vcpu is inspected: | |
182 | * If DAT is off data will be copied to guest real or absolute memory. | |
183 | * If DAT is on data will be copied to the address space as specified by | |
184 | * the address space bits of the PSW: | |
664b4973 | 185 | * Primary, secondary, home space or access register mode. |
22938978 HC |
186 | * The addressing mode of the PSW is also inspected, so that address wrap |
187 | * around is taken into account for 24-, 31- and 64-bit addressing mode, | |
188 | * if the to be copied data crosses page boundaries in guest address space. | |
189 | * In addition also low address and DAT protection are inspected before | |
190 | * copying any data (key protection is currently not implemented). | |
191 | * | |
192 | * This function modifies the 'struct kvm_s390_pgm_info pgm' member of @vcpu. | |
193 | * In case of an access exception (e.g. protection exception) pgm will contain | |
194 | * all data necessary so that a subsequent call to 'kvm_s390_inject_prog_vcpu()' | |
195 | * will inject a correct exception into the guest. | |
196 | * If no access exception happened, the contents of pgm are undefined when | |
197 | * this function returns. | |
198 | * | |
199 | * Returns: - zero on success | |
200 | * - a negative value if e.g. the guest mapping is broken or in | |
201 | * case of out-of-memory. In this case the contents of pgm are | |
202 | * undefined. Also parts of @data may have been copied to guest | |
203 | * space. | |
204 | * - a positive value if an access exception happened. In this case | |
205 | * the returned value is the program interruption code and the | |
206 | * contents of pgm may be used to inject an exception into the | |
207 | * guest. No data has been copied to guest space. | |
208 | * | |
209 | * Note: in case an access exception is recognized no data has been copied to | |
210 | * guest space (this is also true, if the to be copied data would cross | |
211 | * one or more page boundaries in guest space). | |
212 | * Therefore this function may be used for nullifying and suppressing | |
213 | * instruction emulation. | |
214 | * It may also be used for terminating instructions, if it is undefined | |
215 | * if data has been changed in guest space in case of an exception. | |
216 | */ | |
217 | static inline __must_check | |
27f67f87 | 218 | int write_guest(struct kvm_vcpu *vcpu, unsigned long ga, u8 ar, void *data, |
22938978 HC |
219 | unsigned long len) |
220 | { | |
92c96321 | 221 | return access_guest(vcpu, ga, ar, data, len, GACC_STORE); |
22938978 HC |
222 | } |
223 | ||
224 | /** | |
225 | * read_guest - copy data from guest space to kernel space | |
226 | * @vcpu: virtual cpu | |
227 | * @ga: guest address | |
8ae04b8f | 228 | * @ar: access register |
22938978 HC |
229 | * @data: destination address in kernel space |
230 | * @len: number of bytes to copy | |
231 | * | |
232 | * Copy @len bytes from @ga (guest address) to @data (kernel space). | |
233 | * | |
234 | * The behaviour of read_guest is identical to write_guest, except that | |
235 | * data will be copied from guest space to kernel space. | |
236 | */ | |
237 | static inline __must_check | |
27f67f87 | 238 | int read_guest(struct kvm_vcpu *vcpu, unsigned long ga, u8 ar, void *data, |
22938978 HC |
239 | unsigned long len) |
240 | { | |
92c96321 | 241 | return access_guest(vcpu, ga, ar, data, len, GACC_FETCH); |
22938978 HC |
242 | } |
243 | ||
34346b9a DH |
244 | /** |
245 | * read_guest_instr - copy instruction data from guest space to kernel space | |
246 | * @vcpu: virtual cpu | |
3fa8cad7 | 247 | * @ga: guest address |
34346b9a DH |
248 | * @data: destination address in kernel space |
249 | * @len: number of bytes to copy | |
250 | * | |
3fa8cad7 | 251 | * Copy @len bytes from the given address (guest space) to @data (kernel |
34346b9a DH |
252 | * space). |
253 | * | |
254 | * The behaviour of read_guest_instr is identical to read_guest, except that | |
255 | * instruction data will be read from primary space when in home-space or | |
256 | * address-space mode. | |
257 | */ | |
258 | static inline __must_check | |
3fa8cad7 DH |
259 | int read_guest_instr(struct kvm_vcpu *vcpu, unsigned long ga, void *data, |
260 | unsigned long len) | |
34346b9a | 261 | { |
3fa8cad7 | 262 | return access_guest(vcpu, ga, 0, data, len, GACC_IFETCH); |
34346b9a DH |
263 | } |
264 | ||
22938978 HC |
265 | /** |
266 | * write_guest_abs - copy data from kernel space to guest space absolute | |
267 | * @vcpu: virtual cpu | |
268 | * @gpa: guest physical (absolute) address | |
269 | * @data: source address in kernel space | |
270 | * @len: number of bytes to copy | |
271 | * | |
272 | * Copy @len bytes from @data (kernel space) to @gpa (guest absolute address). | |
273 | * It is up to the caller to ensure that the entire guest memory range is | |
274 | * valid memory before calling this function. | |
275 | * Guest low address and key protection are not checked. | |
276 | * | |
277 | * Returns zero on success or -EFAULT on error. | |
278 | * | |
279 | * If an error occurs data may have been copied partially to guest memory. | |
280 | */ | |
281 | static inline __must_check | |
282 | int write_guest_abs(struct kvm_vcpu *vcpu, unsigned long gpa, void *data, | |
283 | unsigned long len) | |
284 | { | |
285 | return kvm_write_guest(vcpu->kvm, gpa, data, len); | |
286 | } | |
287 | ||
288 | /** | |
289 | * read_guest_abs - copy data from guest space absolute to kernel space | |
290 | * @vcpu: virtual cpu | |
291 | * @gpa: guest physical (absolute) address | |
292 | * @data: destination address in kernel space | |
293 | * @len: number of bytes to copy | |
294 | * | |
295 | * Copy @len bytes from @gpa (guest absolute address) to @data (kernel space). | |
296 | * It is up to the caller to ensure that the entire guest memory range is | |
297 | * valid memory before calling this function. | |
298 | * Guest key protection is not checked. | |
299 | * | |
300 | * Returns zero on success or -EFAULT on error. | |
301 | * | |
302 | * If an error occurs data may have been copied partially to kernel space. | |
303 | */ | |
304 | static inline __must_check | |
305 | int read_guest_abs(struct kvm_vcpu *vcpu, unsigned long gpa, void *data, | |
306 | unsigned long len) | |
307 | { | |
308 | return kvm_read_guest(vcpu->kvm, gpa, data, len); | |
309 | } | |
310 | ||
311 | /** | |
312 | * write_guest_real - copy data from kernel space to guest space real | |
313 | * @vcpu: virtual cpu | |
314 | * @gra: guest real address | |
315 | * @data: source address in kernel space | |
316 | * @len: number of bytes to copy | |
317 | * | |
318 | * Copy @len bytes from @data (kernel space) to @gra (guest real address). | |
319 | * It is up to the caller to ensure that the entire guest memory range is | |
320 | * valid memory before calling this function. | |
321 | * Guest low address and key protection are not checked. | |
322 | * | |
323 | * Returns zero on success or -EFAULT on error. | |
324 | * | |
325 | * If an error occurs data may have been copied partially to guest memory. | |
326 | */ | |
327 | static inline __must_check | |
328 | int write_guest_real(struct kvm_vcpu *vcpu, unsigned long gra, void *data, | |
329 | unsigned long len) | |
330 | { | |
331 | return access_guest_real(vcpu, gra, data, len, 1); | |
332 | } | |
333 | ||
334 | /** | |
335 | * read_guest_real - copy data from guest space real to kernel space | |
336 | * @vcpu: virtual cpu | |
337 | * @gra: guest real address | |
338 | * @data: destination address in kernel space | |
339 | * @len: number of bytes to copy | |
340 | * | |
341 | * Copy @len bytes from @gra (guest real address) to @data (kernel space). | |
342 | * It is up to the caller to ensure that the entire guest memory range is | |
343 | * valid memory before calling this function. | |
344 | * Guest key protection is not checked. | |
345 | * | |
346 | * Returns zero on success or -EFAULT on error. | |
347 | * | |
348 | * If an error occurs data may have been copied partially to kernel space. | |
349 | */ | |
350 | static inline __must_check | |
351 | int read_guest_real(struct kvm_vcpu *vcpu, unsigned long gra, void *data, | |
352 | unsigned long len) | |
353 | { | |
354 | return access_guest_real(vcpu, gra, data, len, 0); | |
355 | } | |
356 | ||
a0465f9a TH |
357 | void ipte_lock(struct kvm_vcpu *vcpu); |
358 | void ipte_unlock(struct kvm_vcpu *vcpu); | |
8a242234 | 359 | int ipte_lock_held(struct kvm_vcpu *vcpu); |
dd9e5b7b | 360 | int kvm_s390_check_low_addr_prot_real(struct kvm_vcpu *vcpu, unsigned long gra); |
8a242234 | 361 | |
f4debb40 DH |
362 | int kvm_s390_shadow_fault(struct kvm_vcpu *vcpu, struct gmap *shadow, |
363 | unsigned long saddr); | |
aa17aa57 | 364 | |
f9dc72e8 | 365 | #endif /* __KVM_S390_GACCESS_H */ |