exec, kvm, target-ppc: Move getrampagesize() to common code

getrampagesize() returns the largest supported page size and mainly
used to know if huge pages are enabled.

However is implemented in target-ppc/kvm.c and not available
in TCG or other architectures.

This renames and moves gethugepagesize() to mmap-alloc.c where
fd-based analog of it is already implemented. This renames and moves
getrampagesize() to exec.c as it seems to be the common place for
helpers like this.

Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
This commit is contained in:
Alexey Kardashevskiy 2017-03-02 13:36:11 +11:00 committed by David Gibson
parent 9b44c836dc
commit 9c60766887
5 changed files with 115 additions and 104 deletions

82
exec.c
View File

@ -42,6 +42,7 @@
#include "exec/memory.h"
#include "exec/ioport.h"
#include "sysemu/dma.h"
#include "sysemu/numa.h"
#include "exec/address-spaces.h"
#include "sysemu/xen-mapcache.h"
#include "trace-root.h"
@ -1256,6 +1257,87 @@ void qemu_mutex_unlock_ramlist(void)
qemu_mutex_unlock(&ram_list.mutex);
}
#ifdef __linux__
/*
* FIXME TOCTTOU: this iterates over memory backends' mem-path, which
* may or may not name the same files / on the same filesystem now as
* when we actually open and map them. Iterate over the file
* descriptors instead, and use qemu_fd_getpagesize().
*/
static int find_max_supported_pagesize(Object *obj, void *opaque)
{
char *mem_path;
long *hpsize_min = opaque;
if (object_dynamic_cast(obj, TYPE_MEMORY_BACKEND)) {
mem_path = object_property_get_str(obj, "mem-path", NULL);
if (mem_path) {
long hpsize = qemu_mempath_getpagesize(mem_path);
if (hpsize < *hpsize_min) {
*hpsize_min = hpsize;
}
} else {
*hpsize_min = getpagesize();
}
}
return 0;
}
long qemu_getrampagesize(void)
{
long hpsize = LONG_MAX;
long mainrampagesize;
Object *memdev_root;
if (mem_path) {
mainrampagesize = qemu_mempath_getpagesize(mem_path);
} else {
mainrampagesize = getpagesize();
}
/* it's possible we have memory-backend objects with
* hugepage-backed RAM. these may get mapped into system
* address space via -numa parameters or memory hotplug
* hooks. we want to take these into account, but we
* also want to make sure these supported hugepage
* sizes are applicable across the entire range of memory
* we may boot from, so we take the min across all
* backends, and assume normal pages in cases where a
* backend isn't backed by hugepages.
*/
memdev_root = object_resolve_path("/objects", NULL);
if (memdev_root) {
object_child_foreach(memdev_root, find_max_supported_pagesize, &hpsize);
}
if (hpsize == LONG_MAX) {
/* No additional memory regions found ==> Report main RAM page size */
return mainrampagesize;
}
/* If NUMA is disabled or the NUMA nodes are not backed with a
* memory-backend, then there is at least one node using "normal" RAM,
* so if its page size is smaller we have got to report that size instead.
*/
if (hpsize > mainrampagesize &&
(nb_numa_nodes == 0 || numa_info[0].node_memdev == NULL)) {
static bool warned;
if (!warned) {
error_report("Huge page support disabled (n/a for main memory).");
warned = true;
}
return mainrampagesize;
}
return hpsize;
}
#else
long qemu_getrampagesize(void)
{
return getpagesize();
}
#endif
#ifdef __linux__
static int64_t get_file_size(int fd)
{

View File

@ -52,6 +52,7 @@ static inline void *ramblock_ptr(RAMBlock *block, ram_addr_t offset)
return (char *)block->host + offset;
}
long qemu_getrampagesize(void);
ram_addr_t last_ram_offset(void);
RAMBlock *qemu_ram_alloc_from_file(ram_addr_t size, MemoryRegion *mr,
bool share, const char *mem_path,

View File

@ -5,6 +5,8 @@
size_t qemu_fd_getpagesize(int fd);
size_t qemu_mempath_getpagesize(const char *mem_path);
void *qemu_ram_mmap(int fd, size_t size, size_t align, bool shared);
void qemu_ram_munmap(void *ptr, size_t size);

View File

@ -28,7 +28,6 @@
#include "qemu/timer.h"
#include "sysemu/sysemu.h"
#include "sysemu/hw_accel.h"
#include "sysemu/numa.h"
#include "kvm_ppc.h"
#include "sysemu/cpus.h"
#include "sysemu/device_tree.h"
@ -43,8 +42,10 @@
#include "trace.h"
#include "exec/gdbstub.h"
#include "exec/memattrs.h"
#include "exec/ram_addr.h"
#include "sysemu/hostmem.h"
#include "qemu/cutils.h"
#include "qemu/mmap-alloc.h"
#if defined(TARGET_PPC64)
#include "hw/ppc/spapr_cpu_core.h"
#endif
@ -329,106 +330,6 @@ static void kvm_get_smmu_info(PowerPCCPU *cpu, struct kvm_ppc_smmu_info *info)
kvm_get_fallback_smmu_info(cpu, info);
}
static long gethugepagesize(const char *mem_path)
{
struct statfs fs;
int ret;
do {
ret = statfs(mem_path, &fs);
} while (ret != 0 && errno == EINTR);
if (ret != 0) {
fprintf(stderr, "Couldn't statfs() memory path: %s\n",
strerror(errno));
exit(1);
}
#define HUGETLBFS_MAGIC 0x958458f6
if (fs.f_type != HUGETLBFS_MAGIC) {
/* Explicit mempath, but it's ordinary pages */
return getpagesize();
}
/* It's hugepage, return the huge page size */
return fs.f_bsize;
}
/*
* FIXME TOCTTOU: this iterates over memory backends' mem-path, which
* may or may not name the same files / on the same filesystem now as
* when we actually open and map them. Iterate over the file
* descriptors instead, and use qemu_fd_getpagesize().
*/
static int find_max_supported_pagesize(Object *obj, void *opaque)
{
char *mem_path;
long *hpsize_min = opaque;
if (object_dynamic_cast(obj, TYPE_MEMORY_BACKEND)) {
mem_path = object_property_get_str(obj, "mem-path", NULL);
if (mem_path) {
long hpsize = gethugepagesize(mem_path);
if (hpsize < *hpsize_min) {
*hpsize_min = hpsize;
}
} else {
*hpsize_min = getpagesize();
}
}
return 0;
}
static long getrampagesize(void)
{
long hpsize = LONG_MAX;
long mainrampagesize;
Object *memdev_root;
if (mem_path) {
mainrampagesize = gethugepagesize(mem_path);
} else {
mainrampagesize = getpagesize();
}
/* it's possible we have memory-backend objects with
* hugepage-backed RAM. these may get mapped into system
* address space via -numa parameters or memory hotplug
* hooks. we want to take these into account, but we
* also want to make sure these supported hugepage
* sizes are applicable across the entire range of memory
* we may boot from, so we take the min across all
* backends, and assume normal pages in cases where a
* backend isn't backed by hugepages.
*/
memdev_root = object_resolve_path("/objects", NULL);
if (memdev_root) {
object_child_foreach(memdev_root, find_max_supported_pagesize, &hpsize);
}
if (hpsize == LONG_MAX) {
/* No additional memory regions found ==> Report main RAM page size */
return mainrampagesize;
}
/* If NUMA is disabled or the NUMA nodes are not backed with a
* memory-backend, then there is at least one node using "normal" RAM,
* so if its page size is smaller we have got to report that size instead.
*/
if (hpsize > mainrampagesize &&
(nb_numa_nodes == 0 || numa_info[0].node_memdev == NULL)) {
static bool warned;
if (!warned) {
error_report("Huge page support disabled (n/a for main memory).");
warned = true;
}
return mainrampagesize;
}
return hpsize;
}
static bool kvm_valid_page_size(uint32_t flags, long rampgsize, uint32_t shift)
{
if (!(flags & KVM_PPC_PAGE_SIZES_REAL)) {
@ -460,7 +361,7 @@ static void kvm_fixup_page_sizes(PowerPCCPU *cpu)
}
if (!max_cpu_page_size) {
max_cpu_page_size = getrampagesize();
max_cpu_page_size = qemu_getrampagesize();
}
/* Convert to QEMU form */
@ -521,7 +422,7 @@ bool kvmppc_is_mem_backend_page_size_ok(char *obj_path)
long pagesize;
if (mempath) {
pagesize = gethugepagesize(mempath);
pagesize = qemu_mempath_getpagesize(mempath);
} else {
pagesize = getpagesize();
}
@ -2205,7 +2106,7 @@ uint64_t kvmppc_rma_size(uint64_t current_size, unsigned int hash_shift)
/* Find the largest hardware supported page size that's less than
* or equal to the (logical) backing page size of guest RAM */
kvm_get_smmu_info(POWERPC_CPU(first_cpu), &info);
rampagesize = getrampagesize();
rampagesize = qemu_getrampagesize();
best_page_shift = 0;
for (i = 0; i < KVM_PPC_PAGE_SIZES_MAX_SZ; i++) {

View File

@ -40,6 +40,31 @@ size_t qemu_fd_getpagesize(int fd)
return getpagesize();
}
size_t qemu_mempath_getpagesize(const char *mem_path)
{
#ifdef CONFIG_LINUX
struct statfs fs;
int ret;
do {
ret = statfs(mem_path, &fs);
} while (ret != 0 && errno == EINTR);
if (ret != 0) {
fprintf(stderr, "Couldn't statfs() memory path: %s\n",
strerror(errno));
exit(1);
}
if (fs.f_type == HUGETLBFS_MAGIC) {
/* It's hugepage, return the huge page size */
return fs.f_bsize;
}
#endif
return getpagesize();
}
void *qemu_ram_mmap(int fd, size_t size, size_t align, bool shared)
{
/*