| 
									
										
										
										
											2008-03-25 18:47:20 +01:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2012-07-20 11:15:04 +02:00
										 |  |  |  * access guest memory | 
					
						
							| 
									
										
										
										
											2008-03-25 18:47:20 +01:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2012-07-20 11:15:04 +02:00
										 |  |  |  * Copyright IBM Corp. 2008, 2009 | 
					
						
							| 
									
										
										
										
											2008-03-25 18:47:20 +01:00
										 |  |  |  * | 
					
						
							|  |  |  |  * This program is free software; you can redistribute it and/or modify | 
					
						
							|  |  |  |  * it under the terms of the GNU General Public License (version 2 only) | 
					
						
							|  |  |  |  * as published by the Free Software Foundation. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  *    Author(s): Carsten Otte <cotte@de.ibm.com> | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifndef __KVM_S390_GACCESS_H
 | 
					
						
							|  |  |  | #define __KVM_S390_GACCESS_H
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <linux/compiler.h>
 | 
					
						
							|  |  |  | #include <linux/kvm_host.h>
 | 
					
						
							|  |  |  | #include <asm/uaccess.h>
 | 
					
						
							| 
									
										
										
										
											2009-05-25 13:40:51 +02:00
										 |  |  | #include "kvm-s390.h"
 | 
					
						
							| 
									
										
										
										
											2008-03-25 18:47:20 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-05 13:14:47 +01:00
										 |  |  | static inline void __user *__gptr_to_uptr(struct kvm_vcpu *vcpu, | 
					
						
							|  |  |  | 					  void __user *gptr, | 
					
						
							|  |  |  | 					  int prefixing) | 
					
						
							| 
									
										
										
										
											2008-03-25 18:47:20 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2008-07-25 15:51:00 +02:00
										 |  |  | 	unsigned long prefix  = vcpu->arch.sie_block->prefix; | 
					
						
							| 
									
										
										
										
											2013-03-05 13:14:44 +01:00
										 |  |  | 	unsigned long gaddr = (unsigned long) gptr; | 
					
						
							|  |  |  | 	unsigned long uaddr; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-05 13:14:45 +01:00
										 |  |  | 	if (prefixing) { | 
					
						
							|  |  |  | 		if (gaddr < 2 * PAGE_SIZE) | 
					
						
							|  |  |  | 			gaddr += prefix; | 
					
						
							|  |  |  | 		else if ((gaddr >= prefix) && (gaddr < prefix + 2 * PAGE_SIZE)) | 
					
						
							|  |  |  | 			gaddr -= prefix; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2013-03-05 13:14:44 +01:00
										 |  |  | 	uaddr = gmap_fault(gaddr, vcpu->arch.gmap); | 
					
						
							|  |  |  | 	if (IS_ERR_VALUE(uaddr)) | 
					
						
							|  |  |  | 		uaddr = -EFAULT; | 
					
						
							| 
									
										
										
										
											2013-03-05 13:14:47 +01:00
										 |  |  | 	return (void __user *)uaddr; | 
					
						
							| 
									
										
										
										
											2008-03-25 18:47:20 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-05 13:14:44 +01:00
										 |  |  | #define get_guest(vcpu, x, gptr)				\
 | 
					
						
							|  |  |  | ({								\ | 
					
						
							| 
									
										
										
										
											2013-03-05 13:14:45 +01:00
										 |  |  | 	__typeof__(gptr) __uptr = __gptr_to_uptr(vcpu, gptr, 1);\ | 
					
						
							| 
									
										
										
										
											2013-03-05 13:14:44 +01:00
										 |  |  | 	int __mask = sizeof(__typeof__(*(gptr))) - 1;		\ | 
					
						
							| 
									
										
										
										
											2013-07-15 11:21:32 +09:30
										 |  |  | 	int __ret;						\ | 
					
						
							| 
									
										
										
										
											2013-03-05 13:14:44 +01:00
										 |  |  | 								\ | 
					
						
							| 
									
										
										
										
											2013-07-15 11:21:32 +09:30
										 |  |  | 	if (IS_ERR((void __force *)__uptr)) {			\ | 
					
						
							|  |  |  | 		__ret = PTR_ERR((void __force *)__uptr);	\ | 
					
						
							|  |  |  | 	} else {						\ | 
					
						
							| 
									
										
										
										
											2013-03-05 13:14:44 +01:00
										 |  |  | 		BUG_ON((unsigned long)__uptr & __mask);		\ | 
					
						
							|  |  |  | 		__ret = get_user(x, __uptr);			\ | 
					
						
							|  |  |  | 	}							\ | 
					
						
							|  |  |  | 	__ret;							\ | 
					
						
							|  |  |  | }) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define put_guest(vcpu, x, gptr)				\
 | 
					
						
							|  |  |  | ({								\ | 
					
						
							| 
									
										
										
										
											2013-03-05 13:14:45 +01:00
										 |  |  | 	__typeof__(gptr) __uptr = __gptr_to_uptr(vcpu, gptr, 1);\ | 
					
						
							| 
									
										
										
										
											2013-03-05 13:14:44 +01:00
										 |  |  | 	int __mask = sizeof(__typeof__(*(gptr))) - 1;		\ | 
					
						
							| 
									
										
										
										
											2013-07-15 11:21:32 +09:30
										 |  |  | 	int __ret;						\ | 
					
						
							| 
									
										
										
										
											2013-03-05 13:14:44 +01:00
										 |  |  | 								\ | 
					
						
							| 
									
										
										
										
											2013-07-15 11:21:32 +09:30
										 |  |  | 	if (IS_ERR((void __force *)__uptr)) {			\ | 
					
						
							|  |  |  | 		__ret = PTR_ERR((void __force *)__uptr);	\ | 
					
						
							|  |  |  | 	} else {						\ | 
					
						
							| 
									
										
										
										
											2013-03-05 13:14:44 +01:00
										 |  |  | 		BUG_ON((unsigned long)__uptr & __mask);		\ | 
					
						
							|  |  |  | 		__ret = put_user(x, __uptr);			\ | 
					
						
							|  |  |  | 	}							\ | 
					
						
							|  |  |  | 	__ret;							\ | 
					
						
							|  |  |  | }) | 
					
						
							| 
									
										
										
										
											2008-03-25 18:47:20 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-05 13:14:45 +01:00
										 |  |  | static inline int __copy_guest(struct kvm_vcpu *vcpu, unsigned long to, | 
					
						
							|  |  |  | 			       unsigned long from, unsigned long len, | 
					
						
							|  |  |  | 			       int to_guest, int prefixing) | 
					
						
							| 
									
										
										
										
											2008-03-25 18:47:20 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2013-03-05 13:14:45 +01:00
										 |  |  | 	unsigned long _len, rc; | 
					
						
							| 
									
										
										
										
											2013-03-05 13:14:47 +01:00
										 |  |  | 	void __user *uptr; | 
					
						
							| 
									
										
										
										
											2013-03-05 13:14:45 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	while (len) { | 
					
						
							| 
									
										
										
										
											2013-03-05 13:14:47 +01:00
										 |  |  | 		uptr = to_guest ? (void __user *)to : (void __user *)from; | 
					
						
							| 
									
										
										
										
											2013-03-05 13:14:45 +01:00
										 |  |  | 		uptr = __gptr_to_uptr(vcpu, uptr, prefixing); | 
					
						
							| 
									
										
										
										
											2013-03-05 13:14:47 +01:00
										 |  |  | 		if (IS_ERR((void __force *)uptr)) | 
					
						
							| 
									
										
										
										
											2013-03-05 13:14:45 +01:00
										 |  |  | 			return -EFAULT; | 
					
						
							|  |  |  | 		_len = PAGE_SIZE - ((unsigned long)uptr & (PAGE_SIZE - 1)); | 
					
						
							|  |  |  | 		_len = min(_len, len); | 
					
						
							|  |  |  | 		if (to_guest) | 
					
						
							| 
									
										
										
										
											2013-03-05 13:14:47 +01:00
										 |  |  | 			rc = copy_to_user((void __user *) uptr, (void *)from, _len); | 
					
						
							| 
									
										
										
										
											2013-03-05 13:14:45 +01:00
										 |  |  | 		else | 
					
						
							| 
									
										
										
										
											2013-03-05 13:14:47 +01:00
										 |  |  | 			rc = copy_from_user((void *)to, (void __user *)uptr, _len); | 
					
						
							| 
									
										
										
										
											2013-03-05 13:14:45 +01:00
										 |  |  | 		if (rc) | 
					
						
							|  |  |  | 			return -EFAULT; | 
					
						
							|  |  |  | 		len -= _len; | 
					
						
							|  |  |  | 		from += _len; | 
					
						
							|  |  |  | 		to += _len; | 
					
						
							| 
									
										
										
										
											2008-03-25 18:47:20 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-05 13:14:45 +01:00
										 |  |  | #define copy_to_guest(vcpu, to, from, size) \
 | 
					
						
							|  |  |  | 	__copy_guest(vcpu, to, (unsigned long)from, size, 1, 1) | 
					
						
							|  |  |  | #define copy_from_guest(vcpu, to, from, size) \
 | 
					
						
							|  |  |  | 	__copy_guest(vcpu, (unsigned long)to, from, size, 0, 1) | 
					
						
							|  |  |  | #define copy_to_guest_absolute(vcpu, to, from, size) \
 | 
					
						
							|  |  |  | 	__copy_guest(vcpu, to, (unsigned long)from, size, 1, 0) | 
					
						
							|  |  |  | #define copy_from_guest_absolute(vcpu, to, from, size) \
 | 
					
						
							|  |  |  | 	__copy_guest(vcpu, (unsigned long)to, from, size, 0, 0) | 
					
						
							| 
									
										
										
										
											2011-07-24 10:48:22 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-05 13:14:45 +01:00
										 |  |  | #endif /* __KVM_S390_GACCESS_H */
 |