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