1 /*
2 * This library is free software; you can redistribute it and/or
3 * modify it under the terms of the GNU Lesser General Public
4 * License as published by the Free Software Foundation;
5 * version 2.1 of the License.
6 *
7 * This library is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10 * Lesser General Public License for more details.
11 *
12 * You should have received a copy of the GNU Lesser General Public
13 * License along with this library; If not, see <http://www.gnu.org/licenses/>.
14 */
15
16 #ifndef XC_PRIVATE_H
17 #define XC_PRIVATE_H
18
19 #include <unistd.h>
20 #include <stdarg.h>
21 #include <stdio.h>
22 #include <errno.h>
23 #include <fcntl.h>
24 #include <string.h>
25 #include <sys/mman.h>
26 #include <sys/types.h>
27 #include <sys/stat.h>
28 #include <stdlib.h>
29 #include <sys/ioctl.h>
30
31 #include "_paths.h"
32
33 #define XC_WANT_COMPAT_MAP_FOREIGN_API
34 #define XC_INTERNAL_COMPAT_MAP_FOREIGN_API
35 #include "xenctrl.h"
36
37 #include <xencall.h>
38 #include <xenforeignmemory.h>
39 #include <xendevicemodel.h>
40
41 #include <xen/sys/privcmd.h>
42
43 #if defined(HAVE_VALGRIND_MEMCHECK_H) && !defined(NDEBUG) && !defined(__MINIOS__)
44 /* Compile in Valgrind client requests? */
45 #include <valgrind/memcheck.h>
46 #else
47 #define VALGRIND_MAKE_MEM_UNDEFINED(addr, len) /* addr, len */
48 #endif
49
50 #if defined(__MINIOS__)
51 /*
52 * MiniOS's libc doesn't know about sys/uio.h or writev().
53 * Declare enough of sys/uio.h to compile.
54 */
55 struct iovec {
56 void *iov_base;
57 size_t iov_len;
58 };
59 #else
60 #include <sys/uio.h>
61 #endif
62
63 #define DECLARE_DOMCTL struct xen_domctl domctl
64 #define DECLARE_SYSCTL struct xen_sysctl sysctl
65 #define DECLARE_PHYSDEV_OP struct physdev_op physdev_op
66 #define DECLARE_FLASK_OP struct xen_flask_op op
67 #define DECLARE_PLATFORM_OP struct xen_platform_op platform_op
68
69 #undef PAGE_SHIFT
70 #undef PAGE_SIZE
71 #undef PAGE_MASK
72 #define PAGE_SHIFT XC_PAGE_SHIFT
73 #define PAGE_SIZE XC_PAGE_SIZE
74 #define PAGE_MASK XC_PAGE_MASK
75
76 #ifndef ARRAY_SIZE /* MiniOS leaks ARRAY_SIZE into our namespace as part of a
77 * stubdom build. It shouldn't... */
78 #define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
79 #endif
80
81 /*
82 ** Define max dirty page cache to permit during save/restore -- need to balance
83 ** keeping cache usage down with CPU impact of invalidating too often.
84 ** (Currently 16MB)
85 */
86 #define MAX_PAGECACHE_USAGE (4*1024)
87
88 struct xc_interface_core {
89 int flags;
90 xentoollog_logger *error_handler, *error_handler_tofree;
91 xentoollog_logger *dombuild_logger, *dombuild_logger_tofree;
92 struct xc_error last_error; /* for xc_get_last_error */
93 FILE *dombuild_logger_file;
94 const char *currently_progress_reporting;
95
96 /* Hypercall interface */
97 xencall_handle *xcall;
98
99 /* Foreign mappings */
100 xenforeignmemory_handle *fmem;
101
102 /* Device model */
103 xendevicemodel_handle *dmod;
104 };
105
106 int osdep_privcmd_open(xc_interface *xch);
107 int osdep_privcmd_close(xc_interface *xch);
108
109 void *osdep_alloc_hypercall_buffer(xc_interface *xch, int npages);
110 void osdep_free_hypercall_buffer(xc_interface *xch, void *ptr, int npages);
111
112 void xc_report_error(xc_interface *xch, int code, const char *fmt, ...)
113 __attribute__((format(printf,3,4)));
114 void xc_reportv(xc_interface *xch, xentoollog_logger *lg, xentoollog_level,
115 int code, const char *fmt, va_list args)
116 __attribute__((format(printf,5,0)));
117 void xc_report(xc_interface *xch, xentoollog_logger *lg, xentoollog_level,
118 int code, const char *fmt, ...)
119 __attribute__((format(printf,5,6)));
120
121 const char *xc_set_progress_prefix(xc_interface *xch, const char *doing);
122 void xc_report_progress_single(xc_interface *xch, const char *doing);
123 void xc_report_progress_step(xc_interface *xch,
124 unsigned long done, unsigned long total);
125
126 /* anamorphic macros: struct xc_interface *xch must be in scope */
127
128 #define IPRINTF(_f, _a...) do { int IPRINTF_errno = errno; \
129 xc_report(xch, xch->error_handler, XTL_INFO,0, _f , ## _a); \
130 errno = IPRINTF_errno; \
131 } while (0)
132 #define DPRINTF(_f, _a...) do { int DPRINTF_errno = errno; \
133 xc_report(xch, xch->error_handler, XTL_DETAIL,0, _f , ## _a); \
134 errno = DPRINTF_errno; \
135 } while (0)
136 #define DBGPRINTF(_f, _a...) do { int DBGPRINTF_errno = errno; \
137 xc_report(xch, xch->error_handler, XTL_DEBUG,0, _f , ## _a); \
138 errno = DBGPRINTF_errno; \
139 } while (0)
140
141 #define ERROR(_m, _a...) do { int ERROR_errno = errno; \
142 xc_report_error(xch,XC_INTERNAL_ERROR,_m , ## _a ); \
143 errno = ERROR_errno; \
144 } while (0)
145 #define PERROR(_m, _a...) do { int PERROR_errno = errno; \
146 xc_report_error(xch,XC_INTERNAL_ERROR,_m " (%d = %s)", \
147 ## _a , errno, xc_strerror(xch, errno)); \
148 errno = PERROR_errno; \
149 } while (0)
150
151 /*
152 * HYPERCALL ARGUMENT BUFFERS
153 *
154 * Augment the public hypercall buffer interface with the ability to
155 * bounce between user provided buffers and hypercall safe memory.
156 *
157 * Use xc_hypercall_bounce_pre/post instead of
158 * xc_hypercall_buffer_alloc/free(_pages). The specified user
159 * supplied buffer is automatically copied in/out of the hypercall
160 * safe memory.
161 */
162 enum {
163 XC_HYPERCALL_BUFFER_BOUNCE_NONE = 0,
164 XC_HYPERCALL_BUFFER_BOUNCE_IN = 1,
165 XC_HYPERCALL_BUFFER_BOUNCE_OUT = 2,
166 XC_HYPERCALL_BUFFER_BOUNCE_BOTH = 3
167 };
168
169 /*
170 * Declare a named bounce buffer.
171 *
172 * Normally you should use DECLARE_HYPERCALL_BOUNCE (see below).
173 *
174 * This declaration should only be used when the user pointer is
175 * non-trivial, e.g. when it is contained within an existing data
176 * structure.
177 */
178 #define DECLARE_NAMED_HYPERCALL_BOUNCE(_name, _ubuf, _sz, _dir) \
179 xc_hypercall_buffer_t XC__HYPERCALL_BUFFER_NAME(_name) = { \
180 .hbuf = NULL, \
181 .param_shadow = NULL, \
182 .sz = _sz, .dir = _dir, .ubuf = _ubuf, \
183 }
184
185 /*
186 * Declare a bounce buffer shadowing the named user data pointer.
187 */
188 #define DECLARE_HYPERCALL_BOUNCE(_ubuf, _sz, _dir) DECLARE_NAMED_HYPERCALL_BOUNCE(_ubuf, _ubuf, _sz, _dir)
189
190 /*
191 * Set the size of data to bounce. Useful when the size is not known
192 * when the bounce buffer is declared.
193 */
194 #define HYPERCALL_BOUNCE_SET_SIZE(_buf, _sz) do { (HYPERCALL_BUFFER(_buf))->sz = _sz; } while (0)
195
196 /*
197 * Change the direction.
198 *
199 * Can only be used if the bounce_pre/bounce_post commands have
200 * not been used.
201 */
202 #define HYPERCALL_BOUNCE_SET_DIR(_buf, _dir) do { if ((HYPERCALL_BUFFER(_buf))->hbuf) \
203 assert(1); \
204 (HYPERCALL_BUFFER(_buf))->dir = _dir; \
205 } while (0)
206
207 /*
208 * Initialise and free hypercall safe memory. Takes care of any required
209 * copying.
210 */
211 int xc__hypercall_bounce_pre(xc_interface *xch, xc_hypercall_buffer_t *bounce);
212 #define xc_hypercall_bounce_pre(_xch, _name) xc__hypercall_bounce_pre(_xch, HYPERCALL_BUFFER(_name))
213 void xc__hypercall_bounce_post(xc_interface *xch, xc_hypercall_buffer_t *bounce);
214 #define xc_hypercall_bounce_post(_xch, _name) xc__hypercall_bounce_post(_xch, HYPERCALL_BUFFER(_name))
215
216 /*
217 * Release hypercall buffer cache
218 */
219 void xc__hypercall_buffer_cache_release(xc_interface *xch);
220
221 /*
222 * Hypercall interfaces.
223 */
224
do_xen_version(xc_interface * xch,int cmd,xc_hypercall_buffer_t * dest)225 static inline int do_xen_version(xc_interface *xch, int cmd, xc_hypercall_buffer_t *dest)
226 {
227 DECLARE_HYPERCALL_BUFFER_ARGUMENT(dest);
228 return xencall2(xch->xcall, __HYPERVISOR_xen_version,
229 cmd, HYPERCALL_BUFFER_AS_ARG(dest));
230 }
231
do_physdev_op(xc_interface * xch,int cmd,void * op,size_t len)232 static inline int do_physdev_op(xc_interface *xch, int cmd, void *op, size_t len)
233 {
234 int ret = -1;
235 DECLARE_HYPERCALL_BOUNCE(op, len, XC_HYPERCALL_BUFFER_BOUNCE_BOTH);
236
237 if ( xc_hypercall_bounce_pre(xch, op) )
238 {
239 PERROR("Could not bounce memory for physdev hypercall");
240 goto out1;
241 }
242
243 ret = xencall2(xch->xcall, __HYPERVISOR_physdev_op,
244 cmd, HYPERCALL_BUFFER_AS_ARG(op));
245 if ( ret < 0 )
246 {
247 if ( errno == EACCES )
248 DPRINTF("physdev operation failed -- need to"
249 " rebuild the user-space tool set?\n");
250 }
251
252 xc_hypercall_bounce_post(xch, op);
253 out1:
254 return ret;
255 }
256
do_domctl(xc_interface * xch,struct xen_domctl * domctl)257 static inline int do_domctl(xc_interface *xch, struct xen_domctl *domctl)
258 {
259 int ret = -1;
260 DECLARE_HYPERCALL_BOUNCE(domctl, sizeof(*domctl), XC_HYPERCALL_BUFFER_BOUNCE_BOTH);
261
262 domctl->interface_version = XEN_DOMCTL_INTERFACE_VERSION;
263
264 if ( xc_hypercall_bounce_pre(xch, domctl) )
265 {
266 PERROR("Could not bounce buffer for domctl hypercall");
267 goto out1;
268 }
269
270 ret = xencall1(xch->xcall, __HYPERVISOR_domctl,
271 HYPERCALL_BUFFER_AS_ARG(domctl));
272 if ( ret < 0 )
273 {
274 if ( errno == EACCES )
275 DPRINTF("domctl operation failed -- need to"
276 " rebuild the user-space tool set?\n");
277 }
278
279 xc_hypercall_bounce_post(xch, domctl);
280 out1:
281 return ret;
282 }
283
do_sysctl(xc_interface * xch,struct xen_sysctl * sysctl)284 static inline int do_sysctl(xc_interface *xch, struct xen_sysctl *sysctl)
285 {
286 int ret = -1;
287 DECLARE_HYPERCALL_BOUNCE(sysctl, sizeof(*sysctl), XC_HYPERCALL_BUFFER_BOUNCE_BOTH);
288
289 sysctl->interface_version = XEN_SYSCTL_INTERFACE_VERSION;
290
291 if ( xc_hypercall_bounce_pre(xch, sysctl) )
292 {
293 PERROR("Could not bounce buffer for sysctl hypercall");
294 goto out1;
295 }
296
297 ret = xencall1(xch->xcall, __HYPERVISOR_sysctl,
298 HYPERCALL_BUFFER_AS_ARG(sysctl));
299 if ( ret < 0 )
300 {
301 if ( errno == EACCES )
302 DPRINTF("sysctl operation failed -- need to"
303 " rebuild the user-space tool set?\n");
304 }
305
306 xc_hypercall_bounce_post(xch, sysctl);
307 out1:
308 return ret;
309 }
310
do_platform_op(xc_interface * xch,struct xen_platform_op * platform_op)311 static inline int do_platform_op(xc_interface *xch,
312 struct xen_platform_op *platform_op)
313 {
314 int ret = -1;
315 DECLARE_HYPERCALL_BOUNCE(platform_op, sizeof(*platform_op),
316 XC_HYPERCALL_BUFFER_BOUNCE_BOTH);
317
318 platform_op->interface_version = XENPF_INTERFACE_VERSION;
319
320 if ( xc_hypercall_bounce_pre(xch, platform_op) )
321 {
322 PERROR("Could not bounce buffer for platform_op hypercall");
323 return -1;
324 }
325
326 ret = xencall1(xch->xcall, __HYPERVISOR_platform_op,
327 HYPERCALL_BUFFER_AS_ARG(platform_op));
328 if ( ret < 0 )
329 {
330 if ( errno == EACCES )
331 DPRINTF("platform operation failed -- need to"
332 " rebuild the user-space tool set?\n");
333 }
334
335 xc_hypercall_bounce_post(xch, platform_op);
336 return ret;
337 }
338
do_multicall_op(xc_interface * xch,xc_hypercall_buffer_t * call_list,uint32_t nr_calls)339 static inline int do_multicall_op(xc_interface *xch,
340 xc_hypercall_buffer_t *call_list,
341 uint32_t nr_calls)
342 {
343 int ret = -1;
344 DECLARE_HYPERCALL_BUFFER_ARGUMENT(call_list);
345
346 ret = xencall2(xch->xcall, __HYPERVISOR_multicall,
347 HYPERCALL_BUFFER_AS_ARG(call_list), nr_calls);
348 if ( ret < 0 )
349 {
350 if ( errno == EACCES )
351 DPRINTF("multicall operation failed -- need to"
352 " rebuild the user-space tool set?\n");
353 }
354
355 return ret;
356 }
357
358 long do_memory_op(xc_interface *xch, int cmd, void *arg, size_t len);
359
360 void *xc_map_foreign_ranges(xc_interface *xch, uint32_t dom,
361 size_t size, int prot, size_t chunksize,
362 privcmd_mmap_entry_t entries[], int nentries);
363
364 int xc_get_pfn_type_batch(xc_interface *xch, uint32_t dom,
365 unsigned int num, xen_pfn_t *);
366
367 void bitmap_64_to_byte(uint8_t *bp, const uint64_t *lp, int nbits);
368 void bitmap_byte_to_64(uint64_t *lp, const uint8_t *bp, int nbits);
369
370 /* Optionally flush file to disk and discard page cache */
371 void discard_file_cache(xc_interface *xch, int fd, int flush);
372
373 #define MAX_MMU_UPDATES 1024
374 struct xc_mmu {
375 mmu_update_t updates[MAX_MMU_UPDATES];
376 int idx;
377 unsigned int subject;
378 };
379 /* Structure returned by xc_alloc_mmu_updates must be free()'ed by caller. */
380 struct xc_mmu *xc_alloc_mmu_updates(xc_interface *xch, unsigned int subject);
381 int xc_add_mmu_update(xc_interface *xch, struct xc_mmu *mmu,
382 unsigned long long ptr, unsigned long long val);
383 int xc_flush_mmu_updates(xc_interface *xch, struct xc_mmu *mmu);
384
385 /* Return 0 on success; -1 on error setting errno. */
386 int read_exact(int fd, void *data, size_t size); /* EOF => -1, errno=0 */
387 int write_exact(int fd, const void *data, size_t size);
388 int writev_exact(int fd, const struct iovec *iov, int iovcnt);
389
390 int xc_ffs8(uint8_t x);
391 int xc_ffs16(uint16_t x);
392 int xc_ffs32(uint32_t x);
393 int xc_ffs64(uint64_t x);
394
395 #define min(X, Y) ({ \
396 const typeof (X) _x = (X); \
397 const typeof (Y) _y = (Y); \
398 (void) (&_x == &_y); \
399 (_x < _y) ? _x : _y; })
400 #define max(X, Y) ({ \
401 const typeof (X) _x = (X); \
402 const typeof (Y) _y = (Y); \
403 (void) (&_x == &_y); \
404 (_x > _y) ? _x : _y; })
405
406 #define min_t(type,x,y) \
407 ({ type __x = (x); type __y = (y); __x < __y ? __x: __y; })
408 #define max_t(type,x,y) \
409 ({ type __x = (x); type __y = (y); __x > __y ? __x: __y; })
410
411 #define DOMPRINTF(fmt, args...) xc_dom_printf(dom->xch, fmt, ## args)
412 #define DOMPRINTF_CALLED(xch) xc_dom_printf((xch), "%s: called", __FUNCTION__)
413
414 /**
415 * vm_event operations. Internal use only.
416 */
417 int xc_vm_event_control(xc_interface *xch, uint32_t domain_id, unsigned int op,
418 unsigned int mode, uint32_t *port);
419 /*
420 * Enables vm_event and returns the mapped ring page indicated by param.
421 * param can be HVM_PARAM_PAGING/ACCESS/SHARING_RING_PFN
422 */
423 void *xc_vm_event_enable(xc_interface *xch, uint32_t domain_id, int param,
424 uint32_t *port);
425
426 int do_dm_op(xc_interface *xch, uint32_t domid, unsigned int nr_bufs, ...);
427
428 #endif /* __XC_PRIVATE_H__ */
429
430 /*
431 * Local variables:
432 * mode: C
433 * c-file-style: "BSD"
434 * c-basic-offset: 4
435 * tab-width: 4
436 * indent-tabs-mode: nil
437 * End:
438 */
439