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