您的位置:首页 > 运维架构 > Linux

Linux kernel memory management (ARM)

2015-01-30 17:06 519 查看
本文以 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() 解除某个虚拟地址的映射。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: