一、实验目的

在前面的PA123中,我们分别实现了基本的运算单元,实现了各种指令和程序的装载,实现了存储器的层次结构。而在PA4中,为了让NEMU可以处理异常情况以及和外设交互,我们要做的事情有以下:

  • PA4-1:为NEMU添加异常和中断支持
  • PA4-2:为NEMU添加外设与IO支持

二、实验步骤

PA4-1 异常和中断响应

我们上课时了解到,打断系统运行的特殊事件有两样:异常和中断。它们俩的分类如下:

  • 内部异常:在执行一条指令时,由处理器在其内部检测到的,与正在执行的指令相关的同步事件

    • 故障:缺页、非法操作码、除数为零……
    • 陷阱:用户程序主动调用操作系统处理例程
    • 终止:执行指令时发生严重错误,如内存校验错误
  • 外部中断:典型地由I/O设备触发,与当前正在执行的指令无关的异步事件

那么我们操作系统是怎样响应它们的呢?

  1. OS需要先初始化中断描述符表IDT

    在NEMU中就是kernel在init_cond()函数中调用了位于kernel/src/irq/idt.cinit_idt(),这个函数中将IDT初始化如下:

    vec的那一列就是定义的一系列异常和中断响应程序及其入口,实现位于kernel/src/irq/do_irq.S

  2. 然后进程执行过程中CPU检测到异常或中断后,立刻保护当前程序执行状态

  3. 再根据异常和中断号去查表得到处理程序的入口地址,转到OS提供的异常/中断处理程序继续执行

  4. 处理完后恢复现场,返回原程序继续

好,现在让我们来看看NEMU是怎么具体实现对中断和异常的处理的:

首先,无论是中断还是异常的处理,第一阶段都是保护程序状态。这个操作由NEMU模拟的硬件实现,依次将EFLAGS, CS, EIP寄存器的值压栈。然后我们可以分开两种响应处理:

对中断的处理

因为中断是属于一个外部信号,我们无法预测它会在啥时候到来,所以采用的方法就是让cpu执行指令的过程中保持对外部中断信号的检测。在nemu/src/cpu/cpu.c/exec()中有一个do_intr()函数,cpu每执行完一条指令,都会调用这个函数来检查是否有外部中断的到来。

#ifdef IA32_INTR
void do_intr()
{
if (cpu.intr && cpu.eflags.IF)
{
// get interrupt number
uint8_t intr_no = i8259_query_intr_no();
assert(intr_no != I8259_NO_INTR);
// tell the PIC interrupt info received
i8259_ack_intr();
// raise interrupt
raise_intr(intr_no);
}
}
#endif

对异常的处理

我们在这里主要处理的异常为trap自陷)。自陷操作是可控的,是我们自己发出的一系列指令,在后面进行系统调用方面会大有用途。 我们先来看看trap的样例文件:

#include "trap.h"

const char str[] = "Hello, world!\n";

int main()
{
asm volatile( "movl $4, %eax;"
"movl $1, %ebx;"
"movl $str, %ecx;"
"movl $14, %edx;"
"int $0x80");
HIT_GOOD_TRAP;
return 0;
}

在这里面,int $0x80就是向CPU发出trap信号的指令。它在NEMU中会调用这个函数:

void raise_sw_intr(uint8_t intr_no)
{
// return address is the
// next instruction
cpu.eip += 2;
raise_intr(intr_no);
}

可以看出,我们两种响应最后都是要调用raise_intr()函数。这个函数的实现也是我们PA4-1的关键,我们需要在这个函数里完成:

  • 根据异常或中断号intr_no查询IDT,这个intr_no分别由用户和i8259中断控制器提供。

  • 查询得到处理程序的入口地址。中断门和陷阱门的门描述符结构如下,不同之处在TYPE字段。

  • 清除IF位如果当前信号位中断信号;

  • 将EIP设置为查询得到的处理程序入口。

接下来就靠处理程序操作,然后通过iret指令返回程序断点处就可以了。

所以,我们在PA4-1做了:

  • include/config.h定义宏 #define IA32_INTR并且make clean;
  • 参照i386手册在nemu/include/cpu/reg.h中定义IDTR结构体,并在 CPU_STATE中添加idtr寄存器和中断引脚(框架代码已经提供)
  • 实现了包括lidtclistiintpushapopairet等指令

PA4-2 外设与IO

在这一章,我们需要完成NEMU与外界的交互,让NEMU可以正常进行输入与输出。

我们先来看看NEMU中CPU完成与外设通信的几种方式:

  • 方式1:端口映射I/O(port-mapped I/O)

    • 串口(Serial)、键盘(Keyboard)、硬盘(IDE)
  • 方式2:内存映射I/O (Memory Mapped I/O, mmio)
    • 显卡(VGA)
  • 其它只需要理解:
    • 声卡(Audio)实验性质
    • 时钟(Timer)只产生时钟中断

可以将CPU和外设的交互简要概括为:

将外设的数据、状态、控制寄存器称为I/O端口;对端口进行编号;CPU使用in与out指令同端口间通过按编号“打电话”的方式通信。

设备制造商和OS可以约定占用的端口数和端口参数的设置,并且为OS提供相应的驱动程序。OS安装了相应的驱动后,驱动程序熟知这些约定,便可通过in和out指令完成对设备的控制和数据读写(直接控制法)。

我们在PA4-2里完成了对串口、硬盘、键盘的端口映射模拟,完成了对显卡的内存映射模拟。

三、思考题

本章没有明确的思考题,有几个要点:

PA4-1.跳转前决定是否允许中断嵌套?

  • 当处理外部中断时,清除EFLAGS寄存器中的IF位,实现关中断,不允许嵌套

  • 当处理内部异常时,不清除EFLAGS寄存器中的IF位,不关闭中断,允许嵌套

PA4-1.在函数irq_handle中,结合kernel/src/irq/do_irq.S,理解tf怎么传进来的?tf里面有什么?

我们可以观察到,tfTrapFrame结构的一个指针,我们在上面将程序状态压栈以及进行int $0x80前对寄存器压栈时就是按照这个结构的顺序来压栈的;而在call irq_handle前,我们有一个这样的操作:

而这个时候esp的值就是tf的首地址,我们结合TrapFrame的结构来看:

可以明显看出只要有了首地址,后面的元素就可以通过指针直接访问。

NEMU PA 4 实验报告的更多相关文章

  1. ucoreOS_lab3 实验报告

    所有的实验报告将会在 Github 同步更新,更多内容请移步至Github:https://github.com/AngelKitty/review_the_national_post-graduat ...

  2. ucoreOS_lab2 实验报告

    所有的实验报告将会在 Github 同步更新,更多内容请移步至Github:https://github.com/AngelKitty/review_the_national_post-graduat ...

  3. JAVA实验报告及第七周总结

    JAVA第六周作业 实验报告五 第一题 1.设计一个类层次,定义一个抽象类--形状,其中包括有求形状的面积的抽象方法. 继承该抽象类定义三角型.矩形.圆. 分别创建一个三角形.矩形.圆存对象,将各类图 ...

  4. 第五次java实验报告

    Java实验报告 班级 计科二班 学号 20188437 姓名 何磊 完成时间2019/10/10 评分等级 实验四 类的继承 实验目的 理解抽象类与接口的使用: 了解包的作用,掌握包的设计方法. 实 ...

  5. 第七周总结&第五次实验报告

    学习总结 这周我们加深了对抽象类与接口的学习,获得的知识点也比上周多了许多,抽象类与接口很相似,就比如别人还没有做完的是交给你来做,而他那些样式都做好了,你只需要完善即可 但也有不同点. 区别点 抽象 ...

  6. 第七周课程总结 & 实验报告(五)

    第七周课程总结 一.抽象类与接口的应用 1.实例化 2.实际应用 ---模板设计(抽象类) ---制定标准(接口) 3.设计模式 ---工厂设计 ---代理设计 ---适配器设计 二.抽象类与接口之间 ...

  7. 第七周&实验报告五

    实验四 类的继承 •实验目的 •理解抽象类与接口的使用: •了解包的作用,掌握包的设计方法. •实验要求 •掌握使用抽象类的方法. •掌握使用系统接口的技术和创建自定义接口的方法. •了解 Java ...

  8. 2019JAVA第五次实验报告

    Java实验报告 班级 计科二班 学号 20188442 姓名 吴怡君 完成时间2019/10/11 评分等级 实验四 类的继承 实验目的 理解抽象类与接口的使用: 了解包的作用,掌握包的设计方法. ...

  9. 实验报告5&第七周课程总结

    实验四 类的继承 实验目的 理解抽象类与接口的使用: 了解包的作用,掌握包的设计方法. 实验要求 掌握使用抽象类的方法. 掌握使用系统接口的技术和创建自定义接口的方法. 了解 Java 系统包的结构. ...

  10. 北京电子科技学院(BESTI)实验报告5

    北京电子科技学院(BESTI)实验报告5 课程: 信息安全系统设计基础 班级:1452.1453 姓名:(按贡献大小排名) 郑凯杰.周恩德 学号:(按贡献大小排名) 20145314.20145217 ...

随机推荐

  1. vue 中对style、disable 等样式进行条件判断

    本文为博主原创,未经允许不得转载: 一 原生用法 style="width: 100%; margin-top: 20px" disabled 二  三元表达式 <a :st ...

  2. 06-verilog基础语法_5

    How to build and test a module parameter defparam修改参数 Task & function Task Function function不可以调 ...

  3. VS中多个源文件中只运行其中特定文件

    1.问题 有时候一个项目中创建了多个源文件,但是我只想运行其中的一个,一起运行就会出现多个main入口的问题 2.解决方式 2.1 右键要排除的文件,点击属性 2.2 从生成中排除一项中选择是即可 2 ...

  4. Oracle ORA-01861: 文字与格式字符串不匹配(日期格式导致的问题)

    1.问题 如图所示,Oracle ORA-01861: 文字与格式字符串不匹配.这里的日期格式出现问题,导致了ORA-01861错误. 2.解决方式 原因: 如果直接按照字符串方式,或者直接使用to_ ...

  5. 什么是 doris,为什么几乎国内大厂都会使用它

    转载至我的博客 https://www.infrastack.cn ,公众号:架构成长指南 今天给各位分享一个非常牛的实时分析型数据库Apache Doris,几乎国内的一二线大厂都在使用它做数据分析 ...

  6. [转帖]kubernetes(k8s):容器资源限制(内存限制、cpu限制、namespace限制)

    文章目录 1. k8s容器资源限制 2. 内存资源限制实例 3. cpu资源限制 4. namespace设置资源限制 5. namespace中pod的配额 6. namespace的创建.使用和删 ...

  7. 【转帖】【奇技淫巧】Linux | 安全保障防火墙-iptables

    虽然说Linux在安全方面确实相当于windows要更加可靠一些,但一般使用其作为服务器的我们,也不能大意,也是需要严格限制网络传输过程中的出入规则.上篇文章我们有聊到统计网络的信息,这篇文章来学习一 ...

  8. 【转帖】isolcpus功能与使用

    isolcpus功能存在已久,笔者追溯v2.6.11(2005年)那时内核就已经存在了isolcpus功能.根据kernel-parameters.txt 上的解释,"isolcpus功能用 ...

  9. [转帖]记录几个常用linux命令的使用方法——find、grep、file、which、whereis和压缩命令gzip、bzip2、tar

    一.命令1: find.grep.file.which.whereis 1.find 目的:查找符合条件的文件 1)在哪些目录中查找 2)查找的内容 格式: find 目录名 选项 查找条件 举例: ...

  10. 《Javascript高级程序设计》读书笔记——函数与闭包

    函数与闭包 函数创建 创建函数有两种方式,第一种是函数声明.函数声明有一个很重要的特征就是函数声明提升(function declaration hoisting),意思是在执行代脚本前会先读取所有的 ...