前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >保护模式下的中断和异常(上) -- 硬件原理篇

保护模式下的中断和异常(上) -- 硬件原理篇

作者头像
用户3147702
发布2022-06-27 14:42:14
1K0
发布2022-06-27 14:42:14
举报
文章被收录于专栏:小脑斧科技博客

1. 引言

在我们这个系列的第一篇文章中,我们就已经使用过了 BIOS 10H 中断,用来在屏幕上打印一行字符: 计算机是如何启动的?如何制作自己的操作系统

除了 10H 中断,我们还使用过 BIOS 21H 中断,用来让实地址模式的程序退出,以及使用 15H 中断获取物理内存的信息: 保护模式进阶 — 再回实模式 实战分页机制实现 — 通过实际内存大小动态调整页表个数

在计算机体系中,硬件中断是触发 CPU 与其他硬件设备进行通信的重要方式。 但你有没有发现,这些中断都是在实地址模式下使用的,一旦进入保护模式,我们就再没有使用过中断功能,那么,在保护模式中,我们是否还可以像实地址模式中一样,通过 int 指令触发 BIOS 中断呢?答案是不可以,因为我们在进入保护模式前,通过 cli 指令关闭了硬件中断。 但是,在系统运行中,常常会出现需要暂停当前流程,响应突发事件的中断场景,那么,有什么办法让我们能够在软件的层面实现硬件中断的类似效果呢?答案当然是可以的,本文就来详细介绍。

2. 异常和中断机制

2.1. 异常

有时,我们运行了错误的指令,或指令执行时发生了错误,例如去计算除 0 的情况,或者前面提到的程序调用过程中错误特权级的切换等,这类异常情况就是系统中的“异常”。

2.1.1. 异常的分类

处理器预设了一系列异常,他们分为三类:

  1. Fault — 可更正异常,也称为“故障”,这类异常一旦被更正,系统可以继续原来的程序执行下去,因此,在 fault 异常发生时,处理器会首先保存当前运行状态,在异常处理完成后自动加载刚才的状态重新执行并继续
  2. Trap — 也称为“陷阱”,Fault 在发生时,EIP 值指向的是触发异常的指令,也就是说,在异常处理完成后,会重新执行触发异常的指令,而 Trap 发生时,EIP 指向的是触发异常的下一条指令,当异常处理完成后,CPU 会从下一条指令开始继续执行,Trap 的典型场景是调试中断,调试完成继续执行的时候,当然要调度下一条指令,而不是重新回到刚才的断点再调试一次
  3. Abort — “中止”,是严重的异常,比如硬件错误和系统表中包含非法值或不一致的状态等,一旦这类异常发生,程序运行便随之中止

2.1.2. 异常列表

CPU 预设的异常列表

向量号

助记符

类型

描述

来源

#DE

错误

除零错误

DVI和IDIV指令

1

#DB

错误/陷阱

调试异常,用于软件调试

任何代码或数据引用

2

 

中断

NMI中断

不可屏蔽的外部中断

3

#BP

陷阱

断点

INT 3指令

4

#OF

陷阱

溢出

INTO指令

5

#BR

错误

数组越界

BOUND指令

6

#UD

错误

无效指令(没有定义的指令)

UD2指令(奔腾Pro CPU引入此指令)或任何保留的指令

7

#NM

错误

数学协处理器不存在或不可用

浮点或WAIT/FWAIT指令

8

#DF

终止

双重错误(Double Fault)

任何可能产生异常的指令、不可屏蔽中断或可屏蔽中断

9

#MF

错误

向协处理器传送操作数时检测到页错误(Page Fault)或段不存在,486及以后集成了协处理器,本错误就保留不用了

浮点指令

10

#TS

错误

无效TSS

任务切换或访问TSS

11

#NP

错误

段不存在

加载段寄存器或访问系统段

12

#SS

错误

栈段错误

栈操作或加载SS寄存器

13

#GP

错误

通用/一般保护异常,如果一个操作违反了保护模式下的规定,而且该情况不属于其他异常,CPU就是认为是该异常

任何内存引用或保护性检查

14

#PF

错误

页错误

任何内存引用

15

 

保留

 

 

16

#MF

错误

浮点错误

浮点或WAIT/FWAIT指令

17

#AC

错误

对齐检查

对内存中数据的引用(486CPU引入)

18

#MC

终止

机器检查(Machine Check)

错误代码和来源与型号有关(奔腾CPU引入)

19

#XF

错误

SIMD浮点异常

SIMD浮点指令(奔腾III CPU引入)

20~31

保留

 

32~255

用户自定义中断

中断

可屏蔽中断

来自INTR的外部中断或INT n指令

2.2. 中断

正常的程序运行,除了发生异常外,即便是发生跳转,也都是程序主动的行为,但有时,处理器外部的硬件事件,比如外围设备的请求突然到来等都是随机发生的,我们可以预先设定事件发生时执行的程序,但不能预知事件何时到来,这样的场景就是“中断”,也就是上表中标记为“Interrupt”的类型,另一个触发中断的方式是通过 int 指令手动触发,这就是中断产生的两大原因:

  1. 外部硬件中断,他又可以分为以下两种:
    1. NMI — 不可屏蔽中断,向量号为 2
    2. INTR — 可屏蔽中断 2. int n 指令触发中断

3. 可屏蔽中断的响应 — 可编程中断控制器 8259A

不可屏蔽中断和可屏蔽中断分别是通过 CPU 的 NMI 引脚和 INTR 引脚触发的,顾名思义,可屏蔽中断对硬件中断实现了是否屏蔽的标识,这意味着更加灵活的中断控制,因此也是所有中断最为常用的类型。 为了控制中断的屏蔽,以及在众多中断中控制中断触发的优先级等功能,CPU 在 INTR 引脚上级联了两个 8259A 芯片,8259A 芯片就是“可编程中断控制器”。 如下图所示,这两个级联的 8259A 芯片,每一个都有 8 根中断信号线,从而可以挂接 15 个不同的外部设备,在实地址模式下,IRQ0 ~ IRQ7 被设置为了中断向量号 08h ~ 0Fh 的中断。

3.1. 8259A 的初始化

8259A 芯片有两种工作状态:

  1. 编程状态
  2. 操作状态

加电之初,8259A 处于编程状态,此时 CPU 可以通过 out 指令,向分别挂载在 20h、21h 端口和 A0h、A1h 端口的主 8259A 芯片和从 8259A 芯片写入特定的初始化指令来实现芯片的设置,这个特定的初始化指令被称为 ICW(Initialization Command Word),ICW 命令共有 4 个,分别是 ICW1、ICW2、ICW3、ICW4,他们必须从 1 到 4 依次进行初始化。 ICW 具体取值如下:

可以看到,由于 80x86 体系约定使用主片的 IR2 引脚级联从片,我们就可以确定全部的 ICW 字段取值了,其中最为重要的是 ICW2 的中断向量号标识,他表示 IQR0 对应的中断向量号,此后,IQR1 ~ IQR7 会分别对应 IQR0 的中断向量号 + 1 ~ IQR0 的向量中断号 + 7。

下面的代码展示了如何初始化 8259A,在实地址模式或是保护模式下执行都可以,但只能执行一次,且必须按照顺序执行:

3.2. 8259A 的操作控制 — OCW

完成了上述初始化操作,8259A 就从编程状态进入了操作状态,此时我们可以通过操作控制字 OCW(Operation Control Word)来实现操作控制,虽然和 ICW 一样,OCW 也不只有一个,而是有 OCW1、OCW2、OCW3 三个,但实际上我们只需要使用 OCW1 和 OCW2。 他们分别具有下面两个功能:

  1. OCW1 — 屏蔽或打开外部中断,通过 021h 或 0A1h 端口发送
  2. OCW2 — 发送 EOI 通知 8259A 中断处理完成,通过 020h 或 0A0h 端口发送

当我们需要屏蔽或打开外部中断时,只需要设置好 OCW1,然后通过 out 021h, OCW1 或者 out 0A1h, OCW1 就可以实现主 8259A 或是从 8259A 某个或某几个中断的屏蔽或打开。 这个操作也同样被 8259A 芯片认为是一种中断,而此前我们通过 ICW4 设置了非自动 EOI 模式,所以需要在上述操作完成后通过 OCW2 发送 EOI 信号,OCW2 的 EOI 信号可以选择通过 020h 端口或 0A0h 端口发送给主或从 8259A 中的一个。 下图展示了 OCW1 和 OCW2 的字段含义:

  • 下面的代码实现了仅开启定时器中断的功能:
代码语言:javascript
复制
mov    al, 0FEh    ; 主 OCW1,仅开启定时器中断
out    021h, al    ; 主 8259A,OCW1

mov    al, 0FFh    ; 从 OCW1,关闭所有中断
out    0A1h, al    ; 从 8259A,OCW1

mov    al, 20h        ; OCW2,发送 EOI 信号
out    020h, al    ; 主 8259A,OCW2

4. 结语

本文我们详细介绍了保护模式下的中断和异常与实地址模式下的不同之处,以及如何通过程序操作硬件 — 可编程中断控制器初始化、屏蔽或打开中断的响应,这些是理解硬件系统、操作系统的基础知识,也是硬件的部分。 本文涉及的实际开发内容比较少,你是否已经迫不及待的想要立即尝试一下如何通过程序让我们能够在保护模式下触发和响应中断呢?敬请期待下一篇文章中的实战吧。

5. 参考资料

《Orange’s 一个操作系统的实现》。 《linux 内核完全注释》。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-06-25,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 小脑斧科技博客 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. 引言
  • 2. 异常和中断机制
    • 2.1. 异常
      • 2.1.1. 异常的分类
      • 2.1.2. 异常列表
    • 2.2. 中断
    • 3. 可屏蔽中断的响应 — 可编程中断控制器 8259A
      • 3.1. 8259A 的初始化
        • 3.2. 8259A 的操作控制 — OCW
        • 4. 结语
        • 5. 参考资料
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档