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