Ucore_lab1 相关
- https://kiprey.github.io/2020/08/uCore-1/
- 学堂在线清华大学的Ucore实验指导书以及在线视频
- https://learningos.github.io/ucore_os_webdocs/lab1/lab1_2_1_exercise.html
第一点是一个博客,很优秀的文章,包含了很多很全的内容,借以引用。再在此基础上写自己的笔记。
第二点的内容是我认为需要仔细阅读和学习的,很有帮助。
(君子生非异也,善假于物也)
系统软件启动过程
BIOS 启动过程 及 bootloader 启动过程:
BIOS 将通过读取硬盘主引导扇区到内存,并转跳到对应内存中的位置执行 bootloader。bootloader 完成的工作包括:切换到保护模式,启用分段机制,读磁盘中 ELF 执行文件格式的 ucore 操作系统到内存,显示字符串信息把控制权,交给 ucore 操作系统。
特权级切换,中断与异常部分:
中断的进入:
CPU 根据得到的中断向量(以此为索引)到 IDT 中找到该向量对应的中断描述符,中断描述符里保存着中断服务例程的段选择子; - CPU 使用 IDT 查到的中断服务例程的段选择子从 GDT 中取得相应的段描述符,段描述符里保存了中断服务例程的段基址和属性信息,此时 CPU 就得到了中断服务例程的起始地址,并跳转到该地址; - CPU 会根据 CPL 和中断服务例程的段描述符的 DPL 信息确认是否发生了特权级的转换。比如当前程序正运行在用户态,而中断程序是运行在内核态的,则意味着发生了特权级的转换,这时 CPU 会从当前程序的 TSS 信息(该信息在内存中的起始地址存在 TR 寄存器中)里取得该程序的内核栈地址,即包括内核态的 ss 和 esp 的值,并立即将系统当前使用的栈切换成新的内核栈。这个栈就是即将运行的中断服务程序要使用的栈。紧接着就将当前程序使用的用户态的 ss 和 esp 压到新的内核栈中保存起来; - CPU 需要开始保存当前被打断的程序的现场(即一些寄存器的值),以便于将来恢复被打断的程序继续执行。这需要利用内核栈来保存相关现场信息,即依次压入当前被打断程序使用的 eflags,cs,eip,errorCode(如果是有错误码的异常)信息; - CPU 利用中断服务例程的段描述符将其第一条指令的地址加载到 cs 和 eip 寄存器中,开始执行中断服务例程。这意味着先前的程序被暂停执行,中断服务程序正式开始工作。
中断返回:
程序执行这条 iret 指令时,首先会从内核栈里弹出先前保存的被打断的程序的现场信息,即 eflags,cs,eip 重新开始执行; 如果存在特权级转换(从内核态转换到用户态),则还需要从内核栈中弹出用户态栈的 ss 和 esp,这样也意味着栈也被切换回原先使用的用户态的栈了; - 如果此次处理的是带有错误码(errorCode)的异常,CPU 在恢复先前程序的现场时,并不会弹出 errorCode。这一步需要通过软件完成,即要求相关的中断服务例程在调用 iret 返回之前添加出栈代码主动弹出 errorCode。
x86特权级 0to3 :
计算机启动的时候的代码都是在内核态运行,通过中断切换特权级。产生中断是从0特权级到0特权级,不会发生切换栈的动作,会在当前栈压入一些内容,我们要将内核栈模仿成一个用户栈,压入SS SP ,将CPL改成3,通过iret指令完成特权级的切换。

x86特权级 3to0:
一旦产生中断,就会产生栈的切换,在内核栈中会压入用户态的SS SP CS IP 等信息,通过iret 指令还是会返回到3特权级,我们想让其留在0特权级,我们将修改栈,丢掉用户的SS, SP ,修改CS中的CPL为0。然后通过iret指令返回就完成了特权级的切换。

 
                    
                     
                    
                 
                    
                
 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号