文章目录
- [1. 概述](#1. 概述)
- [2. 软件架构图](#2. 软件架构图)
- [3. 调用流程图](#3. 调用流程图)
- [4. UML类图](#4. UML类图)
- [5. 源码深度分析](#5. 源码深度分析)
-
- [5.1 ARM64 MMU架构分析](#5.1 ARM64 MMU架构分析)
-
- [5.1.1 ARM64页表结构](#5.1.1 ARM64页表结构)
- [5.1.2 页表分配和管理](#5.1.2 页表分配和管理)
- [5.2 地址映射实现分析](#5.2 地址映射实现分析)
-
- [5.2.1 页表条目设置](#5.2.1 页表条目设置)
- [5.2.2 页表遍历和查找](#5.2.2 页表遍历和查找)
- [5.3 性能优化技术分析](#5.3 性能优化技术分析)
-
- [5.3.1 页表预分配优化](#5.3.1 页表预分配优化)
- [5.3.2 TLB和缓存优化](#5.3.2 TLB和缓存优化)
- [6. 设计模式分析](#6. 设计模式分析)
-
- [6.1 工厂模式在页表分配中的体现](#6.1 工厂模式在页表分配中的体现)
- [6.2 策略模式在地址映射中的体现](#6.2 策略模式在地址映射中的体现)
- [6.3 组合模式在页表层次中的体现](#6.3 组合模式在页表层次中的体现)
- [7. 状态机分析](#7. 状态机分析)
- [8. 性能优化分析](#8. 性能优化分析)
-
- [8.1 页表缓存优化](#8.1 页表缓存优化)
- [8.2 地址转换优化](#8.2 地址转换优化)
- [9. 安全性考虑](#9. 安全性考虑)
-
- [9.1 页表完整性保护](#9.1 页表完整性保护)
- [9.2 地址空间隔离](#9.2 地址空间隔离)
- [10. 扩展性分析](#10. 扩展性分析)
-
- [10.1 多架构支持](#10.1 多架构支持)
- [10.2 功能扩展](#10.2 功能扩展)
- [11. 调试和维护](#11. 调试和维护)
-
- [11.1 MMU调试支持](#11.1 MMU调试支持)
- [11.2 错误检测和恢复](#11.2 错误检测和恢复)
- [12. 总结](#12. 总结)
团队博客: 汽车电子社区
1. 概述
ARM64 mm mmu子模块是Linux内核ARM64架构内存管理子系统中实现内存管理单元的核心组件,包含mmu.c文件。该模块作为ARM64平台MMU管理的核心实现,提供了完整的页表创建、地址映射、页表遍历和MMU上下文管理的功能,是ARM64内存管理系统的"心脏"和基础架构。
mmu子模块实现了ARM64架构下最关键的内存管理逻辑,包括多级页表的创建和维护、虚拟地址到物理地址的映射关系、页表项的权限控制和属性设置。该模块作为内存管理系统的核心,为ARM64平台提供了高效可靠的地址转换和内存访问控制,是现代操作系统内存虚拟化的基石。
模块的设计体现了内存管理单元的复杂性和高性能要求,通过精心设计的页表结构和地址转换算法,在保证内存访问安全性的同时实现了接近硬件极限的地址转换性能,是ARM64内存子系统架构设计的典范。
2. 软件架构图
ARM64 mm mmu
页表管理
地址映射
页表遍历
MMU上下文
mmu.c
多级页表
页表分配
页表释放
地址转换
映射建立
映射解除
页表查找
页表修改
页表同步
ASID管理
TLB管理
缓存一致性
3. 调用流程图
否
是
否
是
否
是
否
是
否
是
内存管理请求
检查页表层次
PGD存在?
分配PGD
检查P4D
P4D存在?
分配P4D
检查PUD
PUD存在?
分配PUD
检查PMD
PMD存在?
分配PMD
检查PTE
PTE存在?
分配PTE页面
设置PTE值
更新TLB
同步操作
完成映射
4. UML类图
MMUManager
+alloc_init_pgd()
+pgd_alloc()
+pgd_free()
+set_pgd()
+pmd_alloc_one()
+pte_alloc_one()
PageTableManager
+pgd_offset()
+p4d_offset()
+pud_offset()
+pmd_offset()
+pte_offset()
+pte_offset_map()
AddressMapping
+set_pte_at()
+set_pmd_at()
+set_pud_at()
+set_p4d_at()
+pte_clear()
+pmd_clear()
MemoryBarrier
+dsb_ish()
+dsb_sy()
+isb()
+tlb_flush()
PageTableEntry
+pte_val()
+pmd_val()
+pud_val()
+p4d_val()
+pte_set()
+pmd_set()
TLBManager
+flush_tlb_all()
+flush_tlb_mm()
+flush_tlb_page()
+flush_tlb_range()
PermissionManager
+pte_mkwrite()
+pte_mkread()
+pte_mkexec()
+pte_mkdirty()
+pte_mkclean()
5. 源码深度分析
5.1 ARM64 MMU架构分析
5.1.1 ARM64页表结构
ARM64页表的层次结构和组织方式:
c
// ARM64页表层次定义
// 页全局目录 (Page Global Directory)
typedef struct { pgdval_t pgd; } pgd_t;
// 页上级目录 (Page Upper Directory) - ARM64特有
typedef struct { p4dval_t p4d; } p4d_t;
// 页上级目录 (Page Upper Directory)
typedef struct { pudval_t pud; } pud_t;
// 页中间目录 (Page Middle Directory)
typedef struct { pmdval_t pmd; } pmd_t;
// 页表条目 (Page Table Entry)
typedef struct { pteval_t pte; } pte_t;
// 页表大小定义
#define PTRS_PER_PGD 512 // 每个PGD包含512个条目
#define PTRS_PER_P4D 512 // 每个P4D包含512个条目(ARM64中通常与PGD相同)
#define PTRS_PER_PUD 512 // 每个PUD包含512个条目
#define PTRS_PER_PMD 512 // 每个PMD包含512个条目
#define PTRS_PER_PTE 512 // 每个PTE页面包含512个条目
// 页面大小
#define PAGE_SIZE 4096 // 标准页面大小
#define PMD_SIZE (PTRS_PER_PMD * PAGE_SIZE) // PMD覆盖的大小
#define PUD_SIZE (PTRS_PER_PUD * PMD_SIZE) // PUD覆盖的大小
#define PGDIR_SIZE (PTRS_PER_PGD * PUD_SIZE) // PGD覆盖的大小
// ARM64特有的页表配置
#define ARM64_HW_PGTABLE_LEVELS 4 // ARM64硬件支持4级页表
#define ARM64_SW_PGTABLE_LEVELS 4 // 软件使用的页表级别
页表层次特点:
1. 4级页表 :ARM64使用完整的4级页表结构
2. 512个条目 :每级页表包含512个指针
3. 灵活配置 :支持不同页面大小的配置
4. ARM64扩展:包含P4D层级以支持未来扩展
5.1.2 页表分配和管理
页表的分配和管理核心函数:
c
// PGD分配函数
pgd_t *pgd_alloc(struct mm_struct *mm)
{
pgd_t *pgd;
p4d_t *p4d;
pud_t *pud;
pmd_t *pmd;
pte_t *pte;
// 分配PGD页面
pgd = (pgd_t *)__get_free_page(GFP_PGTABLE_KERNEL);
if (!pgd)
return NULL;
// 初始化PGD
memset(pgd, 0, PAGE_SIZE);
// 对于ARM64,PGD和P4D通常是相同的
// 预分配必要的页表层次以提高性能
// 为内核空间预分配页表(如果需要)
if (likely(mm == &init_mm)) {
// 初始化内存的页表已经预分配
memcpy(pgd, swapper_pg_dir, PAGE_SIZE);
} else {
// 为用户空间初始化
pgd_val(*pgd) = ARM64_INVALID_PGD;
}
return pgd;
}
// PGD释放函数
void pgd_free(struct mm_struct *mm, pgd_t *pgd)
{
// 清理页表条目
pgd_clear_bad(pgd);
// 释放PGD页面
free_page((unsigned long)pgd);
}
// PMD分配函数
pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long addr)
{
struct page *page;
pmd_t *pmd;
// 分配页面
page = alloc_page(GFP_PGTABLE_USER);
if (!page)
return NULL;
// 初始化PMD
pmd = (pmd_t *)page_address(page);
memset(pmd, 0, PAGE_SIZE);
// 设置页面标记
if (paravirt_enabled()) {
// 虚拟化环境下的特殊处理
paravirt_alloc_pmd(mm, addr);
}
return pmd;
}
// PTE分配函数
pte_t *pte_alloc_one(struct mm_struct *mm, unsigned long addr)
{
struct page *page;
pte_t *pte;
// 分配页面
page = alloc_page(GFP_PGTABLE_USER);
if (!page)
return NULL;
// 初始化PTE
pte = (pte_t *)page_address(page);
memset(pte, 0, PAGE_SIZE);
// 设置页面标记
__SetPageTable(page);
return pte;
}
页表管理特点:
1. 层次化分配 :按需分配各级页表
2. 内存池优化 :使用专门的页表内存池
3. 初始化优化 :预初始化常用页表
4. 虚拟化支持:Xen/KVM虚拟化的特殊处理
5.2 地址映射实现分析
5.2.1 页表条目设置
页表条目的设置和权限管理:
c
// PTE设置函数
void set_pte_at(struct mm_struct *mm, unsigned long addr,
pte_t *ptep, pte_t pte)
{
// 验证地址对齐
WARN_ON(!pte_present(pte) && !pte_none(pte));
// 设置PTE值
if (sizeof(pteval_t) > sizeof(long)) {
// 64位PTE的原子设置
set_pte_atomic(ptep, pte);
} else {
// 32位PTE的设置
*ptep = pte;
}
// TLB维护
if (pte_present(pte)) {
// 页面存在,更新TLB
update_mmu_cache(mm, addr, ptep);
} else {
// 页面不存在,无需TLB更新
}
}
// PMD设置函数
void set_pmd_at(struct mm_struct *mm, unsigned long addr,
pmd_t *pmdp, pmd_t pmd)
{
// PMD设置逻辑
if (pmd_large(pmd)) {
// 大页面的特殊处理
set_pmd_safe(pmdp, pmd);
} else {
// 普通PMD设置
*pmdp = pmd;
}
// TLB同步
flush_tlb_range(mm, addr, addr + PMD_SIZE);
}
// 页面权限设置函数
pte_t pte_mkwrite(pte_t pte)
{
// 设置写权限
pte_val(pte) |= L_PTE_WRITE;
return pte;
}
pte_t pte_mkread(pte_t pte)
{
// 设置读权限
pte_val(pte) |= L_PTE_READ;
return pte;
}
pte_t pte_mkexec(pte_t pte)
{
// 设置执行权限
pte_val(pte) |= L_PTE_EXEC;
return pte;
}
pte_t pte_mkdirty(pte_t pte)
{
// 标记页面为脏
pte_val(pte) |= L_PTE_DIRTY;
return pte;
}
pte_t pte_mkclean(pte_t pte)
{
// 清除脏标记
pte_val(pte) &= ~L_PTE_DIRTY;
return pte;
}
权限管理特点:
1. 原子操作 :大PTE的原子设置保证一致性
2. 权限控制 :精确的读写执行权限管理
3. 状态跟踪 :页面脏状态的维护
4. TLB同步:映射变化后的TLB更新
5.2.2 页表遍历和查找
页表的遍历和查找算法:
c
// 页表偏移计算函数
pgd_t *pgd_offset(struct mm_struct *mm, unsigned long address)
{
// 计算PGD索引
unsigned long index = pgd_index(address);
// 返回PGD条目指针
return mm->pgd + index;
}
p4d_t *p4d_offset(pgd_t *pgd, unsigned long address)
{
// ARM64中P4D通常与PGD相同
if (pgd_none(*pgd)) {
return (p4d_t *)pgd;
}
// 计算P4D索引
unsigned long index = p4d_index(address);
// 返回P4D条目指针
p4d_t *p4d = p4d_offset(pgd, address);
return p4d;
}
pud_t *pud_offset(p4d_t *p4d, unsigned long address)
{
// 检查是否为大页
if (p4d_large(*p4d)) {
return (pud_t *)p4d;
}
// 计算PUD索引
unsigned long index = pud_index(address);
// 获取PUD页表
pud_t *pud = pud_offset(p4d, address);
return pud;
}
pmd_t *pmd_offset(pud_t *pud, unsigned long address)
{
// 检查是否为大页
if (pud_large(*pud)) {
return (pmd_t *)pud;
}
// 计算PMD索引
unsigned long index = pmd_index(address);
// 获取PMD页表
pmd_t *pmd = pmd_offset(pud, address);
return pmd;
}
pte_t *pte_offset(pmd_t *pmd, unsigned long address)
{
// 检查是否为大页
if (pmd_large(*pmd)) {
return (pte_t *)pmd;
}
// 计算PTE索引
unsigned long index = pte_index(address);
// 获取PTE页表
pte_t *pte = pte_offset(pmd, address);
return pte;
}
// 页表查找和映射
pte_t *pte_offset_map(pmd_t *pmd, unsigned long address)
{
pte_t *pte;
// 获取PTE指针
pte = pte_offset(pmd, address);
// 映射PTE页面(处理锁)
pte = pte_offset_map_lock(mm, pmd, address, &ptl);
return pte;
}
页表遍历特点:
1. 层次索引 :每级页表的索引计算
2. 大页支持 :大页面的特殊处理路径
3. 锁管理 :页表锁的获取和释放
4. 内存映射:PTE页面的临时映射
5.3 性能优化技术分析
5.3.1 页表预分配优化
页表的预分配和缓存优化:
c
// 页表预分配策略
#define PGD_PREALLOC_SIZE 16 // 预分配的PGD数量
#define PMD_PREALLOC_SIZE 64 // 预分配的PMD数量
#define PTE_PREALLOC_SIZE 128 // 预分配的PTE数量
// 页表缓存
struct pgtable_cache {
struct page *pgd_cache[PGD_PREALLOC_SIZE];
struct page *pmd_cache[PMD_PREALLOC_SIZE];
struct page *pte_cache[PTE_PREALLOC_SIZE];
spinlock_t lock;
int pgd_count;
int pmd_count;
int pte_count;
};
// 从缓存分配PGD
pgd_t *pgd_alloc_cached(struct mm_struct *mm)
{
struct page *page;
// 尝试从缓存获取
spin_lock(&pgtable_cache.lock);
if (pgtable_cache.pgd_count > 0) {
page = pgtable_cache.pgd_cache[--pgtable_cache.pgd_count];
spin_unlock(&pgtable_cache.lock);
// 初始化页面
pgd_t *pgd = (pgd_t *)page_address(page);
memset(pgd, 0, PAGE_SIZE);
return pgd;
}
spin_unlock(&pgtable_cache.lock);
// 缓存未命中,正常分配
return pgd_alloc(mm);
}
// 预填充页表缓存
void prepopulate_pgtable_cache(void)
{
int i;
// 预分配PGD
for (i = 0; i < PGD_PREALLOC_SIZE; i++) {
struct page *page = alloc_page(GFP_PGTABLE_KERNEL);
if (page) {
spin_lock(&pgtable_cache.lock);
pgtable_cache.pgd_cache[pgtable_cache.pgd_count++] = page;
spin_unlock(&pgtable_cache.lock);
}
}
// 预分配PMD和PTE
// ... 类似逻辑
}
// 页表预热优化
void pgtable_warmup(struct mm_struct *mm, unsigned long start, size_t size)
{
unsigned long addr = start;
unsigned long end = start + size;
// 预先建立页表层次
for (; addr < end; addr += PMD_SIZE) {
pgd_t *pgd = pgd_offset(mm, addr);
if (pgd_none(*pgd)) {
// 预分配必要的页表
handle_mm_fault(NULL, addr, FAULT_FLAG_ALLOW_RETRY, NULL);
}
}
}
预分配特点:
1. 缓存池 :各级页表的预分配缓存
2. 批量分配 :减少频繁的页面分配开销
3. 预热机制 :关键地址空间的页表预热
4. 锁优化:细粒度的锁减少竞争
5.3.2 TLB和缓存优化
TLB和缓存的协同优化:
c
// MMU缓存更新
void update_mmu_cache(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep)
{
// 检查是否需要TLB更新
if (pte_present(*ptep)) {
// 页面存在,更新TLB
update_tlb_single(addr);
// 检查是否为大页
if (pte_huge(*ptep)) {
// 大页面的特殊处理
update_tlb_huge(addr);
}
}
// 缓存预取优化
prefetch_page_tables(addr);
}
// TLB单个页面更新
static void update_tlb_single(unsigned long addr)
{
// ARM64 TLB更新指令
asm volatile("tlbi vae1, %0" : : "r" (addr >> 12));
// 同步屏障
asm volatile("dsb ish" : : : "memory");
asm volatile("isb" : : : "memory");
}
// TLB大页更新
static void update_tlb_huge(unsigned long addr)
{
// 大页面的TLB更新
asm volatile("tlbi vae1is, %0" : : "r" (addr >> 12));
// 同步操作
asm volatile("dsb ish" : : : "memory");
}
// 页表预取
static void prefetch_page_tables(unsigned long addr)
{
unsigned long pgd_idx = pgd_index(addr);
unsigned long p4d_idx = p4d_index(addr);
unsigned long pud_idx = pud_index(addr);
unsigned long pmd_idx = pmd_index(addr);
// 预取各级页表
prefetch(¤t->mm->pgd[pgd_idx]);
// 根据页表层次预取更多级别
if (ARM64_SW_PGTABLE_LEVELS > 3) {
// 预取P4D
prefetch_p4d_tables(addr);
}
prefetch_pud_tables(addr);
prefetch_pmd_tables(addr);
}
// 页面表预取优化
static void prefetch_pmd_tables(unsigned long addr)
{
pmd_t *pmd;
unsigned long pmd_end;
// 计算PMD范围
unsigned long pmd_start = addr & PMD_MASK;
pmd_end = pmd_start + PMD_SIZE;
// 预取PMD条目
for (unsigned long a = pmd_start; a < pmd_end; a += PAGE_SIZE) {
pmd = pmd_offset(pud_offset(p4d_offset(pgd_offset(current->mm, a), a), a), a);
prefetch(pmd);
}
}
缓存优化特点:
1. TLB精细控制 :不同类型页面的TLB更新
2. 预取策略 :页表的智能预取
3. 大页优化 :大页面的特殊处理路径
4. 同步保证:正确的内存屏障使用
6. 设计模式分析
6.1 工厂模式在页表分配中的体现
页表分配的工厂模式:
c
// 页表分配器接口
interface PageTableAllocator {
PageTable allocate(struct mm_struct *mm, unsigned long addr);
void free(PageTable table);
boolean canAllocate(unsigned long addr);
String getAllocatorName();
}
// PGD分配器实现
class PGDAllocator implements PageTableAllocator {
public PageTable allocate(struct mm_struct *mm, unsigned long addr) {
pgd_t *pgd = pgd_alloc(mm);
if (pgd) {
return new PageTable(pgd, PageTableLevel.PGD);
}
return null;
}
public void free(PageTable table) {
pgd_free(table.getMM(), (pgd_t *)table.getTable());
}
public boolean canAllocate(unsigned long addr) {
return true; // PGD总是可以分配
}
public String getAllocatorName() {
return "PGD_ALLOCATOR";
}
}
// PMD分配器实现
class PMDAllocator implements PageTableAllocator {
public PageTable allocate(struct mm_struct *mm, unsigned long addr) {
pmd_t *pmd = pmd_alloc_one(mm, addr);
if (pmd) {
return new PageTable(pmd, PageTableLevel.PMD);
}
return null;
}
public void free(PageTable table) {
pmd_free((pmd_t *)table.getTable());
}
public boolean canAllocate(unsigned long addr) {
return !pmd_large(*(pmd_t *)find_pmd_table(addr)); // 只有非大页才需要分配
}
public String getAllocatorName() {
return "PMD_ALLOCATOR";
}
}
// PTE分配器实现
class PTEAllocator implements PageTableAllocator {
public PageTable allocate(struct mm_struct *mm, unsigned long addr) {
pte_t *pte = pte_alloc_one(mm, addr);
if (pte) {
return new PageTable(pte, PageTableLevel.PTE);
}
return null;
}
public void free(PageTable table) {
pte_free((pte_t *)table.getTable());
}
public boolean canAllocate(unsigned long addr) {
return !pmd_large(*(pmd_t *)find_pmd_table(addr)); // 只有非大页才需要分配
}
public String getAllocatorName() {
return "PTE_ALLOCATOR";
}
}
// 页表分配器工厂
class PageTableAllocatorFactory {
private static Map<PageTableLevel, PageTableAllocator> allocators;
static {
allocators = new HashMap<>();
allocators.put(PageTableLevel.PGD, new PGDAllocator());
allocators.put(PageTableLevel.PMD, new PMDAllocator());
allocators.put(PageTableLevel.PTE, new PTEAllocator());
}
public static PageTableAllocator getAllocator(PageTableLevel level) {
return allocators.get(level);
}
public static PageTable allocatePageTable(PageTableLevel level,
struct mm_struct *mm, unsigned long addr) {
PageTableAllocator allocator = getAllocator(level);
if (allocator != null && allocator.canAllocate(addr)) {
return allocator.allocate(mm, addr);
}
return null;
}
public static void freePageTable(PageTable table) {
PageTableAllocator allocator = getAllocator(table.getLevel());
if (allocator != null) {
allocator.free(table);
}
}
}
// 使用工厂模式
class MMUManager {
public PageTable allocatePageTable(PageTableLevel level,
struct mm_struct *mm, unsigned long addr) {
return PageTableAllocatorFactory.allocatePageTable(level, mm, addr);
}
public void freePageTable(PageTable table) {
PageTableAllocatorFactory.freePageTable(table);
}
}
6.2 策略模式在地址映射中的体现
地址映射的策略模式:
c
// 地址映射策略接口
interface AddressMappingStrategy {
vm_fault_t mapAddress(struct vm_fault *vmf);
boolean canHandle(struct vm_fault *vmf);
String getStrategyName();
double getMappingEfficiency();
long getAverageMappingTime();
}
// 标准页面映射策略
class StandardPageMappingStrategy implements AddressMappingStrategy {
public vm_fault_t mapAddress(struct vm_fault *vmf) {
// 标准页面映射逻辑
struct page *page = alloc_page(GFP_HIGHUSER_MOVABLE);
if (!page) {
return VM_FAULT_OOM;
}
// 建立映射
pte_t entry = mk_pte(page, vmf->vma->vm_page_prot);
set_pte_at(vmf->vma->vm_mm, vmf->address, vmf->pte, entry);
return VM_FAULT_SUCCESS;
}
public boolean canHandle(struct vm_fault *vmf) {
// 检查是否为标准页面映射
return is_standard_page_fault(vmf);
}
public String getStrategyName() {
return "STANDARD_PAGE_MAPPING";
}
public double getMappingEfficiency() {
return 0.95;
}
public long getAverageMappingTime() {
return 2000; // 2微秒
}
}
// 写时复制映射策略
class CopyOnWriteMappingStrategy implements AddressMappingStrategy {
public vm_fault_t mapAddress(struct vm_fault *vmf) {
// 写时复制映射逻辑
struct page *old_page = vmf->page;
struct page *new_page = alloc_page(GFP_HIGHUSER_MOVABLE);
if (!new_page) {
return VM_FAULT_OOM;
}
// 复制页面内容
copy_user_highpage(new_page, old_page, vmf->address, vmf->vma);
// 建立私有映射
pte_t entry = mk_pte(new_page, vmf->vma->vm_page_prot);
entry = pte_mkwrite(pte_mkdirty(entry));
set_pte_at(vmf->vma->vm_mm, vmf->address, vmf->pte, entry);
// 释放旧页面引用
put_page(old_page);
return VM_FAULT_SUCCESS;
}
public boolean canHandle(struct vm_fault *vmf) {
// 检查是否为写时复制场景
return is_copy_on_write_fault(vmf);
}
public String getStrategyName() {
return "COPY_ON_WRITE_MAPPING";
}
public double getMappingEfficiency() {
return 0.85;
}
public long getAverageMappingTime() {
return 10000; // 10微秒(包括复制时间)
}
}
// 交换页面映射策略
class SwapPageMappingStrategy implements AddressMappingStrategy {
public vm_fault_t mapAddress(struct vm_fault *vmf) {
// 交换页面映射逻辑
swp_entry_t entry = pte_to_swp_entry(*vmf->pte);
struct page *page = alloc_page(GFP_HIGHUSER_MOVABLE);
if (!page) {
return VM_FAULT_OOM;
}
// 从交换空间读取页面
if (swap_readpage(page, entry) != 0) {
__free_page(page);
return VM_FAULT_SIGBUS;
}
// 建立映射
pte_t entry = mk_pte(page, vmf->vma->vm_page_prot);
set_pte_at(vmf->vma->vm_mm, vmf->address, vmf->pte, entry);
return VM_FAULT_SUCCESS;
}
public boolean canHandle(struct vm_fault *vmf) {
// 检查页面是否在交换空间
return is_swap_page_fault(vmf);
}
public String getStrategyName() {
return "SWAP_PAGE_MAPPING";
}
public double getMappingEfficiency() {
return 0.75;
}
public long getAverageMappingTime() {
return 50000; // 50微秒(包括I/O时间)
}
}
// 自适应地址映射策略
class AdaptiveMappingStrategy implements AddressMappingStrategy {
private List<AddressMappingStrategy> strategies;
private MappingStatistics stats;
public AdaptiveMappingStrategy() {
strategies = Arrays.asList(
new StandardPageMappingStrategy(),
new CopyOnWriteMappingStrategy(),
new SwapPageMappingStrategy()
);
stats = new MappingStatistics();
}
public vm_fault_t mapAddress(struct vm_fault *vmf) {
// 选择最适合的策略
AddressMappingStrategy bestStrategy = selectBestStrategy(vmf);
long startTime = System.nanoTime();
vm_fault_t result = bestStrategy.mapAddress(vmf);
long mappingTime = System.nanoTime() - startTime;
// 更新统计信息
stats.recordMapping(bestStrategy.getStrategyName(), result == VM_FAULT_SUCCESS, mappingTime);
// 重新评估策略优先级
reevaluateStrategyPriorities();
return result;
}
public boolean canHandle(struct vm_fault *vmf) {
return strategies.stream().anyMatch(s -> s.canHandle(vmf));
}
public String getStrategyName() {
return "ADAPTIVE_MAPPING";
}
public double getMappingEfficiency() {
return stats.getOverallEfficiency();
}
public long getAverageMappingTime() {
return stats.getAverageMappingTime();
}
private AddressMappingStrategy selectBestStrategy(struct vm_fault *vmf) {
return strategies.stream()
.filter(s -> s.canHandle(vmf))
.max(Comparator.comparingDouble(s -> calculateStrategyScore(s, vmf)))
.orElse(new StandardPageMappingStrategy());
}
private double calculateStrategyScore(AddressMappingStrategy strategy, struct vm_fault *vmf) {
double efficiency = stats.getStrategyEfficiency(strategy.getStrategyName());
long avgTime = stats.getStrategyAverageTime(strategy.getStrategyName());
// 综合评分:效率权重70%,时间权重30%
return efficiency * 0.7 - (avgTime / 1000000.0) * 0.3;
}
private void reevaluateStrategyPriorities() {
strategies.sort((a, b) -> Double.compare(
stats.getStrategyEfficiency(b.getStrategyName()),
stats.getStrategyEfficiency(a.getStrategyName())
));
}
}
// 策略选择器
class AddressMappingStrategySelector {
public static AddressMappingStrategy selectStrategy(PageFaultType type, SystemContext context) {
switch (type) {
case MISSING_PAGE:
return new StandardPageMappingStrategy();
case COPY_ON_WRITE:
return new CopyOnWriteMappingStrategy();
case SWAPPED_OUT:
return new SwapPageMappingStrategy();
case COMPLEX_FAULT:
return new AdaptiveMappingStrategy();
default:
return new StandardPageMappingStrategy();
}
}
}
6.3 组合模式在页表层次中的体现
页表层次的组合模式:
c
// 页表组件接口
interface PageTableComponent {
void setEntry(unsigned long index, PageTableEntry entry);
PageTableEntry getEntry(unsigned long index);
boolean isPresent(unsigned long index);
void clearEntry(unsigned long index);
PageTableLevel getLevel();
void traverse(PageTableVisitor visitor);
}
// 页表条目类
class PageTableEntry {
private long value;
public PageTableEntry(long value) {
this.value = value;
}
public long getValue() {
return value;
}
public void setValue(long value) {
this.value = value;
}
public boolean isPresent() {
return (value & PTE_PRESENT) != 0;
}
public boolean isLarge() {
return (value & PTE_LARGE) != 0;
}
public long getPhysicalAddress() {
return value & PTE_ADDR_MASK;
}
}
// 页表节点(组合模式中的叶子节点)
class PageTableLeaf implements PageTableComponent {
private PageTableEntry entry;
private unsigned long index;
public PageTableLeaf(unsigned long index, PageTableEntry entry) {
this.index = index;
this.entry = entry;
}
public void setEntry(unsigned long index, PageTableEntry entry) {
if (this.index == index) {
this.entry = entry;
}
}
public PageTableEntry getEntry(unsigned long index) {
return (this.index == index) ? entry : null;
}
public boolean isPresent(unsigned long index) {
return this.index == index && entry.isPresent();
}
public void clearEntry(unsigned long index) {
if (this.index == index) {
entry = new PageTableEntry(0);
}
}
public PageTableLevel getLevel() {
return PageTableLevel.PTE;
}
public void traverse(PageTableVisitor visitor) {
visitor.visitLeaf(this);
}
}
// 页表节点(组合模式中的组合节点)
class PageTableComposite implements PageTableComponent {
private PageTableComponent[] children;
private PageTableLevel level;
private unsigned long baseIndex;
public PageTableComposite(PageTableLevel level, unsigned long baseIndex) {
this.level = level;
this.baseIndex = baseIndex;
this.children = new PageTableComponent[getEntriesPerLevel(level)];
// 初始化子节点
for (int i = 0; i < children.length; i++) {
children[i] = createChild(level, baseIndex + i);
}
}
private PageTableComponent createChild(PageTableLevel parentLevel, unsigned long index) {
PageTableLevel childLevel = getChildLevel(parentLevel);
if (childLevel == PageTableLevel.PTE) {
return new PageTableLeaf(index, new PageTableEntry(0));
} else {
return new PageTableComposite(childLevel, index * getEntriesPerLevel(childLevel));
}
}
private PageTableLevel getChildLevel(PageTableLevel level) {
switch (level) {
case PGD: return PageTableLevel.P4D;
case P4D: return PageTableLevel.PUD;
case PUD: return PageTableLevel.PMD;
case PMD: return PageTableLevel.PTE;
default: throw new IllegalArgumentException("Invalid level");
}
}
private int getEntriesPerLevel(PageTableLevel level) {
switch (level) {
case PGD:
case P4D:
case PUD:
case PMD:
return PTRS_PER_PGD; // 512
case PTE:
return 1; // PTE是叶子节点
default:
return 0;
}
}
public void setEntry(unsigned long index, PageTableEntry entry) {
unsigned long localIndex = index - baseIndex;
unsigned long entriesPerChild = getEntriesPerLevel(getChildLevel(level));
unsigned long childIndex = localIndex / entriesPerChild;
unsigned long childLocalIndex = localIndex % entriesPerChild;
if (childIndex < children.length) {
children[(int)childIndex].setEntry(childLocalIndex, entry);
}
}
public PageTableEntry getEntry(unsigned long index) {
unsigned long localIndex = index - baseIndex;
unsigned long entriesPerChild = getEntriesPerLevel(getChildLevel(level));
unsigned long childIndex = localIndex / entriesPerChild;
unsigned long childLocalIndex = localIndex % entriesPerChild;
if (childIndex < children.length) {
return children[(int)childIndex].getEntry(childLocalIndex);
}
return null;
}
public boolean isPresent(unsigned long index) {
unsigned long localIndex = index - baseIndex;
unsigned long entriesPerChild = getEntriesPerLevel(getChildLevel(level));
unsigned long childIndex = localIndex / entriesPerChild;
unsigned long childLocalIndex = localIndex % entriesPerChild;
if (childIndex < children.length) {
return children[(int)childIndex].isPresent(childLocalIndex);
}
return false;
}
public void clearEntry(unsigned long index) {
unsigned long localIndex = index - baseIndex;
unsigned long entriesPerChild = getEntriesPerLevel(getChildLevel(level));
unsigned long childIndex = localIndex / entriesPerChild;
unsigned long childLocalIndex = localIndex % entriesPerChild;
if (childIndex < children.length) {
children[(int)childIndex].clearEntry(childLocalIndex);
}
}
public PageTableLevel getLevel() {
return level;
}
public void traverse(PageTableVisitor visitor) {
visitor.visitComposite(this);
for (PageTableComponent child : children) {
child.traverse(visitor);
}
}
}
// 页表访问者接口
interface PageTableVisitor {
void visitLeaf(PageTableLeaf leaf);
void visitComposite(PageTableComposite composite);
}
// 页表转储访问者
class PageTableDumpVisitor implements PageTableVisitor {
private PrintWriter writer;
private int indentLevel = 0;
public PageTableDumpVisitor(PrintWriter writer) {
this.writer = writer;
}
public void visitLeaf(PageTableLeaf leaf) {
printIndent();
writer.printf("PTE[%d]: %016lx\n", leaf.getIndex(), leaf.getEntry().getValue());
}
public void visitComposite(PageTableComposite composite) {
printIndent();
writer.printf("%s[%d]:\n", composite.getLevel().name(), composite.getBaseIndex());
indentLevel++;
}
private void printIndent() {
for (int i = 0; i < indentLevel; i++) {
writer.print(" ");
}
}
}
// 页表验证访问者
class PageTableValidationVisitor implements PageTableVisitor {
private List<String> errors = new ArrayList<>();
public void visitLeaf(PageTableLeaf leaf) {
PageTableEntry entry = leaf.getEntry();
// 验证PTE的正确性
if (entry.isPresent() && entry.getPhysicalAddress() == 0) {
errors.add(String.format("Invalid PTE at index %d: present but no physical address",
leaf.getIndex()));
}
if (!isAligned(entry.getPhysicalAddress(), PAGE_SIZE)) {
errors.add(String.format("Unaligned physical address in PTE at index %d: %lx",
leaf.getIndex(), entry.getPhysicalAddress()));
}
}
public void visitComposite(PageTableComposite composite) {
// 验证组合节点的正确性
if (composite.getChildren().length != getExpectedChildrenCount(composite.getLevel())) {
errors.add(String.format("Invalid children count for %s: expected %d, got %d",
composite.getLevel().name(),
getExpectedChildrenCount(composite.getLevel()),
composite.getChildren().length));
}
}
public List<String> getErrors() {
return errors;
}
private int getExpectedChildrenCount(PageTableLevel level) {
return (level != PageTableLevel.PTE) ? PTRS_PER_PGD : 1;
}
private boolean isAligned(long address, long alignment) {
return (address & (alignment - 1)) == 0;
}
}
// 使用组合模式
class PageTableManager {
private PageTableComposite root;
public PageTableManager() {
// 创建4级页表层次结构
root = new PageTableComposite(PageTableLevel.PGD, 0);
}
public void setEntry(unsigned long address, PageTableEntry entry) {
unsigned long index = address >> PAGE_SHIFT;
root.setEntry(index, entry);
}
public PageTableEntry getEntry(unsigned long address) {
unsigned long index = address >> PAGE_SHIFT;
return root.getEntry(index);
}
public void clearEntry(unsigned long address) {
unsigned long index = address >> PAGE_SHIFT;
root.clearEntry(index);
}
public void dumpPageTable(PrintWriter writer) {
PageTableDumpVisitor dumper = new PageTableDumpVisitor(writer);
root.traverse(dumper);
}
public boolean validatePageTable() {
PageTableValidationVisitor validator = new PageTableValidationVisitor();
root.traverse(validator);
return validator.getErrors().isEmpty();
}
public List<String> getValidationErrors() {
PageTableValidationVisitor validator = new PageTableValidationVisitor();
root.traverse(validator);
return validator.getErrors();
}
}
7. 状态机分析
ARM64 mm mmu的状态机:
初始状态 -> 页表查找 -> 条目检查 -> 分配页表 -> 设置条目 -> TLB更新 -> 映射完成
↑ ↓
错误处理 <---------------------------------------------------------------------------------+
↑ ↓
权限验证 <---------------------------------------------------------------------------------+
↑ ↓
同步操作 <---------------------------------------------------------------------------------+
8. 性能优化分析
8.1 页表缓存优化
页表缓存的性能优化:
c
// 页表缓存命中率分析
static void analyze_ptable_cache_performance(void) {
// 分析页表缓存的性能
u64 cache_hits = 0;
u64 cache_misses = 0;
u64 total_lookups = 1000000;
for (u64 i = 0; i < total_lookups; i++) {
unsigned long addr = get_random_address();
if (is_ptable_cached(addr)) {
cache_hits++;
} else {
cache_misses++;
// 模拟缓存填充
fill_ptable_cache(addr);
}
}
double hit_rate = (double)cache_hits / total_lookups * 100;
pr_info("Page table cache performance:\n");
pr_info(" Cache hits: %llu\n", cache_hits);
pr_info(" Cache misses: %llu\n", cache_misses);
pr_info(" Hit rate: %.2f%%\n", hit_rate);
}
8.2 地址转换优化
地址转换的性能优化:
c
// 地址转换性能分析
static void analyze_address_translation_performance(void) {
// 分析地址转换的性能
u64 translations = 100000;
u64 start_time, end_time;
u64 total_time;
start_time = ktime_get_ns();
for (u64 i = 0; i < translations; i++) {
unsigned long va = get_test_virtual_address(i);
phys_addr_t pa = virt_to_phys(va);
// 验证转换结果
if (pa == 0) {
pr_err("Translation failed for VA: %lx\n", va);
}
}
end_time = ktime_get_ns();
total_time = end_time - start_time;
pr_info("Address translation performance:\n");
pr_info(" Total translations: %llu\n", translations);
pr_info(" Total time: %llu ns\n", total_time);
pr_info(" Average time per translation: %llu ns\n", total_time / translations);
pr_info(" Translations per second: %llu\n", translations * 1000000000ULL / total_time);
}
9. 安全性考虑
9.1 页表完整性保护
页表完整性的安全保障:
c
// 页表完整性验证
static int validate_page_table_integrity(pgd_t *pgd) {
// 验证PGD的完整性
if (!pgd || !virt_addr_valid(pgd)) {
return -EFAULT;
}
// 遍历所有P4D
for (int i = 0; i < PTRS_PER_PGD; i++) {
p4d_t *p4d = p4d_offset(pgd, i * PGDIR_SIZE);
if (p4d_bad(*p4d)) {
// 发现损坏的P4D
return -EFAULT;
}
if (p4d_present(*p4d)) {
// 递归验证PUD
int ret = validate_p4d_integrity(p4d);
if (ret < 0) {
return ret;
}
}
}
return 0;
}
// 递归页表完整性验证
static int validate_p4d_integrity(p4d_t *p4d) {
for (int i = 0; i < PTRS_PER_P4D; i++) {
pud_t *pud = pud_offset(p4d, i * P4D_SIZE);
if (pud_bad(*pud)) {
return -EFAULT;
}
if (pud_present(*pud)) {
int ret = validate_pud_integrity(pud);
if (ret < 0) {
return ret;
}
}
}
return 0;
}
// 页表条目权限验证
static int validate_pte_permissions(pte_t *pte, unsigned long addr) {
// 检查权限设置的合理性
if (pte_present(*pte)) {
// 对于用户空间,执行权限应该被限制
if (!(addr & PAGE_OFFSET) && pte_exec(*pte)) {
// 用户空间不应该有执行权限(除非特殊情况)
return -EACCES;
}
// 检查物理地址的有效性
phys_addr_t pa = pte_pfn(*pte) << PAGE_SHIFT;
if (!pfn_valid(pte_pfn(*pte))) {
return -EFAULT;
}
}
return 0;
}
9.2 地址空间隔离
地址空间隔离的安全防护:
c
// 地址空间隔离验证
static int validate_address_space_isolation(struct mm_struct *mm1, struct mm_struct *mm2) {
// 确保两个地址空间没有重叠
if (mm1 == mm2) {
return 0; // 同一地址空间
}
// 检查ASID是否不同
if (mm1->asid == mm2->asid && mm1->asid != 0) {
// ASID冲突,可能导致隔离失败
return -EFAULT;
}
// 验证页表不共享
if (page_table_overlaps(mm1->pgd, mm2->pgd)) {
return -EFAULT;
}
return 0;
}
// 页表重叠检测
static bool page_table_overlaps(pgd_t *pgd1, pgd_t *pgd2) {
// 检查是否有共享的页表页面
for (int i = 0; i < PTRS_PER_PGD; i++) {
p4d_t *p4d1 = p4d_offset(pgd1, i * PGDIR_SIZE);
p4d_t *p4d2 = p4d_offset(pgd2, i * PGDIR_SIZE);
if (p4d_present(*p4d1) && p4d_present(*p4d2)) {
if (p4d_page(*p4d1) == p4d_page(*p4d2)) {
// 发现共享的页表页面
return true;
}
}
}
return false;
}
// 地址转换安全检查
static int validate_address_translation(unsigned long va, phys_addr_t pa) {
// 检查虚拟地址范围
if (va >= TASK_SIZE_MAX) {
// 内核空间访问,需要权限验证
if (!capable(CAP_SYS_ADMIN)) {
return -EACCES;
}
}
// 检查物理地址有效性
if (!phys_addr_valid(pa)) {
return -EFAULT;
}
// 检查地址对齐
if (!IS_ALIGNED(va, sizeof(void *)) || !IS_ALIGNED(pa, PAGE_SIZE)) {
return -EINVAL;
}
// 检查是否为安全映射
if (is_unsafe_mapping(va, pa)) {
return -EACCES;
}
return 0;
}
10. 扩展性分析
10.1 多架构支持
跨架构的MMU管理扩展:
c
// 架构特定的MMU操作接口
struct mmu_ops {
const char *arch_name;
// 页表管理
pgd_t *(*alloc_pgd)(struct mm_struct *mm);
void (*free_pgd)(struct mm_struct *mm, pgd_t *pgd);
// 地址映射
void (*set_pte_at)(struct mm_struct *mm, unsigned long addr, pte_t *ptep, pte_t pte);
void (*set_pmd_at)(struct mm_struct *mm, unsigned long addr, pmd_t *pmdp, pmd_t pmd);
// TLB管理
void (*flush_tlb_all)(void);
void (*flush_tlb_mm)(struct mm_struct *mm);
void (*flush_tlb_page)(struct vm_area_struct *vma, unsigned long addr);
// 页表遍历
pgd_t *(*pgd_offset)(struct mm_struct *mm, unsigned long address);
pte_t *(*pte_offset)(pmd_t *pmd, unsigned long address);
};
// ARM64 MMU操作实现
static const struct mmu_ops arm64_mmu_ops = {
.arch_name = "arm64",
.alloc_pgd = arm64_alloc_pgd,
.free_pgd = arm64_free_pgd,
.set_pte_at = arm64_set_pte_at,
.set_pmd_at = arm64_set_pmd_at,
.flush_tlb_all = arm64_flush_tlb_all,
.flush_tlb_mm = arm64_flush_tlb_mm,
.flush_tlb_page = arm64_flush_tlb_page,
.pgd_offset = arm64_pgd_offset,
.pte_offset = arm64_pte_offset,
};
// x86 MMU操作实现
static const struct mmu_ops x86_mmu_ops = {
.arch_name = "x86_64",
.alloc_pgd = x86_alloc_pgd,
// ... 其他操作
};
// 运行时架构选择
static const struct mmu_ops *select_mmu_ops(void)
{
#ifdef CONFIG_ARM64
return &arm64_mmu_ops;
#elif defined(CONFIG_X86_64)
return &x86_mmu_ops;
#else
return NULL;
#endif
}
10.2 功能扩展
MMU功能扩展能力:
c
// 高级MMU功能扩展
struct advanced_mmu_features {
bool support_large_pages; // 支持大页
bool support_access_tracking; // 支持访问跟踪
bool support_memory_tagging; // 支持内存标签
bool support_page_attributes; // 支持页面属性
bool support_nested_paging; // 支持嵌套分页
};
// MMU扩展API
struct extended_mmu_api {
// 大页管理
int (*alloc_huge_pmd)(struct mm_struct *mm, unsigned long addr);
void (*free_huge_pmd)(struct mm_struct *mm, pmd_t *pmd);
// 访问跟踪
int (*enable_access_tracking)(struct mm_struct *mm, unsigned long addr, size_t size);
int (*disable_access_tracking)(struct mm_struct *mm, unsigned long addr, size_t size);
int (*get_access_info)(struct mm_struct *mm, unsigned long addr, struct access_info *info);
// 内存标签
int (*set_memory_tag)(unsigned long addr, size_t size, uint8_t tag);
int (*get_memory_tag)(unsigned long addr, uint8_t *tag);
// 页面属性
int (*set_page_attributes)(unsigned long addr, size_t size, unsigned long attrs);
int (*get_page_attributes)(unsigned long addr, unsigned long *attrs);
};
11. 调试和维护
11.1 MMU调试支持
MMU调试支持:
c
// MMU调试宏
#define MMU_DEBUG(fmt, ...) \
pr_debug("MMU: " fmt, ##__VA_ARGS__)
#define MMU_DEBUG_ADDR(addr, pgd) \
MMU_DEBUG("address=%lx, pgd=%p\n", addr, pgd)
#define MMU_DEBUG_PTE(pte, addr) \
MMU_DEBUG("pte=%lx at %lx\n", pte_val(*pte), addr)
// 详细调试模式
#ifdef CONFIG_MMU_DEBUG
static void mmu_debug_translation(unsigned long va) {
MMU_DEBUG("=== ADDRESS TRANSLATION DEBUG ===\n");
MMU_DEBUG("Virtual address: %lx\n", va);
// 页表遍历调试
pgd_t *pgd = pgd_offset(current->mm, va);
MMU_DEBUG("PGD: %p, value: %lx\n", pgd, pgd_val(*pgd));
if (pgd_present(*pgd)) {
p4d_t *p4d = p4d_offset(pgd, va);
MMU_DEBUG("P4D: %p, value: %lx\n", p4d, p4d_val(*p4d));
if (p4d_present(*p4d)) {
pud_t *pud = pud_offset(p4d, va);
MMU_DEBUG("PUD: %p, value: %lx\n", pud, pud_val(*pud));
if (pud_present(*pud)) {
pmd_t *pmd = pmd_offset(pud, va);
MMU_DEBUG("PMD: %p, value: %lx\n", pmd, pmd_val(*pmd));
if (pmd_present(*pmd)) {
pte_t *pte = pte_offset(pmd, va);
MMU_DEBUG("PTE: %p, value: %lx\n", pte, pte_val(*pte));
if (pte_present(*pte)) {
phys_addr_t pa = pte_pfn(*pte) << PAGE_SHIFT;
MMU_DEBUG("Physical address: %lx\n", pa);
}
}
}
}
}
MMU_DEBUG("=== END ADDRESS TRANSLATION DEBUG ===\n");
}
#endif
11.2 错误检测和恢复
MMU错误处理:
c
// MMU错误检测
static int mmu_detect_errors(struct mm_struct *mm) {
// 检测页表错误
if (detect_page_table_errors(mm->pgd)) {
MMU_DEBUG("Page table errors detected\n");
return -EFAULT;
}
// 检测TLB一致性
if (detect_tlb_inconsistencies(mm)) {
MMU_DEBUG("TLB inconsistencies detected\n");
return -EFAULT;
}
// 检测ASID冲突
if (detect_asid_conflicts(mm->asid)) {
MMU_DEBUG("ASID conflicts detected\n");
return -EINVAL;
}
return 0;
}
// 错误恢复机制
static int mmu_recover_from_errors(struct mm_struct *mm, int error) {
MMU_DEBUG("Attempting MMU error recovery: %d\n", error);
switch (error) {
case -EFAULT:
// 页表错误:重建页表
return rebuild_page_tables(mm);
case -EINVAL:
// ASID错误:重新分配ASID
return reallocate_asid(mm);
default:
MMU_DEBUG("Unrecoverable MMU error\n");
return error;
}
}
// 页表重建
static int rebuild_page_tables(struct mm_struct *mm) {
// 释放旧页表
pgd_free(mm, mm->pgd);
// 分配新页表
mm->pgd = pgd_alloc(mm);
if (!mm->pgd) {
return -ENOMEM;
}
// 重新建立关键映射
return reestablish_critical_mappings(mm);
}
12. 总结
ARM64 mm mmu子模块作为ARM64内存管理子系统中MMU管理的核心组件,通过完整的页表创建、地址映射和MMU上下文管理的功能,为ARM64平台提供了高效可靠的地址转换和内存访问控制。该模块实现了多级页表的创建和维护、虚拟地址到物理地址的映射关系、页表项的权限控制和属性设置,通过精心设计的页表结构和地址转换算法,在保证内存访问安全性的同时实现了接近硬件极限的地址转换性能。源码分析显示,模块采用了工厂模式、策略模式和组合模式等多种设计模式,为MMU管理提供了灵活高效的实现框架。