Files
kvmtool/util/util.c
T
Michael Ellerman 3ebd8e0bf3 kvm tools: Remember page size as kvm->ram_pagesize
On some powerpc platforms we need to make sure we only advertise page
sizes to the guest which are <= the size of the pages backing guest RAM.

So have mmap_hugetblfs() save the hugetblfs page size for us, and also
teach mmap_anon_or_hugetblfs() to set the page size for anonymous mmap.

Acked-by: Matt Evans <matt@ozlabs.org>
Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
Signed-off-by: Pekka Enberg <penberg@kernel.org>
2015-06-01 16:39:52 +01:00

134 lines
2.7 KiB
C

/*
* 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, 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",
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);
}
}