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