13d0407baSopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-or-later */
23d0407baSopenharmony_ci#ifndef _LINUX_MEMBLOCK_H
33d0407baSopenharmony_ci#define _LINUX_MEMBLOCK_H
43d0407baSopenharmony_ci#ifdef __KERNEL__
53d0407baSopenharmony_ci
63d0407baSopenharmony_ci/*
73d0407baSopenharmony_ci * Logical memory blocks.
83d0407baSopenharmony_ci *
93d0407baSopenharmony_ci * Copyright (C) 2001 Peter Bergner, IBM Corp.
103d0407baSopenharmony_ci */
113d0407baSopenharmony_ci
123d0407baSopenharmony_ci#include <linux/init.h>
133d0407baSopenharmony_ci#include <linux/mm.h>
143d0407baSopenharmony_ci#include <asm/dma.h>
153d0407baSopenharmony_ci
163d0407baSopenharmony_ciextern unsigned long max_low_pfn;
173d0407baSopenharmony_ciextern unsigned long min_low_pfn;
183d0407baSopenharmony_ci
193d0407baSopenharmony_ci/*
203d0407baSopenharmony_ci * highest page
213d0407baSopenharmony_ci */
223d0407baSopenharmony_ciextern unsigned long max_pfn;
233d0407baSopenharmony_ci/*
243d0407baSopenharmony_ci * highest possible page
253d0407baSopenharmony_ci */
263d0407baSopenharmony_ciextern unsigned long long max_possible_pfn;
273d0407baSopenharmony_ci
283d0407baSopenharmony_ci#ifdef CONFIG_ROCKCHIP_THUNDER_BOOT
293d0407baSopenharmony_ciextern int defer_free_memblock(void *unused);
303d0407baSopenharmony_ci#endif
313d0407baSopenharmony_ci
323d0407baSopenharmony_ci/**
333d0407baSopenharmony_ci * enum memblock_flags - definition of memory region attributes
343d0407baSopenharmony_ci * @MEMBLOCK_NONE: no special request
353d0407baSopenharmony_ci * @MEMBLOCK_HOTPLUG: hotpluggable region
363d0407baSopenharmony_ci * @MEMBLOCK_MIRROR: mirrored region
373d0407baSopenharmony_ci * @MEMBLOCK_NOMAP: don't add to kernel direct mapping
383d0407baSopenharmony_ci */
393d0407baSopenharmony_cienum memblock_flags {
403d0407baSopenharmony_ci    MEMBLOCK_NONE = 0x0,    /* No special request */
413d0407baSopenharmony_ci    MEMBLOCK_HOTPLUG = 0x1, /* hotpluggable region */
423d0407baSopenharmony_ci    MEMBLOCK_MIRROR = 0x2,  /* mirrored region */
433d0407baSopenharmony_ci    MEMBLOCK_NOMAP = 0x4,   /* don't add to kernel direct mapping */
443d0407baSopenharmony_ci};
453d0407baSopenharmony_ci
463d0407baSopenharmony_ci/**
473d0407baSopenharmony_ci * struct memblock_region - represents a memory region
483d0407baSopenharmony_ci * @base: base address of the region
493d0407baSopenharmony_ci * @size: size of the region
503d0407baSopenharmony_ci * @flags: memory region attributes
513d0407baSopenharmony_ci * @nid: NUMA node id
523d0407baSopenharmony_ci */
533d0407baSopenharmony_cistruct memblock_region {
543d0407baSopenharmony_ci    phys_addr_t base;
553d0407baSopenharmony_ci    phys_addr_t size;
563d0407baSopenharmony_ci    enum memblock_flags flags;
573d0407baSopenharmony_ci#ifdef CONFIG_NEED_MULTIPLE_NODES
583d0407baSopenharmony_ci    int nid;
593d0407baSopenharmony_ci#endif
603d0407baSopenharmony_ci};
613d0407baSopenharmony_ci
623d0407baSopenharmony_ci/**
633d0407baSopenharmony_ci * struct memblock_type - collection of memory regions of certain type
643d0407baSopenharmony_ci * @cnt: number of regions
653d0407baSopenharmony_ci * @max: size of the allocated array
663d0407baSopenharmony_ci * @total_size: size of all regions
673d0407baSopenharmony_ci * @regions: array of regions
683d0407baSopenharmony_ci * @name: the memory type symbolic name
693d0407baSopenharmony_ci */
703d0407baSopenharmony_cistruct memblock_type {
713d0407baSopenharmony_ci    unsigned long cnt;
723d0407baSopenharmony_ci    unsigned long max;
733d0407baSopenharmony_ci    phys_addr_t total_size;
743d0407baSopenharmony_ci    struct memblock_region *regions;
753d0407baSopenharmony_ci    char *name;
763d0407baSopenharmony_ci};
773d0407baSopenharmony_ci
783d0407baSopenharmony_ci/**
793d0407baSopenharmony_ci * struct memblock - memblock allocator metadata
803d0407baSopenharmony_ci * @bottom_up: is bottom up direction?
813d0407baSopenharmony_ci * @current_limit: physical address of the current allocation limit
823d0407baSopenharmony_ci * @memory: usable memory regions
833d0407baSopenharmony_ci * @reserved: reserved memory regions
843d0407baSopenharmony_ci */
853d0407baSopenharmony_cistruct memblock {
863d0407baSopenharmony_ci    bool bottom_up; /* is bottom up direction? */
873d0407baSopenharmony_ci    phys_addr_t current_limit;
883d0407baSopenharmony_ci    struct memblock_type memory;
893d0407baSopenharmony_ci    struct memblock_type reserved;
903d0407baSopenharmony_ci};
913d0407baSopenharmony_ci
923d0407baSopenharmony_ciextern struct memblock memblock;
933d0407baSopenharmony_ci
943d0407baSopenharmony_ci#ifndef CONFIG_ARCH_KEEP_MEMBLOCK
953d0407baSopenharmony_ci#define __init_memblock __meminit
963d0407baSopenharmony_ci#define __initdata_memblock __meminitdata
973d0407baSopenharmony_civoid memblock_discard(void);
983d0407baSopenharmony_ci#else
993d0407baSopenharmony_ci#define __init_memblock
1003d0407baSopenharmony_ci#define __initdata_memblock
1013d0407baSopenharmony_cistatic inline void memblock_discard(void)
1023d0407baSopenharmony_ci{
1033d0407baSopenharmony_ci}
1043d0407baSopenharmony_ci#endif
1053d0407baSopenharmony_ci
1063d0407baSopenharmony_ciphys_addr_t memblock_find_in_range(phys_addr_t start, phys_addr_t end, phys_addr_t size, phys_addr_t align);
1073d0407baSopenharmony_civoid memblock_allow_resize(void);
1083d0407baSopenharmony_ciint memblock_add_node(phys_addr_t base, phys_addr_t size, int nid);
1093d0407baSopenharmony_ciint memblock_add(phys_addr_t base, phys_addr_t size);
1103d0407baSopenharmony_ciint memblock_remove(phys_addr_t base, phys_addr_t size);
1113d0407baSopenharmony_ciint memblock_free(phys_addr_t base, phys_addr_t size);
1123d0407baSopenharmony_ciint memblock_reserve(phys_addr_t base, phys_addr_t size);
1133d0407baSopenharmony_ci#ifdef CONFIG_HAVE_MEMBLOCK_PHYS_MAP
1143d0407baSopenharmony_ciint memblock_physmem_add(phys_addr_t base, phys_addr_t size);
1153d0407baSopenharmony_ci#endif
1163d0407baSopenharmony_civoid memblock_trim_memory(phys_addr_t align);
1173d0407baSopenharmony_cibool memblock_overlaps_region(struct memblock_type *type, phys_addr_t base, phys_addr_t size);
1183d0407baSopenharmony_ciint memblock_mark_hotplug(phys_addr_t base, phys_addr_t size);
1193d0407baSopenharmony_ciint memblock_clear_hotplug(phys_addr_t base, phys_addr_t size);
1203d0407baSopenharmony_ciint memblock_mark_mirror(phys_addr_t base, phys_addr_t size);
1213d0407baSopenharmony_ciint memblock_mark_nomap(phys_addr_t base, phys_addr_t size);
1223d0407baSopenharmony_ciint memblock_clear_nomap(phys_addr_t base, phys_addr_t size);
1233d0407baSopenharmony_ci
1243d0407baSopenharmony_ciunsigned long memblock_free_all(void);
1253d0407baSopenharmony_civoid reset_node_managed_pages(pg_data_t *pgdat);
1263d0407baSopenharmony_civoid reset_all_zones_managed_pages(void);
1273d0407baSopenharmony_ci
1283d0407baSopenharmony_ci/* Low level functions */
1293d0407baSopenharmony_civoid __next_mem_range(u64 *idx, int nid, enum memblock_flags flags, struct memblock_type *type_a,
1303d0407baSopenharmony_ci                      struct memblock_type *type_b, phys_addr_t *out_start, phys_addr_t *out_end, int *out_nid);
1313d0407baSopenharmony_ci
1323d0407baSopenharmony_civoid __next_mem_range_rev(u64 *idx, int nid, enum memblock_flags flags, struct memblock_type *type_a,
1333d0407baSopenharmony_ci                          struct memblock_type *type_b, phys_addr_t *out_start, phys_addr_t *out_end, int *out_nid);
1343d0407baSopenharmony_ci
1353d0407baSopenharmony_civoid __memblock_free_late(phys_addr_t base, phys_addr_t size);
1363d0407baSopenharmony_ci
1373d0407baSopenharmony_ci#ifdef CONFIG_HAVE_MEMBLOCK_PHYS_MAP
1383d0407baSopenharmony_cistatic inline void _next_physmem_range(u64 *idx, struct memblock_type *type, phys_addr_t *out_start,
1393d0407baSopenharmony_ci                                       phys_addr_t *out_end)
1403d0407baSopenharmony_ci{
1413d0407baSopenharmony_ci    extern struct memblock_type physmem;
1423d0407baSopenharmony_ci
1433d0407baSopenharmony_ci    __next_mem_range(idx, NUMA_NO_NODE, MEMBLOCK_NONE, &physmem, type, out_start, out_end, NULL);
1443d0407baSopenharmony_ci}
1453d0407baSopenharmony_ci
1463d0407baSopenharmony_ci/**
1473d0407baSopenharmony_ci * for_each_physmem_range - iterate through physmem areas not included in type.
1483d0407baSopenharmony_ci * @i: u64 used as loop variable
1493d0407baSopenharmony_ci * @type: ptr to memblock_type which excludes from the iteration, can be %NULL
1503d0407baSopenharmony_ci * @p_start: ptr to phys_addr_t for start address of the range, can be %NULL
1513d0407baSopenharmony_ci * @p_end: ptr to phys_addr_t for end address of the range, can be %NULL
1523d0407baSopenharmony_ci */
1533d0407baSopenharmony_ci#define for_each_physmem_range(i, type, p_start, p_end)                                                                \
1543d0407baSopenharmony_ci    for (i = 0, _next_physmem_range(&i, type, p_start, p_end); i != (u64)ULLONG_MAX;                                   \
1553d0407baSopenharmony_ci         _next_physmem_range(&i, type, p_start, p_end))
1563d0407baSopenharmony_ci#endif /* CONFIG_HAVE_MEMBLOCK_PHYS_MAP */
1573d0407baSopenharmony_ci
1583d0407baSopenharmony_ci/**
1593d0407baSopenharmony_ci * _for_each_mem_range - iterate through memblock areas from type_a and not
1603d0407baSopenharmony_ci * included in type_b. Or just type_a if type_b is NULL.
1613d0407baSopenharmony_ci * @i: u64 used as loop variable
1623d0407baSopenharmony_ci * @type_a: ptr to memblock_type to iterate
1633d0407baSopenharmony_ci * @type_b: ptr to memblock_type which excludes from the iteration
1643d0407baSopenharmony_ci * @nid: node selector, %NUMA_NO_NODE for all nodes
1653d0407baSopenharmony_ci * @flags: pick from blocks based on memory attributes
1663d0407baSopenharmony_ci * @p_start: ptr to phys_addr_t for start address of the range, can be %NULL
1673d0407baSopenharmony_ci * @p_end: ptr to phys_addr_t for end address of the range, can be %NULL
1683d0407baSopenharmony_ci * @p_nid: ptr to int for nid of the range, can be %NULL
1693d0407baSopenharmony_ci */
1703d0407baSopenharmony_ci#define _for_each_mem_range(i, type_a, type_b, nid, flags, p_start, p_end, p_nid)                                      \
1713d0407baSopenharmony_ci    for (i = 0, __next_mem_range(&i, nid, flags, type_a, type_b, p_start, p_end, p_nid); i != (u64)ULLONG_MAX;         \
1723d0407baSopenharmony_ci         __next_mem_range(&i, nid, flags, type_a, type_b, p_start, p_end, p_nid))
1733d0407baSopenharmony_ci
1743d0407baSopenharmony_ci/**
1753d0407baSopenharmony_ci * _for_each_mem_range_rev - reverse iterate through memblock areas from
1763d0407baSopenharmony_ci * type_a and not included in type_b. Or just type_a if type_b is NULL.
1773d0407baSopenharmony_ci * @i: u64 used as loop variable
1783d0407baSopenharmony_ci * @type_a: ptr to memblock_type to iterate
1793d0407baSopenharmony_ci * @type_b: ptr to memblock_type which excludes from the iteration
1803d0407baSopenharmony_ci * @nid: node selector, %NUMA_NO_NODE for all nodes
1813d0407baSopenharmony_ci * @flags: pick from blocks based on memory attributes
1823d0407baSopenharmony_ci * @p_start: ptr to phys_addr_t for start address of the range, can be %NULL
1833d0407baSopenharmony_ci * @p_end: ptr to phys_addr_t for end address of the range, can be %NULL
1843d0407baSopenharmony_ci * @p_nid: ptr to int for nid of the range, can be %NULL
1853d0407baSopenharmony_ci */
1863d0407baSopenharmony_ci#define _for_each_mem_range_rev(i, type_a, type_b, nid, flags, p_start, p_end, p_nid)                                  \
1873d0407baSopenharmony_ci    for (i = (u64)ULLONG_MAX, __next_mem_range_rev(&i, nid, flags, type_a, type_b, p_start, p_end, p_nid);             \
1883d0407baSopenharmony_ci         i != (u64)ULLONG_MAX; __next_mem_range_rev(&i, nid, flags, type_a, type_b, p_start, p_end, p_nid))
1893d0407baSopenharmony_ci
1903d0407baSopenharmony_ci/**
1913d0407baSopenharmony_ci * for_each_mem_range - iterate through memory areas.
1923d0407baSopenharmony_ci * @i: u64 used as loop variable
1933d0407baSopenharmony_ci * @p_start: ptr to phys_addr_t for start address of the range, can be %NULL
1943d0407baSopenharmony_ci * @p_end: ptr to phys_addr_t for end address of the range, can be %NULL
1953d0407baSopenharmony_ci */
1963d0407baSopenharmony_ci#define for_each_mem_range(i, p_start, p_end)                                                                          \
1973d0407baSopenharmony_ci    _for_each_mem_range(i, &memblock.memory, NULL, NUMA_NO_NODE, MEMBLOCK_HOTPLUG, p_start, p_end, NULL)
1983d0407baSopenharmony_ci
1993d0407baSopenharmony_ci/**
2003d0407baSopenharmony_ci * for_each_mem_range_rev - reverse iterate through memblock areas from
2013d0407baSopenharmony_ci * type_a and not included in type_b. Or just type_a if type_b is NULL.
2023d0407baSopenharmony_ci * @i: u64 used as loop variable
2033d0407baSopenharmony_ci * @p_start: ptr to phys_addr_t for start address of the range, can be %NULL
2043d0407baSopenharmony_ci * @p_end: ptr to phys_addr_t for end address of the range, can be %NULL
2053d0407baSopenharmony_ci */
2063d0407baSopenharmony_ci#define for_each_mem_range_rev(i, p_start, p_end)                                                                      \
2073d0407baSopenharmony_ci    _for_each_mem_range_rev(i, &memblock.memory, NULL, NUMA_NO_NODE, MEMBLOCK_HOTPLUG, p_start, p_end, NULL)
2083d0407baSopenharmony_ci
2093d0407baSopenharmony_ci/**
2103d0407baSopenharmony_ci * for_each_reserved_mem_range - iterate over all reserved memblock areas
2113d0407baSopenharmony_ci * @i: u64 used as loop variable
2123d0407baSopenharmony_ci * @p_start: ptr to phys_addr_t for start address of the range, can be %NULL
2133d0407baSopenharmony_ci * @p_end: ptr to phys_addr_t for end address of the range, can be %NULL
2143d0407baSopenharmony_ci *
2153d0407baSopenharmony_ci * Walks over reserved areas of memblock. Available as soon as memblock
2163d0407baSopenharmony_ci * is initialized.
2173d0407baSopenharmony_ci */
2183d0407baSopenharmony_ci#define for_each_reserved_mem_range(i, p_start, p_end)                                                                 \
2193d0407baSopenharmony_ci    _for_each_mem_range(i, &memblock.reserved, NULL, NUMA_NO_NODE, MEMBLOCK_NONE, p_start, p_end, NULL)
2203d0407baSopenharmony_ci
2213d0407baSopenharmony_cistatic inline bool memblock_is_hotpluggable(struct memblock_region *m)
2223d0407baSopenharmony_ci{
2233d0407baSopenharmony_ci    return m->flags & MEMBLOCK_HOTPLUG;
2243d0407baSopenharmony_ci}
2253d0407baSopenharmony_ci
2263d0407baSopenharmony_cistatic inline bool memblock_is_mirror(struct memblock_region *m)
2273d0407baSopenharmony_ci{
2283d0407baSopenharmony_ci    return m->flags & MEMBLOCK_MIRROR;
2293d0407baSopenharmony_ci}
2303d0407baSopenharmony_ci
2313d0407baSopenharmony_cistatic inline bool memblock_is_nomap(struct memblock_region *m)
2323d0407baSopenharmony_ci{
2333d0407baSopenharmony_ci    return m->flags & MEMBLOCK_NOMAP;
2343d0407baSopenharmony_ci}
2353d0407baSopenharmony_ci
2363d0407baSopenharmony_ciint memblock_search_pfn_nid(unsigned long pfn, unsigned long *start_pfn, unsigned long *end_pfn);
2373d0407baSopenharmony_civoid __next_mem_pfn_range(int *idx, int nid, unsigned long *out_start_pfn, unsigned long *out_end_pfn, int *out_nid);
2383d0407baSopenharmony_ci
2393d0407baSopenharmony_ci/**
2403d0407baSopenharmony_ci * for_each_mem_pfn_range - early memory pfn range iterator
2413d0407baSopenharmony_ci * @i: an integer used as loop variable
2423d0407baSopenharmony_ci * @nid: node selector, %MAX_NUMNODES for all nodes
2433d0407baSopenharmony_ci * @p_start: ptr to ulong for start pfn of the range, can be %NULL
2443d0407baSopenharmony_ci * @p_end: ptr to ulong for end pfn of the range, can be %NULL
2453d0407baSopenharmony_ci * @p_nid: ptr to int for nid of the range, can be %NULL
2463d0407baSopenharmony_ci *
2473d0407baSopenharmony_ci * Walks over configured memory ranges.
2483d0407baSopenharmony_ci */
2493d0407baSopenharmony_ci#define for_each_mem_pfn_range(i, nid, p_start, p_end, p_nid)                                                          \
2503d0407baSopenharmony_ci    for (i = -1, __next_mem_pfn_range(&i, nid, p_start, p_end, p_nid); i >= 0;                                         \
2513d0407baSopenharmony_ci         __next_mem_pfn_range(&i, nid, p_start, p_end, p_nid))
2523d0407baSopenharmony_ci
2533d0407baSopenharmony_ci#ifdef CONFIG_DEFERRED_STRUCT_PAGE_INIT
2543d0407baSopenharmony_civoid __next_mem_pfn_range_in_zone(u64 *idx, struct zone *zone, unsigned long *out_spfn, unsigned long *out_epfn);
2553d0407baSopenharmony_ci/**
2563d0407baSopenharmony_ci * for_each_free_mem_range_in_zone - iterate through zone specific free
2573d0407baSopenharmony_ci * memblock areas
2583d0407baSopenharmony_ci * @i: u64 used as loop variable
2593d0407baSopenharmony_ci * @zone: zone in which all of the memory blocks reside
2603d0407baSopenharmony_ci * @p_start: ptr to phys_addr_t for start address of the range, can be %NULL
2613d0407baSopenharmony_ci * @p_end: ptr to phys_addr_t for end address of the range, can be %NULL
2623d0407baSopenharmony_ci *
2633d0407baSopenharmony_ci * Walks over free (memory && !reserved) areas of memblock in a specific
2643d0407baSopenharmony_ci * zone. Available once memblock and an empty zone is initialized. The main
2653d0407baSopenharmony_ci * assumption is that the zone start, end, and pgdat have been associated.
2663d0407baSopenharmony_ci * This way we can use the zone to determine NUMA node, and if a given part
2673d0407baSopenharmony_ci * of the memblock is valid for the zone.
2683d0407baSopenharmony_ci */
2693d0407baSopenharmony_ci#define for_each_free_mem_pfn_range_in_zone(i, zone, p_start, p_end)                                                   \
2703d0407baSopenharmony_ci    for (i = 0, __next_mem_pfn_range_in_zone(&i, zone, p_start, p_end); i != U64_MAX;                                  \
2713d0407baSopenharmony_ci         __next_mem_pfn_range_in_zone(&i, zone, p_start, p_end))
2723d0407baSopenharmony_ci
2733d0407baSopenharmony_ci/**
2743d0407baSopenharmony_ci * for_each_free_mem_range_in_zone_from - iterate through zone specific
2753d0407baSopenharmony_ci * free memblock areas from a given point
2763d0407baSopenharmony_ci * @i: u64 used as loop variable
2773d0407baSopenharmony_ci * @zone: zone in which all of the memory blocks reside
2783d0407baSopenharmony_ci * @p_start: ptr to phys_addr_t for start address of the range, can be %NULL
2793d0407baSopenharmony_ci * @p_end: ptr to phys_addr_t for end address of the range, can be %NULL
2803d0407baSopenharmony_ci *
2813d0407baSopenharmony_ci * Walks over free (memory && !reserved) areas of memblock in a specific
2823d0407baSopenharmony_ci * zone, continuing from current position. Available as soon as memblock is
2833d0407baSopenharmony_ci * initialized.
2843d0407baSopenharmony_ci */
2853d0407baSopenharmony_ci#define for_each_free_mem_pfn_range_in_zone_from(i, zone, p_start, p_end)                                              \
2863d0407baSopenharmony_ci    for (; i != U64_MAX; __next_mem_pfn_range_in_zone(&i, zone, p_start, p_end))
2873d0407baSopenharmony_ci
2883d0407baSopenharmony_ciint __init deferred_page_init_max_threads(const struct cpumask *node_cpumask);
2893d0407baSopenharmony_ci
2903d0407baSopenharmony_ci#endif /* CONFIG_DEFERRED_STRUCT_PAGE_INIT */
2913d0407baSopenharmony_ci
2923d0407baSopenharmony_ci/**
2933d0407baSopenharmony_ci * for_each_free_mem_range - iterate through free memblock areas
2943d0407baSopenharmony_ci * @i: u64 used as loop variable
2953d0407baSopenharmony_ci * @nid: node selector, %NUMA_NO_NODE for all nodes
2963d0407baSopenharmony_ci * @flags: pick from blocks based on memory attributes
2973d0407baSopenharmony_ci * @p_start: ptr to phys_addr_t for start address of the range, can be %NULL
2983d0407baSopenharmony_ci * @p_end: ptr to phys_addr_t for end address of the range, can be %NULL
2993d0407baSopenharmony_ci * @p_nid: ptr to int for nid of the range, can be %NULL
3003d0407baSopenharmony_ci *
3013d0407baSopenharmony_ci * Walks over free (memory && !reserved) areas of memblock.  Available as
3023d0407baSopenharmony_ci * soon as memblock is initialized.
3033d0407baSopenharmony_ci */
3043d0407baSopenharmony_ci#define for_each_free_mem_range(i, nid, flags, p_start, p_end, p_nid)                                                  \
3053d0407baSopenharmony_ci    _for_each_mem_range(i, &memblock.memory, &memblock.reserved, nid, flags, p_start, p_end, p_nid)
3063d0407baSopenharmony_ci
3073d0407baSopenharmony_ci/**
3083d0407baSopenharmony_ci * for_each_free_mem_range_reverse - rev-iterate through free memblock areas
3093d0407baSopenharmony_ci * @i: u64 used as loop variable
3103d0407baSopenharmony_ci * @nid: node selector, %NUMA_NO_NODE for all nodes
3113d0407baSopenharmony_ci * @flags: pick from blocks based on memory attributes
3123d0407baSopenharmony_ci * @p_start: ptr to phys_addr_t for start address of the range, can be %NULL
3133d0407baSopenharmony_ci * @p_end: ptr to phys_addr_t for end address of the range, can be %NULL
3143d0407baSopenharmony_ci * @p_nid: ptr to int for nid of the range, can be %NULL
3153d0407baSopenharmony_ci *
3163d0407baSopenharmony_ci * Walks over free (memory && !reserved) areas of memblock in reverse
3173d0407baSopenharmony_ci * order.  Available as soon as memblock is initialized.
3183d0407baSopenharmony_ci */
3193d0407baSopenharmony_ci#define for_each_free_mem_range_reverse(i, nid, flags, p_start, p_end, p_nid)                                          \
3203d0407baSopenharmony_ci    _for_each_mem_range_rev(i, &memblock.memory, &memblock.reserved, nid, flags, p_start, p_end, p_nid)
3213d0407baSopenharmony_ci
3223d0407baSopenharmony_ciint memblock_set_node(phys_addr_t base, phys_addr_t size, struct memblock_type *type, int nid);
3233d0407baSopenharmony_ci
3243d0407baSopenharmony_ci#ifdef CONFIG_NEED_MULTIPLE_NODES
3253d0407baSopenharmony_cistatic inline void memblock_set_region_node(struct memblock_region *r, int nid)
3263d0407baSopenharmony_ci{
3273d0407baSopenharmony_ci    r->nid = nid;
3283d0407baSopenharmony_ci}
3293d0407baSopenharmony_ci
3303d0407baSopenharmony_cistatic inline int memblock_get_region_node(const struct memblock_region *r)
3313d0407baSopenharmony_ci{
3323d0407baSopenharmony_ci    return r->nid;
3333d0407baSopenharmony_ci}
3343d0407baSopenharmony_ci#else
3353d0407baSopenharmony_cistatic inline void memblock_set_region_node(struct memblock_region *r, int nid)
3363d0407baSopenharmony_ci{
3373d0407baSopenharmony_ci}
3383d0407baSopenharmony_ci
3393d0407baSopenharmony_cistatic inline int memblock_get_region_node(const struct memblock_region *r)
3403d0407baSopenharmony_ci{
3413d0407baSopenharmony_ci    return 0;
3423d0407baSopenharmony_ci}
3433d0407baSopenharmony_ci#endif /* CONFIG_NEED_MULTIPLE_NODES */
3443d0407baSopenharmony_ci
3453d0407baSopenharmony_ci/* Flags for memblock allocation APIs */
3463d0407baSopenharmony_ci#define MEMBLOCK_ALLOC_ANYWHERE (~(phys_addr_t)0)
3473d0407baSopenharmony_ci#define MEMBLOCK_ALLOC_ACCESSIBLE 0
3483d0407baSopenharmony_ci#define MEMBLOCK_ALLOC_KASAN 1
3493d0407baSopenharmony_ci
3503d0407baSopenharmony_ci/* We are using top down, so it is safe to use 0 here */
3513d0407baSopenharmony_ci#define MEMBLOCK_LOW_LIMIT 0
3523d0407baSopenharmony_ci
3533d0407baSopenharmony_ci#ifndef ARCH_LOW_ADDRESS_LIMIT
3543d0407baSopenharmony_ci#define ARCH_LOW_ADDRESS_LIMIT 0xffffffffUL
3553d0407baSopenharmony_ci#endif
3563d0407baSopenharmony_ci
3573d0407baSopenharmony_ciphys_addr_t memblock_phys_alloc_range(phys_addr_t size, phys_addr_t align, phys_addr_t start, phys_addr_t end);
3583d0407baSopenharmony_ciphys_addr_t memblock_alloc_range_nid(phys_addr_t size, phys_addr_t align, phys_addr_t start, phys_addr_t end, int nid,
3593d0407baSopenharmony_ci                                     bool exact_nid);
3603d0407baSopenharmony_ciphys_addr_t memblock_phys_alloc_try_nid(phys_addr_t size, phys_addr_t align, int nid);
3613d0407baSopenharmony_ci
3623d0407baSopenharmony_cistatic __always_inline phys_addr_t memblock_phys_alloc(phys_addr_t size, phys_addr_t align)
3633d0407baSopenharmony_ci{
3643d0407baSopenharmony_ci    return memblock_phys_alloc_range(size, align, 0, MEMBLOCK_ALLOC_ACCESSIBLE);
3653d0407baSopenharmony_ci}
3663d0407baSopenharmony_ci
3673d0407baSopenharmony_civoid *memblock_alloc_exact_nid_raw(phys_addr_t size, phys_addr_t align, phys_addr_t min_addr, phys_addr_t max_addr,
3683d0407baSopenharmony_ci                                   int nid);
3693d0407baSopenharmony_civoid *memblock_alloc_try_nid_raw(phys_addr_t size, phys_addr_t align, phys_addr_t min_addr, phys_addr_t max_addr,
3703d0407baSopenharmony_ci                                 int nid);
3713d0407baSopenharmony_civoid *memblock_alloc_try_nid(phys_addr_t size, phys_addr_t align, phys_addr_t min_addr, phys_addr_t max_addr, int nid);
3723d0407baSopenharmony_ci
3733d0407baSopenharmony_cistatic __always_inline void *memblock_alloc(phys_addr_t size, phys_addr_t align)
3743d0407baSopenharmony_ci{
3753d0407baSopenharmony_ci    return memblock_alloc_try_nid(size, align, MEMBLOCK_LOW_LIMIT, MEMBLOCK_ALLOC_ACCESSIBLE, NUMA_NO_NODE);
3763d0407baSopenharmony_ci}
3773d0407baSopenharmony_ci
3783d0407baSopenharmony_cistatic inline void *memblock_alloc_raw(phys_addr_t size, phys_addr_t align)
3793d0407baSopenharmony_ci{
3803d0407baSopenharmony_ci    return memblock_alloc_try_nid_raw(size, align, MEMBLOCK_LOW_LIMIT, MEMBLOCK_ALLOC_ACCESSIBLE, NUMA_NO_NODE);
3813d0407baSopenharmony_ci}
3823d0407baSopenharmony_ci
3833d0407baSopenharmony_cistatic inline void *memblock_alloc_from(phys_addr_t size, phys_addr_t align, phys_addr_t min_addr)
3843d0407baSopenharmony_ci{
3853d0407baSopenharmony_ci    return memblock_alloc_try_nid(size, align, min_addr, MEMBLOCK_ALLOC_ACCESSIBLE, NUMA_NO_NODE);
3863d0407baSopenharmony_ci}
3873d0407baSopenharmony_ci
3883d0407baSopenharmony_cistatic inline void *memblock_alloc_low(phys_addr_t size, phys_addr_t align)
3893d0407baSopenharmony_ci{
3903d0407baSopenharmony_ci    return memblock_alloc_try_nid(size, align, MEMBLOCK_LOW_LIMIT, ARCH_LOW_ADDRESS_LIMIT, NUMA_NO_NODE);
3913d0407baSopenharmony_ci}
3923d0407baSopenharmony_ci
3933d0407baSopenharmony_cistatic inline void *memblock_alloc_node(phys_addr_t size, phys_addr_t align, int nid)
3943d0407baSopenharmony_ci{
3953d0407baSopenharmony_ci    return memblock_alloc_try_nid(size, align, MEMBLOCK_LOW_LIMIT, MEMBLOCK_ALLOC_ACCESSIBLE, nid);
3963d0407baSopenharmony_ci}
3973d0407baSopenharmony_ci
3983d0407baSopenharmony_cistatic inline void memblock_free_early(phys_addr_t base, phys_addr_t size)
3993d0407baSopenharmony_ci{
4003d0407baSopenharmony_ci    memblock_free(base, size);
4013d0407baSopenharmony_ci}
4023d0407baSopenharmony_ci
4033d0407baSopenharmony_cistatic inline void memblock_free_early_nid(phys_addr_t base, phys_addr_t size, int nid)
4043d0407baSopenharmony_ci{
4053d0407baSopenharmony_ci    memblock_free(base, size);
4063d0407baSopenharmony_ci}
4073d0407baSopenharmony_ci
4083d0407baSopenharmony_cistatic inline void memblock_free_late(phys_addr_t base, phys_addr_t size)
4093d0407baSopenharmony_ci{
4103d0407baSopenharmony_ci    __memblock_free_late(base, size);
4113d0407baSopenharmony_ci}
4123d0407baSopenharmony_ci
4133d0407baSopenharmony_ci/*
4143d0407baSopenharmony_ci * Set the allocation direction to bottom-up or top-down.
4153d0407baSopenharmony_ci */
4163d0407baSopenharmony_cistatic inline __init void memblock_set_bottom_up(bool enable)
4173d0407baSopenharmony_ci{
4183d0407baSopenharmony_ci    memblock.bottom_up = enable;
4193d0407baSopenharmony_ci}
4203d0407baSopenharmony_ci
4213d0407baSopenharmony_ci/*
4223d0407baSopenharmony_ci * Check if the allocation direction is bottom-up or not.
4233d0407baSopenharmony_ci * if this is true, that said, memblock will allocate memory
4243d0407baSopenharmony_ci * in bottom-up direction.
4253d0407baSopenharmony_ci */
4263d0407baSopenharmony_cistatic inline __init bool memblock_bottom_up(void)
4273d0407baSopenharmony_ci{
4283d0407baSopenharmony_ci    return memblock.bottom_up;
4293d0407baSopenharmony_ci}
4303d0407baSopenharmony_ci
4313d0407baSopenharmony_ciphys_addr_t memblock_phys_mem_size(void);
4323d0407baSopenharmony_ciphys_addr_t memblock_reserved_size(void);
4333d0407baSopenharmony_ciphys_addr_t memblock_start_of_DRAM(void);
4343d0407baSopenharmony_ciphys_addr_t memblock_end_of_DRAM(void);
4353d0407baSopenharmony_civoid memblock_enforce_memory_limit(phys_addr_t memory_limit);
4363d0407baSopenharmony_civoid memblock_cap_memory_range(phys_addr_t base, phys_addr_t size);
4373d0407baSopenharmony_civoid memblock_mem_limit_remove_map(phys_addr_t limit);
4383d0407baSopenharmony_cibool memblock_is_memory(phys_addr_t addr);
4393d0407baSopenharmony_cibool memblock_is_map_memory(phys_addr_t addr);
4403d0407baSopenharmony_cibool memblock_is_region_memory(phys_addr_t base, phys_addr_t size);
4413d0407baSopenharmony_cibool memblock_is_reserved(phys_addr_t addr);
4423d0407baSopenharmony_cibool memblock_is_region_reserved(phys_addr_t base, phys_addr_t size);
4433d0407baSopenharmony_ci
4443d0407baSopenharmony_civoid memblock_dump_all(void);
4453d0407baSopenharmony_ci
4463d0407baSopenharmony_ci/**
4473d0407baSopenharmony_ci * memblock_set_current_limit - Set the current allocation limit to allow
4483d0407baSopenharmony_ci *                         limiting allocations to what is currently
4493d0407baSopenharmony_ci *                         accessible during boot
4503d0407baSopenharmony_ci * @limit: New limit value (physical address)
4513d0407baSopenharmony_ci */
4523d0407baSopenharmony_civoid memblock_set_current_limit(phys_addr_t limit);
4533d0407baSopenharmony_ci
4543d0407baSopenharmony_ciphys_addr_t memblock_get_current_limit(void);
4553d0407baSopenharmony_ci
4563d0407baSopenharmony_ci/*
4573d0407baSopenharmony_ci * pfn conversion functions
4583d0407baSopenharmony_ci *
4593d0407baSopenharmony_ci * While the memory MEMBLOCKs should always be page aligned, the reserved
4603d0407baSopenharmony_ci * MEMBLOCKs may not be. This accessor attempt to provide a very clear
4613d0407baSopenharmony_ci * idea of what they return for such non aligned MEMBLOCKs.
4623d0407baSopenharmony_ci */
4633d0407baSopenharmony_ci
4643d0407baSopenharmony_ci/**
4653d0407baSopenharmony_ci * memblock_region_memory_base_pfn - get the lowest pfn of the memory region
4663d0407baSopenharmony_ci * @reg: memblock_region structure
4673d0407baSopenharmony_ci *
4683d0407baSopenharmony_ci * Return: the lowest pfn intersecting with the memory region
4693d0407baSopenharmony_ci */
4703d0407baSopenharmony_cistatic inline unsigned long memblock_region_memory_base_pfn(const struct memblock_region *reg)
4713d0407baSopenharmony_ci{
4723d0407baSopenharmony_ci    return PFN_UP(reg->base);
4733d0407baSopenharmony_ci}
4743d0407baSopenharmony_ci
4753d0407baSopenharmony_ci/**
4763d0407baSopenharmony_ci * memblock_region_memory_end_pfn - get the end pfn of the memory region
4773d0407baSopenharmony_ci * @reg: memblock_region structure
4783d0407baSopenharmony_ci *
4793d0407baSopenharmony_ci * Return: the end_pfn of the reserved region
4803d0407baSopenharmony_ci */
4813d0407baSopenharmony_cistatic inline unsigned long memblock_region_memory_end_pfn(const struct memblock_region *reg)
4823d0407baSopenharmony_ci{
4833d0407baSopenharmony_ci    return PFN_DOWN(reg->base + reg->size);
4843d0407baSopenharmony_ci}
4853d0407baSopenharmony_ci
4863d0407baSopenharmony_ci/**
4873d0407baSopenharmony_ci * memblock_region_reserved_base_pfn - get the lowest pfn of the reserved region
4883d0407baSopenharmony_ci * @reg: memblock_region structure
4893d0407baSopenharmony_ci *
4903d0407baSopenharmony_ci * Return: the lowest pfn intersecting with the reserved region
4913d0407baSopenharmony_ci */
4923d0407baSopenharmony_cistatic inline unsigned long memblock_region_reserved_base_pfn(const struct memblock_region *reg)
4933d0407baSopenharmony_ci{
4943d0407baSopenharmony_ci    return PFN_DOWN(reg->base);
4953d0407baSopenharmony_ci}
4963d0407baSopenharmony_ci
4973d0407baSopenharmony_ci/**
4983d0407baSopenharmony_ci * memblock_region_reserved_end_pfn - get the end pfn of the reserved region
4993d0407baSopenharmony_ci * @reg: memblock_region structure
5003d0407baSopenharmony_ci *
5013d0407baSopenharmony_ci * Return: the end_pfn of the reserved region
5023d0407baSopenharmony_ci */
5033d0407baSopenharmony_cistatic inline unsigned long memblock_region_reserved_end_pfn(const struct memblock_region *reg)
5043d0407baSopenharmony_ci{
5053d0407baSopenharmony_ci    return PFN_UP(reg->base + reg->size);
5063d0407baSopenharmony_ci}
5073d0407baSopenharmony_ci
5083d0407baSopenharmony_ci/**
5093d0407baSopenharmony_ci * for_each_mem_region - itereate over memory regions
5103d0407baSopenharmony_ci * @region: loop variable
5113d0407baSopenharmony_ci */
5123d0407baSopenharmony_ci#define for_each_mem_region(region)                                                                                    \
5133d0407baSopenharmony_ci    for (region = memblock.memory.regions; region < (memblock.memory.regions + memblock.memory.cnt); region++)
5143d0407baSopenharmony_ci
5153d0407baSopenharmony_ci/**
5163d0407baSopenharmony_ci * for_each_reserved_mem_region - itereate over reserved memory regions
5173d0407baSopenharmony_ci * @region: loop variable
5183d0407baSopenharmony_ci */
5193d0407baSopenharmony_ci#define for_each_reserved_mem_region(region)                                                                           \
5203d0407baSopenharmony_ci    for (region = memblock.reserved.regions; region < (memblock.reserved.regions + memblock.reserved.cnt); region++)
5213d0407baSopenharmony_ci
5223d0407baSopenharmony_ciextern void *alloc_large_system_hash(const char *tablename, unsigned long bucketsize, unsigned long numentries,
5233d0407baSopenharmony_ci                                     int scale, int flags, unsigned int *_hash_shift, unsigned int *_hash_mask,
5243d0407baSopenharmony_ci                                     unsigned long low_limit, unsigned long high_limit);
5253d0407baSopenharmony_ci
5263d0407baSopenharmony_ci#define HASH_EARLY 0x00000001 /* Allocating during early boot? */
5273d0407baSopenharmony_ci#define HASH_SMALL                                                                                                     \
5283d0407baSopenharmony_ci    0x00000002               /* sub-page allocation allowed, min                                                       \
5293d0407baSopenharmony_ci                              * shift passed via *_hash_shift */
5303d0407baSopenharmony_ci#define HASH_ZERO 0x00000004 /* Zero allocated hash table */
5313d0407baSopenharmony_ci
5323d0407baSopenharmony_ci/* Only NUMA needs hash distribution. 64bit NUMA architectures have
5333d0407baSopenharmony_ci * sufficient vmalloc space.
5343d0407baSopenharmony_ci */
5353d0407baSopenharmony_ci#ifdef CONFIG_NUMA
5363d0407baSopenharmony_ci#define HASHDIST_DEFAULT IS_ENABLED(CONFIG_64BIT)
5373d0407baSopenharmony_ciextern int hashdist; /* Distribute hashes across NUMA nodes? */
5383d0407baSopenharmony_ci#else
5393d0407baSopenharmony_ci#define hashdist (0)
5403d0407baSopenharmony_ci#endif
5413d0407baSopenharmony_ci
5423d0407baSopenharmony_ci#ifdef CONFIG_MEMTEST
5433d0407baSopenharmony_ciextern void early_memtest(phys_addr_t start, phys_addr_t end);
5443d0407baSopenharmony_ci#else
5453d0407baSopenharmony_cistatic inline void early_memtest(phys_addr_t start, phys_addr_t end)
5463d0407baSopenharmony_ci{
5473d0407baSopenharmony_ci}
5483d0407baSopenharmony_ci#endif
5493d0407baSopenharmony_ci
5503d0407baSopenharmony_ci#endif /* __KERNEL__ */
5513d0407baSopenharmony_ci
5523d0407baSopenharmony_ci#endif /* _LINUX_MEMBLOCK_H */
553