#ifndef XC_PRIVATE_H #define XC_PRIVATE_H #include #include #include #include #include #include #include #include #include #include #include #include "xenctrl.h" #include /* valgrind cannot see when a hypercall has filled in some values. For this reason, we must zero the privcmd_hypercall_t or domctl/sysctl instance before a call, if using valgrind. */ #ifdef VALGRIND #define DECLARE_HYPERCALL privcmd_hypercall_t hypercall = { 0 } #define DECLARE_DOMCTL struct xen_domctl domctl = { 0 } #define DECLARE_SYSCTL struct xen_sysctl sysctl = { 0 } #define DECLARE_PHYSDEV_OP struct physdev_op physdev_op = { 0 } #else #define DECLARE_HYPERCALL privcmd_hypercall_t hypercall #define DECLARE_DOMCTL struct xen_domctl domctl #define DECLARE_SYSCTL struct xen_sysctl sysctl #define DECLARE_PHYSDEV_OP struct physdev_op physdev_op #endif #undef PAGE_SHIFT #undef PAGE_SIZE #undef PAGE_MASK #define PAGE_SHIFT XC_PAGE_SHIFT #define PAGE_SIZE (1UL << PAGE_SHIFT) #define PAGE_MASK (~(PAGE_SIZE-1)) /* Force a compilation error if condition is true */ #define XC_BUILD_BUG_ON(p) ((void)sizeof(struct { int:-!!(p); })) /* ** Define max dirty page cache to permit during save/restore -- need to balance ** keeping cache usage down with CPU impact of invalidating too often. ** (Currently 16MB) */ #define MAX_PAGECACHE_USAGE (4*1024) struct xc_interface { int fd; xentoollog_logger *error_handler, *error_handler_tofree; xentoollog_logger *dombuild_logger, *dombuild_logger_tofree; struct xc_error last_error; /* for xc_get_last_error */ FILE *dombuild_logger_file; const char *currently_progress_reporting; }; char *safe_strerror(int errcode); void xc_report_error(xc_interface *xch, int code, const char *fmt, ...); void xc_reportv(xc_interface *xch, xentoollog_logger *lg, xentoollog_level, int code, const char *fmt, va_list args) __attribute__((format(printf,5,0))); void xc_report(xc_interface *xch, xentoollog_logger *lg, xentoollog_level, int code, const char *fmt, ...) __attribute__((format(printf,5,6))); void xc_report_progress_start(xc_interface *xch, const char *doing, unsigned long total); void xc_report_progress_step(xc_interface *xch, unsigned long done, unsigned long total); /* anamorphic macros: struct xc_interface *xch must be in scope */ #define IPRINTF(_f, _a...) xc_report(xch, xch->error_handler, XTL_INFO,0, _f , ## _a) #define DPRINTF(_f, _a...) xc_report(xch, xch->error_handler, XTL_DETAIL,0, _f , ## _a) #define DBGPRINTF(_f, _a...) xc_report(xch, xch->error_handler, XTL_DEBUG,0, _f , ## _a) #define ERROR(_m, _a...) xc_report_error(xch,XC_INTERNAL_ERROR,_m , ## _a ) #define PERROR(_m, _a...) xc_report_error(xch,XC_INTERNAL_ERROR,_m \ " (%d = %s)", ## _a , errno, safe_strerror(errno)) void *xc_memalign(size_t alignment, size_t size); int lock_pages(void *addr, size_t len); void unlock_pages(void *addr, size_t len); int hcall_buf_prep(void **addr, size_t len); void hcall_buf_release(void **addr, size_t len); static inline void safe_munlock(const void *addr, size_t len) { int saved_errno = errno; (void)munlock(addr, len); errno = saved_errno; } int do_xen_hypercall(xc_interface *xch, privcmd_hypercall_t *hypercall); static inline int do_xen_version(xc_interface *xch, int cmd, void *dest) { DECLARE_HYPERCALL; hypercall.op = __HYPERVISOR_xen_version; hypercall.arg[0] = (unsigned long) cmd; hypercall.arg[1] = (unsigned long) dest; return do_xen_hypercall(xch, &hypercall); } static inline int do_physdev_op(xc_interface *xch, int cmd, void *op, size_t len) { int ret = -1; DECLARE_HYPERCALL; if ( hcall_buf_prep(&op, len) != 0 ) { PERROR("Could not lock memory for Xen hypercall"); goto out1; } hypercall.op = __HYPERVISOR_physdev_op; hypercall.arg[0] = (unsigned long) cmd; hypercall.arg[1] = (unsigned long) op; if ( (ret = do_xen_hypercall(xch, &hypercall)) < 0 ) { if ( errno == EACCES ) DPRINTF("physdev operation failed -- need to" " rebuild the user-space tool set?\n"); } hcall_buf_release(&op, len); out1: return ret; } static inline int do_domctl(xc_interface *xch, struct xen_domctl *domctl) { int ret = -1; DECLARE_HYPERCALL; if ( hcall_buf_prep((void **)&domctl, sizeof(*domctl)) != 0 ) { PERROR("Could not lock memory for Xen hypercall"); goto out1; } domctl->interface_version = XEN_DOMCTL_INTERFACE_VERSION; hypercall.op = __HYPERVISOR_domctl; hypercall.arg[0] = (unsigned long)domctl; if ( (ret = do_xen_hypercall(xch, &hypercall)) < 0 ) { if ( errno == EACCES ) DPRINTF("domctl operation failed -- need to" " rebuild the user-space tool set?\n"); } hcall_buf_release((void **)&domctl, sizeof(*domctl)); out1: return ret; } static inline int do_sysctl(xc_interface *xch, struct xen_sysctl *sysctl) { int ret = -1; DECLARE_HYPERCALL; if ( hcall_buf_prep((void **)&sysctl, sizeof(*sysctl)) != 0 ) { PERROR("Could not lock memory for Xen hypercall"); goto out1; } sysctl->interface_version = XEN_SYSCTL_INTERFACE_VERSION; hypercall.op = __HYPERVISOR_sysctl; hypercall.arg[0] = (unsigned long)sysctl; if ( (ret = do_xen_hypercall(xch, &hypercall)) < 0 ) { if ( errno == EACCES ) DPRINTF("sysctl operation failed -- need to" " rebuild the user-space tool set?\n"); } hcall_buf_release((void **)&sysctl, sizeof(*sysctl)); out1: return ret; } int xc_interface_open_core(xc_interface *xch); /* returns fd, logs errors */ int xc_interface_close_core(xc_interface *xch, int fd); /* no logging */ void *xc_map_foreign_ranges(xc_interface *xch, uint32_t dom, size_t size, int prot, size_t chunksize, privcmd_mmap_entry_t entries[], int nentries); int xc_get_pfn_type_batch(xc_interface *xch, uint32_t dom, unsigned int num, xen_pfn_t *); void bitmap_64_to_byte(uint8_t *bp, const uint64_t *lp, int nbits); void bitmap_byte_to_64(uint64_t *lp, const uint8_t *bp, int nbits); /* Optionally flush file to disk and discard page cache */ void discard_file_cache(xc_interface *xch, int fd, int flush); #define MAX_MMU_UPDATES 1024 struct xc_mmu { mmu_update_t updates[MAX_MMU_UPDATES]; int idx; domid_t subject; }; /* Structure returned by xc_alloc_mmu_updates must be free()'ed by caller. */ struct xc_mmu *xc_alloc_mmu_updates(xc_interface *xch, domid_t dom); int xc_add_mmu_update(xc_interface *xch, struct xc_mmu *mmu, unsigned long long ptr, unsigned long long val); int xc_flush_mmu_updates(xc_interface *xch, struct xc_mmu *mmu); /* Return 0 on success; -1 on error setting errno. */ int read_exact(int fd, void *data, size_t size); /* EOF => -1, errno=0 */ int write_exact(int fd, const void *data, size_t size); int xc_ffs8(uint8_t x); int xc_ffs16(uint16_t x); int xc_ffs32(uint32_t x); int xc_ffs64(uint64_t x); #define DOMPRINTF(fmt, args...) xc_dom_printf(dom->xch, fmt, ## args) #define DOMPRINTF_CALLED(xch) xc_dom_printf((xch), "%s: called", __FUNCTION__) #endif /* __XC_PRIVATE_H__ */