162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Contiguous Memory Allocator 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (c) 2010-2011 by Samsung Electronics. 662306a36Sopenharmony_ci * Copyright IBM Corporation, 2013 762306a36Sopenharmony_ci * Copyright LG Electronics Inc., 2014 862306a36Sopenharmony_ci * Written by: 962306a36Sopenharmony_ci * Marek Szyprowski <m.szyprowski@samsung.com> 1062306a36Sopenharmony_ci * Michal Nazarewicz <mina86@mina86.com> 1162306a36Sopenharmony_ci * Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com> 1262306a36Sopenharmony_ci * Joonsoo Kim <iamjoonsoo.kim@lge.com> 1362306a36Sopenharmony_ci */ 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ci#define pr_fmt(fmt) "cma: " fmt 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ci#ifdef CONFIG_CMA_DEBUG 1862306a36Sopenharmony_ci#ifndef DEBUG 1962306a36Sopenharmony_ci# define DEBUG 2062306a36Sopenharmony_ci#endif 2162306a36Sopenharmony_ci#endif 2262306a36Sopenharmony_ci#define CREATE_TRACE_POINTS 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ci#include <linux/memblock.h> 2562306a36Sopenharmony_ci#include <linux/err.h> 2662306a36Sopenharmony_ci#include <linux/mm.h> 2762306a36Sopenharmony_ci#include <linux/sizes.h> 2862306a36Sopenharmony_ci#include <linux/slab.h> 2962306a36Sopenharmony_ci#include <linux/log2.h> 3062306a36Sopenharmony_ci#include <linux/cma.h> 3162306a36Sopenharmony_ci#include <linux/highmem.h> 3262306a36Sopenharmony_ci#include <linux/io.h> 3362306a36Sopenharmony_ci#include <linux/kmemleak.h> 3462306a36Sopenharmony_ci#include <trace/events/cma.h> 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_ci#include "internal.h" 3762306a36Sopenharmony_ci#include "cma.h" 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_cistruct cma cma_areas[MAX_CMA_AREAS]; 4062306a36Sopenharmony_ciunsigned cma_area_count; 4162306a36Sopenharmony_cistatic DEFINE_MUTEX(cma_mutex); 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_ciphys_addr_t cma_get_base(const struct cma *cma) 4462306a36Sopenharmony_ci{ 4562306a36Sopenharmony_ci return PFN_PHYS(cma->base_pfn); 4662306a36Sopenharmony_ci} 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_ciunsigned long cma_get_size(const struct cma *cma) 4962306a36Sopenharmony_ci{ 5062306a36Sopenharmony_ci return cma->count << PAGE_SHIFT; 5162306a36Sopenharmony_ci} 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_ciconst char *cma_get_name(const struct cma *cma) 5462306a36Sopenharmony_ci{ 5562306a36Sopenharmony_ci return cma->name; 5662306a36Sopenharmony_ci} 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_cistatic unsigned long cma_bitmap_aligned_mask(const struct cma *cma, 5962306a36Sopenharmony_ci unsigned int align_order) 6062306a36Sopenharmony_ci{ 6162306a36Sopenharmony_ci if (align_order <= cma->order_per_bit) 6262306a36Sopenharmony_ci return 0; 6362306a36Sopenharmony_ci return (1UL << (align_order - cma->order_per_bit)) - 1; 6462306a36Sopenharmony_ci} 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ci/* 6762306a36Sopenharmony_ci * Find the offset of the base PFN from the specified align_order. 6862306a36Sopenharmony_ci * The value returned is represented in order_per_bits. 6962306a36Sopenharmony_ci */ 7062306a36Sopenharmony_cistatic unsigned long cma_bitmap_aligned_offset(const struct cma *cma, 7162306a36Sopenharmony_ci unsigned int align_order) 7262306a36Sopenharmony_ci{ 7362306a36Sopenharmony_ci return (cma->base_pfn & ((1UL << align_order) - 1)) 7462306a36Sopenharmony_ci >> cma->order_per_bit; 7562306a36Sopenharmony_ci} 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_cistatic unsigned long cma_bitmap_pages_to_bits(const struct cma *cma, 7862306a36Sopenharmony_ci unsigned long pages) 7962306a36Sopenharmony_ci{ 8062306a36Sopenharmony_ci return ALIGN(pages, 1UL << cma->order_per_bit) >> cma->order_per_bit; 8162306a36Sopenharmony_ci} 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_cistatic void cma_clear_bitmap(struct cma *cma, unsigned long pfn, 8462306a36Sopenharmony_ci unsigned long count) 8562306a36Sopenharmony_ci{ 8662306a36Sopenharmony_ci unsigned long bitmap_no, bitmap_count; 8762306a36Sopenharmony_ci unsigned long flags; 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_ci bitmap_no = (pfn - cma->base_pfn) >> cma->order_per_bit; 9062306a36Sopenharmony_ci bitmap_count = cma_bitmap_pages_to_bits(cma, count); 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_ci spin_lock_irqsave(&cma->lock, flags); 9362306a36Sopenharmony_ci bitmap_clear(cma->bitmap, bitmap_no, bitmap_count); 9462306a36Sopenharmony_ci spin_unlock_irqrestore(&cma->lock, flags); 9562306a36Sopenharmony_ci} 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_cistatic void __init cma_activate_area(struct cma *cma) 9862306a36Sopenharmony_ci{ 9962306a36Sopenharmony_ci unsigned long base_pfn = cma->base_pfn, pfn; 10062306a36Sopenharmony_ci struct zone *zone; 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_ci cma->bitmap = bitmap_zalloc(cma_bitmap_maxno(cma), GFP_KERNEL); 10362306a36Sopenharmony_ci if (!cma->bitmap) 10462306a36Sopenharmony_ci goto out_error; 10562306a36Sopenharmony_ci 10662306a36Sopenharmony_ci /* 10762306a36Sopenharmony_ci * alloc_contig_range() requires the pfn range specified to be in the 10862306a36Sopenharmony_ci * same zone. Simplify by forcing the entire CMA resv range to be in the 10962306a36Sopenharmony_ci * same zone. 11062306a36Sopenharmony_ci */ 11162306a36Sopenharmony_ci WARN_ON_ONCE(!pfn_valid(base_pfn)); 11262306a36Sopenharmony_ci zone = page_zone(pfn_to_page(base_pfn)); 11362306a36Sopenharmony_ci for (pfn = base_pfn + 1; pfn < base_pfn + cma->count; pfn++) { 11462306a36Sopenharmony_ci WARN_ON_ONCE(!pfn_valid(pfn)); 11562306a36Sopenharmony_ci if (page_zone(pfn_to_page(pfn)) != zone) 11662306a36Sopenharmony_ci goto not_in_zone; 11762306a36Sopenharmony_ci } 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_ci for (pfn = base_pfn; pfn < base_pfn + cma->count; 12062306a36Sopenharmony_ci pfn += pageblock_nr_pages) 12162306a36Sopenharmony_ci init_cma_reserved_pageblock(pfn_to_page(pfn)); 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_ci spin_lock_init(&cma->lock); 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_ci#ifdef CONFIG_CMA_DEBUGFS 12662306a36Sopenharmony_ci INIT_HLIST_HEAD(&cma->mem_head); 12762306a36Sopenharmony_ci spin_lock_init(&cma->mem_head_lock); 12862306a36Sopenharmony_ci#endif 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_ci return; 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_cinot_in_zone: 13362306a36Sopenharmony_ci bitmap_free(cma->bitmap); 13462306a36Sopenharmony_ciout_error: 13562306a36Sopenharmony_ci /* Expose all pages to the buddy, they are useless for CMA. */ 13662306a36Sopenharmony_ci if (!cma->reserve_pages_on_error) { 13762306a36Sopenharmony_ci for (pfn = base_pfn; pfn < base_pfn + cma->count; pfn++) 13862306a36Sopenharmony_ci free_reserved_page(pfn_to_page(pfn)); 13962306a36Sopenharmony_ci } 14062306a36Sopenharmony_ci totalcma_pages -= cma->count; 14162306a36Sopenharmony_ci cma->count = 0; 14262306a36Sopenharmony_ci pr_err("CMA area %s could not be activated\n", cma->name); 14362306a36Sopenharmony_ci return; 14462306a36Sopenharmony_ci} 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_cistatic int __init cma_init_reserved_areas(void) 14762306a36Sopenharmony_ci{ 14862306a36Sopenharmony_ci int i; 14962306a36Sopenharmony_ci 15062306a36Sopenharmony_ci for (i = 0; i < cma_area_count; i++) 15162306a36Sopenharmony_ci cma_activate_area(&cma_areas[i]); 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_ci return 0; 15462306a36Sopenharmony_ci} 15562306a36Sopenharmony_cicore_initcall(cma_init_reserved_areas); 15662306a36Sopenharmony_ci 15762306a36Sopenharmony_civoid __init cma_reserve_pages_on_error(struct cma *cma) 15862306a36Sopenharmony_ci{ 15962306a36Sopenharmony_ci cma->reserve_pages_on_error = true; 16062306a36Sopenharmony_ci} 16162306a36Sopenharmony_ci 16262306a36Sopenharmony_ci/** 16362306a36Sopenharmony_ci * cma_init_reserved_mem() - create custom contiguous area from reserved memory 16462306a36Sopenharmony_ci * @base: Base address of the reserved area 16562306a36Sopenharmony_ci * @size: Size of the reserved area (in bytes), 16662306a36Sopenharmony_ci * @order_per_bit: Order of pages represented by one bit on bitmap. 16762306a36Sopenharmony_ci * @name: The name of the area. If this parameter is NULL, the name of 16862306a36Sopenharmony_ci * the area will be set to "cmaN", where N is a running counter of 16962306a36Sopenharmony_ci * used areas. 17062306a36Sopenharmony_ci * @res_cma: Pointer to store the created cma region. 17162306a36Sopenharmony_ci * 17262306a36Sopenharmony_ci * This function creates custom contiguous area from already reserved memory. 17362306a36Sopenharmony_ci */ 17462306a36Sopenharmony_ciint __init cma_init_reserved_mem(phys_addr_t base, phys_addr_t size, 17562306a36Sopenharmony_ci unsigned int order_per_bit, 17662306a36Sopenharmony_ci const char *name, 17762306a36Sopenharmony_ci struct cma **res_cma) 17862306a36Sopenharmony_ci{ 17962306a36Sopenharmony_ci struct cma *cma; 18062306a36Sopenharmony_ci 18162306a36Sopenharmony_ci /* Sanity checks */ 18262306a36Sopenharmony_ci if (cma_area_count == ARRAY_SIZE(cma_areas)) { 18362306a36Sopenharmony_ci pr_err("Not enough slots for CMA reserved regions!\n"); 18462306a36Sopenharmony_ci return -ENOSPC; 18562306a36Sopenharmony_ci } 18662306a36Sopenharmony_ci 18762306a36Sopenharmony_ci if (!size || !memblock_is_region_reserved(base, size)) 18862306a36Sopenharmony_ci return -EINVAL; 18962306a36Sopenharmony_ci 19062306a36Sopenharmony_ci /* alignment should be aligned with order_per_bit */ 19162306a36Sopenharmony_ci if (!IS_ALIGNED(CMA_MIN_ALIGNMENT_PAGES, 1 << order_per_bit)) 19262306a36Sopenharmony_ci return -EINVAL; 19362306a36Sopenharmony_ci 19462306a36Sopenharmony_ci /* ensure minimal alignment required by mm core */ 19562306a36Sopenharmony_ci if (!IS_ALIGNED(base | size, CMA_MIN_ALIGNMENT_BYTES)) 19662306a36Sopenharmony_ci return -EINVAL; 19762306a36Sopenharmony_ci 19862306a36Sopenharmony_ci /* 19962306a36Sopenharmony_ci * Each reserved area must be initialised later, when more kernel 20062306a36Sopenharmony_ci * subsystems (like slab allocator) are available. 20162306a36Sopenharmony_ci */ 20262306a36Sopenharmony_ci cma = &cma_areas[cma_area_count]; 20362306a36Sopenharmony_ci 20462306a36Sopenharmony_ci if (name) 20562306a36Sopenharmony_ci snprintf(cma->name, CMA_MAX_NAME, name); 20662306a36Sopenharmony_ci else 20762306a36Sopenharmony_ci snprintf(cma->name, CMA_MAX_NAME, "cma%d\n", cma_area_count); 20862306a36Sopenharmony_ci 20962306a36Sopenharmony_ci cma->base_pfn = PFN_DOWN(base); 21062306a36Sopenharmony_ci cma->count = size >> PAGE_SHIFT; 21162306a36Sopenharmony_ci cma->order_per_bit = order_per_bit; 21262306a36Sopenharmony_ci *res_cma = cma; 21362306a36Sopenharmony_ci cma_area_count++; 21462306a36Sopenharmony_ci totalcma_pages += (size / PAGE_SIZE); 21562306a36Sopenharmony_ci 21662306a36Sopenharmony_ci return 0; 21762306a36Sopenharmony_ci} 21862306a36Sopenharmony_ci 21962306a36Sopenharmony_ci/** 22062306a36Sopenharmony_ci * cma_declare_contiguous_nid() - reserve custom contiguous area 22162306a36Sopenharmony_ci * @base: Base address of the reserved area optional, use 0 for any 22262306a36Sopenharmony_ci * @size: Size of the reserved area (in bytes), 22362306a36Sopenharmony_ci * @limit: End address of the reserved memory (optional, 0 for any). 22462306a36Sopenharmony_ci * @alignment: Alignment for the CMA area, should be power of 2 or zero 22562306a36Sopenharmony_ci * @order_per_bit: Order of pages represented by one bit on bitmap. 22662306a36Sopenharmony_ci * @fixed: hint about where to place the reserved area 22762306a36Sopenharmony_ci * @name: The name of the area. See function cma_init_reserved_mem() 22862306a36Sopenharmony_ci * @res_cma: Pointer to store the created cma region. 22962306a36Sopenharmony_ci * @nid: nid of the free area to find, %NUMA_NO_NODE for any node 23062306a36Sopenharmony_ci * 23162306a36Sopenharmony_ci * This function reserves memory from early allocator. It should be 23262306a36Sopenharmony_ci * called by arch specific code once the early allocator (memblock or bootmem) 23362306a36Sopenharmony_ci * has been activated and all other subsystems have already allocated/reserved 23462306a36Sopenharmony_ci * memory. This function allows to create custom reserved areas. 23562306a36Sopenharmony_ci * 23662306a36Sopenharmony_ci * If @fixed is true, reserve contiguous area at exactly @base. If false, 23762306a36Sopenharmony_ci * reserve in range from @base to @limit. 23862306a36Sopenharmony_ci */ 23962306a36Sopenharmony_ciint __init cma_declare_contiguous_nid(phys_addr_t base, 24062306a36Sopenharmony_ci phys_addr_t size, phys_addr_t limit, 24162306a36Sopenharmony_ci phys_addr_t alignment, unsigned int order_per_bit, 24262306a36Sopenharmony_ci bool fixed, const char *name, struct cma **res_cma, 24362306a36Sopenharmony_ci int nid) 24462306a36Sopenharmony_ci{ 24562306a36Sopenharmony_ci phys_addr_t memblock_end = memblock_end_of_DRAM(); 24662306a36Sopenharmony_ci phys_addr_t highmem_start; 24762306a36Sopenharmony_ci int ret = 0; 24862306a36Sopenharmony_ci 24962306a36Sopenharmony_ci /* 25062306a36Sopenharmony_ci * We can't use __pa(high_memory) directly, since high_memory 25162306a36Sopenharmony_ci * isn't a valid direct map VA, and DEBUG_VIRTUAL will (validly) 25262306a36Sopenharmony_ci * complain. Find the boundary by adding one to the last valid 25362306a36Sopenharmony_ci * address. 25462306a36Sopenharmony_ci */ 25562306a36Sopenharmony_ci highmem_start = __pa(high_memory - 1) + 1; 25662306a36Sopenharmony_ci pr_debug("%s(size %pa, base %pa, limit %pa alignment %pa)\n", 25762306a36Sopenharmony_ci __func__, &size, &base, &limit, &alignment); 25862306a36Sopenharmony_ci 25962306a36Sopenharmony_ci if (cma_area_count == ARRAY_SIZE(cma_areas)) { 26062306a36Sopenharmony_ci pr_err("Not enough slots for CMA reserved regions!\n"); 26162306a36Sopenharmony_ci return -ENOSPC; 26262306a36Sopenharmony_ci } 26362306a36Sopenharmony_ci 26462306a36Sopenharmony_ci if (!size) 26562306a36Sopenharmony_ci return -EINVAL; 26662306a36Sopenharmony_ci 26762306a36Sopenharmony_ci if (alignment && !is_power_of_2(alignment)) 26862306a36Sopenharmony_ci return -EINVAL; 26962306a36Sopenharmony_ci 27062306a36Sopenharmony_ci if (!IS_ENABLED(CONFIG_NUMA)) 27162306a36Sopenharmony_ci nid = NUMA_NO_NODE; 27262306a36Sopenharmony_ci 27362306a36Sopenharmony_ci /* Sanitise input arguments. */ 27462306a36Sopenharmony_ci alignment = max_t(phys_addr_t, alignment, CMA_MIN_ALIGNMENT_BYTES); 27562306a36Sopenharmony_ci if (fixed && base & (alignment - 1)) { 27662306a36Sopenharmony_ci ret = -EINVAL; 27762306a36Sopenharmony_ci pr_err("Region at %pa must be aligned to %pa bytes\n", 27862306a36Sopenharmony_ci &base, &alignment); 27962306a36Sopenharmony_ci goto err; 28062306a36Sopenharmony_ci } 28162306a36Sopenharmony_ci base = ALIGN(base, alignment); 28262306a36Sopenharmony_ci size = ALIGN(size, alignment); 28362306a36Sopenharmony_ci limit &= ~(alignment - 1); 28462306a36Sopenharmony_ci 28562306a36Sopenharmony_ci if (!base) 28662306a36Sopenharmony_ci fixed = false; 28762306a36Sopenharmony_ci 28862306a36Sopenharmony_ci /* size should be aligned with order_per_bit */ 28962306a36Sopenharmony_ci if (!IS_ALIGNED(size >> PAGE_SHIFT, 1 << order_per_bit)) 29062306a36Sopenharmony_ci return -EINVAL; 29162306a36Sopenharmony_ci 29262306a36Sopenharmony_ci /* 29362306a36Sopenharmony_ci * If allocating at a fixed base the request region must not cross the 29462306a36Sopenharmony_ci * low/high memory boundary. 29562306a36Sopenharmony_ci */ 29662306a36Sopenharmony_ci if (fixed && base < highmem_start && base + size > highmem_start) { 29762306a36Sopenharmony_ci ret = -EINVAL; 29862306a36Sopenharmony_ci pr_err("Region at %pa defined on low/high memory boundary (%pa)\n", 29962306a36Sopenharmony_ci &base, &highmem_start); 30062306a36Sopenharmony_ci goto err; 30162306a36Sopenharmony_ci } 30262306a36Sopenharmony_ci 30362306a36Sopenharmony_ci /* 30462306a36Sopenharmony_ci * If the limit is unspecified or above the memblock end, its effective 30562306a36Sopenharmony_ci * value will be the memblock end. Set it explicitly to simplify further 30662306a36Sopenharmony_ci * checks. 30762306a36Sopenharmony_ci */ 30862306a36Sopenharmony_ci if (limit == 0 || limit > memblock_end) 30962306a36Sopenharmony_ci limit = memblock_end; 31062306a36Sopenharmony_ci 31162306a36Sopenharmony_ci if (base + size > limit) { 31262306a36Sopenharmony_ci ret = -EINVAL; 31362306a36Sopenharmony_ci pr_err("Size (%pa) of region at %pa exceeds limit (%pa)\n", 31462306a36Sopenharmony_ci &size, &base, &limit); 31562306a36Sopenharmony_ci goto err; 31662306a36Sopenharmony_ci } 31762306a36Sopenharmony_ci 31862306a36Sopenharmony_ci /* Reserve memory */ 31962306a36Sopenharmony_ci if (fixed) { 32062306a36Sopenharmony_ci if (memblock_is_region_reserved(base, size) || 32162306a36Sopenharmony_ci memblock_reserve(base, size) < 0) { 32262306a36Sopenharmony_ci ret = -EBUSY; 32362306a36Sopenharmony_ci goto err; 32462306a36Sopenharmony_ci } 32562306a36Sopenharmony_ci } else { 32662306a36Sopenharmony_ci phys_addr_t addr = 0; 32762306a36Sopenharmony_ci 32862306a36Sopenharmony_ci /* 32962306a36Sopenharmony_ci * If there is enough memory, try a bottom-up allocation first. 33062306a36Sopenharmony_ci * It will place the new cma area close to the start of the node 33162306a36Sopenharmony_ci * and guarantee that the compaction is moving pages out of the 33262306a36Sopenharmony_ci * cma area and not into it. 33362306a36Sopenharmony_ci * Avoid using first 4GB to not interfere with constrained zones 33462306a36Sopenharmony_ci * like DMA/DMA32. 33562306a36Sopenharmony_ci */ 33662306a36Sopenharmony_ci#ifdef CONFIG_PHYS_ADDR_T_64BIT 33762306a36Sopenharmony_ci if (!memblock_bottom_up() && memblock_end >= SZ_4G + size) { 33862306a36Sopenharmony_ci memblock_set_bottom_up(true); 33962306a36Sopenharmony_ci addr = memblock_alloc_range_nid(size, alignment, SZ_4G, 34062306a36Sopenharmony_ci limit, nid, true); 34162306a36Sopenharmony_ci memblock_set_bottom_up(false); 34262306a36Sopenharmony_ci } 34362306a36Sopenharmony_ci#endif 34462306a36Sopenharmony_ci 34562306a36Sopenharmony_ci /* 34662306a36Sopenharmony_ci * All pages in the reserved area must come from the same zone. 34762306a36Sopenharmony_ci * If the requested region crosses the low/high memory boundary, 34862306a36Sopenharmony_ci * try allocating from high memory first and fall back to low 34962306a36Sopenharmony_ci * memory in case of failure. 35062306a36Sopenharmony_ci */ 35162306a36Sopenharmony_ci if (!addr && base < highmem_start && limit > highmem_start) { 35262306a36Sopenharmony_ci addr = memblock_alloc_range_nid(size, alignment, 35362306a36Sopenharmony_ci highmem_start, limit, nid, true); 35462306a36Sopenharmony_ci limit = highmem_start; 35562306a36Sopenharmony_ci } 35662306a36Sopenharmony_ci 35762306a36Sopenharmony_ci if (!addr) { 35862306a36Sopenharmony_ci addr = memblock_alloc_range_nid(size, alignment, base, 35962306a36Sopenharmony_ci limit, nid, true); 36062306a36Sopenharmony_ci if (!addr) { 36162306a36Sopenharmony_ci ret = -ENOMEM; 36262306a36Sopenharmony_ci goto err; 36362306a36Sopenharmony_ci } 36462306a36Sopenharmony_ci } 36562306a36Sopenharmony_ci 36662306a36Sopenharmony_ci /* 36762306a36Sopenharmony_ci * kmemleak scans/reads tracked objects for pointers to other 36862306a36Sopenharmony_ci * objects but this address isn't mapped and accessible 36962306a36Sopenharmony_ci */ 37062306a36Sopenharmony_ci kmemleak_ignore_phys(addr); 37162306a36Sopenharmony_ci base = addr; 37262306a36Sopenharmony_ci } 37362306a36Sopenharmony_ci 37462306a36Sopenharmony_ci ret = cma_init_reserved_mem(base, size, order_per_bit, name, res_cma); 37562306a36Sopenharmony_ci if (ret) 37662306a36Sopenharmony_ci goto free_mem; 37762306a36Sopenharmony_ci 37862306a36Sopenharmony_ci pr_info("Reserved %ld MiB at %pa on node %d\n", (unsigned long)size / SZ_1M, 37962306a36Sopenharmony_ci &base, nid); 38062306a36Sopenharmony_ci return 0; 38162306a36Sopenharmony_ci 38262306a36Sopenharmony_cifree_mem: 38362306a36Sopenharmony_ci memblock_phys_free(base, size); 38462306a36Sopenharmony_cierr: 38562306a36Sopenharmony_ci pr_err("Failed to reserve %ld MiB on node %d\n", (unsigned long)size / SZ_1M, 38662306a36Sopenharmony_ci nid); 38762306a36Sopenharmony_ci return ret; 38862306a36Sopenharmony_ci} 38962306a36Sopenharmony_ci 39062306a36Sopenharmony_ci#ifdef CONFIG_CMA_DEBUG 39162306a36Sopenharmony_cistatic void cma_debug_show_areas(struct cma *cma) 39262306a36Sopenharmony_ci{ 39362306a36Sopenharmony_ci unsigned long next_zero_bit, next_set_bit, nr_zero; 39462306a36Sopenharmony_ci unsigned long start = 0; 39562306a36Sopenharmony_ci unsigned long nr_part, nr_total = 0; 39662306a36Sopenharmony_ci unsigned long nbits = cma_bitmap_maxno(cma); 39762306a36Sopenharmony_ci 39862306a36Sopenharmony_ci spin_lock_irq(&cma->lock); 39962306a36Sopenharmony_ci pr_info("number of available pages: "); 40062306a36Sopenharmony_ci for (;;) { 40162306a36Sopenharmony_ci next_zero_bit = find_next_zero_bit(cma->bitmap, nbits, start); 40262306a36Sopenharmony_ci if (next_zero_bit >= nbits) 40362306a36Sopenharmony_ci break; 40462306a36Sopenharmony_ci next_set_bit = find_next_bit(cma->bitmap, nbits, next_zero_bit); 40562306a36Sopenharmony_ci nr_zero = next_set_bit - next_zero_bit; 40662306a36Sopenharmony_ci nr_part = nr_zero << cma->order_per_bit; 40762306a36Sopenharmony_ci pr_cont("%s%lu@%lu", nr_total ? "+" : "", nr_part, 40862306a36Sopenharmony_ci next_zero_bit); 40962306a36Sopenharmony_ci nr_total += nr_part; 41062306a36Sopenharmony_ci start = next_zero_bit + nr_zero; 41162306a36Sopenharmony_ci } 41262306a36Sopenharmony_ci pr_cont("=> %lu free of %lu total pages\n", nr_total, cma->count); 41362306a36Sopenharmony_ci spin_unlock_irq(&cma->lock); 41462306a36Sopenharmony_ci} 41562306a36Sopenharmony_ci#else 41662306a36Sopenharmony_cistatic inline void cma_debug_show_areas(struct cma *cma) { } 41762306a36Sopenharmony_ci#endif 41862306a36Sopenharmony_ci 41962306a36Sopenharmony_ci/** 42062306a36Sopenharmony_ci * cma_alloc() - allocate pages from contiguous area 42162306a36Sopenharmony_ci * @cma: Contiguous memory region for which the allocation is performed. 42262306a36Sopenharmony_ci * @count: Requested number of pages. 42362306a36Sopenharmony_ci * @align: Requested alignment of pages (in PAGE_SIZE order). 42462306a36Sopenharmony_ci * @no_warn: Avoid printing message about failed allocation 42562306a36Sopenharmony_ci * 42662306a36Sopenharmony_ci * This function allocates part of contiguous memory on specific 42762306a36Sopenharmony_ci * contiguous memory area. 42862306a36Sopenharmony_ci */ 42962306a36Sopenharmony_cistruct page *cma_alloc(struct cma *cma, unsigned long count, 43062306a36Sopenharmony_ci unsigned int align, bool no_warn) 43162306a36Sopenharmony_ci{ 43262306a36Sopenharmony_ci unsigned long mask, offset; 43362306a36Sopenharmony_ci unsigned long pfn = -1; 43462306a36Sopenharmony_ci unsigned long start = 0; 43562306a36Sopenharmony_ci unsigned long bitmap_maxno, bitmap_no, bitmap_count; 43662306a36Sopenharmony_ci unsigned long i; 43762306a36Sopenharmony_ci struct page *page = NULL; 43862306a36Sopenharmony_ci int ret = -ENOMEM; 43962306a36Sopenharmony_ci 44062306a36Sopenharmony_ci if (!cma || !cma->count || !cma->bitmap) 44162306a36Sopenharmony_ci goto out; 44262306a36Sopenharmony_ci 44362306a36Sopenharmony_ci pr_debug("%s(cma %p, name: %s, count %lu, align %d)\n", __func__, 44462306a36Sopenharmony_ci (void *)cma, cma->name, count, align); 44562306a36Sopenharmony_ci 44662306a36Sopenharmony_ci if (!count) 44762306a36Sopenharmony_ci goto out; 44862306a36Sopenharmony_ci 44962306a36Sopenharmony_ci trace_cma_alloc_start(cma->name, count, align); 45062306a36Sopenharmony_ci 45162306a36Sopenharmony_ci mask = cma_bitmap_aligned_mask(cma, align); 45262306a36Sopenharmony_ci offset = cma_bitmap_aligned_offset(cma, align); 45362306a36Sopenharmony_ci bitmap_maxno = cma_bitmap_maxno(cma); 45462306a36Sopenharmony_ci bitmap_count = cma_bitmap_pages_to_bits(cma, count); 45562306a36Sopenharmony_ci 45662306a36Sopenharmony_ci if (bitmap_count > bitmap_maxno) 45762306a36Sopenharmony_ci goto out; 45862306a36Sopenharmony_ci 45962306a36Sopenharmony_ci for (;;) { 46062306a36Sopenharmony_ci spin_lock_irq(&cma->lock); 46162306a36Sopenharmony_ci bitmap_no = bitmap_find_next_zero_area_off(cma->bitmap, 46262306a36Sopenharmony_ci bitmap_maxno, start, bitmap_count, mask, 46362306a36Sopenharmony_ci offset); 46462306a36Sopenharmony_ci if (bitmap_no >= bitmap_maxno) { 46562306a36Sopenharmony_ci spin_unlock_irq(&cma->lock); 46662306a36Sopenharmony_ci break; 46762306a36Sopenharmony_ci } 46862306a36Sopenharmony_ci bitmap_set(cma->bitmap, bitmap_no, bitmap_count); 46962306a36Sopenharmony_ci /* 47062306a36Sopenharmony_ci * It's safe to drop the lock here. We've marked this region for 47162306a36Sopenharmony_ci * our exclusive use. If the migration fails we will take the 47262306a36Sopenharmony_ci * lock again and unmark it. 47362306a36Sopenharmony_ci */ 47462306a36Sopenharmony_ci spin_unlock_irq(&cma->lock); 47562306a36Sopenharmony_ci 47662306a36Sopenharmony_ci pfn = cma->base_pfn + (bitmap_no << cma->order_per_bit); 47762306a36Sopenharmony_ci mutex_lock(&cma_mutex); 47862306a36Sopenharmony_ci ret = alloc_contig_range(pfn, pfn + count, MIGRATE_CMA, 47962306a36Sopenharmony_ci GFP_KERNEL | (no_warn ? __GFP_NOWARN : 0)); 48062306a36Sopenharmony_ci mutex_unlock(&cma_mutex); 48162306a36Sopenharmony_ci if (ret == 0) { 48262306a36Sopenharmony_ci page = pfn_to_page(pfn); 48362306a36Sopenharmony_ci break; 48462306a36Sopenharmony_ci } 48562306a36Sopenharmony_ci 48662306a36Sopenharmony_ci cma_clear_bitmap(cma, pfn, count); 48762306a36Sopenharmony_ci if (ret != -EBUSY) 48862306a36Sopenharmony_ci break; 48962306a36Sopenharmony_ci 49062306a36Sopenharmony_ci pr_debug("%s(): memory range at pfn 0x%lx %p is busy, retrying\n", 49162306a36Sopenharmony_ci __func__, pfn, pfn_to_page(pfn)); 49262306a36Sopenharmony_ci 49362306a36Sopenharmony_ci trace_cma_alloc_busy_retry(cma->name, pfn, pfn_to_page(pfn), 49462306a36Sopenharmony_ci count, align); 49562306a36Sopenharmony_ci /* try again with a bit different memory target */ 49662306a36Sopenharmony_ci start = bitmap_no + mask + 1; 49762306a36Sopenharmony_ci } 49862306a36Sopenharmony_ci 49962306a36Sopenharmony_ci trace_cma_alloc_finish(cma->name, pfn, page, count, align, ret); 50062306a36Sopenharmony_ci 50162306a36Sopenharmony_ci /* 50262306a36Sopenharmony_ci * CMA can allocate multiple page blocks, which results in different 50362306a36Sopenharmony_ci * blocks being marked with different tags. Reset the tags to ignore 50462306a36Sopenharmony_ci * those page blocks. 50562306a36Sopenharmony_ci */ 50662306a36Sopenharmony_ci if (page) { 50762306a36Sopenharmony_ci for (i = 0; i < count; i++) 50862306a36Sopenharmony_ci page_kasan_tag_reset(nth_page(page, i)); 50962306a36Sopenharmony_ci } 51062306a36Sopenharmony_ci 51162306a36Sopenharmony_ci if (ret && !no_warn) { 51262306a36Sopenharmony_ci pr_err_ratelimited("%s: %s: alloc failed, req-size: %lu pages, ret: %d\n", 51362306a36Sopenharmony_ci __func__, cma->name, count, ret); 51462306a36Sopenharmony_ci cma_debug_show_areas(cma); 51562306a36Sopenharmony_ci } 51662306a36Sopenharmony_ci 51762306a36Sopenharmony_ci pr_debug("%s(): returned %p\n", __func__, page); 51862306a36Sopenharmony_ciout: 51962306a36Sopenharmony_ci if (page) { 52062306a36Sopenharmony_ci count_vm_event(CMA_ALLOC_SUCCESS); 52162306a36Sopenharmony_ci cma_sysfs_account_success_pages(cma, count); 52262306a36Sopenharmony_ci } else { 52362306a36Sopenharmony_ci count_vm_event(CMA_ALLOC_FAIL); 52462306a36Sopenharmony_ci if (cma) 52562306a36Sopenharmony_ci cma_sysfs_account_fail_pages(cma, count); 52662306a36Sopenharmony_ci } 52762306a36Sopenharmony_ci 52862306a36Sopenharmony_ci return page; 52962306a36Sopenharmony_ci} 53062306a36Sopenharmony_ci 53162306a36Sopenharmony_cibool cma_pages_valid(struct cma *cma, const struct page *pages, 53262306a36Sopenharmony_ci unsigned long count) 53362306a36Sopenharmony_ci{ 53462306a36Sopenharmony_ci unsigned long pfn; 53562306a36Sopenharmony_ci 53662306a36Sopenharmony_ci if (!cma || !pages) 53762306a36Sopenharmony_ci return false; 53862306a36Sopenharmony_ci 53962306a36Sopenharmony_ci pfn = page_to_pfn(pages); 54062306a36Sopenharmony_ci 54162306a36Sopenharmony_ci if (pfn < cma->base_pfn || pfn >= cma->base_pfn + cma->count) { 54262306a36Sopenharmony_ci pr_debug("%s(page %p, count %lu)\n", __func__, 54362306a36Sopenharmony_ci (void *)pages, count); 54462306a36Sopenharmony_ci return false; 54562306a36Sopenharmony_ci } 54662306a36Sopenharmony_ci 54762306a36Sopenharmony_ci return true; 54862306a36Sopenharmony_ci} 54962306a36Sopenharmony_ci 55062306a36Sopenharmony_ci/** 55162306a36Sopenharmony_ci * cma_release() - release allocated pages 55262306a36Sopenharmony_ci * @cma: Contiguous memory region for which the allocation is performed. 55362306a36Sopenharmony_ci * @pages: Allocated pages. 55462306a36Sopenharmony_ci * @count: Number of allocated pages. 55562306a36Sopenharmony_ci * 55662306a36Sopenharmony_ci * This function releases memory allocated by cma_alloc(). 55762306a36Sopenharmony_ci * It returns false when provided pages do not belong to contiguous area and 55862306a36Sopenharmony_ci * true otherwise. 55962306a36Sopenharmony_ci */ 56062306a36Sopenharmony_cibool cma_release(struct cma *cma, const struct page *pages, 56162306a36Sopenharmony_ci unsigned long count) 56262306a36Sopenharmony_ci{ 56362306a36Sopenharmony_ci unsigned long pfn; 56462306a36Sopenharmony_ci 56562306a36Sopenharmony_ci if (!cma_pages_valid(cma, pages, count)) 56662306a36Sopenharmony_ci return false; 56762306a36Sopenharmony_ci 56862306a36Sopenharmony_ci pr_debug("%s(page %p, count %lu)\n", __func__, (void *)pages, count); 56962306a36Sopenharmony_ci 57062306a36Sopenharmony_ci pfn = page_to_pfn(pages); 57162306a36Sopenharmony_ci 57262306a36Sopenharmony_ci VM_BUG_ON(pfn + count > cma->base_pfn + cma->count); 57362306a36Sopenharmony_ci 57462306a36Sopenharmony_ci free_contig_range(pfn, count); 57562306a36Sopenharmony_ci cma_clear_bitmap(cma, pfn, count); 57662306a36Sopenharmony_ci trace_cma_release(cma->name, pfn, pages, count); 57762306a36Sopenharmony_ci 57862306a36Sopenharmony_ci return true; 57962306a36Sopenharmony_ci} 58062306a36Sopenharmony_ci 58162306a36Sopenharmony_ciint cma_for_each_area(int (*it)(struct cma *cma, void *data), void *data) 58262306a36Sopenharmony_ci{ 58362306a36Sopenharmony_ci int i; 58462306a36Sopenharmony_ci 58562306a36Sopenharmony_ci for (i = 0; i < cma_area_count; i++) { 58662306a36Sopenharmony_ci int ret = it(&cma_areas[i], data); 58762306a36Sopenharmony_ci 58862306a36Sopenharmony_ci if (ret) 58962306a36Sopenharmony_ci return ret; 59062306a36Sopenharmony_ci } 59162306a36Sopenharmony_ci 59262306a36Sopenharmony_ci return 0; 59362306a36Sopenharmony_ci} 594