mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 02:30:03 +01:00
* Make "read_exact" in libxc always set errno. * Rename "read_exact" macro in xc_domain_restore.c (which shadows real function) to RDEXACT and change all callers. * Make RDEXACT anamorphically use xch for error reporting rather than * stderr. * Call PERROR rather than ERROR when appropriate, so that log messages include errno. * Save errno in noncached_write so that its errno value is always * right. Signed-off-by: Ian Jackson <Ian.Jackson@eu.citrix.com>
242 lines
7.5 KiB
C
242 lines
7.5 KiB
C
|
|
#ifndef XC_PRIVATE_H
|
|
#define XC_PRIVATE_H
|
|
|
|
#include <unistd.h>
|
|
#include <stdarg.h>
|
|
#include <stdio.h>
|
|
#include <errno.h>
|
|
#include <fcntl.h>
|
|
#include <string.h>
|
|
#include <sys/mman.h>
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <stdlib.h>
|
|
#include <sys/ioctl.h>
|
|
|
|
#include "xenctrl.h"
|
|
|
|
#include <xen/sys/privcmd.h>
|
|
|
|
/* 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__ */
|