LCOV - code coverage report
Current view: top level - include/linux - memory_hotplug.h (source / functions) Hit Total Coverage
Test: landlock.info Lines: 10 14 71.4 %
Date: 2021-04-22 12:43:58 Functions: 0 0 -

          Line data    Source code
       1             : /* SPDX-License-Identifier: GPL-2.0 */
       2             : #ifndef __LINUX_MEMORY_HOTPLUG_H
       3             : #define __LINUX_MEMORY_HOTPLUG_H
       4             : 
       5             : #include <linux/mmzone.h>
       6             : #include <linux/spinlock.h>
       7             : #include <linux/notifier.h>
       8             : #include <linux/bug.h>
       9             : 
      10             : struct page;
      11             : struct zone;
      12             : struct pglist_data;
      13             : struct mem_section;
      14             : struct memory_block;
      15             : struct resource;
      16             : struct vmem_altmap;
      17             : 
      18             : #ifdef CONFIG_MEMORY_HOTPLUG
      19             : struct page *pfn_to_online_page(unsigned long pfn);
      20             : 
      21             : /*
      22             :  * Types for free bootmem stored in page->lru.next. These have to be in
      23             :  * some random range in unsigned long space for debugging purposes.
      24             :  */
      25             : enum {
      26             :         MEMORY_HOTPLUG_MIN_BOOTMEM_TYPE = 12,
      27             :         SECTION_INFO = MEMORY_HOTPLUG_MIN_BOOTMEM_TYPE,
      28             :         MIX_SECTION_INFO,
      29             :         NODE_INFO,
      30             :         MEMORY_HOTPLUG_MAX_BOOTMEM_TYPE = NODE_INFO,
      31             : };
      32             : 
      33             : /* Types for control the zone type of onlined and offlined memory */
      34             : enum {
      35             :         /* Offline the memory. */
      36             :         MMOP_OFFLINE = 0,
      37             :         /* Online the memory. Zone depends, see default_zone_for_pfn(). */
      38             :         MMOP_ONLINE,
      39             :         /* Online the memory to ZONE_NORMAL. */
      40             :         MMOP_ONLINE_KERNEL,
      41             :         /* Online the memory to ZONE_MOVABLE. */
      42             :         MMOP_ONLINE_MOVABLE,
      43             : };
      44             : 
      45             : /* Flags for add_memory() and friends to specify memory hotplug details. */
      46             : typedef int __bitwise mhp_t;
      47             : 
      48             : /* No special request */
      49             : #define MHP_NONE                ((__force mhp_t)0)
      50             : /*
      51             :  * Allow merging of the added System RAM resource with adjacent,
      52             :  * mergeable resources. After a successful call to add_memory_resource()
      53             :  * with this flag set, the resource pointer must no longer be used as it
      54             :  * might be stale, or the resource might have changed.
      55             :  */
      56             : #define MHP_MERGE_RESOURCE      ((__force mhp_t)BIT(0))
      57             : 
      58             : /*
      59             :  * Extended parameters for memory hotplug:
      60             :  * altmap: alternative allocator for memmap array (optional)
      61             :  * pgprot: page protection flags to apply to newly created page tables
      62             :  *      (required)
      63             :  */
      64             : struct mhp_params {
      65             :         struct vmem_altmap *altmap;
      66             :         pgprot_t pgprot;
      67             : };
      68             : 
      69             : bool mhp_range_allowed(u64 start, u64 size, bool need_mapping);
      70             : struct range mhp_get_pluggable_range(bool need_mapping);
      71             : 
      72             : /*
      73             :  * Zone resizing functions
      74             :  *
      75             :  * Note: any attempt to resize a zone should has pgdat_resize_lock()
      76             :  * zone_span_writelock() both held. This ensure the size of a zone
      77             :  * can't be changed while pgdat_resize_lock() held.
      78             :  */
      79             : static inline unsigned zone_span_seqbegin(struct zone *zone)
      80             : {
      81             :         return read_seqbegin(&zone->span_seqlock);
      82             : }
      83             : static inline int zone_span_seqretry(struct zone *zone, unsigned iv)
      84             : {
      85             :         return read_seqretry(&zone->span_seqlock, iv);
      86             : }
      87             : static inline void zone_span_writelock(struct zone *zone)
      88             : {
      89             :         write_seqlock(&zone->span_seqlock);
      90             : }
      91             : static inline void zone_span_writeunlock(struct zone *zone)
      92             : {
      93             :         write_sequnlock(&zone->span_seqlock);
      94             : }
      95             : static inline void zone_seqlock_init(struct zone *zone)
      96             : {
      97             :         seqlock_init(&zone->span_seqlock);
      98             : }
      99             : extern int zone_grow_free_lists(struct zone *zone, unsigned long new_nr_pages);
     100             : extern int zone_grow_waitqueues(struct zone *zone, unsigned long nr_pages);
     101             : extern int add_one_highpage(struct page *page, int pfn, int bad_ppro);
     102             : /* VM interface that may be used by firmware interface */
     103             : extern int online_pages(unsigned long pfn, unsigned long nr_pages,
     104             :                         int online_type, int nid);
     105             : extern struct zone *test_pages_in_a_zone(unsigned long start_pfn,
     106             :                                          unsigned long end_pfn);
     107             : extern void __offline_isolated_pages(unsigned long start_pfn,
     108             :                                      unsigned long end_pfn);
     109             : 
     110             : typedef void (*online_page_callback_t)(struct page *page, unsigned int order);
     111             : 
     112             : extern void generic_online_page(struct page *page, unsigned int order);
     113             : extern int set_online_page_callback(online_page_callback_t callback);
     114             : extern int restore_online_page_callback(online_page_callback_t callback);
     115             : 
     116             : extern int try_online_node(int nid);
     117             : 
     118             : extern int arch_add_memory(int nid, u64 start, u64 size,
     119             :                            struct mhp_params *params);
     120             : extern u64 max_mem_size;
     121             : 
     122             : extern int mhp_online_type_from_str(const char *str);
     123             : 
     124             : /* Default online_type (MMOP_*) when new memory blocks are added. */
     125             : extern int mhp_default_online_type;
     126             : /* If movable_node boot option specified */
     127             : extern bool movable_node_enabled;
     128             : static inline bool movable_node_is_enabled(void)
     129             : {
     130             :         return movable_node_enabled;
     131             : }
     132             : 
     133             : extern void arch_remove_memory(int nid, u64 start, u64 size,
     134             :                                struct vmem_altmap *altmap);
     135             : extern void __remove_pages(unsigned long start_pfn, unsigned long nr_pages,
     136             :                            struct vmem_altmap *altmap);
     137             : 
     138             : /* reasonably generic interface to expand the physical pages */
     139             : extern int __add_pages(int nid, unsigned long start_pfn, unsigned long nr_pages,
     140             :                        struct mhp_params *params);
     141             : 
     142             : #ifndef CONFIG_ARCH_HAS_ADD_PAGES
     143             : static inline int add_pages(int nid, unsigned long start_pfn,
     144             :                 unsigned long nr_pages, struct mhp_params *params)
     145             : {
     146             :         return __add_pages(nid, start_pfn, nr_pages, params);
     147             : }
     148             : #else /* ARCH_HAS_ADD_PAGES */
     149             : int add_pages(int nid, unsigned long start_pfn, unsigned long nr_pages,
     150             :               struct mhp_params *params);
     151             : #endif /* ARCH_HAS_ADD_PAGES */
     152             : 
     153             : #ifdef CONFIG_HAVE_ARCH_NODEDATA_EXTENSION
     154             : /*
     155             :  * For supporting node-hotadd, we have to allocate a new pgdat.
     156             :  *
     157             :  * If an arch has generic style NODE_DATA(),
     158             :  * node_data[nid] = kzalloc() works well. But it depends on the architecture.
     159             :  *
     160             :  * In general, generic_alloc_nodedata() is used.
     161             :  * Now, arch_free_nodedata() is just defined for error path of node_hot_add.
     162             :  *
     163             :  */
     164             : extern pg_data_t *arch_alloc_nodedata(int nid);
     165             : extern void arch_free_nodedata(pg_data_t *pgdat);
     166             : extern void arch_refresh_nodedata(int nid, pg_data_t *pgdat);
     167             : 
     168             : #else /* CONFIG_HAVE_ARCH_NODEDATA_EXTENSION */
     169             : 
     170             : #define arch_alloc_nodedata(nid)        generic_alloc_nodedata(nid)
     171             : #define arch_free_nodedata(pgdat)       generic_free_nodedata(pgdat)
     172             : 
     173             : #ifdef CONFIG_NUMA
     174             : /*
     175             :  * If ARCH_HAS_NODEDATA_EXTENSION=n, this func is used to allocate pgdat.
     176             :  * XXX: kmalloc_node() can't work well to get new node's memory at this time.
     177             :  *      Because, pgdat for the new node is not allocated/initialized yet itself.
     178             :  *      To use new node's memory, more consideration will be necessary.
     179             :  */
     180             : #define generic_alloc_nodedata(nid)                             \
     181             : ({                                                              \
     182             :         kzalloc(sizeof(pg_data_t), GFP_KERNEL);                 \
     183             : })
     184             : /*
     185             :  * This definition is just for error path in node hotadd.
     186             :  * For node hotremove, we have to replace this.
     187             :  */
     188             : #define generic_free_nodedata(pgdat)    kfree(pgdat)
     189             : 
     190             : extern pg_data_t *node_data[];
     191             : static inline void arch_refresh_nodedata(int nid, pg_data_t *pgdat)
     192             : {
     193             :         node_data[nid] = pgdat;
     194             : }
     195             : 
     196             : #else /* !CONFIG_NUMA */
     197             : 
     198             : /* never called */
     199             : static inline pg_data_t *generic_alloc_nodedata(int nid)
     200             : {
     201             :         BUG();
     202             :         return NULL;
     203             : }
     204             : static inline void generic_free_nodedata(pg_data_t *pgdat)
     205             : {
     206             : }
     207             : static inline void arch_refresh_nodedata(int nid, pg_data_t *pgdat)
     208             : {
     209             : }
     210             : #endif /* CONFIG_NUMA */
     211             : #endif /* CONFIG_HAVE_ARCH_NODEDATA_EXTENSION */
     212             : 
     213             : #ifdef CONFIG_HAVE_BOOTMEM_INFO_NODE
     214             : extern void __init register_page_bootmem_info_node(struct pglist_data *pgdat);
     215             : #else
     216             : static inline void register_page_bootmem_info_node(struct pglist_data *pgdat)
     217             : {
     218             : }
     219             : #endif
     220             : extern void put_page_bootmem(struct page *page);
     221             : extern void get_page_bootmem(unsigned long ingo, struct page *page,
     222             :                              unsigned long type);
     223             : 
     224             : void get_online_mems(void);
     225             : void put_online_mems(void);
     226             : 
     227             : void mem_hotplug_begin(void);
     228             : void mem_hotplug_done(void);
     229             : 
     230             : #else /* ! CONFIG_MEMORY_HOTPLUG */
     231             : #define pfn_to_online_page(pfn)                 \
     232             : ({                                              \
     233             :         struct page *___page = NULL;            \
     234             :         if (pfn_valid(pfn))                     \
     235             :                 ___page = pfn_to_page(pfn);     \
     236             :         ___page;                                \
     237             :  })
     238             : 
     239      290654 : static inline unsigned zone_span_seqbegin(struct zone *zone)
     240             : {
     241      290654 :         return 0;
     242             : }
     243           0 : static inline int zone_span_seqretry(struct zone *zone, unsigned iv)
     244             : {
     245           0 :         return 0;
     246             : }
     247             : static inline void zone_span_writelock(struct zone *zone) {}
     248             : static inline void zone_span_writeunlock(struct zone *zone) {}
     249           3 : static inline void zone_seqlock_init(struct zone *zone) {}
     250             : 
     251           1 : static inline void register_page_bootmem_info_node(struct pglist_data *pgdat)
     252             : {
     253           1 : }
     254             : 
     255           3 : static inline int try_online_node(int nid)
     256             : {
     257           3 :         return 0;
     258             : }
     259             : 
     260           0 : static inline void get_online_mems(void) {}
     261           0 : static inline void put_online_mems(void) {}
     262             : 
     263             : static inline void mem_hotplug_begin(void) {}
     264             : static inline void mem_hotplug_done(void) {}
     265             : 
     266         949 : static inline bool movable_node_is_enabled(void)
     267             : {
     268         949 :         return false;
     269             : }
     270             : #endif /* ! CONFIG_MEMORY_HOTPLUG */
     271             : 
     272             : /*
     273             :  * Keep this declaration outside CONFIG_MEMORY_HOTPLUG as some
     274             :  * platforms might override and use arch_get_mappable_range()
     275             :  * for internal non memory hotplug purposes.
     276             :  */
     277             : struct range arch_get_mappable_range(void);
     278             : 
     279             : #if defined(CONFIG_MEMORY_HOTPLUG) || defined(CONFIG_DEFERRED_STRUCT_PAGE_INIT)
     280             : /*
     281             :  * pgdat resizing functions
     282             :  */
     283             : static inline
     284             : void pgdat_resize_lock(struct pglist_data *pgdat, unsigned long *flags)
     285             : {
     286             :         spin_lock_irqsave(&pgdat->node_size_lock, *flags);
     287             : }
     288             : static inline
     289             : void pgdat_resize_unlock(struct pglist_data *pgdat, unsigned long *flags)
     290             : {
     291             :         spin_unlock_irqrestore(&pgdat->node_size_lock, *flags);
     292             : }
     293             : static inline
     294             : void pgdat_resize_init(struct pglist_data *pgdat)
     295             : {
     296             :         spin_lock_init(&pgdat->node_size_lock);
     297             : }
     298             : #else /* !(CONFIG_MEMORY_HOTPLUG || CONFIG_DEFERRED_STRUCT_PAGE_INIT) */
     299             : /*
     300             :  * Stub functions for when hotplug is off
     301             :  */
     302             : static inline void pgdat_resize_lock(struct pglist_data *p, unsigned long *f) {}
     303             : static inline void pgdat_resize_unlock(struct pglist_data *p, unsigned long *f) {}
     304           1 : static inline void pgdat_resize_init(struct pglist_data *pgdat) {}
     305             : #endif /* !(CONFIG_MEMORY_HOTPLUG || CONFIG_DEFERRED_STRUCT_PAGE_INIT) */
     306             : 
     307             : #ifdef CONFIG_MEMORY_HOTREMOVE
     308             : 
     309             : extern void try_offline_node(int nid);
     310             : extern int offline_pages(unsigned long start_pfn, unsigned long nr_pages);
     311             : extern int remove_memory(int nid, u64 start, u64 size);
     312             : extern void __remove_memory(int nid, u64 start, u64 size);
     313             : extern int offline_and_remove_memory(int nid, u64 start, u64 size);
     314             : 
     315             : #else
     316             : static inline void try_offline_node(int nid) {}
     317             : 
     318             : static inline int offline_pages(unsigned long start_pfn, unsigned long nr_pages)
     319             : {
     320             :         return -EINVAL;
     321             : }
     322             : 
     323             : static inline int remove_memory(int nid, u64 start, u64 size)
     324             : {
     325             :         return -EBUSY;
     326             : }
     327             : 
     328             : static inline void __remove_memory(int nid, u64 start, u64 size) {}
     329             : #endif /* CONFIG_MEMORY_HOTREMOVE */
     330             : 
     331             : extern void set_zone_contiguous(struct zone *zone);
     332             : extern void clear_zone_contiguous(struct zone *zone);
     333             : 
     334             : #ifdef CONFIG_MEMORY_HOTPLUG
     335             : extern void __ref free_area_init_core_hotplug(int nid);
     336             : extern int __add_memory(int nid, u64 start, u64 size, mhp_t mhp_flags);
     337             : extern int add_memory(int nid, u64 start, u64 size, mhp_t mhp_flags);
     338             : extern int add_memory_resource(int nid, struct resource *resource,
     339             :                                mhp_t mhp_flags);
     340             : extern int add_memory_driver_managed(int nid, u64 start, u64 size,
     341             :                                      const char *resource_name,
     342             :                                      mhp_t mhp_flags);
     343             : extern void move_pfn_range_to_zone(struct zone *zone, unsigned long start_pfn,
     344             :                                    unsigned long nr_pages,
     345             :                                    struct vmem_altmap *altmap, int migratetype);
     346             : extern void remove_pfn_range_from_zone(struct zone *zone,
     347             :                                        unsigned long start_pfn,
     348             :                                        unsigned long nr_pages);
     349             : extern bool is_memblock_offlined(struct memory_block *mem);
     350             : extern int sparse_add_section(int nid, unsigned long pfn,
     351             :                 unsigned long nr_pages, struct vmem_altmap *altmap);
     352             : extern void sparse_remove_section(struct mem_section *ms,
     353             :                 unsigned long pfn, unsigned long nr_pages,
     354             :                 unsigned long map_offset, struct vmem_altmap *altmap);
     355             : extern struct page *sparse_decode_mem_map(unsigned long coded_mem_map,
     356             :                                           unsigned long pnum);
     357             : extern struct zone *zone_for_pfn_range(int online_type, int nid, unsigned start_pfn,
     358             :                 unsigned long nr_pages);
     359             : extern int arch_create_linear_mapping(int nid, u64 start, u64 size,
     360             :                                       struct mhp_params *params);
     361             : void arch_remove_linear_mapping(u64 start, u64 size);
     362             : #endif /* CONFIG_MEMORY_HOTPLUG */
     363             : 
     364             : #endif /* __LINUX_MEMORY_HOTPLUG_H */

Generated by: LCOV version 1.14