1 /*
2 * Taken from perf which in turn take it from GIT
3 */
4
5 #include "kvm/util.h"
6
7 #include <kvm/kvm.h>
8 #include <linux/magic.h> /* For HUGETLBFS_MAGIC */
9 #include <sys/mman.h>
10 #include <sys/stat.h>
11 #include <sys/statfs.h>
12
report(const char * prefix,const char * err,va_list params)13 static void report(const char *prefix, const char *err, va_list params)
14 {
15 char msg[1024];
16 vsnprintf(msg, sizeof(msg), err, params);
17 fprintf(stderr, " %s%s\n", prefix, msg);
18 }
19
die_builtin(const char * err,va_list params)20 static NORETURN void die_builtin(const char *err, va_list params)
21 {
22 report(" Fatal: ", err, params);
23 exit(128);
24 }
25
error_builtin(const char * err,va_list params)26 static void error_builtin(const char *err, va_list params)
27 {
28 report(" Error: ", err, params);
29 }
30
warn_builtin(const char * warn,va_list params)31 static void warn_builtin(const char *warn, va_list params)
32 {
33 report(" Warning: ", warn, params);
34 }
35
info_builtin(const char * info,va_list params)36 static void info_builtin(const char *info, va_list params)
37 {
38 report(" Info: ", info, params);
39 }
40
debug_builtin(const char * debug,va_list params)41 static void debug_builtin(const char *debug, va_list params)
42 {
43 report(" Debug: ", debug, params);
44 }
45
die(const char * err,...)46 void die(const char *err, ...)
47 {
48 va_list params;
49
50 va_start(params, err);
51 die_builtin(err, params);
52 va_end(params);
53 }
54
pr_err(const char * err,...)55 void pr_err(const char *err, ...)
56 {
57 va_list params;
58
59 if (loglevel < LOGLEVEL_ERROR)
60 return;
61
62 va_start(params, err);
63 error_builtin(err, params);
64 va_end(params);
65 }
66
pr_warning(const char * warn,...)67 void pr_warning(const char *warn, ...)
68 {
69 va_list params;
70
71 if (loglevel < LOGLEVEL_WARNING)
72 return;
73
74 va_start(params, warn);
75 warn_builtin(warn, params);
76 va_end(params);
77 }
78
pr_info(const char * info,...)79 void pr_info(const char *info, ...)
80 {
81 va_list params;
82
83 if (loglevel < LOGLEVEL_INFO)
84 return;
85
86 va_start(params, info);
87 info_builtin(info, params);
88 va_end(params);
89 }
90
91 /* Do not call directly; call pr_debug() instead. */
__pr_debug(const char * debug,...)92 void __pr_debug(const char *debug, ...)
93 {
94 va_list params;
95
96 va_start(params, debug);
97 debug_builtin(debug, params);
98 va_end(params);
99 }
100
die_perror(const char * s)101 void die_perror(const char *s)
102 {
103 perror(s);
104 exit(1);
105 }
106
mmap_hugetlbfs(struct kvm * kvm,const char * htlbfs_path,u64 size)107 void *mmap_hugetlbfs(struct kvm *kvm, const char *htlbfs_path, u64 size)
108 {
109 char mpath[PATH_MAX];
110 int fd;
111 struct statfs sfs;
112 void *addr;
113 unsigned long blk_size;
114
115 if (statfs(htlbfs_path, &sfs) < 0)
116 die("Can't stat %s\n", htlbfs_path);
117
118 if ((unsigned int)sfs.f_type != HUGETLBFS_MAGIC)
119 die("%s is not hugetlbfs!\n", htlbfs_path);
120
121 blk_size = (unsigned long)sfs.f_bsize;
122 if (sfs.f_bsize == 0 || blk_size > size) {
123 die("Can't use hugetlbfs pagesize %ld for mem size %lld\n",
124 blk_size, (unsigned long long)size);
125 }
126
127 kvm->ram_pagesize = blk_size;
128
129 snprintf(mpath, PATH_MAX, "%s/kvmtoolXXXXXX", htlbfs_path);
130 fd = mkstemp(mpath);
131 if (fd < 0)
132 die("Can't open %s for hugetlbfs map\n", mpath);
133 unlink(mpath);
134 if (ftruncate(fd, size) < 0)
135 die("Can't ftruncate for mem mapping size %lld\n",
136 (unsigned long long)size);
137 addr = mmap(NULL, size, PROT_RW, MAP_PRIVATE, fd, 0);
138 close(fd);
139
140 return addr;
141 }
142
143 /* This function wraps the decision between hugetlbfs map (if requested) or normal mmap */
mmap_anon_or_hugetlbfs(struct kvm * kvm,const char * hugetlbfs_path,u64 size)144 void *mmap_anon_or_hugetlbfs(struct kvm *kvm, const char *hugetlbfs_path, u64 size)
145 {
146 if (hugetlbfs_path)
147 /*
148 * We don't /need/ to map guest RAM from hugetlbfs, but we do so
149 * if the user specifies a hugetlbfs path.
150 */
151 return mmap_hugetlbfs(kvm, hugetlbfs_path, size);
152 else {
153 kvm->ram_pagesize = getpagesize();
154 return mmap(NULL, size, PROT_RW, MAP_ANON_NORESERVE, -1, 0);
155 }
156 }
157