计算机基础
看内核的时候发现很多东西都处于似懂非懂的状态,比如MMU、TLB,甚至各个寄存器的作用,今天就认真地学习一下这些东西。首先先来看CPU的寄存器:
32位CPU中有4个数据寄存器,分别是EAX,EBX,ECX和EDX。数据寄存器用来保存操作数和运算结果,从而节省读取操作数所需占用总线和访问存储器的时间。EAX通常称为累加器,用累加器进行的操作可能需要更少的时间。可用于乘、除、输入/输出操作,使用频率很高。EBX称为基地址寄存器,可作为存储器指针来使用。ECX称为计数寄存器,在循环和字符串操作时,要用它来控制循环次数。在位移操作中,如果位移多位时用CL来指明位数。EDX称为数据寄存器,在进行乘除运算时,可以作为默认操作数参与运算,也可用于存放I/O的端口地址。这四个寄存器不仅可以传送数据、暂存数据保存算数逻辑运算结果,而且可以作为指针寄存器,所以这些32位寄存器具更具有通用性。
有两个变址寄存器为ESI和EDI,其中低16位对应先前CPU中的SI和DI,对低16位的数据的存取,不影响高16位的数据。他们的主要用途用于存放存储单元在段内的偏移量,用他们可实现多种存储器操作数的寻址方式,为以后不同的地址形式访问存储单元提供方便。
指针寄存器EIP,其低16位对应先前CPU中的BP和SP,对低16位的数据进行存取不影响高16位的数据。
2个32位通用寄存器EBP和ESP,主要用于访问堆栈内的存储单元,并规定:EBP为基指针,可直接存取堆栈中的数据,ESP为堆栈指针寄存器,可访问栈顶。
段寄存器为了实现段式管理,其中包括代码段寄存器ECS、数据段寄存器EDS、附加段寄存器EES和EFS和EGS、堆栈段寄存器ESS。
运算结果标志位包括进位标志CF、奇偶标志位标志结果中“1”的个数、辅助进位标志AF、零标志ZF判断结果是否为0、符号标志位SF指示结果的正负号、溢出标志位OF。
状态控制标志位用来控制CPU的操作,要通过专门的指令才能使其变化。追踪标志位TF为1时CPU进入单步执行状态。中断允许标志符IF用来决定是否响应CPU外部可屏蔽中断发出的中断请求。方向标识符DF用来决定在串操作指令执行时指针寄存器调整的方向。
32位标志寄存器增加的标志位:I/O特权标志位IOPL,嵌套任务标志NT,重启动标志RF,虚拟8086方式标志位VM。
上面只是一些通用寄存器,下面开始看一下在看内核的时候需要知道的一些寄存器的作用:
Intel中的CR寄存器:CR0中包含有控制处理器操作模式和状态的系统控制标志,CR1保留不用,CR2中包括导致页错误的线性地址,CR3中含有页表地址。关于CPU的运行模式就不在这儿说啦。
在看程序或者说明的时候经常会看到MMU,那MMU是什么?MMU是Memory Management Unit的缩写,针对各种CPU,MMU是个可选的配件,负责从虚拟地址到物理地址的转换,提供硬件机制的内存访问授权。现代的多用户操作系统需要MMU才能达到每个用户进程都有自己独立的地址空间的目标,涉及到的寄存器有GDT、LDT、CR0、CR3。虚拟地址到物理地址的转换在《情景分析》上面已经讲的很清楚了。
下面接着看TLB是什么。在CPU通过分页机制访问内存的时候并不总是根据三级的结构去找到线性地址相对应的物理地址,而是优先考虑TLB是不是有,如果有的话就不必进行这个过程了。TLB中保存的是内存页表,而L1、L2 cache则是保存对应的内存数据。在X86中有四组TLB:第一组缓存一般页表的指令页表,第二组缓存一般页表的数据页表,第三组缓存大页面指令页表,第四组缓存大页面数据页表。TLB内部存储空间被划分为相同的块,块的大小与内存的页表区里页表条目的大小相同。下面看看TLB中项的结构,每个TLB表项的长度为64位:
- 最高20位:VPN;
- 接下来的6位:PID;
- 接下来的6位:未使用;
- 接下来的20位:物理页面地址;
- 下一位N:如果为1表示该地址使用cache;
- 下一位D:如果为1表示可写;
- 下一位V:表示valid;
- 下一位G:如果为1表示不检查PID。
- UTLB miss:访问kuseg时,TLB中没有对应的项;
- TLB miss:访问kseg0,kseg1,kseg2时,TLB中没有对应的映射,或者虽然有映射但是V=0;
- TLB mod:写操作,有映射,但是Dirty bit = 0。
- 在用户模式下访问的地址最高位为1,产生地址错误异常;
- 匹配VPN,如果没有,地址最高位为1则产生TLB miss,最高位为0则产生UTLB miss;
- 匹配PID或者Global bit=1,如果错误则产生TLB miss,或者UTLB miss;
- 检查Valid bit=1,如果不是就产生TLB miss;
- 如果D=0,操作却在写,产生TLB mod;
- 如果N=1,访问内存,否则访问cache。
- mtc0:把通用的寄存器的值装入TLB寄存器;
- mfc0:从TLB寄存器中读取数据到通用寄存器;
- tlbp:在TLB中查找是否有与EntryHi寄存器匹配的,如果有则匹配项的index保存在index寄存器中,没有匹配则配置Index的最高位为1;
- tlbr:把Index指向的TLB表项装入EntryHi和EntryLo;
- tlbwi:把EntryHi和EntryLo中的值写入Index指向的TLB表项中;
- tlbwr:把EntryHi和EntryLo中的值写入Random指向的TLB表项中。
- EPC寄存器:指向发生异常的指令,如果指令在分支延迟槽中则指向分支指令,基本思想:当恢复了异常中的错误,将返回用户模式,并跳转到EPC指向的地址;
- Cause寄存器:指明异常的原因,并保存中断状态;
- Status寄存器:包含机器状态的信息,重要的位:Kernel/User mode bit,Interrupt Enable bit。硬件为这些位维护一个深为3的栈,发生异常时自动移位,因此异常可以嵌套2层而不需要保存这些位;
- BadVaddr寄存器:保存发生访问错误的虚拟地址;
- Context寄存器:高11位由程序控制,接下来的19位被设为发生异常的虚拟地址的VPN,最后两位永远为0。
- 设置EPC;
- 设置Cause;
- 设置Status,把K/U和IE移一位,并把current K/U和IE置0,即进入内核模式,中断关闭;
- 设置BadVaddr,保护产生异常的虚拟地址;
- 设置Context,高11位不变,接下来的19位设成发成错误的虚拟地址的VPN;
- 设置TLB EntryHi,使它包含出错地址的VPN。