Page MenuHomeFreeBSD

D61071.1793503447.diff
No OneTemporary

Authored By
Unknown
Size
6 KB
Referenced Files
None
Subscribers
None

D61071.1793503447.diff

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

Mime Type
text/plain
Expires
Sun, Nov 1, 3:24 AM (18 h, 44 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
41273751
Default Alt Text
D61071.1793503447.diff (6 KB)

Event Timeline