summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--target-ppc/kvm.c57
1 files changed, 51 insertions, 6 deletions
diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c
index 12328a4027..84ae447556 100644
--- a/target-ppc/kvm.c
+++ b/target-ppc/kvm.c
@@ -39,6 +39,7 @@
#include "sysemu/watchdog.h"
#include "trace.h"
#include "exec/gdbstub.h"
+#include "sysemu/hostmem.h"
//#define DEBUG_KVM
@@ -302,16 +303,11 @@ static void kvm_get_smmu_info(PowerPCCPU *cpu, struct kvm_ppc_smmu_info *info)
kvm_get_fallback_smmu_info(cpu, info);
}
-static long getrampagesize(void)
+static long gethugepagesize(const char *mem_path)
{
struct statfs fs;
int ret;
- if (!mem_path) {
- /* guest RAM is backed by normal anonymous pages */
- return getpagesize();
- }
-
do {
ret = statfs(mem_path, &fs);
} while (ret != 0 && errno == EINTR);
@@ -333,6 +329,55 @@ static long getrampagesize(void)
return fs.f_bsize;
}
+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;
+ Object *memdev_root;
+
+ if (mem_path) {
+ return gethugepagesize(mem_path);
+ }
+
+ /* 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) {
+ return getpagesize();
+ }
+
+ object_child_foreach(memdev_root, find_max_supported_pagesize, &hpsize);
+
+ return (hpsize == LONG_MAX) ? getpagesize() : hpsize;
+}
+
static bool kvm_valid_page_size(uint32_t flags, long rampgsize, uint32_t shift)
{
if (!(flags & KVM_PPC_PAGE_SIZES_REAL)) {