0xFFFFFFF0 -> BIOS -> bootloader -> OS
BIOS是固化在主板的程序,初始化硬件,准备环境,为上层软件提供访问和控制
-
bootloader位于存储介质的引导扇区,切换保护模式,启用分段机制,读取ELF格式的操作系统到内存
- 保护模式拥有4GB的寻址空间以及更好的保护机制,提供虚拟化支持
- 实模式只有16位寻址空间,没有保护机制
- 分段机制:将内存划分为以初始地址和长度限制表示的内存块,称之为段
- 逻辑地址,段描述符,段描述符表,段选择子
- 段描述符:是描述段的属性
- 段描述符表: 段描述符的数组
- 段选择子: 段寄存器,定位段描述符表项
- ELF格式文件:
-
分段存储管理机制:
- 段寄存器:DS(Data segment) SS(Stack segment) CS(Code segment)
- 段寄存器里存放段选择子
- 段选择子由INDEX,TI,RPL三部分组成
- 段选择子结合GDTR里的基地址,来从GDT中选择相应的segment-descriptor,GDTR的LIMIT为GDT表项(包括第一个空表项)数目*8-1
- segment-descriptor包含base addr,limit,type,accessed,avaliable,granularity,dpl以及segment-present这些部分。由base addr以及logical addr里的offset一起组成linear addr,在ucore里便是physical addr,但实际中还会再由linear addr生成physical addr。
-
保护机制
- DS和SS里的段选择子为RPL,CS的段选择子为CPL,segment-descriptor里的为DPL
- CPL为进程当前的权限
- PL分为0-3,最低为3,最高为0,这些特权级称为环,最内为ring 0,最外为ring 3,在ucore里只使用了两级,ring 0: 内核态 ring 3:用户态。
- 两个关节节点时会检查特权:
- 当一个段选择符被加载时
- 通过linear addr访问内存页时
- MAX(CPL,RPL)<= DPL,如果为真,通过检测否则不通过。即当前权限或者请求权限的最低的一个必须比数据段的权限高,才可以通过。
-
地址空间
- 逻辑地址由一个16bit的segment selector和一个32bit的offset构成
硬盘访问概述
bootloader通过lba模式PIO(program IO)方式访问硬盘。所有的IO操作都是通过CPU访问硬盘的IO地址寄存器实现的
具体寄存器的访问方式参考指导书
流程-
Link addr&Load addr
- Link addr:编译器和指定代码和数据所需要放置的内存地址,由链接器配置
- Load addr: 程序实际被加载到内存的位置(由程序加载器ld配置)
- 一般由可执行文件结构信息和加载器保证这两个地址相同
-
中断与异常
polling较为浪费计算机资源,因此采用iterrupt机制来节约资源-
interrupt分为三类:
- asynchronous interrupt,简称interrupt,是由外部事件如IO,timer,console等异步事件产生的
- synchronous interrupt,简称exception,是由内部事件如指令错误,或非法条件同步产生的
- trap interrupt,简称trap,也称软中断soft interrupt,是由system call产生的
当CPU收到中断信号时,会根据idtr的基地址和中断编号来定位到idt,idtr由idt addr以及limit组成,同gdtr
由idtr+编号*8即位interrupt-descriptor的地址。
lidt(load idt register)根据内存所存放的idtr格式内存数加载idtr,ring 0;sidt(store idt register)拷贝idtr的内容到一个内存地址,任意特权级均可用运行
-
id(interrupt descrptor)分为三类
- interrupt Gate: 调用时会禁止interrupt
- trap Gate:不会禁止interrupt
- task Gate: ucore里没有使用
-
id的结构:
- selector: 段选择子,会根据CPL和DPL的值确认是否发生了特权级别的转换
- offset: 这两者构成了中断处理程序的入口地址
- dpl
所谓自动禁止,是指CPU跳转到Gate里的地址时,在将EFLAGS保存到栈上之后,清除EFLAGS里的IF位,以避免重复触发中断。当然操作系统可以将EFLAGS里的IF设上,从而允许嵌套中断。当然在此之前必须做好处理嵌套中断的准备
而trap往往时系统调用,用户进程在用户态不可以禁止中断,而到达内核态时禁止中断没有意义,因为不会有嵌套系统调用
-
-
中断与异常的流程
- 当出发中断时,根据CS里的CPL和selector所指向descriptor里的DPL判断时是否发生了特权级转换,这里,特权级要么保持,内核态到内核态,要么提升,用户态到内核态。如果发生了转化,那么会从当前用户的TSS信息里去的该程序的内核栈地址,包括ss和esp的值,并且将当前使用的栈切换成新的内核栈,再把当前用户栈的ss和esp压入内核栈
- 保存现场信息,像内核栈依次压入EFLAGS,CS,EIP,ERRORCODE
- 根据段选择子和offset,执行中断服务例程。
-
返回时
通过iret(or iretd)指令恢复被打断程序的执行,具体过程:- 从内核栈里弹出现场信息,即EFLAGS,CS,EIP重新开始执行
- 如果存在特权转换,则还需要弹出用户栈的ss和esp
- CPU在恢复过程中不会弹出errorcode,需要软件完成
-
中断与异常保护机制
- check DPL in selector <= CPL in CS
- 如果中断是被用户态程序中的指令触发,还会chck DPL in Gate <= CPL in CS,放置用户随意触发中断。
- 如果检查失败,会产生一个general-protection exception