[PATCH] hw/virtio: balloon: access RAMBlock directly via mr->ram_block

Bin Guo posted 1 patch 16 hours ago
Patches applied successfully (tree, apply log)
git fetch https://github.com/patchew-project/qemu tags/patchew/20260608073632.1113-1-guobin@linux.alibaba.com
Maintainers: "Michael S. Tsirkin" <mst@redhat.com>, David Hildenbrand <david@kernel.org>
hw/virtio/virtio-balloon.c | 30 +++++++++---------------------
1 file changed, 9 insertions(+), 21 deletions(-)
[PATCH] hw/virtio: balloon: access RAMBlock directly via mr->ram_block
Posted by Bin Guo 16 hours ago
The balloon inflate/deflate paths obtained the RAMBlock through a
round-trip: compute host VA via memory_region_get_ram_ptr(), then
reverse-lookup via qemu_ram_block_from_host() which linearly scans
the RAMBlock list.

Since memory_region_find() already resolves to the concrete RAM
MemoryRegion (aliases flattened), mr->ram_block is guaranteed valid
and mr_offset directly serves as the RAMBlock offset.  Use this to
eliminate the unnecessary VA computation and list walk.

This also removes the long-standing XXX comment asking for a better
approach.

Signed-off-by: Bin Guo <guobin@linux.alibaba.com>
---
 hw/virtio/virtio-balloon.c | 30 +++++++++---------------------
 1 file changed, 9 insertions(+), 21 deletions(-)

diff --git a/hw/virtio/virtio-balloon.c b/hw/virtio/virtio-balloon.c
index 4c5f486ba2..4a7f0bb9a8 100644
--- a/hw/virtio/virtio-balloon.c
+++ b/hw/virtio/virtio-balloon.c
@@ -80,21 +80,15 @@ static void balloon_inflate_page(VirtIOBalloon *balloon,
                                  MemoryRegion *mr, hwaddr mr_offset,
                                  PartiallyBalloonedPage *pbp)
 {
-    void *addr = memory_region_get_ram_ptr(mr) + mr_offset;
-    ram_addr_t rb_offset, rb_aligned_offset, base_gpa;
-    RAMBlock *rb;
+    RAMBlock *rb = mr->ram_block;
+    ram_addr_t rb_aligned_offset, base_gpa;
     size_t rb_page_size;
     int subpages;
 
-    /* XXX is there a better way to get to the RAMBlock than via a
-     * host address? */
-    rb = qemu_ram_block_from_host(addr, false, &rb_offset);
     rb_page_size = qemu_ram_pagesize(rb);
 
     if (rb_page_size == BALLOON_PAGE_SIZE) {
-        /* Easy case */
-
-        ram_block_discard_range(rb, rb_offset, rb_page_size);
+        ram_block_discard_range(rb, mr_offset, rb_page_size);
         /* We ignore errors from ram_block_discard_range(), because it
          * has already reported them, and failing to discard a balloon
          * page is not fatal */
@@ -110,10 +104,9 @@ static void balloon_inflate_page(VirtIOBalloon *balloon,
     warn_report_once(
 "Balloon used with backing page size > 4kiB, this may not be reliable");
 
-    rb_aligned_offset = QEMU_ALIGN_DOWN(rb_offset, rb_page_size);
+    rb_aligned_offset = QEMU_ALIGN_DOWN(mr_offset, rb_page_size);
     subpages = rb_page_size / BALLOON_PAGE_SIZE;
-    base_gpa = memory_region_get_ram_addr(mr) + mr_offset -
-               (rb_offset - rb_aligned_offset);
+    base_gpa = memory_region_get_ram_addr(mr) + rb_aligned_offset;
 
     if (pbp->bitmap && !virtio_balloon_pbp_matches(pbp, base_gpa)) {
         /* We've partially ballooned part of a host page, but now
@@ -126,7 +119,7 @@ static void balloon_inflate_page(VirtIOBalloon *balloon,
         virtio_balloon_pbp_alloc(pbp, base_gpa, subpages);
     }
 
-    set_bit((rb_offset - rb_aligned_offset) / BALLOON_PAGE_SIZE,
+    set_bit((mr_offset - rb_aligned_offset) / BALLOON_PAGE_SIZE,
             pbp->bitmap);
 
     if (bitmap_full(pbp->bitmap, subpages)) {
@@ -144,19 +137,14 @@ static void balloon_inflate_page(VirtIOBalloon *balloon,
 static void balloon_deflate_page(VirtIOBalloon *balloon,
                                  MemoryRegion *mr, hwaddr mr_offset)
 {
-    void *addr = memory_region_get_ram_ptr(mr) + mr_offset;
-    ram_addr_t rb_offset;
-    RAMBlock *rb;
+    RAMBlock *rb = mr->ram_block;
     size_t rb_page_size;
     void *host_addr;
     int ret;
 
-    /* XXX is there a better way to get to the RAMBlock than via a
-     * host address? */
-    rb = qemu_ram_block_from_host(addr, false, &rb_offset);
     rb_page_size = qemu_ram_pagesize(rb);
-
-    host_addr = (void *)((uintptr_t)addr & ~(rb_page_size - 1));
+    host_addr = qemu_ram_get_host_addr(rb) +
+                QEMU_ALIGN_DOWN(mr_offset, rb_page_size);
 
     /* When a page is deflated, we hint the whole host page it lives
      * on, since we can't do anything smaller */
-- 
2.50.1 (Apple Git-155)