162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * mm/balloon_compaction.c 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Common interface for making balloon pages movable by compaction. 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * Copyright (C) 2012, Red Hat, Inc. Rafael Aquini <aquini@redhat.com> 862306a36Sopenharmony_ci */ 962306a36Sopenharmony_ci#include <linux/mm.h> 1062306a36Sopenharmony_ci#include <linux/slab.h> 1162306a36Sopenharmony_ci#include <linux/export.h> 1262306a36Sopenharmony_ci#include <linux/balloon_compaction.h> 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_cistatic void balloon_page_enqueue_one(struct balloon_dev_info *b_dev_info, 1562306a36Sopenharmony_ci struct page *page) 1662306a36Sopenharmony_ci{ 1762306a36Sopenharmony_ci /* 1862306a36Sopenharmony_ci * Block others from accessing the 'page' when we get around to 1962306a36Sopenharmony_ci * establishing additional references. We should be the only one 2062306a36Sopenharmony_ci * holding a reference to the 'page' at this point. If we are not, then 2162306a36Sopenharmony_ci * memory corruption is possible and we should stop execution. 2262306a36Sopenharmony_ci */ 2362306a36Sopenharmony_ci BUG_ON(!trylock_page(page)); 2462306a36Sopenharmony_ci balloon_page_insert(b_dev_info, page); 2562306a36Sopenharmony_ci unlock_page(page); 2662306a36Sopenharmony_ci __count_vm_event(BALLOON_INFLATE); 2762306a36Sopenharmony_ci} 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_ci/** 3062306a36Sopenharmony_ci * balloon_page_list_enqueue() - inserts a list of pages into the balloon page 3162306a36Sopenharmony_ci * list. 3262306a36Sopenharmony_ci * @b_dev_info: balloon device descriptor where we will insert a new page to 3362306a36Sopenharmony_ci * @pages: pages to enqueue - allocated using balloon_page_alloc. 3462306a36Sopenharmony_ci * 3562306a36Sopenharmony_ci * Driver must call this function to properly enqueue balloon pages before 3662306a36Sopenharmony_ci * definitively removing them from the guest system. 3762306a36Sopenharmony_ci * 3862306a36Sopenharmony_ci * Return: number of pages that were enqueued. 3962306a36Sopenharmony_ci */ 4062306a36Sopenharmony_cisize_t balloon_page_list_enqueue(struct balloon_dev_info *b_dev_info, 4162306a36Sopenharmony_ci struct list_head *pages) 4262306a36Sopenharmony_ci{ 4362306a36Sopenharmony_ci struct page *page, *tmp; 4462306a36Sopenharmony_ci unsigned long flags; 4562306a36Sopenharmony_ci size_t n_pages = 0; 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ci spin_lock_irqsave(&b_dev_info->pages_lock, flags); 4862306a36Sopenharmony_ci list_for_each_entry_safe(page, tmp, pages, lru) { 4962306a36Sopenharmony_ci list_del(&page->lru); 5062306a36Sopenharmony_ci balloon_page_enqueue_one(b_dev_info, page); 5162306a36Sopenharmony_ci n_pages++; 5262306a36Sopenharmony_ci } 5362306a36Sopenharmony_ci spin_unlock_irqrestore(&b_dev_info->pages_lock, flags); 5462306a36Sopenharmony_ci return n_pages; 5562306a36Sopenharmony_ci} 5662306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(balloon_page_list_enqueue); 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_ci/** 5962306a36Sopenharmony_ci * balloon_page_list_dequeue() - removes pages from balloon's page list and 6062306a36Sopenharmony_ci * returns a list of the pages. 6162306a36Sopenharmony_ci * @b_dev_info: balloon device descriptor where we will grab a page from. 6262306a36Sopenharmony_ci * @pages: pointer to the list of pages that would be returned to the caller. 6362306a36Sopenharmony_ci * @n_req_pages: number of requested pages. 6462306a36Sopenharmony_ci * 6562306a36Sopenharmony_ci * Driver must call this function to properly de-allocate a previous enlisted 6662306a36Sopenharmony_ci * balloon pages before definitively releasing it back to the guest system. 6762306a36Sopenharmony_ci * This function tries to remove @n_req_pages from the ballooned pages and 6862306a36Sopenharmony_ci * return them to the caller in the @pages list. 6962306a36Sopenharmony_ci * 7062306a36Sopenharmony_ci * Note that this function may fail to dequeue some pages even if the balloon 7162306a36Sopenharmony_ci * isn't empty - since the page list can be temporarily empty due to compaction 7262306a36Sopenharmony_ci * of isolated pages. 7362306a36Sopenharmony_ci * 7462306a36Sopenharmony_ci * Return: number of pages that were added to the @pages list. 7562306a36Sopenharmony_ci */ 7662306a36Sopenharmony_cisize_t balloon_page_list_dequeue(struct balloon_dev_info *b_dev_info, 7762306a36Sopenharmony_ci struct list_head *pages, size_t n_req_pages) 7862306a36Sopenharmony_ci{ 7962306a36Sopenharmony_ci struct page *page, *tmp; 8062306a36Sopenharmony_ci unsigned long flags; 8162306a36Sopenharmony_ci size_t n_pages = 0; 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_ci spin_lock_irqsave(&b_dev_info->pages_lock, flags); 8462306a36Sopenharmony_ci list_for_each_entry_safe(page, tmp, &b_dev_info->pages, lru) { 8562306a36Sopenharmony_ci if (n_pages == n_req_pages) 8662306a36Sopenharmony_ci break; 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_ci /* 8962306a36Sopenharmony_ci * Block others from accessing the 'page' while we get around to 9062306a36Sopenharmony_ci * establishing additional references and preparing the 'page' 9162306a36Sopenharmony_ci * to be released by the balloon driver. 9262306a36Sopenharmony_ci */ 9362306a36Sopenharmony_ci if (!trylock_page(page)) 9462306a36Sopenharmony_ci continue; 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_ci if (IS_ENABLED(CONFIG_BALLOON_COMPACTION) && 9762306a36Sopenharmony_ci PageIsolated(page)) { 9862306a36Sopenharmony_ci /* raced with isolation */ 9962306a36Sopenharmony_ci unlock_page(page); 10062306a36Sopenharmony_ci continue; 10162306a36Sopenharmony_ci } 10262306a36Sopenharmony_ci balloon_page_delete(page); 10362306a36Sopenharmony_ci __count_vm_event(BALLOON_DEFLATE); 10462306a36Sopenharmony_ci list_add(&page->lru, pages); 10562306a36Sopenharmony_ci unlock_page(page); 10662306a36Sopenharmony_ci n_pages++; 10762306a36Sopenharmony_ci } 10862306a36Sopenharmony_ci spin_unlock_irqrestore(&b_dev_info->pages_lock, flags); 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_ci return n_pages; 11162306a36Sopenharmony_ci} 11262306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(balloon_page_list_dequeue); 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_ci/* 11562306a36Sopenharmony_ci * balloon_page_alloc - allocates a new page for insertion into the balloon 11662306a36Sopenharmony_ci * page list. 11762306a36Sopenharmony_ci * 11862306a36Sopenharmony_ci * Driver must call this function to properly allocate a new balloon page. 11962306a36Sopenharmony_ci * Driver must call balloon_page_enqueue before definitively removing the page 12062306a36Sopenharmony_ci * from the guest system. 12162306a36Sopenharmony_ci * 12262306a36Sopenharmony_ci * Return: struct page for the allocated page or NULL on allocation failure. 12362306a36Sopenharmony_ci */ 12462306a36Sopenharmony_cistruct page *balloon_page_alloc(void) 12562306a36Sopenharmony_ci{ 12662306a36Sopenharmony_ci struct page *page = alloc_page(balloon_mapping_gfp_mask() | 12762306a36Sopenharmony_ci __GFP_NOMEMALLOC | __GFP_NORETRY | 12862306a36Sopenharmony_ci __GFP_NOWARN); 12962306a36Sopenharmony_ci return page; 13062306a36Sopenharmony_ci} 13162306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(balloon_page_alloc); 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_ci/* 13462306a36Sopenharmony_ci * balloon_page_enqueue - inserts a new page into the balloon page list. 13562306a36Sopenharmony_ci * 13662306a36Sopenharmony_ci * @b_dev_info: balloon device descriptor where we will insert a new page 13762306a36Sopenharmony_ci * @page: new page to enqueue - allocated using balloon_page_alloc. 13862306a36Sopenharmony_ci * 13962306a36Sopenharmony_ci * Drivers must call this function to properly enqueue a new allocated balloon 14062306a36Sopenharmony_ci * page before definitively removing the page from the guest system. 14162306a36Sopenharmony_ci * 14262306a36Sopenharmony_ci * Drivers must not call balloon_page_enqueue on pages that have been pushed to 14362306a36Sopenharmony_ci * a list with balloon_page_push before removing them with balloon_page_pop. To 14462306a36Sopenharmony_ci * enqueue a list of pages, use balloon_page_list_enqueue instead. 14562306a36Sopenharmony_ci */ 14662306a36Sopenharmony_civoid balloon_page_enqueue(struct balloon_dev_info *b_dev_info, 14762306a36Sopenharmony_ci struct page *page) 14862306a36Sopenharmony_ci{ 14962306a36Sopenharmony_ci unsigned long flags; 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_ci spin_lock_irqsave(&b_dev_info->pages_lock, flags); 15262306a36Sopenharmony_ci balloon_page_enqueue_one(b_dev_info, page); 15362306a36Sopenharmony_ci spin_unlock_irqrestore(&b_dev_info->pages_lock, flags); 15462306a36Sopenharmony_ci} 15562306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(balloon_page_enqueue); 15662306a36Sopenharmony_ci 15762306a36Sopenharmony_ci/* 15862306a36Sopenharmony_ci * balloon_page_dequeue - removes a page from balloon's page list and returns 15962306a36Sopenharmony_ci * its address to allow the driver to release the page. 16062306a36Sopenharmony_ci * @b_dev_info: balloon device descriptor where we will grab a page from. 16162306a36Sopenharmony_ci * 16262306a36Sopenharmony_ci * Driver must call this function to properly dequeue a previously enqueued page 16362306a36Sopenharmony_ci * before definitively releasing it back to the guest system. 16462306a36Sopenharmony_ci * 16562306a36Sopenharmony_ci * Caller must perform its own accounting to ensure that this 16662306a36Sopenharmony_ci * function is called only if some pages are actually enqueued. 16762306a36Sopenharmony_ci * 16862306a36Sopenharmony_ci * Note that this function may fail to dequeue some pages even if there are 16962306a36Sopenharmony_ci * some enqueued pages - since the page list can be temporarily empty due to 17062306a36Sopenharmony_ci * the compaction of isolated pages. 17162306a36Sopenharmony_ci * 17262306a36Sopenharmony_ci * TODO: remove the caller accounting requirements, and allow caller to wait 17362306a36Sopenharmony_ci * until all pages can be dequeued. 17462306a36Sopenharmony_ci * 17562306a36Sopenharmony_ci * Return: struct page for the dequeued page, or NULL if no page was dequeued. 17662306a36Sopenharmony_ci */ 17762306a36Sopenharmony_cistruct page *balloon_page_dequeue(struct balloon_dev_info *b_dev_info) 17862306a36Sopenharmony_ci{ 17962306a36Sopenharmony_ci unsigned long flags; 18062306a36Sopenharmony_ci LIST_HEAD(pages); 18162306a36Sopenharmony_ci int n_pages; 18262306a36Sopenharmony_ci 18362306a36Sopenharmony_ci n_pages = balloon_page_list_dequeue(b_dev_info, &pages, 1); 18462306a36Sopenharmony_ci 18562306a36Sopenharmony_ci if (n_pages != 1) { 18662306a36Sopenharmony_ci /* 18762306a36Sopenharmony_ci * If we are unable to dequeue a balloon page because the page 18862306a36Sopenharmony_ci * list is empty and there are no isolated pages, then something 18962306a36Sopenharmony_ci * went out of track and some balloon pages are lost. 19062306a36Sopenharmony_ci * BUG() here, otherwise the balloon driver may get stuck in 19162306a36Sopenharmony_ci * an infinite loop while attempting to release all its pages. 19262306a36Sopenharmony_ci */ 19362306a36Sopenharmony_ci spin_lock_irqsave(&b_dev_info->pages_lock, flags); 19462306a36Sopenharmony_ci if (unlikely(list_empty(&b_dev_info->pages) && 19562306a36Sopenharmony_ci !b_dev_info->isolated_pages)) 19662306a36Sopenharmony_ci BUG(); 19762306a36Sopenharmony_ci spin_unlock_irqrestore(&b_dev_info->pages_lock, flags); 19862306a36Sopenharmony_ci return NULL; 19962306a36Sopenharmony_ci } 20062306a36Sopenharmony_ci return list_first_entry(&pages, struct page, lru); 20162306a36Sopenharmony_ci} 20262306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(balloon_page_dequeue); 20362306a36Sopenharmony_ci 20462306a36Sopenharmony_ci#ifdef CONFIG_BALLOON_COMPACTION 20562306a36Sopenharmony_ci 20662306a36Sopenharmony_cistatic bool balloon_page_isolate(struct page *page, isolate_mode_t mode) 20762306a36Sopenharmony_ci 20862306a36Sopenharmony_ci{ 20962306a36Sopenharmony_ci struct balloon_dev_info *b_dev_info = balloon_page_device(page); 21062306a36Sopenharmony_ci unsigned long flags; 21162306a36Sopenharmony_ci 21262306a36Sopenharmony_ci spin_lock_irqsave(&b_dev_info->pages_lock, flags); 21362306a36Sopenharmony_ci list_del(&page->lru); 21462306a36Sopenharmony_ci b_dev_info->isolated_pages++; 21562306a36Sopenharmony_ci spin_unlock_irqrestore(&b_dev_info->pages_lock, flags); 21662306a36Sopenharmony_ci 21762306a36Sopenharmony_ci return true; 21862306a36Sopenharmony_ci} 21962306a36Sopenharmony_ci 22062306a36Sopenharmony_cistatic void balloon_page_putback(struct page *page) 22162306a36Sopenharmony_ci{ 22262306a36Sopenharmony_ci struct balloon_dev_info *b_dev_info = balloon_page_device(page); 22362306a36Sopenharmony_ci unsigned long flags; 22462306a36Sopenharmony_ci 22562306a36Sopenharmony_ci spin_lock_irqsave(&b_dev_info->pages_lock, flags); 22662306a36Sopenharmony_ci list_add(&page->lru, &b_dev_info->pages); 22762306a36Sopenharmony_ci b_dev_info->isolated_pages--; 22862306a36Sopenharmony_ci spin_unlock_irqrestore(&b_dev_info->pages_lock, flags); 22962306a36Sopenharmony_ci} 23062306a36Sopenharmony_ci 23162306a36Sopenharmony_ci/* move_to_new_page() counterpart for a ballooned page */ 23262306a36Sopenharmony_cistatic int balloon_page_migrate(struct page *newpage, struct page *page, 23362306a36Sopenharmony_ci enum migrate_mode mode) 23462306a36Sopenharmony_ci{ 23562306a36Sopenharmony_ci struct balloon_dev_info *balloon = balloon_page_device(page); 23662306a36Sopenharmony_ci 23762306a36Sopenharmony_ci /* 23862306a36Sopenharmony_ci * We can not easily support the no copy case here so ignore it as it 23962306a36Sopenharmony_ci * is unlikely to be used with balloon pages. See include/linux/hmm.h 24062306a36Sopenharmony_ci * for a user of the MIGRATE_SYNC_NO_COPY mode. 24162306a36Sopenharmony_ci */ 24262306a36Sopenharmony_ci if (mode == MIGRATE_SYNC_NO_COPY) 24362306a36Sopenharmony_ci return -EINVAL; 24462306a36Sopenharmony_ci 24562306a36Sopenharmony_ci VM_BUG_ON_PAGE(!PageLocked(page), page); 24662306a36Sopenharmony_ci VM_BUG_ON_PAGE(!PageLocked(newpage), newpage); 24762306a36Sopenharmony_ci 24862306a36Sopenharmony_ci return balloon->migratepage(balloon, newpage, page, mode); 24962306a36Sopenharmony_ci} 25062306a36Sopenharmony_ci 25162306a36Sopenharmony_ciconst struct movable_operations balloon_mops = { 25262306a36Sopenharmony_ci .migrate_page = balloon_page_migrate, 25362306a36Sopenharmony_ci .isolate_page = balloon_page_isolate, 25462306a36Sopenharmony_ci .putback_page = balloon_page_putback, 25562306a36Sopenharmony_ci}; 25662306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(balloon_mops); 25762306a36Sopenharmony_ci 25862306a36Sopenharmony_ci#endif /* CONFIG_BALLOON_COMPACTION */ 259