(6). TLB Miss异常处理
这一部分我打算介绍的是软件处理部分,并不局限于TLB Miss异常处理,还包括MMU的配置,内核进程线性映射区的设置,用户进程地址的切换等。
一. MMU 软件配置和内核线性区映射配置
对于MMU的配置,其实就是对TLB的配置。前面说过,对于TLB,软件能通过写入MAS寄存器进行操作。我不想具体介绍这些寄存器,具体可以查询文档。关于MAS寄存器的操作定义,在:arch\powerpc\include\asm\mmu-book3e.h。
在PACA结构体中,有一个struct tlb_core_data,它定义了几个变量分别表示TLB1 中第一个entry,entry数和下一个entry。
struct tlb_core_data {
/*
* Per-core spinlock for e6500 TLB handlers (no tlbsrx.)
* Must be the first struct element.
*/
u8 lock;
/* For software way selection, as on Freescale TLB1 */
u8 esel_next, esel_max, esel_first;
};
软件能够操作TLB0和TLB1。在内核实际操作中,只是配置了TLB1。当TLB1不够用时,如果新的PMD需要更新到TLB1,那么我们要能够安全的替换TLB1中已使用的entry。这里的变量就是用于这样的替换算法的。
PACA在PowerPC中用来保存CPU的私有数据的结构体,每个CPU都有一份私有拷贝。在多核系统中,像中断处理、线程执行这些是在不同的CPU上并行执行的。那么每个CPU就需要一个私有数据拷贝以记录像中断栈空间这样的私有数据。这个结构体定义在:arch\powerpc\include\asm\paca.h。
我们前面说过,PGD表的地址非常重要,每个进程都有自己的一份拷贝。在TLB Miss发生后,内核需要查找页表。那么在异常发生后,内核需要知道是哪个进程访问虚拟地址发生了TLB Miss。在PACA中,有一个成员:pgd_t *pgd,记录了当前CPU的当前进程的PGD表地址。异常发生后,软件能够直接读取这个地址,快速的查找页表。
因为MMU的初始化配置和内核的线性映射区配置是同步完成,下面我将它们放在一起介绍。我先将函数执行过程列出来,这些函数定义在:arch\powerpc\mm\fsl_booke_mmu.c,arch\powerpc\mm\tlb_nohash.c
setup_page_sizes:
这个函数通过查询MMU寄存器SPRN_TLBxPS获得TLB0和TBL1能够支持的最大page size。我们知道TLB0是固定4KB页面,则TLB1决定了MMU能够支持的最大页面SIZE。从笔者平台打印出的信息看,e6500最大支持1GB的页面映射。这个会对后面的内核线性区页面映射有影响。setup_mmu_htw:
根据平台不同,设置TLB Miss异常处理函数。注意这里的处理函数&#x