diff options
author | Heiko Carstens <heiko.carstens@de.ibm.com> | 2014-01-01 10:23:29 -0500 |
---|---|---|
committer | Christian Borntraeger <borntraeger@de.ibm.com> | 2014-04-22 07:24:37 -0400 |
commit | d95fb12ff4d73e897126043bb5d03a068997a2ef (patch) | |
tree | e8b5b34cb7810fa7bb8f7ae3edcb2f3d7ea404da | |
parent | 1b0462e574f5238bb1ee811f014d629092c160cb (diff) |
KVM: s390: add lowcore access functions
put_guest_lc, read_guest_lc and write_guest_lc are guest access
functions which shall only be used to access the lowcore of a vcpu.
These functions should be used for e.g. interrupt handlers where no
guest memory access protection facilities, like key or low address
protection, are applicable.
At a later point guest vcpu lowcore access should happen via pinned
prefix pages, so that these pages can be accessed directly via the
kernel mapping. All of these *_lc functions can be removed then.
Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com>
Reviewed-by: Thomas Huth <thuth@linux.vnet.ibm.com>
Reviewed-by: Cornelia Huck <cornelia.huck@de.ibm.com>
Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
-rw-r--r-- | arch/s390/kvm/gaccess.h | 95 |
1 files changed, 93 insertions, 2 deletions
diff --git a/arch/s390/kvm/gaccess.h b/arch/s390/kvm/gaccess.h index ae3cb638f220..917aeaa04fff 100644 --- a/arch/s390/kvm/gaccess.h +++ b/arch/s390/kvm/gaccess.h | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * access guest memory | 2 | * access guest memory |
3 | * | 3 | * |
4 | * Copyright IBM Corp. 2008, 2009 | 4 | * Copyright IBM Corp. 2008, 2014 |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify | 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) | 7 | * it under the terms of the GNU General Public License (version 2 only) |
@@ -15,7 +15,8 @@ | |||
15 | 15 | ||
16 | #include <linux/compiler.h> | 16 | #include <linux/compiler.h> |
17 | #include <linux/kvm_host.h> | 17 | #include <linux/kvm_host.h> |
18 | #include <asm/uaccess.h> | 18 | #include <linux/uaccess.h> |
19 | #include <linux/ptrace.h> | ||
19 | #include "kvm-s390.h" | 20 | #include "kvm-s390.h" |
20 | 21 | ||
21 | /* Convert real to absolute address by applying the prefix of the CPU */ | 22 | /* Convert real to absolute address by applying the prefix of the CPU */ |
@@ -136,4 +137,94 @@ static inline int __copy_guest(struct kvm_vcpu *vcpu, unsigned long to, | |||
136 | #define copy_from_guest_absolute(vcpu, to, from, size) \ | 137 | #define copy_from_guest_absolute(vcpu, to, from, size) \ |
137 | __copy_guest(vcpu, (unsigned long)to, from, size, 0, 0) | 138 | __copy_guest(vcpu, (unsigned long)to, from, size, 0, 0) |
138 | 139 | ||
140 | /* | ||
141 | * put_guest_lc, read_guest_lc and write_guest_lc are guest access functions | ||
142 | * which shall only be used to access the lowcore of a vcpu. | ||
143 | * These functions should be used for e.g. interrupt handlers where no | ||
144 | * guest memory access protection facilities, like key or low address | ||
145 | * protection, are applicable. | ||
146 | * At a later point guest vcpu lowcore access should happen via pinned | ||
147 | * prefix pages, so that these pages can be accessed directly via the | ||
148 | * kernel mapping. All of these *_lc functions can be removed then. | ||
149 | */ | ||
150 | |||
151 | /** | ||
152 | * put_guest_lc - write a simple variable to a guest vcpu's lowcore | ||
153 | * @vcpu: virtual cpu | ||
154 | * @x: value to copy to guest | ||
155 | * @gra: vcpu's destination guest real address | ||
156 | * | ||
157 | * Copies a simple value from kernel space to a guest vcpu's lowcore. | ||
158 | * The size of the variable may be 1, 2, 4 or 8 bytes. The destination | ||
159 | * must be located in the vcpu's lowcore. Otherwise the result is undefined. | ||
160 | * | ||
161 | * Returns zero on success or -EFAULT on error. | ||
162 | * | ||
163 | * Note: an error indicates that either the kernel is out of memory or | ||
164 | * the guest memory mapping is broken. In any case the best solution | ||
165 | * would be to terminate the guest. | ||
166 | * It is wrong to inject a guest exception. | ||
167 | */ | ||
168 | #define put_guest_lc(vcpu, x, gra) \ | ||
169 | ({ \ | ||
170 | struct kvm_vcpu *__vcpu = (vcpu); \ | ||
171 | __typeof__(*(gra)) __x = (x); \ | ||
172 | unsigned long __gpa; \ | ||
173 | \ | ||
174 | __gpa = (unsigned long)(gra); \ | ||
175 | __gpa += __vcpu->arch.sie_block->prefix; \ | ||
176 | kvm_write_guest(__vcpu->kvm, __gpa, &__x, sizeof(__x)); \ | ||
177 | }) | ||
178 | |||
179 | /** | ||
180 | * write_guest_lc - copy data from kernel space to guest vcpu's lowcore | ||
181 | * @vcpu: virtual cpu | ||
182 | * @gra: vcpu's source guest real address | ||
183 | * @data: source address in kernel space | ||
184 | * @len: number of bytes to copy | ||
185 | * | ||
186 | * Copy data from kernel space to guest vcpu's lowcore. The entire range must | ||
187 | * be located within the vcpu's lowcore, otherwise the result is undefined. | ||
188 | * | ||
189 | * Returns zero on success or -EFAULT on error. | ||
190 | * | ||
191 | * Note: an error indicates that either the kernel is out of memory or | ||
192 | * the guest memory mapping is broken. In any case the best solution | ||
193 | * would be to terminate the guest. | ||
194 | * It is wrong to inject a guest exception. | ||
195 | */ | ||
196 | static inline __must_check | ||
197 | int write_guest_lc(struct kvm_vcpu *vcpu, unsigned long gra, void *data, | ||
198 | unsigned long len) | ||
199 | { | ||
200 | unsigned long gpa = gra + vcpu->arch.sie_block->prefix; | ||
201 | |||
202 | return kvm_write_guest(vcpu->kvm, gpa, data, len); | ||
203 | } | ||
204 | |||
205 | /** | ||
206 | * read_guest_lc - copy data from guest vcpu's lowcore to kernel space | ||
207 | * @vcpu: virtual cpu | ||
208 | * @gra: vcpu's source guest real address | ||
209 | * @data: destination address in kernel space | ||
210 | * @len: number of bytes to copy | ||
211 | * | ||
212 | * Copy data from guest vcpu's lowcore to kernel space. The entire range must | ||
213 | * be located within the vcpu's lowcore, otherwise the result is undefined. | ||
214 | * | ||
215 | * Returns zero on success or -EFAULT on error. | ||
216 | * | ||
217 | * Note: an error indicates that either the kernel is out of memory or | ||
218 | * the guest memory mapping is broken. In any case the best solution | ||
219 | * would be to terminate the guest. | ||
220 | * It is wrong to inject a guest exception. | ||
221 | */ | ||
222 | static inline __must_check | ||
223 | int read_guest_lc(struct kvm_vcpu *vcpu, unsigned long gra, void *data, | ||
224 | unsigned long len) | ||
225 | { | ||
226 | unsigned long gpa = gra + vcpu->arch.sie_block->prefix; | ||
227 | |||
228 | return kvm_read_guest(vcpu->kvm, gpa, data, len); | ||
229 | } | ||
139 | #endif /* __KVM_S390_GACCESS_H */ | 230 | #endif /* __KVM_S390_GACCESS_H */ |