aboutsummaryrefslogtreecommitdiffstats
path: root/Documentation/vm/memory-model.rst
diff options
context:
space:
mode:
Diffstat (limited to 'Documentation/vm/memory-model.rst')
-rw-r--r--Documentation/vm/memory-model.rst219
1 files changed, 0 insertions, 219 deletions
diff --git a/Documentation/vm/memory-model.rst b/Documentation/vm/memory-model.rst
deleted file mode 100644
index 9daadf9faba1..000000000000
--- a/Documentation/vm/memory-model.rst
+++ /dev/null
@@ -1,219 +0,0 @@
-.. SPDX-License-Identifier: GPL-2.0
-
-.. _physical_memory_model:
-
-=====================
-Physical Memory Model
-=====================
-
-Physical memory in a system may be addressed in different ways. The
-simplest case is when the physical memory starts at address 0 and
-spans a contiguous range up to the maximal address. It could be,
-however, that this range contains small holes that are not accessible
-for the CPU. Then there could be several contiguous ranges at
-completely distinct addresses. And, don't forget about NUMA, where
-different memory banks are attached to different CPUs.
-
-Linux abstracts this diversity using one of the three memory models:
-FLATMEM, DISCONTIGMEM and SPARSEMEM. Each architecture defines what
-memory models it supports, what the default memory model is and
-whether it is possible to manually override that default.
-
-.. note::
- At time of this writing, DISCONTIGMEM is considered deprecated,
- although it is still in use by several architectures.
-
-All the memory models track the status of physical page frames using
-struct page arranged in one or more arrays.
-
-Regardless of the selected memory model, there exists one-to-one
-mapping between the physical page frame number (PFN) and the
-corresponding `struct page`.
-
-Each memory model defines :c:func:`pfn_to_page` and :c:func:`page_to_pfn`
-helpers that allow the conversion from PFN to `struct page` and vice
-versa.
-
-FLATMEM
-=======
-
-The simplest memory model is FLATMEM. This model is suitable for
-non-NUMA systems with contiguous, or mostly contiguous, physical
-memory.
-
-In the FLATMEM memory model, there is a global `mem_map` array that
-maps the entire physical memory. For most architectures, the holes
-have entries in the `mem_map` array. The `struct page` objects
-corresponding to the holes are never fully initialized.
-
-To allocate the `mem_map` array, architecture specific setup code should
-call :c:func:`free_area_init` function. Yet, the mappings array is not
-usable until the call to :c:func:`memblock_free_all` that hands all the
-memory to the page allocator.
-
-If an architecture enables `CONFIG_ARCH_HAS_HOLES_MEMORYMODEL` option,
-it may free parts of the `mem_map` array that do not cover the
-actual physical pages. In such case, the architecture specific
-:c:func:`pfn_valid` implementation should take the holes in the
-`mem_map` into account.
-
-With FLATMEM, the conversion between a PFN and the `struct page` is
-straightforward: `PFN - ARCH_PFN_OFFSET` is an index to the
-`mem_map` array.
-
-The `ARCH_PFN_OFFSET` defines the first page frame number for
-systems with physical memory starting at address different from 0.
-
-DISCONTIGMEM
-============
-
-The DISCONTIGMEM model treats the physical memory as a collection of
-`nodes` similarly to how Linux NUMA support does. For each node Linux
-constructs an independent memory management subsystem represented by
-`struct pglist_data` (or `pg_data_t` for short). Among other
-things, `pg_data_t` holds the `node_mem_map` array that maps
-physical pages belonging to that node. The `node_start_pfn` field of
-`pg_data_t` is the number of the first page frame belonging to that
-node.
-
-The architecture setup code should call :c:func:`free_area_init_node` for
-each node in the system to initialize the `pg_data_t` object and its
-`node_mem_map`.
-
-Every `node_mem_map` behaves exactly as FLATMEM's `mem_map` -
-every physical page frame in a node has a `struct page` entry in the
-`node_mem_map` array. When DISCONTIGMEM is enabled, a portion of the
-`flags` field of the `struct page` encodes the node number of the
-node hosting that page.
-
-The conversion between a PFN and the `struct page` in the
-DISCONTIGMEM model became slightly more complex as it has to determine
-which node hosts the physical page and which `pg_data_t` object
-holds the `struct page`.
-
-Architectures that support DISCONTIGMEM provide :c:func:`pfn_to_nid`
-to convert PFN to the node number. The opposite conversion helper
-:c:func:`page_to_nid` is generic as it uses the node number encoded in
-page->flags.
-
-Once the node number is known, the PFN can be used to index
-appropriate `node_mem_map` array to access the `struct page` and
-the offset of the `struct page` from the `node_mem_map` plus
-`node_start_pfn` is the PFN of that page.
-
-SPARSEMEM
-=========
-
-SPARSEMEM is the most versatile memory model available in Linux and it
-is the only memory model that supports several advanced features such
-as hot-plug and hot-remove of the physical memory, alternative memory
-maps for non-volatile memory devices and deferred initialization of
-the memory map for larger systems.
-
-The SPARSEMEM model presents the physical memory as a collection of
-sections. A section is represented with struct mem_section
-that contains `section_mem_map` that is, logically, a pointer to an
-array of struct pages. However, it is stored with some other magic
-that aids the sections management. The section size and maximal number
-of section is specified using `SECTION_SIZE_BITS` and
-`MAX_PHYSMEM_BITS` constants defined by each architecture that
-supports SPARSEMEM. While `MAX_PHYSMEM_BITS` is an actual width of a
-physical address that an architecture supports, the
-`SECTION_SIZE_BITS` is an arbitrary value.
-
-The maximal number of sections is denoted `NR_MEM_SECTIONS` and
-defined as
-
-.. math::
-
- NR\_MEM\_SECTIONS = 2 ^ {(MAX\_PHYSMEM\_BITS - SECTION\_SIZE\_BITS)}
-
-The `mem_section` objects are arranged in a two-dimensional array
-called `mem_sections`. The size and placement of this array depend
-on `CONFIG_SPARSEMEM_EXTREME` and the maximal possible number of
-sections:
-
-* When `CONFIG_SPARSEMEM_EXTREME` is disabled, the `mem_sections`
- array is static and has `NR_MEM_SECTIONS` rows. Each row holds a
- single `mem_section` object.
-* When `CONFIG_SPARSEMEM_EXTREME` is enabled, the `mem_sections`
- array is dynamically allocated. Each row contains PAGE_SIZE worth of
- `mem_section` objects and the number of rows is calculated to fit
- all the memory sections.
-
-The architecture setup code should call sparse_init() to
-initialize the memory sections and the memory maps.
-
-With SPARSEMEM there are two possible ways to convert a PFN to the
-corresponding `struct page` - a "classic sparse" and "sparse
-vmemmap". The selection is made at build time and it is determined by
-the value of `CONFIG_SPARSEMEM_VMEMMAP`.
-
-The classic sparse encodes the section number of a page in page->flags
-and uses high bits of a PFN to access the section that maps that page
-frame. Inside a section, the PFN is the index to the array of pages.
-
-The sparse vmemmap uses a virtually mapped memory map to optimize
-pfn_to_page and page_to_pfn operations. There is a global `struct
-page *vmemmap` pointer that points to a virtually contiguous array of
-`struct page` objects. A PFN is an index to that array and the
-offset of the `struct page` from `vmemmap` is the PFN of that
-page.
-
-To use vmemmap, an architecture has to reserve a range of virtual
-addresses that will map the physical pages containing the memory
-map and make sure that `vmemmap` points to that range. In addition,
-the architecture should implement :c:func:`vmemmap_populate` method
-that will allocate the physical memory and create page tables for the
-virtual memory map. If an architecture does not have any special
-requirements for the vmemmap mappings, it can use default
-:c:func:`vmemmap_populate_basepages` provided by the generic memory
-management.
-
-The virtually mapped memory map allows storing `struct page` objects
-for persistent memory devices in pre-allocated storage on those
-devices. This storage is represented with struct vmem_altmap
-that is eventually passed to vmemmap_populate() through a long chain
-of function calls. The vmemmap_populate() implementation may use the
-`vmem_altmap` along with :c:func:`vmemmap_alloc_block_buf` helper to
-allocate memory map on the persistent memory device.
-
-ZONE_DEVICE
-===========
-The `ZONE_DEVICE` facility builds upon `SPARSEMEM_VMEMMAP` to offer
-`struct page` `mem_map` services for device driver identified physical
-address ranges. The "device" aspect of `ZONE_DEVICE` relates to the fact
-that the page objects for these address ranges are never marked online,
-and that a reference must be taken against the device, not just the page
-to keep the memory pinned for active use. `ZONE_DEVICE`, via
-:c:func:`devm_memremap_pages`, performs just enough memory hotplug to
-turn on :c:func:`pfn_to_page`, :c:func:`page_to_pfn`, and
-:c:func:`get_user_pages` service for the given range of pfns. Since the
-page reference count never drops below 1 the page is never tracked as
-free memory and the page's `struct list_head lru` space is repurposed
-for back referencing to the host device / driver that mapped the memory.
-
-While `SPARSEMEM` presents memory as a collection of sections,
-optionally collected into memory blocks, `ZONE_DEVICE` users have a need
-for smaller granularity of populating the `mem_map`. Given that
-`ZONE_DEVICE` memory is never marked online it is subsequently never
-subject to its memory ranges being exposed through the sysfs memory
-hotplug api on memory block boundaries. The implementation relies on
-this lack of user-api constraint to allow sub-section sized memory
-ranges to be specified to :c:func:`arch_add_memory`, the top-half of
-memory hotplug. Sub-section support allows for 2MB as the cross-arch
-common alignment granularity for :c:func:`devm_memremap_pages`.
-
-The users of `ZONE_DEVICE` are:
-
-* pmem: Map platform persistent memory to be used as a direct-I/O target
- via DAX mappings.
-
-* hmm: Extend `ZONE_DEVICE` with `->page_fault()` and `->page_free()`
- event callbacks to allow a device-driver to coordinate memory management
- events related to device-memory, typically GPU memory. See
- Documentation/vm/hmm.rst.
-
-* p2pdma: Create `struct page` objects to allow peer devices in a
- PCI/-E topology to coordinate direct-DMA operations between themselves,
- i.e. bypass host memory.