/* * Taken from perf which in turn take it from GIT */ #include "kvm/util.h" #include #include /* For HUGETLBFS_MAGIC */ #include #include #include static void report(const char *prefix, const char *err, va_list params) { char msg[1024]; vsnprintf(msg, sizeof(msg), err, params); fprintf(stderr, " %s%s\n", prefix, msg); } static NORETURN void die_builtin(const char *err, va_list params) { report(" Fatal: ", err, params); exit(128); } static void error_builtin(const char *err, va_list params) { report(" Error: ", err, params); } static void warn_builtin(const char *warn, va_list params) { report(" Warning: ", warn, params); } static void info_builtin(const char *info, va_list params) { report(" Info: ", info, params); } static void debug_builtin(const char *debug, va_list params) { report(" Debug: ", debug, params); } void die(const char *err, ...) { va_list params; va_start(params, err); die_builtin(err, params); va_end(params); } void pr_err(const char *err, ...) { va_list params; if (loglevel < LOGLEVEL_ERROR) return; va_start(params, err); error_builtin(err, params); va_end(params); } void pr_warning(const char *warn, ...) { va_list params; if (loglevel < LOGLEVEL_WARNING) return; va_start(params, warn); warn_builtin(warn, params); va_end(params); } void pr_info(const char *info, ...) { va_list params; if (loglevel < LOGLEVEL_INFO) return; va_start(params, info); info_builtin(info, params); va_end(params); } /* Do not call directly; call pr_debug() instead. */ void __pr_debug(const char *debug, ...) { va_list params; va_start(params, debug); debug_builtin(debug, params); va_end(params); } void die_perror(const char *s) { perror(s); exit(1); } void *mmap_hugetlbfs(struct kvm *kvm, const char *htlbfs_path, u64 size) { char mpath[PATH_MAX]; int fd; struct statfs sfs; void *addr; unsigned long blk_size; if (statfs(htlbfs_path, &sfs) < 0) die("Can't stat %s\n", htlbfs_path); if ((unsigned int)sfs.f_type != HUGETLBFS_MAGIC) die("%s is not hugetlbfs!\n", htlbfs_path); blk_size = (unsigned long)sfs.f_bsize; if (sfs.f_bsize == 0 || blk_size > size) { die("Can't use hugetlbfs pagesize %ld for mem size %lld\n", blk_size, (unsigned long long)size); } kvm->ram_pagesize = blk_size; snprintf(mpath, PATH_MAX, "%s/kvmtoolXXXXXX", htlbfs_path); fd = mkstemp(mpath); if (fd < 0) die("Can't open %s for hugetlbfs map\n", mpath); unlink(mpath); if (ftruncate(fd, size) < 0) die("Can't ftruncate for mem mapping size %lld\n", (unsigned long long)size); addr = mmap(NULL, size, PROT_RW, MAP_PRIVATE, fd, 0); close(fd); return addr; } /* This function wraps the decision between hugetlbfs map (if requested) or normal mmap */ void *mmap_anon_or_hugetlbfs(struct kvm *kvm, const char *hugetlbfs_path, u64 size) { if (hugetlbfs_path) /* * We don't /need/ to map guest RAM from hugetlbfs, but we do so * if the user specifies a hugetlbfs path. */ return mmap_hugetlbfs(kvm, hugetlbfs_path, size); else { kvm->ram_pagesize = getpagesize(); return mmap(NULL, size, PROT_RW, MAP_ANON_NORESERVE, -1, 0); } }