思考:如何在PowerPC架构e500芯片实现low_memory的大小控制?

内存区域zone

三个内存区域zone,分别为ZONE_DMA,ZONE_NORMAL和ZONE_HIGHMEM,在e500上ZONE_NORMAL实际划分的内存为空,所以所有低端内存(low_memory)都划分到ZONE_DMA中;

内存区域的划分信息保存在max_zone_pfns中,其定义如下:

static unsigned long max_zone_pfns[MAX_NR_ZONES] = {[0 ... MAX_NR_ZONES - 1] = ~0UL
};

每个zone都有一个max_zone_pfn对应来限定内存页帧上限,同时作为更高内存区域内存页帧的下限。在paging_init函数中计算各个zone区域的划分信息:

/** paging_init() sets up the page tables - in fact we've already done this.*/
void __init paging_init(void)
{unsigned long long total_ram = memblock_phys_mem_size();phys_addr_t top_of_ram = memblock_end_of_DRAM();enum zone_type top_zone;#ifdef CONFIG_PPC32unsigned long v = __fix_to_virt(__end_of_fixed_addresses - 1);unsigned long end = __fix_to_virt(FIX_HOLE);for (; v < end; v += PAGE_SIZE)map_page(v, 0, 0); /* XXX gross */
#endif#ifdef CONFIG_HIGHMEMmap_page(PKMAP_BASE, 0, 0);    /* XXX gross */pkmap_page_table = virt_to_kpte(PKMAP_BASE);kmap_pte = virt_to_kpte(__fix_to_virt(FIX_KMAP_BEGIN));kmap_prot = PAGE_KERNEL;
#endif /* CONFIG_HIGHMEM */printk(KERN_DEBUG "Top of RAM: 0x%llx, Total RAM: 0x%llx\n",(unsigned long long)top_of_ram, total_ram);printk(KERN_DEBUG "Memory hole size: %ldMB\n",(long int)((top_of_ram - total_ram) >> 20));#ifdef CONFIG_HIGHMEMtop_zone = ZONE_HIGHMEM;limit_zone_pfn(ZONE_NORMAL, lowmem_end_addr >> PAGE_SHIFT);
#elsetop_zone = ZONE_NORMAL;
#endiflimit_zone_pfn(top_zone, top_of_ram >> PAGE_SHIFT);zone_limits_final = true;free_area_init_nodes(max_zone_pfns);mark_nonram_nosave();
}

首先看函数尾部,分别调用两次limit_zone_pfn对ZONE_NORMAL和ZONE_HIGHMEM页帧进行限制,这里需要注意的一点是因为没有对ZONE_DMA进行特殊处理,因此会导致ZONE_DMA占用所有低端内存,ZONE_NORMAL为空;

ZONE_HIGHMEM的设置用到了top_of_ram,为RAM的最高空间,通过memblock可以查询到,在内存节点的添加以及后面的一些运算过程中会设置物理内存的上限;

ZONE_NORMAL的设置用到了lowmem_end_addr即低端内存的末尾,其数值又下面计算过程决定:
在MMU_init中:

lowmem_end_addr = memstart_addr + total_lowmem;

其值直接依赖于total_lowmem,该计算过程进行了两次,分别在adjust_total_lowmem之前和之后,而在adjust_total_lowmem中对__max_low_memory进行了计算,从而将可能进一步限定total_lowmem的取值,那么可以看到total_lowmem(在可能被__max_low_memory覆盖之前)和__max_low_memory的最小值决定了lowmem_end_addr的值,并且此时将更小者赋值给了total_lowmem作为最新值;total_lowmem即为RAM的大小;
__max_low_memory通过下面过程取得:

1. 定义和初始化

#define CONFIG_LOWMEM_SIZE 0x30000000
#define MAX_LOW_MEM    CONFIG_LOWMEM_SIZE/* max amount of low RAM to map in */
unsigned long __max_low_memory = MAX_LOW_MEM;

其中CONFIG_LOWMEM_SIZE为内核.config中定义的大小;

2. 内核启动参数bootargs中vmalloc参数的影响

/** vmalloc=size forces the vmalloc area to be exactly 'size'* bytes. This can be used to increase (or decrease) the low* memory  area. Thus this can be also used to decrease (or increase)* low memory area.*/
static int __init early_vmalloc(char *arg)
{unsigned long vmalloc_reserve = memparse(arg, NULL);PRT("vmalloc_reserve = 0x%lx", vmalloc_reserve);if (vmalloc_reserve < SZ_16M) {vmalloc_reserve = SZ_16M;PRT("vmalloc area too small, limiting to %luMB\n",vmalloc_reserve >> 20);}if (vmalloc_reserve > VMALLOC_RESERVE_MAX) {vmalloc_reserve = VMALLOC_RESERVE_MAX;PRT("vmalloc area is too big, limiting to %luMB\n",vmalloc_reserve >> 20);}/* low memory aligned 16M*/PRT("__max_low_memory = 0x%lx", __max_low_memory);__max_low_memory = __pa(IOREMAP_TOP) - VMALLOC_OFFSET - vmalloc_reserve;__max_low_memory &= ~(SZ_16M - 1);PRT("__max_low_memory = 0x%lx", __max_low_memory);return 0;
}
early_param("vmalloc", early_vmalloc);

early_vmalloc函数根据vmalloc参数解析出vmalloc_reserve的大小,大小有一定的限制,指定最小16M,最大为1G的内核虚拟地址空间除去一个VMALLOC_OFFSET和64M,64M应该是作为系统低端保障内存的空间大小;
接下来直接算出__max_low_memory的大小,并进行16M对其:

    __max_low_memory = __pa(IOREMAP_TOP) - VMALLOC_OFFSET - vmalloc_reserve;__max_low_memory &= ~(SZ_16M - 1);

3. adjust_total_lowmem进行调整,这是CONFIG_FSL_BOOKE架构特性特有

取__max_low_memory和total_lowmem中较小者,然后通过map_mem_in_cams接口进行映射建立tlb条目,将可以映射的最大RAM作为最终结果重新赋值给__max_low_memory;可以看到如果tlb条目可映射的RAM数量较小,则__max_low_memory会进一步在此被修改变小

按照上面1/2/3条逐步进行限制,如果bootargs未配置vmalloc参数则无第2条执行;

回到最开始的部分,通过__max_low_memory参数最终的值和total_lowmem,在MMU_init中确定total_lowmem的最终值,从而决定了lowmem_end_addr的大小,相对total_lowmem偏移memstart_addr,在此偏移为0;进而决定了ZONE_DMA和ZONE_NORMAL的内存布局

Linux内存管理之vmalloc与low_memory相关推荐

  1. Linux 内存管理之vmalloc

    走进vmalloc 根据前面的系列文章,我们知道了buddy system是基于页框分配器,kmalloc是基于slab分配器,而且这些分配的地址都是物理内存连续的.但是随着碎片化的积累,连续物理内存 ...

  2. Linux内存管理和分析vmalloc使用的地址范围

    From: http://www.cnblogs.com/dubingsky/archive/2010/04/20/1716158.html Vmalloc可以获得的地址在VMALLOC_START到 ...

  3. 万字整理,图解Linux内存管理所有知识点

    Linux的内存管理可谓是学好Linux的必经之路,也是Linux的关键知识点,有人说打通了内存管理的知识,也就打通了Linux的任督二脉,这一点不夸张.有人问网上有很多Linux内存管理的内容,为什 ...

  4. Linux内存管理:知识点总结(ARM64)

    https://mp.weixin.qq.com/s/7zFrBuJUK9JMQP4TmymGjA 目录 Linux内存管理之CPU访问内存的过程 虚拟地址转换为物理地址的本质 Linux内存初始化 ...

  5. 万字整理,肝翻Linux内存管理所有知识点

    Linux的内存管理可谓是学好Linux的必经之路,也是Linux的关键知识点,有人说打通了内存管理的知识,也就打通了Linux的任督二脉,这一点不夸张.有人问网上有很多Linux内存管理的内容,为什 ...

  6. 万字整理,肝翻Linux内存管理所有知识点【Linux内核开发人员必学】都是精髓

    Linux的内存管理可谓是学好Linux的必经之路,也是Linux的关键知识点,有人说打通了内存管理的知识,也就打通了Linux的任督二脉,这一点不夸张.有人问网上有很多Linux内存管理的内容,为什 ...

  7. Linux内存管理之kmalloc、malloc、vmalloc的区别

    Linux内存管理之kmalloc.malloc.vmalloc的区别 kmalloc和vmalloc分配的是内核空间的内存,malloc分配的是用户空间的内存. kmalloc保证分配的内存在物理上 ...

  8. Windows内存管理和linux内存管理

    windows内存管理 windows 内存管理方式主要分为:页式管理,段式管理,段页式管理. 页式管理的基本原理是将各进程的虚拟空间划分为若干个长度相等的页:页式管理把内存空间按照页的大小划分成片或 ...

  9. 万字长文,别再说你不懂Linux内存管理了(合辑),30 张图给你安排的明明白白...

    之前写了两篇详细分析 Linux 内存管理的文章,读者好评如潮.但由于是分开两篇来写,而这两篇内容其实是有很强关联的,有读者反馈没有看到另一篇读起来不够不连贯,为方便阅读这次特意把两篇整合在一起,看这 ...

  10. 别再说你不懂Linux内存管理了,10张图给你安排的明明白白!

    来自:后端技术学堂 过去的一周有点魔幻,有印象的有三个新闻:天猫总裁绯闻事件,蘑菇街裁员,不可能打工的周某也放出来了.三件事,两件和互联网行业相关,好像外面的世界很是精彩啊!吃瓜归吃瓜,学习还是不能落 ...

最新文章

  1. PHP Shell生成工具Weevely
  2. 关于搭建haddoop分布式系统的全部过程复习
  3. 数据中心机房供电需求有哪些?供配电系统如何布置??
  4. jquery设置表单元素只读_jquery设置元素readonly与disabled属性
  5. lingo变量无限制版本_【运筹学】用Lingo求解运输问题,兼谈Lingo语法
  6. 判断用户是否存在再进行新增_基于tableau从商业分析模型角度对业务数据进行多维度分析--【商业分析类】...
  7. all any 或 此运算符后面必须跟_用 ANY、SOME 或 ALL 修改的比较运算符
  8. OJ1079: a+b(多实例测试2)(C语言数组实现)
  9. 前端实习生笔试_前端实习生面试题——HTML
  10. Python 推导式(列表推导式,字典推导式,集合推导式)
  11. jQuery 学习笔记 选择元素
  12. Vapnik-Chervonenkis
  13. WPS中word转pdf文件时给pdf文件增加目录
  14. 一张图搞懂什么是M0、M1 、M2
  15. Mac中搜狗输入法在各应用中默认中英文状态
  16. ply补全为立方体_PLY格式文件具体解释
  17. 100集华为HCIE安全培训视频教材整理 | Agile Controller终端安全管理特性(五)
  18. 【Java】MacOS Eclipse使用JOL观察对象布局(详解)
  19. 初识Python之刨根问底
  20. 蓝牙4.0 BLE 广播包解析

热门文章

  1. 【LeetCode】242. Valid Anagram
  2. 如何落地用户画像分析?
  3. 区块链软件公司:供应链高本钱的运用区块链技能是否值得?
  4. 爬取猎聘大数据岗位相关信息--Python
  5. laravel中修改默认时区
  6. spring security免登录动态配置方案2
  7. MVC渲染文章内容的html标签转义
  8. 应用HTK搭建语音拨号系统2:创建单音素HMM模型
  9. 如何让内容页调用样式表?
  10. Drools workbench kie-server部署和简单使用(全流程