X86的三振出局(triple-fault)

triple fault从字面含义理解就是三次错误(失误)。

在X86的世界里,triple-fault真的就是三振出局了,因为系统会被shut down。

通常这个错误很不容易触发,因为X86的设计者也知道“再一再二,不能再三再四”。当系统接连出现了两次fault,第三次fault就会导致系统的关机,这个是硬件的行为,软件没法干预,或者说虽然叫fault,但是没有triple-fault的出错处理的机会!

这个triple-fault一般在虚机环境里比较容易发生,通常是因为内存的问题,导致页表挂了,然后page fault再次被触发,第三次就直接把虚机shutdown了。

在虚拟化环境里面进行调试运行软件的好处在于,有hypervisor的存在,CPU的triple-fault会导致一个VMExit到host(需要正确配置VMCS),hypervisor会保留当时虚机的现场,从而便于后期做Post-mortem分析。

下面demo一下怎么故意触发triple-fault,以及在虚拟化环境下triple-fault的VMEXIT都包含哪些信息。

要在guest里面触发一个triple fault,最简单的就是在double-fault handler里面再触发一个fault就可以。

例如,在Linux内核当中进行下面的修改。

dotraplinkage void

do_general_protection(struct pt_regs *regs, long error_code)

{

    struct task_struct *tsk;

    printk("XXXXXXXXXXX TaoW: %s, %d\n", __func__, __LINE__);

    error_code /= 0; /// TaoW: divided by 0, to trigger triple-fault

    RCU_LOCKDEP_WARN(!rcu_is_watching(), "entry code didn't wake RCU");

    conditional_sti(regs);

    if (v8086_mode(regs)) {

        local_irq_enable();

        handle_vm86_fault((struct kernel_vm86_regs *) regs, error_code);

        return;

    }

...

}

我自己的toyvmm hypervisor的VMEXIT里面可以得到

[237699.178169] VM-instruction error: 0 [-----]

[237699.178191]  Exit Reason: 0x2 (2)

[237699.178203]  Exit Qualif: 0

[237699.178219]  VMexit-interruption-information: 00000000

[237699.178230]  VMexit-interruption-error-code:  00000000

[237699.178241]  VMexit-instruction-length:      00000001

[237699.178282]  EXIT REASON: (launched = 1),  02 EXIT_REASON_TRIPLE_FAULT

[237699.178288]  guest Interrupt State: 0x0

[237699.178301]  guest Active State:    0x0

[237699.179084]  # GUEST_RIP = 0x8a07

[237699.179097]  # GUEST_RFLAGS = 0x10046

that is it, 说简单也简单。

你可能感兴趣的:(X86的三振出局(triple-fault))