/* * The pg_data_t structure is used in machines with CONFIG_DISCONTIGMEM * (mostly NUMA machines?) to denote a higher-level memory zone than the * zone denotes. * * On NUMA machines, each NUMA node would have a pg_data_t to describe * it's memory layout. * * Memory statistics and page replacement data structures are maintained on a * per-zone basis. */ typedefstructpglist_data { structzonenode_zones[MAX_NR_ZONES]; structzonelistnode_zonelists[MAX_ZONELISTS]; int nr_zones; #ifdef CONFIG_FLAT_NODE_MEM_MAP /* means !SPARSEMEM */ structpage *node_mem_map; #ifdef CONFIG_MEMCG structpage_cgroup *node_page_cgroup; #endif ... }pg_data_t;
/* * Normal addressable memory is in ZONE_NORMAL. DMA operations can be * performed on pages in ZONE_NORMAL if the DMA devices support * transfers to all addressable memory. */ ZONE_NORMAL,
config DISCONTIGMEM_MANUAL bool "Discontiguous Memory" depends on ARCH_DISCONTIGMEM_ENABLE help This option provides enhanced support for discontiguous memory systems, over FLATMEM. These systems have holes in their physical address spaces, and this option provides more efficient handling of these holes. However, the vast majority of hardware has quite flat address spaces, and can have degraded performance from the extra overhead that this option imposes.
Many NUMA configurations will have this as the only option.
If unsure, choose "Flat Memory" over this option.
config SPARSEMEM_MANUAL bool "Sparse Memory" depends on ARCH_SPARSEMEM_ENABLE help This will be the only option for some systems, including memory hotplug systems. This is normal.
For many other systems, this will be an alternative to "Discontiguous Memory". This option provides some potential performance benefits, along with decreased code complexity, but it is newer, and more experimental.
If unsure, choose "Discontiguous Memory" or "Flat Memory" over this option.
# # Both the NUMA code and DISCONTIGMEM use arrays of pg_data_t's # to represent different areas of memory. This variable allows # those dependencies to exist individually. # config NEED_MULTIPLE_NODES def_bool y depends on DISCONTIGMEM || NUMA
不连续,地址空间被分成多个node,这个node就是之前的bank了。
so, mem_map应该给flat用,从代码看sparse也能用?应该不是。mem_map就是node 0的node_mem_map.
代码如下:
staticvoid __init_refok alloc_node_mem_map(struct pglist_data *pgdat) { ... #ifndef CONFIG_NEED_MULTIPLE_NODES /* * With no DISCONTIG, the global mem_map is just set as node 0's */ if (pgdat == NODE_DATA(0)) { mem_map = NODE_DATA(0)->node_mem_map; ...
#ifdef CONFIG_SPARSEMEM structmem_section { /* * This is, logically, a pointer to an array of struct * pages. However, it is stored with some other magic. * (see sparse.c::sparse_init_one_section()) * * Additionally during early boot we encode node id of * the location of the section here to guide allocation. * (see sparse.c::memory_present()) * * Making it a UL at least makes someone do a cast * before using it wrong. */ unsignedlong section_mem_map;