1. 添加zone_type枚举类型
//路径: include/linux/Mmzone.h
enum zone_type {
#ifdef CONFIG_ZONE_DMA
/*
* ZONE_DMA is used when there are devices that are not able
* to do DMA to all of addressable memory (ZONE_NORMAL). Then we
* carve out the portion of memory that is needed for these devices.
* The range is arch specific.
*
* Some examples
*
* Architecture Limit
* ---------------------------
* parisc, ia64, sparc <4G
* s390 <2G
* arm Various
* alpha Unlimited or 0-16MB.
*
* i386, x86_64 and multiple other arches
* <16M.
*/
ZONE_DMA,
#endif
#ifdef CONFIG_ZONE_DMA32
/*
* x86_64 needs two ZONE_DMAs because it supports devices that are
* only able to do DMA to the lower 16M but also 32 bit devices that
* can only do DMA areas below 4G.
*/
ZONE_DMA32,
#endif
/*
* 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,
ZONE_MEMSWAP,
#ifdef CONFIG_HIGHMEM
/*
* A memory area that is only addressable by the kernel through
* mapping portions into its own address space. This is for example
* used by i386 to allow the kernel to address the memory beyond
* 900MB. The kernel will set up special mappings (page
* table entries on i386) for each page that the kernel needs to
* access.
*/
ZONE_HIGHMEM,
#endif
ZONE_MOVABLE,
__MAX_NR_ZONES
};
ZONE_MEMSWAP,
即为添加zone对应的枚举类型
2. 修改内存初始化代码
//路径 arch/arm/mm/Init.c
static void __init arm_bootmem_free(unsigned long min, unsigned long max_low,
unsigned long max_high)
添加代码
unsigned long mem_swap_size = 1UL << 15;
unsigned long normal_start = min, normal_end = max_low - mem_swap_size;
zone_size[0] = normal_end - normal_start;
zone_size[ZONE_MEMSWAP] = mem_swap_size;
#ifdef CONFIG_HIGHMEM
zone_size[ZONE_HIGHMEM] = max_high - max_low;
#endif
zhole_size[ZONE_MEMSWAP] = 0UL;
for_each_memblock(memory, reg) {
unsigned long start = memblock_region_memory_base_pfn(reg);
unsigned long end = memblock_region_memory_end_pfn(reg);
if (start < normal_end) {
unsigned long low_end = min(end, normal_end);
zhole_size[0] -= low_end - start;
}
#ifdef CONFIG_HIGHMEM
if (end > max_low) {
unsigned long high_start = max(start, max_low);
zhole_size[ZONE_HIGHMEM] -= end - high_start;
}
#endif
3. 修改内存分配代码
//路径:mm/page_alloc.c
get_page_from_freelist(gfp_t gfp_mask, nodemask_t *nodemask, unsigned int order,
struct zonelist *zonelist, int high_zoneidx, int alloc_flags,
struct zone *preferred_zone, int migratetype)
for_each_zone_zonelist_nodemask(zone, z, zonelist,
high_zoneidx, nodemask) {
...
if (zone_idx(zone) == ZONE_MEMSWAP)
continue;
...
}
同样是该路径的该函数:
static char * const zone_names[MAX_NR_ZONES] = {
#ifdef CONFIG_ZONE_DMA
"DMA",
#endif
#ifdef CONFIG_ZONE_DMA32
"DMA32",
#endif
"Normal",
"MemSwap",
#ifdef CONFIG_HIGHMEM
"HighMem",
#endif
"Movable",
};