• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * 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 
__gptr_to_uptr(struct kvm_vcpu * vcpu,void __user * gptr,int prefixing)21 static inline void __user *__gptr_to_uptr(struct kvm_vcpu *vcpu,
22 					  void __user *gptr,
23 					  int prefixing)
24 {
25 	unsigned long prefix  = vcpu->arch.sie_block->prefix;
26 	unsigned long gaddr = (unsigned long) gptr;
27 	unsigned long uaddr;
28 
29 	if (prefixing) {
30 		if (gaddr < 2 * PAGE_SIZE)
31 			gaddr += prefix;
32 		else if ((gaddr >= prefix) && (gaddr < prefix + 2 * PAGE_SIZE))
33 			gaddr -= prefix;
34 	}
35 	uaddr = gmap_fault(gaddr, vcpu->arch.gmap);
36 	if (IS_ERR_VALUE(uaddr))
37 		uaddr = -EFAULT;
38 	return (void __user *)uaddr;
39 }
40 
41 #define get_guest(vcpu, x, gptr)				\
42 ({								\
43 	__typeof__(gptr) __uptr = __gptr_to_uptr(vcpu, gptr, 1);\
44 	int __mask = sizeof(__typeof__(*(gptr))) - 1;		\
45 	int __ret = PTR_RET((void __force *)__uptr);		\
46 								\
47 	if (!__ret) {						\
48 		BUG_ON((unsigned long)__uptr & __mask);		\
49 		__ret = get_user(x, __uptr);			\
50 	}							\
51 	__ret;							\
52 })
53 
54 #define put_guest(vcpu, x, gptr)				\
55 ({								\
56 	__typeof__(gptr) __uptr = __gptr_to_uptr(vcpu, gptr, 1);\
57 	int __mask = sizeof(__typeof__(*(gptr))) - 1;		\
58 	int __ret = PTR_RET((void __force *)__uptr);		\
59 								\
60 	if (!__ret) {						\
61 		BUG_ON((unsigned long)__uptr & __mask);		\
62 		__ret = put_user(x, __uptr);			\
63 	}							\
64 	__ret;							\
65 })
66 
__copy_guest(struct kvm_vcpu * vcpu,unsigned long to,unsigned long from,unsigned long len,int to_guest,int prefixing)67 static inline int __copy_guest(struct kvm_vcpu *vcpu, unsigned long to,
68 			       unsigned long from, unsigned long len,
69 			       int to_guest, int prefixing)
70 {
71 	unsigned long _len, rc;
72 	void __user *uptr;
73 
74 	while (len) {
75 		uptr = to_guest ? (void __user *)to : (void __user *)from;
76 		uptr = __gptr_to_uptr(vcpu, uptr, prefixing);
77 		if (IS_ERR((void __force *)uptr))
78 			return -EFAULT;
79 		_len = PAGE_SIZE - ((unsigned long)uptr & (PAGE_SIZE - 1));
80 		_len = min(_len, len);
81 		if (to_guest)
82 			rc = copy_to_user((void __user *) uptr, (void *)from, _len);
83 		else
84 			rc = copy_from_user((void *)to, (void __user *)uptr, _len);
85 		if (rc)
86 			return -EFAULT;
87 		len -= _len;
88 		from += _len;
89 		to += _len;
90 	}
91 	return 0;
92 }
93 
94 #define copy_to_guest(vcpu, to, from, size) \
95 	__copy_guest(vcpu, to, (unsigned long)from, size, 1, 1)
96 #define copy_from_guest(vcpu, to, from, size) \
97 	__copy_guest(vcpu, (unsigned long)to, from, size, 0, 1)
98 #define copy_to_guest_absolute(vcpu, to, from, size) \
99 	__copy_guest(vcpu, to, (unsigned long)from, size, 1, 0)
100 #define copy_from_guest_absolute(vcpu, to, from, size) \
101 	__copy_guest(vcpu, (unsigned long)to, from, size, 0, 0)
102 
103 #endif /* __KVM_S390_GACCESS_H */
104