OK6410A 开发板 (八) 34 linux-5.11 OK6410A 内存管理第二阶段

发布者:雅致书香最新更新时间:2022-09-07 来源: csdn关键字:OK6410A  开发板  11  内存管理 手机看文章 扫描二维码
随时随地手机看文章

B __turn_mmu_on符号 - setup_arch->paging_init->bootmem_init->memblock_allow_resize返回

----此时memblock初始化完成,开启了基于虚拟内时代的 memblock内存管理器时代


流程

__turn_mmu_on

mcr p15, 0, r0, c1, c0, 0       @ write control reg // 内存管理相关1

// 上句执行之后,mmu开启

ret r3 // 调用到 __mmap_switched


__mmap_switched

adr r4, __mmap_switched_data // 内存管理相关2

...

ldmia   r4!, {r0, r1, sp}

...

bl  __memset // 内存管理相关3

ldmia   r4, {r0, r1, r2, r3}

...

b   start_kernel // 内存管理相关4



start_kernel->setup_arch

setup_processor // 内存管理相关5

setup_machine_tags

// 根据 board id 匹配 mdesc

// parse 所有的 atags

// 对于 MEM, 调用 parse_tag_mem32 初始化 memblock.memory.regions // 内存管理相关6


early_fixmap_init

// 建立了一个映射的框架,具体的物理地址和虚拟地址的映射没有去填充 // 内存管理相关7

early_ioremap_init // 内存管理相关8

// 为 parse_early_param 做准备

// 建立 slot_vir

// 没有消费者

// 在 OK6410a-linux-5.11 中 没有 early_ioremap_init

parse_early_param

// parse ...

// earlycon

// 没有利用 early_ioremap_init 创建的 slot_vir

// 在 early_fixmap_init 创建的框架中 填充映射

early_mm_init // 内存管理相关9

// [10:14:27]Memory policy: Data cache writeback

setup_dma_zone // 内存管理相关10

adjust_lowmem_bounds // 内存管理相关11

// 调整 memblock.current_limit 的值

arm_memblock_init // 内存管理相关12

// 初始化 memblock.reserved.regions

adjust_lowmem_bounds // 内存管理相关13

// 调整 memblock.current_limit 的值

early_ioremap_reset // 内存管理相关14

early_ioremap_shutdown

after_paging_init = 1;

paging_init

prepare_page_table // 内存管理相关15

// 在 页表地址 处 写入 0

map_lowmem // 内存管理相关16

// 映射3组

memblock_set_current_limit // 内存管理相关17

dma_contiguous_remap // 内存管理相关18

early_fixmap_shutdown // 内存管理相关19

pmd_clear(fixmap_pmd(va));

devicemaps_init // 内存管理相关20

// 映射 14组

kmap_init // 内存管理相关21

tcm_init // 内存管理相关22

// 映射 2组

top_pmd = pmd_off_k(0xffff0000);

zero_page = early_alloc(PAGE_SIZE); // 内存管理相关23

// 第一次使用 memblock 内存管理器的 内存申请API

bootmem_init

memblock_allow_resize // 内存管理相关24

// 到此为止,还没出现 struct page.


memblock 时代 物理内存和虚拟内存是怎么管控的

1. 页表(物理地址到虚拟地址的映射)

// 对应下面的 early map 类 和 map 类

2. 按区域 注册物理内存到 memblock 内存管理器中的 memblock 变量

// 对应下面的 memblock 类

buddy 时代 物理内存和虚拟内存是怎么管控的

1. 页表(物理地址到虚拟地址的映射)

2. 按物理页 注册物理内存到 buddy 内存管理器中的 struct page


memblock 切换 到 buddy , 只需要做

1. 不需要做页表的映射(因为memblock时代,已经做完了,buddy直接用就行了)

2. 将 注册到memblock内存管理器memblock变量中 的 物理页 注册到 buddy内存管理器中的struct page


内存管理相关1

__turn_mmu_on 写 cp15 寄存器

write control reg

// 开MMU

// 此语句一开始执行,就代表MMU开启了

// 下一句就是 MMU开启后的访问内存流程


内存管理相关2

ldmia   r4!, {r0, r1, sp}

将 __bss_start 放入 r0 , 该符号为连接符号,在 System.map 查到地址

将 __bss_stop  放入 r1

为 .bss 段 清0 做准备

将 init_thread_union + THREAD_START_SP 放入 sp

设置 栈(.stack)


内存管理相关3

bl  __memset

清0 .bss 段


内存管理相关4

这里 与 内存管理无关

只是 解释 一下 在这个 命令运行的时候, 内存 的布局

看的出来,所有的 内存布局 都在 Image二进制文件 里面

.code 是 Image 里面的 _stext -  _etext

.rodata 是 Image 里面的 __start_rodata -  __end_rodata

.data 是 Image 里面的 _sdata -  _edata

.bss 是 Image 里面的 __bss_start -  __bss_stop

.stack  是 Image 里面的 init_task + 8K - 8 的位置

// arch/arm/include/asm/thread_info.h

// https://www.zhihu.com/question/24811279

Image 虚拟地址 : 0xC0008000 - 0xC088E547 8.6MB

_stext _etext

.code : c0100000 - c0600000

__start_rodata __end_rodata

.rodata : c0600000 - c06b6000

_sdata _edata

.data c0800000 - c088e548

__bss_start __bss_stop

.bss : c088e548 - c08c413c

init_thread_union init_thread_union + THREAD_START_SP

.stack : C0800000 - C0801FF8

.heap : null


内存管理相关5

[10:14:27]CPU: ARMv6-compatible processor [410fb766] revision 6 (ARMv7), cr=00c5387d

[10:14:27]CPU: PIPT / VIPT nonaliasing data cache, VIPT nonaliasing instruction cache


setup_processor

struct proc_info_list *list = lookup_processor(midr); // __v6_proc_info

cpu_cache = *list->cache; // v6_cache_fns


之后的 内存管理相关分类

memblock 类

setup_machine_tags

parse_tag_mem32 

adjust_lowmem_bounds

arm_memblock_init

memblock_allow_resize

zero_page = early_alloc(PAGE_SIZE);


early map 类 (为 parse_early_param 做准备的映射)

early_fixmap_init

// 查看提交记录 a5f4c561b3b19a9bc43a81da6382b0098ebbc1fb

early_ioremap_init

parse_early_param

early_ioremap_reset

early_fixmap_shutdown

// 查看 提交记录 a5f4c561b3b19a9bc43a81da6382b0098ebbc1fb


map 类(为 linux 运行时 做准备的映射) // 做页表初始化 , 不是 做page初始化

early_mm_init

prepare_page_table

map_lowmem

dma_contiguous_remap

devicemaps_init

kmap_init

tcm_init


memblock 类

填充 memblock 全局变量  的各个成员

memblock_add 填充 memblock.memory

memblock_reserve 填充 memblock.reserved


setup_machine_tags

parse_tag_mem32 调用 memblock_add 填充 memblock.memory


adjust_lowmem_bounds

调整 memblock.current_limit 的值


根据 什么调整  TODO 


arm_memblock_init

调用 memblock_reserve 填充 memblock.reserved

填充完毕, memblock.reserved 中有

1. kernel

2. 页表(50004000-50008000)

3. dma/cma 等


memblock_allow_resize

memblock_can_resize = 1;

// 


zero_page = early_alloc(PAGE_SIZE);

第一次使用 memblock 内存管理器的 内存申请API


early map 类

内存管理相关7 early_fixmap_init

early_fixmap_init 

pmd = fixmap_pmd(FIXADDR_TOP); 

// FIXADDR_TOP : FFEF F000

// pmd : c0007ff8

pmd_populate_kernel(&init_mm, pmd, bm_pte);

// 以 pmd    变量的值 为 addr

// 以 bm_pte  变量的值 为 value

// 在 addr 处 写入 value


// 其实写了 两个 pmd

// 一个是  addr : c0007ff8 , value : 50728811

// 一个是  addr : c0007ffc , value : 50728c11

pte_offset_fixmap = pte_offset_early_fixmap;

// &bm_pte[pte_index(addr)];


early_fixmap_init  的过程是建立 一级页表

// 这样子 二级页表的位置是确定的,在 bm_pte 地址开始的 1024字节,256项

// 消费者 通过 填充二级页表来做映射

// 二级页表的内容根据 做的映射关系而变化

// 1.二级页表的地址(pte)是固定的,从 c072 8000 - c072 9ffc

// 2.映射关系中有一个是固定的,那就是 虚拟地址(在 0xffeff000范围附近) , 虚拟地址通过 __fix_to_virt 获得

// 3.消费者必须在 enum fixed_addresses 结构体中.  

// 4.消费者同用 同一个 一级页表 (add : c0007ff8)

// 5.此时的消费者创建的映射关系是临时性的,消费者创建的映射关系会被销毁掉

// 6.对应 enum fixed_addresses 结构体 中的 temporary

c0700000 T __init_begin

c0728000 t bm_pte // 1024 字节

c0729000 T v6_cache_fns

c0800000 D __init_end



 345 static pte_t bm_pte[PTRS_PER_PTE + PTE_HWTABLE_PTRS]                             

 346     __aligned(PTE_HWTABLE_OFF + PTE_HWTABLE_SIZE) __initdata;

// PTRS_PER_PTE  : 512

// PTE_HWTABLE_PTRS : 512


内存管理相关9 parse_early_param

early_param("earlycon", param_setup_earlycon);


param_setup_earlycon

setup_earlycon

register_earlycon

// mapbase:7f005000

port->membase = earlycon_map(port->mapbase, 64); // membase:ffeff000

set_fixmap_io(FIX_EARLYCON_MEM_BASE, paddr & PAGE_MASK); 

__set_fixmap

pte_t *pte = pte_offset_fixmap(pmd_off_k(vaddr), vaddr);

set_pte_at(NULL, vaddr, pte, pfn_pte(phys >> PAGE_SHIFT, prot));

base = (void __iomem *)__fix_to_virt(FIX_EARLYCON_MEM_BASE);

base += paddr & ~PAGE_MASK;

// addr of pte: c07283fc

// value of pte: 7f005653 


内存管理相关19 early_fixmap_shutdown

early_fixmap_shutdown

unsigned long va = fix_to_virt(__end_of_permanent_fixed_addresses - 1); // va = ffeff000

pmd_clear(fixmap_pmd(va)); 

// 将 一级页表 c0007ff8 和 c0007ffc 中的内容清空

// 之前通过 一级页表 访问的 二级页表 不能访问了

// 即之前通过 early_fixmap 建立的 映射(例如earlycon中 uart 的映射),不能用了


// 如果 0 - __end_of_permanent_fixed_addresses(消费者) 还有映射关系在建立(*pte不为0)

// map.pfn:7f005,map.virtual:ffeff000,map.length:1000,map.type:0

// 标识了 物理地址 7f005 000 - 7f005 000 +1000

// 这次如果 不会成真


// early_fixmap_shutdown 返回之后,devicemaps_init 会 填充一个page

// map.pfn:7f005,map.virtual:f7005000,map.length:1000,map.type:0

// 标识了 物理地址 7f005 000 - 7f005 000 +1000


map 类

其实是调用 create_mapping 在 0x50004000 - 0x50008000 写入了 pgd 和 pte


create_mapping 的参数 md 的类型 struct map_desc  中的成员

virtual : 虚拟地址

pfn : 物理地址 去掉 低12位

length  : 长度

type : 映射类型(该值被写入页表描述符/页目录表描述符)



以下面的例子为例

md->virtual:c0000000

md->pfn:50000

md->length:100000

md->type:a

此次创建的映射 为 

虚拟地址 c0000000 - c0000000+100000

物理地址 50000000 - 50000000+100000

此次映射的pte 范围在 0xc0004000-0xc000741f

page table entry : 页表的地址


early_mm_init

pte 中的 值叫做 页表描述符


页表描述符 

由 物理地址 7f005xxx 中的 7f005

其他控制位 ,例如 653

构成

构成为:7f005653

而这些控制位,是 根据 不同的控制需求 设置的, 这些控制位的组合 在 linux 看来,有17种 

// 定义在 arch/arm/include/asm/mach/map.h 和 arch/arm/include/asm/io.h 中

// 由 MT_ 开头

// 初始化 后 放在 全局变量 mem_types 中


而 early_mm_init 就是 初始化 mem_types  的过程


prepare_page_table

清0 0xc0004000-0xc000741f

之后 做映射关系的话,pte 就从 这个范围 取


map_lowmem

建立 物理地址 50000 000 - 50100 000 到 虚拟地址 c0000 000 - c0100 000

建立 物理地址 50100 000 - 50800 000 到 虚拟地址 c0100 000 - c0800 000

建立 物理地址 50800 000 - 60000 000 到 虚拟地址 c0800 000 - d0000 000


dma_contiguous_remap

null

因为 dma_mmu_remap_num 等于 0 , 所以什么都不做


devicemaps_init

建立 物理地址 50000 000 - 50200 000 到 虚拟地址 ff800 000 - ffa00 000

建立 物理地址 5fffe 000 - 5ffff 000 到 虚拟地址 ffff0 000 - ffff1 000

建立 物理地址 5ffff 000 - 60000 000 到 虚拟地址 ffff1 000 - ffff2 000


以下建立了 11 个 设备物理地址的映射 

// map.pfn:7e00f,map.virtual:f6100000,map.length:1000,map.type:0 // S3C64XX_PA_SYSCON

// map.pfn:70000,map.virtual:f6200000,map.length:1000,map.type:0 // S3C64XX_PA_SROM

// map.pfn:7f005,map.virtual:f7005000,map.length:1000,map.type:0 // S3C_PA_UART

// map.pfn:71200,map.virtual:f6000000,map.length:4000,map.type:0 // S3C64XX_PA_VIC0

// map.pfn:71300,map.virtual:f6010000,map.length:4000,map.type:0 // S3C64XX_PA_VIC1

// map.pfn:7f006,map.virtual:f6300000,map.length:4000,map.type:0 // S3C_PA_TIMER

// map.pfn:7f008,map.virtual:f6500000,map.length:1000,map.type:0 // S3C64XX_PA_GPIO

// map.pfn:74108,map.virtual:f6600000,map.length:1000,map.type:0 // S3C64XX_PA_MODEM

// map.pfn:7e004,map.virtual:f6400000,map.length:1000,map.type:0 // S3C64XX_PA_WATCHDOG

// map.pfn:7c100,map.virtual:f6700000,map.length:0400,map.type:0 // S3C64XX_PA_USB_HSPHY

// map.pfn:77100,map.virtual:f7100000,map.length:4000,map.type:0 // S3C_PA_FB


kmap_init

做 fixmap 映射

early_pte_alloc(pmd_off_k(FIXADDR_START), FIXADDR_START, _PAGE_KERNEL_TABLE); // c0007ff0 , ffc80000 , 0x11

arm_pte_alloc(pmd, addr, prot, early_alloc); // c0007ff0,ffc80000,0x11

if (pmd_none(*pmd)){ // c0007ff0 为空

pte_t *pte = alloc(PTE_HWTABLE_OFF + PTE_HWTABLE_SIZE);

// 申请了 pte , 其实地址在 cfff7000

// 大小为 1024 * sizeof(pte)

[1] [2]
关键字:OK6410A  开发板  11  内存管理 引用地址:OK6410A 开发板 (八) 34 linux-5.11 OK6410A 内存管理第二阶段

上一篇:OK6410A 开发板 (八) 35 linux-5.11 OK6410A 内存管理第三阶段
下一篇:OK6410A 开发板 (八) 33 linux-5.11 OK6410A 内存管理第一阶段

推荐阅读最新更新时间:2024-11-16 23:44

环旭电子12月合并营收为66.37亿元 同比增11.59%
1月9日,环旭电子发布2021年12月营业收入简报,公司2021年12月合并营业收入为人民币66.37亿元,较去年同期的合并营业收入增加11.59%,较2021年11月合并营业收入环比减少4.47%。 环旭电子2021年1月至12合并营业收入为人民币553亿元,较去年同期的合并营业收入增加15.94%。 同时,其2021年第四季度(2021年10-12月)合并营业收入为人民币187.82亿元,较去年同期的合并营业收入增加3.10%,较第三季度(2021年7-9月)合并营业收入环比增加31.85%。 据悉,环旭电子2021年11月合并营业收入为人民币69.48亿元,较去年同期的合并营业收入增加10.33%,较2021年10月合并营
[手机便携]
stm32开发板开发笔记(1)-开发板主控芯片总体映像
国内一行业知名人士要用stm32来开发一个产品,准备将这个产品的开发的过程记录下来。 手里有与一个某宝上淘来的stm32开发板,控制器IC的型号为stm32f103vet6 ,由于ST公司推出的产品众多, 而且每个产品的名字都比较长,不是很容易记忆,作为开发者也没有必要去记住每个型号的特征。 所以我去ST的官网上查询到以下的信息。 显然 根据名字,我们的产品的主控制器型号就是stm32F1系列中一个。 当然,有F1系列,当然就有F0系列,F2系列,F3系列,F4系列,不行你看 可以看到,st公司的产品线极为丰富。根据名字的不同,对应的是不同的内核架构。 因为我们使用的stm103vet6是F1 系列,我们就
[单片机]
stm32<font color='red'>开发板</font>开发笔记(1)-<font color='red'>开发板</font>主控芯片总体映像
国产芯片AI跑分数据亮相CES 弯道超车苹果A11
手机智能终端而言,苹果对性能与系统优化的确堪称一流,但是在AI硬件层面,天生的基因缺陷就有点悲催了。据外媒报道,CES期间,针对四颗主流AI芯片进行了跑分测试,苹果A11惨成炮灰,似乎落后了一个时代。从截图来看,较有代表性的VGG16、ResNet50、InceptionV4几项神经网络模型跑分成本,苹果 A11直接垫底。 近乎被国产芯片Kirin970、RK3399Pro秒杀的节奏。NVIDIA TX2在VGG16、ResNet50测试上表现不错,但并没有给出NVIDIA TX2运行InceptionV4的数据,是否不支持此项测试不得而知。 数据显示,在最重要的NPU关键运算性能方面,苹果A11惨成了渣,瑞芯
[半导体设计/制造]
OPPO全面屏手机R11s售价曝光:或2999元起
   OPPO将于11月2日正式发布旗下首款全面屏手机OPPO R11s。目前除了官方不断开始揭秘该新机,不少网友也开始在网上曝光更多的该机消息。   今日,知名数码博主@数码闲聊站爆料称,“OPPO R11s&OPPO R11s Plus入网工信部:6.01英寸2160×1080AMOLED、骁龙660、4+64GB、3120mAh;6.43英寸2160×1080AMOLED、骁龙660、6+64GB、3880mAh。” OPPO全面屏手机R11s售价曝光:或2999元起售   此外,该博主还称,R11s预估售价2999元,主推3199元的红色版本。如果该爆料属实,那么笼罩在R11s身上最后一层“面纱”也就揭开。   事实上,此
[手机便携]
linux-2.6.32在mini2440开发板上移植(17)之按键驱动程序移植
编者:按键驱动程序涉及到linux中断程序的编写。 1、按键原理图。 2、驱动程序的编写移植。 在/linux-2.6.32.2/drivers/char/目录下创建一个新的驱动程序文件mini2440_buttons.c,内容及详细注释如下: #include linux/module.h #include linux/kernel.h #include linux/fs.h #include linux/init.h #include linux/delay.h #include linux/poll.h #include linux/irq.h #include asm/irq.h #incl
[单片机]
生态系统成形 802.11ad商用鸣枪起跑
802.11ad商用正式开跑。高通(Qualcomm)近期宣布旗下子公司高通创锐讯之802.11ad解决方案,可赋予联网、行动及运算领域大量产品全新多频Wi-Fi功能,目前已获多家业者采用,设计出具有各种先进无线联网功能的产品。这些产品预计将引领生态系统的强势发展,并突显802.11ad为Wi-Fi演进所带来更高的传输量与速率。 高通技术公司资深副总裁暨连结事业总经理Rahul Patel表示,随着家庭与职场对于无线网路传输量及速率的需求不断提升,持续推动Wi-Fi演进仍是业界与该公司的首要目标。透过802.11ad多频技术带来的数千兆位元(Multi-gigabit)高传输量连接,该公司将再次引领产业发展。 802.1
[网络通信]
打造下一个 ASML?传荷兰将投资11亿欧元培育硅光子技术企业
荷兰决定投资 11 亿欧元,以促进新一代硅光子技术企业的发展,为打造下一个 ASML 做好准备。这将意味着围绕下一代半导体技术的商业化,各国和各公司之间正展开激烈竞争。 据 ETNews 报道,这 11 亿欧元中,4 亿 7100 万欧元来自于荷兰政府,其余的投资则来自于荷兰埃因霍温理工大学和特文特大学等合作机构,荷兰基金资助机构 Delta Photon 将负责管理投资的资金。    硅光子技术是替代电子半导体信号传输的一种光传输技术。由于传输速度大幅提高,功率效率也非常高,因此被认为是新一代半导体技术。目前,以半导体输入 / 输出 (I / O) 为中心的技术开发正在进行中。    报道指出,荷兰的投资是为了抢占未来半导体
[半导体设计/制造]
打造下一个 ASML?传荷兰将投资<font color='red'>11</font>亿欧元培育硅光子技术企业
11.汇编代码简单操作
使用汇编的原因很简单,就是汇编代码的高效。在机器启动的时候,利用汇编的高效,对硬件进行初始化,为加载内核,提供条件。 目前常用的ARM汇编指令有两种: *ARM标准汇编:适用于ARM公司的汇编器,适合在Windows平台下使用。 *GNU汇编:使用与GNU交叉编译工具链中的汇编器,适合于Linux平台开发。 3.汇编程序框架:注意下面的操作环境是Redhat 6.4 + eclipse C/C++ +CDT插件。 汇编代码的基本框架 汇编用到的地方,启动代码,效率要求高效的地方。 上面是启动代码的框架。 下面搭建框架: start.S: .text .global _start _start: mov r2,#2
[单片机]
<font color='red'>11</font>.汇编代码简单操作
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved