| /* |
| * Taken from perf which in turn take it from GIT |
| */ |
| |
| #include "kvm/util.h" |
| |
| #include <kvm/kvm.h> |
| #include <linux/magic.h> /* For HUGETLBFS_MAGIC */ |
| #include <sys/mman.h> |
| #include <sys/stat.h> |
| #include <sys/statfs.h> |
| |
| 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); |
| } |
| |
| void die(const char *err, ...) |
| { |
| va_list params; |
| |
| va_start(params, err); |
| die_builtin(err, params); |
| va_end(params); |
| } |
| |
| int pr_err(const char *err, ...) |
| { |
| va_list params; |
| |
| va_start(params, err); |
| error_builtin(err, params); |
| va_end(params); |
| return -1; |
| } |
| |
| void pr_warning(const char *warn, ...) |
| { |
| va_list params; |
| |
| va_start(params, warn); |
| warn_builtin(warn, params); |
| va_end(params); |
| } |
| |
| void pr_info(const char *info, ...) |
| { |
| va_list params; |
| |
| va_start(params, info); |
| info_builtin(info, 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); |
| } |
| } |