18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Virtio balloon implementation, inspired by Dor Laor and Marcelo 48c2ecf20Sopenharmony_ci * Tosatti's implementations. 58c2ecf20Sopenharmony_ci * 68c2ecf20Sopenharmony_ci * Copyright 2008 Rusty Russell IBM Corporation 78c2ecf20Sopenharmony_ci */ 88c2ecf20Sopenharmony_ci 98c2ecf20Sopenharmony_ci#include <linux/virtio.h> 108c2ecf20Sopenharmony_ci#include <linux/virtio_balloon.h> 118c2ecf20Sopenharmony_ci#include <linux/swap.h> 128c2ecf20Sopenharmony_ci#include <linux/workqueue.h> 138c2ecf20Sopenharmony_ci#include <linux/delay.h> 148c2ecf20Sopenharmony_ci#include <linux/slab.h> 158c2ecf20Sopenharmony_ci#include <linux/module.h> 168c2ecf20Sopenharmony_ci#include <linux/balloon_compaction.h> 178c2ecf20Sopenharmony_ci#include <linux/oom.h> 188c2ecf20Sopenharmony_ci#include <linux/wait.h> 198c2ecf20Sopenharmony_ci#include <linux/mm.h> 208c2ecf20Sopenharmony_ci#include <linux/mount.h> 218c2ecf20Sopenharmony_ci#include <linux/magic.h> 228c2ecf20Sopenharmony_ci#include <linux/pseudo_fs.h> 238c2ecf20Sopenharmony_ci#include <linux/page_reporting.h> 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_ci/* 268c2ecf20Sopenharmony_ci * Balloon device works in 4K page units. So each page is pointed to by 278c2ecf20Sopenharmony_ci * multiple balloon pages. All memory counters in this driver are in balloon 288c2ecf20Sopenharmony_ci * page units. 298c2ecf20Sopenharmony_ci */ 308c2ecf20Sopenharmony_ci#define VIRTIO_BALLOON_PAGES_PER_PAGE (unsigned)(PAGE_SIZE >> VIRTIO_BALLOON_PFN_SHIFT) 318c2ecf20Sopenharmony_ci#define VIRTIO_BALLOON_ARRAY_PFNS_MAX 256 328c2ecf20Sopenharmony_ci/* Maximum number of (4k) pages to deflate on OOM notifications. */ 338c2ecf20Sopenharmony_ci#define VIRTIO_BALLOON_OOM_NR_PAGES 256 348c2ecf20Sopenharmony_ci#define VIRTIO_BALLOON_OOM_NOTIFY_PRIORITY 80 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_ci#define VIRTIO_BALLOON_FREE_PAGE_ALLOC_FLAG (__GFP_NORETRY | __GFP_NOWARN | \ 378c2ecf20Sopenharmony_ci __GFP_NOMEMALLOC) 388c2ecf20Sopenharmony_ci/* The order of free page blocks to report to host */ 398c2ecf20Sopenharmony_ci#define VIRTIO_BALLOON_HINT_BLOCK_ORDER (MAX_ORDER - 1) 408c2ecf20Sopenharmony_ci/* The size of a free page block in bytes */ 418c2ecf20Sopenharmony_ci#define VIRTIO_BALLOON_HINT_BLOCK_BYTES \ 428c2ecf20Sopenharmony_ci (1 << (VIRTIO_BALLOON_HINT_BLOCK_ORDER + PAGE_SHIFT)) 438c2ecf20Sopenharmony_ci#define VIRTIO_BALLOON_HINT_BLOCK_PAGES (1 << VIRTIO_BALLOON_HINT_BLOCK_ORDER) 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_ci#ifdef CONFIG_BALLOON_COMPACTION 468c2ecf20Sopenharmony_cistatic struct vfsmount *balloon_mnt; 478c2ecf20Sopenharmony_ci#endif 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_cienum virtio_balloon_vq { 508c2ecf20Sopenharmony_ci VIRTIO_BALLOON_VQ_INFLATE, 518c2ecf20Sopenharmony_ci VIRTIO_BALLOON_VQ_DEFLATE, 528c2ecf20Sopenharmony_ci VIRTIO_BALLOON_VQ_STATS, 538c2ecf20Sopenharmony_ci VIRTIO_BALLOON_VQ_FREE_PAGE, 548c2ecf20Sopenharmony_ci VIRTIO_BALLOON_VQ_REPORTING, 558c2ecf20Sopenharmony_ci VIRTIO_BALLOON_VQ_MAX 568c2ecf20Sopenharmony_ci}; 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_cienum virtio_balloon_config_read { 598c2ecf20Sopenharmony_ci VIRTIO_BALLOON_CONFIG_READ_CMD_ID = 0, 608c2ecf20Sopenharmony_ci}; 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_cistruct virtio_balloon { 638c2ecf20Sopenharmony_ci struct virtio_device *vdev; 648c2ecf20Sopenharmony_ci struct virtqueue *inflate_vq, *deflate_vq, *stats_vq, *free_page_vq; 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_ci /* Balloon's own wq for cpu-intensive work items */ 678c2ecf20Sopenharmony_ci struct workqueue_struct *balloon_wq; 688c2ecf20Sopenharmony_ci /* The free page reporting work item submitted to the balloon wq */ 698c2ecf20Sopenharmony_ci struct work_struct report_free_page_work; 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_ci /* The balloon servicing is delegated to a freezable workqueue. */ 728c2ecf20Sopenharmony_ci struct work_struct update_balloon_stats_work; 738c2ecf20Sopenharmony_ci struct work_struct update_balloon_size_work; 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_ci /* Prevent updating balloon when it is being canceled. */ 768c2ecf20Sopenharmony_ci spinlock_t stop_update_lock; 778c2ecf20Sopenharmony_ci bool stop_update; 788c2ecf20Sopenharmony_ci /* Bitmap to indicate if reading the related config fields are needed */ 798c2ecf20Sopenharmony_ci unsigned long config_read_bitmap; 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_ci /* The list of allocated free pages, waiting to be given back to mm */ 828c2ecf20Sopenharmony_ci struct list_head free_page_list; 838c2ecf20Sopenharmony_ci spinlock_t free_page_list_lock; 848c2ecf20Sopenharmony_ci /* The number of free page blocks on the above list */ 858c2ecf20Sopenharmony_ci unsigned long num_free_page_blocks; 868c2ecf20Sopenharmony_ci /* 878c2ecf20Sopenharmony_ci * The cmd id received from host. 888c2ecf20Sopenharmony_ci * Read it via virtio_balloon_cmd_id_received to get the latest value 898c2ecf20Sopenharmony_ci * sent from host. 908c2ecf20Sopenharmony_ci */ 918c2ecf20Sopenharmony_ci u32 cmd_id_received_cache; 928c2ecf20Sopenharmony_ci /* The cmd id that is actively in use */ 938c2ecf20Sopenharmony_ci __virtio32 cmd_id_active; 948c2ecf20Sopenharmony_ci /* Buffer to store the stop sign */ 958c2ecf20Sopenharmony_ci __virtio32 cmd_id_stop; 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_ci /* Waiting for host to ack the pages we released. */ 988c2ecf20Sopenharmony_ci wait_queue_head_t acked; 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_ci /* Number of balloon pages we've told the Host we're not using. */ 1018c2ecf20Sopenharmony_ci unsigned int num_pages; 1028c2ecf20Sopenharmony_ci /* 1038c2ecf20Sopenharmony_ci * The pages we've told the Host we're not using are enqueued 1048c2ecf20Sopenharmony_ci * at vb_dev_info->pages list. 1058c2ecf20Sopenharmony_ci * Each page on this list adds VIRTIO_BALLOON_PAGES_PER_PAGE 1068c2ecf20Sopenharmony_ci * to num_pages above. 1078c2ecf20Sopenharmony_ci */ 1088c2ecf20Sopenharmony_ci struct balloon_dev_info vb_dev_info; 1098c2ecf20Sopenharmony_ci 1108c2ecf20Sopenharmony_ci /* Synchronize access/update to this struct virtio_balloon elements */ 1118c2ecf20Sopenharmony_ci struct mutex balloon_lock; 1128c2ecf20Sopenharmony_ci 1138c2ecf20Sopenharmony_ci /* The array of pfns we tell the Host about. */ 1148c2ecf20Sopenharmony_ci unsigned int num_pfns; 1158c2ecf20Sopenharmony_ci __virtio32 pfns[VIRTIO_BALLOON_ARRAY_PFNS_MAX]; 1168c2ecf20Sopenharmony_ci 1178c2ecf20Sopenharmony_ci /* Memory statistics */ 1188c2ecf20Sopenharmony_ci struct virtio_balloon_stat stats[VIRTIO_BALLOON_S_NR]; 1198c2ecf20Sopenharmony_ci 1208c2ecf20Sopenharmony_ci /* Shrinker to return free pages - VIRTIO_BALLOON_F_FREE_PAGE_HINT */ 1218c2ecf20Sopenharmony_ci struct shrinker shrinker; 1228c2ecf20Sopenharmony_ci 1238c2ecf20Sopenharmony_ci /* OOM notifier to deflate on OOM - VIRTIO_BALLOON_F_DEFLATE_ON_OOM */ 1248c2ecf20Sopenharmony_ci struct notifier_block oom_nb; 1258c2ecf20Sopenharmony_ci 1268c2ecf20Sopenharmony_ci /* Free page reporting device */ 1278c2ecf20Sopenharmony_ci struct virtqueue *reporting_vq; 1288c2ecf20Sopenharmony_ci struct page_reporting_dev_info pr_dev_info; 1298c2ecf20Sopenharmony_ci}; 1308c2ecf20Sopenharmony_ci 1318c2ecf20Sopenharmony_cistatic const struct virtio_device_id id_table[] = { 1328c2ecf20Sopenharmony_ci { VIRTIO_ID_BALLOON, VIRTIO_DEV_ANY_ID }, 1338c2ecf20Sopenharmony_ci { 0 }, 1348c2ecf20Sopenharmony_ci}; 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_cistatic u32 page_to_balloon_pfn(struct page *page) 1378c2ecf20Sopenharmony_ci{ 1388c2ecf20Sopenharmony_ci unsigned long pfn = page_to_pfn(page); 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_ci BUILD_BUG_ON(PAGE_SHIFT < VIRTIO_BALLOON_PFN_SHIFT); 1418c2ecf20Sopenharmony_ci /* Convert pfn from Linux page size to balloon page size. */ 1428c2ecf20Sopenharmony_ci return pfn * VIRTIO_BALLOON_PAGES_PER_PAGE; 1438c2ecf20Sopenharmony_ci} 1448c2ecf20Sopenharmony_ci 1458c2ecf20Sopenharmony_cistatic void balloon_ack(struct virtqueue *vq) 1468c2ecf20Sopenharmony_ci{ 1478c2ecf20Sopenharmony_ci struct virtio_balloon *vb = vq->vdev->priv; 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_ci wake_up(&vb->acked); 1508c2ecf20Sopenharmony_ci} 1518c2ecf20Sopenharmony_ci 1528c2ecf20Sopenharmony_cistatic void tell_host(struct virtio_balloon *vb, struct virtqueue *vq) 1538c2ecf20Sopenharmony_ci{ 1548c2ecf20Sopenharmony_ci struct scatterlist sg; 1558c2ecf20Sopenharmony_ci unsigned int len; 1568c2ecf20Sopenharmony_ci 1578c2ecf20Sopenharmony_ci sg_init_one(&sg, vb->pfns, sizeof(vb->pfns[0]) * vb->num_pfns); 1588c2ecf20Sopenharmony_ci 1598c2ecf20Sopenharmony_ci /* We should always be able to add one buffer to an empty queue. */ 1608c2ecf20Sopenharmony_ci virtqueue_add_outbuf(vq, &sg, 1, vb, GFP_KERNEL); 1618c2ecf20Sopenharmony_ci virtqueue_kick(vq); 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_ci /* When host has read buffer, this completes via balloon_ack */ 1648c2ecf20Sopenharmony_ci wait_event(vb->acked, virtqueue_get_buf(vq, &len)); 1658c2ecf20Sopenharmony_ci 1668c2ecf20Sopenharmony_ci} 1678c2ecf20Sopenharmony_ci 1688c2ecf20Sopenharmony_cistatic int virtballoon_free_page_report(struct page_reporting_dev_info *pr_dev_info, 1698c2ecf20Sopenharmony_ci struct scatterlist *sg, unsigned int nents) 1708c2ecf20Sopenharmony_ci{ 1718c2ecf20Sopenharmony_ci struct virtio_balloon *vb = 1728c2ecf20Sopenharmony_ci container_of(pr_dev_info, struct virtio_balloon, pr_dev_info); 1738c2ecf20Sopenharmony_ci struct virtqueue *vq = vb->reporting_vq; 1748c2ecf20Sopenharmony_ci unsigned int unused, err; 1758c2ecf20Sopenharmony_ci 1768c2ecf20Sopenharmony_ci /* We should always be able to add these buffers to an empty queue. */ 1778c2ecf20Sopenharmony_ci err = virtqueue_add_inbuf(vq, sg, nents, vb, GFP_NOWAIT | __GFP_NOWARN); 1788c2ecf20Sopenharmony_ci 1798c2ecf20Sopenharmony_ci /* 1808c2ecf20Sopenharmony_ci * In the extremely unlikely case that something has occurred and we 1818c2ecf20Sopenharmony_ci * are able to trigger an error we will simply display a warning 1828c2ecf20Sopenharmony_ci * and exit without actually processing the pages. 1838c2ecf20Sopenharmony_ci */ 1848c2ecf20Sopenharmony_ci if (WARN_ON_ONCE(err)) 1858c2ecf20Sopenharmony_ci return err; 1868c2ecf20Sopenharmony_ci 1878c2ecf20Sopenharmony_ci virtqueue_kick(vq); 1888c2ecf20Sopenharmony_ci 1898c2ecf20Sopenharmony_ci /* When host has read buffer, this completes via balloon_ack */ 1908c2ecf20Sopenharmony_ci wait_event(vb->acked, virtqueue_get_buf(vq, &unused)); 1918c2ecf20Sopenharmony_ci 1928c2ecf20Sopenharmony_ci return 0; 1938c2ecf20Sopenharmony_ci} 1948c2ecf20Sopenharmony_ci 1958c2ecf20Sopenharmony_cistatic void set_page_pfns(struct virtio_balloon *vb, 1968c2ecf20Sopenharmony_ci __virtio32 pfns[], struct page *page) 1978c2ecf20Sopenharmony_ci{ 1988c2ecf20Sopenharmony_ci unsigned int i; 1998c2ecf20Sopenharmony_ci 2008c2ecf20Sopenharmony_ci BUILD_BUG_ON(VIRTIO_BALLOON_PAGES_PER_PAGE > VIRTIO_BALLOON_ARRAY_PFNS_MAX); 2018c2ecf20Sopenharmony_ci 2028c2ecf20Sopenharmony_ci /* 2038c2ecf20Sopenharmony_ci * Set balloon pfns pointing at this page. 2048c2ecf20Sopenharmony_ci * Note that the first pfn points at start of the page. 2058c2ecf20Sopenharmony_ci */ 2068c2ecf20Sopenharmony_ci for (i = 0; i < VIRTIO_BALLOON_PAGES_PER_PAGE; i++) 2078c2ecf20Sopenharmony_ci pfns[i] = cpu_to_virtio32(vb->vdev, 2088c2ecf20Sopenharmony_ci page_to_balloon_pfn(page) + i); 2098c2ecf20Sopenharmony_ci} 2108c2ecf20Sopenharmony_ci 2118c2ecf20Sopenharmony_cistatic unsigned fill_balloon(struct virtio_balloon *vb, size_t num) 2128c2ecf20Sopenharmony_ci{ 2138c2ecf20Sopenharmony_ci unsigned num_allocated_pages; 2148c2ecf20Sopenharmony_ci unsigned num_pfns; 2158c2ecf20Sopenharmony_ci struct page *page; 2168c2ecf20Sopenharmony_ci LIST_HEAD(pages); 2178c2ecf20Sopenharmony_ci 2188c2ecf20Sopenharmony_ci /* We can only do one array worth at a time. */ 2198c2ecf20Sopenharmony_ci num = min(num, ARRAY_SIZE(vb->pfns)); 2208c2ecf20Sopenharmony_ci 2218c2ecf20Sopenharmony_ci for (num_pfns = 0; num_pfns < num; 2228c2ecf20Sopenharmony_ci num_pfns += VIRTIO_BALLOON_PAGES_PER_PAGE) { 2238c2ecf20Sopenharmony_ci struct page *page = balloon_page_alloc(); 2248c2ecf20Sopenharmony_ci 2258c2ecf20Sopenharmony_ci if (!page) { 2268c2ecf20Sopenharmony_ci dev_info_ratelimited(&vb->vdev->dev, 2278c2ecf20Sopenharmony_ci "Out of puff! Can't get %u pages\n", 2288c2ecf20Sopenharmony_ci VIRTIO_BALLOON_PAGES_PER_PAGE); 2298c2ecf20Sopenharmony_ci /* Sleep for at least 1/5 of a second before retry. */ 2308c2ecf20Sopenharmony_ci msleep(200); 2318c2ecf20Sopenharmony_ci break; 2328c2ecf20Sopenharmony_ci } 2338c2ecf20Sopenharmony_ci 2348c2ecf20Sopenharmony_ci balloon_page_push(&pages, page); 2358c2ecf20Sopenharmony_ci } 2368c2ecf20Sopenharmony_ci 2378c2ecf20Sopenharmony_ci mutex_lock(&vb->balloon_lock); 2388c2ecf20Sopenharmony_ci 2398c2ecf20Sopenharmony_ci vb->num_pfns = 0; 2408c2ecf20Sopenharmony_ci 2418c2ecf20Sopenharmony_ci while ((page = balloon_page_pop(&pages))) { 2428c2ecf20Sopenharmony_ci balloon_page_enqueue(&vb->vb_dev_info, page); 2438c2ecf20Sopenharmony_ci 2448c2ecf20Sopenharmony_ci set_page_pfns(vb, vb->pfns + vb->num_pfns, page); 2458c2ecf20Sopenharmony_ci vb->num_pages += VIRTIO_BALLOON_PAGES_PER_PAGE; 2468c2ecf20Sopenharmony_ci if (!virtio_has_feature(vb->vdev, 2478c2ecf20Sopenharmony_ci VIRTIO_BALLOON_F_DEFLATE_ON_OOM)) 2488c2ecf20Sopenharmony_ci adjust_managed_page_count(page, -1); 2498c2ecf20Sopenharmony_ci vb->num_pfns += VIRTIO_BALLOON_PAGES_PER_PAGE; 2508c2ecf20Sopenharmony_ci } 2518c2ecf20Sopenharmony_ci 2528c2ecf20Sopenharmony_ci num_allocated_pages = vb->num_pfns; 2538c2ecf20Sopenharmony_ci /* Did we get any? */ 2548c2ecf20Sopenharmony_ci if (vb->num_pfns != 0) 2558c2ecf20Sopenharmony_ci tell_host(vb, vb->inflate_vq); 2568c2ecf20Sopenharmony_ci mutex_unlock(&vb->balloon_lock); 2578c2ecf20Sopenharmony_ci 2588c2ecf20Sopenharmony_ci return num_allocated_pages; 2598c2ecf20Sopenharmony_ci} 2608c2ecf20Sopenharmony_ci 2618c2ecf20Sopenharmony_cistatic void release_pages_balloon(struct virtio_balloon *vb, 2628c2ecf20Sopenharmony_ci struct list_head *pages) 2638c2ecf20Sopenharmony_ci{ 2648c2ecf20Sopenharmony_ci struct page *page, *next; 2658c2ecf20Sopenharmony_ci 2668c2ecf20Sopenharmony_ci list_for_each_entry_safe(page, next, pages, lru) { 2678c2ecf20Sopenharmony_ci if (!virtio_has_feature(vb->vdev, 2688c2ecf20Sopenharmony_ci VIRTIO_BALLOON_F_DEFLATE_ON_OOM)) 2698c2ecf20Sopenharmony_ci adjust_managed_page_count(page, 1); 2708c2ecf20Sopenharmony_ci list_del(&page->lru); 2718c2ecf20Sopenharmony_ci put_page(page); /* balloon reference */ 2728c2ecf20Sopenharmony_ci } 2738c2ecf20Sopenharmony_ci} 2748c2ecf20Sopenharmony_ci 2758c2ecf20Sopenharmony_cistatic unsigned leak_balloon(struct virtio_balloon *vb, size_t num) 2768c2ecf20Sopenharmony_ci{ 2778c2ecf20Sopenharmony_ci unsigned num_freed_pages; 2788c2ecf20Sopenharmony_ci struct page *page; 2798c2ecf20Sopenharmony_ci struct balloon_dev_info *vb_dev_info = &vb->vb_dev_info; 2808c2ecf20Sopenharmony_ci LIST_HEAD(pages); 2818c2ecf20Sopenharmony_ci 2828c2ecf20Sopenharmony_ci /* We can only do one array worth at a time. */ 2838c2ecf20Sopenharmony_ci num = min(num, ARRAY_SIZE(vb->pfns)); 2848c2ecf20Sopenharmony_ci 2858c2ecf20Sopenharmony_ci mutex_lock(&vb->balloon_lock); 2868c2ecf20Sopenharmony_ci /* We can't release more pages than taken */ 2878c2ecf20Sopenharmony_ci num = min(num, (size_t)vb->num_pages); 2888c2ecf20Sopenharmony_ci for (vb->num_pfns = 0; vb->num_pfns < num; 2898c2ecf20Sopenharmony_ci vb->num_pfns += VIRTIO_BALLOON_PAGES_PER_PAGE) { 2908c2ecf20Sopenharmony_ci page = balloon_page_dequeue(vb_dev_info); 2918c2ecf20Sopenharmony_ci if (!page) 2928c2ecf20Sopenharmony_ci break; 2938c2ecf20Sopenharmony_ci set_page_pfns(vb, vb->pfns + vb->num_pfns, page); 2948c2ecf20Sopenharmony_ci list_add(&page->lru, &pages); 2958c2ecf20Sopenharmony_ci vb->num_pages -= VIRTIO_BALLOON_PAGES_PER_PAGE; 2968c2ecf20Sopenharmony_ci } 2978c2ecf20Sopenharmony_ci 2988c2ecf20Sopenharmony_ci num_freed_pages = vb->num_pfns; 2998c2ecf20Sopenharmony_ci /* 3008c2ecf20Sopenharmony_ci * Note that if 3018c2ecf20Sopenharmony_ci * virtio_has_feature(vdev, VIRTIO_BALLOON_F_MUST_TELL_HOST); 3028c2ecf20Sopenharmony_ci * is true, we *have* to do it in this order 3038c2ecf20Sopenharmony_ci */ 3048c2ecf20Sopenharmony_ci if (vb->num_pfns != 0) 3058c2ecf20Sopenharmony_ci tell_host(vb, vb->deflate_vq); 3068c2ecf20Sopenharmony_ci release_pages_balloon(vb, &pages); 3078c2ecf20Sopenharmony_ci mutex_unlock(&vb->balloon_lock); 3088c2ecf20Sopenharmony_ci return num_freed_pages; 3098c2ecf20Sopenharmony_ci} 3108c2ecf20Sopenharmony_ci 3118c2ecf20Sopenharmony_cistatic inline void update_stat(struct virtio_balloon *vb, int idx, 3128c2ecf20Sopenharmony_ci u16 tag, u64 val) 3138c2ecf20Sopenharmony_ci{ 3148c2ecf20Sopenharmony_ci BUG_ON(idx >= VIRTIO_BALLOON_S_NR); 3158c2ecf20Sopenharmony_ci vb->stats[idx].tag = cpu_to_virtio16(vb->vdev, tag); 3168c2ecf20Sopenharmony_ci vb->stats[idx].val = cpu_to_virtio64(vb->vdev, val); 3178c2ecf20Sopenharmony_ci} 3188c2ecf20Sopenharmony_ci 3198c2ecf20Sopenharmony_ci#define pages_to_bytes(x) ((u64)(x) << PAGE_SHIFT) 3208c2ecf20Sopenharmony_ci 3218c2ecf20Sopenharmony_cistatic unsigned int update_balloon_stats(struct virtio_balloon *vb) 3228c2ecf20Sopenharmony_ci{ 3238c2ecf20Sopenharmony_ci unsigned long events[NR_VM_EVENT_ITEMS]; 3248c2ecf20Sopenharmony_ci struct sysinfo i; 3258c2ecf20Sopenharmony_ci unsigned int idx = 0; 3268c2ecf20Sopenharmony_ci long available; 3278c2ecf20Sopenharmony_ci unsigned long caches; 3288c2ecf20Sopenharmony_ci 3298c2ecf20Sopenharmony_ci all_vm_events(events); 3308c2ecf20Sopenharmony_ci si_meminfo(&i); 3318c2ecf20Sopenharmony_ci 3328c2ecf20Sopenharmony_ci available = si_mem_available(); 3338c2ecf20Sopenharmony_ci caches = global_node_page_state(NR_FILE_PAGES); 3348c2ecf20Sopenharmony_ci 3358c2ecf20Sopenharmony_ci#ifdef CONFIG_VM_EVENT_COUNTERS 3368c2ecf20Sopenharmony_ci update_stat(vb, idx++, VIRTIO_BALLOON_S_SWAP_IN, 3378c2ecf20Sopenharmony_ci pages_to_bytes(events[PSWPIN])); 3388c2ecf20Sopenharmony_ci update_stat(vb, idx++, VIRTIO_BALLOON_S_SWAP_OUT, 3398c2ecf20Sopenharmony_ci pages_to_bytes(events[PSWPOUT])); 3408c2ecf20Sopenharmony_ci update_stat(vb, idx++, VIRTIO_BALLOON_S_MAJFLT, events[PGMAJFAULT]); 3418c2ecf20Sopenharmony_ci update_stat(vb, idx++, VIRTIO_BALLOON_S_MINFLT, events[PGFAULT]); 3428c2ecf20Sopenharmony_ci#ifdef CONFIG_HUGETLB_PAGE 3438c2ecf20Sopenharmony_ci update_stat(vb, idx++, VIRTIO_BALLOON_S_HTLB_PGALLOC, 3448c2ecf20Sopenharmony_ci events[HTLB_BUDDY_PGALLOC]); 3458c2ecf20Sopenharmony_ci update_stat(vb, idx++, VIRTIO_BALLOON_S_HTLB_PGFAIL, 3468c2ecf20Sopenharmony_ci events[HTLB_BUDDY_PGALLOC_FAIL]); 3478c2ecf20Sopenharmony_ci#endif 3488c2ecf20Sopenharmony_ci#endif 3498c2ecf20Sopenharmony_ci update_stat(vb, idx++, VIRTIO_BALLOON_S_MEMFREE, 3508c2ecf20Sopenharmony_ci pages_to_bytes(i.freeram)); 3518c2ecf20Sopenharmony_ci update_stat(vb, idx++, VIRTIO_BALLOON_S_MEMTOT, 3528c2ecf20Sopenharmony_ci pages_to_bytes(i.totalram)); 3538c2ecf20Sopenharmony_ci update_stat(vb, idx++, VIRTIO_BALLOON_S_AVAIL, 3548c2ecf20Sopenharmony_ci pages_to_bytes(available)); 3558c2ecf20Sopenharmony_ci update_stat(vb, idx++, VIRTIO_BALLOON_S_CACHES, 3568c2ecf20Sopenharmony_ci pages_to_bytes(caches)); 3578c2ecf20Sopenharmony_ci 3588c2ecf20Sopenharmony_ci return idx; 3598c2ecf20Sopenharmony_ci} 3608c2ecf20Sopenharmony_ci 3618c2ecf20Sopenharmony_ci/* 3628c2ecf20Sopenharmony_ci * While most virtqueues communicate guest-initiated requests to the hypervisor, 3638c2ecf20Sopenharmony_ci * the stats queue operates in reverse. The driver initializes the virtqueue 3648c2ecf20Sopenharmony_ci * with a single buffer. From that point forward, all conversations consist of 3658c2ecf20Sopenharmony_ci * a hypervisor request (a call to this function) which directs us to refill 3668c2ecf20Sopenharmony_ci * the virtqueue with a fresh stats buffer. Since stats collection can sleep, 3678c2ecf20Sopenharmony_ci * we delegate the job to a freezable workqueue that will do the actual work via 3688c2ecf20Sopenharmony_ci * stats_handle_request(). 3698c2ecf20Sopenharmony_ci */ 3708c2ecf20Sopenharmony_cistatic void stats_request(struct virtqueue *vq) 3718c2ecf20Sopenharmony_ci{ 3728c2ecf20Sopenharmony_ci struct virtio_balloon *vb = vq->vdev->priv; 3738c2ecf20Sopenharmony_ci 3748c2ecf20Sopenharmony_ci spin_lock(&vb->stop_update_lock); 3758c2ecf20Sopenharmony_ci if (!vb->stop_update) 3768c2ecf20Sopenharmony_ci queue_work(system_freezable_wq, &vb->update_balloon_stats_work); 3778c2ecf20Sopenharmony_ci spin_unlock(&vb->stop_update_lock); 3788c2ecf20Sopenharmony_ci} 3798c2ecf20Sopenharmony_ci 3808c2ecf20Sopenharmony_cistatic void stats_handle_request(struct virtio_balloon *vb) 3818c2ecf20Sopenharmony_ci{ 3828c2ecf20Sopenharmony_ci struct virtqueue *vq; 3838c2ecf20Sopenharmony_ci struct scatterlist sg; 3848c2ecf20Sopenharmony_ci unsigned int len, num_stats; 3858c2ecf20Sopenharmony_ci 3868c2ecf20Sopenharmony_ci num_stats = update_balloon_stats(vb); 3878c2ecf20Sopenharmony_ci 3888c2ecf20Sopenharmony_ci vq = vb->stats_vq; 3898c2ecf20Sopenharmony_ci if (!virtqueue_get_buf(vq, &len)) 3908c2ecf20Sopenharmony_ci return; 3918c2ecf20Sopenharmony_ci sg_init_one(&sg, vb->stats, sizeof(vb->stats[0]) * num_stats); 3928c2ecf20Sopenharmony_ci virtqueue_add_outbuf(vq, &sg, 1, vb, GFP_KERNEL); 3938c2ecf20Sopenharmony_ci virtqueue_kick(vq); 3948c2ecf20Sopenharmony_ci} 3958c2ecf20Sopenharmony_ci 3968c2ecf20Sopenharmony_cistatic inline s64 towards_target(struct virtio_balloon *vb) 3978c2ecf20Sopenharmony_ci{ 3988c2ecf20Sopenharmony_ci s64 target; 3998c2ecf20Sopenharmony_ci u32 num_pages; 4008c2ecf20Sopenharmony_ci 4018c2ecf20Sopenharmony_ci /* Legacy balloon config space is LE, unlike all other devices. */ 4028c2ecf20Sopenharmony_ci virtio_cread_le(vb->vdev, struct virtio_balloon_config, num_pages, 4038c2ecf20Sopenharmony_ci &num_pages); 4048c2ecf20Sopenharmony_ci 4058c2ecf20Sopenharmony_ci /* 4068c2ecf20Sopenharmony_ci * Aligned up to guest page size to avoid inflating and deflating 4078c2ecf20Sopenharmony_ci * balloon endlessly. 4088c2ecf20Sopenharmony_ci */ 4098c2ecf20Sopenharmony_ci target = ALIGN(num_pages, VIRTIO_BALLOON_PAGES_PER_PAGE); 4108c2ecf20Sopenharmony_ci return target - vb->num_pages; 4118c2ecf20Sopenharmony_ci} 4128c2ecf20Sopenharmony_ci 4138c2ecf20Sopenharmony_ci/* Gives back @num_to_return blocks of free pages to mm. */ 4148c2ecf20Sopenharmony_cistatic unsigned long return_free_pages_to_mm(struct virtio_balloon *vb, 4158c2ecf20Sopenharmony_ci unsigned long num_to_return) 4168c2ecf20Sopenharmony_ci{ 4178c2ecf20Sopenharmony_ci struct page *page; 4188c2ecf20Sopenharmony_ci unsigned long num_returned; 4198c2ecf20Sopenharmony_ci 4208c2ecf20Sopenharmony_ci spin_lock_irq(&vb->free_page_list_lock); 4218c2ecf20Sopenharmony_ci for (num_returned = 0; num_returned < num_to_return; num_returned++) { 4228c2ecf20Sopenharmony_ci page = balloon_page_pop(&vb->free_page_list); 4238c2ecf20Sopenharmony_ci if (!page) 4248c2ecf20Sopenharmony_ci break; 4258c2ecf20Sopenharmony_ci free_pages((unsigned long)page_address(page), 4268c2ecf20Sopenharmony_ci VIRTIO_BALLOON_HINT_BLOCK_ORDER); 4278c2ecf20Sopenharmony_ci } 4288c2ecf20Sopenharmony_ci vb->num_free_page_blocks -= num_returned; 4298c2ecf20Sopenharmony_ci spin_unlock_irq(&vb->free_page_list_lock); 4308c2ecf20Sopenharmony_ci 4318c2ecf20Sopenharmony_ci return num_returned; 4328c2ecf20Sopenharmony_ci} 4338c2ecf20Sopenharmony_ci 4348c2ecf20Sopenharmony_cistatic void virtio_balloon_queue_free_page_work(struct virtio_balloon *vb) 4358c2ecf20Sopenharmony_ci{ 4368c2ecf20Sopenharmony_ci if (!virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_FREE_PAGE_HINT)) 4378c2ecf20Sopenharmony_ci return; 4388c2ecf20Sopenharmony_ci 4398c2ecf20Sopenharmony_ci /* No need to queue the work if the bit was already set. */ 4408c2ecf20Sopenharmony_ci if (test_and_set_bit(VIRTIO_BALLOON_CONFIG_READ_CMD_ID, 4418c2ecf20Sopenharmony_ci &vb->config_read_bitmap)) 4428c2ecf20Sopenharmony_ci return; 4438c2ecf20Sopenharmony_ci 4448c2ecf20Sopenharmony_ci queue_work(vb->balloon_wq, &vb->report_free_page_work); 4458c2ecf20Sopenharmony_ci} 4468c2ecf20Sopenharmony_ci 4478c2ecf20Sopenharmony_cistatic void virtballoon_changed(struct virtio_device *vdev) 4488c2ecf20Sopenharmony_ci{ 4498c2ecf20Sopenharmony_ci struct virtio_balloon *vb = vdev->priv; 4508c2ecf20Sopenharmony_ci unsigned long flags; 4518c2ecf20Sopenharmony_ci 4528c2ecf20Sopenharmony_ci spin_lock_irqsave(&vb->stop_update_lock, flags); 4538c2ecf20Sopenharmony_ci if (!vb->stop_update) { 4548c2ecf20Sopenharmony_ci queue_work(system_freezable_wq, 4558c2ecf20Sopenharmony_ci &vb->update_balloon_size_work); 4568c2ecf20Sopenharmony_ci virtio_balloon_queue_free_page_work(vb); 4578c2ecf20Sopenharmony_ci } 4588c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&vb->stop_update_lock, flags); 4598c2ecf20Sopenharmony_ci} 4608c2ecf20Sopenharmony_ci 4618c2ecf20Sopenharmony_cistatic void update_balloon_size(struct virtio_balloon *vb) 4628c2ecf20Sopenharmony_ci{ 4638c2ecf20Sopenharmony_ci u32 actual = vb->num_pages; 4648c2ecf20Sopenharmony_ci 4658c2ecf20Sopenharmony_ci /* Legacy balloon config space is LE, unlike all other devices. */ 4668c2ecf20Sopenharmony_ci virtio_cwrite_le(vb->vdev, struct virtio_balloon_config, actual, 4678c2ecf20Sopenharmony_ci &actual); 4688c2ecf20Sopenharmony_ci} 4698c2ecf20Sopenharmony_ci 4708c2ecf20Sopenharmony_cistatic void update_balloon_stats_func(struct work_struct *work) 4718c2ecf20Sopenharmony_ci{ 4728c2ecf20Sopenharmony_ci struct virtio_balloon *vb; 4738c2ecf20Sopenharmony_ci 4748c2ecf20Sopenharmony_ci vb = container_of(work, struct virtio_balloon, 4758c2ecf20Sopenharmony_ci update_balloon_stats_work); 4768c2ecf20Sopenharmony_ci stats_handle_request(vb); 4778c2ecf20Sopenharmony_ci} 4788c2ecf20Sopenharmony_ci 4798c2ecf20Sopenharmony_cistatic void update_balloon_size_func(struct work_struct *work) 4808c2ecf20Sopenharmony_ci{ 4818c2ecf20Sopenharmony_ci struct virtio_balloon *vb; 4828c2ecf20Sopenharmony_ci s64 diff; 4838c2ecf20Sopenharmony_ci 4848c2ecf20Sopenharmony_ci vb = container_of(work, struct virtio_balloon, 4858c2ecf20Sopenharmony_ci update_balloon_size_work); 4868c2ecf20Sopenharmony_ci diff = towards_target(vb); 4878c2ecf20Sopenharmony_ci 4888c2ecf20Sopenharmony_ci if (!diff) 4898c2ecf20Sopenharmony_ci return; 4908c2ecf20Sopenharmony_ci 4918c2ecf20Sopenharmony_ci if (diff > 0) 4928c2ecf20Sopenharmony_ci diff -= fill_balloon(vb, diff); 4938c2ecf20Sopenharmony_ci else 4948c2ecf20Sopenharmony_ci diff += leak_balloon(vb, -diff); 4958c2ecf20Sopenharmony_ci update_balloon_size(vb); 4968c2ecf20Sopenharmony_ci 4978c2ecf20Sopenharmony_ci if (diff) 4988c2ecf20Sopenharmony_ci queue_work(system_freezable_wq, work); 4998c2ecf20Sopenharmony_ci} 5008c2ecf20Sopenharmony_ci 5018c2ecf20Sopenharmony_cistatic int init_vqs(struct virtio_balloon *vb) 5028c2ecf20Sopenharmony_ci{ 5038c2ecf20Sopenharmony_ci struct virtqueue *vqs[VIRTIO_BALLOON_VQ_MAX]; 5048c2ecf20Sopenharmony_ci vq_callback_t *callbacks[VIRTIO_BALLOON_VQ_MAX]; 5058c2ecf20Sopenharmony_ci const char *names[VIRTIO_BALLOON_VQ_MAX]; 5068c2ecf20Sopenharmony_ci int err; 5078c2ecf20Sopenharmony_ci 5088c2ecf20Sopenharmony_ci /* 5098c2ecf20Sopenharmony_ci * Inflateq and deflateq are used unconditionally. The names[] 5108c2ecf20Sopenharmony_ci * will be NULL if the related feature is not enabled, which will 5118c2ecf20Sopenharmony_ci * cause no allocation for the corresponding virtqueue in find_vqs. 5128c2ecf20Sopenharmony_ci */ 5138c2ecf20Sopenharmony_ci callbacks[VIRTIO_BALLOON_VQ_INFLATE] = balloon_ack; 5148c2ecf20Sopenharmony_ci names[VIRTIO_BALLOON_VQ_INFLATE] = "inflate"; 5158c2ecf20Sopenharmony_ci callbacks[VIRTIO_BALLOON_VQ_DEFLATE] = balloon_ack; 5168c2ecf20Sopenharmony_ci names[VIRTIO_BALLOON_VQ_DEFLATE] = "deflate"; 5178c2ecf20Sopenharmony_ci callbacks[VIRTIO_BALLOON_VQ_STATS] = NULL; 5188c2ecf20Sopenharmony_ci names[VIRTIO_BALLOON_VQ_STATS] = NULL; 5198c2ecf20Sopenharmony_ci callbacks[VIRTIO_BALLOON_VQ_FREE_PAGE] = NULL; 5208c2ecf20Sopenharmony_ci names[VIRTIO_BALLOON_VQ_FREE_PAGE] = NULL; 5218c2ecf20Sopenharmony_ci names[VIRTIO_BALLOON_VQ_REPORTING] = NULL; 5228c2ecf20Sopenharmony_ci 5238c2ecf20Sopenharmony_ci if (virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_STATS_VQ)) { 5248c2ecf20Sopenharmony_ci names[VIRTIO_BALLOON_VQ_STATS] = "stats"; 5258c2ecf20Sopenharmony_ci callbacks[VIRTIO_BALLOON_VQ_STATS] = stats_request; 5268c2ecf20Sopenharmony_ci } 5278c2ecf20Sopenharmony_ci 5288c2ecf20Sopenharmony_ci if (virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_FREE_PAGE_HINT)) { 5298c2ecf20Sopenharmony_ci names[VIRTIO_BALLOON_VQ_FREE_PAGE] = "free_page_vq"; 5308c2ecf20Sopenharmony_ci callbacks[VIRTIO_BALLOON_VQ_FREE_PAGE] = NULL; 5318c2ecf20Sopenharmony_ci } 5328c2ecf20Sopenharmony_ci 5338c2ecf20Sopenharmony_ci if (virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_REPORTING)) { 5348c2ecf20Sopenharmony_ci names[VIRTIO_BALLOON_VQ_REPORTING] = "reporting_vq"; 5358c2ecf20Sopenharmony_ci callbacks[VIRTIO_BALLOON_VQ_REPORTING] = balloon_ack; 5368c2ecf20Sopenharmony_ci } 5378c2ecf20Sopenharmony_ci 5388c2ecf20Sopenharmony_ci err = vb->vdev->config->find_vqs(vb->vdev, VIRTIO_BALLOON_VQ_MAX, 5398c2ecf20Sopenharmony_ci vqs, callbacks, names, NULL, NULL); 5408c2ecf20Sopenharmony_ci if (err) 5418c2ecf20Sopenharmony_ci return err; 5428c2ecf20Sopenharmony_ci 5438c2ecf20Sopenharmony_ci vb->inflate_vq = vqs[VIRTIO_BALLOON_VQ_INFLATE]; 5448c2ecf20Sopenharmony_ci vb->deflate_vq = vqs[VIRTIO_BALLOON_VQ_DEFLATE]; 5458c2ecf20Sopenharmony_ci if (virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_STATS_VQ)) { 5468c2ecf20Sopenharmony_ci struct scatterlist sg; 5478c2ecf20Sopenharmony_ci unsigned int num_stats; 5488c2ecf20Sopenharmony_ci vb->stats_vq = vqs[VIRTIO_BALLOON_VQ_STATS]; 5498c2ecf20Sopenharmony_ci 5508c2ecf20Sopenharmony_ci /* 5518c2ecf20Sopenharmony_ci * Prime this virtqueue with one buffer so the hypervisor can 5528c2ecf20Sopenharmony_ci * use it to signal us later (it can't be broken yet!). 5538c2ecf20Sopenharmony_ci */ 5548c2ecf20Sopenharmony_ci num_stats = update_balloon_stats(vb); 5558c2ecf20Sopenharmony_ci 5568c2ecf20Sopenharmony_ci sg_init_one(&sg, vb->stats, sizeof(vb->stats[0]) * num_stats); 5578c2ecf20Sopenharmony_ci err = virtqueue_add_outbuf(vb->stats_vq, &sg, 1, vb, 5588c2ecf20Sopenharmony_ci GFP_KERNEL); 5598c2ecf20Sopenharmony_ci if (err) { 5608c2ecf20Sopenharmony_ci dev_warn(&vb->vdev->dev, "%s: add stat_vq failed\n", 5618c2ecf20Sopenharmony_ci __func__); 5628c2ecf20Sopenharmony_ci return err; 5638c2ecf20Sopenharmony_ci } 5648c2ecf20Sopenharmony_ci virtqueue_kick(vb->stats_vq); 5658c2ecf20Sopenharmony_ci } 5668c2ecf20Sopenharmony_ci 5678c2ecf20Sopenharmony_ci if (virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_FREE_PAGE_HINT)) 5688c2ecf20Sopenharmony_ci vb->free_page_vq = vqs[VIRTIO_BALLOON_VQ_FREE_PAGE]; 5698c2ecf20Sopenharmony_ci 5708c2ecf20Sopenharmony_ci if (virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_REPORTING)) 5718c2ecf20Sopenharmony_ci vb->reporting_vq = vqs[VIRTIO_BALLOON_VQ_REPORTING]; 5728c2ecf20Sopenharmony_ci 5738c2ecf20Sopenharmony_ci return 0; 5748c2ecf20Sopenharmony_ci} 5758c2ecf20Sopenharmony_ci 5768c2ecf20Sopenharmony_cistatic u32 virtio_balloon_cmd_id_received(struct virtio_balloon *vb) 5778c2ecf20Sopenharmony_ci{ 5788c2ecf20Sopenharmony_ci if (test_and_clear_bit(VIRTIO_BALLOON_CONFIG_READ_CMD_ID, 5798c2ecf20Sopenharmony_ci &vb->config_read_bitmap)) { 5808c2ecf20Sopenharmony_ci /* Legacy balloon config space is LE, unlike all other devices. */ 5818c2ecf20Sopenharmony_ci virtio_cread_le(vb->vdev, struct virtio_balloon_config, 5828c2ecf20Sopenharmony_ci free_page_hint_cmd_id, 5838c2ecf20Sopenharmony_ci &vb->cmd_id_received_cache); 5848c2ecf20Sopenharmony_ci } 5858c2ecf20Sopenharmony_ci 5868c2ecf20Sopenharmony_ci return vb->cmd_id_received_cache; 5878c2ecf20Sopenharmony_ci} 5888c2ecf20Sopenharmony_ci 5898c2ecf20Sopenharmony_cistatic int send_cmd_id_start(struct virtio_balloon *vb) 5908c2ecf20Sopenharmony_ci{ 5918c2ecf20Sopenharmony_ci struct scatterlist sg; 5928c2ecf20Sopenharmony_ci struct virtqueue *vq = vb->free_page_vq; 5938c2ecf20Sopenharmony_ci int err, unused; 5948c2ecf20Sopenharmony_ci 5958c2ecf20Sopenharmony_ci /* Detach all the used buffers from the vq */ 5968c2ecf20Sopenharmony_ci while (virtqueue_get_buf(vq, &unused)) 5978c2ecf20Sopenharmony_ci ; 5988c2ecf20Sopenharmony_ci 5998c2ecf20Sopenharmony_ci vb->cmd_id_active = cpu_to_virtio32(vb->vdev, 6008c2ecf20Sopenharmony_ci virtio_balloon_cmd_id_received(vb)); 6018c2ecf20Sopenharmony_ci sg_init_one(&sg, &vb->cmd_id_active, sizeof(vb->cmd_id_active)); 6028c2ecf20Sopenharmony_ci err = virtqueue_add_outbuf(vq, &sg, 1, &vb->cmd_id_active, GFP_KERNEL); 6038c2ecf20Sopenharmony_ci if (!err) 6048c2ecf20Sopenharmony_ci virtqueue_kick(vq); 6058c2ecf20Sopenharmony_ci return err; 6068c2ecf20Sopenharmony_ci} 6078c2ecf20Sopenharmony_ci 6088c2ecf20Sopenharmony_cistatic int send_cmd_id_stop(struct virtio_balloon *vb) 6098c2ecf20Sopenharmony_ci{ 6108c2ecf20Sopenharmony_ci struct scatterlist sg; 6118c2ecf20Sopenharmony_ci struct virtqueue *vq = vb->free_page_vq; 6128c2ecf20Sopenharmony_ci int err, unused; 6138c2ecf20Sopenharmony_ci 6148c2ecf20Sopenharmony_ci /* Detach all the used buffers from the vq */ 6158c2ecf20Sopenharmony_ci while (virtqueue_get_buf(vq, &unused)) 6168c2ecf20Sopenharmony_ci ; 6178c2ecf20Sopenharmony_ci 6188c2ecf20Sopenharmony_ci sg_init_one(&sg, &vb->cmd_id_stop, sizeof(vb->cmd_id_stop)); 6198c2ecf20Sopenharmony_ci err = virtqueue_add_outbuf(vq, &sg, 1, &vb->cmd_id_stop, GFP_KERNEL); 6208c2ecf20Sopenharmony_ci if (!err) 6218c2ecf20Sopenharmony_ci virtqueue_kick(vq); 6228c2ecf20Sopenharmony_ci return err; 6238c2ecf20Sopenharmony_ci} 6248c2ecf20Sopenharmony_ci 6258c2ecf20Sopenharmony_cistatic int get_free_page_and_send(struct virtio_balloon *vb) 6268c2ecf20Sopenharmony_ci{ 6278c2ecf20Sopenharmony_ci struct virtqueue *vq = vb->free_page_vq; 6288c2ecf20Sopenharmony_ci struct page *page; 6298c2ecf20Sopenharmony_ci struct scatterlist sg; 6308c2ecf20Sopenharmony_ci int err, unused; 6318c2ecf20Sopenharmony_ci void *p; 6328c2ecf20Sopenharmony_ci 6338c2ecf20Sopenharmony_ci /* Detach all the used buffers from the vq */ 6348c2ecf20Sopenharmony_ci while (virtqueue_get_buf(vq, &unused)) 6358c2ecf20Sopenharmony_ci ; 6368c2ecf20Sopenharmony_ci 6378c2ecf20Sopenharmony_ci page = alloc_pages(VIRTIO_BALLOON_FREE_PAGE_ALLOC_FLAG, 6388c2ecf20Sopenharmony_ci VIRTIO_BALLOON_HINT_BLOCK_ORDER); 6398c2ecf20Sopenharmony_ci /* 6408c2ecf20Sopenharmony_ci * When the allocation returns NULL, it indicates that we have got all 6418c2ecf20Sopenharmony_ci * the possible free pages, so return -EINTR to stop. 6428c2ecf20Sopenharmony_ci */ 6438c2ecf20Sopenharmony_ci if (!page) 6448c2ecf20Sopenharmony_ci return -EINTR; 6458c2ecf20Sopenharmony_ci 6468c2ecf20Sopenharmony_ci p = page_address(page); 6478c2ecf20Sopenharmony_ci sg_init_one(&sg, p, VIRTIO_BALLOON_HINT_BLOCK_BYTES); 6488c2ecf20Sopenharmony_ci /* There is always 1 entry reserved for the cmd id to use. */ 6498c2ecf20Sopenharmony_ci if (vq->num_free > 1) { 6508c2ecf20Sopenharmony_ci err = virtqueue_add_inbuf(vq, &sg, 1, p, GFP_KERNEL); 6518c2ecf20Sopenharmony_ci if (unlikely(err)) { 6528c2ecf20Sopenharmony_ci free_pages((unsigned long)p, 6538c2ecf20Sopenharmony_ci VIRTIO_BALLOON_HINT_BLOCK_ORDER); 6548c2ecf20Sopenharmony_ci return err; 6558c2ecf20Sopenharmony_ci } 6568c2ecf20Sopenharmony_ci virtqueue_kick(vq); 6578c2ecf20Sopenharmony_ci spin_lock_irq(&vb->free_page_list_lock); 6588c2ecf20Sopenharmony_ci balloon_page_push(&vb->free_page_list, page); 6598c2ecf20Sopenharmony_ci vb->num_free_page_blocks++; 6608c2ecf20Sopenharmony_ci spin_unlock_irq(&vb->free_page_list_lock); 6618c2ecf20Sopenharmony_ci } else { 6628c2ecf20Sopenharmony_ci /* 6638c2ecf20Sopenharmony_ci * The vq has no available entry to add this page block, so 6648c2ecf20Sopenharmony_ci * just free it. 6658c2ecf20Sopenharmony_ci */ 6668c2ecf20Sopenharmony_ci free_pages((unsigned long)p, VIRTIO_BALLOON_HINT_BLOCK_ORDER); 6678c2ecf20Sopenharmony_ci } 6688c2ecf20Sopenharmony_ci 6698c2ecf20Sopenharmony_ci return 0; 6708c2ecf20Sopenharmony_ci} 6718c2ecf20Sopenharmony_ci 6728c2ecf20Sopenharmony_cistatic int send_free_pages(struct virtio_balloon *vb) 6738c2ecf20Sopenharmony_ci{ 6748c2ecf20Sopenharmony_ci int err; 6758c2ecf20Sopenharmony_ci u32 cmd_id_active; 6768c2ecf20Sopenharmony_ci 6778c2ecf20Sopenharmony_ci while (1) { 6788c2ecf20Sopenharmony_ci /* 6798c2ecf20Sopenharmony_ci * If a stop id or a new cmd id was just received from host, 6808c2ecf20Sopenharmony_ci * stop the reporting. 6818c2ecf20Sopenharmony_ci */ 6828c2ecf20Sopenharmony_ci cmd_id_active = virtio32_to_cpu(vb->vdev, vb->cmd_id_active); 6838c2ecf20Sopenharmony_ci if (unlikely(cmd_id_active != 6848c2ecf20Sopenharmony_ci virtio_balloon_cmd_id_received(vb))) 6858c2ecf20Sopenharmony_ci break; 6868c2ecf20Sopenharmony_ci 6878c2ecf20Sopenharmony_ci /* 6888c2ecf20Sopenharmony_ci * The free page blocks are allocated and sent to host one by 6898c2ecf20Sopenharmony_ci * one. 6908c2ecf20Sopenharmony_ci */ 6918c2ecf20Sopenharmony_ci err = get_free_page_and_send(vb); 6928c2ecf20Sopenharmony_ci if (err == -EINTR) 6938c2ecf20Sopenharmony_ci break; 6948c2ecf20Sopenharmony_ci else if (unlikely(err)) 6958c2ecf20Sopenharmony_ci return err; 6968c2ecf20Sopenharmony_ci } 6978c2ecf20Sopenharmony_ci 6988c2ecf20Sopenharmony_ci return 0; 6998c2ecf20Sopenharmony_ci} 7008c2ecf20Sopenharmony_ci 7018c2ecf20Sopenharmony_cistatic void virtio_balloon_report_free_page(struct virtio_balloon *vb) 7028c2ecf20Sopenharmony_ci{ 7038c2ecf20Sopenharmony_ci int err; 7048c2ecf20Sopenharmony_ci struct device *dev = &vb->vdev->dev; 7058c2ecf20Sopenharmony_ci 7068c2ecf20Sopenharmony_ci /* Start by sending the received cmd id to host with an outbuf. */ 7078c2ecf20Sopenharmony_ci err = send_cmd_id_start(vb); 7088c2ecf20Sopenharmony_ci if (unlikely(err)) 7098c2ecf20Sopenharmony_ci dev_err(dev, "Failed to send a start id, err = %d\n", err); 7108c2ecf20Sopenharmony_ci 7118c2ecf20Sopenharmony_ci err = send_free_pages(vb); 7128c2ecf20Sopenharmony_ci if (unlikely(err)) 7138c2ecf20Sopenharmony_ci dev_err(dev, "Failed to send a free page, err = %d\n", err); 7148c2ecf20Sopenharmony_ci 7158c2ecf20Sopenharmony_ci /* End by sending a stop id to host with an outbuf. */ 7168c2ecf20Sopenharmony_ci err = send_cmd_id_stop(vb); 7178c2ecf20Sopenharmony_ci if (unlikely(err)) 7188c2ecf20Sopenharmony_ci dev_err(dev, "Failed to send a stop id, err = %d\n", err); 7198c2ecf20Sopenharmony_ci} 7208c2ecf20Sopenharmony_ci 7218c2ecf20Sopenharmony_cistatic void report_free_page_func(struct work_struct *work) 7228c2ecf20Sopenharmony_ci{ 7238c2ecf20Sopenharmony_ci struct virtio_balloon *vb = container_of(work, struct virtio_balloon, 7248c2ecf20Sopenharmony_ci report_free_page_work); 7258c2ecf20Sopenharmony_ci u32 cmd_id_received; 7268c2ecf20Sopenharmony_ci 7278c2ecf20Sopenharmony_ci cmd_id_received = virtio_balloon_cmd_id_received(vb); 7288c2ecf20Sopenharmony_ci if (cmd_id_received == VIRTIO_BALLOON_CMD_ID_DONE) { 7298c2ecf20Sopenharmony_ci /* Pass ULONG_MAX to give back all the free pages */ 7308c2ecf20Sopenharmony_ci return_free_pages_to_mm(vb, ULONG_MAX); 7318c2ecf20Sopenharmony_ci } else if (cmd_id_received != VIRTIO_BALLOON_CMD_ID_STOP && 7328c2ecf20Sopenharmony_ci cmd_id_received != 7338c2ecf20Sopenharmony_ci virtio32_to_cpu(vb->vdev, vb->cmd_id_active)) { 7348c2ecf20Sopenharmony_ci virtio_balloon_report_free_page(vb); 7358c2ecf20Sopenharmony_ci } 7368c2ecf20Sopenharmony_ci} 7378c2ecf20Sopenharmony_ci 7388c2ecf20Sopenharmony_ci#ifdef CONFIG_BALLOON_COMPACTION 7398c2ecf20Sopenharmony_ci/* 7408c2ecf20Sopenharmony_ci * virtballoon_migratepage - perform the balloon page migration on behalf of 7418c2ecf20Sopenharmony_ci * a compation thread. (called under page lock) 7428c2ecf20Sopenharmony_ci * @vb_dev_info: the balloon device 7438c2ecf20Sopenharmony_ci * @newpage: page that will replace the isolated page after migration finishes. 7448c2ecf20Sopenharmony_ci * @page : the isolated (old) page that is about to be migrated to newpage. 7458c2ecf20Sopenharmony_ci * @mode : compaction mode -- not used for balloon page migration. 7468c2ecf20Sopenharmony_ci * 7478c2ecf20Sopenharmony_ci * After a ballooned page gets isolated by compaction procedures, this is the 7488c2ecf20Sopenharmony_ci * function that performs the page migration on behalf of a compaction thread 7498c2ecf20Sopenharmony_ci * The page migration for virtio balloon is done in a simple swap fashion which 7508c2ecf20Sopenharmony_ci * follows these two macro steps: 7518c2ecf20Sopenharmony_ci * 1) insert newpage into vb->pages list and update the host about it; 7528c2ecf20Sopenharmony_ci * 2) update the host about the old page removed from vb->pages list; 7538c2ecf20Sopenharmony_ci * 7548c2ecf20Sopenharmony_ci * This function preforms the balloon page migration task. 7558c2ecf20Sopenharmony_ci * Called through balloon_mapping->a_ops->migratepage 7568c2ecf20Sopenharmony_ci */ 7578c2ecf20Sopenharmony_cistatic int virtballoon_migratepage(struct balloon_dev_info *vb_dev_info, 7588c2ecf20Sopenharmony_ci struct page *newpage, struct page *page, enum migrate_mode mode) 7598c2ecf20Sopenharmony_ci{ 7608c2ecf20Sopenharmony_ci struct virtio_balloon *vb = container_of(vb_dev_info, 7618c2ecf20Sopenharmony_ci struct virtio_balloon, vb_dev_info); 7628c2ecf20Sopenharmony_ci unsigned long flags; 7638c2ecf20Sopenharmony_ci 7648c2ecf20Sopenharmony_ci /* 7658c2ecf20Sopenharmony_ci * In order to avoid lock contention while migrating pages concurrently 7668c2ecf20Sopenharmony_ci * to leak_balloon() or fill_balloon() we just give up the balloon_lock 7678c2ecf20Sopenharmony_ci * this turn, as it is easier to retry the page migration later. 7688c2ecf20Sopenharmony_ci * This also prevents fill_balloon() getting stuck into a mutex 7698c2ecf20Sopenharmony_ci * recursion in the case it ends up triggering memory compaction 7708c2ecf20Sopenharmony_ci * while it is attempting to inflate the ballon. 7718c2ecf20Sopenharmony_ci */ 7728c2ecf20Sopenharmony_ci if (!mutex_trylock(&vb->balloon_lock)) 7738c2ecf20Sopenharmony_ci return -EAGAIN; 7748c2ecf20Sopenharmony_ci 7758c2ecf20Sopenharmony_ci get_page(newpage); /* balloon reference */ 7768c2ecf20Sopenharmony_ci 7778c2ecf20Sopenharmony_ci /* 7788c2ecf20Sopenharmony_ci * When we migrate a page to a different zone and adjusted the 7798c2ecf20Sopenharmony_ci * managed page count when inflating, we have to fixup the count of 7808c2ecf20Sopenharmony_ci * both involved zones. 7818c2ecf20Sopenharmony_ci */ 7828c2ecf20Sopenharmony_ci if (!virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_DEFLATE_ON_OOM) && 7838c2ecf20Sopenharmony_ci page_zone(page) != page_zone(newpage)) { 7848c2ecf20Sopenharmony_ci adjust_managed_page_count(page, 1); 7858c2ecf20Sopenharmony_ci adjust_managed_page_count(newpage, -1); 7868c2ecf20Sopenharmony_ci } 7878c2ecf20Sopenharmony_ci 7888c2ecf20Sopenharmony_ci /* balloon's page migration 1st step -- inflate "newpage" */ 7898c2ecf20Sopenharmony_ci spin_lock_irqsave(&vb_dev_info->pages_lock, flags); 7908c2ecf20Sopenharmony_ci balloon_page_insert(vb_dev_info, newpage); 7918c2ecf20Sopenharmony_ci vb_dev_info->isolated_pages--; 7928c2ecf20Sopenharmony_ci __count_vm_event(BALLOON_MIGRATE); 7938c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&vb_dev_info->pages_lock, flags); 7948c2ecf20Sopenharmony_ci vb->num_pfns = VIRTIO_BALLOON_PAGES_PER_PAGE; 7958c2ecf20Sopenharmony_ci set_page_pfns(vb, vb->pfns, newpage); 7968c2ecf20Sopenharmony_ci tell_host(vb, vb->inflate_vq); 7978c2ecf20Sopenharmony_ci 7988c2ecf20Sopenharmony_ci /* balloon's page migration 2nd step -- deflate "page" */ 7998c2ecf20Sopenharmony_ci spin_lock_irqsave(&vb_dev_info->pages_lock, flags); 8008c2ecf20Sopenharmony_ci balloon_page_delete(page); 8018c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&vb_dev_info->pages_lock, flags); 8028c2ecf20Sopenharmony_ci vb->num_pfns = VIRTIO_BALLOON_PAGES_PER_PAGE; 8038c2ecf20Sopenharmony_ci set_page_pfns(vb, vb->pfns, page); 8048c2ecf20Sopenharmony_ci tell_host(vb, vb->deflate_vq); 8058c2ecf20Sopenharmony_ci 8068c2ecf20Sopenharmony_ci mutex_unlock(&vb->balloon_lock); 8078c2ecf20Sopenharmony_ci 8088c2ecf20Sopenharmony_ci put_page(page); /* balloon reference */ 8098c2ecf20Sopenharmony_ci 8108c2ecf20Sopenharmony_ci return MIGRATEPAGE_SUCCESS; 8118c2ecf20Sopenharmony_ci} 8128c2ecf20Sopenharmony_ci 8138c2ecf20Sopenharmony_cistatic int balloon_init_fs_context(struct fs_context *fc) 8148c2ecf20Sopenharmony_ci{ 8158c2ecf20Sopenharmony_ci return init_pseudo(fc, BALLOON_KVM_MAGIC) ? 0 : -ENOMEM; 8168c2ecf20Sopenharmony_ci} 8178c2ecf20Sopenharmony_ci 8188c2ecf20Sopenharmony_cistatic struct file_system_type balloon_fs = { 8198c2ecf20Sopenharmony_ci .name = "balloon-kvm", 8208c2ecf20Sopenharmony_ci .init_fs_context = balloon_init_fs_context, 8218c2ecf20Sopenharmony_ci .kill_sb = kill_anon_super, 8228c2ecf20Sopenharmony_ci}; 8238c2ecf20Sopenharmony_ci 8248c2ecf20Sopenharmony_ci#endif /* CONFIG_BALLOON_COMPACTION */ 8258c2ecf20Sopenharmony_ci 8268c2ecf20Sopenharmony_cistatic unsigned long shrink_free_pages(struct virtio_balloon *vb, 8278c2ecf20Sopenharmony_ci unsigned long pages_to_free) 8288c2ecf20Sopenharmony_ci{ 8298c2ecf20Sopenharmony_ci unsigned long blocks_to_free, blocks_freed; 8308c2ecf20Sopenharmony_ci 8318c2ecf20Sopenharmony_ci pages_to_free = round_up(pages_to_free, 8328c2ecf20Sopenharmony_ci VIRTIO_BALLOON_HINT_BLOCK_PAGES); 8338c2ecf20Sopenharmony_ci blocks_to_free = pages_to_free / VIRTIO_BALLOON_HINT_BLOCK_PAGES; 8348c2ecf20Sopenharmony_ci blocks_freed = return_free_pages_to_mm(vb, blocks_to_free); 8358c2ecf20Sopenharmony_ci 8368c2ecf20Sopenharmony_ci return blocks_freed * VIRTIO_BALLOON_HINT_BLOCK_PAGES; 8378c2ecf20Sopenharmony_ci} 8388c2ecf20Sopenharmony_ci 8398c2ecf20Sopenharmony_cistatic unsigned long virtio_balloon_shrinker_scan(struct shrinker *shrinker, 8408c2ecf20Sopenharmony_ci struct shrink_control *sc) 8418c2ecf20Sopenharmony_ci{ 8428c2ecf20Sopenharmony_ci struct virtio_balloon *vb = container_of(shrinker, 8438c2ecf20Sopenharmony_ci struct virtio_balloon, shrinker); 8448c2ecf20Sopenharmony_ci 8458c2ecf20Sopenharmony_ci return shrink_free_pages(vb, sc->nr_to_scan); 8468c2ecf20Sopenharmony_ci} 8478c2ecf20Sopenharmony_ci 8488c2ecf20Sopenharmony_cistatic unsigned long virtio_balloon_shrinker_count(struct shrinker *shrinker, 8498c2ecf20Sopenharmony_ci struct shrink_control *sc) 8508c2ecf20Sopenharmony_ci{ 8518c2ecf20Sopenharmony_ci struct virtio_balloon *vb = container_of(shrinker, 8528c2ecf20Sopenharmony_ci struct virtio_balloon, shrinker); 8538c2ecf20Sopenharmony_ci 8548c2ecf20Sopenharmony_ci return vb->num_free_page_blocks * VIRTIO_BALLOON_HINT_BLOCK_PAGES; 8558c2ecf20Sopenharmony_ci} 8568c2ecf20Sopenharmony_ci 8578c2ecf20Sopenharmony_cistatic int virtio_balloon_oom_notify(struct notifier_block *nb, 8588c2ecf20Sopenharmony_ci unsigned long dummy, void *parm) 8598c2ecf20Sopenharmony_ci{ 8608c2ecf20Sopenharmony_ci struct virtio_balloon *vb = container_of(nb, 8618c2ecf20Sopenharmony_ci struct virtio_balloon, oom_nb); 8628c2ecf20Sopenharmony_ci unsigned long *freed = parm; 8638c2ecf20Sopenharmony_ci 8648c2ecf20Sopenharmony_ci *freed += leak_balloon(vb, VIRTIO_BALLOON_OOM_NR_PAGES) / 8658c2ecf20Sopenharmony_ci VIRTIO_BALLOON_PAGES_PER_PAGE; 8668c2ecf20Sopenharmony_ci update_balloon_size(vb); 8678c2ecf20Sopenharmony_ci 8688c2ecf20Sopenharmony_ci return NOTIFY_OK; 8698c2ecf20Sopenharmony_ci} 8708c2ecf20Sopenharmony_ci 8718c2ecf20Sopenharmony_cistatic void virtio_balloon_unregister_shrinker(struct virtio_balloon *vb) 8728c2ecf20Sopenharmony_ci{ 8738c2ecf20Sopenharmony_ci unregister_shrinker(&vb->shrinker); 8748c2ecf20Sopenharmony_ci} 8758c2ecf20Sopenharmony_ci 8768c2ecf20Sopenharmony_cistatic int virtio_balloon_register_shrinker(struct virtio_balloon *vb) 8778c2ecf20Sopenharmony_ci{ 8788c2ecf20Sopenharmony_ci vb->shrinker.scan_objects = virtio_balloon_shrinker_scan; 8798c2ecf20Sopenharmony_ci vb->shrinker.count_objects = virtio_balloon_shrinker_count; 8808c2ecf20Sopenharmony_ci vb->shrinker.seeks = DEFAULT_SEEKS; 8818c2ecf20Sopenharmony_ci 8828c2ecf20Sopenharmony_ci return register_shrinker(&vb->shrinker); 8838c2ecf20Sopenharmony_ci} 8848c2ecf20Sopenharmony_ci 8858c2ecf20Sopenharmony_cistatic int virtballoon_probe(struct virtio_device *vdev) 8868c2ecf20Sopenharmony_ci{ 8878c2ecf20Sopenharmony_ci struct virtio_balloon *vb; 8888c2ecf20Sopenharmony_ci int err; 8898c2ecf20Sopenharmony_ci 8908c2ecf20Sopenharmony_ci if (!vdev->config->get) { 8918c2ecf20Sopenharmony_ci dev_err(&vdev->dev, "%s failure: config access disabled\n", 8928c2ecf20Sopenharmony_ci __func__); 8938c2ecf20Sopenharmony_ci return -EINVAL; 8948c2ecf20Sopenharmony_ci } 8958c2ecf20Sopenharmony_ci 8968c2ecf20Sopenharmony_ci vdev->priv = vb = kzalloc(sizeof(*vb), GFP_KERNEL); 8978c2ecf20Sopenharmony_ci if (!vb) { 8988c2ecf20Sopenharmony_ci err = -ENOMEM; 8998c2ecf20Sopenharmony_ci goto out; 9008c2ecf20Sopenharmony_ci } 9018c2ecf20Sopenharmony_ci 9028c2ecf20Sopenharmony_ci INIT_WORK(&vb->update_balloon_stats_work, update_balloon_stats_func); 9038c2ecf20Sopenharmony_ci INIT_WORK(&vb->update_balloon_size_work, update_balloon_size_func); 9048c2ecf20Sopenharmony_ci spin_lock_init(&vb->stop_update_lock); 9058c2ecf20Sopenharmony_ci mutex_init(&vb->balloon_lock); 9068c2ecf20Sopenharmony_ci init_waitqueue_head(&vb->acked); 9078c2ecf20Sopenharmony_ci vb->vdev = vdev; 9088c2ecf20Sopenharmony_ci 9098c2ecf20Sopenharmony_ci balloon_devinfo_init(&vb->vb_dev_info); 9108c2ecf20Sopenharmony_ci 9118c2ecf20Sopenharmony_ci err = init_vqs(vb); 9128c2ecf20Sopenharmony_ci if (err) 9138c2ecf20Sopenharmony_ci goto out_free_vb; 9148c2ecf20Sopenharmony_ci 9158c2ecf20Sopenharmony_ci#ifdef CONFIG_BALLOON_COMPACTION 9168c2ecf20Sopenharmony_ci balloon_mnt = kern_mount(&balloon_fs); 9178c2ecf20Sopenharmony_ci if (IS_ERR(balloon_mnt)) { 9188c2ecf20Sopenharmony_ci err = PTR_ERR(balloon_mnt); 9198c2ecf20Sopenharmony_ci goto out_del_vqs; 9208c2ecf20Sopenharmony_ci } 9218c2ecf20Sopenharmony_ci 9228c2ecf20Sopenharmony_ci vb->vb_dev_info.migratepage = virtballoon_migratepage; 9238c2ecf20Sopenharmony_ci vb->vb_dev_info.inode = alloc_anon_inode(balloon_mnt->mnt_sb); 9248c2ecf20Sopenharmony_ci if (IS_ERR(vb->vb_dev_info.inode)) { 9258c2ecf20Sopenharmony_ci err = PTR_ERR(vb->vb_dev_info.inode); 9268c2ecf20Sopenharmony_ci goto out_kern_unmount; 9278c2ecf20Sopenharmony_ci } 9288c2ecf20Sopenharmony_ci vb->vb_dev_info.inode->i_mapping->a_ops = &balloon_aops; 9298c2ecf20Sopenharmony_ci#endif 9308c2ecf20Sopenharmony_ci if (virtio_has_feature(vdev, VIRTIO_BALLOON_F_FREE_PAGE_HINT)) { 9318c2ecf20Sopenharmony_ci /* 9328c2ecf20Sopenharmony_ci * There is always one entry reserved for cmd id, so the ring 9338c2ecf20Sopenharmony_ci * size needs to be at least two to report free page hints. 9348c2ecf20Sopenharmony_ci */ 9358c2ecf20Sopenharmony_ci if (virtqueue_get_vring_size(vb->free_page_vq) < 2) { 9368c2ecf20Sopenharmony_ci err = -ENOSPC; 9378c2ecf20Sopenharmony_ci goto out_iput; 9388c2ecf20Sopenharmony_ci } 9398c2ecf20Sopenharmony_ci vb->balloon_wq = alloc_workqueue("balloon-wq", 9408c2ecf20Sopenharmony_ci WQ_FREEZABLE | WQ_CPU_INTENSIVE, 0); 9418c2ecf20Sopenharmony_ci if (!vb->balloon_wq) { 9428c2ecf20Sopenharmony_ci err = -ENOMEM; 9438c2ecf20Sopenharmony_ci goto out_iput; 9448c2ecf20Sopenharmony_ci } 9458c2ecf20Sopenharmony_ci INIT_WORK(&vb->report_free_page_work, report_free_page_func); 9468c2ecf20Sopenharmony_ci vb->cmd_id_received_cache = VIRTIO_BALLOON_CMD_ID_STOP; 9478c2ecf20Sopenharmony_ci vb->cmd_id_active = cpu_to_virtio32(vb->vdev, 9488c2ecf20Sopenharmony_ci VIRTIO_BALLOON_CMD_ID_STOP); 9498c2ecf20Sopenharmony_ci vb->cmd_id_stop = cpu_to_virtio32(vb->vdev, 9508c2ecf20Sopenharmony_ci VIRTIO_BALLOON_CMD_ID_STOP); 9518c2ecf20Sopenharmony_ci spin_lock_init(&vb->free_page_list_lock); 9528c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&vb->free_page_list); 9538c2ecf20Sopenharmony_ci /* 9548c2ecf20Sopenharmony_ci * We're allowed to reuse any free pages, even if they are 9558c2ecf20Sopenharmony_ci * still to be processed by the host. 9568c2ecf20Sopenharmony_ci */ 9578c2ecf20Sopenharmony_ci err = virtio_balloon_register_shrinker(vb); 9588c2ecf20Sopenharmony_ci if (err) 9598c2ecf20Sopenharmony_ci goto out_del_balloon_wq; 9608c2ecf20Sopenharmony_ci } 9618c2ecf20Sopenharmony_ci 9628c2ecf20Sopenharmony_ci if (virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_DEFLATE_ON_OOM)) { 9638c2ecf20Sopenharmony_ci vb->oom_nb.notifier_call = virtio_balloon_oom_notify; 9648c2ecf20Sopenharmony_ci vb->oom_nb.priority = VIRTIO_BALLOON_OOM_NOTIFY_PRIORITY; 9658c2ecf20Sopenharmony_ci err = register_oom_notifier(&vb->oom_nb); 9668c2ecf20Sopenharmony_ci if (err < 0) 9678c2ecf20Sopenharmony_ci goto out_unregister_shrinker; 9688c2ecf20Sopenharmony_ci } 9698c2ecf20Sopenharmony_ci 9708c2ecf20Sopenharmony_ci if (virtio_has_feature(vdev, VIRTIO_BALLOON_F_PAGE_POISON)) { 9718c2ecf20Sopenharmony_ci /* Start with poison val of 0 representing general init */ 9728c2ecf20Sopenharmony_ci __u32 poison_val = 0; 9738c2ecf20Sopenharmony_ci 9748c2ecf20Sopenharmony_ci /* 9758c2ecf20Sopenharmony_ci * Let the hypervisor know that we are expecting a 9768c2ecf20Sopenharmony_ci * specific value to be written back in balloon pages. 9778c2ecf20Sopenharmony_ci * 9788c2ecf20Sopenharmony_ci * If the PAGE_POISON value was larger than a byte we would 9798c2ecf20Sopenharmony_ci * need to byte swap poison_val here to guarantee it is 9808c2ecf20Sopenharmony_ci * little-endian. However for now it is a single byte so we 9818c2ecf20Sopenharmony_ci * can pass it as-is. 9828c2ecf20Sopenharmony_ci */ 9838c2ecf20Sopenharmony_ci if (!want_init_on_free()) 9848c2ecf20Sopenharmony_ci memset(&poison_val, PAGE_POISON, sizeof(poison_val)); 9858c2ecf20Sopenharmony_ci 9868c2ecf20Sopenharmony_ci virtio_cwrite_le(vb->vdev, struct virtio_balloon_config, 9878c2ecf20Sopenharmony_ci poison_val, &poison_val); 9888c2ecf20Sopenharmony_ci } 9898c2ecf20Sopenharmony_ci 9908c2ecf20Sopenharmony_ci vb->pr_dev_info.report = virtballoon_free_page_report; 9918c2ecf20Sopenharmony_ci if (virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_REPORTING)) { 9928c2ecf20Sopenharmony_ci unsigned int capacity; 9938c2ecf20Sopenharmony_ci 9948c2ecf20Sopenharmony_ci capacity = virtqueue_get_vring_size(vb->reporting_vq); 9958c2ecf20Sopenharmony_ci if (capacity < PAGE_REPORTING_CAPACITY) { 9968c2ecf20Sopenharmony_ci err = -ENOSPC; 9978c2ecf20Sopenharmony_ci goto out_unregister_oom; 9988c2ecf20Sopenharmony_ci } 9998c2ecf20Sopenharmony_ci 10008c2ecf20Sopenharmony_ci err = page_reporting_register(&vb->pr_dev_info); 10018c2ecf20Sopenharmony_ci if (err) 10028c2ecf20Sopenharmony_ci goto out_unregister_oom; 10038c2ecf20Sopenharmony_ci } 10048c2ecf20Sopenharmony_ci 10058c2ecf20Sopenharmony_ci virtio_device_ready(vdev); 10068c2ecf20Sopenharmony_ci 10078c2ecf20Sopenharmony_ci if (towards_target(vb)) 10088c2ecf20Sopenharmony_ci virtballoon_changed(vdev); 10098c2ecf20Sopenharmony_ci return 0; 10108c2ecf20Sopenharmony_ci 10118c2ecf20Sopenharmony_ciout_unregister_oom: 10128c2ecf20Sopenharmony_ci if (virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_DEFLATE_ON_OOM)) 10138c2ecf20Sopenharmony_ci unregister_oom_notifier(&vb->oom_nb); 10148c2ecf20Sopenharmony_ciout_unregister_shrinker: 10158c2ecf20Sopenharmony_ci if (virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_FREE_PAGE_HINT)) 10168c2ecf20Sopenharmony_ci virtio_balloon_unregister_shrinker(vb); 10178c2ecf20Sopenharmony_ciout_del_balloon_wq: 10188c2ecf20Sopenharmony_ci if (virtio_has_feature(vdev, VIRTIO_BALLOON_F_FREE_PAGE_HINT)) 10198c2ecf20Sopenharmony_ci destroy_workqueue(vb->balloon_wq); 10208c2ecf20Sopenharmony_ciout_iput: 10218c2ecf20Sopenharmony_ci#ifdef CONFIG_BALLOON_COMPACTION 10228c2ecf20Sopenharmony_ci iput(vb->vb_dev_info.inode); 10238c2ecf20Sopenharmony_ciout_kern_unmount: 10248c2ecf20Sopenharmony_ci kern_unmount(balloon_mnt); 10258c2ecf20Sopenharmony_ciout_del_vqs: 10268c2ecf20Sopenharmony_ci#endif 10278c2ecf20Sopenharmony_ci vdev->config->del_vqs(vdev); 10288c2ecf20Sopenharmony_ciout_free_vb: 10298c2ecf20Sopenharmony_ci kfree(vb); 10308c2ecf20Sopenharmony_ciout: 10318c2ecf20Sopenharmony_ci return err; 10328c2ecf20Sopenharmony_ci} 10338c2ecf20Sopenharmony_ci 10348c2ecf20Sopenharmony_cistatic void remove_common(struct virtio_balloon *vb) 10358c2ecf20Sopenharmony_ci{ 10368c2ecf20Sopenharmony_ci /* There might be pages left in the balloon: free them. */ 10378c2ecf20Sopenharmony_ci while (vb->num_pages) 10388c2ecf20Sopenharmony_ci leak_balloon(vb, vb->num_pages); 10398c2ecf20Sopenharmony_ci update_balloon_size(vb); 10408c2ecf20Sopenharmony_ci 10418c2ecf20Sopenharmony_ci /* There might be free pages that are being reported: release them. */ 10428c2ecf20Sopenharmony_ci if (virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_FREE_PAGE_HINT)) 10438c2ecf20Sopenharmony_ci return_free_pages_to_mm(vb, ULONG_MAX); 10448c2ecf20Sopenharmony_ci 10458c2ecf20Sopenharmony_ci /* Now we reset the device so we can clean up the queues. */ 10468c2ecf20Sopenharmony_ci vb->vdev->config->reset(vb->vdev); 10478c2ecf20Sopenharmony_ci 10488c2ecf20Sopenharmony_ci vb->vdev->config->del_vqs(vb->vdev); 10498c2ecf20Sopenharmony_ci} 10508c2ecf20Sopenharmony_ci 10518c2ecf20Sopenharmony_cistatic void virtballoon_remove(struct virtio_device *vdev) 10528c2ecf20Sopenharmony_ci{ 10538c2ecf20Sopenharmony_ci struct virtio_balloon *vb = vdev->priv; 10548c2ecf20Sopenharmony_ci 10558c2ecf20Sopenharmony_ci if (virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_REPORTING)) 10568c2ecf20Sopenharmony_ci page_reporting_unregister(&vb->pr_dev_info); 10578c2ecf20Sopenharmony_ci if (virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_DEFLATE_ON_OOM)) 10588c2ecf20Sopenharmony_ci unregister_oom_notifier(&vb->oom_nb); 10598c2ecf20Sopenharmony_ci if (virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_FREE_PAGE_HINT)) 10608c2ecf20Sopenharmony_ci virtio_balloon_unregister_shrinker(vb); 10618c2ecf20Sopenharmony_ci spin_lock_irq(&vb->stop_update_lock); 10628c2ecf20Sopenharmony_ci vb->stop_update = true; 10638c2ecf20Sopenharmony_ci spin_unlock_irq(&vb->stop_update_lock); 10648c2ecf20Sopenharmony_ci cancel_work_sync(&vb->update_balloon_size_work); 10658c2ecf20Sopenharmony_ci cancel_work_sync(&vb->update_balloon_stats_work); 10668c2ecf20Sopenharmony_ci 10678c2ecf20Sopenharmony_ci if (virtio_has_feature(vdev, VIRTIO_BALLOON_F_FREE_PAGE_HINT)) { 10688c2ecf20Sopenharmony_ci cancel_work_sync(&vb->report_free_page_work); 10698c2ecf20Sopenharmony_ci destroy_workqueue(vb->balloon_wq); 10708c2ecf20Sopenharmony_ci } 10718c2ecf20Sopenharmony_ci 10728c2ecf20Sopenharmony_ci remove_common(vb); 10738c2ecf20Sopenharmony_ci#ifdef CONFIG_BALLOON_COMPACTION 10748c2ecf20Sopenharmony_ci if (vb->vb_dev_info.inode) 10758c2ecf20Sopenharmony_ci iput(vb->vb_dev_info.inode); 10768c2ecf20Sopenharmony_ci 10778c2ecf20Sopenharmony_ci kern_unmount(balloon_mnt); 10788c2ecf20Sopenharmony_ci#endif 10798c2ecf20Sopenharmony_ci kfree(vb); 10808c2ecf20Sopenharmony_ci} 10818c2ecf20Sopenharmony_ci 10828c2ecf20Sopenharmony_ci#ifdef CONFIG_PM_SLEEP 10838c2ecf20Sopenharmony_cistatic int virtballoon_freeze(struct virtio_device *vdev) 10848c2ecf20Sopenharmony_ci{ 10858c2ecf20Sopenharmony_ci struct virtio_balloon *vb = vdev->priv; 10868c2ecf20Sopenharmony_ci 10878c2ecf20Sopenharmony_ci /* 10888c2ecf20Sopenharmony_ci * The workqueue is already frozen by the PM core before this 10898c2ecf20Sopenharmony_ci * function is called. 10908c2ecf20Sopenharmony_ci */ 10918c2ecf20Sopenharmony_ci remove_common(vb); 10928c2ecf20Sopenharmony_ci return 0; 10938c2ecf20Sopenharmony_ci} 10948c2ecf20Sopenharmony_ci 10958c2ecf20Sopenharmony_cistatic int virtballoon_restore(struct virtio_device *vdev) 10968c2ecf20Sopenharmony_ci{ 10978c2ecf20Sopenharmony_ci struct virtio_balloon *vb = vdev->priv; 10988c2ecf20Sopenharmony_ci int ret; 10998c2ecf20Sopenharmony_ci 11008c2ecf20Sopenharmony_ci ret = init_vqs(vdev->priv); 11018c2ecf20Sopenharmony_ci if (ret) 11028c2ecf20Sopenharmony_ci return ret; 11038c2ecf20Sopenharmony_ci 11048c2ecf20Sopenharmony_ci virtio_device_ready(vdev); 11058c2ecf20Sopenharmony_ci 11068c2ecf20Sopenharmony_ci if (towards_target(vb)) 11078c2ecf20Sopenharmony_ci virtballoon_changed(vdev); 11088c2ecf20Sopenharmony_ci update_balloon_size(vb); 11098c2ecf20Sopenharmony_ci return 0; 11108c2ecf20Sopenharmony_ci} 11118c2ecf20Sopenharmony_ci#endif 11128c2ecf20Sopenharmony_ci 11138c2ecf20Sopenharmony_cistatic int virtballoon_validate(struct virtio_device *vdev) 11148c2ecf20Sopenharmony_ci{ 11158c2ecf20Sopenharmony_ci /* 11168c2ecf20Sopenharmony_ci * Inform the hypervisor that our pages are poisoned or 11178c2ecf20Sopenharmony_ci * initialized. If we cannot do that then we should disable 11188c2ecf20Sopenharmony_ci * page reporting as it could potentially change the contents 11198c2ecf20Sopenharmony_ci * of our free pages. 11208c2ecf20Sopenharmony_ci */ 11218c2ecf20Sopenharmony_ci if (!want_init_on_free() && 11228c2ecf20Sopenharmony_ci (IS_ENABLED(CONFIG_PAGE_POISONING_NO_SANITY) || 11238c2ecf20Sopenharmony_ci !page_poisoning_enabled())) 11248c2ecf20Sopenharmony_ci __virtio_clear_bit(vdev, VIRTIO_BALLOON_F_PAGE_POISON); 11258c2ecf20Sopenharmony_ci else if (!virtio_has_feature(vdev, VIRTIO_BALLOON_F_PAGE_POISON)) 11268c2ecf20Sopenharmony_ci __virtio_clear_bit(vdev, VIRTIO_BALLOON_F_REPORTING); 11278c2ecf20Sopenharmony_ci 11288c2ecf20Sopenharmony_ci __virtio_clear_bit(vdev, VIRTIO_F_ACCESS_PLATFORM); 11298c2ecf20Sopenharmony_ci return 0; 11308c2ecf20Sopenharmony_ci} 11318c2ecf20Sopenharmony_ci 11328c2ecf20Sopenharmony_cistatic unsigned int features[] = { 11338c2ecf20Sopenharmony_ci VIRTIO_BALLOON_F_MUST_TELL_HOST, 11348c2ecf20Sopenharmony_ci VIRTIO_BALLOON_F_STATS_VQ, 11358c2ecf20Sopenharmony_ci VIRTIO_BALLOON_F_DEFLATE_ON_OOM, 11368c2ecf20Sopenharmony_ci VIRTIO_BALLOON_F_FREE_PAGE_HINT, 11378c2ecf20Sopenharmony_ci VIRTIO_BALLOON_F_PAGE_POISON, 11388c2ecf20Sopenharmony_ci VIRTIO_BALLOON_F_REPORTING, 11398c2ecf20Sopenharmony_ci}; 11408c2ecf20Sopenharmony_ci 11418c2ecf20Sopenharmony_cistatic struct virtio_driver virtio_balloon_driver = { 11428c2ecf20Sopenharmony_ci .feature_table = features, 11438c2ecf20Sopenharmony_ci .feature_table_size = ARRAY_SIZE(features), 11448c2ecf20Sopenharmony_ci .driver.name = KBUILD_MODNAME, 11458c2ecf20Sopenharmony_ci .driver.owner = THIS_MODULE, 11468c2ecf20Sopenharmony_ci .id_table = id_table, 11478c2ecf20Sopenharmony_ci .validate = virtballoon_validate, 11488c2ecf20Sopenharmony_ci .probe = virtballoon_probe, 11498c2ecf20Sopenharmony_ci .remove = virtballoon_remove, 11508c2ecf20Sopenharmony_ci .config_changed = virtballoon_changed, 11518c2ecf20Sopenharmony_ci#ifdef CONFIG_PM_SLEEP 11528c2ecf20Sopenharmony_ci .freeze = virtballoon_freeze, 11538c2ecf20Sopenharmony_ci .restore = virtballoon_restore, 11548c2ecf20Sopenharmony_ci#endif 11558c2ecf20Sopenharmony_ci}; 11568c2ecf20Sopenharmony_ci 11578c2ecf20Sopenharmony_cimodule_virtio_driver(virtio_balloon_driver); 11588c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(virtio, id_table); 11598c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Virtio balloon driver"); 11608c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 1161