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

