Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F176851973
D61071.1793506353.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Authored By
Unknown
Size
6 KB
Referenced Files
None
Subscribers
None
D61071.1793506353.diff
View Options
diff --git a/lib/libvmmapi/amd64/vmmapi_machdep.c b/lib/libvmmapi/amd64/vmmapi_machdep.c
--- a/lib/libvmmapi/amd64/vmmapi_machdep.c
+++ b/lib/libvmmapi/amd64/vmmapi_machdep.c
@@ -56,6 +56,7 @@
#define VM_MD_IOCTLS \
VM_DISCARD_PAGES, \
+ VM_GET_POPULATED_PAGES, \
VM_SET_SEGMENT_DESCRIPTOR, \
VM_GET_SEGMENT_DESCRIPTOR, \
VM_SET_KERNEMU_DEV, \
diff --git a/lib/libvmmapi/vmmapi.h b/lib/libvmmapi/vmmapi.h
--- a/lib/libvmmapi/vmmapi.h
+++ b/lib/libvmmapi/vmmapi.h
@@ -113,6 +113,10 @@
#ifdef VM_DISCARD_PAGES
int vm_discard_pages(struct vmctx *ctx, vm_paddr_t gpa, size_t len);
#endif
+#ifdef VM_GET_POPULATED_PAGES
+int vm_get_populated_pages(struct vmctx *ctx, vm_paddr_t gpa, size_t len,
+ uint64_t *map);
+#endif
int vm_create(const char *name);
struct vmctx *vm_open(const char *name);
diff --git a/lib/libvmmapi/vmmapi.c b/lib/libvmmapi/vmmapi.c
--- a/lib/libvmmapi/vmmapi.c
+++ b/lib/libvmmapi/vmmapi.c
@@ -359,6 +359,24 @@
}
#endif
+#ifdef VM_GET_POPULATED_PAGES
+int
+vm_get_populated_pages(struct vmctx *ctx, vm_paddr_t gpa, size_t len,
+ uint64_t *map)
+{
+ struct vm_populated_pages req;
+ int error;
+
+ req.gpa = gpa;
+ req.len = len;
+ error = ioctl(ctx->fd, VM_GET_POPULATED_PAGES, &req);
+ if (error == 0)
+ memcpy(map, req.map,
+ howmany(len / PAGE_SIZE, 64) * sizeof(*map));
+ return (error);
+}
+#endif
+
int
vm_mmap_getnext(struct vmctx *ctx, vm_paddr_t *gpa, int *segid,
vm_ooffset_t *segoff, size_t *len, int *prot, int *flags)
diff --git a/sys/amd64/include/vmm_dev.h b/sys/amd64/include/vmm_dev.h
--- a/sys/amd64/include/vmm_dev.h
+++ b/sys/amd64/include/vmm_dev.h
@@ -346,6 +346,9 @@
/* memory reclamation */
IOCNUM_DISCARD_PAGES = 116,
+
+ /* memory population */
+ IOCNUM_GET_POPULATED_PAGES = 117,
};
#define VM_RUN \
@@ -366,6 +369,8 @@
_IOW('v', IOCNUM_MUNMAP_MEMSEG, struct vm_munmap)
#define VM_DISCARD_PAGES \
_IOW('v', IOCNUM_DISCARD_PAGES, struct vm_discard_pages)
+#define VM_GET_POPULATED_PAGES \
+ _IOWR('v', IOCNUM_GET_POPULATED_PAGES, struct vm_populated_pages)
#define VM_SET_REGISTER \
_IOW('v', IOCNUM_SET_REGISTER, struct vm_register)
#define VM_GET_REGISTER \
diff --git a/sys/dev/vmm/vmm_dev.h b/sys/dev/vmm/vmm_dev.h
--- a/sys/dev/vmm/vmm_dev.h
+++ b/sys/dev/vmm/vmm_dev.h
@@ -46,6 +46,28 @@
#define VM_DISCARD_PAGES_MAX_PAGES 256
+/*
+ * Report which pages of a range of guest RAM are populated, that is,
+ * resident or stored in swap. Pages that are not populated read as
+ * zeroes. The range must be aligned to the host page size, contain at
+ * most VM_POPULATED_PAGES_MAX_PAGES pages, and lie within one
+ * system-memory mapping. Bit (i % 64) of map[i / 64] is set if page i of
+ * the range is populated, and bits beyond the range are cleared. The
+ * VM_GET_POPULATED_PAGES ioctl is defined by <machine/vmm_dev.h> on
+ * platforms that support it (amd64).
+ *
+ * The result is a snapshot: concurrent accesses may populate pages, and
+ * discards may depopulate them, after it is taken.
+ */
+#define VM_POPULATED_PAGES_MAX_PAGES 1024
+
+struct vm_populated_pages {
+ uint64_t gpa;
+ uint64_t len;
+ uint64_t map[VM_POPULATED_PAGES_MAX_PAGES / 64];
+};
+_Static_assert(sizeof(struct vm_populated_pages) == 144, "ABI");
+
#ifdef _KERNEL
struct thread;
struct vm;
diff --git a/sys/dev/vmm/vmm_dev.c b/sys/dev/vmm/vmm_dev.c
--- a/sys/dev/vmm/vmm_dev.c
+++ b/sys/dev/vmm/vmm_dev.c
@@ -422,6 +422,9 @@
#ifdef VM_DISCARD_PAGES
VMMDEV_IOCTL(VM_DISCARD_PAGES, VMMDEV_IOCTL_SLOCK_MEMSEGS),
#endif
+#ifdef VM_GET_POPULATED_PAGES
+ VMMDEV_IOCTL(VM_GET_POPULATED_PAGES, VMMDEV_IOCTL_SLOCK_MEMSEGS),
+#endif
VMMDEV_IOCTL(VM_SUSPEND_CPU, VMMDEV_IOCTL_MAYBE_ALLOC_VCPU),
VMMDEV_IOCTL(VM_RESUME_CPU, VMMDEV_IOCTL_MAYBE_ALLOC_VCPU),
@@ -570,6 +573,16 @@
break;
}
#endif
+#ifdef VM_GET_POPULATED_PAGES
+ case VM_GET_POPULATED_PAGES: {
+ struct vm_populated_pages *populated;
+
+ populated = (struct vm_populated_pages *)data;
+ error = vm_mem_populated_pages(sc->vm, populated->gpa,
+ populated->len, populated->map);
+ break;
+ }
+#endif
#ifdef __amd64__
#ifdef COMPAT_FREEBSD12
case VM_ALLOC_MEMSEG_12:
diff --git a/sys/dev/vmm/vmm_mem.h b/sys/dev/vmm/vmm_mem.h
--- a/sys/dev/vmm/vmm_mem.h
+++ b/sys/dev/vmm/vmm_mem.h
@@ -103,6 +103,8 @@
bool vm_mem_allocated(struct vcpu *vcpu, vm_paddr_t gpa);
int vm_mem_discard_pages(struct vm *vm, vm_paddr_t gpa, size_t len);
+int vm_mem_populated_pages(struct vm *vm, vm_paddr_t gpa, size_t len,
+ uint64_t *map);
int vm_gla2gpa_nofault(struct vcpu *vcpu, struct vm_guest_paging *paging,
uint64_t gla, int prot, uint64_t *gpa, int *is_fault);
diff --git a/sys/dev/vmm/vmm_mem.c b/sys/dev/vmm/vmm_mem.c
--- a/sys/dev/vmm/vmm_mem.c
+++ b/sys/dev/vmm/vmm_mem.c
@@ -26,6 +26,7 @@
#include <vm/vm_map.h>
#include <vm/vm_object.h>
#include <vm/vm_page.h>
+#include <vm/vm_pager.h>
#include <dev/vmm/vmm_dev.h>
#include <dev/vmm/vmm_mem.h>
@@ -430,7 +431,7 @@
return (maxaddr);
}
-#ifdef VM_DISCARD_PAGES
+#if defined(VM_DISCARD_PAGES) || defined(VM_GET_POPULATED_PAGES)
/*
* Find the system-memory mapping that contains all of [gpa, gpa + len) and
* the object offset of gpa. The range must be page-aligned and contain at
@@ -478,7 +479,9 @@
*offp = off;
return (0);
}
+#endif
+#ifdef VM_DISCARD_PAGES
int
vm_mem_discard_pages(struct vm *vm, vm_paddr_t gpa, size_t len)
{
@@ -520,6 +523,42 @@
}
#endif
+#ifdef VM_GET_POPULATED_PAGES
+/*
+ * A page counts as populated if it is in the object, whatever its state, or
+ * has swap backing. Any other page reads as zeroes.
+ */
+int
+vm_mem_populated_pages(struct vm *vm, vm_paddr_t gpa, size_t len,
+ uint64_t *map)
+{
+ struct vm_mem_map *mm;
+ vm_object_t obj;
+ vm_ooffset_t off;
+ vm_pindex_t pindex;
+ size_t i;
+ int error;
+
+ error = vm_mem_find_sysmem(vm, gpa, len, VM_POPULATED_PAGES_MAX_PAGES,
+ &mm, &off);
+ if (error != 0)
+ return (error);
+ obj = vm_mem(vm)->mem_segs[mm->segid].object;
+ pindex = OFF_TO_IDX(off);
+
+ memset(map, 0, VM_POPULATED_PAGES_MAX_PAGES / NBBY);
+ VM_OBJECT_RLOCK(obj);
+ for (i = 0; i < len / PAGE_SIZE; i++) {
+ if (vm_page_lookup(obj, pindex + i) != NULL ||
+ vm_pager_has_page(obj, pindex + i, NULL, NULL))
+ map[i / 64] |= (uint64_t)1 << (i % 64);
+ }
+ VM_OBJECT_RUNLOCK(obj);
+
+ return (0);
+}
+#endif
+
static void *
_vm_gpa_hold(struct vm *vm, vm_paddr_t gpa, size_t len, int reqprot,
void **cookie)
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sun, Nov 1, 4:12 AM (19 h, 33 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
41273751
Default Alt Text
D61071.1793506353.diff (6 KB)
Attached To
Mode
D61071: vmm: Add a query for populated guest memory
Attached
Detach File
Event Timeline