Linux kernel memory management (ARM)

来源:互联网 发布:java 代码生成器插件 编辑:程序博客网 时间:2024/06/05 17:35
本文以 linux mainline 代码分析,v3.19-rc5 + (SHA-1 : b97f880c8342fd6e49a02c9ef7507a678722b2b3)
以ARM vexpress 为例进行分析,用到的调试命令如下:


make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- distclean ; make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- vexpress_defconfig ; make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- -j16 ;qemu-system-arm -kernel arch/arm/boot/zImage -dtb ./arch/arm/boot/dts/vexpress-v2p-ca9.dtb -serial stdio -M vexpress-a9 -append "root=/dev/mmcblk0 console=ttyAMA0"


CONFIG_CPU_V7=y
# CONFIG_ARM_LPAE is not set




Makefile for the linux arm-specific parts of the memory manager.


arch/arm/mm/Makefile
obj-$(CONFIG_CPU_V7)        += proc-v7.o


proc-v7.S 用汇编实现了 ARM 内存管理 Specific的部分, 包括一些重要的函数定义都在这个文件或是include 的文件。


arch/arm/mm/proc-v7.S


#include <linux/init.h>
#include <linux/linkage.h>
#include <asm/assembler.h>
#include <asm/asm-offsets.h>
#include <asm/hwcap.h>
#include <asm/pgtable-hwdef.h>
#include <asm/pgtable.h>


#include "proc-macros.S"


#ifdef CONFIG_ARM_LPAE // Disabled.
#include "proc-v7-3level.S"
#else
#include "proc-v7-2level.S"
#endif


ENTRY(cpu_v7_proc_init)
ret lr
ENDPROC(cpu_v7_proc_init)


ENTRY(cpu_v7_proc_fin)
mrc p15, 0, r0, c1, c0, 0@ ctrl register
bic r0, r0, #0x1000@ ...i............
bic r0, r0, #0x0006@ .............ca.
mcr p15, 0, r0, c1, c0, 0@ disable caches
ret lr
ENDPROC(cpu_v7_proc_fin)


本文重点分析 proc-v7-2level.S


/*
 * cpu_v7_switch_mm(pgd_phys, tsk)
 *
 * Set the translation table base pointer to be pgd_phys // C语言函数调用过来的时候传的两个参数,第一个 pgd_phys (r0)就是新的 TTB(Translation Table Base) 的物理地址
 *
 * - pgd_phys - physical address of new TTB
 *
 * It is assumed that:
 * - we are not using split page tables
 */
ENTRY(cpu_v7_switch_mm)
#ifdef CONFIG_MMU
mov r2, #0
mmid r1, r1@ get mm->context.id
ALT_SMP(orr r0, r0, #TTB_FLAGS_SMP)
ALT_UP(orr r0, r0, #TTB_FLAGS_UP)


mcr p15, 0, r1, c13, c0, 1@ set context ID
isb
mcr p15, 0, r0, c2, c0, 0@ set TTB 0
isb
#endif
bx lr
ENDPROC(cpu_v7_switch_mm)




看ARM MMU之前先看一下 CP15 协处理器的作用:
About the system control coprocessor


The section gives an overall view of the system control coprocessor. For detail of the registers
in the system control coprocessor, see System control processor registers on page 3-13.
The purpose of the system control coprocessor, CP15, is to control and provide status
information for the functions implemented in the ARM1176JZF-S processor. The main
functions of the system control coprocessor are:


• overall system control and configuration
• cache configuration and management
• Tightly-Coupled Memory (TCM) configuration and management
• Memory Management Unit (MMU) configuration and management
• DMA control
• system performance monitoring.




MMU software-accessible registers
http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0301h/I1031142.html
http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0301h/Bgbfdjaa.html


System control processor registers
This section gives details of all the registers in the system control coprocessor. The section presents a summary of the registers and detailed descriptions in register order of CRn, Opcode_1, CRm, Opcode_2.
You can access CP15 registers with MRC and MCR instructions:
MCR{cond} P15,<Opcode_1>,<Rd>,<CRn>,<CRm>,<Opcode_2>
MRC{cond} P15,<Opcode_1>,<Rd>,<CRn>,<CRm>,<Opcode_2>


To use the Translation Table Base Register 0 read or write CP15 c2 with:
Opcode_1 set to 0
CRn set to c2
CRm set to c0
Opcode_2 set to 0.


For example:
MRC p15, 0, <Rd>, c2, c0, 0    ; Read Translation Table Base Register 0
MCR p15, 0, <Rd>, c2, c0, 0    ; Write Translation Table Base Register 0


http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0301h/Bgbfaich.html




To use the Translation Table Base Control Register read or write CP15 with:
Opcode_1 set to 0
CRn set to c2
CRm set to c0
Opcode_2 set to 2.


For example:
MRC p15, 0, <Rd>, c2, c0, 2    ; Read Translation Table Base Control Register
MCR p15, 0, <Rd>, c2, c0, 2    ; Write Translation Table Base Control Register


linux 内核在做调度进行进程切换的时候的调用流程(内存管理部分)


__schedule
context_switch
switch_mm
check_and_switch_context
cpu_switch_mm
cpu_do_switch_mm
cpu_v7_switch_mm ( proc-v7-2level.S )

将将要执行的进程的pgd 页目录写到CP15 TTBR0.




一个页表项对应一页(也就是4K内容),因为其后面有12位的偏移。一个页表有1024个页表项,因为一个页表大小为4K,一个页表项为32位(4B)。一个页目录项对应一个页表,对应4K*1024=4M空间的映射。一个页目录有1024个页目录项,对应4M*1024=4G地址的映射,正好是32位地址空间。


基本数据类型与函数说明
pde_t 代表一个页目录项
pte_t 代表一个页表项
pgdir_walk()  用于查找某个虚拟地址是否有页表项,如果没有也可以通过此函数创建,值得注意的是,有页表项并不代表已经被映射。
boot_map_region()  映射一个虚拟地址区间到一个物理地址区间,貌似在本部分没用到。
page_insert() 将一个虚拟地址映射到一个Page数据结构,也就是映射到某个物理地址。
page_lookup() 查找一个虚拟地址对应的Page数据结构,若没有映射返回空。
page_remove() 解除某个虚拟地址的映射。

0 0
原创粉丝点击