xref: /kvmtool/util/util.c (revision 3ebd8e0bf30b6b7c04b1e42f2ac453594fd9205b)
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 
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 
20 static NORETURN void die_builtin(const char *err, va_list params)
21 {
22 	report(" Fatal: ", err, params);
23 	exit(128);
24 }
25 
26 static void error_builtin(const char *err, va_list params)
27 {
28 	report(" Error: ", err, params);
29 }
30 
31 static void warn_builtin(const char *warn, va_list params)
32 {
33 	report(" Warning: ", warn, params);
34 }
35 
36 static void info_builtin(const char *info, va_list params)
37 {
38 	report(" Info: ", info, params);
39 }
40 
41 void die(const char *err, ...)
42 {
43 	va_list params;
44 
45 	va_start(params, err);
46 	die_builtin(err, params);
47 	va_end(params);
48 }
49 
50 int pr_err(const char *err, ...)
51 {
52 	va_list params;
53 
54 	va_start(params, err);
55 	error_builtin(err, params);
56 	va_end(params);
57 	return -1;
58 }
59 
60 void pr_warning(const char *warn, ...)
61 {
62 	va_list params;
63 
64 	va_start(params, warn);
65 	warn_builtin(warn, params);
66 	va_end(params);
67 }
68 
69 void pr_info(const char *info, ...)
70 {
71 	va_list params;
72 
73 	va_start(params, info);
74 	info_builtin(info, params);
75 	va_end(params);
76 }
77 
78 void die_perror(const char *s)
79 {
80 	perror(s);
81 	exit(1);
82 }
83 
84 void *mmap_hugetlbfs(struct kvm *kvm, const char *htlbfs_path, u64 size)
85 {
86 	char mpath[PATH_MAX];
87 	int fd;
88 	struct statfs sfs;
89 	void *addr;
90 	unsigned long blk_size;
91 
92 	if (statfs(htlbfs_path, &sfs) < 0)
93 		die("Can't stat %s\n", htlbfs_path);
94 
95 	if ((unsigned int)sfs.f_type != HUGETLBFS_MAGIC)
96 		die("%s is not hugetlbfs!\n", htlbfs_path);
97 
98 	blk_size = (unsigned long)sfs.f_bsize;
99 	if (sfs.f_bsize == 0 || blk_size > size) {
100 		die("Can't use hugetlbfs pagesize %ld for mem size %lld\n",
101 		    blk_size, size);
102 	}
103 
104 	kvm->ram_pagesize = blk_size;
105 
106 	snprintf(mpath, PATH_MAX, "%s/kvmtoolXXXXXX", htlbfs_path);
107 	fd = mkstemp(mpath);
108 	if (fd < 0)
109 		die("Can't open %s for hugetlbfs map\n", mpath);
110 	unlink(mpath);
111 	if (ftruncate(fd, size) < 0)
112 		die("Can't ftruncate for mem mapping size %lld\n",
113 		    size);
114 	addr = mmap(NULL, size, PROT_RW, MAP_PRIVATE, fd, 0);
115 	close(fd);
116 
117 	return addr;
118 }
119 
120 /* This function wraps the decision between hugetlbfs map (if requested) or normal mmap */
121 void *mmap_anon_or_hugetlbfs(struct kvm *kvm, const char *hugetlbfs_path, u64 size)
122 {
123 	if (hugetlbfs_path)
124 		/*
125 		 * We don't /need/ to map guest RAM from hugetlbfs, but we do so
126 		 * if the user specifies a hugetlbfs path.
127 		 */
128 		return mmap_hugetlbfs(kvm, hugetlbfs_path, size);
129 	else {
130 		kvm->ram_pagesize = getpagesize();
131 		return mmap(NULL, size, PROT_RW, MAP_ANON_NORESERVE, -1, 0);
132 	}
133 }
134