1 /******************************************************************************
2  * compat.h
3  */
4 
5 #ifndef __XEN_COMPAT_H__
6 #define __XEN_COMPAT_H__
7 
8 #ifdef CONFIG_COMPAT
9 
10 #include <xen/types.h>
11 #include <asm/compat.h>
12 #include <compat/xlat.h>
13 
14 #define __DEFINE_COMPAT_HANDLE(name, type) \
15     typedef struct { \
16         compat_ptr_t c; \
17         type *_[0] __packed; \
18     } __compat_handle_ ## name; \
19     typedef struct { \
20         compat_ptr_t c; \
21         const type *_[0] __packed; \
22     } __compat_handle_const_ ## name
23 
24 #define DEFINE_COMPAT_HANDLE(name) \
25     __DEFINE_COMPAT_HANDLE(name, name)
26 #define COMPAT_HANDLE(name)          __compat_handle_ ## name
27 
28 /* Is the compat handle a NULL reference? */
29 #define compat_handle_is_null(hnd)        ((hnd).c == 0)
30 
31 /* Offset the given compat handle into the array it refers to. */
32 #define compat_handle_add_offset(hnd, nr)                            \
33     ((hnd).c += (nr) * sizeof(**(hnd)._))
34 
35 /* Cast a compat handle to the specified type of handle. */
36 #define compat_handle_cast(chnd, type) ({                            \
37     type *_x = (__typeof__(**(chnd)._) *)(full_ptr_t)(chnd).c;       \
38     (COMPAT_HANDLE(type)) { (full_ptr_t)_x };                        \
39 })
40 
41 #define guest_from_compat_handle(ghnd, chnd)                         \
42     set_xen_guest_handle(ghnd,                                       \
43                          (__typeof__(**(chnd)._) *)(full_ptr_t)(chnd).c)
44 
45 /*
46  * Copy an array of objects to guest context via a compat handle,
47  * specifying an offset into the guest array.
48  */
49 #define copy_to_compat_offset(hnd, off, ptr, nr) ({                  \
50     const typeof(*(ptr)) *_s = (ptr);                                \
51     char (*_d)[sizeof(*_s)] = (void *)(full_ptr_t)(hnd).c;           \
52     ((void)((typeof(**(hnd)._) *)(full_ptr_t)(hnd).c == (ptr)));     \
53     raw_copy_to_guest(_d + (off), _s, sizeof(*_s) * (nr));           \
54 })
55 
56 /*
57  * Copy an array of objects from guest context via a compat handle,
58  * specifying an offset into the guest array.
59  */
60 #define copy_from_compat_offset(ptr, hnd, off, nr) ({                \
61     const typeof(*(ptr)) *_s = (typeof(**(hnd)._) *)(full_ptr_t)(hnd).c; \
62     typeof(*(ptr)) *_d = (ptr);                                      \
63     raw_copy_from_guest(_d, _s + (off), sizeof(*_d) * (nr));         \
64 })
65 
66 #define copy_to_compat(hnd, ptr, nr)                                 \
67     copy_to_compat_offset(hnd, 0, ptr, nr)
68 
69 #define copy_from_compat(ptr, hnd, nr)                               \
70     copy_from_compat_offset(ptr, hnd, 0, nr)
71 
72 /* Copy sub-field of a structure to guest context via a compat handle. */
73 #define copy_field_to_compat(hnd, ptr, field) ({                     \
74     const typeof(&(ptr)->field) _s = &(ptr)->field;                  \
75     void *_d = &((typeof(**(hnd)._) *)(full_ptr_t)(hnd).c)->field;   \
76     ((void)(&((typeof(**(hnd)._) *)(full_ptr_t)(hnd).c)->field ==    \
77             &(ptr)->field));                                         \
78     raw_copy_to_guest(_d, _s, sizeof(*_s));                          \
79 })
80 
81 /* Copy sub-field of a structure from guest context via a compat handle. */
82 #define copy_field_from_compat(ptr, hnd, field) ({                   \
83     const typeof(&(ptr)->field) _s =                                 \
84         &((typeof(**(hnd)._) *)(full_ptr_t)(hnd).c)->field;          \
85     typeof(&(ptr)->field) _d = &(ptr)->field;                        \
86     raw_copy_from_guest(_d, _s, sizeof(*_d));                        \
87 })
88 
89 /*
90  * Pre-validate a guest handle.
91  * Allows use of faster __copy_* functions.
92  */
93 #define compat_handle_okay(hnd, nr)                                  \
94     (paging_mode_external(current->domain) ||                        \
95     compat_array_access_ok((void *)(full_ptr_t)(hnd).c, (nr),        \
96                            sizeof(**(hnd)._)))
97 
98 #define __copy_to_compat_offset(hnd, off, ptr, nr) ({                \
99     const typeof(*(ptr)) *_s = (ptr);                                \
100     char (*_d)[sizeof(*_s)] = (void *)(full_ptr_t)(hnd).c;           \
101     ((void)((typeof(**(hnd)._) *)(full_ptr_t)(hnd).c == (ptr)));     \
102     __raw_copy_to_guest(_d + (off), _s, sizeof(*_s) * (nr));         \
103 })
104 
105 #define __copy_from_compat_offset(ptr, hnd, off, nr) ({              \
106     const typeof(*(ptr)) *_s = (typeof(**(hnd)._) *)(full_ptr_t)(hnd).c; \
107     typeof(*(ptr)) *_d = (ptr);                                      \
108     __raw_copy_from_guest(_d, _s + (off), sizeof(*_d) * (nr));       \
109 })
110 
111 #define __copy_to_compat(hnd, ptr, nr)                               \
112     __copy_to_compat_offset(hnd, 0, ptr, nr)
113 
114 #define __copy_from_compat(ptr, hnd, nr)                             \
115     __copy_from_compat_offset(ptr, hnd, 0, nr)
116 
117 #define __copy_field_to_compat(hnd, ptr, field) ({                   \
118     const typeof(&(ptr)->field) _s = &(ptr)->field;                  \
119     void *_d = &((typeof(**(hnd)._) *)(full_ptr_t)(hnd).c)->field;   \
120     ((void)(&((typeof(**(hnd)._) *)(full_ptr_t)(hnd).c)->field ==    \
121             &(ptr)->field));                                         \
122     __raw_copy_to_guest(_d, _s, sizeof(*_s));                        \
123 })
124 
125 #define __copy_field_from_compat(ptr, hnd, field) ({                 \
126     const typeof(&(ptr)->field) _s =                                 \
127         &((typeof(**(hnd)._) *)(full_ptr_t)(hnd).c)->field;          \
128     typeof(&(ptr)->field) _d = &(ptr)->field;                        \
129     __raw_copy_from_guest(_d, _s, sizeof(*_d));                      \
130 })
131 
132 
133 #define CHECK_NAME(name, tag) __check ## tag ## name
134 #define CHECK_NAME_(k, n, tag) __check ## tag ## k ## _ ## n
135 
136 #define CHECK_TYPE(name) \
137 static inline int __maybe_unused \
138 CHECK_NAME(name, T)(xen_ ## name ## _t *x, \
139                     compat_ ## name ## _t *c) \
140 { \
141     return x == c; \
142 }
143 #define CHECK_TYPE_(k, n) \
144 static inline int __maybe_unused \
145 CHECK_NAME_(k, n, T)(k xen_ ## n *x, \
146                      k compat_ ## n *c) \
147 { \
148     return x == c; \
149 }
150 
151 #define CHECK_SIZE(name) \
152     typedef int CHECK_NAME(name, S)[1 - (sizeof(xen_ ## name ## _t) != \
153                                          sizeof(compat_ ## name ## _t)) * 2]
154 #define CHECK_SIZE_(k, n) \
155     typedef int CHECK_NAME_(k, n, S)[1 - (sizeof(k xen_ ## n) != \
156                                           sizeof(k compat_ ## n)) * 2]
157 
158 #define CHECK_FIELD_COMMON(name, t, f) \
159 static inline int __maybe_unused name(xen_ ## t ## _t *x, compat_ ## t ## _t *c) \
160 { \
161     BUILD_BUG_ON(offsetof(xen_ ## t ## _t, f) != \
162                  offsetof(compat_ ## t ## _t, f)); \
163     return &x->f == &c->f; \
164 }
165 #define CHECK_FIELD_COMMON_(k, name, n, f) \
166 static inline int __maybe_unused name(k xen_ ## n *x, k compat_ ## n *c) \
167 { \
168     BUILD_BUG_ON(offsetof(k xen_ ## n, f) != \
169                  offsetof(k compat_ ## n, f)); \
170     return &x->f == &c->f; \
171 }
172 
173 #define CHECK_FIELD(t, f) \
174     CHECK_FIELD_COMMON(CHECK_NAME(t ## __ ## f, F), t, f)
175 #define CHECK_FIELD_(k, n, f) \
176     CHECK_FIELD_COMMON_(k, CHECK_NAME_(k, n ## __ ## f, F), n, f)
177 
178 #define CHECK_SUBFIELD_1(t, f1, f2) \
179     CHECK_FIELD_COMMON(CHECK_NAME(t ## __ ## f1 ## __ ## f2, F1), t, f1.f2)
180 #define CHECK_SUBFIELD_1_(k, n, f1, f2) \
181     CHECK_FIELD_COMMON_(k, CHECK_NAME_(k, n ## __ ## f1 ## __ ## f2, F1), \
182                         n, f1.f2)
183 
184 #define CHECK_SUBFIELD_2(t, f1, f2, f3) \
185     CHECK_FIELD_COMMON(CHECK_NAME(t ## __ ## f1 ## __ ## f2 ## __ ## f3, F2), \
186                        t, f1.f2.f3)
187 #define CHECK_SUBFIELD_2_(k, n, f1, f2, f3) \
188     CHECK_FIELD_COMMON_(k, CHECK_NAME_(k, n ## __ ## f1 ## __ ## f2 ## __ ## \
189                                        f3, F2), n, f1.f2.f3)
190 
191 /*
192  * Translate a native continuation into a compat guest continuation.
193  *
194  * id: If non-NULL then points to an integer N between 0-5. Will be updated
195  * with the value of the N'th argument to the hypercall. The N'th argument must
196  * not be subject to translation (i.e. cannot be referenced by @mask below).
197  * This option is useful for extracting the "op" argument or similar from the
198  * hypercall to enable further xlat processing.
199  *
200  * nr: Total number of arguments the hypercall has.
201  *
202  * mask: Specifies which of the hypercall arguments require compat translation.
203  * bit 0 indicates that the 0'th argument requires translation, bit 1 indicates
204  * that the first argument requires translation and so on. Native and compat
205  * values for each translated argument are provided as @varargs (see below).
206  *
207  * varargs: For each bit which is set in @mask the varargs contain a native
208  * value (unsigned long) and a compat value (unsigned int). If the native value
209  * and compat value differ and the N'th argument is equal to the native value
210  * then that argument is replaced by the compat value. If the native and compat
211  * values are equal then no translation takes place. If the N'th argument does
212  * not equal the native value then no translation takes place.
213  *
214  * Any untranslated argument (whether due to not being requested in @mask,
215  * native and compat values being equal or N'th argument not equalling native
216  * value) must be equal in both native and compat representations (i.e. the
217  * native version cannot have any bits > 32 set)
218  *
219  * Return: Number of arguments which were actually translated.
220  */
221 int hypercall_xlat_continuation(unsigned int *id, unsigned int nr,
222                                 unsigned int mask, ...);
223 
224 /* In-place translation functons: */
225 struct start_info;
226 void xlat_start_info(struct start_info *, enum XLAT_start_info_console);
227 struct vcpu_runstate_info;
228 void xlat_vcpu_runstate_info(struct vcpu_runstate_info *);
229 
230 struct domain;
231 int switch_compat(struct domain *);
232 
233 #else
234 
235 #define compat_handle_is_null(hnd) 0
236 
237 #endif
238 
239 #endif /* __XEN_COMPAT_H__ */
240