Double Fault & Triple Fault

之前我曾提到过intel x86 cpu的14号中断用于处理缺页异常,这也是被人熟知的一个中断号,事实上intel架构总共可用的中断号有256个(从0到255),其中前32个(从0到31)中断号保留给Intel架构内部使用,也就是说这些中断都有其特定的含义而不可被用户更改,而剩余的224(从32到255)个中断则可由用户自定义和实现其具体功能。本文重点关注前32个中断,更具体点说是其中的一个中断Double Fault,以及隐包含的另外一个中断Triple Fault。

前32个中断,每个中断的含义都可以在intel手册“Intel 64 and IA-32 Architectures Software Developer’s Manual Volume 3A System Programming Guide.pdf”上找到对应的描述(Table 6-1. Protected-Mode Exceptions and Interrupts ),这里不再过多解释其它中断,重点看一下8号Double Fault中断。
Double Fault从字面上来讲,就是前后的动作连续触发两个中断的异常,比如一个缺页异常没有对应的异常中断处理函数(用c代码表示即为NULL,空指针),这就将会引发一个典型的Double Fault,在这种情况下,如果发生缺页异常则将触发一个中断,此时cpu要去调用缺页异常中断处理函数进行处理,但却发现没有这个处理函数,因而这又是一个异常而再次触发中断,此时触发的就是Double Fault异常中断。但是,值得注意的是并不是连续发生两个中断就是Double Fault,因为部分情况下,连续发生的两个中断可以依次被cpu处理。为了辨别什么情况下才会触发Double Fault,Intel cpu把32个中断分为3类:
Table 6-4. Interrupt and Exception Classes

ClassVector NumberDescription
Benign
Exceptions
and
Interrupts








16 
17 
18 
19 
All 
All 
Debug
NMI Interrupt
Breakpoint
Overflow
BOUND Range Exceeded
Invalid Opcode
Device Not Available
Coprocessor Segment Overrun
Floating-Point Error
Alignment Check
Machine Check
SIMD floating-point
INT n
INTR
Contributory
Exceptions

10 
11 
12 
13 
Divide Error
Invalid TSS
Segment Not Present
Stack Fault
General Protection
Page Faults14 Page Fault

而下表显示了会导致发生Double Fault的情况,即如果先发生某类型的异常,接着再发生某类型的异常,此时是否会导致发生Double Fault异常:
Table 6-5. Conditions for Generating a Double Fault

First ExceptionSecond Exception
BenignContributoryPage Fault
Benignxxx
ContributoryxDouble Faultx
Page FaultxDouble FaultDouble Fault

看看前面举的示例,先发生Page Fault,接着发生Contributory Exception(执行NULL空函数为Segment Not Present,11号中断),对应下表的确将引发Double Fault。事实上,这个示例有点特殊,其实不管前一个异常是Benign也好,Contributory也好,Page Fault也好,只要对应的中断函数为空,此时都会触发Double Fault,对应intel手册里的话为:“Any further faults generated while the processor is attempting to transfer control to the appropriate fault handler could still lead to a double-fault sequence.”
Double Fault不可恢复,所以在该中断的处理函数里能做的也只能是收集相关信息(以便进行Double Fault问题原因排查),主动关闭相关程序和服务(如果可以的话),让机器‘死’得优雅一点。
如果Double Fault异常中断的函数也为空,那么此时将发生Triple Fault异常,该异常并不是一个真正的异常,它没有对应中断号,也表示如果发生了Triple Fault异常这种情况,cpu都不管了,除了重启机器别无他法(一般外部硬件,比如主板会向cpu发出重启信号)。
触发Triple Fault的情况大部分是因为LDT或者GDT或IDT错误导致(被无意中踩坏?)或者内核栈溢出(或下溢),比如内核栈溢出,栈顶指针刚好达到一个无效内存页(即访问页不在内存中)而触发Page Fault中断,进而调用Page Fault异常中断函数进行处理,函数调用需要进行异常信息压栈(以传递给中断函数),但栈内存页不存在内存中,这又触发Page Fault异常,如此反复进而触发Double Fault、Triple Fault。
遇到Triple Fault怎么弄?额,我不知道,不过Linus给出了明确的答复,但那是03年的事情:
Triple faults (Linus Torvalds)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

Newsgroups: fa.linux.kernel

From: Linus Torvalds <torvalds@osdl.org>

Subject: Re: 2.6.0-test9-mm3

Original-Message-ID: <Pine.LNX.4.44.0311141344290.5877-100000@home.osdl.org>

Date: Fri, 14 Nov 2003 21:48:59 GMT

Message-ID: <fa.jjta19r.1gl80h1@ifi.uio.no>

On Fri, 14 Nov 2003, Martin J. Bligh wrote:

>

> Linus had some debug thing for triple faults, a few months ago, IIRC ...

> probably in the archives somewhere ...

Triple faults you can't debug, they raise a line outside the CPU, and

normal PC hardware will cause that to just trigger a reboot.

But double faults do get caught, and that debugging stuff actually is in

the standard kernel. It won't give _nearly_ as good a debug report as a

"normal" oops, since I didn't want the double-fault handler to touch

anything even remotely unsafe, but it often gives a good hint about what

might be wrong. Certainly better than triple-faulting did (which we still

do for _catastrophic_ corruption, eg totally munged kernel page tables etc

- it's just very hard to avoid once you get corrupted enough).

        Linus

  • 9
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值