文章目录
- [1. 概述](#1. 概述)
- [2. 软件架构图](#2. 软件架构图)
- [3. 调用流程图](#3. 调用流程图)
- [4. UML类图](#4. UML类图)
- [5. 源码深度分析](#5. 源码深度分析)
-
- [5.1 ARM64大页管理架构分析](#5.1 ARM64大页管理架构分析)
-
- [5.1.1 HugeTLB页面系统](#5.1.1 HugeTLB页面系统)
- [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 大页访问优化](#5.3.2 大页访问优化)
- [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 大页调试支持](#11.1 大页调试支持)
- [11.2 错误检测和恢复](#11.2 错误检测和恢复)
- [12. 总结](#12. 总结)
团队博客: 汽车电子社区
1. 概述
ARM64 mm hugetlbpage子模块是Linux内核ARM64架构内存管理子系统中实现大页管理的核心组件,包含hugetlbpage.c文件。该模块作为ARM64平台大页内存管理的关键实现,提供了完整的HugeTLB页面和透明大页(THP)的创建、分配和管理功能,是ARM64内存管理性能优化的重要组成部分。
hugetlbpage子模块实现了Linux大页内存系统的核心机制,包括预分配大页池的管理、大页的页表建立、透明大页的自动合并和拆分等高级功能。该模块作为内存性能优化的核心,为高性能计算、数据库、大数据处理等应用提供了高效的内存访问支持,是现代服务器和数据中心的关键技术。
模块的设计体现了大页管理的复杂性和高性能要求,通过精心设计的页面合并算法和页表优化机制,在减少TLB压力和页表开销的同时保证了内存访问的效率,是ARM64内存子系统性能优化的典范。
2. 软件架构图
ARM64 mm hugetlbpage
大页管理
透明大页
HugeTLB页面
页表优化
hugetlbpage.c
大页分配器
页面合并
页面拆分
自动合并
内存紧缩
后台扫描
预分配池
hugetlbfs
共享内存
多级页表
TLB优化
缓存效率
3. 调用流程图
是
否
是
否
应用程序请求大页
检查大页池状态
预分配大页可用?
分配大页
动态分配大页
建立大页映射
更新页表
返回大页地址
应用程序使用
需要释放?
释放大页
回收到大页池
4. UML类图
HugePageManager
+alloc_huge_page()
+free_huge_page()
+hugetlb_fault()
+hugetlb_no_page()
+hugetlb_wp()
TransparentHugePage
+khugepaged()
+collapse_huge_page()
+split_huge_page()
+__split_huge_page()
+can_change_pmd_writable()
HugeTLBPool
+hugetlb_reserve_pages()
+hugetlb_unreserve_pages()
+gather_bootmem_huge_pages()
+alloc_bootmem_huge_page()
PageTableManager
+set_huge_pte_at()
+huge_pte_alloc()
+huge_pte_offset()
+follow_huge_pmd()
MemoryCompaction
+khugepaged_scan_mm_slot()
+khugepaged_scan_file()
+khugepaged_do_scan()
+compact_page()
HugePageFileSystem
+hugetlbfs_file_mmap()
+hugetlb_file_setup()
+hugetlb_vmtruncate()
+hugetlb_change_protection()
5. 源码深度分析
5.1 ARM64大页管理架构分析
5.1.1 HugeTLB页面系统
HugeTLB页面的核心实现:
c
// HugeTLB页面大小定义
#define HPAGE_SHIFT 21 // 2MB大页
#define HPAGE_SIZE (1UL << HPAGE_SHIFT)
// ARM64支持的大页大小
#ifdef CONFIG_ARM64_4K_PAGES
#define HUGETLB_PAGE_ORDER (HPAGE_SHIFT - PAGE_SHIFT) // 512个4K页面
#endif
#ifdef CONFIG_ARM64_16K_PAGES
#define HUGETLB_PAGE_ORDER (HPAGE_SHIFT - PAGE_SHIFT) // 128个16K页面
#endif
#ifdef CONFIG_ARM64_64K_PAGES
#define HUGETLB_PAGE_ORDER (HPAGE_SHIFT - PAGE_SHIFT) // 32个64K页面
#endif
// HugeTLB页面分配
struct page *alloc_huge_page(struct vm_area_struct *vma,
unsigned long addr, int avoid_reserve)
{
struct hstate *h = hstate_vma(vma);
struct page *page;
// 检查是否可以分配大页
if (!alloc_huge_page_noerr(h, vma, addr, avoid_reserve, &page))
return NULL;
// 初始化页面
prep_new_huge_page(h, page, addr);
// 设置页面属性
set_page_huge_active(page);
return page;
}
// HugeTLB页面释放
void free_huge_page(struct page *page)
{
struct hstate *h = page_hstate(page);
int nid = page_to_nid(page);
// 清除大页标记
clear_page_huge_active(page);
// 释放到伙伴系统或大页池
if (hstate_is_gigantic(h))
free_gigantic_page(page, huge_page_order(h));
else
__free_pages(page, huge_page_order(h));
// 更新统计信息
h->nr_huge_pages--;
h->free_huge_pages++;
}
// HugeTLB页面错误处理
vm_fault_t hugetlb_fault(struct mm_struct *mm, struct vm_area_struct *vma,
unsigned long address, unsigned int flags)
{
pte_t *ptep;
pte_t entry;
spinlock_t *ptl;
vm_fault_t ret;
// 获取PTE
ptep = huge_pte_offset(mm, address, huge_page_size(hstate_vma(vma)));
if (!ptep)
return VM_FAULT_SIGBUS;
// 获取锁
ptl = huge_pte_lockptr(hstate_vma(vma), mm, ptep);
spin_lock(ptl);
// 检查PTE是否已存在
entry = huge_ptep_get(ptep);
if (pte_present(entry)) {
// 页面已存在
ret = hugetlb_wp(mm, vma, address, ptep, flags);
} else {
// 页面不存在
ret = hugetlb_no_page(mm, vma, address, ptep, flags);
}
spin_unlock(ptl);
return ret;
}
HugeTLB特点:
1. 预分配机制 :预先分配大页池避免运行时分配延迟
2. 固定大小 :支持多种标准大页大小(2MB、1GB等)
3. 专用文件系统 :hugetlbfs提供大页文件的支持
4. 共享支持:支持进程间的大页共享
5.1.2 透明大页系统
透明大页(THP)的核心实现:
c
// 透明大页合并守护进程
static int khugepaged(void *none)
{
struct mm_slot *mm_slot;
while (!kthread_should_stop()) {
// 扫描内存区域
mm_slot = khugepaged_scan_mm_slot();
if (mm_slot) {
// 处理扫描到的内存区域
khugepaged_scan_mm_slot(mm_slot);
// 尝试合并页面
if (khugepaged_should_run(mm_slot->mm)) {
khugepaged_do_scan(mm_slot);
}
// 释放锁
khugepaged_release_mm_slot(mm_slot);
}
// 等待下一次扫描
wait_event_freezable(khugepaged_wait,
khugepaged_should_wakeup());
// 扫描间隔
if (!khugepaged_should_wakeup())
schedule_timeout_interruptible(khugepaged_sleep_millisecs * HZ / 1000);
}
return 0;
}
// 页面合并函数
int collapse_huge_page(struct mm_struct *mm, unsigned long address,
int referenced, int mapcount)
{
pmd_t *pmd;
pte_t *pte;
struct page *hpage;
struct vm_area_struct *vma;
spinlock_t *ptl;
int ret = 0;
// 获取VMA
vma = find_vma(mm, address);
if (!vma)
return -EFAULT;
// 检查是否可以合并
if (!can_change_pmd_writable(mm, address, pte))
return -EINVAL;
// 分配大页
hpage = alloc_huge_zero_page();
if (!hpage)
return -ENOMEM;
// 获取锁
ptl = pmd_lock(mm, pmd);
// 再次验证条件
if (!can_change_pmd_writable(mm, address, pte)) {
ret = -EINVAL;
goto out;
}
// 复制页面内容
ret = copy_page_content(hpage, address, mm);
if (ret)
goto out;
// 更新页表
ret = set_huge_pmd(vma, address, pmd, hpage);
if (ret)
goto out;
// 更新统计信息
count_vm_event(THP_COLLAPSE_ALLOC);
out:
spin_unlock(ptl);
if (ret)
put_page(hpage);
return ret;
}
// 页面拆分函数
void __split_huge_page(struct page *page, struct list_head *list,
unsigned long flags)
{
struct page *head = compound_head(page);
struct lruvec *lruvec;
struct address_space *swap_cache = NULL;
unsigned long offset = 0;
int i;
// 锁定页面
VM_BUG_ON_PAGE(!PageLocked(head), head);
VM_BUG_ON_PAGE(!PageCompound(head), head);
// 准备拆分
if (!list_empty(list)) {
split_page_prepare(head, list);
}
// 拆分页面
for (i = HPAGE_PMD_NR - 1; i >= 1; i--) {
__split_huge_page_tail(head, i, lruvec, list);
}
// 清除复合页面标志
ClearPageCompound(head);
// 更新页面计数
if (PageAnon(head)) {
// 匿名页面
if (unlikely(PageSwapCache(head))) {
swp_entry_t entry = { .val = page_private(head) };
swap_cache = swap_address_space(entry);
}
}
// 释放尾页
__split_huge_page_refcount(head, list);
// 完成拆分
split_page_owner(head, HPAGE_PMD_NR);
}
透明大页特点:
1. 自动合并 :khugepaged守护进程自动合并页面
2. 透明性 :应用程序无需修改即可使用大页
3. 动态拆分 :内存压力下自动拆分大页
4. 性能优化:减少TLB未命中和页表遍历开销
5.2 大页分配和管理分析
5.2.1 大页池管理
大页池的分配和管理:
c
// 大页池数据结构
struct hstate {
int order; // 页面顺序
unsigned long mask; // 页面掩码
unsigned long max_huge_pages; // 最大大页数
unsigned long nr_huge_pages; // 当前大页数
unsigned long free_huge_pages; // 空闲大页数
unsigned long resv_huge_pages; // 预留大页数
unsigned long surplus_huge_pages; // 超额大页数
struct list_head hugepage_activelist; // 活动大页列表
struct list_head hugepage_freelist; // 空闲大页列表
struct kobject kobj;
struct kobj_type *ktype;
};
// 大页预留
int hugetlb_reserve_pages(struct inode *inode, long from, long to,
struct vm_area_struct *vma, int acctflags)
{
long ret = 0;
struct hstate *h = hstate_inode(inode);
struct resv_map *resv_map = inode_resv_map(inode);
// 计算需要的页面数量
long chg = region_chg(&inode->i_mapping->private_list, from, to, &resv_map);
// 检查配额
if (hugetlb_get_quota(inode->i_mapping, chg))
return -ENOSPC;
// 预留页面
ret = hugetlb_acct_memory(h, chg);
if (ret < 0) {
hugetlb_put_quota(inode->i_mapping, chg);
return ret;
}
// 更新预留映射
region_add(&inode->i_mapping->private_list, from, to, &resv_map, from, to);
return 0;
}
// 大页取消预留
void hugetlb_unreserve_pages(struct inode *inode, long offset, long freed)
{
struct hstate *h = hstate_inode(inode);
struct resv_map *resv_map = inode_resv_map(inode);
// 更新预留映射
region_sub(&inode->i_mapping->private_list, offset, freed);
// 释放配额
hugetlb_put_quota(inode->i_mapping, freed);
// 释放内存记账
hugetlb_acct_memory(h, -freed);
}
// 引导时大页收集
static void __init gather_bootmem_huge_pages(struct hstate *h)
{
struct page *page;
int nid;
// 遍历所有节点
for_each_online_node(nid) {
// 收集该节点的大页
for (page = NODE_DATA(nid)->node_mem_map;
page < NODE_DATA(nid)->node_mem_map + NODE_DATA(nid)->node_present_pages;
page += pages_per_huge_page(h)) {
if (PageReserved(page) && page_size(page) == huge_page_size(h)) {
// 找到大页,添加到大页池
enqueue_huge_page(h, page);
h->nr_huge_pages++;
}
}
}
}
大页池特点:
1. 预分配管理 :维护大页的预分配池
2. 配额控制 :用户和组的大页使用配额
3. 预留机制 :保证关键应用的大页供应
4. NUMA感知:支持多节点的大页分配
5.2.2 大页页表管理
大页的页表操作:
c
// 设置大页PTE
void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
pte_t *ptep, pte_t pte)
{
// 验证参数
WARN_ON(!pte_present(pte));
// 设置PTE
if (sizeof(pteval_t) > sizeof(long)) {
// 64位PTE的原子设置
set_pte_atomic(ptep, pte);
} else {
*ptep = pte;
}
// 更新MMU缓存
update_mmu_cache(mm, addr, ptep);
}
// 大页PTE分配
pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr,
unsigned long sz)
{
pgd_t *pgd;
p4d_t *p4d;
pud_t *pud;
pmd_t *pmd;
pte_t *pte = NULL;
// 遍历页表层次
pgd = pgd_offset(mm, addr);
if (!pgd_present(*pgd))
return NULL;
p4d = p4d_offset(pgd, addr);
if (!p4d_present(*p4d))
return NULL;
pud = pud_offset(p4d, addr);
if (!pud_present(*pud))
return NULL;
pmd = pmd_offset(pud, addr);
if (!pmd_present(*pmd))
return NULL;
// 检查是否为大页
if (pmd_huge(*pmd)) {
// 大页PTE
pte = (pte_t *)pmd;
} else {
// 普通PTE(不应该发生)
return NULL;
}
return pte;
}
// 大页PTE锁定
spinlock_t *huge_pte_lockptr(struct hstate *h, struct mm_struct *mm,
pte_t *pte)
{
// 对于大页,PTE就是PMD,锁定PMD
return pmd_lockptr(mm, (pmd_t *)pte);
}
// 跟随大页PMD
struct page *follow_huge_pmd(struct mm_struct *mm, unsigned long address,
pmd_t *pmd, int flags)
{
struct page *page = NULL;
// 检查PMD是否存在
if (!pmd_present(*pmd))
return NULL;
// 检查是否为大页
if (!pmd_huge(*pmd))
return NULL;
// 获取页面
page = pmd_page(*pmd);
// 检查页面引用
if (flags & FOLL_GET) {
if (!get_page_unless_zero(page))
return NULL;
}
return page;
}
大页页表特点:
1. 多级优化 :大页在PMD级别的直接映射
2. 原子操作 :大页PTE的原子设置保证一致性
3. 锁定机制 :大页特有的锁定策略
4. 跟随函数:大页的页面跟随和引用管理
5.3 性能优化技术分析
5.3.1 透明大页优化
透明大页的性能优化:
c
// 内存紧缩扫描
static void khugepaged_scan_mm_slot(unsigned long *hpage_collapse_alloced,
unsigned long *hpage_collapse_written)
{
struct mm_slot *mm_slot;
struct mm_struct *mm;
struct vm_area_struct *vma;
unsigned long addr;
int progress = 0;
// 获取内存区域
mm_slot = khugepaged_scan_mm_slot();
if (!mm_slot)
return;
mm = mm_slot->mm;
// 扫描VMA
for (vma = mm->mmap; vma; vma = vma->vm_next) {
// 检查VMA是否适合合并
if (!khugepaged_scan_abort(mm, vma))
continue;
// 扫描地址范围
for (addr = vma->vm_start; addr < vma->vm_end;
addr += HPAGE_SIZE) {
// 检查是否可以合并
if (khugepaged_should_scan(mm, addr, HPAGE_SIZE)) {
// 尝试合并
if (collapse_huge_page(mm, addr, 0, 0) == 0) {
(*hpage_collapse_alloced)++;
}
}
// 检查进度
if (++progress >= khugepaged_max_ptes_scan) {
progress = 0;
if (khugepaged_scan_abort(mm, vma))
break;
}
}
}
// 释放内存区域
khugepaged_release_mm_slot(mm_slot);
}
// 合并条件检查
static int khugepaged_should_scan(struct mm_struct *mm, unsigned long addr,
unsigned long hpage_size)
{
pmd_t *pmd;
pte_t *pte;
spinlock_t *ptl;
int ret = 0;
// 检查是否已是大页
if (pmd_trans_huge(*pmd))
goto out;
// 检查内存策略
if (!khugepaged_scan_abort(mm, find_vma(mm, addr)))
goto out;
// 获取锁
ptl = pmd_lock(mm, pmd);
// 检查页面是否适合合并
if (pmd_present(*pmd) && !pmd_trans_huge(*pmd)) {
// 检查所有PTE
ret = khugepaged_check_pte(pte, hpage_size);
}
spin_unlock(ptl);
out:
return ret;
}
// 页面合并决策
static int khugepaged_check_pte(pte_t *pte, unsigned long hpage_size)
{
int i;
int referenced = 0;
int young = 0;
int mapcount = 0;
// 检查所有子页面
for (i = 0; i < hpage_size / PAGE_SIZE; i++) {
pte_t pteval = pte[i];
// 检查页面是否存在
if (!pte_present(pteval))
return 0;
// 检查是否可写
if (!pte_write(pteval))
return 0;
// 统计引用信息
if (pte_young(pteval))
young++;
if (pte_referenced(pteval))
referenced++;
// 获取页面映射计数
struct page *page = pte_page(pteval);
mapcount = max(mapcount, page_mapcount(page));
}
// 决策是否合并
return (young > khugepaged_max_ptes_none * 2 &&
referenced > khugepaged_max_ptes_none &&
mapcount <= khugepaged_max_ptes_shared);
}
透明大页优化特点:
1. 智能扫描 :khugepaged的智能内存扫描
2. 合并决策 :基于页面访问模式的合并决策
3. 后台处理 :异步的页面合并处理
4. 内存效率:减少页表开销和TLB压力
5.3.2 大页访问优化
大页访问的性能优化:
c
// 大页访问跟踪
void hugepage_access_track(struct page *page, bool accessed)
{
// 标记大页访问
if (accessed) {
SetPageAccessed(page);
// 对于透明大页,设置PMD的访问位
if (PageTransHuge(page)) {
pmd_t *pmd = page_to_pmd(page);
*pmd = pmd_mkaccessed(*pmd);
}
} else {
ClearPageAccessed(page);
if (PageTransHuge(page)) {
pmd_t *pmd = page_to_pmd(page);
*pmd = pmd_mknotaccessed(*pmd);
}
}
}
// 大页写时复制优化
static void hugepage_cow_optimization(struct page *page)
{
// 对于大页的写时复制,尽量保持大页
if (PageTransHuge(page) && PageAnon(page)) {
// 检查是否可以继续使用大页
if (hugepage_cow_possible(page)) {
// 保持大页映射
return;
}
// 需要拆分大页
split_huge_page(page);
}
}
// 大页预取优化
void hugepage_prefetch_optimization(struct vm_area_struct *vma,
unsigned long addr)
{
// 对于顺序访问模式,预取后续大页
if (vma->vm_flags & VM_HUGETLB) {
unsigned long next_addr = addr + huge_page_size(hstate_vma(vma));
// 检查下一个地址是否在VMA范围内
if (next_addr < vma->vm_end) {
// 预取下一个大页
prefetch_huge_page(vma, next_addr);
}
}
}
// 大页交换优化
void hugepage_swap_optimization(struct page *page)
{
// 大页交换时,尽量保持大页的连续性
if (PageTransHuge(page)) {
// 尝试分配连续的交换空间
if (hugepage_swap_contiguous(page)) {
// 成功分配连续交换空间
return;
}
// 拆分大页进行交换
split_huge_page(page);
}
}
大页访问优化特点:
1. 访问跟踪 :大页的访问位管理优化
2. COW优化 :写时复制的大页保持策略
3. 预取机制 :大页访问模式的预取优化
4. 交换优化:大页交换的连续性优化
6. 设计模式分析
6.1 策略模式在大页分配中的体现
大页分配的策略模式:
c
// 大页分配策略接口
interface HugePageAllocationStrategy {
struct page* allocateHugePage(HugePageRequest request);
void freeHugePage(struct page* page);
boolean canAllocate(HugePageRequest request);
String getStrategyName();
long getAllocationLatency();
}
// HugeTLB池分配策略
class HugeTLBPoolStrategy implements HugePageAllocationStrategy {
public struct page* allocateHugePage(HugePageRequest request) {
struct hstate *h = request.getHstate();
// 从预分配池中分配
return dequeue_huge_page_node(h, request.getNid());
}
public void freeHugePage(struct page* page) {
struct hstate *h = page_hstate(page);
// 释放回池中
enqueue_huge_page(h, page);
}
public boolean canAllocate(HugePageRequest request) {
struct hstate *h = request.getHstate();
return h->free_huge_pages > 0;
}
public String getStrategyName() {
return "HUGETLB_POOL";
}
public long getAllocationLatency() {
return 100; // 纳秒级延迟
}
}
// 动态分配策略
class DynamicAllocationStrategy implements HugePageAllocationStrategy {
public struct page* allocateHugePage(HugePageRequest request) {
struct hstate *h = request.getHstate();
int nid = request.getNid();
// 动态分配大页
return alloc_fresh_huge_page(h, nid);
}
public void freeHugePage(struct page* page) {
// 释放到伙伴系统
__free_pages(page, huge_page_order(page_hstate(page)));
}
public boolean canAllocate(HugePageRequest request) {
// 总是可以尝试动态分配
return true;
}
public String getStrategyName() {
return "DYNAMIC_ALLOCATION";
}
public long getAllocationLatency() {
return 10000; // 微秒级延迟(包括内存分配时间)
}
}
// 自适应分配策略
class AdaptiveHugePageStrategy implements HugePageAllocationStrategy {
private List<HugePageAllocationStrategy> strategies;
private AllocationMetrics metrics;
public AdaptiveHugePageStrategy() {
strategies = Arrays.asList(
new HugeTLBPoolStrategy(),
new DynamicAllocationStrategy()
);
metrics = new AllocationMetrics();
}
public struct page* allocateHugePage(HugePageRequest request) {
// 选择最优策略
HugePageAllocationStrategy bestStrategy = selectBestStrategy(request);
long startTime = System.nanoTime();
struct page* result = bestStrategy.allocateHugePage(request);
long allocationTime = System.nanoTime() - startTime;
// 更新统计信息
metrics.recordAllocation(bestStrategy.getStrategyName(),
result != null, allocationTime);
// 重新评估策略
reevaluateStrategies();
return result;
}
public void freeHugePage(struct page* page) {
// 选择释放策略
HugePageAllocationStrategy strategy = determineFreeStrategy(page);
strategy.freeHugePage(page);
metrics.recordFree(strategy.getStrategyName());
}
public boolean canAllocate(HugePageRequest request) {
return strategies.stream().anyMatch(s -> s.canAllocate(request));
}
public String getStrategyName() {
return "ADAPTIVE_HUGEPAGE";
}
public long getAllocationLatency() {
return metrics.getAverageAllocationTime();
}
private HugePageAllocationStrategy selectBestStrategy(HugePageRequest request) {
return strategies.stream()
.filter(s -> s.canAllocate(request))
.min(Comparator.comparingLong(HugePageAllocationStrategy::getAllocationLatency))
.orElse(new DynamicAllocationStrategy());
}
private void reevaluateStrategies() {
// 基于性能数据重新排序策略
strategies.sort(Comparator.comparingLong(HugePageAllocationStrategy::getAllocationLatency));
}
private HugePageAllocationStrategy determineFreeStrategy(struct page* page) {
// 根据页面来源确定释放策略
if (page_from_pool(page)) {
return new HugeTLBPoolStrategy();
} else {
return new DynamicAllocationStrategy();
}
}
}
// 策略选择器
class HugePageStrategySelector {
public static HugePageAllocationStrategy selectStrategy(SystemConfiguration config) {
if (config.supportsAdaptiveAllocation()) {
return new AdaptiveHugePageStrategy();
} else if (config.hasHugeTLBPool()) {
return new HugeTLBPoolStrategy();
} else {
return new DynamicAllocationStrategy();
}
}
}
6.2 观察者模式在大页监控中的体现
大页监控的观察者模式:
c
// 大页事件接口
interface HugePageEvent {
String getEventType();
long getTimestamp();
struct page* getHugePage();
struct hstate* getHstate();
Map<String, Object> getEventData();
boolean isTransparentHugePage();
}
// 大页分配事件
class HugePageAllocationEvent implements HugePageEvent {
private final struct page* page;
private final struct hstate* hstate;
private final boolean transparent;
private final Map<String, Object> eventData;
public HugePageAllocationEvent(struct page* page, struct hstate* hstate,
boolean transparent, Map<String, Object> eventData) {
this.page = page;
this.hstate = hstate;
this.transparent = transparent;
this.eventData = eventData != null ? eventData : new HashMap<>();
}
public String getEventType() {
return "HUGEPAGE_ALLOCATION";
}
public long getTimestamp() {
return System.nanoTime();
}
public struct page* getHugePage() {
return page;
}
public struct hstate* getHstate() {
return hstate;
}
public Map<String, Object> getEventData() {
return eventData;
}
public boolean isTransparentHugePage() {
return transparent;
}
}
// 大页观察者接口
interface HugePageObserver {
void onHugePageEvent(HugePageEvent event);
Set<String> getInterestedEventTypes();
boolean isEnabled();
}
// 性能监控观察者
class HugePagePerformanceObserver implements HugePageObserver {
private Map<String, Long> allocationTimes = new HashMap<>();
private Map<String, Integer> allocationCounts = new HashMap<>();
public void onHugePageEvent(HugePageEvent event) {
if ("HUGEPAGE_ALLOCATION".equals(event.getEventType())) {
String pageType = event.isTransparentHugePage() ? "THP" : "HUGETLB";
// 记录分配时间
Long time = (Long) event.getEventData().get("allocationTime");
if (time != null) {
allocationTimes.put(pageType,
allocationTimes.getOrDefault(pageType, 0L) + time);
}
// 记录分配次数
allocationCounts.put(pageType,
allocationCounts.getOrDefault(pageType, 0) + 1);
}
}
public Set<String> getInterestedEventTypes() {
return new HashSet<>(Arrays.asList("HUGEPAGE_ALLOCATION", "HUGEPAGE_FREE"));
}
public boolean isEnabled() {
return true;
}
public double getAverageAllocationTime(String pageType) {
Long totalTime = allocationTimes.get(pageType);
Integer count = allocationCounts.get(pageType);
if (totalTime != null && count != null && count > 0) {
return totalTime.doubleValue() / count;
}
return 0.0;
}
}
// 内存使用观察者
class HugePageMemoryObserver implements HugePageObserver {
private AtomicLong totalHugePages = new AtomicLong(0);
private Map<String, AtomicLong> typeHugePages = new ConcurrentHashMap<>();
public void onHugePageEvent(HugePageEvent event) {
String pageType = event.isTransparentHugePage() ? "THP" : "HUGETLB";
if ("HUGEPAGE_ALLOCATION".equals(event.getEventType())) {
totalHugePages.incrementAndGet();
typeHugePages.computeIfAbsent(pageType, k -> new AtomicLong(0)).incrementAndGet();
} else if ("HUGEPAGE_FREE".equals(event.getEventType())) {
totalHugePages.decrementAndGet();
AtomicLong typeCount = typeHugePages.get(pageType);
if (typeCount != null) {
typeCount.decrementAndGet();
}
}
}
public Set<String> getInterestedEventTypes() {
return new HashSet<>(Arrays.asList("HUGEPAGE_ALLOCATION", "HUGEPAGE_FREE"));
}
public boolean isEnabled() {
return true;
}
public long getTotalHugePages() {
return totalHugePages.get();
}
public long getHugePagesByType(String type) {
AtomicLong count = typeHugePages.get(type);
return count != null ? count.get() : 0;
}
}
// 透明大页合并观察者
class TransparentHugePageObserver implements HugePageObserver {
private AtomicLong collapseCount = new AtomicLong(0);
private AtomicLong splitCount = new AtomicLong(0);
public void onHugePageEvent(HugePageEvent event) {
if (!event.isTransparentHugePage()) {
return;
}
if ("THP_COLLAPSE".equals(event.getEventType())) {
collapseCount.incrementAndGet();
} else if ("THP_SPLIT".equals(event.getEventType())) {
splitCount.incrementAndGet();
}
}
public Set<String> getInterestedEventTypes() {
return new HashSet<>(Arrays.asList("THP_COLLAPSE", "THP_SPLIT"));
}
public boolean isEnabled() {
return true;
}
public long getCollapseCount() {
return collapseCount.get();
}
public long getSplitCount() {
return splitCount.get();
}
public double getCollapseRatio() {
long total = collapseCount.get() + splitCount.get();
return total > 0 ? (double) collapseCount.get() / total : 0.0;
}
}
// 大页监控器
class HugePageMonitor {
private List<HugePageObserver> observers = new CopyOnWriteArrayList<>();
private Executor notificationExecutor;
public HugePageMonitor() {
this.notificationExecutor = Executors.newSingleThreadExecutor();
}
public void addObserver(HugePageObserver observer) {
observers.add(observer);
}
public void removeObserver(HugePageObserver observer) {
observers.remove(observer);
}
public void notifyHugePageEvent(HugePageEvent event) {
notificationExecutor.submit(() -> {
for (HugePageObserver observer : observers) {
if (observer.isEnabled()) {
Set<String> interestedTypes = observer.getInterestedEventTypes();
if (interestedTypes.contains(event.getEventType()) ||
interestedTypes.contains("*")) {
try {
observer.onHugePageEvent(event);
} catch (Exception e) {
logObserverError(observer, event, e);
}
}
}
}
});
}
public void hugePageAllocated(struct page* page, struct hstate* hstate,
boolean transparent, Map<String, Object> eventData) {
HugePageEvent event = new HugePageAllocationEvent(page, hstate, transparent, eventData);
notifyHugePageEvent(event);
}
public void hugePageFreed(struct page* page, struct hstate* hstate,
boolean transparent, Map<String, Object> eventData) {
HugePageEvent event = new HugePageFreedEvent(page, hstate, transparent, eventData);
notifyHugePageEvent(event);
}
public void transparentHugePageCollapsed(unsigned long address, struct mm_struct* mm) {
Map<String, Object> eventData = new HashMap<>();
eventData.put("address", address);
eventData.put("mm", mm);
HugePageEvent event = new TransparentHugePageEvent("THP_COLLAPSE",
null, null, true, eventData);
notifyHugePageEvent(event);
}
public void transparentHugePageSplit(struct page* page) {
Map<String, Object> eventData = new HashMap<>();
eventData.put("page", page);
HugePageEvent event = new TransparentHugePageEvent("THP_SPLIT",
page, null, true, eventData);
notifyHugePageEvent(event);
}
public void shutdown() {
notificationExecutor.shutdown();
try {
if (!notificationExecutor.awaitTermination(5, TimeUnit.SECONDS)) {
notificationExecutor.shutdownNow();
}
} catch (InterruptedException e) {
notificationExecutor.shutdownNow();
}
}
private void logObserverError(HugePageObserver observer, HugePageEvent event, Exception e) {
System.err.println("HugePage observer error: " + observer.getClass().getSimpleName() +
" failed to process event " + event.getEventType() + ": " + e.getMessage());
}
}
// 使用观察者模式
class HugePageSubsystem {
private HugePageMonitor monitor;
public HugePageSubsystem() {
this.monitor = new HugePageMonitor();
// 注册观察者
monitor.addObserver(new HugePagePerformanceObserver());
monitor.addObserver(new HugePageMemoryObserver());
monitor.addObserver(new TransparentHugePageObserver());
}
public struct page* allocateHugePage(HugePageRequest request) {
long startTime = System.nanoTime();
// 执行分配
struct page* page = performHugePageAllocation(request);
long allocationTime = System.nanoTime() - startTime;
// 通知分配事件
Map<String, Object> eventData = new HashMap<>();
eventData.put("allocationTime", allocationTime);
eventData.put("request", request);
monitor.hugePageAllocated(page, request.getHstate(),
request.isTransparent(), eventData);
return page;
}
public void freeHugePage(struct page* page) {
struct hstate* hstate = page_hstate(page);
boolean transparent = PageTransHuge(page);
// 执行释放
performHugePageFree(page);
// 通知释放事件
Map<String, Object> eventData = new HashMap<>();
eventData.put("freeTime", System.nanoTime());
monitor.hugePageFreed(page, hstate, transparent, eventData);
}
public void collapseTransparentHugePage(unsigned long address, struct mm_struct* mm) {
// 执行合并
if (collapse_huge_page(mm, address, 0, 0) == 0) {
monitor.transparentHugePageCollapsed(address, mm);
}
}
public void splitTransparentHugePage(struct page* page) {
// 执行拆分
split_huge_page(page);
monitor.transparentHugePageSplit(page);
}
private struct page* performHugePageAllocation(HugePageRequest request) {
// 实际的分配逻辑实现
if (request.isTransparent()) {
return alloc_huge_zero_page();
} else {
return alloc_huge_page(request.getVma(), request.getAddr(), 0);
}
}
private void performHugePageFree(struct page* page) {
// 实际的释放逻辑实现
if (PageTransHuge(page)) {
__split_huge_page(page, NULL, 0);
} else {
free_huge_page(page);
}
}
}
6.3 模板方法模式在大页初始化中的体现
大页初始化的模板方法模式:
c
// 大页初始化模板类
abstract class HugePageInitializationTemplate {
// 模板方法:执行完整的大页初始化
public final void initializeHugePages() {
// 1. 准备初始化环境
prepareInitializationEnvironment();
// 2. 初始化大页状态
initializeHugePageStates();
// 3. 配置大页参数
configureHugePageParameters();
// 4. 初始化大页池
initializeHugePagePools();
// 5. 设置大页文件系统
setupHugePageFileSystem();
// 6. 初始化透明大页
initializeTransparentHugePages();
// 7. 启动大页服务
startHugePageServices();
// 8. 验证初始化结果
validateInitialization();
// 9. 完成初始化
finalizeInitialization();
}
// 抽象方法:由子类实现
protected abstract void prepareInitializationEnvironment();
protected abstract void initializeHugePageStates();
protected abstract void configureHugePageParameters();
protected abstract void initializeHugePagePools();
protected abstract void setupHugePageFileSystem();
protected abstract void initializeTransparentHugePages();
protected abstract void startHugePageServices();
protected abstract void validateInitialization();
protected abstract void finalizeInitialization();
// 钩子方法:可由子类重写
protected void preInitializationHook() {
// 默认空实现
}
protected void postInitializationHook() {
// 默认空实现
}
protected boolean shouldSkipStep(String step) {
return false; // 默认执行所有步骤
}
protected void handleInitializationError(String step, Exception error) {
// 默认错误处理
throw new InitializationException("Failed to initialize " + step, error);
}
}
// ARM64大页初始化实现
class Arm64HugePageInitialization extends HugePageInitializationTemplate {
protected void prepareInitializationEnvironment() {
// ARM64特定的环境准备
validateArm64HugePageSupport();
setupEarlyHugePageParameters();
reserveHugePageBootMemory();
initializeHugePageSysctl();
}
protected void initializeHugePageStates() {
// 初始化大页状态结构
for (int i = 0; i < HUGE_MAX_HSTATE; i++) {
struct hstate *h = &hstates[i];
// 计算页面大小
h->order = huge_page_order(i);
h->mask = (1UL << h->order) - 1;
// 初始化列表
INIT_LIST_HEAD(&h->hugepage_activelist);
INIT_LIST_HEAD(&h->hugepage_freelist);
// 设置最大页面数
h->max_huge_pages = default_hugepages[i];
}
}
protected void configureHugePageParameters() {
// 配置大页参数
configureHugePageSizes();
setupHugePageSysfs();
initializeHugePageTunables();
configureHugePageCgroup();
}
protected void initializeHugePagePools() {
// 初始化大页池
for (int i = 0; i < HUGE_MAX_HSTATE; i++) {
struct hstate *h = &hstates[i];
// 收集引导时大页
gather_bootmem_huge_pages(h);
// 初始化剩余页面
hugetlb_init_hstate(h);
// 设置页面分配器
hugetlb_register_node(h);
}
}
protected void setupHugePageFileSystem() {
// 设置大页文件系统
register_filesystem(&hugetlbfs_fs_type);
hugetlbfs_init();
setupHugetlbfsSysctls();
}
protected void initializeTransparentHugePages() {
// 初始化透明大页
setup_transparent_hugepage();
khugepaged_init();
madvise_init();
khugepaged_fork_init();
}
protected void startHugePageServices() {
// 启动大页服务
start_khugepaged();
hugepage_migration_init();
register_hugepage_migration_notifier();
}
protected void validateInitialization() {
// 验证初始化
validate_hugepage_states();
test_hugepage_allocation();
verify_hugepage_filesystem();
check_transparent_hugepage_setup();
}
protected void finalizeInitialization() {
// 完成初始化
update_bootmem_stats();
print_hugepage_info();
enable_hugepage_features();
cleanup_initialization_resources();
}
// ARM64特定的辅助方法
private void validateArm64HugePageSupport() {
// 验证ARM64大页支持
if (!IS_ENABLED(CONFIG_ARM64_4K_PAGES) &&
!IS_ENABLED(CONFIG_ARM64_16K_PAGES) &&
!IS_ENABLED(CONFIG_ARM64_64K_PAGES)) {
panic("No page size configuration for ARM64");
}
}
private void setupEarlyHugePageParameters() {
// 设置早期大页参数
default_hugepages[HUGE_STD_HSTATE] = CONFIG_NR_HUGEPAGES;
if (IS_ENABLED(CONFIG_TRANSPARENT_HUGEPAGE)) {
default_hugepages[HUGE_STD_HSTATE] += CONFIG_TRANSPARENT_HUGEPAGE_NR_HUGEPAGES;
}
}
private void reserveHugePageBootMemory() {
// 保留引导时大页内存
for (int i = 0; i < HUGE_MAX_HSTATE; i++) {
unsigned long size = default_hugepages[i] * huge_page_size(&hstates[i]);
if (size > 0) {
reserve_bootmem_generic(size, huge_page_size(&hstates[i]));
}
}
}
private void initializeHugePageSysctl() {
// 初始化大页sysctl
register_hugetlbfs_sysctl();
setup_hugepage_sysctls();
}
private void configureHugePageSizes() {
// 配置大页大小
for (int i = 0; i < HUGE_MAX_HSTATE; i++) {
struct hstate *h = &hstates[i];
h->order = huge_page_order(i);
h->mask = (1UL << h->order) - 1;
}
}
private void setupHugePageSysfs() {
// 设置大页sysfs
for (int i = 0; i < HUGE_MAX_HSTATE; i++) {
struct hstate *h = &hstates[i];
hugetlb_sysfs_add_hstate(h);
}
}
private void initializeHugePageTunables() {
// 初始化大页可调参数
khugepaged_max_ptes_none = HPAGE_PMD_NR;
khugepaged_max_ptes_swap = HPAGE_PMD_NR / 8;
khugepaged_max_ptes_shared = HPAGE_PMD_NR / 2;
}
private void configureHugePageCgroup() {
// 配置大页cgroup
hugetlb_cgroup_file_init();
register_hugetlb_cgroups();
}
private void gather_bootmem_huge_pages(struct hstate *h) {
// 收集引导时大页
gather_bootmem_huge_pages(h);
}
private void hugetlb_init_hstate(struct hstate *h) {
// 初始化大页状态
hugetlb_init_hstate(h);
}
private void hugetlb_register_node(struct hstate *h) {
// 注册大页节点
hugetlb_register_node(h);
}
private void register_filesystem(struct file_system_type *fs) {
// 注册文件系统
register_filesystem(fs);
}
private void hugetlbfs_init() {
// 初始化hugetlbfs
hugetlbfs_init();
}
private void setupHugetlbfsSysctls() {
// 设置hugetlbfs sysctls
hugetlbfs_register_sysctls();
}
private void setup_transparent_hugepage() {
// 设置透明大页
hugepage_init();
khugepaged_tunables_init();
}
private void khugepaged_init() {
// 初始化khugepaged
khugepaged_init();
}
private void madvise_init() {
// 初始化madvise
madvise_init();
}
private void khugepaged_fork_init() {
// 初始化khugepaged fork
khugepaged_fork_init();
}
private void start_khugepaged() {
// 启动khugepaged
start_khugepaged();
}
private void hugepage_migration_init() {
// 初始化大页迁移
hugepage_migration_init();
}
private void register_hugepage_migration_notifier() {
// 注册大页迁移通知器
register_hugepage_migration_notifier();
}
private void validate_hugepage_states() {
// 验证大页状态
for (int i = 0; i < HUGE_MAX_HSTATE; i++) {
struct hstate *h = &hstates[i];
if (h->nr_huge_pages < 0 || h->free_huge_pages < 0) {
panic("Invalid hugepage state for hstate %d", i);
}
}
}
private void test_hugepage_allocation() {
// 测试大页分配
for (int i = 0; i < HUGE_MAX_HSTATE; i++) {
struct hstate *h = &hstates[i];
struct page *page = alloc_huge_page(NULL, 0, 0);
if (page) {
free_huge_page(page);
} else {
pr_warn("Failed to allocate hugepage for hstate %d", i);
}
}
}
private void verify_hugepage_filesystem() {
// 验证大页文件系统
struct file_system_type *fs = get_fs_type("hugetlbfs");
if (!fs) {
panic("hugetlbfs not registered");
}
}
private void check_transparent_hugepage_setup() {
// 检查透明大页设置
if (khugepaged_thread == NULL) {
pr_warn("khugepaged not started");
}
}
private void update_bootmem_stats() {
// 更新引导内存统计
update_bootmem_stats();
}
private void print_hugepage_info() {
// 打印大页信息
report_hugepages();
}
private void enable_hugepage_features() {
// 启用大页功能
enable_transparent_huge_pages();
enable_hugepage_migration();
}
private void cleanup_initialization_resources() {
// 清理初始化资源
free_bootmem_huge_pages();
cleanup_hugepage_init_structures();
}
}
7. 状态机分析
ARM64 mm hugetlbpage的状态机:
初始状态 -> 大页请求 -> 池检查 -> 动态分配 -> 页表映射 -> TLB更新 -> 大页就绪
↑ ↓
合并检查 <---------------------------------------------------------------------------------+
↑ ↓
拆分处理 <---------------------------------------------------------------------------------+
↑ ↓
释放回收 <---------------------------------------------------------------------------------+
8. 性能优化分析
8.1 大页分配优化
大页分配的性能优化:
c
// 大页快速分配路径
struct page *fast_alloc_huge_page(struct hstate *h, int nid)
{
struct page *page = NULL;
// 尝试从本地节点分配
if (nid != NUMA_NO_NODE) {
page = dequeue_huge_page_node(h, nid);
if (page)
return page;
}
// 尝试从其他节点分配
page = dequeue_huge_page_nodemask(h, node_online_map);
if (page)
return page;
// 最后尝试动态分配
return alloc_fresh_huge_page(h, nid);
}
// 大页预取优化
void huge_page_prefetch(struct vm_area_struct *vma, unsigned long addr)
{
struct hstate *h = hstate_vma(vma);
unsigned long next_addr = addr + huge_page_size(h);
// 检查是否需要预取
if (next_addr < vma->vm_end) {
// 预先分配下一个大页
struct page *page = alloc_huge_page(vma, next_addr, 1);
if (page) {
// 放入预取缓存
prefetch_cache_add(page);
}
}
}
// 大页缓存优化
struct page *alloc_huge_page_cached(struct vm_area_struct *vma, unsigned long addr)
{
struct hstate *h = hstate_vma(vma);
struct page *page;
// 检查预取缓存
page = prefetch_cache_get(h);
if (page)
return page;
// 正常分配
return alloc_huge_page(vma, addr, 0);
}
8.2 透明大页性能优化
透明大页的性能优化:
c
// 透明大页合并优化
int optimized_collapse_huge_page(struct mm_struct *mm, unsigned long address)
{
pmd_t *pmd;
struct page *page;
int result;
// 快速检查条件
if (!can_collapse_huge_page_fast(mm, address))
return -EINVAL;
// 预锁页面
if (!trylock_page_collapse(mm, address))
return -EBUSY;
// 执行合并
result = __collapse_huge_page(mm, address);
// 解锁页面
unlock_page_collapse(mm, address);
return result;
}
// 大页访问优化
void huge_page_access_optimize(struct vm_area_struct *vma, unsigned long addr)
{
// 对于顺序访问,预取后续大页
if (is_sequential_access(vma, addr)) {
prefetch_next_huge_page(vma, addr);
}
// 对于随机访问,保持大页以减少TLB压力
if (is_random_access(vma, addr)) {
avoid_splitting_huge_page(vma, addr);
}
}
// 大页内存紧缩优化
void optimized_memory_compaction(struct mm_struct *mm)
{
// 识别大页合并机会
identify_compaction_opportunities(mm);
// 批量合并大页
batch_collapse_huge_pages(mm);
// 优化大页布局
optimize_huge_page_layout(mm);
}
9. 安全性考虑
9.1 大页访问控制
大页访问控制的安全性:
c
// 大页权限验证
int validate_huge_page_access(struct vm_area_struct *vma, unsigned long addr,
unsigned int flags)
{
struct hstate *h = hstate_vma(vma);
// 检查基本权限
if ((flags & FAULT_FLAG_WRITE) && !(vma->vm_flags & VM_WRITE))
return VM_FAULT_SIGSEGV;
// 检查大页特定的权限
if (!huge_page_permission_check(vma, addr, flags))
return VM_FAULT_SIGSEGV;
// 验证地址范围
if (!huge_page_address_valid(vma, addr))
return VM_FAULT_SIGBUS;
return 0;
}
// 大页地址验证
bool huge_page_address_valid(struct vm_area_struct *vma, unsigned long addr)
{
struct hstate *h = hstate_vma(vma);
unsigned long hpage_size = huge_page_size(h);
// 检查地址对齐
if (addr & (hpage_size - 1))
return false;
// 检查VMA范围
if (addr < vma->vm_start || addr + hpage_size > vma->vm_end)
return false;
return true;
}
// 大页权限检查
bool huge_page_permission_check(struct vm_area_struct *vma, unsigned long addr,
unsigned int flags)
{
// 对于大页,需要检查所有子页面的权限
// 简化实现:假设大页权限一致
return true;
}
9.2 透明大页安全防护
透明大页的安全防护:
c
// 透明大页安全检查
int transparent_huge_page_security_check(struct mm_struct *mm, unsigned long addr)
{
// 检查地址空间安全
if (!address_space_secure(mm, addr))
return -EACCES;
// 验证页面内容安全
if (!page_content_secure(mm, addr))
return -EACCES;
// 检查合并操作的安全性
if (!collapse_operation_secure(mm, addr))
return -EACCES;
return 0;
}
// 地址空间安全验证
bool address_space_secure(struct mm_struct *mm, unsigned long addr)
{
// 检查是否跨越安全边界
if (crosses_security_boundary(mm, addr))
return false;
// 验证地址空间布局
if (!validate_address_space_layout(mm))
return false;
return true;
}
// 页面内容安全验证
bool page_content_secure(struct mm_struct *mm, unsigned long addr)
{
// 检查页面是否包含敏感数据
if (contains_sensitive_data(mm, addr))
return false;
// 验证页面完整性
if (!verify_page_integrity(mm, addr))
return false;
return true;
}
// 合并操作安全检查
bool collapse_operation_secure(struct mm_struct *mm, unsigned long addr)
{
// 检查合并是否会破坏安全隔离
if (would_break_security_isolation(mm, addr))
return false;
// 验证合并后的权限一致性
if (!permissions_consistent_after_collapse(mm, addr))
return false;
return true;
}
10. 扩展性分析
10.1 多架构支持
跨架构的大页扩展:
c
// 架构特定的大页操作接口
struct arch_huge_page_ops {
const char *arch_name;
// 大页分配
struct page *(*alloc_huge_page)(struct hstate *h, int nid);
void (*free_huge_page)(struct page *page);
// 页表操作
void (*set_huge_pte_at)(struct mm_struct *mm, unsigned long addr,
pte_t *ptep, pte_t pte);
pte_t *(*huge_pte_alloc)(struct mm_struct *mm, unsigned long addr,
unsigned long sz);
// TLB管理
void (*flush_huge_tlb)(struct vm_area_struct *vma, unsigned long addr);
void (*update_huge_mmu_cache)(struct vm_area_struct *vma, unsigned long addr,
struct page *page);
};
// ARM64大页操作实现
static const struct arch_huge_page_ops arm64_huge_page_ops = {
.arch_name = "arm64",
.alloc_huge_page = arm64_alloc_huge_page,
.free_huge_page = arm64_free_huge_page,
.set_huge_pte_at = arm64_set_huge_pte_at,
.huge_pte_alloc = arm64_huge_pte_alloc,
.flush_huge_tlb = arm64_flush_huge_tlb,
.update_huge_mmu_cache = arm64_update_huge_mmu_cache,
};
// 运行时架构选择
static const struct arch_huge_page_ops *select_arch_huge_page_ops(void)
{
#ifdef CONFIG_ARM64
return &arm64_huge_page_ops;
#else
return NULL;
#endif
}
10.2 功能扩展
大页功能扩展能力:
c
// 高级大页功能扩展
struct advanced_huge_page_features {
bool support_1gb_huge_pages; // 支持1GB大页
bool support_dynamic_huge_pages; // 支持动态大页
bool support_huge_page_migration; // 支持大页迁移
bool support_huge_page_compaction; // 支持大页紧缩
bool support_huge_page_pooling; // 支持大页池化
};
// 大页扩展API
struct extended_huge_page_api {
// 1GB大页支持
int (*alloc_1gb_huge_page)(struct hstate *h, int nid);
void (*free_1gb_huge_page)(struct page *page);
// 动态大页
int (*create_dynamic_huge_page)(size_t size);
int (*destroy_dynamic_huge_page)(struct page *page);
// 大页迁移
int (*migrate_huge_page)(struct page *page, int dest_nid);
int (*huge_page_migration_supported)(struct page *page);
// 大页紧缩
int (*compact_huge_pages)(struct mm_struct *mm);
int (*huge_page_compaction_suitable)(struct mm_struct *mm);
// 大页池化
int (*create_huge_page_pool)(size_t pool_size);
int (*destroy_huge_page_pool)(int pool_id);
struct page *(*alloc_from_pool)(int pool_id);
};
11. 调试和维护
11.1 大页调试支持
大页调试支持:
c
// 大页调试宏
#define HUGEPAGE_DEBUG(fmt, ...) \
pr_debug("HUGEPAGE: " fmt, ##__VA_ARGS__)
#define HUGEPAGE_DEBUG_ALLOC(page, h) \
HUGEPAGE_DEBUG("allocated hugepage %p from hstate %p\n", page, h)
#define HUGEPAGE_DEBUG_FREE(page) \
HUGEPAGE_DEBUG("freed hugepage %p\n", page)
// 详细调试模式
#ifdef CONFIG_HUGEPAGE_DEBUG
static void hugepage_debug_allocation(struct page *page, struct hstate *h)
{
HUGEPAGE_DEBUG("=== HUGEPAGE ALLOCATION DEBUG ===");
HUGEPAGE_DEBUG("Page: %p", page);
HUGEPAGE_DEBUG("Hstate: %p", h);
HUGEPAGE_DEBUG("Order: %d", h->order);
HUGEPAGE_DEBUG("Size: %lu KB", huge_page_size(h) >> 10);
// 调试页表设置
debug_hugepage_pagetable(page);
// 调试NUMA信息
debug_hugepage_numa(page);
HUGEPAGE_DEBUG("=== END HUGEPAGE ALLOCATION DEBUG ===");
}
#endif
11.2 错误检测和恢复
大页错误处理:
c
// 大页错误检测
int detect_hugepage_errors(struct hstate *h)
{
// 检测大页池状态
if (h->nr_huge_pages < 0 || h->free_huge_pages < 0)
return -EINVAL;
// 检测列表一致性
if (!list_consistent(&h->hugepage_freelist))
return -EFAULT;
// 检测页面状态
if (!validate_hugepage_pages(h))
return -EFAULT;
return 0;
}
// 错误恢复机制
int recover_hugepage_errors(struct hstate *h, int error)
{
HUGEPAGE_DEBUG("Attempting hugepage error recovery: %d\n", error);
switch (error) {
case -EINVAL:
// 状态错误:重新计算统计信息
return recalculate_hugepage_stats(h);
case -EFAULT:
// 结构错误:重建大页列表
return rebuild_hugepage_lists(h);
default:
HUGEPAGE_DEBUG("Unrecoverable hugepage error\n");
return error;
}
}
// 重新计算统计信息
static int recalculate_hugepage_stats(struct hstate *h)
{
struct page *page;
int total = 0, free = 0;
// 遍历所有大页
list_for_each_entry(page, &h->hugepage_activelist, lru) {
total++;
if (PageHuge(page) && !PageLocked(page))
free++;
}
// 更新统计信息
h->nr_huge_pages = total;
h->free_huge_pages = free;
return 0;
}
12. 总结
ARM64 mm hugetlbpage子模块作为ARM64内存管理子系统中大页管理的核心组件,通过完整的HugeTLB页面和透明大页的创建、分配和管理功能,为ARM64平台提供了高效的内存性能优化。该模块实现了预分配大页池的管理、大页的页表建立、透明大页的自动合并和拆分等高级功能,通过精心设计的页面合并算法和页表优化机制,在减少TLB压力和页表开销的同时保证了内存访问的效率,是ARM64内存子系统性能优化的典范。