1.. SPDX-License-Identifier: GPL-2.0 2 3.. _physical_memory_model: 4 5===================== 6Physical Memory Model 7===================== 8 9Physical memory in a system may be addressed in different ways. The 10simplest case is when the physical memory starts at address 0 and 11spans a contiguous range up to the maximal address. It could be, 12however, that this range contains small holes that are not accessible 13for the CPU. Then there could be several contiguous ranges at 14completely distinct addresses. And, don't forget about NUMA, where 15different memory banks are attached to different CPUs. 16 17Linux abstracts this diversity using one of the three memory models: 18FLATMEM, DISCONTIGMEM and SPARSEMEM. Each architecture defines what 19memory models it supports, what the default memory model is and 20whether it is possible to manually override that default. 21 22.. note:: 23 At time of this writing, DISCONTIGMEM is considered deprecated, 24 although it is still in use by several architectures. 25 26All the memory models track the status of physical page frames using 27:c:type:`struct page` arranged in one or more arrays. 28 29Regardless of the selected memory model, there exists one-to-one 30mapping between the physical page frame number (PFN) and the 31corresponding `struct page`. 32 33Each memory model defines :c:func:`pfn_to_page` and :c:func:`page_to_pfn` 34helpers that allow the conversion from PFN to `struct page` and vice 35versa. 36 37FLATMEM 38======= 39 40The simplest memory model is FLATMEM. This model is suitable for 41non-NUMA systems with contiguous, or mostly contiguous, physical 42memory. 43 44In the FLATMEM memory model, there is a global `mem_map` array that 45maps the entire physical memory. For most architectures, the holes 46have entries in the `mem_map` array. The `struct page` objects 47corresponding to the holes are never fully initialized. 48 49To allocate the `mem_map` array, architecture specific setup code 50should call :c:func:`free_area_init_node` function or its convenience 51wrapper :c:func:`free_area_init`. Yet, the mappings array is not 52usable until the call to :c:func:`memblock_free_all` that hands all 53the memory to the page allocator. 54 55If an architecture enables `CONFIG_ARCH_HAS_HOLES_MEMORYMODEL` option, 56it may free parts of the `mem_map` array that do not cover the 57actual physical pages. In such case, the architecture specific 58:c:func:`pfn_valid` implementation should take the holes in the 59`mem_map` into account. 60 61With FLATMEM, the conversion between a PFN and the `struct page` is 62straightforward: `PFN - ARCH_PFN_OFFSET` is an index to the 63`mem_map` array. 64 65The `ARCH_PFN_OFFSET` defines the first page frame number for 66systems with physical memory starting at address different from 0. 67 68DISCONTIGMEM 69============ 70 71The DISCONTIGMEM model treats the physical memory as a collection of 72`nodes` similarly to how Linux NUMA support does. For each node Linux 73constructs an independent memory management subsystem represented by 74`struct pglist_data` (or `pg_data_t` for short). Among other 75things, `pg_data_t` holds the `node_mem_map` array that maps 76physical pages belonging to that node. The `node_start_pfn` field of 77`pg_data_t` is the number of the first page frame belonging to that 78node. 79 80The architecture setup code should call :c:func:`free_area_init_node` for 81each node in the system to initialize the `pg_data_t` object and its 82`node_mem_map`. 83 84Every `node_mem_map` behaves exactly as FLATMEM's `mem_map` - 85every physical page frame in a node has a `struct page` entry in the 86`node_mem_map` array. When DISCONTIGMEM is enabled, a portion of the 87`flags` field of the `struct page` encodes the node number of the 88node hosting that page. 89 90The conversion between a PFN and the `struct page` in the 91DISCONTIGMEM model became slightly more complex as it has to determine 92which node hosts the physical page and which `pg_data_t` object 93holds the `struct page`. 94 95Architectures that support DISCONTIGMEM provide :c:func:`pfn_to_nid` 96to convert PFN to the node number. The opposite conversion helper 97:c:func:`page_to_nid` is generic as it uses the node number encoded in 98page->flags. 99 100Once the node number is known, the PFN can be used to index 101appropriate `node_mem_map` array to access the `struct page` and 102the offset of the `struct page` from the `node_mem_map` plus 103`node_start_pfn` is the PFN of that page. 104 105SPARSEMEM 106========= 107 108SPARSEMEM is the most versatile memory model available in Linux and it 109is the only memory model that supports several advanced features such 110as hot-plug and hot-remove of the physical memory, alternative memory 111maps for non-volatile memory devices and deferred initialization of 112the memory map for larger systems. 113 114The SPARSEMEM model presents the physical memory as a collection of 115sections. A section is represented with :c:type:`struct mem_section` 116that contains `section_mem_map` that is, logically, a pointer to an 117array of struct pages. However, it is stored with some other magic 118that aids the sections management. The section size and maximal number 119of section is specified using `SECTION_SIZE_BITS` and 120`MAX_PHYSMEM_BITS` constants defined by each architecture that 121supports SPARSEMEM. While `MAX_PHYSMEM_BITS` is an actual width of a 122physical address that an architecture supports, the 123`SECTION_SIZE_BITS` is an arbitrary value. 124 125The maximal number of sections is denoted `NR_MEM_SECTIONS` and 126defined as 127 128.. math:: 129 130 NR\_MEM\_SECTIONS = 2 ^ {(MAX\_PHYSMEM\_BITS - SECTION\_SIZE\_BITS)} 131 132The `mem_section` objects are arranged in a two-dimensional array 133called `mem_sections`. The size and placement of this array depend 134on `CONFIG_SPARSEMEM_EXTREME` and the maximal possible number of 135sections: 136 137* When `CONFIG_SPARSEMEM_EXTREME` is disabled, the `mem_sections` 138 array is static and has `NR_MEM_SECTIONS` rows. Each row holds a 139 single `mem_section` object. 140* When `CONFIG_SPARSEMEM_EXTREME` is enabled, the `mem_sections` 141 array is dynamically allocated. Each row contains PAGE_SIZE worth of 142 `mem_section` objects and the number of rows is calculated to fit 143 all the memory sections. 144 145The architecture setup code should call :c:func:`memory_present` for 146each active memory range or use :c:func:`memblocks_present` or 147:c:func:`sparse_memory_present_with_active_regions` wrappers to 148initialize the memory sections. Next, the actual memory maps should be 149set up using :c:func:`sparse_init`. 150 151With SPARSEMEM there are two possible ways to convert a PFN to the 152corresponding `struct page` - a "classic sparse" and "sparse 153vmemmap". The selection is made at build time and it is determined by 154the value of `CONFIG_SPARSEMEM_VMEMMAP`. 155 156The classic sparse encodes the section number of a page in page->flags 157and uses high bits of a PFN to access the section that maps that page 158frame. Inside a section, the PFN is the index to the array of pages. 159 160The sparse vmemmap uses a virtually mapped memory map to optimize 161pfn_to_page and page_to_pfn operations. There is a global `struct 162page *vmemmap` pointer that points to a virtually contiguous array of 163`struct page` objects. A PFN is an index to that array and the the 164offset of the `struct page` from `vmemmap` is the PFN of that 165page. 166 167To use vmemmap, an architecture has to reserve a range of virtual 168addresses that will map the physical pages containing the memory 169map and make sure that `vmemmap` points to that range. In addition, 170the architecture should implement :c:func:`vmemmap_populate` method 171that will allocate the physical memory and create page tables for the 172virtual memory map. If an architecture does not have any special 173requirements for the vmemmap mappings, it can use default 174:c:func:`vmemmap_populate_basepages` provided by the generic memory 175management. 176 177The virtually mapped memory map allows storing `struct page` objects 178for persistent memory devices in pre-allocated storage on those 179devices. This storage is represented with :c:type:`struct vmem_altmap` 180that is eventually passed to vmemmap_populate() through a long chain 181of function calls. The vmemmap_populate() implementation may use the 182`vmem_altmap` along with :c:func:`altmap_alloc_block_buf` helper to 183allocate memory map on the persistent memory device. 184 185ZONE_DEVICE 186=========== 187The `ZONE_DEVICE` facility builds upon `SPARSEMEM_VMEMMAP` to offer 188`struct page` `mem_map` services for device driver identified physical 189address ranges. The "device" aspect of `ZONE_DEVICE` relates to the fact 190that the page objects for these address ranges are never marked online, 191and that a reference must be taken against the device, not just the page 192to keep the memory pinned for active use. `ZONE_DEVICE`, via 193:c:func:`devm_memremap_pages`, performs just enough memory hotplug to 194turn on :c:func:`pfn_to_page`, :c:func:`page_to_pfn`, and 195:c:func:`get_user_pages` service for the given range of pfns. Since the 196page reference count never drops below 1 the page is never tracked as 197free memory and the page's `struct list_head lru` space is repurposed 198for back referencing to the host device / driver that mapped the memory. 199 200While `SPARSEMEM` presents memory as a collection of sections, 201optionally collected into memory blocks, `ZONE_DEVICE` users have a need 202for smaller granularity of populating the `mem_map`. Given that 203`ZONE_DEVICE` memory is never marked online it is subsequently never 204subject to its memory ranges being exposed through the sysfs memory 205hotplug api on memory block boundaries. The implementation relies on 206this lack of user-api constraint to allow sub-section sized memory 207ranges to be specified to :c:func:`arch_add_memory`, the top-half of 208memory hotplug. Sub-section support allows for 2MB as the cross-arch 209common alignment granularity for :c:func:`devm_memremap_pages`. 210 211The users of `ZONE_DEVICE` are: 212 213* pmem: Map platform persistent memory to be used as a direct-I/O target 214 via DAX mappings. 215 216* hmm: Extend `ZONE_DEVICE` with `->page_fault()` and `->page_free()` 217 event callbacks to allow a device-driver to coordinate memory management 218 events related to device-memory, typically GPU memory. See 219 Documentation/vm/hmm.rst. 220 221* p2pdma: Create `struct page` objects to allow peer devices in a 222 PCI/-E topology to coordinate direct-DMA operations between themselves, 223 i.e. bypass host memory. 224