/* * Balloon device works in 4K page units. So each page is pointed to by * multiple balloon pages. All memory counters in this driver are in balloon * page units.
*/ #define VIRTIO_BALLOON_PAGES_PER_PAGE (unsignedint)(PAGE_SIZE >> VIRTIO_BALLOON_PFN_SHIFT) #define VIRTIO_BALLOON_ARRAY_PFNS_MAX 256 /* Maximum number of (4k) pages to deflate on OOM notifications. */ #define VIRTIO_BALLOON_OOM_NR_PAGES 256 #define VIRTIO_BALLOON_OOM_NOTIFY_PRIORITY 80
#define VIRTIO_BALLOON_FREE_PAGE_ALLOC_FLAG (__GFP_NORETRY | __GFP_NOWARN | \
__GFP_NOMEMALLOC) /* The order of free page blocks to report to host */ #define VIRTIO_BALLOON_HINT_BLOCK_ORDER MAX_PAGE_ORDER /* The size of a free page block in bytes */ #define VIRTIO_BALLOON_HINT_BLOCK_BYTES \
(1 << (VIRTIO_BALLOON_HINT_BLOCK_ORDER + PAGE_SHIFT)) #define VIRTIO_BALLOON_HINT_BLOCK_PAGES (1 << VIRTIO_BALLOON_HINT_BLOCK_ORDER)
/* Balloon's own wq for cpu-intensive work items */ struct workqueue_struct *balloon_wq; /* The free page reporting work item submitted to the balloon wq */ struct work_struct report_free_page_work;
/* The balloon servicing is delegated to a freezable workqueue. */ struct work_struct update_balloon_stats_work; struct work_struct update_balloon_size_work;
/* Prevent updating balloon when it is being canceled. */
spinlock_t stop_update_lock; bool stop_update; /* Bitmap to indicate if reading the related config fields are needed */ unsignedlong config_read_bitmap;
/* The list of allocated free pages, waiting to be given back to mm */ struct list_head free_page_list;
spinlock_t free_page_list_lock; /* The number of free page blocks on the above list */ unsignedlong num_free_page_blocks; /* * The cmd id received from host. * Read it via virtio_balloon_cmd_id_received to get the latest value * sent from host.
*/
u32 cmd_id_received_cache; /* The cmd id that is actively in use */
__virtio32 cmd_id_active; /* Buffer to store the stop sign */
__virtio32 cmd_id_stop;
/* Waiting for host to ack the pages we released. */
wait_queue_head_t acked;
/* Number of balloon pages we've told the Host we're not using. */ unsignedint num_pages; /* * The pages we've told the Host we're not using are enqueued * at vb_dev_info->pages list. * Each page on this list adds VIRTIO_BALLOON_PAGES_PER_PAGE * to num_pages above.
*/ struct balloon_dev_info vb_dev_info;
/* Synchronize access/update to this struct virtio_balloon elements */ struct mutex balloon_lock;
/* The array of pfns we tell the Host about. */ unsignedint num_pfns;
__virtio32 pfns[VIRTIO_BALLOON_ARRAY_PFNS_MAX];
/* State for keeping the wakeup_source active while adjusting the balloon */
spinlock_t wakeup_lock; bool processing_wakeup_event;
u32 wakeup_signal_mask;
};
/* We should always be able to add these buffers to an empty queue. */
err = virtqueue_add_inbuf(vq, sg, nents, vb, GFP_NOWAIT | __GFP_NOWARN);
/* * In the extremely unlikely case that something has occurred and we * are able to trigger an error we will simply display a warning * and exit without actually processing the pages.
*/ if (WARN_ON_ONCE(err)) return err;
virtqueue_kick(vq);
/* When host has read buffer, this completes via balloon_ack */
wait_event(vb->acked, virtqueue_get_buf(vq, &unused));
/* * Set balloon pfns pointing at this page. * Note that the first pfn points at start of the page.
*/ for (i = 0; i < VIRTIO_BALLOON_PAGES_PER_PAGE; i++)
pfns[i] = cpu_to_virtio32(vb->vdev,
page_to_balloon_pfn(page) + i);
}
if (!page) {
dev_info_ratelimited(&vb->vdev->dev, "Out of puff! Can't get %u pages\n",
VIRTIO_BALLOON_PAGES_PER_PAGE); /* Sleep for at least 1/5 of a second before retry. */
msleep(200); break;
}
balloon_page_push(&pages, page);
}
mutex_lock(&vb->balloon_lock);
vb->num_pfns = 0;
while ((page = balloon_page_pop(&pages))) {
balloon_page_enqueue(&vb->vb_dev_info, page);
/* We can only do one array worth at a time. */
num = min(num, ARRAY_SIZE(vb->pfns));
mutex_lock(&vb->balloon_lock); /* We can't release more pages than taken */
num = min(num, (size_t)vb->num_pages); for (vb->num_pfns = 0; vb->num_pfns < num;
vb->num_pfns += VIRTIO_BALLOON_PAGES_PER_PAGE) {
page = balloon_page_dequeue(vb_dev_info); if (!page) break;
set_page_pfns(vb, vb->pfns + vb->num_pfns, page);
list_add(&page->lru, &pages);
vb->num_pages -= VIRTIO_BALLOON_PAGES_PER_PAGE;
}
num_freed_pages = vb->num_pfns; /* * Note that if * virtio_has_feature(vdev, VIRTIO_BALLOON_F_MUST_TELL_HOST); * is true, we *have* to do it in this order
*/ if (vb->num_pfns != 0)
tell_host(vb, vb->deflate_vq);
release_pages_balloon(vb, &pages);
mutex_unlock(&vb->balloon_lock); return num_freed_pages;
}
/* * While most virtqueues communicate guest-initiated requests to the hypervisor, * the stats queue operates in reverse. The driver initializes the virtqueue * with a single buffer. From that point forward, all conversations consist of * a hypervisor request (a call to this function) which directs us to refill * the virtqueue with a fresh stats buffer. Since stats collection can sleep, * we delegate the job to a freezable workqueue that will do the actual work via * stats_handle_request().
*/ staticvoid stats_request(struct virtqueue *vq)
{ struct virtio_balloon *vb = vq->vdev->priv;
/* * Inflateq and deflateq are used unconditionally. The names[] * will be NULL if the related feature is not enabled, which will * cause no allocation for the corresponding virtqueue in find_vqs.
*/
vqs_info[VIRTIO_BALLOON_VQ_INFLATE].callback = balloon_ack;
vqs_info[VIRTIO_BALLOON_VQ_INFLATE].name = "inflate";
vqs_info[VIRTIO_BALLOON_VQ_DEFLATE].callback = balloon_ack;
vqs_info[VIRTIO_BALLOON_VQ_DEFLATE].name = "deflate";
/* * Prime this virtqueue with one buffer so the hypervisor can * use it to signal us later (it can't be broken yet!).
*/
num_stats = update_balloon_stats(vb);
if (virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_FREE_PAGE_HINT))
vb->free_page_vq = vqs[VIRTIO_BALLOON_VQ_FREE_PAGE];
if (virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_REPORTING))
vb->reporting_vq = vqs[VIRTIO_BALLOON_VQ_REPORTING];
return 0;
}
static u32 virtio_balloon_cmd_id_received(struct virtio_balloon *vb)
{ if (test_and_clear_bit(VIRTIO_BALLOON_CONFIG_READ_CMD_ID,
&vb->config_read_bitmap)) { /* Legacy balloon config space is LE, unlike all other devices. */
virtio_cread_le(vb->vdev, struct virtio_balloon_config,
free_page_hint_cmd_id,
&vb->cmd_id_received_cache);
}
/* Detach all the used buffers from the vq */ while (virtqueue_get_buf(vq, &unused))
;
page = alloc_pages(VIRTIO_BALLOON_FREE_PAGE_ALLOC_FLAG,
VIRTIO_BALLOON_HINT_BLOCK_ORDER); /* * When the allocation returns NULL, it indicates that we have got all * the possible free pages, so return -EINTR to stop.
*/ if (!page) return -EINTR;
p = page_address(page);
sg_init_one(&sg, p, VIRTIO_BALLOON_HINT_BLOCK_BYTES); /* There is always 1 entry reserved for the cmd id to use. */ if (vq->num_free > 1) {
err = virtqueue_add_inbuf(vq, &sg, 1, p, GFP_KERNEL); if (unlikely(err)) {
free_pages((unsignedlong)p,
VIRTIO_BALLOON_HINT_BLOCK_ORDER); return err;
}
virtqueue_kick(vq);
spin_lock_irq(&vb->free_page_list_lock);
balloon_page_push(&vb->free_page_list, page);
vb->num_free_page_blocks++;
spin_unlock_irq(&vb->free_page_list_lock);
} else { /* * The vq has no available entry to add this page block, so * just free it.
*/
free_pages((unsignedlong)p, VIRTIO_BALLOON_HINT_BLOCK_ORDER);
}
return 0;
}
staticint send_free_pages(struct virtio_balloon *vb)
{ int err;
u32 cmd_id_active;
while (1) { /* * If a stop id or a new cmd id was just received from host, * stop the reporting.
*/
cmd_id_active = virtio32_to_cpu(vb->vdev, vb->cmd_id_active); if (unlikely(cmd_id_active !=
virtio_balloon_cmd_id_received(vb))) break;
/* * The free page blocks are allocated and sent to host one by * one.
*/
err = get_free_page_and_send(vb); if (err == -EINTR) break; elseif (unlikely(err)) return err;
}
/* Start by sending the received cmd id to host with an outbuf. */
err = send_cmd_id_start(vb); if (unlikely(err))
dev_err(dev, "Failed to send a start id, err = %d\n", err);
err = send_free_pages(vb); if (unlikely(err))
dev_err(dev, "Failed to send a free page, err = %d\n", err);
/* End by sending a stop id to host with an outbuf. */
err = send_cmd_id_stop(vb); if (unlikely(err))
dev_err(dev, "Failed to send a stop id, err = %d\n", err);
}
cmd_id_received = virtio_balloon_cmd_id_received(vb); if (cmd_id_received == VIRTIO_BALLOON_CMD_ID_DONE) { /* Pass ULONG_MAX to give back all the free pages */
return_free_pages_to_mm(vb, ULONG_MAX);
} elseif (cmd_id_received != VIRTIO_BALLOON_CMD_ID_STOP &&
cmd_id_received !=
virtio32_to_cpu(vb->vdev, vb->cmd_id_active)) {
virtio_balloon_report_free_page(vb);
}
}
#ifdef CONFIG_BALLOON_COMPACTION /* * virtballoon_migratepage - perform the balloon page migration on behalf of * a compaction thread. (called under page lock) * @vb_dev_info: the balloon device * @newpage: page that will replace the isolated page after migration finishes. * @page : the isolated (old) page that is about to be migrated to newpage. * @mode : compaction mode -- not used for balloon page migration. * * After a ballooned page gets isolated by compaction procedures, this is the * function that performs the page migration on behalf of a compaction thread * The page migration for virtio balloon is done in a simple swap fashion which * follows these two macro steps: * 1) insert newpage into vb->pages list and update the host about it; * 2) update the host about the old page removed from vb->pages list; * * This function preforms the balloon page migration task. * Called through movable_operations->migrate_page
*/ staticint virtballoon_migratepage(struct balloon_dev_info *vb_dev_info, struct page *newpage, struct page *page, enum migrate_mode mode)
{ struct virtio_balloon *vb = container_of(vb_dev_info, struct virtio_balloon, vb_dev_info); unsignedlong flags;
/* * In order to avoid lock contention while migrating pages concurrently * to leak_balloon() or fill_balloon() we just give up the balloon_lock * this turn, as it is easier to retry the page migration later. * This also prevents fill_balloon() getting stuck into a mutex * recursion in the case it ends up triggering memory compaction * while it is attempting to inflate the ballon.
*/ if (!mutex_trylock(&vb->balloon_lock)) return -EAGAIN;
get_page(newpage); /* balloon reference */
/* * When we migrate a page to a different zone and adjusted the * managed page count when inflating, we have to fixup the count of * both involved zones.
*/ if (!virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_DEFLATE_ON_OOM) &&
page_zone(page) != page_zone(newpage)) {
adjust_managed_page_count(page, 1);
adjust_managed_page_count(newpage, -1);
}
#ifdef CONFIG_BALLOON_COMPACTION
vb->vb_dev_info.migratepage = virtballoon_migratepage; #endif if (virtio_has_feature(vdev, VIRTIO_BALLOON_F_FREE_PAGE_HINT)) { /* * There is always one entry reserved for cmd id, so the ring * size needs to be at least two to report free page hints.
*/ if (virtqueue_get_vring_size(vb->free_page_vq) < 2) {
err = -ENOSPC; goto out_del_vqs;
}
vb->balloon_wq = alloc_workqueue("balloon-wq",
WQ_FREEZABLE | WQ_CPU_INTENSIVE, 0); if (!vb->balloon_wq) {
err = -ENOMEM; goto out_del_vqs;
}
INIT_WORK(&vb->report_free_page_work, report_free_page_func);
vb->cmd_id_received_cache = VIRTIO_BALLOON_CMD_ID_STOP;
vb->cmd_id_active = cpu_to_virtio32(vb->vdev,
VIRTIO_BALLOON_CMD_ID_STOP);
vb->cmd_id_stop = cpu_to_virtio32(vb->vdev,
VIRTIO_BALLOON_CMD_ID_STOP);
spin_lock_init(&vb->free_page_list_lock);
INIT_LIST_HEAD(&vb->free_page_list); /* * We're allowed to reuse any free pages, even if they are * still to be processed by the host.
*/
err = virtio_balloon_register_shrinker(vb); if (err) goto out_del_balloon_wq;
}
if (virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_DEFLATE_ON_OOM)) {
vb->oom_nb.notifier_call = virtio_balloon_oom_notify;
vb->oom_nb.priority = VIRTIO_BALLOON_OOM_NOTIFY_PRIORITY;
err = register_oom_notifier(&vb->oom_nb); if (err < 0) goto out_unregister_shrinker;
}
if (virtio_has_feature(vdev, VIRTIO_BALLOON_F_PAGE_POISON)) { /* Start with poison val of 0 representing general init */
__u32 poison_val = 0;
/* * Let the hypervisor know that we are expecting a * specific value to be written back in balloon pages. * * If the PAGE_POISON value was larger than a byte we would * need to byte swap poison_val here to guarantee it is * little-endian. However for now it is a single byte so we * can pass it as-is.
*/ if (!want_init_on_free())
memset(&poison_val, PAGE_POISON, sizeof(poison_val));
/* * The default page reporting order is @pageblock_order, which * corresponds to 512MB in size on ARM64 when 64KB base page * size is used. The page reporting won't be triggered if the * freeing page can't come up with a free area like that huge. * So we specify the page reporting order to 5, corresponding * to 2MB. It helps to avoid THP splitting if 4KB base page * size is used by host. * * Ideally, the page reporting order is selected based on the * host's base page size. However, it needs more work to report * that value. The hard-coded order would be fine currently.
*/ #ifdefined(CONFIG_ARM64) && defined(CONFIG_ARM64_64K_PAGES)
vb->pr_dev_info.order = 5; #endif
err = page_reporting_register(&vb->pr_dev_info); if (err) goto out_unregister_oom;
}
spin_lock_init(&vb->wakeup_lock);
/* * The virtio balloon itself can't wake up the device, but it is * responsible for processing wakeup events passed up from the transport * layer. Wakeup sources don't support nesting/chaining calls, so we use * our own wakeup source to ensure wakeup events are properly handled * without trampling on the transport layer's wakeup source.
*/
device_set_wakeup_capable(&vb->vdev->dev, true);
virtio_device_ready(vdev);
if (towards_target(vb))
virtballoon_changed(vdev); return 0;
out_unregister_oom: if (virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_DEFLATE_ON_OOM))
unregister_oom_notifier(&vb->oom_nb);
out_unregister_shrinker: if (virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_FREE_PAGE_HINT))
virtio_balloon_unregister_shrinker(vb);
out_del_balloon_wq: if (virtio_has_feature(vdev, VIRTIO_BALLOON_F_FREE_PAGE_HINT))
destroy_workqueue(vb->balloon_wq);
out_del_vqs:
vdev->config->del_vqs(vdev);
out_free_vb:
kfree(vb);
out: return err;
}
staticvoid remove_common(struct virtio_balloon *vb)
{ /* There might be pages left in the balloon: free them. */ while (vb->num_pages)
leak_balloon(vb, vb->num_pages);
update_balloon_size(vb);
/* There might be free pages that are being reported: release them. */ if (virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_FREE_PAGE_HINT))
return_free_pages_to_mm(vb, ULONG_MAX);
/* Now we reset the device so we can clean up the queues. */
virtio_reset_device(vb->vdev);
if (towards_target(vb))
virtballoon_changed(vdev);
update_balloon_size(vb); return 0;
} #endif
staticint virtballoon_validate(struct virtio_device *vdev)
{ /* * Inform the hypervisor that our pages are poisoned or * initialized. If we cannot do that then we should disable * page reporting as it could potentially change the contents * of our free pages.
*/ if (!want_init_on_free() && !page_poisoning_enabled_static())
__virtio_clear_bit(vdev, VIRTIO_BALLOON_F_PAGE_POISON); elseif (!virtio_has_feature(vdev, VIRTIO_BALLOON_F_PAGE_POISON))
__virtio_clear_bit(vdev, VIRTIO_BALLOON_F_REPORTING);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.