Integrate coco memory management operations into the virtio-mem driver to
manage the state of hotplug memory.

In virtio_mem_send_plug_request(), once the host hypervisor acknowledges a
plug request, invoke coco_set_plugged_bitmap() to set the corresponding
bits in the plugged bitmap. Conversely, in virtio_mem_send_unplug_request()
and virtio_mem_send_unplug_all_request(), call unaccept_memory() to let the
guest autonomously transition the target private pages back to "unaccepted"
state before asking the VMM to unplug them. After the VMM acknowledges the
unplug request, clear the ranges from the plugged bitmap.

Note that memory block hotplug/unplug also sets or clears the plugged
bitmap at memory block granularity. While doing this at device block
granularity here creates a slight redundancy, it is completely harmless.

Additionally, update virtio_mem_fake_online() to explicitly invoke
accept_memory() when transitioning memory out of the fake-offline state and
back into service. This ensures that any pages returning to the buddy
system are cleanly accepted by the guest architecture before they are freed
back into the allocator via free_contig_range().

Signed-off-by: Zhenzhong Duan <[email protected]>
---
 drivers/virtio/virtio_mem.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/drivers/virtio/virtio_mem.c b/drivers/virtio/virtio_mem.c
index 48051e9e98ab..9f6e53df8caf 100644
--- a/drivers/virtio/virtio_mem.c
+++ b/drivers/virtio/virtio_mem.c
@@ -1211,6 +1211,7 @@ static void virtio_mem_fake_online(unsigned long pfn, 
unsigned long nr_pages)
                        generic_online_page(page, order);
                } else {
                        virtio_mem_clear_fake_offline(pfn + i, 1 << order, 
true);
+                       accept_memory(page_to_phys(page), PAGE_SIZE << order);
                        free_contig_range(pfn + i, 1 << order);
                        adjust_managed_page_count(page, 1 << order);
                }
@@ -1436,6 +1437,7 @@ static int virtio_mem_send_plug_request(struct virtio_mem 
*vm, uint64_t addr,
        switch (virtio_mem_send_request(vm, &req)) {
        case VIRTIO_MEM_RESP_ACK:
                vm->plugged_size += size;
+               WARN_ON(coco_set_plugged_bitmap(addr, size, true));
                return 0;
        case VIRTIO_MEM_RESP_NACK:
                rc = -EAGAIN;
@@ -1471,9 +1473,12 @@ static int virtio_mem_send_unplug_request(struct 
virtio_mem *vm, uint64_t addr,
        dev_dbg(&vm->vdev->dev, "unplugging memory: 0x%llx - 0x%llx\n", addr,
                addr + size - 1);
 
+       unaccept_memory(addr, size);
+
        switch (virtio_mem_send_request(vm, &req)) {
        case VIRTIO_MEM_RESP_ACK:
                vm->plugged_size -= size;
+               WARN_ON(coco_set_plugged_bitmap(addr, size, false));
                return 0;
        case VIRTIO_MEM_RESP_BUSY:
                rc = -ETXTBSY;
@@ -1498,10 +1503,13 @@ static int virtio_mem_send_unplug_all_request(struct 
virtio_mem *vm)
 
        dev_dbg(&vm->vdev->dev, "unplugging all memory");
 
+       unaccept_memory(vm->addr, vm->region_size);
+
        switch (virtio_mem_send_request(vm, &req)) {
        case VIRTIO_MEM_RESP_ACK:
                vm->unplug_all_required = false;
                vm->plugged_size = 0;
+               WARN_ON(coco_set_plugged_bitmap(vm->addr, vm->region_size, 
false));
                /* usable region might have shrunk */
                atomic_set(&vm->config_changed, 1);
                return 0;
-- 
2.52.0


Reply via email to