[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH v2 09/14] libvhost-user: Factor out search for memory region by G
From: |
David Hildenbrand |
Subject: |
[PATCH v2 09/14] libvhost-user: Factor out search for memory region by GPA and simplify |
Date: |
Wed, 14 Feb 2024 16:16:56 +0100 |
Memory regions cannot overlap, and if we ever hit that case something
would be really flawed.
For example, when vhost code in QEMU decides to increase the size of memory
regions to cover full huge pages, it makes sure to never create overlaps,
and if there would be overlaps, it would bail out.
QEMU commits 48d7c9757749 ("vhost: Merge sections added to temporary
list"), c1ece84e7c93 ("vhost: Huge page align and merge") and
e7b94a84b6cb ("vhost: Allow adjoining regions") added and clarified that
handling and how overlaps are impossible.
Consequently, each GPA can belong to at most one memory region, and
everything else doesn't make sense. Let's factor out our search to prepare
for further changes.
Reviewed-by: Raphael Norwitz <raphael@enfabrica.net>
Acked-by: Stefano Garzarella <sgarzare@redhat.com>
Signed-off-by: David Hildenbrand <david@redhat.com>
---
subprojects/libvhost-user/libvhost-user.c | 79 +++++++++++++----------
1 file changed, 45 insertions(+), 34 deletions(-)
diff --git a/subprojects/libvhost-user/libvhost-user.c
b/subprojects/libvhost-user/libvhost-user.c
index 7f29e01c30..d72f25396d 100644
--- a/subprojects/libvhost-user/libvhost-user.c
+++ b/subprojects/libvhost-user/libvhost-user.c
@@ -195,30 +195,47 @@ vu_panic(VuDev *dev, const char *msg, ...)
*/
}
+/* Search for a memory region that covers this guest physical address. */
+static VuDevRegion *
+vu_gpa_to_mem_region(VuDev *dev, uint64_t guest_addr)
+{
+ unsigned int i;
+
+ /*
+ * Memory regions cannot overlap in guest physical address space. Each
+ * GPA belongs to exactly one memory region, so there can only be one
+ * match.
+ */
+ for (i = 0; i < dev->nregions; i++) {
+ VuDevRegion *cur = &dev->regions[i];
+
+ if (guest_addr >= cur->gpa && guest_addr < cur->gpa + cur->size) {
+ return cur;
+ }
+ }
+ return NULL;
+}
+
/* Translate guest physical address to our virtual address. */
void *
vu_gpa_to_va(VuDev *dev, uint64_t *plen, uint64_t guest_addr)
{
- unsigned int i;
+ VuDevRegion *r;
if (*plen == 0) {
return NULL;
}
- /* Find matching memory region. */
- for (i = 0; i < dev->nregions; i++) {
- VuDevRegion *r = &dev->regions[i];
-
- if ((guest_addr >= r->gpa) && (guest_addr < (r->gpa + r->size))) {
- if ((guest_addr + *plen) > (r->gpa + r->size)) {
- *plen = r->gpa + r->size - guest_addr;
- }
- return (void *)(uintptr_t)
- guest_addr - r->gpa + r->mmap_addr + r->mmap_offset;
- }
+ r = vu_gpa_to_mem_region(dev, guest_addr);
+ if (!r) {
+ return NULL;
}
- return NULL;
+ if ((guest_addr + *plen) > (r->gpa + r->size)) {
+ *plen = r->gpa + r->size - guest_addr;
+ }
+ return (void *)(uintptr_t)guest_addr - r->gpa + r->mmap_addr +
+ r->mmap_offset;
}
/* Translate qemu virtual address to our virtual address. */
@@ -854,8 +871,8 @@ static inline bool reg_equal(VuDevRegion *vudev_reg,
static bool
vu_rem_mem_reg(VuDev *dev, VhostUserMsg *vmsg) {
VhostUserMemoryRegion m = vmsg->payload.memreg.region, *msg_region = &m;
- unsigned int i;
- bool found = false;
+ unsigned int idx;
+ VuDevRegion *r;
if (vmsg->fd_num > 1) {
vmsg_close_fds(vmsg);
@@ -882,28 +899,22 @@ vu_rem_mem_reg(VuDev *dev, VhostUserMsg *vmsg) {
DPRINT(" mmap_offset 0x%016"PRIx64"\n",
msg_region->mmap_offset);
- for (i = 0; i < dev->nregions; i++) {
- if (reg_equal(&dev->regions[i], msg_region)) {
- VuDevRegion *r = &dev->regions[i];
-
- munmap((void *)(uintptr_t)r->mmap_addr, r->size + r->mmap_offset);
-
- /* Shift all affected entries by 1 to close the hole at index. */
- memmove(dev->regions + i, dev->regions + i + 1,
- sizeof(VuDevRegion) * (dev->nregions - i - 1));
- DPRINT("Successfully removed a region\n");
- dev->nregions--;
- i--;
-
- found = true;
- break;
- }
- }
-
- if (!found) {
+ r = vu_gpa_to_mem_region(dev, msg_region->guest_phys_addr);
+ if (!r || !reg_equal(r, msg_region)) {
+ vmsg_close_fds(vmsg);
vu_panic(dev, "Specified region not found\n");
+ return false;
}
+ munmap((void *)(uintptr_t)r->mmap_addr, r->size + r->mmap_offset);
+
+ idx = r - dev->regions;
+ assert(idx < dev->nregions);
+ /* Shift all affected entries by 1 to close the hole. */
+ memmove(r, r + 1, sizeof(VuDevRegion) * (dev->nregions - idx - 1));
+ DPRINT("Successfully removed a region\n");
+ dev->nregions--;
+
vmsg_close_fds(vmsg);
return false;
--
2.43.0
- [PATCH v2 00/14] libvhost-user: support more memslots and cleanup memslot handling code, David Hildenbrand, 2024/02/14
- [PATCH v2 01/14] libvhost-user: Dynamically allocate memory for memory slots, David Hildenbrand, 2024/02/14
- [PATCH v2 02/14] libvhost-user: Bump up VHOST_USER_MAX_RAM_SLOTS to 509, David Hildenbrand, 2024/02/14
- [PATCH v2 03/14] libvhost-user: Factor out removing all mem regions, David Hildenbrand, 2024/02/14
- [PATCH v2 04/14] libvhost-user: Merge vu_set_mem_table_exec_postcopy() into vu_set_mem_table_exec(), David Hildenbrand, 2024/02/14
- [PATCH v2 05/14] libvhost-user: Factor out adding a memory region, David Hildenbrand, 2024/02/14
- [PATCH v2 06/14] libvhost-user: No need to check for NULL when unmapping, David Hildenbrand, 2024/02/14
- [PATCH v2 07/14] libvhost-user: Don't zero out memory for memory regions, David Hildenbrand, 2024/02/14
- [PATCH v2 08/14] libvhost-user: Don't search for duplicates when removing memory regions, David Hildenbrand, 2024/02/14
- [PATCH v2 09/14] libvhost-user: Factor out search for memory region by GPA and simplify,
David Hildenbrand <=
- [PATCH v2 10/14] libvhost-user: Speedup gpa_to_mem_region() and vu_gpa_to_va(), David Hildenbrand, 2024/02/14
- [PATCH v2 11/14] libvhost-user: Use most of mmap_offset as fd_offset, David Hildenbrand, 2024/02/14
- [PATCH v2 12/14] libvhost-user: Factor out vq usability check, David Hildenbrand, 2024/02/14
- [PATCH v2 13/14] libvhost-user: Dynamically remap rings after (temporarily?) removing memory regions, David Hildenbrand, 2024/02/14
- [PATCH v2 14/14] libvhost-user: Mark mmap'ed region memory as MADV_DONTDUMP, David Hildenbrand, 2024/02/14