LCOV - code coverage report
Current view: top level - mm - sparse.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 138 180 76.7 %
Date: 2022-04-01 14:35:51 Functions: 12 17 70.6 %
Branches: 52 113 46.0 %

           Branch data     Line data    Source code
       1                 :            : // SPDX-License-Identifier: GPL-2.0
       2                 :            : /*
       3                 :            :  * sparse memory mappings.
       4                 :            :  */
       5                 :            : #include <linux/mm.h>
       6                 :            : #include <linux/slab.h>
       7                 :            : #include <linux/mmzone.h>
       8                 :            : #include <linux/memblock.h>
       9                 :            : #include <linux/compiler.h>
      10                 :            : #include <linux/highmem.h>
      11                 :            : #include <linux/export.h>
      12                 :            : #include <linux/spinlock.h>
      13                 :            : #include <linux/vmalloc.h>
      14                 :            : #include <linux/swap.h>
      15                 :            : #include <linux/swapops.h>
      16                 :            : 
      17                 :            : #include "internal.h"
      18                 :            : #include <asm/dma.h>
      19                 :            : #include <asm/pgalloc.h>
      20                 :            : #include <asm/pgtable.h>
      21                 :            : 
      22                 :            : /*
      23                 :            :  * Permanent SPARSEMEM data:
      24                 :            :  *
      25                 :            :  * 1) mem_section       - memory sections, mem_map's for valid memory
      26                 :            :  */
      27                 :            : #ifdef CONFIG_SPARSEMEM_EXTREME
      28                 :            : struct mem_section **mem_section;
      29                 :            : #else
      30                 :            : struct mem_section mem_section[NR_SECTION_ROOTS][SECTIONS_PER_ROOT]
      31                 :            :         ____cacheline_internodealigned_in_smp;
      32                 :            : #endif
      33                 :            : EXPORT_SYMBOL(mem_section);
      34                 :            : 
      35                 :            : #ifdef NODE_NOT_IN_PAGE_FLAGS
      36                 :            : /*
      37                 :            :  * If we did not store the node number in the page then we have to
      38                 :            :  * do a lookup in the section_to_node_table in order to find which
      39                 :            :  * node the page belongs to.
      40                 :            :  */
      41                 :            : #if MAX_NUMNODES <= 256
      42                 :            : static u8 section_to_node_table[NR_MEM_SECTIONS] __cacheline_aligned;
      43                 :            : #else
      44                 :            : static u16 section_to_node_table[NR_MEM_SECTIONS] __cacheline_aligned;
      45                 :            : #endif
      46                 :            : 
      47                 :            : int page_to_nid(const struct page *page)
      48                 :            : {
      49                 :            :         return section_to_node_table[page_to_section(page)];
      50                 :            : }
      51                 :            : EXPORT_SYMBOL(page_to_nid);
      52                 :            : 
      53                 :            : static void set_section_nid(unsigned long section_nr, int nid)
      54                 :            : {
      55                 :            :         section_to_node_table[section_nr] = nid;
      56                 :            : }
      57                 :            : #else /* !NODE_NOT_IN_PAGE_FLAGS */
      58                 :        189 : static inline void set_section_nid(unsigned long section_nr, int nid)
      59                 :            : {
      60                 :        189 : }
      61                 :            : #endif
      62                 :            : 
      63                 :            : #ifdef CONFIG_SPARSEMEM_EXTREME
      64                 :         21 : static noinline struct mem_section __ref *sparse_index_alloc(int nid)
      65                 :            : {
      66                 :         21 :         struct mem_section *section = NULL;
      67                 :         21 :         unsigned long array_size = SECTIONS_PER_ROOT *
      68                 :            :                                    sizeof(struct mem_section);
      69                 :            : 
      70         [ -  + ]:         21 :         if (slab_is_available()) {
      71                 :          0 :                 section = kzalloc_node(array_size, GFP_KERNEL, nid);
      72                 :            :         } else {
      73                 :         21 :                 section = memblock_alloc_node(array_size, SMP_CACHE_BYTES,
      74                 :            :                                               nid);
      75         [ -  + ]:         21 :                 if (!section)
      76                 :          0 :                         panic("%s: Failed to allocate %lu bytes nid=%d\n",
      77                 :            :                               __func__, array_size, nid);
      78                 :            :         }
      79                 :            : 
      80                 :         21 :         return section;
      81                 :            : }
      82                 :            : 
      83                 :        189 : static int __meminit sparse_index_init(unsigned long section_nr, int nid)
      84                 :            : {
      85                 :        189 :         unsigned long root = SECTION_NR_TO_ROOT(section_nr);
      86                 :        189 :         struct mem_section *section;
      87                 :            : 
      88                 :            :         /*
      89                 :            :          * An existing section is possible in the sub-section hotplug
      90                 :            :          * case. First hot-add instantiates, follow-on hot-add reuses
      91                 :            :          * the existing section.
      92                 :            :          *
      93                 :            :          * The mem_hotplug_lock resolves the apparent race below.
      94                 :            :          */
      95         [ +  + ]:        189 :         if (mem_section[root])
      96                 :            :                 return 0;
      97                 :            : 
      98                 :         21 :         section = sparse_index_alloc(nid);
      99         [ +  - ]:         21 :         if (!section)
     100                 :            :                 return -ENOMEM;
     101                 :            : 
     102                 :         21 :         mem_section[root] = section;
     103                 :            : 
     104                 :         21 :         return 0;
     105                 :            : }
     106                 :            : #else /* !SPARSEMEM_EXTREME */
     107                 :            : static inline int sparse_index_init(unsigned long section_nr, int nid)
     108                 :            : {
     109                 :            :         return 0;
     110                 :            : }
     111                 :            : #endif
     112                 :            : 
     113                 :            : #ifdef CONFIG_SPARSEMEM_EXTREME
     114                 :        168 : unsigned long __section_nr(struct mem_section *ms)
     115                 :            : {
     116                 :        168 :         unsigned long root_nr;
     117                 :        168 :         struct mem_section *root = NULL;
     118                 :            : 
     119   [ -  -  +  +  :        168 :         for (root_nr = 0; root_nr < NR_SECTION_ROOTS; root_nr++) {
                      - ]
     120         [ +  - ]:        168 :                 root = __nr_to_section(root_nr * SECTIONS_PER_ROOT);
     121                 :        168 :                 if (!root)
     122                 :          0 :                         continue;
     123                 :            : 
     124   [ +  -  -  + ]:        168 :                 if ((ms >= root) && (ms < (root + SECTIONS_PER_ROOT)))
     125                 :            :                      break;
     126                 :            :         }
     127                 :            : 
     128                 :        168 :         VM_BUG_ON(!root);
     129                 :            : 
     130                 :        168 :         return (root_nr * SECTIONS_PER_ROOT) + (ms - root);
     131                 :            : }
     132                 :            : #else
     133                 :            : unsigned long __section_nr(struct mem_section *ms)
     134                 :            : {
     135                 :            :         return (unsigned long)(ms - mem_section[0]);
     136                 :            : }
     137                 :            : #endif
     138                 :            : 
     139                 :            : /*
     140                 :            :  * During early boot, before section_mem_map is used for an actual
     141                 :            :  * mem_map, we use section_mem_map to store the section's NUMA
     142                 :            :  * node.  This keeps us from having to use another data structure.  The
     143                 :            :  * node information is cleared just before we store the real mem_map.
     144                 :            :  */
     145                 :        168 : static inline unsigned long sparse_encode_early_nid(int nid)
     146                 :            : {
     147                 :        168 :         return (nid << SECTION_NID_SHIFT);
     148                 :            : }
     149                 :            : 
     150                 :        168 : static inline int sparse_early_nid(struct mem_section *section)
     151                 :            : {
     152                 :        168 :         return (section->section_mem_map >> SECTION_NID_SHIFT);
     153                 :            : }
     154                 :            : 
     155                 :            : /* Validate the physical addressing limitations of the model */
     156                 :         42 : void __meminit mminit_validate_memmodel_limits(unsigned long *start_pfn,
     157                 :            :                                                 unsigned long *end_pfn)
     158                 :            : {
     159      [ -  +  - ]:         42 :         unsigned long max_sparsemem_pfn = 1UL << (MAX_PHYSMEM_BITS-PAGE_SHIFT);
     160                 :            : 
     161                 :            :         /*
     162                 :            :          * Sanity checks - do not allow an architecture to pass
     163                 :            :          * in larger pfns than the maximum scope of sparsemem:
     164                 :            :          */
     165         [ -  + ]:         42 :         if (*start_pfn > max_sparsemem_pfn) {
     166         [ #  # ]:          0 :                 mminit_dprintk(MMINIT_WARNING, "pfnvalidation",
     167                 :            :                         "Start of range %lu -> %lu exceeds SPARSEMEM max %lu\n",
     168                 :            :                         *start_pfn, *end_pfn, max_sparsemem_pfn);
     169                 :          0 :                 WARN_ON_ONCE(1);
     170                 :          0 :                 *start_pfn = max_sparsemem_pfn;
     171                 :          0 :                 *end_pfn = max_sparsemem_pfn;
     172         [ -  + ]:         42 :         } else if (*end_pfn > max_sparsemem_pfn) {
     173         [ #  # ]:          0 :                 mminit_dprintk(MMINIT_WARNING, "pfnvalidation",
     174                 :            :                         "End of range %lu -> %lu exceeds SPARSEMEM max %lu\n",
     175                 :            :                         *start_pfn, *end_pfn, max_sparsemem_pfn);
     176                 :          0 :                 WARN_ON_ONCE(1);
     177                 :          0 :                 *end_pfn = max_sparsemem_pfn;
     178                 :            :         }
     179                 :         42 : }
     180                 :            : 
     181                 :            : /*
     182                 :            :  * There are a number of times that we loop over NR_MEM_SECTIONS,
     183                 :            :  * looking for section_present() on each.  But, when we have very
     184                 :            :  * large physical address spaces, NR_MEM_SECTIONS can also be
     185                 :            :  * very large which makes the loops quite long.
     186                 :            :  *
     187                 :            :  * Keeping track of this gives us an easy way to break out of
     188                 :            :  * those loops early.
     189                 :            :  */
     190                 :            : unsigned long __highest_present_section_nr;
     191                 :        168 : static void section_mark_present(struct mem_section *ms)
     192                 :            : {
     193                 :        168 :         unsigned long section_nr = __section_nr(ms);
     194                 :            : 
     195         [ +  + ]:        168 :         if (section_nr > __highest_present_section_nr)
     196                 :        147 :                 __highest_present_section_nr = section_nr;
     197                 :            : 
     198                 :        168 :         ms->section_mem_map |= SECTION_MARKED_PRESENT;
     199                 :        168 : }
     200                 :            : 
     201                 :            : #define for_each_present_section_nr(start, section_nr)          \
     202                 :            :         for (section_nr = next_present_section_nr(start-1);     \
     203                 :            :              ((section_nr != -1) &&                             \
     204                 :            :               (section_nr <= __highest_present_section_nr)); \
     205                 :            :              section_nr = next_present_section_nr(section_nr))
     206                 :            : 
     207                 :         21 : static inline unsigned long first_present_section_nr(void)
     208                 :            : {
     209                 :         21 :         return next_present_section_nr(-1);
     210                 :            : }
     211                 :            : 
     212                 :        189 : static void subsection_mask_set(unsigned long *map, unsigned long pfn,
     213                 :            :                 unsigned long nr_pages)
     214                 :            : {
     215         [ -  + ]:        189 :         int idx = subsection_map_index(pfn);
     216                 :        189 :         int end = subsection_map_index(pfn + nr_pages - 1);
     217                 :            : 
     218         [ -  + ]:        189 :         bitmap_set(map, idx, end - idx + 1);
     219                 :        189 : }
     220                 :            : 
     221                 :         42 : void __init subsection_map_init(unsigned long pfn, unsigned long nr_pages)
     222                 :            : {
     223         [ +  - ]:         42 :         int end_sec = pfn_to_section_nr(pfn + nr_pages - 1);
     224                 :         42 :         unsigned long nr, start_sec = pfn_to_section_nr(pfn);
     225                 :            : 
     226         [ +  - ]:         42 :         if (!nr_pages)
     227                 :            :                 return;
     228                 :            : 
     229         [ +  + ]:        231 :         for (nr = start_sec; nr <= end_sec; nr++) {
     230                 :        189 :                 struct mem_section *ms;
     231                 :        189 :                 unsigned long pfns;
     232                 :            : 
     233                 :        189 :                 pfns = min(nr_pages, PAGES_PER_SECTION
     234                 :            :                                 - (pfn & ~PAGE_SECTION_MASK));
     235         [ +  - ]:        189 :                 ms = __nr_to_section(nr);
     236                 :        189 :                 subsection_mask_set(ms->usage->subsection_map, pfn, pfns);
     237                 :            : 
     238                 :        189 :                 pr_debug("%s: sec: %lu pfns: %lu set(%d, %d)\n", __func__, nr,
     239                 :            :                                 pfns, subsection_map_index(pfn),
     240                 :            :                                 subsection_map_index(pfn + pfns - 1));
     241                 :            : 
     242                 :        189 :                 pfn += pfns;
     243                 :        189 :                 nr_pages -= pfns;
     244                 :            :         }
     245                 :            : }
     246                 :            : 
     247                 :            : /* Record a memory area against a node. */
     248                 :         42 : void __init memory_present(int nid, unsigned long start, unsigned long end)
     249                 :            : {
     250                 :         42 :         unsigned long pfn;
     251                 :            : 
     252                 :            : #ifdef CONFIG_SPARSEMEM_EXTREME
     253         [ +  + ]:         42 :         if (unlikely(!mem_section)) {
     254                 :         21 :                 unsigned long size, align;
     255                 :            : 
     256      [ -  +  - ]:         21 :                 size = sizeof(struct mem_section*) * NR_SECTION_ROOTS;
     257                 :         21 :                 align = 1 << (INTERNODE_CACHE_SHIFT);
     258                 :         21 :                 mem_section = memblock_alloc(size, align);
     259         [ -  + ]:         21 :                 if (!mem_section)
     260                 :          0 :                         panic("%s: Failed to allocate %lu bytes align=0x%lx\n",
     261                 :            :                               __func__, size, align);
     262                 :            :         }
     263                 :            : #endif
     264                 :            : 
     265                 :         42 :         start &= PAGE_SECTION_MASK;
     266                 :         42 :         mminit_validate_memmodel_limits(&start, &end);
     267         [ +  + ]:        231 :         for (pfn = start; pfn < end; pfn += PAGES_PER_SECTION) {
     268                 :        189 :                 unsigned long section = pfn_to_section_nr(pfn);
     269                 :        189 :                 struct mem_section *ms;
     270                 :            : 
     271                 :        189 :                 sparse_index_init(section, nid);
     272                 :        189 :                 set_section_nid(section, nid);
     273                 :            : 
     274         [ +  - ]:        189 :                 ms = __nr_to_section(section);
     275         [ +  + ]:        189 :                 if (!ms->section_mem_map) {
     276                 :        168 :                         ms->section_mem_map = sparse_encode_early_nid(nid) |
     277                 :            :                                                         SECTION_IS_ONLINE;
     278                 :        168 :                         section_mark_present(ms);
     279                 :            :                 }
     280                 :            :         }
     281                 :         42 : }
     282                 :            : 
     283                 :            : /*
     284                 :            :  * Mark all memblocks as present using memory_present(). This is a
     285                 :            :  * convienence function that is useful for a number of arches
     286                 :            :  * to mark all of the systems memory as present during initialization.
     287                 :            :  */
     288                 :          0 : void __init memblocks_present(void)
     289                 :            : {
     290                 :          0 :         struct memblock_region *reg;
     291                 :            : 
     292         [ #  # ]:          0 :         for_each_memblock(memory, reg) {
     293                 :          0 :                 memory_present(memblock_get_region_node(reg),
     294                 :            :                                memblock_region_memory_base_pfn(reg),
     295                 :            :                                memblock_region_memory_end_pfn(reg));
     296                 :            :         }
     297                 :          0 : }
     298                 :            : 
     299                 :            : /*
     300                 :            :  * Subtle, we encode the real pfn into the mem_map such that
     301                 :            :  * the identity pfn - section_mem_map will return the actual
     302                 :            :  * physical page frame number.
     303                 :            :  */
     304                 :            : static unsigned long sparse_encode_mem_map(struct page *mem_map, unsigned long pnum)
     305                 :            : {
     306                 :            :         unsigned long coded_mem_map =
     307                 :            :                 (unsigned long)(mem_map - (section_nr_to_pfn(pnum)));
     308                 :            :         BUILD_BUG_ON(SECTION_MAP_LAST_BIT > (1UL<<PFN_SECTION_SHIFT));
     309                 :            :         BUG_ON(coded_mem_map & ~SECTION_MAP_MASK);
     310                 :            :         return coded_mem_map;
     311                 :            : }
     312                 :            : 
     313                 :            : /*
     314                 :            :  * Decode mem_map from the coded memmap
     315                 :            :  */
     316                 :          0 : struct page *sparse_decode_mem_map(unsigned long coded_mem_map, unsigned long pnum)
     317                 :            : {
     318                 :            :         /* mask off the extra low bits of information */
     319                 :          0 :         coded_mem_map &= SECTION_MAP_MASK;
     320                 :          0 :         return ((struct page *)coded_mem_map) + section_nr_to_pfn(pnum);
     321                 :            : }
     322                 :            : 
     323                 :            : static void __meminit sparse_init_one_section(struct mem_section *ms,
     324                 :            :                 unsigned long pnum, struct page *mem_map,
     325                 :            :                 struct mem_section_usage *usage, unsigned long flags)
     326                 :            : {
     327                 :            :         ms->section_mem_map &= ~SECTION_MAP_MASK;
     328                 :            :         ms->section_mem_map |= sparse_encode_mem_map(mem_map, pnum)
     329                 :            :                 | SECTION_HAS_MEM_MAP | flags;
     330                 :            :         ms->usage = usage;
     331                 :            : }
     332                 :            : 
     333                 :        189 : static unsigned long usemap_size(void)
     334                 :            : {
     335                 :        189 :         return BITS_TO_LONGS(SECTION_BLOCKFLAGS_BITS) * sizeof(unsigned long);
     336                 :            : }
     337                 :            : 
     338                 :        189 : size_t mem_section_usage_size(void)
     339                 :            : {
     340                 :        189 :         return sizeof(struct mem_section_usage) + usemap_size();
     341                 :            : }
     342                 :            : 
     343                 :            : #ifdef CONFIG_MEMORY_HOTREMOVE
     344                 :            : static struct mem_section_usage * __init
     345                 :            : sparse_early_usemaps_alloc_pgdat_section(struct pglist_data *pgdat,
     346                 :            :                                          unsigned long size)
     347                 :            : {
     348                 :            :         struct mem_section_usage *usage;
     349                 :            :         unsigned long goal, limit;
     350                 :            :         int nid;
     351                 :            :         /*
     352                 :            :          * A page may contain usemaps for other sections preventing the
     353                 :            :          * page being freed and making a section unremovable while
     354                 :            :          * other sections referencing the usemap remain active. Similarly,
     355                 :            :          * a pgdat can prevent a section being removed. If section A
     356                 :            :          * contains a pgdat and section B contains the usemap, both
     357                 :            :          * sections become inter-dependent. This allocates usemaps
     358                 :            :          * from the same section as the pgdat where possible to avoid
     359                 :            :          * this problem.
     360                 :            :          */
     361                 :            :         goal = __pa(pgdat) & (PAGE_SECTION_MASK << PAGE_SHIFT);
     362                 :            :         limit = goal + (1UL << PA_SECTION_SHIFT);
     363                 :            :         nid = early_pfn_to_nid(goal >> PAGE_SHIFT);
     364                 :            : again:
     365                 :            :         usage = memblock_alloc_try_nid(size, SMP_CACHE_BYTES, goal, limit, nid);
     366                 :            :         if (!usage && limit) {
     367                 :            :                 limit = 0;
     368                 :            :                 goto again;
     369                 :            :         }
     370                 :            :         return usage;
     371                 :            : }
     372                 :            : 
     373                 :            : static void __init check_usemap_section_nr(int nid,
     374                 :            :                 struct mem_section_usage *usage)
     375                 :            : {
     376                 :            :         unsigned long usemap_snr, pgdat_snr;
     377                 :            :         static unsigned long old_usemap_snr;
     378                 :            :         static unsigned long old_pgdat_snr;
     379                 :            :         struct pglist_data *pgdat = NODE_DATA(nid);
     380                 :            :         int usemap_nid;
     381                 :            : 
     382                 :            :         /* First call */
     383                 :            :         if (!old_usemap_snr) {
     384                 :            :                 old_usemap_snr = NR_MEM_SECTIONS;
     385                 :            :                 old_pgdat_snr = NR_MEM_SECTIONS;
     386                 :            :         }
     387                 :            : 
     388                 :            :         usemap_snr = pfn_to_section_nr(__pa(usage) >> PAGE_SHIFT);
     389                 :            :         pgdat_snr = pfn_to_section_nr(__pa(pgdat) >> PAGE_SHIFT);
     390                 :            :         if (usemap_snr == pgdat_snr)
     391                 :            :                 return;
     392                 :            : 
     393                 :            :         if (old_usemap_snr == usemap_snr && old_pgdat_snr == pgdat_snr)
     394                 :            :                 /* skip redundant message */
     395                 :            :                 return;
     396                 :            : 
     397                 :            :         old_usemap_snr = usemap_snr;
     398                 :            :         old_pgdat_snr = pgdat_snr;
     399                 :            : 
     400                 :            :         usemap_nid = sparse_early_nid(__nr_to_section(usemap_snr));
     401                 :            :         if (usemap_nid != nid) {
     402                 :            :                 pr_info("node %d must be removed before remove section %ld\n",
     403                 :            :                         nid, usemap_snr);
     404                 :            :                 return;
     405                 :            :         }
     406                 :            :         /*
     407                 :            :          * There is a circular dependency.
     408                 :            :          * Some platforms allow un-removable section because they will just
     409                 :            :          * gather other removable sections for dynamic partitioning.
     410                 :            :          * Just notify un-removable section's number here.
     411                 :            :          */
     412                 :            :         pr_info("Section %ld and %ld (node %d) have a circular dependency on usemap and pgdat allocations\n",
     413                 :            :                 usemap_snr, pgdat_snr, nid);
     414                 :            : }
     415                 :            : #else
     416                 :            : static struct mem_section_usage * __init
     417                 :            : sparse_early_usemaps_alloc_pgdat_section(struct pglist_data *pgdat,
     418                 :            :                                          unsigned long size)
     419                 :            : {
     420                 :            :         return memblock_alloc_node(size, SMP_CACHE_BYTES, pgdat->node_id);
     421                 :            : }
     422                 :            : 
     423                 :        168 : static void __init check_usemap_section_nr(int nid,
     424                 :            :                 struct mem_section_usage *usage)
     425                 :            : {
     426                 :        168 : }
     427                 :            : #endif /* CONFIG_MEMORY_HOTREMOVE */
     428                 :            : 
     429                 :            : #ifdef CONFIG_SPARSEMEM_VMEMMAP
     430                 :         42 : static unsigned long __init section_map_size(void)
     431                 :            : {
     432                 :         42 :         return ALIGN(sizeof(struct page) * PAGES_PER_SECTION, PMD_SIZE);
     433                 :            : }
     434                 :            : 
     435                 :            : #else
     436                 :            : static unsigned long __init section_map_size(void)
     437                 :            : {
     438                 :            :         return PAGE_ALIGN(sizeof(struct page) * PAGES_PER_SECTION);
     439                 :            : }
     440                 :            : 
     441                 :            : struct page __init *__populate_section_memmap(unsigned long pfn,
     442                 :            :                 unsigned long nr_pages, int nid, struct vmem_altmap *altmap)
     443                 :            : {
     444                 :            :         unsigned long size = section_map_size();
     445                 :            :         struct page *map = sparse_buffer_alloc(size);
     446                 :            :         phys_addr_t addr = __pa(MAX_DMA_ADDRESS);
     447                 :            : 
     448                 :            :         if (map)
     449                 :            :                 return map;
     450                 :            : 
     451                 :            :         map = memblock_alloc_try_nid_raw(size, size, addr,
     452                 :            :                                           MEMBLOCK_ALLOC_ACCESSIBLE, nid);
     453                 :            :         if (!map)
     454                 :            :                 panic("%s: Failed to allocate %lu bytes align=0x%lx nid=%d from=%pa\n",
     455                 :            :                       __func__, size, PAGE_SIZE, nid, &addr);
     456                 :            : 
     457                 :            :         return map;
     458                 :            : }
     459                 :            : #endif /* !CONFIG_SPARSEMEM_VMEMMAP */
     460                 :            : 
     461                 :            : static void *sparsemap_buf __meminitdata;
     462                 :            : static void *sparsemap_buf_end __meminitdata;
     463                 :            : 
     464                 :          0 : static inline void __meminit sparse_buffer_free(unsigned long size)
     465                 :            : {
     466   [ #  #  #  #  :          0 :         WARN_ON(!sparsemap_buf || size == 0);
                   #  # ]
     467         [ #  # ]:          0 :         memblock_free_early(__pa(sparsemap_buf), size);
     468                 :          0 : }
     469                 :            : 
     470                 :         21 : static void __init sparse_buffer_init(unsigned long size, int nid)
     471                 :            : {
     472         [ +  - ]:         21 :         phys_addr_t addr = __pa(MAX_DMA_ADDRESS);
     473         [ -  + ]:         21 :         WARN_ON(sparsemap_buf); /* forgot to call sparse_buffer_fini()? */
     474                 :            :         /*
     475                 :            :          * Pre-allocated buffer is mainly used by __populate_section_memmap
     476                 :            :          * and we want it to be properly aligned to the section size - this is
     477                 :            :          * especially the case for VMEMMAP which maps memmap to PMDs
     478                 :            :          */
     479                 :         21 :         sparsemap_buf = memblock_alloc_exact_nid_raw(size, section_map_size(),
     480                 :            :                                         addr, MEMBLOCK_ALLOC_ACCESSIBLE, nid);
     481                 :         21 :         sparsemap_buf_end = sparsemap_buf + size;
     482                 :         21 : }
     483                 :            : 
     484                 :         21 : static void __init sparse_buffer_fini(void)
     485                 :            : {
     486                 :         21 :         unsigned long size = sparsemap_buf_end - sparsemap_buf;
     487                 :            : 
     488   [ +  -  -  + ]:         21 :         if (sparsemap_buf && size > 0)
     489                 :          0 :                 sparse_buffer_free(size);
     490                 :         21 :         sparsemap_buf = NULL;
     491                 :         21 : }
     492                 :            : 
     493                 :        168 : void * __meminit sparse_buffer_alloc(unsigned long size)
     494                 :            : {
     495                 :        168 :         void *ptr = NULL;
     496                 :            : 
     497         [ +  - ]:        168 :         if (sparsemap_buf) {
     498                 :        168 :                 ptr = (void *) roundup((unsigned long)sparsemap_buf, size);
     499         [ +  - ]:        168 :                 if (ptr + size > sparsemap_buf_end)
     500                 :            :                         ptr = NULL;
     501                 :            :                 else {
     502                 :            :                         /* Free redundant aligned space */
     503         [ -  + ]:        168 :                         if ((unsigned long)(ptr - sparsemap_buf) > 0)
     504                 :          0 :                                 sparse_buffer_free((unsigned long)(ptr - sparsemap_buf));
     505                 :        168 :                         sparsemap_buf = ptr + size;
     506                 :            :                 }
     507                 :            :         }
     508                 :        168 :         return ptr;
     509                 :            : }
     510                 :            : 
     511                 :          0 : void __weak __meminit vmemmap_populate_print_last(void)
     512                 :            : {
     513                 :          0 : }
     514                 :            : 
     515                 :            : /*
     516                 :            :  * Initialize sparse on a specific node. The node spans [pnum_begin, pnum_end)
     517                 :            :  * And number of present sections in this node is map_count.
     518                 :            :  */
     519                 :         21 : static void __init sparse_init_nid(int nid, unsigned long pnum_begin,
     520                 :            :                                    unsigned long pnum_end,
     521                 :            :                                    unsigned long map_count)
     522                 :            : {
     523                 :         21 :         struct mem_section_usage *usage;
     524                 :         21 :         unsigned long pnum;
     525                 :         21 :         struct page *map;
     526                 :            : 
     527                 :         21 :         usage = sparse_early_usemaps_alloc_pgdat_section(NODE_DATA(nid),
     528                 :            :                         mem_section_usage_size() * map_count);
     529         [ -  + ]:         21 :         if (!usage) {
     530                 :          0 :                 pr_err("%s: node[%d] usemap allocation failed", __func__, nid);
     531                 :          0 :                 goto failed;
     532                 :            :         }
     533                 :         21 :         sparse_buffer_init(map_count * section_map_size(), nid);
     534   [ +  +  +  - ]:        210 :         for_each_present_section_nr(pnum_begin, pnum) {
     535         [ +  - ]:        168 :                 unsigned long pfn = section_nr_to_pfn(pnum);
     536                 :            : 
     537         [ +  - ]:        168 :                 if (pnum >= pnum_end)
     538                 :            :                         break;
     539                 :            : 
     540                 :        168 :                 map = __populate_section_memmap(pfn, PAGES_PER_SECTION,
     541                 :            :                                 nid, NULL);
     542         [ -  + ]:        168 :                 if (!map) {
     543                 :          0 :                         pr_err("%s: node[%d] memory map backing failed. Some memory will not be available.",
     544                 :            :                                __func__, nid);
     545                 :          0 :                         pnum_begin = pnum;
     546                 :          0 :                         goto failed;
     547                 :            :                 }
     548                 :        168 :                 check_usemap_section_nr(nid, usage);
     549         [ +  - ]:        336 :                 sparse_init_one_section(__nr_to_section(pnum), pnum, map, usage,
     550                 :            :                                 SECTION_IS_EARLY);
     551                 :        168 :                 usage = (void *) usage + mem_section_usage_size();
     552                 :            :         }
     553                 :         21 :         sparse_buffer_fini();
     554                 :         21 :         return;
     555                 :          0 : failed:
     556                 :            :         /* We failed to allocate, mark all the following pnums as not present */
     557   [ #  #  #  # ]:          0 :         for_each_present_section_nr(pnum_begin, pnum) {
     558                 :          0 :                 struct mem_section *ms;
     559                 :            : 
     560         [ #  # ]:          0 :                 if (pnum >= pnum_end)
     561                 :            :                         break;
     562         [ #  # ]:          0 :                 ms = __nr_to_section(pnum);
     563                 :          0 :                 ms->section_mem_map = 0;
     564                 :            :         }
     565                 :            : }
     566                 :            : 
     567                 :            : /*
     568                 :            :  * Allocate the accumulated non-linear sections, allocate a mem_map
     569                 :            :  * for each and record the physical to section mapping.
     570                 :            :  */
     571                 :         21 : void __init sparse_init(void)
     572                 :            : {
     573                 :         21 :         unsigned long pnum_begin = first_present_section_nr();
     574         [ +  - ]:         21 :         int nid_begin = sparse_early_nid(__nr_to_section(pnum_begin));
     575                 :         21 :         unsigned long pnum_end, map_count = 1;
     576                 :            : 
     577                 :            :         /* Setup pageblock_order for HUGETLB_PAGE_SIZE_VARIABLE */
     578                 :         21 :         set_pageblock_order();
     579                 :            : 
     580   [ +  +  +  - ]:        336 :         for_each_present_section_nr(pnum_begin + 1, pnum_end) {
     581         [ +  - ]:        147 :                 int nid = sparse_early_nid(__nr_to_section(pnum_end));
     582                 :            : 
     583         [ +  - ]:        147 :                 if (nid == nid_begin) {
     584                 :        147 :                         map_count++;
     585                 :        147 :                         continue;
     586                 :            :                 }
     587                 :            :                 /* Init node with sections in range [pnum_begin, pnum_end) */
     588                 :          0 :                 sparse_init_nid(nid_begin, pnum_begin, pnum_end, map_count);
     589                 :          0 :                 nid_begin = nid;
     590                 :          0 :                 pnum_begin = pnum_end;
     591                 :          0 :                 map_count = 1;
     592                 :            :         }
     593                 :            :         /* cover the last node */
     594                 :         21 :         sparse_init_nid(nid_begin, pnum_begin, pnum_end, map_count);
     595                 :         21 :         vmemmap_populate_print_last();
     596                 :         21 : }
     597                 :            : 
     598                 :            : #ifdef CONFIG_MEMORY_HOTPLUG
     599                 :            : 
     600                 :            : /* Mark all memory sections within the pfn range as online */
     601                 :            : void online_mem_sections(unsigned long start_pfn, unsigned long end_pfn)
     602                 :            : {
     603                 :            :         unsigned long pfn;
     604                 :            : 
     605                 :            :         for (pfn = start_pfn; pfn < end_pfn; pfn += PAGES_PER_SECTION) {
     606                 :            :                 unsigned long section_nr = pfn_to_section_nr(pfn);
     607                 :            :                 struct mem_section *ms;
     608                 :            : 
     609                 :            :                 /* onlining code should never touch invalid ranges */
     610                 :            :                 if (WARN_ON(!valid_section_nr(section_nr)))
     611                 :            :                         continue;
     612                 :            : 
     613                 :            :                 ms = __nr_to_section(section_nr);
     614                 :            :                 ms->section_mem_map |= SECTION_IS_ONLINE;
     615                 :            :         }
     616                 :            : }
     617                 :            : 
     618                 :            : #ifdef CONFIG_MEMORY_HOTREMOVE
     619                 :            : /* Mark all memory sections within the pfn range as offline */
     620                 :            : void offline_mem_sections(unsigned long start_pfn, unsigned long end_pfn)
     621                 :            : {
     622                 :            :         unsigned long pfn;
     623                 :            : 
     624                 :            :         for (pfn = start_pfn; pfn < end_pfn; pfn += PAGES_PER_SECTION) {
     625                 :            :                 unsigned long section_nr = pfn_to_section_nr(pfn);
     626                 :            :                 struct mem_section *ms;
     627                 :            : 
     628                 :            :                 /*
     629                 :            :                  * TODO this needs some double checking. Offlining code makes
     630                 :            :                  * sure to check pfn_valid but those checks might be just bogus
     631                 :            :                  */
     632                 :            :                 if (WARN_ON(!valid_section_nr(section_nr)))
     633                 :            :                         continue;
     634                 :            : 
     635                 :            :                 ms = __nr_to_section(section_nr);
     636                 :            :                 ms->section_mem_map &= ~SECTION_IS_ONLINE;
     637                 :            :         }
     638                 :            : }
     639                 :            : #endif
     640                 :            : 
     641                 :            : #ifdef CONFIG_SPARSEMEM_VMEMMAP
     642                 :            : static struct page * __meminit populate_section_memmap(unsigned long pfn,
     643                 :            :                 unsigned long nr_pages, int nid, struct vmem_altmap *altmap)
     644                 :            : {
     645                 :            :         return __populate_section_memmap(pfn, nr_pages, nid, altmap);
     646                 :            : }
     647                 :            : 
     648                 :            : static void depopulate_section_memmap(unsigned long pfn, unsigned long nr_pages,
     649                 :            :                 struct vmem_altmap *altmap)
     650                 :            : {
     651                 :            :         unsigned long start = (unsigned long) pfn_to_page(pfn);
     652                 :            :         unsigned long end = start + nr_pages * sizeof(struct page);
     653                 :            : 
     654                 :            :         vmemmap_free(start, end, altmap);
     655                 :            : }
     656                 :            : static void free_map_bootmem(struct page *memmap)
     657                 :            : {
     658                 :            :         unsigned long start = (unsigned long)memmap;
     659                 :            :         unsigned long end = (unsigned long)(memmap + PAGES_PER_SECTION);
     660                 :            : 
     661                 :            :         vmemmap_free(start, end, NULL);
     662                 :            : }
     663                 :            : #else
     664                 :            : struct page * __meminit populate_section_memmap(unsigned long pfn,
     665                 :            :                 unsigned long nr_pages, int nid, struct vmem_altmap *altmap)
     666                 :            : {
     667                 :            :         struct page *page, *ret;
     668                 :            :         unsigned long memmap_size = sizeof(struct page) * PAGES_PER_SECTION;
     669                 :            : 
     670                 :            :         page = alloc_pages(GFP_KERNEL|__GFP_NOWARN, get_order(memmap_size));
     671                 :            :         if (page)
     672                 :            :                 goto got_map_page;
     673                 :            : 
     674                 :            :         ret = vmalloc(memmap_size);
     675                 :            :         if (ret)
     676                 :            :                 goto got_map_ptr;
     677                 :            : 
     678                 :            :         return NULL;
     679                 :            : got_map_page:
     680                 :            :         ret = (struct page *)pfn_to_kaddr(page_to_pfn(page));
     681                 :            : got_map_ptr:
     682                 :            : 
     683                 :            :         return ret;
     684                 :            : }
     685                 :            : 
     686                 :            : static void depopulate_section_memmap(unsigned long pfn, unsigned long nr_pages,
     687                 :            :                 struct vmem_altmap *altmap)
     688                 :            : {
     689                 :            :         struct page *memmap = pfn_to_page(pfn);
     690                 :            : 
     691                 :            :         if (is_vmalloc_addr(memmap))
     692                 :            :                 vfree(memmap);
     693                 :            :         else
     694                 :            :                 free_pages((unsigned long)memmap,
     695                 :            :                            get_order(sizeof(struct page) * PAGES_PER_SECTION));
     696                 :            : }
     697                 :            : 
     698                 :            : static void free_map_bootmem(struct page *memmap)
     699                 :            : {
     700                 :            :         unsigned long maps_section_nr, removing_section_nr, i;
     701                 :            :         unsigned long magic, nr_pages;
     702                 :            :         struct page *page = virt_to_page(memmap);
     703                 :            : 
     704                 :            :         nr_pages = PAGE_ALIGN(PAGES_PER_SECTION * sizeof(struct page))
     705                 :            :                 >> PAGE_SHIFT;
     706                 :            : 
     707                 :            :         for (i = 0; i < nr_pages; i++, page++) {
     708                 :            :                 magic = (unsigned long) page->freelist;
     709                 :            : 
     710                 :            :                 BUG_ON(magic == NODE_INFO);
     711                 :            : 
     712                 :            :                 maps_section_nr = pfn_to_section_nr(page_to_pfn(page));
     713                 :            :                 removing_section_nr = page_private(page);
     714                 :            : 
     715                 :            :                 /*
     716                 :            :                  * When this function is called, the removing section is
     717                 :            :                  * logical offlined state. This means all pages are isolated
     718                 :            :                  * from page allocator. If removing section's memmap is placed
     719                 :            :                  * on the same section, it must not be freed.
     720                 :            :                  * If it is freed, page allocator may allocate it which will
     721                 :            :                  * be removed physically soon.
     722                 :            :                  */
     723                 :            :                 if (maps_section_nr != removing_section_nr)
     724                 :            :                         put_page_bootmem(page);
     725                 :            :         }
     726                 :            : }
     727                 :            : #endif /* CONFIG_SPARSEMEM_VMEMMAP */
     728                 :            : 
     729                 :            : static void section_deactivate(unsigned long pfn, unsigned long nr_pages,
     730                 :            :                 struct vmem_altmap *altmap)
     731                 :            : {
     732                 :            :         DECLARE_BITMAP(map, SUBSECTIONS_PER_SECTION) = { 0 };
     733                 :            :         DECLARE_BITMAP(tmp, SUBSECTIONS_PER_SECTION) = { 0 };
     734                 :            :         struct mem_section *ms = __pfn_to_section(pfn);
     735                 :            :         bool section_is_early = early_section(ms);
     736                 :            :         struct page *memmap = NULL;
     737                 :            :         bool empty;
     738                 :            :         unsigned long *subsection_map = ms->usage
     739                 :            :                 ? &ms->usage->subsection_map[0] : NULL;
     740                 :            : 
     741                 :            :         subsection_mask_set(map, pfn, nr_pages);
     742                 :            :         if (subsection_map)
     743                 :            :                 bitmap_and(tmp, map, subsection_map, SUBSECTIONS_PER_SECTION);
     744                 :            : 
     745                 :            :         if (WARN(!subsection_map || !bitmap_equal(tmp, map, SUBSECTIONS_PER_SECTION),
     746                 :            :                                 "section already deactivated (%#lx + %ld)\n",
     747                 :            :                                 pfn, nr_pages))
     748                 :            :                 return;
     749                 :            : 
     750                 :            :         /*
     751                 :            :          * There are 3 cases to handle across two configurations
     752                 :            :          * (SPARSEMEM_VMEMMAP={y,n}):
     753                 :            :          *
     754                 :            :          * 1/ deactivation of a partial hot-added section (only possible
     755                 :            :          * in the SPARSEMEM_VMEMMAP=y case).
     756                 :            :          *    a/ section was present at memory init
     757                 :            :          *    b/ section was hot-added post memory init
     758                 :            :          * 2/ deactivation of a complete hot-added section
     759                 :            :          * 3/ deactivation of a complete section from memory init
     760                 :            :          *
     761                 :            :          * For 1/, when subsection_map does not empty we will not be
     762                 :            :          * freeing the usage map, but still need to free the vmemmap
     763                 :            :          * range.
     764                 :            :          *
     765                 :            :          * For 2/ and 3/ the SPARSEMEM_VMEMMAP={y,n} cases are unified
     766                 :            :          */
     767                 :            :         bitmap_xor(subsection_map, map, subsection_map, SUBSECTIONS_PER_SECTION);
     768                 :            :         empty = bitmap_empty(subsection_map, SUBSECTIONS_PER_SECTION);
     769                 :            :         if (empty) {
     770                 :            :                 unsigned long section_nr = pfn_to_section_nr(pfn);
     771                 :            : 
     772                 :            :                 /*
     773                 :            :                  * When removing an early section, the usage map is kept (as the
     774                 :            :                  * usage maps of other sections fall into the same page). It
     775                 :            :                  * will be re-used when re-adding the section - which is then no
     776                 :            :                  * longer an early section. If the usage map is PageReserved, it
     777                 :            :                  * was allocated during boot.
     778                 :            :                  */
     779                 :            :                 if (!PageReserved(virt_to_page(ms->usage))) {
     780                 :            :                         kfree(ms->usage);
     781                 :            :                         ms->usage = NULL;
     782                 :            :                 }
     783                 :            :                 memmap = sparse_decode_mem_map(ms->section_mem_map, section_nr);
     784                 :            :                 /*
     785                 :            :                  * Mark the section invalid so that valid_section()
     786                 :            :                  * return false. This prevents code from dereferencing
     787                 :            :                  * ms->usage array.
     788                 :            :                  */
     789                 :            :                 ms->section_mem_map &= ~SECTION_HAS_MEM_MAP;
     790                 :            :         }
     791                 :            : 
     792                 :            :         if (section_is_early && memmap)
     793                 :            :                 free_map_bootmem(memmap);
     794                 :            :         else
     795                 :            :                 depopulate_section_memmap(pfn, nr_pages, altmap);
     796                 :            : 
     797                 :            :         if (empty)
     798                 :            :                 ms->section_mem_map = (unsigned long)NULL;
     799                 :            : }
     800                 :            : 
     801                 :            : static struct page * __meminit section_activate(int nid, unsigned long pfn,
     802                 :            :                 unsigned long nr_pages, struct vmem_altmap *altmap)
     803                 :            : {
     804                 :            :         DECLARE_BITMAP(map, SUBSECTIONS_PER_SECTION) = { 0 };
     805                 :            :         struct mem_section *ms = __pfn_to_section(pfn);
     806                 :            :         struct mem_section_usage *usage = NULL;
     807                 :            :         unsigned long *subsection_map;
     808                 :            :         struct page *memmap;
     809                 :            :         int rc = 0;
     810                 :            : 
     811                 :            :         subsection_mask_set(map, pfn, nr_pages);
     812                 :            : 
     813                 :            :         if (!ms->usage) {
     814                 :            :                 usage = kzalloc(mem_section_usage_size(), GFP_KERNEL);
     815                 :            :                 if (!usage)
     816                 :            :                         return ERR_PTR(-ENOMEM);
     817                 :            :                 ms->usage = usage;
     818                 :            :         }
     819                 :            :         subsection_map = &ms->usage->subsection_map[0];
     820                 :            : 
     821                 :            :         if (bitmap_empty(map, SUBSECTIONS_PER_SECTION))
     822                 :            :                 rc = -EINVAL;
     823                 :            :         else if (bitmap_intersects(map, subsection_map, SUBSECTIONS_PER_SECTION))
     824                 :            :                 rc = -EEXIST;
     825                 :            :         else
     826                 :            :                 bitmap_or(subsection_map, map, subsection_map,
     827                 :            :                                 SUBSECTIONS_PER_SECTION);
     828                 :            : 
     829                 :            :         if (rc) {
     830                 :            :                 if (usage)
     831                 :            :                         ms->usage = NULL;
     832                 :            :                 kfree(usage);
     833                 :            :                 return ERR_PTR(rc);
     834                 :            :         }
     835                 :            : 
     836                 :            :         /*
     837                 :            :          * The early init code does not consider partially populated
     838                 :            :          * initial sections, it simply assumes that memory will never be
     839                 :            :          * referenced.  If we hot-add memory into such a section then we
     840                 :            :          * do not need to populate the memmap and can simply reuse what
     841                 :            :          * is already there.
     842                 :            :          */
     843                 :            :         if (nr_pages < PAGES_PER_SECTION && early_section(ms))
     844                 :            :                 return pfn_to_page(pfn);
     845                 :            : 
     846                 :            :         memmap = populate_section_memmap(pfn, nr_pages, nid, altmap);
     847                 :            :         if (!memmap) {
     848                 :            :                 section_deactivate(pfn, nr_pages, altmap);
     849                 :            :                 return ERR_PTR(-ENOMEM);
     850                 :            :         }
     851                 :            : 
     852                 :            :         return memmap;
     853                 :            : }
     854                 :            : 
     855                 :            : /**
     856                 :            :  * sparse_add_section - add a memory section, or populate an existing one
     857                 :            :  * @nid: The node to add section on
     858                 :            :  * @start_pfn: start pfn of the memory range
     859                 :            :  * @nr_pages: number of pfns to add in the section
     860                 :            :  * @altmap: device page map
     861                 :            :  *
     862                 :            :  * This is only intended for hotplug.
     863                 :            :  *
     864                 :            :  * Return:
     865                 :            :  * * 0          - On success.
     866                 :            :  * * -EEXIST    - Section has been present.
     867                 :            :  * * -ENOMEM    - Out of memory.
     868                 :            :  */
     869                 :            : int __meminit sparse_add_section(int nid, unsigned long start_pfn,
     870                 :            :                 unsigned long nr_pages, struct vmem_altmap *altmap)
     871                 :            : {
     872                 :            :         unsigned long section_nr = pfn_to_section_nr(start_pfn);
     873                 :            :         struct mem_section *ms;
     874                 :            :         struct page *memmap;
     875                 :            :         int ret;
     876                 :            : 
     877                 :            :         ret = sparse_index_init(section_nr, nid);
     878                 :            :         if (ret < 0)
     879                 :            :                 return ret;
     880                 :            : 
     881                 :            :         memmap = section_activate(nid, start_pfn, nr_pages, altmap);
     882                 :            :         if (IS_ERR(memmap))
     883                 :            :                 return PTR_ERR(memmap);
     884                 :            : 
     885                 :            :         /*
     886                 :            :          * Poison uninitialized struct pages in order to catch invalid flags
     887                 :            :          * combinations.
     888                 :            :          */
     889                 :            :         page_init_poison(memmap, sizeof(struct page) * nr_pages);
     890                 :            : 
     891                 :            :         ms = __nr_to_section(section_nr);
     892                 :            :         set_section_nid(section_nr, nid);
     893                 :            :         section_mark_present(ms);
     894                 :            : 
     895                 :            :         /* Align memmap to section boundary in the subsection case */
     896                 :            :         if (section_nr_to_pfn(section_nr) != start_pfn)
     897                 :            :                 memmap = pfn_to_kaddr(section_nr_to_pfn(section_nr));
     898                 :            :         sparse_init_one_section(ms, section_nr, memmap, ms->usage, 0);
     899                 :            : 
     900                 :            :         return 0;
     901                 :            : }
     902                 :            : 
     903                 :            : #ifdef CONFIG_MEMORY_FAILURE
     904                 :            : static void clear_hwpoisoned_pages(struct page *memmap, int nr_pages)
     905                 :            : {
     906                 :            :         int i;
     907                 :            : 
     908                 :            :         /*
     909                 :            :          * A further optimization is to have per section refcounted
     910                 :            :          * num_poisoned_pages.  But that would need more space per memmap, so
     911                 :            :          * for now just do a quick global check to speed up this routine in the
     912                 :            :          * absence of bad pages.
     913                 :            :          */
     914                 :            :         if (atomic_long_read(&num_poisoned_pages) == 0)
     915                 :            :                 return;
     916                 :            : 
     917                 :            :         for (i = 0; i < nr_pages; i++) {
     918                 :            :                 if (PageHWPoison(&memmap[i])) {
     919                 :            :                         num_poisoned_pages_dec();
     920                 :            :                         ClearPageHWPoison(&memmap[i]);
     921                 :            :                 }
     922                 :            :         }
     923                 :            : }
     924                 :            : #else
     925                 :            : static inline void clear_hwpoisoned_pages(struct page *memmap, int nr_pages)
     926                 :            : {
     927                 :            : }
     928                 :            : #endif
     929                 :            : 
     930                 :            : void sparse_remove_section(struct mem_section *ms, unsigned long pfn,
     931                 :            :                 unsigned long nr_pages, unsigned long map_offset,
     932                 :            :                 struct vmem_altmap *altmap)
     933                 :            : {
     934                 :            :         clear_hwpoisoned_pages(pfn_to_page(pfn) + map_offset,
     935                 :            :                         nr_pages - map_offset);
     936                 :            :         section_deactivate(pfn, nr_pages, altmap);
     937                 :            : }
     938                 :            : #endif /* CONFIG_MEMORY_HOTPLUG */

Generated by: LCOV version 1.14